From buildbot at python.org Sun Mar 1 00:03:19 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 28 Feb 2009 23:03:19 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu trunk Message-ID: <20090228230321.A2A451E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%20trunk/builds/1076 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: jeffrey.yasskin BUILD FAILED: failed test Excerpt from the test logfile: ======= Backtrace: ========= /lib/libc.so.6.1[0x200000000025ade0] /lib/libc.so.6.1(cfree-0xb5750a0)[0x200000000025f460] /usr/lib/libdb-4.7.so(__os_free-0x44b8370)[0x200000000731c1a0] /usr/lib/libdb-4.7.so(__os_closehandle-0x44b5e30)[0x200000000731e6f0] /usr/lib/libdb-4.7.so(__fop_file_setup-0x44f7540)[0x20000000072dcff0] /usr/lib/libdb-4.7.so(__db_open-0x4553ce0)[0x2000000007280860] /usr/lib/libdb-4.7.so(__db_open_pp+0x4180520)[0x20000000072711f0] /home/pybot/buildarea/trunk.klose-debian-ia64/build/build/lib.linux-ia64-2.7-pydebug/_bsddb.so[0x200000000703e6f0] ./python(PyCFunction_Call+0x20000000003cd3b0)[0x4000000000417d40] ./python[0x400000000027cd90] ./python(PyEval_EvalFrameEx+0x1ffffffff4a98330)[0x400000000026c880] ./python(PyEval_EvalCodeEx+0x1ffffffff4aa0220)[0x4000000000274780] ./python[0x400000000027e020] ./python[0x400000000027d380] ./python(PyEval_EvalFrameEx+0x1ffffffff4a98330)[0x400000000026c880] ./python(PyEval_EvalCodeEx+0x1ffffffff4aa0220)[0x4000000000274780] ./python[0x400000000027e020] ./python[0x400000000027d380] ./python(PyEval_EvalFrameEx+0x1ffffffff4a98330)[0x400000000026c880] ./python(PyEval_EvalCodeEx+0x1ffffffff4aa0220)[0x4000000000274780] ./python[0x400000000027e020] ./python[0x400000000027d380] ./python(PyEval_EvalFrameEx+0x1ffffffff4a98330)[0x400000000026c880] ./python(PyEval_EvalCodeEx+0x1ffffffff4aa0220)[0x4000000000274780] ./python[0x40000000004157c0] ./python(PyObject_Call+0x1ffffffff486ef00)[0x4000000000043470] ./python[0x40000000000661f0] ./python(PyObject_Call+0x1ffffffff486ef00)[0x4000000000043470] ./python(PyEval_CallObjectWithKeywords+0x1ffffffff4aa6bc0)[0x400000000027b140] ./python(PyInstance_New+0x2000000000004320)[0x400000000004eaa0] ./python(PyObject_Call+0x1ffffffff486ef00)[0x4000000000043470] ./python[0x400000000027f6a0] ./python[0x400000000027d3e0] ./python(PyEval_EvalFrameEx+0x1ffffffff4a98330)[0x400000000026c880] ./python(PyEval_EvalCodeEx+0x1ffffffff4aa0220)[0x4000000000274780] ./python[0x40000000004157c0] ./python(PyObject_Call+0x1ffffffff486ef00)[0x4000000000043470] ./python[0x4000000000280580] ./python(PyEval_EvalFrameEx+0x1ffffffff4a98b10)[0x400000000026d060] ./python[0x400000000027dca0] ./python[0x400000000027d380] ./python(PyEval_EvalFrameEx+0x1ffffffff4a98330)[0x400000000026c880] ./python(PyEval_EvalCodeEx+0x1ffffffff4aa0220)[0x4000000000274780] ./python[0x400000000027e020] ./python[0x400000000027d380] ./python(PyEval_EvalFrameEx+0x1ffffffff4a98330)[0x400000000026c880] ./python(PyEval_EvalCodeEx+0x1ffffffff4aa0220)[0x4000000000274780] ./python[0x40000000004157c0] ./python(PyObject_Call+0x1ffffffff486ef00)[0x4000000000043470] ./python[0x4000000000280580] ./python(PyEval_EvalFrameEx+0x1ffffffff4a98b10)[0x400000000026d060] ./python(PyEval_EvalCodeEx+0x1ffffffff4aa0220)[0x4000000000274780] ./python[0x40000000004157c0] ./python(PyObject_Call+0x1ffffffff486ef00)[0x4000000000043470] ./python[0x40000000000661f0] ./python(PyObject_Call+0x1ffffffff486ef00)[0x4000000000043470] ./python[0x40000000001bbec0] ./python(PyObject_Call+0x1ffffffff486ef00)[0x4000000000043470] ./python[0x400000000027f6a0] ./python[0x400000000027d3e0] ./python(PyEval_EvalFrameEx+0x1ffffffff4a98330)[0x400000000026c880] ./python(PyEval_EvalCodeEx+0x1ffffffff4aa0220)[0x4000000000274780] ./python[0x40000000004157c0] ======= Memory map: ======== 00000000-00004000 r--p 00000000 00:00 0 2000000000000000-200000000003c000 r-xp 00000000 03:05 2420685 /lib/ld-2.8.so 2000000000048000-2000000000050000 rw-p 00038000 03:05 2420685 /lib/ld-2.8.so 2000000000050000-2000000000078000 r-xp 00000000 03:05 2420667 /lib/libpthread-2.8.so 2000000000078000-2000000000084000 ---p 00028000 03:05 2420667 /lib/libpthread-2.8.so 2000000000084000-200000000008c000 rw-p 00024000 03:05 2420667 /lib/libpthread-2.8.so 200000000008c000-2000000000094000 rw-p 200000000008c000 00:00 0 2000000000094000-200000000009c000 r-xp 00000000 03:05 2420682 /lib/libdl-2.8.so 200000000009c000-20000000000a8000 ---p 00008make: *** [buildbottest] Aborted sincerely, -The Buildbot From python-checkins at python.org Sun Mar 1 03:04:34 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 1 Mar 2009 03:04:34 +0100 (CET) Subject: [Python-checkins] r70081 - python/trunk/Doc/library/configparser.rst Message-ID: <20090301020434.3DE061E4016@bag.python.org> Author: raymond.hettinger Date: Sun Mar 1 03:04:32 2009 New Revision: 70081 Log: Fix docs for ConfigParser. Modified: python/trunk/Doc/library/configparser.rst Modified: python/trunk/Doc/library/configparser.rst ============================================================================== --- python/trunk/Doc/library/configparser.rst (original) +++ python/trunk/Doc/library/configparser.rst Sun Mar 1 03:04:32 2009 @@ -76,7 +76,7 @@ *dict_type* was added. -.. class:: ConfigParser([defaults]) +.. class:: ConfigParser([defaults[, dict_type]]) Derived class of :class:`RawConfigParser` that implements the magical interpolation feature and adds optional arguments to the :meth:`get` and @@ -92,7 +92,7 @@ equivalent. -.. class:: SafeConfigParser([defaults]) +.. class:: SafeConfigParser([defaults[, dict_type]]) Derived class of :class:`ConfigParser` that implements a more-sane variant of the magical interpolation feature. This implementation is more predictable as From python-checkins at python.org Sun Mar 1 03:07:25 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 1 Mar 2009 03:07:25 +0100 (CET) Subject: [Python-checkins] r70082 - python/branches/release26-maint/Doc/library/configparser.rst Message-ID: <20090301020725.D852C1E4002@bag.python.org> Author: raymond.hettinger Date: Sun Mar 1 03:07:25 2009 New Revision: 70082 Log: Fix docs for ConfigParser. Modified: python/branches/release26-maint/Doc/library/configparser.rst Modified: python/branches/release26-maint/Doc/library/configparser.rst ============================================================================== --- python/branches/release26-maint/Doc/library/configparser.rst (original) +++ python/branches/release26-maint/Doc/library/configparser.rst Sun Mar 1 03:07:25 2009 @@ -76,7 +76,7 @@ *dict_type* was added. -.. class:: ConfigParser([defaults]) +.. class:: ConfigParser([defaults[, dict_type]]) Derived class of :class:`RawConfigParser` that implements the magical interpolation feature and adds optional arguments to the :meth:`get` and @@ -92,7 +92,7 @@ equivalent. -.. class:: SafeConfigParser([defaults]) +.. class:: SafeConfigParser([defaults[, dict_type]]) Derived class of :class:`ConfigParser` that implements a more-sane variant of the magical interpolation feature. This implementation is more predictable as From python-checkins at python.org Sun Mar 1 03:15:42 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 1 Mar 2009 03:15:42 +0100 (CET) Subject: [Python-checkins] r70083 - python/branches/release30-maint/Doc/library/configparser.rst Message-ID: <20090301021542.DB7181E4002@bag.python.org> Author: raymond.hettinger Date: Sun Mar 1 03:15:42 2009 New Revision: 70083 Log: Fix docs for ConfigParser. Modified: python/branches/release30-maint/Doc/library/configparser.rst Modified: python/branches/release30-maint/Doc/library/configparser.rst ============================================================================== --- python/branches/release30-maint/Doc/library/configparser.rst (original) +++ python/branches/release30-maint/Doc/library/configparser.rst Sun Mar 1 03:15:42 2009 @@ -65,7 +65,7 @@ support the magical interpolation behavior. -.. class:: ConfigParser([defaults]) +.. class:: ConfigParser([defaults[, dict_type]]) Derived class of :class:`RawConfigParser` that implements the magical interpolation feature and adds optional arguments to the :meth:`get` and @@ -81,7 +81,7 @@ equivalent. -.. class:: SafeConfigParser([defaults]) +.. class:: SafeConfigParser([defaults[, dict_type]]) Derived class of :class:`ConfigParser` that implements a more-sane variant of the magical interpolation feature. This implementation is more predictable as From python-checkins at python.org Sun Mar 1 03:16:04 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 1 Mar 2009 03:16:04 +0100 (CET) Subject: [Python-checkins] r70084 - python/branches/py3k/Doc/library/configparser.rst Message-ID: <20090301021604.E2B0E1E4002@bag.python.org> Author: raymond.hettinger Date: Sun Mar 1 03:16:04 2009 New Revision: 70084 Log: Fix docs for ConfigParser. Modified: python/branches/py3k/Doc/library/configparser.rst Modified: python/branches/py3k/Doc/library/configparser.rst ============================================================================== --- python/branches/py3k/Doc/library/configparser.rst (original) +++ python/branches/py3k/Doc/library/configparser.rst Sun Mar 1 03:16:04 2009 @@ -65,7 +65,7 @@ support the magical interpolation behavior. -.. class:: ConfigParser([defaults]) +.. class:: ConfigParser([defaults[, dict_type]]) Derived class of :class:`RawConfigParser` that implements the magical interpolation feature and adds optional arguments to the :meth:`get` and @@ -81,7 +81,7 @@ equivalent. -.. class:: SafeConfigParser([defaults]) +.. class:: SafeConfigParser([defaults[, dict_type]]) Derived class of :class:`ConfigParser` that implements a more-sane variant of the magical interpolation feature. This implementation is more predictable as From python-checkins at python.org Sun Mar 1 11:34:55 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 1 Mar 2009 11:34:55 +0100 (CET) Subject: [Python-checkins] r70085 - peps/trunk/pep-0372.txt Message-ID: <20090301103455.079441E4002@bag.python.org> Author: raymond.hettinger Date: Sun Mar 1 11:34:54 2009 New Revision: 70085 Log: Add link to a working patch. Modified: peps/trunk/pep-0372.txt Modified: peps/trunk/pep-0372.txt ============================================================================== --- peps/trunk/pep-0372.txt (original) +++ peps/trunk/pep-0372.txt Sun Mar 1 11:34:54 2009 @@ -22,6 +22,13 @@ and other programming languages. +Patch +===== + +A working Py3.1 patch including tests and documentation is at: + + `OrderedDict patch `_ + Rationale ========= @@ -251,9 +258,9 @@ Reference Implementation ======================== -A proposed version is at: +An implementation with tests and documentation is at: - `OrderedDict recipe `_ + `OrderedDict patch `_ The proposed version has several merits: @@ -264,8 +271,6 @@ * Generally good performance. The big-oh times are the same as regular dictionaries except that key deletion is O(n). -* The code runs without modification on Py2.6, Py2.7, Py3.0, and Py3.1. - Other implementations of ordered dicts in various Python projects or standalone libraries, that inspired the API proposed here, are: From python-checkins at python.org Mon Mar 2 04:35:13 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 2 Mar 2009 04:35:13 +0100 (CET) Subject: [Python-checkins] r70086 - in python/trunk: Lib/mimetypes.py Misc/NEWS Message-ID: <20090302033513.301EC1E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 2 04:35:12 2009 New Revision: 70086 Log: fix a silly problem of caching gone wrong #5401 Modified: python/trunk/Lib/mimetypes.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/mimetypes.py ============================================================================== --- python/trunk/Lib/mimetypes.py (original) +++ python/trunk/Lib/mimetypes.py Mon Mar 2 04:35:12 2009 @@ -237,7 +237,8 @@ Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ - init() + if not inited: + init() return guess_type(url, strict) @@ -254,7 +255,8 @@ Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ - init() + if not inited: + init() return guess_all_extensions(type, strict) def guess_extension(type, strict=True): @@ -269,7 +271,8 @@ Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ - init() + if not inited: + init() return guess_extension(type, strict) def add_type(type, ext, strict=True): @@ -284,7 +287,8 @@ list of standard types, else to the list of non-standard types. """ - init() + if not inited: + init() return add_type(type, ext, strict) Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Mon Mar 2 04:35:12 2009 @@ -166,6 +166,9 @@ Library ------- +- Issue #5401: Fixed a performance problem in mimetypes when ``from mimetypes + import guess_extension`` was used. + - Issue #1733986: Fixed mmap crash in accessing elements of second map object with same tagname but larger size than first map. (Windows) From python-checkins at python.org Mon Mar 2 04:42:40 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 2 Mar 2009 04:42:40 +0100 (CET) Subject: [Python-checkins] r70087 - in python/branches/release26-maint: Lib/mimetypes.py Misc/NEWS Message-ID: <20090302034240.0A4561E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 2 04:42:39 2009 New Revision: 70087 Log: Merged revisions 70086 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70086 | benjamin.peterson | 2009-03-01 21:35:12 -0600 (Sun, 01 Mar 2009) | 1 line fix a silly problem of caching gone wrong #5401 ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/mimetypes.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/mimetypes.py ============================================================================== --- python/branches/release26-maint/Lib/mimetypes.py (original) +++ python/branches/release26-maint/Lib/mimetypes.py Mon Mar 2 04:42:39 2009 @@ -237,7 +237,8 @@ Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ - init() + if not inited: + init() return guess_type(url, strict) @@ -254,7 +255,8 @@ Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ - init() + if not inited: + init() return guess_all_extensions(type, strict) def guess_extension(type, strict=True): @@ -269,7 +271,8 @@ Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ - init() + if not inited: + init() return guess_extension(type, strict) def add_type(type, ext, strict=True): @@ -284,7 +287,8 @@ list of standard types, else to the list of non-standard types. """ - init() + if not inited: + init() return add_type(type, ext, strict) Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Mon Mar 2 04:42:39 2009 @@ -89,6 +89,9 @@ Library ------- +- Issue #5401: Fixed a performance problem in mimetypes when ``from mimetypes + import guess_extension`` was used. + - Issue #1733986: Fixed mmap crash in accessing elements of second map object with same tagname but larger size than first map. (Windows) From buildbot at python.org Mon Mar 2 05:22:53 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 02 Mar 2009 04:22:53 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090302042253.633711E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/204 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 ====================================================================== FAIL: test01_basic_replication (bsddb.test.test_replication.DBReplicationManager) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ppc/build/Lib/bsddb/test/test_replication.py", line 134, in test01_basic_replication self.assertTrue(time.time() The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/695 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Mon Mar 2 05:53:25 2009 From: python-checkins at python.org (gregory.p.smith) Date: Mon, 2 Mar 2009 05:53:25 +0100 (CET) Subject: [Python-checkins] r70088 - python/trunk/Doc/library/re.rst Message-ID: <20090302045325.145591E400C@bag.python.org> Author: gregory.p.smith Date: Mon Mar 2 05:53:24 2009 New Revision: 70088 Log: The note about caching of regular expression objects was incorrect ReST and thus invisible in the compiled documentation. Fixed. Also I cleaned up the wording. Modified: python/trunk/Doc/library/re.rst Modified: python/trunk/Doc/library/re.rst ============================================================================== --- python/trunk/Doc/library/re.rst (original) +++ python/trunk/Doc/library/re.rst Mon Mar 2 05:53:24 2009 @@ -440,19 +440,23 @@ The sequence :: - prog = re.compile(pat) - result = prog.match(str) + prog = re.compile(pattern) + result = prog.match(string) is equivalent to :: - result = re.match(pat, str) + result = re.match(pattern, string) - but the version using :func:`compile` is more efficient when the expression - will be used several times in a single program. + but using :func:`compile` and saving the resulting regular expression object + for reuse is more efficient when the expression will be used several times + in a single program. - .. (The compiled version of the last pattern passed to :func:`re.match` or - :func:`re.search` is cached, so programs that use only a single regular - expression at a time needn't worry about compiling regular expressions.) + .. note:: + + The compiled versions of the most recent patterns passed to + :func:`re.match`, :func:`re.search` or :func:`re.compile` are cached, so + programs that use only a few regular expressions at a time needn't worry + about compiling regular expressions. .. data:: I From python-checkins at python.org Mon Mar 2 06:04:04 2009 From: python-checkins at python.org (gregory.p.smith) Date: Mon, 2 Mar 2009 06:04:04 +0100 (CET) Subject: [Python-checkins] r70089 - in python/branches/py3k: Doc/library/re.rst Message-ID: <20090302050404.C55111E403B@bag.python.org> Author: gregory.p.smith Date: Mon Mar 2 06:04:04 2009 New Revision: 70089 Log: Merged r70088 from trunk (re documentation update) Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/re.rst Modified: python/branches/py3k/Doc/library/re.rst ============================================================================== --- python/branches/py3k/Doc/library/re.rst (original) +++ python/branches/py3k/Doc/library/re.rst Mon Mar 2 06:04:04 2009 @@ -460,19 +460,23 @@ The sequence :: - prog = re.compile(pat) - result = prog.match(str) + prog = re.compile(pattern) + result = prog.match(string) is equivalent to :: - result = re.match(pat, str) + result = re.match(pattern, string) - but the version using :func:`compile` is more efficient when the expression - will be used several times in a single program. + but using :func:`compile` and saving the resulting regular expression object + for reuse is more efficient when the expression will be used several times + in a single program. - .. (The compiled version of the last pattern passed to :func:`re.match` or - :func:`re.search` is cached, so programs that use only a single regular - expression at a time needn't worry about compiling regular expressions.) + .. note:: + + The compiled versions of the most recent patterns passed to + :func:`re.match`, :func:`re.search` or :func:`re.compile` are cached, so + programs that use only a few regular expressions at a time needn't worry + about compiling regular expressions. .. data:: A From python-checkins at python.org Mon Mar 2 06:13:58 2009 From: python-checkins at python.org (gregory.p.smith) Date: Mon, 2 Mar 2009 06:13:58 +0100 (CET) Subject: [Python-checkins] r70090 - in python/trunk: Doc/library/re.rst Lib/re.py Misc/NEWS Message-ID: <20090302051358.4F9271E4002@bag.python.org> Author: gregory.p.smith Date: Mon Mar 2 06:13:57 2009 New Revision: 70090 Log: Adds an optional flags argument to re.split, re.sub and re.subn to be consistent with the other re module functions. Modified: python/trunk/Doc/library/re.rst python/trunk/Lib/re.py python/trunk/Misc/NEWS Modified: python/trunk/Doc/library/re.rst ============================================================================== --- python/trunk/Doc/library/re.rst (original) +++ python/trunk/Doc/library/re.rst Mon Mar 2 06:13:57 2009 @@ -540,7 +540,7 @@ instead. -.. function:: split(pattern, string[, maxsplit=0]) +.. function:: split(pattern, string[, maxsplit=0, flags=0]) Split *string* by the occurrences of *pattern*. If capturing parentheses are used in *pattern*, then the text of all groups in the pattern are also returned @@ -555,6 +555,8 @@ ['Words', ', ', 'words', ', ', 'words', '.', ''] >>> re.split('\W+', 'Words, words, words.', 1) ['Words', 'words, words.'] + >>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE) + ['0', '3', '9'] If there are capturing groups in the separator and it matches at the start of the string, the result will start with an empty string. The same holds for @@ -575,6 +577,9 @@ >>> re.split("(?m)^$", "foo\n\nbar\n") ['foo\n\nbar\n'] + .. versionchanged:: 2.7,3.1 + Added the optional flags argument. + .. function:: findall(pattern, string[, flags]) @@ -605,7 +610,7 @@ Added the optional flags argument. -.. function:: sub(pattern, repl, string[, count]) +.. function:: sub(pattern, repl, string[, count, flags]) Return the string obtained by replacing the leftmost non-overlapping occurrences of *pattern* in *string* by the replacement *repl*. If the pattern isn't found, @@ -630,6 +635,8 @@ ... else: return '-' >>> re.sub('-{1,2}', dashrepl, 'pro----gram-files') 'pro--gram files' + >>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE) + 'Baked Beans & Spam' The pattern may be a string or an RE object; if you need to specify regular expression flags, you must use a RE object, or use embedded modifiers in a @@ -650,12 +657,18 @@ character ``'0'``. The backreference ``\g<0>`` substitutes in the entire substring matched by the RE. + .. versionchanged:: 2.7,3.1 + Added the optional flags argument. + -.. function:: subn(pattern, repl, string[, count]) +.. function:: subn(pattern, repl, string[, count, flags]) Perform the same operation as :func:`sub`, but return a tuple ``(new_string, number_of_subs_made)``. + .. versionchanged:: 2.7,3.1 + Added the optional flags argument. + .. function:: escape(string) Modified: python/trunk/Lib/re.py ============================================================================== --- python/trunk/Lib/re.py (original) +++ python/trunk/Lib/re.py Mon Mar 2 06:13:57 2009 @@ -141,16 +141,16 @@ a match object, or None if no match was found.""" return _compile(pattern, flags).search(string) -def sub(pattern, repl, string, count=0): +def sub(pattern, repl, string, count=0, flags=0): """Return the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in string by the replacement repl. repl can be either a string or a callable; if a string, backslash escapes in it are processed. If it is a callable, it's passed the match object and must return a replacement string to be used.""" - return _compile(pattern, 0).sub(repl, string, count) + return _compile(pattern, flags).sub(repl, string, count) -def subn(pattern, repl, string, count=0): +def subn(pattern, repl, string, count=0, flags=0): """Return a 2-tuple containing (new_string, number). new_string is the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in the source @@ -159,12 +159,12 @@ callable; if a string, backslash escapes in it are processed. If it is a callable, it's passed the match object and must return a replacement string to be used.""" - return _compile(pattern, 0).subn(repl, string, count) + return _compile(pattern, flags).subn(repl, string, count) -def split(pattern, string, maxsplit=0): +def split(pattern, string, maxsplit=0, flags=0): """Split the source string by the occurrences of the pattern, returning a list containing the resulting substrings.""" - return _compile(pattern, 0).split(string, maxsplit) + return _compile(pattern, flags).split(string, maxsplit) def findall(pattern, string, flags=0): """Return a list of all non-overlapping matches in the string. Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Mon Mar 2 06:13:57 2009 @@ -163,6 +163,8 @@ - Issue #3582: Use native TLS functions on Windows +- The re.sub(), re.subn() and re.split() functions now accept a flags parameter. + Library ------- From buildbot at python.org Mon Mar 2 06:20:11 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 02 Mar 2009 05:20:11 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo 3.x Message-ID: <20090302052012.03B401E4002@bag.python.org> The Buildbot has detected a new failure of x86 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20gentoo%203.x/builds/443 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: gregory.p.smith,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Unknown signal 32 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 2 06:21:56 2009 From: python-checkins at python.org (gregory.p.smith) Date: Mon, 2 Mar 2009 06:21:56 +0100 (CET) Subject: [Python-checkins] r70091 - in python/branches/py3k: Doc/library/re.rst Lib/re.py Misc/NEWS Message-ID: <20090302052156.0A27C1E4002@bag.python.org> Author: gregory.p.smith Date: Mon Mar 2 06:21:55 2009 New Revision: 70091 Log: Merged revisions 70090 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70090 | gregory.p.smith | 2009-03-01 21:13:57 -0800 (Sun, 01 Mar 2009) | 3 lines Adds an optional flags argument to re.split, re.sub and re.subn to be consistent with the other re module functions. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/re.rst python/branches/py3k/Lib/re.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Doc/library/re.rst ============================================================================== --- python/branches/py3k/Doc/library/re.rst (original) +++ python/branches/py3k/Doc/library/re.rst Mon Mar 2 06:21:55 2009 @@ -571,7 +571,7 @@ instead. -.. function:: split(pattern, string[, maxsplit=0]) +.. function:: split(pattern, string[, maxsplit=0, flags=0]) Split *string* by the occurrences of *pattern*. If capturing parentheses are used in *pattern*, then the text of all groups in the pattern are also returned @@ -585,6 +585,8 @@ ['Words', ', ', 'words', ', ', 'words', '.', ''] >>> re.split('\W+', 'Words, words, words.', 1) ['Words', 'words, words.'] + >>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE) + ['0', '3', '9'] If there are capturing groups in the separator and it matches at the start of the string, the result will start with an empty string. The same holds for @@ -605,6 +607,9 @@ >>> re.split("(?m)^$", "foo\n\nbar\n") ['foo\n\nbar\n'] + .. versionchanged:: 2.7,3.1 + Added the optional flags argument. + .. function:: findall(pattern, string[, flags]) @@ -625,7 +630,7 @@ match. -.. function:: sub(pattern, repl, string[, count]) +.. function:: sub(pattern, repl, string[, count, flags]) Return the string obtained by replacing the leftmost non-overlapping occurrences of *pattern* in *string* by the replacement *repl*. If the pattern isn't found, @@ -650,6 +655,8 @@ ... else: return '-' >>> re.sub('-{1,2}', dashrepl, 'pro----gram-files') 'pro--gram files' + >>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE) + 'Baked Beans & Spam' The pattern may be a string or an RE object; if you need to specify regular expression flags, you must use a RE object, or use embedded modifiers in a @@ -670,12 +677,18 @@ character ``'0'``. The backreference ``\g<0>`` substitutes in the entire substring matched by the RE. + .. versionchanged:: 2.7,3.1 + Added the optional flags argument. + -.. function:: subn(pattern, repl, string[, count]) +.. function:: subn(pattern, repl, string[, count, flags]) Perform the same operation as :func:`sub`, but return a tuple ``(new_string, number_of_subs_made)``. + .. versionchanged:: 2.7,3.1 + Added the optional flags argument. + .. function:: escape(string) Modified: python/branches/py3k/Lib/re.py ============================================================================== --- python/branches/py3k/Lib/re.py (original) +++ python/branches/py3k/Lib/re.py Mon Mar 2 06:21:55 2009 @@ -156,16 +156,16 @@ a match object, or None if no match was found.""" return _compile(pattern, flags).search(string) -def sub(pattern, repl, string, count=0): +def sub(pattern, repl, string, count=0, flags=0): """Return the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in string by the replacement repl. repl can be either a string or a callable; if a string, backslash escapes in it are processed. If it is a callable, it's passed the match object and must return a replacement string to be used.""" - return _compile(pattern, 0).sub(repl, string, count) + return _compile(pattern, flags).sub(repl, string, count) -def subn(pattern, repl, string, count=0): +def subn(pattern, repl, string, count=0, flags=0): """Return a 2-tuple containing (new_string, number). new_string is the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in the source @@ -174,12 +174,12 @@ callable; if a string, backslash escapes in it are processed. If it is a callable, it's passed the match object and must return a replacement string to be used.""" - return _compile(pattern, 0).subn(repl, string, count) + return _compile(pattern, flags).subn(repl, string, count) -def split(pattern, string, maxsplit=0): +def split(pattern, string, maxsplit=0, flags=0): """Split the source string by the occurrences of the pattern, returning a list containing the resulting substrings.""" - return _compile(pattern, 0).split(string, maxsplit) + return _compile(pattern, flags).split(string, maxsplit) def findall(pattern, string, flags=0): """Return a list of all non-overlapping matches in the string. Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Mon Mar 2 06:21:55 2009 @@ -170,6 +170,8 @@ - Issue #4748: Lambda generators no longer return a value. +- The re.sub(), re.subn() and re.split() functions now accept a flags parameter. + Library ------- From python-checkins at python.org Mon Mar 2 06:25:12 2009 From: python-checkins at python.org (gregory.p.smith) Date: Mon, 2 Mar 2009 06:25:12 +0100 (CET) Subject: [Python-checkins] r70092 - in python/branches/release26-maint: Doc/library/re.rst Message-ID: <20090302052512.2EC881E4002@bag.python.org> Author: gregory.p.smith Date: Mon Mar 2 06:25:11 2009 New Revision: 70092 Log: Merged revisions 70088 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70088 | gregory.p.smith | 2009-03-01 20:53:24 -0800 (Sun, 01 Mar 2009) | 4 lines The note about caching of regular expression objects was incorrect ReST and thus invisible in the compiled documentation. Fixed. Also I cleaned up the wording. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/library/re.rst Modified: python/branches/release26-maint/Doc/library/re.rst ============================================================================== --- python/branches/release26-maint/Doc/library/re.rst (original) +++ python/branches/release26-maint/Doc/library/re.rst Mon Mar 2 06:25:11 2009 @@ -440,19 +440,23 @@ The sequence :: - prog = re.compile(pat) - result = prog.match(str) + prog = re.compile(pattern) + result = prog.match(string) is equivalent to :: - result = re.match(pat, str) + result = re.match(pattern, string) - but the version using :func:`compile` is more efficient when the expression - will be used several times in a single program. + but using :func:`compile` and saving the resulting regular expression object + for reuse is more efficient when the expression will be used several times + in a single program. - .. (The compiled version of the last pattern passed to :func:`re.match` or - :func:`re.search` is cached, so programs that use only a single regular - expression at a time needn't worry about compiling regular expressions.) + .. note:: + + The compiled versions of the most recent patterns passed to + :func:`re.match`, :func:`re.search` or :func:`re.compile` are cached, so + programs that use only a few regular expressions at a time needn't worry + about compiling regular expressions. .. data:: I From python-checkins at python.org Mon Mar 2 06:35:45 2009 From: python-checkins at python.org (gregory.p.smith) Date: Mon, 2 Mar 2009 06:35:45 +0100 (CET) Subject: [Python-checkins] r70093 - in python/branches/release30-maint: Doc/library/re.rst Message-ID: <20090302053545.A7F081E4002@bag.python.org> Author: gregory.p.smith Date: Mon Mar 2 06:35:45 2009 New Revision: 70093 Log: Merged revisions 70089 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70089 | gregory.p.smith | 2009-03-01 21:04:04 -0800 (Sun, 01 Mar 2009) | 2 lines Merged r70088 from trunk (re documentation update) ........ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Doc/library/re.rst Modified: python/branches/release30-maint/Doc/library/re.rst ============================================================================== --- python/branches/release30-maint/Doc/library/re.rst (original) +++ python/branches/release30-maint/Doc/library/re.rst Mon Mar 2 06:35:45 2009 @@ -460,19 +460,23 @@ The sequence :: - prog = re.compile(pat) - result = prog.match(str) + prog = re.compile(pattern) + result = prog.match(string) is equivalent to :: - result = re.match(pat, str) + result = re.match(pattern, string) - but the version using :func:`compile` is more efficient when the expression - will be used several times in a single program. + but using :func:`compile` and saving the resulting regular expression object + for reuse is more efficient when the expression will be used several times + in a single program. - .. (The compiled version of the last pattern passed to :func:`re.match` or - :func:`re.search` is cached, so programs that use only a single regular - expression at a time needn't worry about compiling regular expressions.) + .. note:: + + The compiled versions of the most recent patterns passed to + :func:`re.match`, :func:`re.search` or :func:`re.compile` are cached, so + programs that use only a few regular expressions at a time needn't worry + about compiling regular expressions. .. data:: A From python-checkins at python.org Mon Mar 2 06:38:44 2009 From: python-checkins at python.org (tarek.ziade) Date: Mon, 2 Mar 2009 06:38:44 +0100 (CET) Subject: [Python-checkins] r70094 - in python/trunk/Lib/distutils: command/bdist_rpm.py tests/test_bdist_rpm.py Message-ID: <20090302053844.882DE1E4002@bag.python.org> Author: tarek.ziade Date: Mon Mar 2 06:38:44 2009 New Revision: 70094 Log: removing the force-optimized option as discussed in #1533164 Modified: python/trunk/Lib/distutils/command/bdist_rpm.py python/trunk/Lib/distutils/tests/test_bdist_rpm.py Modified: python/trunk/Lib/distutils/command/bdist_rpm.py ============================================================================== --- python/trunk/Lib/distutils/command/bdist_rpm.py (original) +++ python/trunk/Lib/distutils/command/bdist_rpm.py Mon Mar 2 06:38:44 2009 @@ -126,18 +126,10 @@ ('quiet', 'q', "Run the INSTALL phase of RPM building in quiet mode"), - - # Forces the -O1 option when calling the install command, - # so the rpm contains all files needed for proper operation under - # SELinux. Some systems checks for this on build-time and will - # fail without this. - ('force-optimize', None, - "Forces the -O1 option when calling the install command"), - ] boolean_options = ['keep-temp', 'use-rpm-opt-flags', 'rpm3-mode', - 'no-autoreq', 'quiet', 'force-optimize'] + 'no-autoreq', 'quiet'] negative_opt = {'no-keep-temp': 'keep-temp', 'no-rpm-opt-flags': 'use-rpm-opt-flags', @@ -188,7 +180,6 @@ self.force_arch = None self.quiet = 0 - self.force_optimize = 1 # initialize_options() @@ -504,14 +495,8 @@ # that we open and interpolate into the spec file, but the defaults # are just text that we drop in as-is. Hmmm. - # forcing -O1 if force-optimize - if self.force_optimize: - optimize = ' -O1' - else: - optimize = '' - - install_cmd = ('%s install%s --root=$RPM_BUILD_ROOT ' - '--record=INSTALLED_FILES') % (def_setup_call, optimize) + install_cmd = ('%s install -O1 --root=$RPM_BUILD_ROOT ' + '--record=INSTALLED_FILES') % def_setup_call script_options = [ ('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"), Modified: python/trunk/Lib/distutils/tests/test_bdist_rpm.py ============================================================================== --- python/trunk/Lib/distutils/tests/test_bdist_rpm.py (original) +++ python/trunk/Lib/distutils/tests/test_bdist_rpm.py Mon Mar 2 06:38:44 2009 @@ -109,8 +109,6 @@ cmd = bdist_rpm(dist) cmd.fix_python = True - # running with force-optimize = 1 - # and quiet = 1 cmd.quiet = 1 cmd.ensure_finalized() cmd.run() @@ -119,29 +117,6 @@ self.assert_('foo-0.1-1.noarch.rpm' in dist_created) os.remove(os.path.join(pkg_dir, 'dist', 'foo-0.1-1.noarch.rpm')) - # XXX I am unable yet to make this test work without - # spurious stderr output - # so returning until distutils.spawn acts better - return - - # running with force-optimize = 0 - cmd.force_optimize = 0 - try: - # XXX How to prevent the spawned - # rpmbuild command to display errors ? - # this can be a problem for buildbots - cmd.ensure_finalized() - cmd.run() - except DistutilsExecError: - # happens only under Fedora/RedHat - # and some flavors of Linux - # otherwise it's a bug - if sys.platform == 'linux2': - return - - dist_created = os.listdir(os.path.join(pkg_dir, 'dist')) - self.assert_('foo-0.1-1.noarch.rpm' in dist_created) - def test_suite(): return unittest.makeSuite(BuildRpmTestCase) From python-checkins at python.org Mon Mar 2 06:40:02 2009 From: python-checkins at python.org (tarek.ziade) Date: Mon, 2 Mar 2009 06:40:02 +0100 (CET) Subject: [Python-checkins] r70095 - python/branches/release26-maint Message-ID: <20090302054002.A25961E4002@bag.python.org> Author: tarek.ziade Date: Mon Mar 2 06:40:02 2009 New Revision: 70095 Log: Blocked revisions 70094 via svnmerge ........ r70094 | tarek.ziade | 2009-03-02 06:38:44 +0100 (Mon, 02 Mar 2009) | 1 line removing the force-optimized option as discussed in #1533164 ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Mon Mar 2 06:41:25 2009 From: python-checkins at python.org (tarek.ziade) Date: Mon, 2 Mar 2009 06:41:25 +0100 (CET) Subject: [Python-checkins] r70096 - in python/branches/py3k: Lib/distutils/command/bdist_rpm.py Lib/distutils/tests/test_bdist_rpm.py Message-ID: <20090302054125.8FF291E4002@bag.python.org> Author: tarek.ziade Date: Mon Mar 2 06:41:25 2009 New Revision: 70096 Log: Merged revisions 70094 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70094 | tarek.ziade | 2009-03-02 06:38:44 +0100 (Mon, 02 Mar 2009) | 1 line removing the force-optimized option as discussed in #1533164 ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/distutils/command/bdist_rpm.py python/branches/py3k/Lib/distutils/tests/test_bdist_rpm.py Modified: python/branches/py3k/Lib/distutils/command/bdist_rpm.py ============================================================================== --- python/branches/py3k/Lib/distutils/command/bdist_rpm.py (original) +++ python/branches/py3k/Lib/distutils/command/bdist_rpm.py Mon Mar 2 06:41:25 2009 @@ -125,18 +125,10 @@ ('quiet', 'q', "Run the INSTALL phase of RPM building in quiet mode"), - - # Forces the -O1 option when calling the install command, - # so the rpm contains all files needed for proper operation under - # SELinux. Some systems checks for this on build-time and will - # fail without this. - ('force-optimize', None, - "Forces the -O1 option when calling the install command"), - ] boolean_options = ['keep-temp', 'use-rpm-opt-flags', 'rpm3-mode', - 'no-autoreq', 'quiet', 'force-optimize'] + 'no-autoreq', 'quiet'] negative_opt = {'no-keep-temp': 'keep-temp', 'no-rpm-opt-flags': 'use-rpm-opt-flags', @@ -187,7 +179,6 @@ self.force_arch = None self.quiet = 0 - self.force_optimize = 1 def finalize_options(self): self.set_undefined_options('bdist', ('bdist_base', 'bdist_base')) @@ -492,14 +483,8 @@ # that we open and interpolate into the spec file, but the defaults # are just text that we drop in as-is. Hmmm. - # forcing -O1 if force-optimize - if self.force_optimize: - optimize = ' -O1' - else: - optimize = '' - - install_cmd = ('%s install%s --root=$RPM_BUILD_ROOT ' - '--record=INSTALLED_FILES') % (def_setup_call, optimize) + install_cmd = ('%s install -O1 --root=$RPM_BUILD_ROOT ' + '--record=INSTALLED_FILES') % def_setup_call script_options = [ ('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"), Modified: python/branches/py3k/Lib/distutils/tests/test_bdist_rpm.py ============================================================================== --- python/branches/py3k/Lib/distutils/tests/test_bdist_rpm.py (original) +++ python/branches/py3k/Lib/distutils/tests/test_bdist_rpm.py Mon Mar 2 06:41:25 2009 @@ -109,8 +109,6 @@ cmd = bdist_rpm(dist) cmd.fix_python = True - # running with force-optimize = 1 - # and quiet = 1 cmd.quiet = 1 cmd.ensure_finalized() cmd.run() @@ -119,29 +117,6 @@ self.assert_('foo-0.1-1.noarch.rpm' in dist_created) os.remove(os.path.join(pkg_dir, 'dist', 'foo-0.1-1.noarch.rpm')) - # XXX I am unable yet to make this test work without - # spurious stderr output - # so returning until distutils.spawn acts better - return - - # running with force-optimize = 0 - cmd.force_optimize = 0 - try: - # XXX How to prevent the spawned - # rpmbuild command to display errors ? - # this can be a problem for buildbots - cmd.ensure_finalized() - cmd.run() - except DistutilsExecError: - # happens only under Fedora/RedHat - # and some flavors of Linux - # otherwise it's a bug - if sys.platform == 'linux2': - return - - dist_created = os.listdir(os.path.join(pkg_dir, 'dist')) - self.assert_('foo-0.1-1.noarch.rpm' in dist_created) - def test_suite(): return unittest.makeSuite(BuildRpmTestCase) From python-checkins at python.org Mon Mar 2 06:41:57 2009 From: python-checkins at python.org (tarek.ziade) Date: Mon, 2 Mar 2009 06:41:57 +0100 (CET) Subject: [Python-checkins] r70097 - python/branches/release30-maint Message-ID: <20090302054157.916321E4002@bag.python.org> Author: tarek.ziade Date: Mon Mar 2 06:41:57 2009 New Revision: 70097 Log: Blocked revisions 70051 via svnmerge ................ r70051 | tarek.ziade | 2009-02-28 11:16:43 +0100 (Sat, 28 Feb 2009) | 9 lines Merged revisions 70049 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70049 | tarek.ziade | 2009-02-28 11:08:02 +0100 (Sat, 28 Feb 2009) | 1 line Issues #1533164 and #5378: Added quiet and force-optimize options to Distutils bdist_rpm command ........ ................ Modified: python/branches/release30-maint/ (props changed) From python-checkins at python.org Mon Mar 2 06:49:44 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Mon, 2 Mar 2009 06:49:44 +0100 (CET) Subject: [Python-checkins] r70098 - python/branches/py3k/Doc/c-api/buffer.rst Message-ID: <20090302054944.C1D9E1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Mon Mar 2 06:49:44 2009 New Revision: 70098 Log: Fixed typo. Modified: python/branches/py3k/Doc/c-api/buffer.rst Modified: python/branches/py3k/Doc/c-api/buffer.rst ============================================================================== --- python/branches/py3k/Doc/c-api/buffer.rst (original) +++ python/branches/py3k/Doc/c-api/buffer.rst Mon Mar 2 06:49:44 2009 @@ -252,7 +252,7 @@ .. cfunction:: void PyBuffer_Release(PyObject *obj, Py_buffer *view) - Release the buffer *view* over *obj*. This shouldd be called when the buffer + Release the buffer *view* over *obj*. This should be called when the buffer is no longer being used as it may free memory from it. From buildbot at python.org Mon Mar 2 06:52:50 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 02 Mar 2009 05:52:50 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo trunk Message-ID: <20090302055251.173B31E400C@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%20gentoo%20trunk/builds/4693 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: gregory.p.smith BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Mon Mar 2 08:12:36 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 02 Mar 2009 07:12:36 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090302071237.3ECD71E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/156 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: gregory.p.smith BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Mon Mar 2 08:28:52 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 02 Mar 2009 07:28:52 +0000 Subject: [Python-checkins] buildbot failure in OS X x86 trunk Message-ID: <20090302072852.BCB161E4002@bag.python.org> The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/199 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: tarek.ziade BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/threading.py", line 477, in run self.__target(*self.__args, **self.__kwargs) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/bsddb/test/test_thread.py", line 306, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/bsddb/dbutils.py", line 68, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') 1 test failed: test_applesingle make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Mon Mar 2 09:56:51 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 02 Mar 2009 08:56:51 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090302085651.B8F621E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/364 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: gregory.p.smith,tarek.ziade BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_posix test_subprocess ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_subprocess.py", line 149, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From buildbot at python.org Mon Mar 2 11:49:37 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 02 Mar 2009 10:49:37 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090302104938.5B7E91E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/190 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: tarek.ziade BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_distutils test_posix ====================================================================== FAIL: test_get_python_inc (distutils.tests.test_sysconfig.SysconfigTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/distutils/tests/test_sysconfig.py", line 45, in test_get_python_inc self.assert_(os.path.isdir(inc_dir), inc_dir) AssertionError: /home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/Include ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From buildbot at python.org Mon Mar 2 12:56:35 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 02 Mar 2009 11:56:35 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.0 Message-ID: <20090302115635.D65C91E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.0/builds/189 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: tarek.ziade BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From python-checkins at python.org Mon Mar 2 15:38:26 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 2 Mar 2009 15:38:26 +0100 (CET) Subject: [Python-checkins] r70099 - in python/branches/py3k: Doc/library/importlib.rst Lib/importlib/NOTES Lib/importlib/test/test_util.py Lib/importlib/util.py Message-ID: <20090302143826.8BC691E4002@bag.python.org> Author: brett.cannon Date: Mon Mar 2 15:38:26 2009 New Revision: 70099 Log: Expose importlib.util.set___package__. Modified: python/branches/py3k/Doc/library/importlib.rst python/branches/py3k/Lib/importlib/NOTES python/branches/py3k/Lib/importlib/test/test_util.py python/branches/py3k/Lib/importlib/util.py Modified: python/branches/py3k/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k/Doc/library/importlib.rst (original) +++ python/branches/py3k/Doc/library/importlib.rst Mon Mar 2 15:38:26 2009 @@ -167,20 +167,28 @@ A :term:`decorator` for a :term:`loader` which handles selecting the proper module object to load with. The decorated method is expected to have a call signature of ``method(self, module_object)`` for which the second argument - will be the module object to be used (note that the decorator will not work - on static methods because of the assumption of two arguments). + will be the module object to be used by the loader (note that the decorator + will not work on static methods because of the assumption of two + arguments). The decorated method will take in the name of the module to be loaded as - normal. If the module is not found in :data:`sys.modules` then a new one is - constructed with its :attr:`__name__` attribute set. Otherwise the module - found in :data:`sys.modules` will be passed into the method. If an + expected for a :term:`loader`. If the module is not found in + :data:`sys.modules` then a new one is constructed with its + :attr:`__name__` attribute set. Otherwise the module found in + :data:`sys.modules` will be passed into the method. If an exception is raised by the decorated method and a module was added to :data:`sys.modules` it will be removed to prevent a partially initialized - module from being in left in :data:`sys.modules` If an exception is raised - by the decorated method and a module was added to :data:`sys.modules` it - will be removed to prevent a partially initialized module from being in - left in :data:`sys.modules`. If the module was already in - :data:`sys.modules` then it is left alone. + module from being in left in :data:`sys.modules`. If the module was already + in :data:`sys.modules` then it is left alone. - Use of this decorator handles all the details of what module a loader - should use as specified by :pep:`302`. + Use of this decorator handles all the details of what module object a + loader should initialize as specified by :pep:`302`. + + +.. function:: set___package__(method) + + A :term:`decorator` for a :term:`loader` to set the :attr:`__package__` + attribute on the module returned by the loader. If :attr:`__package__` is + set and has a value other than :keyword:`None` it will not be changed. + Note that the module returned by the loader is what has the attribute + set on and not the module found in :data:`sys.modules`. Modified: python/branches/py3k/Lib/importlib/NOTES ============================================================================== --- python/branches/py3k/Lib/importlib/NOTES (original) +++ python/branches/py3k/Lib/importlib/NOTES Mon Mar 2 15:38:26 2009 @@ -1,10 +1,6 @@ to do ///// -* Implement PEP 302 protocol for loaders (should just be a matter of testing). - - + Source/bytecode. - * Public API left to expose (w/ docs!) + abc @@ -27,27 +23,15 @@ * get_code * get_source - - (?) SourceLoader(ResourceLoader) + - PyLoader(ResourceLoader) * source_path - * bytecode_path - * write_bytecode (not abstract) - - + util - - - set___package__ decorator - + machinery + - PyPycLoader(PyLoader) - - Extensions importers - - * ExtensionFinder - * (?) Loader - - - Source/bytecode importers - - * SourceFinder - * (?) Loader + * source_mtime + * bytecode_path + * write_bytecode + test (Really want to worry about compatibility with future versions?) Modified: python/branches/py3k/Lib/importlib/test/test_util.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/test_util.py (original) +++ python/branches/py3k/Lib/importlib/test/test_util.py Mon Mar 2 15:38:26 2009 @@ -60,9 +60,58 @@ self.assert_(sys.modules[name] is module) +class SetPackageTests(unittest.TestCase): + + + """Tests for importlib.util.set___package__.""" + + def verify(self, module, expect): + """Verify the module has the expected value for __package__ after + passing through set___package__.""" + fxn = lambda: module + wrapped = util.set___package__(fxn) + wrapped() + self.assert_(hasattr(module, '__package__')) + self.assertEqual(expect, module.__package__) + + def test_top_level(self): + # __package__ should be set to the empty string if a top-level module. + # Implicitly tests when package is set to None. + module = imp.new_module('module') + module.__package__ = None + self.verify(module, '') + + def test_package(self): + # Test setting __package__ for a package. + module = imp.new_module('pkg') + module.__path__ = [''] + module.__package__ = None + self.verify(module, 'pkg') + + def test_submodule(self): + # Test __package__ for a module in a package. + module = imp.new_module('pkg.mod') + module.__package__ = None + self.verify(module, 'pkg') + + def test_setting_if_missing(self): + # __package__ should be set if it is missing. + module = imp.new_module('mod') + if hasattr(module, '__package__'): + delattr(module, '__package__') + self.verify(module, '') + + def test_leaving_alone(self): + # If __package__ is set and not None then leave it alone. + for value in (True, False): + module = imp.new_module('mod') + module.__package__ = value + self.verify(module, value) + + def test_main(): from test import support - support.run_unittest(ModuleForLoaderTests) + support.run_unittest(ModuleForLoaderTests, SetPackageTests) if __name__ == '__main__': Modified: python/branches/py3k/Lib/importlib/util.py ============================================================================== --- python/branches/py3k/Lib/importlib/util.py (original) +++ python/branches/py3k/Lib/importlib/util.py Mon Mar 2 15:38:26 2009 @@ -1,2 +1,3 @@ """Utility code for constructing importers, etc.""" from ._bootstrap import module_for_loader +from ._bootstrap import set___package__ From solipsis at pitrou.net Mon Mar 2 16:06:31 2009 From: solipsis at pitrou.net (Antoine Pitrou) Date: Mon, 2 Mar 2009 15:06:31 +0000 (UTC) Subject: [Python-checkins] =?utf-8?q?r70099_-_in_python/branches/py3k=3A?= =?utf-8?q?=09Doc/library/importlib=2ErstLib/importlib/NOTES=09Lib/?= =?utf-8?q?importlib/test/test=5Futil=2Epy_Lib/importlib/util=2Epy?= References: <20090302143826.8BC691E4002@bag.python.org> Message-ID: writes: > > Log: > Expose importlib.util.set___package__. I'm not sure there's an underscore run-length restriction in PEP8, but what about simply naming it set_package ? :-) From python-checkins at python.org Mon Mar 2 21:40:37 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 2 Mar 2009 21:40:37 +0100 (CET) Subject: [Python-checkins] r70100 - peps/trunk/pep-0372.txt Message-ID: <20090302204037.158C21E400C@bag.python.org> Author: raymond.hettinger Date: Mon Mar 2 21:40:36 2009 New Revision: 70100 Log: Mark the PEP as Accepted. Replace the odict references with OrderedDict. Specify the __repr__() format. Update the __eq__() specification as discussed on python-dev. Modified: peps/trunk/pep-0372.txt Modified: peps/trunk/pep-0372.txt ============================================================================== --- peps/trunk/pep-0372.txt (original) +++ peps/trunk/pep-0372.txt Mon Mar 2 21:40:36 2009 @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Armin Ronacher Raymond Hettinger -Status: Draft +Status: Accepted Type: Standards Track Content-Type: text/x-rst Created: 15-Jun-2008 @@ -16,7 +16,7 @@ ======== This PEP proposes an ordered dictionary as a new data structure for -the ``collections`` module, called "odict" in this PEP for short. The +the ``collections`` module, called "OrderedDict" in this PEP. The proposed API incorporates the experiences gained from working with similar implementations that exist in various real-world applications and other programming languages. @@ -44,13 +44,13 @@ The following example shows the behavior for simple assignments: - >>> d = odict() + >>> d = OrderedDict() >>> d['parrot'] = 'dead' >>> d['penguin'] = 'exploded' >>> d.items() [('parrot', 'dead'), ('penguin', 'exploded')] -That the ordering is preserved makes an odict useful for a couple of +That the ordering is preserved makes an OrderedDict useful for a couple of situations: - XML/HTML processing libraries currently drop the ordering of @@ -97,10 +97,10 @@ well as mappings like a dict does. Unlike a regular dictionary, the insertion order is preserved. - >>> d = odict([('a', 'b'), ('c', 'd')]) + >>> d = OrderedDict([('a', 'b'), ('c', 'd')]) >>> d.update({'foo': 'bar'}) >>> d - collections.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar')]) + collections.OrderedDict([('a', 'b'), ('c', 'd'), ('foo', 'bar')]) If ordered dicts are updated from regular dicts, the ordering of new keys is of course undefined. @@ -119,7 +119,7 @@ New methods not available on dict: -``odict.__reversed__()`` +``OrderedDict.__reversed__()`` Supports reverse iteration by key. @@ -138,8 +138,8 @@ former. This has the side-effect that the position of the first key is used because only the value is actually overwritten:: - >>> odict([('a', 1), ('b', 2), ('a', 3)]) - collections.odict([('a', 3), ('b', 2)]) + >>> OrderedDict([('a', 1), ('b', 2), ('a', 3)]) + collections.OrderedDict([('a', 3), ('b', 2)]) This behavior is consistent with existing implementations in Python, the PHP array and the hashmap in Ruby 1.9. @@ -155,10 +155,10 @@ Do any limitations arise from subclassing dict? Yes. Since the API for dicts is different in Py2.x and Py3.x, the - odict API must also be different. So, the Py2.7 version will need + OrderedDict API must also be different. So, the Py2.7 version will need to override iterkeys, itervalues, and iteritems. -Does ``odict.popitem()`` return a particular key/value pair? +Does ``OrderedDict.popitem()`` return a particular key/value pair? Yes. It pops-off the most recently inserted new key and its corresponding value. This corresponds to the usual LIFO behavior @@ -167,23 +167,26 @@ The actual implementation is more efficient and pops directly from a sorted list of keys. -Does odict support indexing, slicing, and whatnot? +Does OrderedDict support indexing, slicing, and whatnot? - As a matter of fact, ``odict`` does not implement the ``Sequence`` + As a matter of fact, ``OrderedDict`` does not implement the ``Sequence`` interface. Rather, it is a ``MutableMapping`` that remembers the order of key insertion. The only sequence-like addition is support for ``reversed``. -Does odict support alternate sort orders such as alphabetical? + An further advantage of not allowing indexing is that it leaves open + the possibility of a fast C implementation using linked lists. + +Does OrderedDict support alternate sort orders such as alphabetical? No. Those wanting different sort orders really need to be using another - technique. The odict is all about recording insertion order. If any + technique. The OrderedDict is all about recording insertion order. If any other order is of interest, then another structure (like an in-memory dbm) is likely a better fit. -How well does odict work with the json module, PyYAML, and ConfigParser? +How well does OrderedDict work with the json module, PyYAML, and ConfigParser? - For json, the good news is that json's encoder respects odict's iteration order:: + For json, the good news is that json's encoder respects OrderedDict's iteration order:: >>> items = [('one', 1), ('two', 2), ('three',3), ('four',4), ('five',5)] >>> json.dumps(OrderedDict(items)) @@ -221,20 +224,18 @@ >>> config.remove_option('Log', 'error') >>> config.write(open('myconfig.ini', 'w')) -How does odict handle equality testing? +How does OrderedDict handle equality testing? + + Comparing two ordered dictionaries implies that the test will be + order-sensitive so that list ``(od1.items())==list(od2.items())``. - Being a dict, one might expect equality tests to not care about order. For - an odict-to-dict comparison, this would be a necessity and it's probably - not wise to silently switch comparison modes based on the input types. - Also, some third-party tools that expect dict inputs may also expect the - comparison to not care about order. Accordingly, we decided to punt and - let the usual dict equality testing run without reference to internal - ordering. This should be documented clearly since different people will - have different expectations. If a use case does arise, it's not hard for - a user explicitly craft an order based comparison:: + When ordered dicts are compared with other Mappings, their order + insensitive comparison is used. This allows ordered dictionaries + to be substituted anywhere regular dictionaries are used. - # Explict order-sensitive comparison - >>> list(od1.items())==list(od2.items()) +How __repr__ format will maintain order during an repr/eval round-trip? + + OrderedDict([('a', 1), ('b', 2)]) What are the trade-offs of the possible underlying data structures? @@ -255,6 +256,7 @@ would keep the same big-oh performance as regular dictionaries. It is the fastest and most space efficient. + Reference Implementation ======================== From python-checkins at python.org Mon Mar 2 22:24:57 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 2 Mar 2009 22:24:57 +0100 (CET) Subject: [Python-checkins] r70101 - in python/branches/py3k: Doc/library/collections.rst Lib/collections.py Lib/test/test_collections.py Misc/NEWS Message-ID: <20090302212457.DA3D01E4043@bag.python.org> Author: raymond.hettinger Date: Mon Mar 2 22:24:57 2009 New Revision: 70101 Log: PEP 372: OrderedDict() Modified: python/branches/py3k/Doc/library/collections.rst python/branches/py3k/Lib/collections.py python/branches/py3k/Lib/test/test_collections.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Doc/library/collections.rst ============================================================================== --- python/branches/py3k/Doc/library/collections.rst (original) +++ python/branches/py3k/Doc/library/collections.rst Mon Mar 2 22:24:57 2009 @@ -14,7 +14,7 @@ __name__ = '' This module implements high-performance container datatypes. Currently, -there are three datatypes, :class:`Counter`, :class:`deque` and +there are four datatypes, :class:`Counter`, :class:`deque`, :class:`OrderedDict` and :class:`defaultdict`, and one datatype factory function, :func:`namedtuple`. The specialized containers provided in this module provide alternatives @@ -806,6 +806,33 @@ adapted for Python 2.4. +:class:`OrderedDict` objects +---------------------------- + +Ordered dictionaries are just like regular dictionaries but they remember the +order that items were inserted. When iterating over an ordered dictionary, +the items are returned in the order their keys were first added. + +.. class:: OrderedDict([items]) + + Return an instance of a dict subclass, supporting the usual :class:`dict` + methods. An *OrderedDict* is a dict that remembers the order that keys + were first inserted. If a new entry overwrites an existing entry, the + original insertion position is left unchanged. Deleting an entry and + reinserting it will move it to the end. + + .. versionadded:: 2.7 + +The :meth:`popitem` method for ordered dictionaries returns and removes the +last added entry. The key/value pairs are returned in LIFO order. + +Equality tests between :class:`OrderedDict` objects are order-sensitive +and are implemented as ``list(od1.items())==list(od2.items())``. +Equality tests between :class:`OrderedDict` objects and other +:class:`Mapping` objects are order-insensitive like regular dictionaries. +This allows :class:`OrderedDict` objects to be substituted anywhere a +regular dictionary is used. + :class:`UserDict` objects ------------------------- Modified: python/branches/py3k/Lib/collections.py ============================================================================== --- python/branches/py3k/Lib/collections.py (original) +++ python/branches/py3k/Lib/collections.py Mon Mar 2 22:24:57 2009 @@ -1,5 +1,5 @@ __all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList', - 'UserString', 'Counter'] + 'UserString', 'Counter', 'OrderedDict'] # For bootstrapping reasons, the collection ABCs are defined in _abcoll.py. # They should however be considered an integral part of collections.py. from _abcoll import * @@ -11,7 +11,81 @@ from keyword import iskeyword as _iskeyword import sys as _sys import heapq as _heapq -from itertools import repeat as _repeat, chain as _chain, starmap as _starmap +from itertools import repeat as _repeat, chain as _chain, starmap as _starmap, \ + zip_longest as _zip_longest + +################################################################################ +### OrderedDict +################################################################################ + +class OrderedDict(dict, MutableMapping): + + def __init__(self, *args, **kwds): + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + if not hasattr(self, '_keys'): + self._keys = [] + self.update(*args, **kwds) + + def clear(self): + del self._keys[:] + dict.clear(self) + + def __setitem__(self, key, value): + if key not in self: + self._keys.append(key) + dict.__setitem__(self, key, value) + + def __delitem__(self, key): + dict.__delitem__(self, key) + self._keys.remove(key) + + def __iter__(self): + return iter(self._keys) + + def __reversed__(self): + return reversed(self._keys) + + def popitem(self): + if not self: + raise KeyError('dictionary is empty') + key = self._keys.pop() + value = dict.pop(self, key) + return key, value + + def __reduce__(self): + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + inst_dict.pop('_keys', None) + return (self.__class__, (items,), inst_dict) + + setdefault = MutableMapping.setdefault + update = MutableMapping.update + pop = MutableMapping.pop + keys = MutableMapping.keys + values = MutableMapping.values + items = MutableMapping.items + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, list(self.items())) + + def copy(self): + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + if isinstance(other, OrderedDict): + return all(p==q for p, q in _zip_longest(self.items(), other.items())) + return dict.__eq__(self, other) + ################################################################################ Modified: python/branches/py3k/Lib/test/test_collections.py ============================================================================== --- python/branches/py3k/Lib/test/test_collections.py (original) +++ python/branches/py3k/Lib/test/test_collections.py Mon Mar 2 22:24:57 2009 @@ -1,10 +1,12 @@ """Unit tests for collections.py.""" import unittest, doctest +import inspect from test import support -from collections import namedtuple, Counter, Mapping +from collections import namedtuple, Counter, OrderedDict +from test import mapping_tests import pickle, copy -from random import randrange +from random import randrange, shuffle import operator from collections import Hashable, Iterable, Iterator from collections import Sized, Container, Callable @@ -571,12 +573,201 @@ set_result = setop(set(p.elements()), set(q.elements())) self.assertEqual(counter_result, dict.fromkeys(set_result, 1)) + +class TestOrderedDict(unittest.TestCase): + + def test_init(self): + with self.assertRaises(TypeError): + OrderedDict([('a', 1), ('b', 2)], None) # too many args + pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] + self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input + self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input + self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input + self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)], + c=3, e=5).items()), pairs) # mixed input + + # make sure no positional args conflict with possible kwdargs + self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args, + ['self']) + + # Make sure that direct calls to __init__ do not clear previous contents + d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)]) + d.__init__([('e', 5), ('f', 6)], g=7, d=4) + self.assertEqual(list(d.items()), + [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)]) + + def test_update(self): + with self.assertRaises(TypeError): + OrderedDict().update([('a', 1), ('b', 2)], None) # too many args + pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] + od = OrderedDict() + od.update(dict(pairs)) + self.assertEqual(sorted(od.items()), pairs) # dict input + od = OrderedDict() + od.update(**dict(pairs)) + self.assertEqual(sorted(od.items()), pairs) # kwds input + od = OrderedDict() + od.update(pairs) + self.assertEqual(list(od.items()), pairs) # pairs input + od = OrderedDict() + od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5) + self.assertEqual(list(od.items()), pairs) # mixed input + + # Make sure that direct calls to update do not clear previous contents + # add that updates items are not moved to the end + d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)]) + d.update([('e', 5), ('f', 6)], g=7, d=4) + self.assertEqual(list(d.items()), + [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)]) + + def test_clear(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + self.assertEqual(len(od), len(pairs)) + od.clear() + self.assertEqual(len(od), 0) + + def test_delitem(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + od = OrderedDict(pairs) + del od['a'] + self.assert_('a' not in od) + with self.assertRaises(KeyError): + del od['a'] + self.assertEqual(list(od.items()), pairs[:2] + pairs[3:]) + + def test_setitem(self): + od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)]) + od['c'] = 10 # existing element + od['f'] = 20 # new element + self.assertEqual(list(od.items()), + [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)]) + + def test_iterators(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + self.assertEqual(list(od), [t[0] for t in pairs]) + self.assertEqual(list(od.keys()), [t[0] for t in pairs]) + self.assertEqual(list(od.values()), [t[1] for t in pairs]) + self.assertEqual(list(od.items()), pairs) + self.assertEqual(list(reversed(od)), + [t[0] for t in reversed(pairs)]) + + def test_popitem(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + while pairs: + self.assertEqual(od.popitem(), pairs.pop()) + with self.assertRaises(KeyError): + od.popitem() + self.assertEqual(len(od), 0) + + def test_pop(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + shuffle(pairs) + while pairs: + k, v = pairs.pop() + self.assertEqual(od.pop(k), v) + with self.assertRaises(KeyError): + od.pop('xyz') + self.assertEqual(len(od), 0) + self.assertEqual(od.pop(k, 12345), 12345) + + def test_equality(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od1 = OrderedDict(pairs) + od2 = OrderedDict(pairs) + self.assertEqual(od1, od2) # same order implies equality + pairs = pairs[2:] + pairs[:2] + od2 = OrderedDict(pairs) + self.assertNotEqual(od1, od2) # different order implies inequality + # comparison to regular dict is not order sensitive + self.assertEqual(od1, dict(od2)) + self.assertEqual(dict(od2), od1) + # different length implied inequality + self.assertNotEqual(od1, OrderedDict(pairs[:-1])) + + def test_copying(self): + # Check that ordered dicts are copyable, deepcopyable, picklable, + # and have a repr/eval round-trip + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + od = OrderedDict(pairs) + update_test = OrderedDict() + update_test.update(od) + for i, dup in enumerate([ + od.copy(), + copy.copy(od), + copy.deepcopy(od), + pickle.loads(pickle.dumps(od, 0)), + pickle.loads(pickle.dumps(od, 1)), + pickle.loads(pickle.dumps(od, 2)), + pickle.loads(pickle.dumps(od, 3)), + pickle.loads(pickle.dumps(od, -1)), + eval(repr(od)), + update_test, + OrderedDict(od), + ]): + self.assert_(dup is not od) + self.assertEquals(dup, od) + self.assertEquals(list(dup.items()), list(od.items())) + self.assertEquals(len(dup), len(od)) + self.assertEquals(type(dup), type(od)) + + def test_repr(self): + od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]) + self.assertEqual(repr(od), + "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])") + self.assertEqual(eval(repr(od)), od) + self.assertEqual(repr(OrderedDict()), "OrderedDict()") + + def test_setdefault(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + pair_order = list(od.items()) + self.assertEqual(od.setdefault('a', 10), 3) + # make sure order didn't change + self.assertEqual(list(od.items()), pair_order) + self.assertEqual(od.setdefault('x', 10), 10) + # make sure 'x' is added to the end + self.assertEqual(list(od.items())[-1], ('x', 10)) + + def test_reinsert(self): + # Given insert a, insert b, delete a, re-insert a, + # verify that a is now later than b. + od = OrderedDict() + od['a'] = 1 + od['b'] = 2 + del od['a'] + od['a'] = 1 + self.assertEqual(list(od.items()), [('b', 2), ('a', 1)]) + + + +class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol): + type2test = OrderedDict + +class MyOrderedDict(OrderedDict): + pass + +class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol): + type2test = MyOrderedDict + + + import doctest, collections def test_main(verbose=None): NamedTupleDocs = doctest.DocTestSuite(module=collections) test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs, - TestCollectionABCs, TestCounter] + TestCollectionABCs, TestCounter, + TestOrderedDict, GeneralMappingTests, SubclassMappingTests] support.run_unittest(*test_classes) support.run_doctest(collections, verbose) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Mon Mar 2 22:24:57 2009 @@ -175,6 +175,8 @@ Library ------- +- PEP 372: Added collections.OrderedDict(). + - Issue #1733986: Fixed mmap crash in accessing elements of second map object with same tagname but larger size than first map. (Windows) From benjamin at python.org Mon Mar 2 22:28:17 2009 From: benjamin at python.org (Benjamin Peterson) Date: Mon, 2 Mar 2009 15:28:17 -0600 Subject: [Python-checkins] r70101 - in python/branches/py3k: Doc/library/collections.rst Lib/collections.py Lib/test/test_collections.py Misc/NEWS In-Reply-To: <20090302212457.DA3D01E4043@bag.python.org> References: <20090302212457.DA3D01E4043@bag.python.org> Message-ID: <1afaf6160903021328r6491b5a7u1954c13325a8efa4@mail.gmail.com> 2009/3/2 raymond. hettinger : > Author: raymond.hettinger > Date: Mon Mar ?2 22:24:57 2009 > New Revision: 70101 > > Log: > PEP 372: OrderedDict() > + ? .. versionadded:: 2.7 This should be 3.1. -- Regards, Benjamin From python-checkins at python.org Mon Mar 2 22:28:41 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 2 Mar 2009 22:28:41 +0100 (CET) Subject: [Python-checkins] r70102 - python/branches/py3k/Lib/collections.py Message-ID: <20090302212841.791751E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 2 22:28:41 2009 New Revision: 70102 Log: Missed my last update to __eq__ to check matching length. Modified: python/branches/py3k/Lib/collections.py Modified: python/branches/py3k/Lib/collections.py ============================================================================== --- python/branches/py3k/Lib/collections.py (original) +++ python/branches/py3k/Lib/collections.py Mon Mar 2 22:28:41 2009 @@ -11,8 +11,7 @@ from keyword import iskeyword as _iskeyword import sys as _sys import heapq as _heapq -from itertools import repeat as _repeat, chain as _chain, starmap as _starmap, \ - zip_longest as _zip_longest +from itertools import repeat as _repeat, chain as _chain, starmap as _starmap ################################################################################ ### OrderedDict @@ -83,7 +82,7 @@ def __eq__(self, other): if isinstance(other, OrderedDict): - return all(p==q for p, q in _zip_longest(self.items(), other.items())) + return len(self)==len(other) and all(p==q for p, q in zip(self.items(), other.items())) return dict.__eq__(self, other) From python-checkins at python.org Mon Mar 2 22:32:06 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 2 Mar 2009 22:32:06 +0100 (CET) Subject: [Python-checkins] r70103 - peps/trunk/pep-0372.txt Message-ID: <20090302213206.C7C211E4045@bag.python.org> Author: raymond.hettinger Date: Mon Mar 2 22:32:04 2009 New Revision: 70103 Log: Mark PEP372 as final. Modified: peps/trunk/pep-0372.txt Modified: peps/trunk/pep-0372.txt ============================================================================== --- peps/trunk/pep-0372.txt (original) +++ peps/trunk/pep-0372.txt Mon Mar 2 22:32:04 2009 @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: Armin Ronacher Raymond Hettinger -Status: Accepted +Status: Final Type: Standards Track Content-Type: text/x-rst Created: 15-Jun-2008 @@ -29,6 +29,8 @@ `OrderedDict patch `_ +The check-in was in revisions: 70101 and 70102 + Rationale ========= From python-checkins at python.org Mon Mar 2 22:44:55 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 2 Mar 2009 22:44:55 +0100 (CET) Subject: [Python-checkins] r70104 - python/branches/py3k/Doc/library/collections.rst Message-ID: <20090302214455.069CF1E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 2 22:44:54 2009 New Revision: 70104 Log: fix versionadded Modified: python/branches/py3k/Doc/library/collections.rst Modified: python/branches/py3k/Doc/library/collections.rst ============================================================================== --- python/branches/py3k/Doc/library/collections.rst (original) +++ python/branches/py3k/Doc/library/collections.rst Mon Mar 2 22:44:54 2009 @@ -184,7 +184,7 @@ >>> c['sausage'] = 0 # counter entry with a zero count >>> del c['sausage'] # del actually removes the entry - .. versionadded:: 2.7 + .. versionadded:: 3.1 Counter objects support two methods beyond those available for all @@ -821,7 +821,7 @@ original insertion position is left unchanged. Deleting an entry and reinserting it will move it to the end. - .. versionadded:: 2.7 + .. versionadded:: 3.1 The :meth:`popitem` method for ordered dictionaries returns and removes the last added entry. The key/value pairs are returned in LIFO order. From python-checkins at python.org Mon Mar 2 23:16:43 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 2 Mar 2009 23:16:43 +0100 (CET) Subject: [Python-checkins] r70105 - python/branches/py3k/Doc/library/collections.rst Message-ID: <20090302221643.B3F201E406A@bag.python.org> Author: raymond.hettinger Date: Mon Mar 2 23:16:43 2009 New Revision: 70105 Log: Fix versionchanged. Modified: python/branches/py3k/Doc/library/collections.rst Modified: python/branches/py3k/Doc/library/collections.rst ============================================================================== --- python/branches/py3k/Doc/library/collections.rst (original) +++ python/branches/py3k/Doc/library/collections.rst Mon Mar 2 23:16:43 2009 @@ -621,7 +621,7 @@ Named tuple instances do not have per-instance dictionaries, so they are lightweight and require no more memory than regular tuples. - .. versionchanged:: 2.7 + .. versionchanged:: 3.1 added support for *rename*. Example: From python-checkins at python.org Mon Mar 2 23:28:32 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 2 Mar 2009 23:28:32 +0100 (CET) Subject: [Python-checkins] r70106 - in python/branches/py3k: Doc/library/collections.rst Lib/collections.py Misc/NEWS Message-ID: <20090302222832.144211E400C@bag.python.org> Author: raymond.hettinger Date: Mon Mar 2 23:28:31 2009 New Revision: 70106 Log: Add OrderedDict support to collections.namedtuple(). Modified: python/branches/py3k/Doc/library/collections.rst python/branches/py3k/Lib/collections.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Doc/library/collections.rst ============================================================================== --- python/branches/py3k/Doc/library/collections.rst (original) +++ python/branches/py3k/Doc/library/collections.rst Mon Mar 2 23:28:31 2009 @@ -651,9 +651,9 @@ def __repr__(self): return 'Point(x=%r, y=%r)' % self - def _asdict(t): - 'Return a new dict which maps field names to their values' - return {'x': t[0], 'y': t[1]} + def _asdict(self): + 'Return a new OrderedDict which maps field names to their values' + return OrderedDict(zip(self._fields, self)) def _replace(self, **kwds): 'Return a new Point object replacing specified fields with new values' @@ -711,10 +711,14 @@ .. method:: somenamedtuple._asdict() - Return a new dict which maps field names to their corresponding values:: + Return a new :class:`OrderedDict` which maps field names to their corresponding + values:: >>> p._asdict() - {'x': 11, 'y': 22} + OrderedDict([('x', 11), ('y', 22)]) + + .. versionchanged 3.1 + Returns an :class:`OrderedDict` instead of a regular :class:`dict`. .. method:: somenamedtuple._replace(kwargs) Modified: python/branches/py3k/Lib/collections.py ============================================================================== --- python/branches/py3k/Lib/collections.py (original) +++ python/branches/py3k/Lib/collections.py Mon Mar 2 23:28:31 2009 @@ -149,7 +149,6 @@ numfields = len(field_names) argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes reprtxt = ', '.join('%s=%%r' % name for name in field_names) - dicttxt = ', '.join('%r: t[%d]' % (name, pos) for pos, name in enumerate(field_names)) template = '''class %(typename)s(tuple): '%(typename)s(%(argtxt)s)' \n __slots__ = () \n @@ -165,9 +164,9 @@ return result \n def __repr__(self): return '%(typename)s(%(reprtxt)s)' %% self \n - def _asdict(t): - 'Return a new dict which maps field names to their values' - return {%(dicttxt)s} \n + def _asdict(self): + 'Return a new OrderedDict which maps field names to their values' + return OrderedDict(zip(self._fields, self)) \n def _replace(self, **kwds): 'Return a new %(typename)s object replacing specified fields with new values' result = self._make(map(kwds.pop, %(field_names)r, self)) @@ -183,7 +182,8 @@ # Execute the template string in a temporary namespace and # support tracing utilities by setting a value for frame.f_globals['__name__'] - namespace = dict(itemgetter=_itemgetter, __name__='namedtuple_%s' % typename) + namespace = dict(itemgetter=_itemgetter, __name__='namedtuple_%s' % typename, + OrderedDict=OrderedDict) try: exec(template, namespace) except SyntaxError as e: Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Mon Mar 2 23:28:31 2009 @@ -177,6 +177,8 @@ - PEP 372: Added collections.OrderedDict(). +- The _asdict() for method for namedtuples now returns an OrderedDict(). + - Issue #1733986: Fixed mmap crash in accessing elements of second map object with same tagname but larger size than first map. (Windows) From buildbot at python.org Mon Mar 2 23:38:31 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 02 Mar 2009 22:38:31 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090302223832.977C01E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/366 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_posix test_subprocess ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_subprocess.py", line 149, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 2 23:41:42 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 2 Mar 2009 23:41:42 +0100 (CET) Subject: [Python-checkins] r70107 - in python/trunk: Lib/httplib.py Lib/test/test_httplib.py Misc/ACKS Misc/NEWS Message-ID: <20090302224142.BBB221E400C@bag.python.org> Author: benjamin.peterson Date: Mon Mar 2 23:41:42 2009 New Revision: 70107 Log: give httplib.IncompleteRead a more sane repr #4308 Modified: python/trunk/Lib/httplib.py python/trunk/Lib/test/test_httplib.py python/trunk/Misc/ACKS python/trunk/Misc/NEWS Modified: python/trunk/Lib/httplib.py ============================================================================== --- python/trunk/Lib/httplib.py (original) +++ python/trunk/Lib/httplib.py Mon Mar 2 23:41:42 2009 @@ -626,7 +626,7 @@ while amt > 0: chunk = self.fp.read(min(amt, MAXAMOUNT)) if not chunk: - raise IncompleteRead(s) + raise IncompleteRead(''.join(s), amt) s.append(chunk) amt -= len(chunk) return ''.join(s) @@ -1161,9 +1161,18 @@ pass class IncompleteRead(HTTPException): - def __init__(self, partial): + def __init__(self, partial, expected=None): self.args = partial, self.partial = partial + self.expected = expected + def __repr__(self): + if self.expected is not None: + e = ', %i more expected' % self.expected + else: + e = '' + return 'IncompleteRead(%i bytes read%s)' % (len(self.partial), e) + def __str__(self): + return repr(self) class ImproperConnectionState(HTTPException): pass Modified: python/trunk/Lib/test/test_httplib.py ============================================================================== --- python/trunk/Lib/test/test_httplib.py (original) +++ python/trunk/Lib/test/test_httplib.py Mon Mar 2 23:41:42 2009 @@ -185,6 +185,8 @@ resp.read() except httplib.IncompleteRead, i: self.assertEquals(i.partial, 'hello world') + self.assertEqual(repr(i),'IncompleteRead(11 bytes read)') + self.assertEqual(str(i),'IncompleteRead(11 bytes read)') else: self.fail('IncompleteRead expected') finally: @@ -198,6 +200,23 @@ self.assertEquals(resp.read(), 'Hello\r\n') resp.close() + def test_incomplete_read(self): + sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n') + resp = httplib.HTTPResponse(sock, method="GET") + resp.begin() + try: + resp.read() + except httplib.IncompleteRead as i: + self.assertEquals(i.partial, 'Hello\r\n') + self.assertEqual(repr(i), + "IncompleteRead(7 bytes read, 3 more expected)") + self.assertEqual(str(i), + "IncompleteRead(7 bytes read, 3 more expected)") + else: + self.fail('IncompleteRead expected') + finally: + resp.close() + class OfflineTest(TestCase): def test_responses(self): Modified: python/trunk/Misc/ACKS ============================================================================== --- python/trunk/Misc/ACKS (original) +++ python/trunk/Misc/ACKS Mon Mar 2 23:41:42 2009 @@ -765,6 +765,7 @@ Blake Winton Jean-Claude Wippler Lars Wirzenius +Chris Withers Stefan Witzel David Wolever Klaus-Juergen Wolf Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Mon Mar 2 23:41:42 2009 @@ -168,6 +168,9 @@ Library ------- +- Issue #4308: httplib.IncompleteRead's repr doesn't include all of the data all + ready received. + - Issue #5401: Fixed a performance problem in mimetypes when ``from mimetypes import guess_extension`` was used. From python-checkins at python.org Mon Mar 2 23:46:12 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 2 Mar 2009 23:46:12 +0100 (CET) Subject: [Python-checkins] r70108 - in python/branches/release26-maint: Lib/httplib.py Lib/test/test_httplib.py Misc/ACKS Misc/NEWS Message-ID: <20090302224612.278391E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 2 23:46:11 2009 New Revision: 70108 Log: Merged revisions 70107 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70107 | benjamin.peterson | 2009-03-02 16:41:42 -0600 (Mon, 02 Mar 2009) | 1 line give httplib.IncompleteRead a more sane repr #4308 ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/httplib.py python/branches/release26-maint/Lib/test/test_httplib.py python/branches/release26-maint/Misc/ACKS python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/httplib.py ============================================================================== --- python/branches/release26-maint/Lib/httplib.py (original) +++ python/branches/release26-maint/Lib/httplib.py Mon Mar 2 23:46:11 2009 @@ -616,7 +616,7 @@ while amt > 0: chunk = self.fp.read(min(amt, MAXAMOUNT)) if not chunk: - raise IncompleteRead(s) + raise IncompleteRead(''.join(s), amt) s.append(chunk) amt -= len(chunk) return ''.join(s) @@ -1130,9 +1130,18 @@ pass class IncompleteRead(HTTPException): - def __init__(self, partial): + def __init__(self, partial, expected=None): self.args = partial, self.partial = partial + self.expected = expected + def __repr__(self): + if self.expected is not None: + e = ', %i more expected' % self.expected + else: + e = '' + return 'IncompleteRead(%i bytes read%s)' % (len(self.partial), e) + def __str__(self): + return repr(self) class ImproperConnectionState(HTTPException): pass Modified: python/branches/release26-maint/Lib/test/test_httplib.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_httplib.py (original) +++ python/branches/release26-maint/Lib/test/test_httplib.py Mon Mar 2 23:46:11 2009 @@ -185,6 +185,8 @@ resp.read() except httplib.IncompleteRead, i: self.assertEquals(i.partial, 'hello world') + self.assertEqual(repr(i),'IncompleteRead(11 bytes read)') + self.assertEqual(str(i),'IncompleteRead(11 bytes read)') else: self.fail('IncompleteRead expected') finally: @@ -198,6 +200,23 @@ self.assertEquals(resp.read(), 'Hello\r\n') resp.close() + def test_incomplete_read(self): + sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n') + resp = httplib.HTTPResponse(sock, method="GET") + resp.begin() + try: + resp.read() + except httplib.IncompleteRead as i: + self.assertEquals(i.partial, 'Hello\r\n') + self.assertEqual(repr(i), + "IncompleteRead(7 bytes read, 3 more expected)") + self.assertEqual(str(i), + "IncompleteRead(7 bytes read, 3 more expected)") + else: + self.fail('IncompleteRead expected') + finally: + resp.close() + class OfflineTest(TestCase): def test_responses(self): Modified: python/branches/release26-maint/Misc/ACKS ============================================================================== --- python/branches/release26-maint/Misc/ACKS (original) +++ python/branches/release26-maint/Misc/ACKS Mon Mar 2 23:46:11 2009 @@ -753,6 +753,7 @@ Blake Winton Jean-Claude Wippler Lars Wirzenius +Chris Withers Stefan Witzel David Wolever Klaus-Juergen Wolf Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Mon Mar 2 23:46:11 2009 @@ -89,6 +89,9 @@ Library ------- +- Issue #4308: httplib.IncompleteRead's repr doesn't include all of the data all + ready received. + - Issue #5401: Fixed a performance problem in mimetypes when ``from mimetypes import guess_extension`` was used. From python-checkins at python.org Mon Mar 2 23:50:25 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 2 Mar 2009 23:50:25 +0100 (CET) Subject: [Python-checkins] r70109 - in python/branches/py3k: Lib/http/client.py Lib/test/test_httplib.py Misc/ACKS Message-ID: <20090302225025.C6B8D1E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 2 23:50:25 2009 New Revision: 70109 Log: Merged revisions 70107 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70107 | benjamin.peterson | 2009-03-02 16:41:42 -0600 (Mon, 02 Mar 2009) | 1 line give httplib.IncompleteRead a more sane repr #4308 ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/http/client.py python/branches/py3k/Lib/test/test_httplib.py python/branches/py3k/Misc/ACKS Modified: python/branches/py3k/Lib/http/client.py ============================================================================== --- python/branches/py3k/Lib/http/client.py (original) +++ python/branches/py3k/Lib/http/client.py Mon Mar 2 23:50:25 2009 @@ -578,7 +578,7 @@ while amt > 0: chunk = self.fp.read(min(amt, MAXAMOUNT)) if not chunk: - raise IncompleteRead(s) + raise IncompleteRead(b''.join(s), amt) s.append(chunk) amt -= len(chunk) return b"".join(s) @@ -1009,9 +1009,18 @@ pass class IncompleteRead(HTTPException): - def __init__(self, partial): + def __init__(self, partial, expected=None): self.args = partial, self.partial = partial + self.expected = expected + def __repr__(self): + if self.expected is not None: + e = ', %i more expected' % self.expected + else: + e = '' + return 'IncompleteRead(%i bytes read%s)' % (len(self.partial), e) + def __str__(self): + return repr(self) class ImproperConnectionState(HTTPException): pass Modified: python/branches/py3k/Lib/test/test_httplib.py ============================================================================== --- python/branches/py3k/Lib/test/test_httplib.py (original) +++ python/branches/py3k/Lib/test/test_httplib.py Mon Mar 2 23:50:25 2009 @@ -181,6 +181,8 @@ resp.read() except httplib.IncompleteRead as i: self.assertEquals(i.partial, b'hello world') + self.assertEqual(repr(i),'IncompleteRead(11 bytes read)') + self.assertEqual(str(i),'IncompleteRead(11 bytes read)') else: self.fail('IncompleteRead expected') finally: @@ -194,6 +196,23 @@ self.assertEquals(resp.read(), b'Hello\r\n') resp.close() + def test_incomplete_read(self): + sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n') + resp = httplib.HTTPResponse(sock, method="GET") + resp.begin() + try: + resp.read() + except httplib.IncompleteRead as i: + self.assertEquals(i.partial, b'Hello\r\n') + self.assertEqual(repr(i), + "IncompleteRead(7 bytes read, 3 more expected)") + self.assertEqual(str(i), + "IncompleteRead(7 bytes read, 3 more expected)") + else: + self.fail('IncompleteRead expected') + finally: + resp.close() + class OfflineTest(TestCase): def test_responses(self): Modified: python/branches/py3k/Misc/ACKS ============================================================================== --- python/branches/py3k/Misc/ACKS (original) +++ python/branches/py3k/Misc/ACKS Mon Mar 2 23:50:25 2009 @@ -767,6 +767,7 @@ Blake Winton Jean-Claude Wippler Lars Wirzenius +Chris Withers Stefan Witzel David Wolever Klaus-Juergen Wolf From python-checkins at python.org Mon Mar 2 23:52:59 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 2 Mar 2009 23:52:59 +0100 (CET) Subject: [Python-checkins] r70110 - in python/branches/release30-maint: Lib/http/client.py Lib/test/test_httplib.py Misc/ACKS Message-ID: <20090302225259.03E151E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 2 23:52:58 2009 New Revision: 70110 Log: Merged revisions 70109 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70109 | benjamin.peterson | 2009-03-02 16:50:25 -0600 (Mon, 02 Mar 2009) | 9 lines Merged revisions 70107 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70107 | benjamin.peterson | 2009-03-02 16:41:42 -0600 (Mon, 02 Mar 2009) | 1 line give httplib.IncompleteRead a more sane repr #4308 ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/http/client.py python/branches/release30-maint/Lib/test/test_httplib.py python/branches/release30-maint/Misc/ACKS Modified: python/branches/release30-maint/Lib/http/client.py ============================================================================== --- python/branches/release30-maint/Lib/http/client.py (original) +++ python/branches/release30-maint/Lib/http/client.py Mon Mar 2 23:52:58 2009 @@ -578,7 +578,7 @@ while amt > 0: chunk = self.fp.read(min(amt, MAXAMOUNT)) if not chunk: - raise IncompleteRead(s) + raise IncompleteRead(b''.join(s), amt) s.append(chunk) amt -= len(chunk) return b"".join(s) @@ -1008,9 +1008,18 @@ pass class IncompleteRead(HTTPException): - def __init__(self, partial): + def __init__(self, partial, expected=None): self.args = partial, self.partial = partial + self.expected = expected + def __repr__(self): + if self.expected is not None: + e = ', %i more expected' % self.expected + else: + e = '' + return 'IncompleteRead(%i bytes read%s)' % (len(self.partial), e) + def __str__(self): + return repr(self) class ImproperConnectionState(HTTPException): pass Modified: python/branches/release30-maint/Lib/test/test_httplib.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_httplib.py (original) +++ python/branches/release30-maint/Lib/test/test_httplib.py Mon Mar 2 23:52:58 2009 @@ -181,6 +181,8 @@ resp.read() except httplib.IncompleteRead as i: self.assertEquals(i.partial, b'hello world') + self.assertEqual(repr(i),'IncompleteRead(11 bytes read)') + self.assertEqual(str(i),'IncompleteRead(11 bytes read)') else: self.fail('IncompleteRead expected') finally: @@ -194,6 +196,23 @@ self.assertEquals(resp.read(), b'Hello\r\n') resp.close() + def test_incomplete_read(self): + sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n') + resp = httplib.HTTPResponse(sock, method="GET") + resp.begin() + try: + resp.read() + except httplib.IncompleteRead as i: + self.assertEquals(i.partial, b'Hello\r\n') + self.assertEqual(repr(i), + "IncompleteRead(7 bytes read, 3 more expected)") + self.assertEqual(str(i), + "IncompleteRead(7 bytes read, 3 more expected)") + else: + self.fail('IncompleteRead expected') + finally: + resp.close() + class OfflineTest(TestCase): def test_responses(self): Modified: python/branches/release30-maint/Misc/ACKS ============================================================================== --- python/branches/release30-maint/Misc/ACKS (original) +++ python/branches/release30-maint/Misc/ACKS Mon Mar 2 23:52:58 2009 @@ -755,6 +755,7 @@ Blake Winton Jean-Claude Wippler Lars Wirzenius +Chris Withers Stefan Witzel David Wolever Klaus-Juergen Wolf From python-checkins at python.org Tue Mar 3 00:06:11 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 00:06:11 +0100 (CET) Subject: [Python-checkins] r70111 - in python/branches/py3k: Doc/library/configparser.rst Lib/configparser.py Misc/NEWS Message-ID: <20090302230611.CAD511E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 00:06:00 2009 New Revision: 70111 Log: Let configparser use ordered dicts by default. Modified: python/branches/py3k/Doc/library/configparser.rst python/branches/py3k/Lib/configparser.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Doc/library/configparser.rst ============================================================================== --- python/branches/py3k/Doc/library/configparser.rst (original) +++ python/branches/py3k/Doc/library/configparser.rst Tue Mar 3 00:06:00 2009 @@ -64,6 +64,9 @@ options within a section, and for the default values. This class does not support the magical interpolation behavior. + .. versionchanged 3.1 + The default *dict_type* is :class:`collections.OrderedDict`. + .. class:: ConfigParser([defaults[, dict_type]]) @@ -80,6 +83,9 @@ option names to lower case), the values ``foo %(bar)s`` and ``foo %(BAR)s`` are equivalent. + .. versionchanged 3.1 + The default *dict_type* is :class:`collections.OrderedDict`. + .. class:: SafeConfigParser([defaults[, dict_type]]) @@ -90,6 +96,9 @@ .. XXX Need to explain what's safer/more predictable about it. + .. versionchanged 3.1 + The default *dict_type* is :class:`collections.OrderedDict`. + .. exception:: NoSectionError Modified: python/branches/py3k/Lib/configparser.py ============================================================================== --- python/branches/py3k/Lib/configparser.py (original) +++ python/branches/py3k/Lib/configparser.py Tue Mar 3 00:06:00 2009 @@ -88,6 +88,7 @@ """ import re +from collections import OrderedDict __all__ = ["NoSectionError", "DuplicateSectionError", "NoOptionError", "InterpolationError", "InterpolationDepthError", @@ -215,7 +216,7 @@ class RawConfigParser: - def __init__(self, defaults=None, dict_type=dict): + def __init__(self, defaults=None, dict_type=OrderedDict): self._dict = dict_type self._sections = self._dict() self._defaults = self._dict() Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 3 00:06:00 2009 @@ -179,6 +179,8 @@ - The _asdict() for method for namedtuples now returns an OrderedDict(). +- configparser now defaults to using an ordered dictionary. + - Issue #1733986: Fixed mmap crash in accessing elements of second map object with same tagname but larger size than first map. (Windows) From python-checkins at python.org Tue Mar 3 00:11:56 2009 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 3 Mar 2009 00:11:56 +0100 (CET) Subject: [Python-checkins] r70112 - python/branches/io-c/PC/config.c Message-ID: <20090302231156.163EC1E404A@bag.python.org> Author: antoine.pitrou Date: Tue Mar 3 00:11:55 2009 New Revision: 70112 Log: Looks like this is necessary in order to build cleanly under Windows (someone correct this if it's wrong, I'm no Windows user) Modified: python/branches/io-c/PC/config.c Modified: python/branches/io-c/PC/config.c ============================================================================== --- python/branches/io-c/PC/config.c (original) +++ python/branches/io-c/PC/config.c Tue Mar 3 00:11:55 2009 @@ -59,7 +59,6 @@ extern PyObject* PyInit__lsprof(void); extern PyObject* PyInit__ast(void); extern PyObject* PyInit__io(void); -extern PyObject* PyInit__stringio(void); extern PyObject* PyInit__pickle(void); extern PyObject* PyInit_atexit(void); extern PyObject* _PyWarnings_Init(void); @@ -150,7 +149,6 @@ {"_warnings", _PyWarnings_Init}, {"_io", PyInit__io}, - {"_stringio", PyInit__stringio}, {"_pickle", PyInit__pickle}, {"atexit", PyInit_atexit}, From python-checkins at python.org Tue Mar 3 00:31:26 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 3 Mar 2009 00:31:26 +0100 (CET) Subject: [Python-checkins] r70113 - in python/branches/py3k: Include/parsetok.h Include/pythonrun.h Lib/test/test_coding.py Lib/test/test_pep263.py Misc/NEWS Parser/parsetok.c Parser/tokenizer.c Parser/tokenizer.h Python/bltinmodule.c Python/pythonrun.c Message-ID: <20090302233126.7953A1E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 3 00:31:26 2009 New Revision: 70113 Log: ignore the coding cookie in compile(), exec(), and eval() if the source is a string #4626 Modified: python/branches/py3k/Include/parsetok.h python/branches/py3k/Include/pythonrun.h python/branches/py3k/Lib/test/test_coding.py python/branches/py3k/Lib/test/test_pep263.py python/branches/py3k/Misc/NEWS python/branches/py3k/Parser/parsetok.c python/branches/py3k/Parser/tokenizer.c python/branches/py3k/Parser/tokenizer.h python/branches/py3k/Python/bltinmodule.c python/branches/py3k/Python/pythonrun.c Modified: python/branches/py3k/Include/parsetok.h ============================================================================== --- python/branches/py3k/Include/parsetok.h (original) +++ python/branches/py3k/Include/parsetok.h Tue Mar 3 00:31:26 2009 @@ -29,6 +29,8 @@ #define PyPARSE_UNICODE_LITERALS 0x0008 #endif +#define PyPARSE_IGNORE_COOKIE 0x0010 + PyAPI_FUNC(node *) PyParser_ParseString(const char *, grammar *, int, perrdetail *); PyAPI_FUNC(node *) PyParser_ParseFile (FILE *, const char *, grammar *, int, Modified: python/branches/py3k/Include/pythonrun.h ============================================================================== --- python/branches/py3k/Include/pythonrun.h (original) +++ python/branches/py3k/Include/pythonrun.h Tue Mar 3 00:31:26 2009 @@ -12,6 +12,7 @@ #define PyCF_SOURCE_IS_UTF8 0x0100 #define PyCF_DONT_IMPLY_DEDENT 0x0200 #define PyCF_ONLY_AST 0x0400 +#define PyCF_IGNORE_COOKIE 0x0800 typedef struct { int cf_flags; /* bitmask of CO_xxx flags relevant to future */ Modified: python/branches/py3k/Lib/test/test_coding.py ============================================================================== --- python/branches/py3k/Lib/test/test_coding.py (original) +++ python/branches/py3k/Lib/test/test_coding.py Tue Mar 3 00:31:26 2009 @@ -17,10 +17,10 @@ path = os.path.dirname(__file__) filename = os.path.join(path, module_name + '.py') - fp = open(filename, encoding='utf-8') - text = fp.read() + fp = open(filename, "rb") + bytes = fp.read() fp.close() - self.assertRaises(SyntaxError, compile, text, filename, 'exec') + self.assertRaises(SyntaxError, compile, bytes, filename, 'exec') def test_exec_valid_coding(self): d = {} Modified: python/branches/py3k/Lib/test/test_pep263.py ============================================================================== --- python/branches/py3k/Lib/test/test_pep263.py (original) +++ python/branches/py3k/Lib/test/test_pep263.py Tue Mar 3 00:31:26 2009 @@ -30,6 +30,12 @@ else: self.fail() + def test_issue4626(self): + c = compile("# coding=latin-1\n\u00c6 = '\u00c6'", "dummy", "exec") + d = {} + exec(c, d) + self.assertEquals(d['\xc6'], '\xc6') + def test_main(): support.run_unittest(PEP263Test) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 3 00:31:26 2009 @@ -19,6 +19,9 @@ - Issue #5249: time.strftime returned malformed string when format string contained non ascii character on windows. +- Issue #4626: compile(), exec(), and eval() ignore the coding cookie if the + source has already been decoded into str. + - Issue #5186: Reduce hash collisions for objects with no __hash__ method by rotating the object pointer by 4 bits to the right. Modified: python/branches/py3k/Parser/parsetok.c ============================================================================== --- python/branches/py3k/Parser/parsetok.c (original) +++ python/branches/py3k/Parser/parsetok.c Tue Mar 3 00:31:26 2009 @@ -49,7 +49,11 @@ initerr(err_ret, filename); - if ((tok = PyTokenizer_FromString(s)) == NULL) { + if (*flags & PyPARSE_IGNORE_COOKIE) + tok = PyTokenizer_FromUTF8(s); + else + tok = PyTokenizer_FromString(s); + if (tok == NULL) { err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM; return NULL; } Modified: python/branches/py3k/Parser/tokenizer.c ============================================================================== --- python/branches/py3k/Parser/tokenizer.c (original) +++ python/branches/py3k/Parser/tokenizer.c Tue Mar 3 00:31:26 2009 @@ -715,6 +715,28 @@ return tok; } +struct tok_state * +PyTokenizer_FromUTF8(const char *str) +{ + struct tok_state *tok = tok_new(); + if (tok == NULL) + return NULL; + tok->decoding_state = STATE_RAW; + tok->read_coding_spec = 1; + tok->enc = NULL; + tok->str = str; + tok->encoding = (char *)PyMem_MALLOC(6); + if (!tok->encoding) { + PyTokenizer_Free(tok); + return NULL; + } + strcpy(tok->encoding, "utf-8"); + + /* XXX: constify members. */ + tok->buf = tok->cur = tok->end = tok->inp = (char*)str; + return tok; +} + /* Set up tokenizer for file */ Modified: python/branches/py3k/Parser/tokenizer.h ============================================================================== --- python/branches/py3k/Parser/tokenizer.h (original) +++ python/branches/py3k/Parser/tokenizer.h Tue Mar 3 00:31:26 2009 @@ -61,6 +61,7 @@ }; extern struct tok_state *PyTokenizer_FromString(const char *); +extern struct tok_state *PyTokenizer_FromUTF8(const char *); extern struct tok_state *PyTokenizer_FromFile(FILE *, char*, char *, char *); extern void PyTokenizer_Free(struct tok_state *); Modified: python/branches/py3k/Python/bltinmodule.c ============================================================================== --- python/branches/py3k/Python/bltinmodule.c (original) +++ python/branches/py3k/Python/bltinmodule.c Tue Mar 3 00:31:26 2009 @@ -494,12 +494,13 @@ static char * -source_as_string(PyObject *cmd, char *funcname, char *what) +source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf) { char *str; Py_ssize_t size; if (PyUnicode_Check(cmd)) { + cf->cf_flags |= PyCF_IGNORE_COOKIE; cmd = _PyUnicode_AsDefaultEncodedString(cmd, NULL); if (cmd == NULL) return NULL; @@ -591,7 +592,7 @@ return result; } - str = source_as_string(cmd, "compile", "string, bytes, AST or code"); + str = source_as_string(cmd, "compile", "string, bytes, AST or code", &cf); if (str == NULL) return NULL; @@ -703,14 +704,14 @@ return PyEval_EvalCode((PyCodeObject *) cmd, globals, locals); } - str = source_as_string(cmd, "eval", "string, bytes or code"); + cf.cf_flags = PyCF_SOURCE_IS_UTF8; + str = source_as_string(cmd, "eval", "string, bytes or code", &cf); if (str == NULL) return NULL; while (*str == ' ' || *str == '\t') str++; - cf.cf_flags = PyCF_SOURCE_IS_UTF8; (void)PyEval_MergeCompilerFlags(&cf); result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf); Py_XDECREF(tmp); @@ -779,12 +780,13 @@ v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals); } else { - char *str = source_as_string(prog, "exec", - "string, bytes or code"); + char *str; PyCompilerFlags cf; + cf.cf_flags = PyCF_SOURCE_IS_UTF8; + str = source_as_string(prog, "exec", + "string, bytes or code", &cf); if (str == NULL) return NULL; - cf.cf_flags = PyCF_SOURCE_IS_UTF8; if (PyEval_MergeCompilerFlags(&cf)) v = PyRun_StringFlags(str, Py_file_input, globals, locals, &cf); Modified: python/branches/py3k/Python/pythonrun.c ============================================================================== --- python/branches/py3k/Python/pythonrun.c (original) +++ python/branches/py3k/Python/pythonrun.c Tue Mar 3 00:31:26 2009 @@ -1002,9 +1002,17 @@ } /* compute parser flags based on compiler flags */ -#define PARSER_FLAGS(flags) \ - ((flags) ? ((((flags)->cf_flags & PyCF_DONT_IMPLY_DEDENT) ? \ - PyPARSE_DONT_IMPLY_DEDENT : 0)) : 0) +static int PARSER_FLAGS(PyCompilerFlags *flags) +{ + int parser_flags = 0; + if (!flags) + return 0; + if (flags->cf_flags & PyCF_DONT_IMPLY_DEDENT) + parser_flags |= PyPARSE_DONT_IMPLY_DEDENT; + if (flags->cf_flags & PyCF_IGNORE_COOKIE) + parser_flags |= PyPARSE_IGNORE_COOKIE; + return parser_flags; +} #if 0 /* Keep an example of flags with future keyword support. */ From python-checkins at python.org Tue Mar 3 00:52:57 2009 From: python-checkins at python.org (amaury.forgeotdarc) Date: Tue, 3 Mar 2009 00:52:57 +0100 (CET) Subject: [Python-checkins] r70114 - python/branches/py3k/Modules/timemodule.c Message-ID: <20090302235257.563D81E4002@bag.python.org> Author: amaury.forgeotdarc Date: Tue Mar 3 00:52:57 2009 New Revision: 70114 Log: re-merge r69268 (issue4804) from trunk: Now that the C runtime assertions are not silenced any more, we must provide checks for the format string of strftime Modified: python/branches/py3k/Modules/timemodule.c Modified: python/branches/py3k/Modules/timemodule.c ============================================================================== --- python/branches/py3k/Modules/timemodule.c (original) +++ python/branches/py3k/Modules/timemodule.c Tue Mar 3 00:52:57 2009 @@ -513,6 +513,24 @@ if (format == NULL) return NULL; fmt = PyBytes_AS_STRING(format); + +#ifdef MS_WINDOWS + /* check that the format string contains only valid directives */ + for(outbuf = strchr(fmt, '%'); + outbuf != NULL; + outbuf = strchr(outbuf+2, '%')) + { + if (outbuf[1]=='#') + ++outbuf; /* not documented by python, */ + if (outbuf[1]=='\0' || + !strchr("aAbBcdfHIjmMpSUwWxXyYzZ%", outbuf[1])) + { + PyErr_SetString(PyExc_ValueError, "Invalid format string"); + return 0; + } + } +#endif + fmtlen = strlen(fmt); /* I hate these functions that presume you know how big the output From buildbot at python.org Tue Mar 3 01:02:51 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 00:02:51 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 2.6 Message-ID: <20090303000252.1CFD01E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%202.6/builds/161 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 3 01:13:51 2009 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 3 Mar 2009 01:13:51 +0100 (CET) Subject: [Python-checkins] r70115 - in python/branches/io-c: Doc/c-api/buffer.rst Doc/library/collections.rst Doc/library/configparser.rst Doc/library/importlib.rst Doc/library/re.rst Include/parsetok.h Include/pythonrun.h Lib/collections.py Lib/configparser.py Lib/distutils/command/bdist_rpm.py Lib/distutils/tests/test_bdist_rpm.py Lib/http/client.py Lib/importlib/NOTES Lib/importlib/test/test_util.py Lib/importlib/util.py Lib/re.py Lib/test/test_coding.py Lib/test/test_collections.py Lib/test/test_httplib.py Lib/test/test_pep263.py Misc/ACKS Misc/NEWS Modules/timemodule.c Parser/parsetok.c Parser/tokenizer.c Parser/tokenizer.h Python/bltinmodule.c Python/peephole.c Python/pythonrun.c Message-ID: <20090303001351.D66D91E4002@bag.python.org> Author: antoine.pitrou Date: Tue Mar 3 01:13:51 2009 New Revision: 70115 Log: Merged revisions 70076-70077,70079,70084,70089,70091,70096,70098-70099,70101-70102,70104-70106,70109,70111,70113-70114 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70076 | jeffrey.yasskin | 2009-02-28 20:49:43 +0100 (sam., 28 f?vr. 2009) | 2 lines Fix 2 oversights from r69961. ................ r70077 | jeffrey.yasskin | 2009-02-28 20:52:09 +0100 (sam., 28 f?vr. 2009) | 11 lines Blocked revisions 70071 via svnmerge ........ r70071 | jeffrey.yasskin | 2009-02-28 11:03:21 -0800 (Sat, 28 Feb 2009) | 5 lines Backport r69961 to trunk, replacing JUMP_IF_{TRUE,FALSE} with POP_JUMP_IF_{TRUE,FALSE} and JUMP_IF_{TRUE,FALSE}_OR_POP. This avoids executing a POP_TOP on each conditional and sometimes allows the peephole optimizer to skip a JUMP_ABSOLUTE entirely. It speeds up list comprehensions significantly. ........ ................ r70079 | georg.brandl | 2009-02-28 22:34:14 +0100 (sam., 28 f?vr. 2009) | 8 lines Blocked revisions 70078 via svnmerge ........ r70078 | georg.brandl | 2009-02-28 22:33:10 +0100 (Sa, 28 Feb 2009) | 2 lines Fix 3k-style metaclass syntax in docstrings. ........ ................ r70084 | raymond.hettinger | 2009-03-01 03:16:04 +0100 (dim., 01 mars 2009) | 1 line Fix docs for ConfigParser. ................ r70089 | gregory.p.smith | 2009-03-02 06:04:04 +0100 (lun., 02 mars 2009) | 2 lines Merged r70088 from trunk (re documentation update) ................ r70091 | gregory.p.smith | 2009-03-02 06:21:55 +0100 (lun., 02 mars 2009) | 10 lines Merged revisions 70090 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70090 | gregory.p.smith | 2009-03-01 21:13:57 -0800 (Sun, 01 Mar 2009) | 3 lines Adds an optional flags argument to re.split, re.sub and re.subn to be consistent with the other re module functions. ........ ................ r70096 | tarek.ziade | 2009-03-02 06:41:25 +0100 (lun., 02 mars 2009) | 9 lines Merged revisions 70094 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70094 | tarek.ziade | 2009-03-02 06:38:44 +0100 (Mon, 02 Mar 2009) | 1 line removing the force-optimized option as discussed in #1533164 ........ ................ r70098 | hirokazu.yamamoto | 2009-03-02 06:49:44 +0100 (lun., 02 mars 2009) | 1 line Fixed typo. ................ r70099 | brett.cannon | 2009-03-02 15:38:26 +0100 (lun., 02 mars 2009) | 2 lines Expose importlib.util.set___package__. ................ r70101 | raymond.hettinger | 2009-03-02 22:24:57 +0100 (lun., 02 mars 2009) | 1 line PEP 372: OrderedDict() ................ r70102 | raymond.hettinger | 2009-03-02 22:28:41 +0100 (lun., 02 mars 2009) | 1 line Missed my last update to __eq__ to check matching length. ................ r70104 | benjamin.peterson | 2009-03-02 22:44:54 +0100 (lun., 02 mars 2009) | 1 line fix versionadded ................ r70105 | raymond.hettinger | 2009-03-02 23:16:43 +0100 (lun., 02 mars 2009) | 1 line Fix versionchanged. ................ r70106 | raymond.hettinger | 2009-03-02 23:28:31 +0100 (lun., 02 mars 2009) | 1 line Add OrderedDict support to collections.namedtuple(). ................ r70109 | benjamin.peterson | 2009-03-02 23:50:25 +0100 (lun., 02 mars 2009) | 9 lines Merged revisions 70107 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70107 | benjamin.peterson | 2009-03-02 16:41:42 -0600 (Mon, 02 Mar 2009) | 1 line give httplib.IncompleteRead a more sane repr #4308 ........ ................ r70111 | raymond.hettinger | 2009-03-03 00:06:00 +0100 (mar., 03 mars 2009) | 1 line Let configparser use ordered dicts by default. ................ r70113 | benjamin.peterson | 2009-03-03 00:31:26 +0100 (mar., 03 mars 2009) | 1 line ignore the coding cookie in compile(), exec(), and eval() if the source is a string #4626 ................ r70114 | amaury.forgeotdarc | 2009-03-03 00:52:57 +0100 (mar., 03 mars 2009) | 4 lines re-merge r69268 (issue4804) from trunk: Now that the C runtime assertions are not silenced any more, we must provide checks for the format string of strftime ................ Modified: python/branches/io-c/ (props changed) python/branches/io-c/Doc/c-api/buffer.rst python/branches/io-c/Doc/library/collections.rst python/branches/io-c/Doc/library/configparser.rst python/branches/io-c/Doc/library/importlib.rst python/branches/io-c/Doc/library/re.rst python/branches/io-c/Include/parsetok.h python/branches/io-c/Include/pythonrun.h python/branches/io-c/Lib/collections.py python/branches/io-c/Lib/configparser.py python/branches/io-c/Lib/distutils/command/bdist_rpm.py python/branches/io-c/Lib/distutils/tests/test_bdist_rpm.py python/branches/io-c/Lib/http/client.py python/branches/io-c/Lib/importlib/NOTES python/branches/io-c/Lib/importlib/test/test_util.py python/branches/io-c/Lib/importlib/util.py python/branches/io-c/Lib/re.py python/branches/io-c/Lib/test/test_coding.py python/branches/io-c/Lib/test/test_collections.py python/branches/io-c/Lib/test/test_httplib.py python/branches/io-c/Lib/test/test_pep263.py python/branches/io-c/Misc/ACKS python/branches/io-c/Misc/NEWS python/branches/io-c/Modules/timemodule.c python/branches/io-c/Parser/parsetok.c python/branches/io-c/Parser/tokenizer.c python/branches/io-c/Parser/tokenizer.h python/branches/io-c/Python/bltinmodule.c python/branches/io-c/Python/peephole.c python/branches/io-c/Python/pythonrun.c Modified: python/branches/io-c/Doc/c-api/buffer.rst ============================================================================== --- python/branches/io-c/Doc/c-api/buffer.rst (original) +++ python/branches/io-c/Doc/c-api/buffer.rst Tue Mar 3 01:13:51 2009 @@ -252,7 +252,7 @@ .. cfunction:: void PyBuffer_Release(PyObject *obj, Py_buffer *view) - Release the buffer *view* over *obj*. This shouldd be called when the buffer + Release the buffer *view* over *obj*. This should be called when the buffer is no longer being used as it may free memory from it. Modified: python/branches/io-c/Doc/library/collections.rst ============================================================================== --- python/branches/io-c/Doc/library/collections.rst (original) +++ python/branches/io-c/Doc/library/collections.rst Tue Mar 3 01:13:51 2009 @@ -14,7 +14,7 @@ __name__ = '' This module implements high-performance container datatypes. Currently, -there are three datatypes, :class:`Counter`, :class:`deque` and +there are four datatypes, :class:`Counter`, :class:`deque`, :class:`OrderedDict` and :class:`defaultdict`, and one datatype factory function, :func:`namedtuple`. The specialized containers provided in this module provide alternatives @@ -184,7 +184,7 @@ >>> c['sausage'] = 0 # counter entry with a zero count >>> del c['sausage'] # del actually removes the entry - .. versionadded:: 2.7 + .. versionadded:: 3.1 Counter objects support two methods beyond those available for all @@ -621,7 +621,7 @@ Named tuple instances do not have per-instance dictionaries, so they are lightweight and require no more memory than regular tuples. - .. versionchanged:: 2.7 + .. versionchanged:: 3.1 added support for *rename*. Example: @@ -651,9 +651,9 @@ def __repr__(self): return 'Point(x=%r, y=%r)' % self - def _asdict(t): - 'Return a new dict which maps field names to their values' - return {'x': t[0], 'y': t[1]} + def _asdict(self): + 'Return a new OrderedDict which maps field names to their values' + return OrderedDict(zip(self._fields, self)) def _replace(self, **kwds): 'Return a new Point object replacing specified fields with new values' @@ -711,10 +711,14 @@ .. method:: somenamedtuple._asdict() - Return a new dict which maps field names to their corresponding values:: + Return a new :class:`OrderedDict` which maps field names to their corresponding + values:: >>> p._asdict() - {'x': 11, 'y': 22} + OrderedDict([('x', 11), ('y', 22)]) + + .. versionchanged 3.1 + Returns an :class:`OrderedDict` instead of a regular :class:`dict`. .. method:: somenamedtuple._replace(kwargs) @@ -806,6 +810,33 @@ adapted for Python 2.4. +:class:`OrderedDict` objects +---------------------------- + +Ordered dictionaries are just like regular dictionaries but they remember the +order that items were inserted. When iterating over an ordered dictionary, +the items are returned in the order their keys were first added. + +.. class:: OrderedDict([items]) + + Return an instance of a dict subclass, supporting the usual :class:`dict` + methods. An *OrderedDict* is a dict that remembers the order that keys + were first inserted. If a new entry overwrites an existing entry, the + original insertion position is left unchanged. Deleting an entry and + reinserting it will move it to the end. + + .. versionadded:: 3.1 + +The :meth:`popitem` method for ordered dictionaries returns and removes the +last added entry. The key/value pairs are returned in LIFO order. + +Equality tests between :class:`OrderedDict` objects are order-sensitive +and are implemented as ``list(od1.items())==list(od2.items())``. +Equality tests between :class:`OrderedDict` objects and other +:class:`Mapping` objects are order-insensitive like regular dictionaries. +This allows :class:`OrderedDict` objects to be substituted anywhere a +regular dictionary is used. + :class:`UserDict` objects ------------------------- Modified: python/branches/io-c/Doc/library/configparser.rst ============================================================================== --- python/branches/io-c/Doc/library/configparser.rst (original) +++ python/branches/io-c/Doc/library/configparser.rst Tue Mar 3 01:13:51 2009 @@ -64,8 +64,11 @@ options within a section, and for the default values. This class does not support the magical interpolation behavior. + .. versionchanged 3.1 + The default *dict_type* is :class:`collections.OrderedDict`. -.. class:: ConfigParser([defaults]) + +.. class:: ConfigParser([defaults[, dict_type]]) Derived class of :class:`RawConfigParser` that implements the magical interpolation feature and adds optional arguments to the :meth:`get` and @@ -80,8 +83,11 @@ option names to lower case), the values ``foo %(bar)s`` and ``foo %(BAR)s`` are equivalent. + .. versionchanged 3.1 + The default *dict_type* is :class:`collections.OrderedDict`. + -.. class:: SafeConfigParser([defaults]) +.. class:: SafeConfigParser([defaults[, dict_type]]) Derived class of :class:`ConfigParser` that implements a more-sane variant of the magical interpolation feature. This implementation is more predictable as @@ -90,6 +96,9 @@ .. XXX Need to explain what's safer/more predictable about it. + .. versionchanged 3.1 + The default *dict_type* is :class:`collections.OrderedDict`. + .. exception:: NoSectionError Modified: python/branches/io-c/Doc/library/importlib.rst ============================================================================== --- python/branches/io-c/Doc/library/importlib.rst (original) +++ python/branches/io-c/Doc/library/importlib.rst Tue Mar 3 01:13:51 2009 @@ -167,20 +167,28 @@ A :term:`decorator` for a :term:`loader` which handles selecting the proper module object to load with. The decorated method is expected to have a call signature of ``method(self, module_object)`` for which the second argument - will be the module object to be used (note that the decorator will not work - on static methods because of the assumption of two arguments). + will be the module object to be used by the loader (note that the decorator + will not work on static methods because of the assumption of two + arguments). The decorated method will take in the name of the module to be loaded as - normal. If the module is not found in :data:`sys.modules` then a new one is - constructed with its :attr:`__name__` attribute set. Otherwise the module - found in :data:`sys.modules` will be passed into the method. If an + expected for a :term:`loader`. If the module is not found in + :data:`sys.modules` then a new one is constructed with its + :attr:`__name__` attribute set. Otherwise the module found in + :data:`sys.modules` will be passed into the method. If an exception is raised by the decorated method and a module was added to :data:`sys.modules` it will be removed to prevent a partially initialized - module from being in left in :data:`sys.modules` If an exception is raised - by the decorated method and a module was added to :data:`sys.modules` it - will be removed to prevent a partially initialized module from being in - left in :data:`sys.modules`. If the module was already in - :data:`sys.modules` then it is left alone. + module from being in left in :data:`sys.modules`. If the module was already + in :data:`sys.modules` then it is left alone. - Use of this decorator handles all the details of what module a loader - should use as specified by :pep:`302`. + Use of this decorator handles all the details of what module object a + loader should initialize as specified by :pep:`302`. + + +.. function:: set___package__(method) + + A :term:`decorator` for a :term:`loader` to set the :attr:`__package__` + attribute on the module returned by the loader. If :attr:`__package__` is + set and has a value other than :keyword:`None` it will not be changed. + Note that the module returned by the loader is what has the attribute + set on and not the module found in :data:`sys.modules`. Modified: python/branches/io-c/Doc/library/re.rst ============================================================================== --- python/branches/io-c/Doc/library/re.rst (original) +++ python/branches/io-c/Doc/library/re.rst Tue Mar 3 01:13:51 2009 @@ -460,19 +460,23 @@ The sequence :: - prog = re.compile(pat) - result = prog.match(str) + prog = re.compile(pattern) + result = prog.match(string) is equivalent to :: - result = re.match(pat, str) + result = re.match(pattern, string) - but the version using :func:`compile` is more efficient when the expression - will be used several times in a single program. + but using :func:`compile` and saving the resulting regular expression object + for reuse is more efficient when the expression will be used several times + in a single program. - .. (The compiled version of the last pattern passed to :func:`re.match` or - :func:`re.search` is cached, so programs that use only a single regular - expression at a time needn't worry about compiling regular expressions.) + .. note:: + + The compiled versions of the most recent patterns passed to + :func:`re.match`, :func:`re.search` or :func:`re.compile` are cached, so + programs that use only a few regular expressions at a time needn't worry + about compiling regular expressions. .. data:: A @@ -567,7 +571,7 @@ instead. -.. function:: split(pattern, string[, maxsplit=0]) +.. function:: split(pattern, string[, maxsplit=0, flags=0]) Split *string* by the occurrences of *pattern*. If capturing parentheses are used in *pattern*, then the text of all groups in the pattern are also returned @@ -581,6 +585,8 @@ ['Words', ', ', 'words', ', ', 'words', '.', ''] >>> re.split('\W+', 'Words, words, words.', 1) ['Words', 'words, words.'] + >>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE) + ['0', '3', '9'] If there are capturing groups in the separator and it matches at the start of the string, the result will start with an empty string. The same holds for @@ -601,6 +607,9 @@ >>> re.split("(?m)^$", "foo\n\nbar\n") ['foo\n\nbar\n'] + .. versionchanged:: 2.7,3.1 + Added the optional flags argument. + .. function:: findall(pattern, string[, flags]) @@ -621,7 +630,7 @@ match. -.. function:: sub(pattern, repl, string[, count]) +.. function:: sub(pattern, repl, string[, count, flags]) Return the string obtained by replacing the leftmost non-overlapping occurrences of *pattern* in *string* by the replacement *repl*. If the pattern isn't found, @@ -646,6 +655,8 @@ ... else: return '-' >>> re.sub('-{1,2}', dashrepl, 'pro----gram-files') 'pro--gram files' + >>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE) + 'Baked Beans & Spam' The pattern may be a string or an RE object; if you need to specify regular expression flags, you must use a RE object, or use embedded modifiers in a @@ -666,12 +677,18 @@ character ``'0'``. The backreference ``\g<0>`` substitutes in the entire substring matched by the RE. + .. versionchanged:: 2.7,3.1 + Added the optional flags argument. -.. function:: subn(pattern, repl, string[, count]) + +.. function:: subn(pattern, repl, string[, count, flags]) Perform the same operation as :func:`sub`, but return a tuple ``(new_string, number_of_subs_made)``. + .. versionchanged:: 2.7,3.1 + Added the optional flags argument. + .. function:: escape(string) Modified: python/branches/io-c/Include/parsetok.h ============================================================================== --- python/branches/io-c/Include/parsetok.h (original) +++ python/branches/io-c/Include/parsetok.h Tue Mar 3 01:13:51 2009 @@ -29,6 +29,8 @@ #define PyPARSE_UNICODE_LITERALS 0x0008 #endif +#define PyPARSE_IGNORE_COOKIE 0x0010 + PyAPI_FUNC(node *) PyParser_ParseString(const char *, grammar *, int, perrdetail *); PyAPI_FUNC(node *) PyParser_ParseFile (FILE *, const char *, grammar *, int, Modified: python/branches/io-c/Include/pythonrun.h ============================================================================== --- python/branches/io-c/Include/pythonrun.h (original) +++ python/branches/io-c/Include/pythonrun.h Tue Mar 3 01:13:51 2009 @@ -12,6 +12,7 @@ #define PyCF_SOURCE_IS_UTF8 0x0100 #define PyCF_DONT_IMPLY_DEDENT 0x0200 #define PyCF_ONLY_AST 0x0400 +#define PyCF_IGNORE_COOKIE 0x0800 typedef struct { int cf_flags; /* bitmask of CO_xxx flags relevant to future */ Modified: python/branches/io-c/Lib/collections.py ============================================================================== --- python/branches/io-c/Lib/collections.py (original) +++ python/branches/io-c/Lib/collections.py Tue Mar 3 01:13:51 2009 @@ -1,5 +1,5 @@ __all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList', - 'UserString', 'Counter'] + 'UserString', 'Counter', 'OrderedDict'] # For bootstrapping reasons, the collection ABCs are defined in _abcoll.py. # They should however be considered an integral part of collections.py. from _abcoll import * @@ -13,6 +13,79 @@ import heapq as _heapq from itertools import repeat as _repeat, chain as _chain, starmap as _starmap +################################################################################ +### OrderedDict +################################################################################ + +class OrderedDict(dict, MutableMapping): + + def __init__(self, *args, **kwds): + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + if not hasattr(self, '_keys'): + self._keys = [] + self.update(*args, **kwds) + + def clear(self): + del self._keys[:] + dict.clear(self) + + def __setitem__(self, key, value): + if key not in self: + self._keys.append(key) + dict.__setitem__(self, key, value) + + def __delitem__(self, key): + dict.__delitem__(self, key) + self._keys.remove(key) + + def __iter__(self): + return iter(self._keys) + + def __reversed__(self): + return reversed(self._keys) + + def popitem(self): + if not self: + raise KeyError('dictionary is empty') + key = self._keys.pop() + value = dict.pop(self, key) + return key, value + + def __reduce__(self): + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + inst_dict.pop('_keys', None) + return (self.__class__, (items,), inst_dict) + + setdefault = MutableMapping.setdefault + update = MutableMapping.update + pop = MutableMapping.pop + keys = MutableMapping.keys + values = MutableMapping.values + items = MutableMapping.items + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, list(self.items())) + + def copy(self): + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + if isinstance(other, OrderedDict): + return len(self)==len(other) and all(p==q for p, q in zip(self.items(), other.items())) + return dict.__eq__(self, other) + + ################################################################################ ### namedtuple @@ -76,7 +149,6 @@ numfields = len(field_names) argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes reprtxt = ', '.join('%s=%%r' % name for name in field_names) - dicttxt = ', '.join('%r: t[%d]' % (name, pos) for pos, name in enumerate(field_names)) template = '''class %(typename)s(tuple): '%(typename)s(%(argtxt)s)' \n __slots__ = () \n @@ -92,9 +164,9 @@ return result \n def __repr__(self): return '%(typename)s(%(reprtxt)s)' %% self \n - def _asdict(t): - 'Return a new dict which maps field names to their values' - return {%(dicttxt)s} \n + def _asdict(self): + 'Return a new OrderedDict which maps field names to their values' + return OrderedDict(zip(self._fields, self)) \n def _replace(self, **kwds): 'Return a new %(typename)s object replacing specified fields with new values' result = self._make(map(kwds.pop, %(field_names)r, self)) @@ -110,7 +182,8 @@ # Execute the template string in a temporary namespace and # support tracing utilities by setting a value for frame.f_globals['__name__'] - namespace = dict(itemgetter=_itemgetter, __name__='namedtuple_%s' % typename) + namespace = dict(itemgetter=_itemgetter, __name__='namedtuple_%s' % typename, + OrderedDict=OrderedDict) try: exec(template, namespace) except SyntaxError as e: Modified: python/branches/io-c/Lib/configparser.py ============================================================================== --- python/branches/io-c/Lib/configparser.py (original) +++ python/branches/io-c/Lib/configparser.py Tue Mar 3 01:13:51 2009 @@ -88,6 +88,7 @@ """ import re +from collections import OrderedDict __all__ = ["NoSectionError", "DuplicateSectionError", "NoOptionError", "InterpolationError", "InterpolationDepthError", @@ -215,7 +216,7 @@ class RawConfigParser: - def __init__(self, defaults=None, dict_type=dict): + def __init__(self, defaults=None, dict_type=OrderedDict): self._dict = dict_type self._sections = self._dict() self._defaults = self._dict() Modified: python/branches/io-c/Lib/distutils/command/bdist_rpm.py ============================================================================== --- python/branches/io-c/Lib/distutils/command/bdist_rpm.py (original) +++ python/branches/io-c/Lib/distutils/command/bdist_rpm.py Tue Mar 3 01:13:51 2009 @@ -125,18 +125,10 @@ ('quiet', 'q', "Run the INSTALL phase of RPM building in quiet mode"), - - # Forces the -O1 option when calling the install command, - # so the rpm contains all files needed for proper operation under - # SELinux. Some systems checks for this on build-time and will - # fail without this. - ('force-optimize', None, - "Forces the -O1 option when calling the install command"), - ] boolean_options = ['keep-temp', 'use-rpm-opt-flags', 'rpm3-mode', - 'no-autoreq', 'quiet', 'force-optimize'] + 'no-autoreq', 'quiet'] negative_opt = {'no-keep-temp': 'keep-temp', 'no-rpm-opt-flags': 'use-rpm-opt-flags', @@ -187,7 +179,6 @@ self.force_arch = None self.quiet = 0 - self.force_optimize = 1 def finalize_options(self): self.set_undefined_options('bdist', ('bdist_base', 'bdist_base')) @@ -492,14 +483,8 @@ # that we open and interpolate into the spec file, but the defaults # are just text that we drop in as-is. Hmmm. - # forcing -O1 if force-optimize - if self.force_optimize: - optimize = ' -O1' - else: - optimize = '' - - install_cmd = ('%s install%s --root=$RPM_BUILD_ROOT ' - '--record=INSTALLED_FILES') % (def_setup_call, optimize) + install_cmd = ('%s install -O1 --root=$RPM_BUILD_ROOT ' + '--record=INSTALLED_FILES') % def_setup_call script_options = [ ('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"), Modified: python/branches/io-c/Lib/distutils/tests/test_bdist_rpm.py ============================================================================== --- python/branches/io-c/Lib/distutils/tests/test_bdist_rpm.py (original) +++ python/branches/io-c/Lib/distutils/tests/test_bdist_rpm.py Tue Mar 3 01:13:51 2009 @@ -109,8 +109,6 @@ cmd = bdist_rpm(dist) cmd.fix_python = True - # running with force-optimize = 1 - # and quiet = 1 cmd.quiet = 1 cmd.ensure_finalized() cmd.run() @@ -119,29 +117,6 @@ self.assert_('foo-0.1-1.noarch.rpm' in dist_created) os.remove(os.path.join(pkg_dir, 'dist', 'foo-0.1-1.noarch.rpm')) - # XXX I am unable yet to make this test work without - # spurious stderr output - # so returning until distutils.spawn acts better - return - - # running with force-optimize = 0 - cmd.force_optimize = 0 - try: - # XXX How to prevent the spawned - # rpmbuild command to display errors ? - # this can be a problem for buildbots - cmd.ensure_finalized() - cmd.run() - except DistutilsExecError: - # happens only under Fedora/RedHat - # and some flavors of Linux - # otherwise it's a bug - if sys.platform == 'linux2': - return - - dist_created = os.listdir(os.path.join(pkg_dir, 'dist')) - self.assert_('foo-0.1-1.noarch.rpm' in dist_created) - def test_suite(): return unittest.makeSuite(BuildRpmTestCase) Modified: python/branches/io-c/Lib/http/client.py ============================================================================== --- python/branches/io-c/Lib/http/client.py (original) +++ python/branches/io-c/Lib/http/client.py Tue Mar 3 01:13:51 2009 @@ -578,7 +578,7 @@ while amt > 0: chunk = self.fp.read(min(amt, MAXAMOUNT)) if not chunk: - raise IncompleteRead(s) + raise IncompleteRead(b''.join(s), amt) s.append(chunk) amt -= len(chunk) return b"".join(s) @@ -1009,9 +1009,18 @@ pass class IncompleteRead(HTTPException): - def __init__(self, partial): + def __init__(self, partial, expected=None): self.args = partial, self.partial = partial + self.expected = expected + def __repr__(self): + if self.expected is not None: + e = ', %i more expected' % self.expected + else: + e = '' + return 'IncompleteRead(%i bytes read%s)' % (len(self.partial), e) + def __str__(self): + return repr(self) class ImproperConnectionState(HTTPException): pass Modified: python/branches/io-c/Lib/importlib/NOTES ============================================================================== --- python/branches/io-c/Lib/importlib/NOTES (original) +++ python/branches/io-c/Lib/importlib/NOTES Tue Mar 3 01:13:51 2009 @@ -1,10 +1,6 @@ to do ///// -* Implement PEP 302 protocol for loaders (should just be a matter of testing). - - + Source/bytecode. - * Public API left to expose (w/ docs!) + abc @@ -27,27 +23,15 @@ * get_code * get_source - - (?) SourceLoader(ResourceLoader) + - PyLoader(ResourceLoader) * source_path - * bytecode_path - * write_bytecode (not abstract) - - + util - - - set___package__ decorator - + machinery + - PyPycLoader(PyLoader) - - Extensions importers - - * ExtensionFinder - * (?) Loader - - - Source/bytecode importers - - * SourceFinder - * (?) Loader + * source_mtime + * bytecode_path + * write_bytecode + test (Really want to worry about compatibility with future versions?) Modified: python/branches/io-c/Lib/importlib/test/test_util.py ============================================================================== --- python/branches/io-c/Lib/importlib/test/test_util.py (original) +++ python/branches/io-c/Lib/importlib/test/test_util.py Tue Mar 3 01:13:51 2009 @@ -60,9 +60,58 @@ self.assert_(sys.modules[name] is module) +class SetPackageTests(unittest.TestCase): + + + """Tests for importlib.util.set___package__.""" + + def verify(self, module, expect): + """Verify the module has the expected value for __package__ after + passing through set___package__.""" + fxn = lambda: module + wrapped = util.set___package__(fxn) + wrapped() + self.assert_(hasattr(module, '__package__')) + self.assertEqual(expect, module.__package__) + + def test_top_level(self): + # __package__ should be set to the empty string if a top-level module. + # Implicitly tests when package is set to None. + module = imp.new_module('module') + module.__package__ = None + self.verify(module, '') + + def test_package(self): + # Test setting __package__ for a package. + module = imp.new_module('pkg') + module.__path__ = [''] + module.__package__ = None + self.verify(module, 'pkg') + + def test_submodule(self): + # Test __package__ for a module in a package. + module = imp.new_module('pkg.mod') + module.__package__ = None + self.verify(module, 'pkg') + + def test_setting_if_missing(self): + # __package__ should be set if it is missing. + module = imp.new_module('mod') + if hasattr(module, '__package__'): + delattr(module, '__package__') + self.verify(module, '') + + def test_leaving_alone(self): + # If __package__ is set and not None then leave it alone. + for value in (True, False): + module = imp.new_module('mod') + module.__package__ = value + self.verify(module, value) + + def test_main(): from test import support - support.run_unittest(ModuleForLoaderTests) + support.run_unittest(ModuleForLoaderTests, SetPackageTests) if __name__ == '__main__': Modified: python/branches/io-c/Lib/importlib/util.py ============================================================================== --- python/branches/io-c/Lib/importlib/util.py (original) +++ python/branches/io-c/Lib/importlib/util.py Tue Mar 3 01:13:51 2009 @@ -1,2 +1,3 @@ """Utility code for constructing importers, etc.""" from ._bootstrap import module_for_loader +from ._bootstrap import set___package__ Modified: python/branches/io-c/Lib/re.py ============================================================================== --- python/branches/io-c/Lib/re.py (original) +++ python/branches/io-c/Lib/re.py Tue Mar 3 01:13:51 2009 @@ -156,16 +156,16 @@ a match object, or None if no match was found.""" return _compile(pattern, flags).search(string) -def sub(pattern, repl, string, count=0): +def sub(pattern, repl, string, count=0, flags=0): """Return the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in string by the replacement repl. repl can be either a string or a callable; if a string, backslash escapes in it are processed. If it is a callable, it's passed the match object and must return a replacement string to be used.""" - return _compile(pattern, 0).sub(repl, string, count) + return _compile(pattern, flags).sub(repl, string, count) -def subn(pattern, repl, string, count=0): +def subn(pattern, repl, string, count=0, flags=0): """Return a 2-tuple containing (new_string, number). new_string is the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in the source @@ -174,12 +174,12 @@ callable; if a string, backslash escapes in it are processed. If it is a callable, it's passed the match object and must return a replacement string to be used.""" - return _compile(pattern, 0).subn(repl, string, count) + return _compile(pattern, flags).subn(repl, string, count) -def split(pattern, string, maxsplit=0): +def split(pattern, string, maxsplit=0, flags=0): """Split the source string by the occurrences of the pattern, returning a list containing the resulting substrings.""" - return _compile(pattern, 0).split(string, maxsplit) + return _compile(pattern, flags).split(string, maxsplit) def findall(pattern, string, flags=0): """Return a list of all non-overlapping matches in the string. Modified: python/branches/io-c/Lib/test/test_coding.py ============================================================================== --- python/branches/io-c/Lib/test/test_coding.py (original) +++ python/branches/io-c/Lib/test/test_coding.py Tue Mar 3 01:13:51 2009 @@ -17,10 +17,10 @@ path = os.path.dirname(__file__) filename = os.path.join(path, module_name + '.py') - fp = open(filename, encoding='utf-8') - text = fp.read() + fp = open(filename, "rb") + bytes = fp.read() fp.close() - self.assertRaises(SyntaxError, compile, text, filename, 'exec') + self.assertRaises(SyntaxError, compile, bytes, filename, 'exec') def test_exec_valid_coding(self): d = {} Modified: python/branches/io-c/Lib/test/test_collections.py ============================================================================== --- python/branches/io-c/Lib/test/test_collections.py (original) +++ python/branches/io-c/Lib/test/test_collections.py Tue Mar 3 01:13:51 2009 @@ -1,10 +1,12 @@ """Unit tests for collections.py.""" import unittest, doctest +import inspect from test import support -from collections import namedtuple, Counter, Mapping +from collections import namedtuple, Counter, OrderedDict +from test import mapping_tests import pickle, copy -from random import randrange +from random import randrange, shuffle import operator from collections import Hashable, Iterable, Iterator from collections import Sized, Container, Callable @@ -571,12 +573,201 @@ set_result = setop(set(p.elements()), set(q.elements())) self.assertEqual(counter_result, dict.fromkeys(set_result, 1)) + +class TestOrderedDict(unittest.TestCase): + + def test_init(self): + with self.assertRaises(TypeError): + OrderedDict([('a', 1), ('b', 2)], None) # too many args + pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] + self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input + self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input + self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input + self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)], + c=3, e=5).items()), pairs) # mixed input + + # make sure no positional args conflict with possible kwdargs + self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args, + ['self']) + + # Make sure that direct calls to __init__ do not clear previous contents + d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)]) + d.__init__([('e', 5), ('f', 6)], g=7, d=4) + self.assertEqual(list(d.items()), + [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)]) + + def test_update(self): + with self.assertRaises(TypeError): + OrderedDict().update([('a', 1), ('b', 2)], None) # too many args + pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] + od = OrderedDict() + od.update(dict(pairs)) + self.assertEqual(sorted(od.items()), pairs) # dict input + od = OrderedDict() + od.update(**dict(pairs)) + self.assertEqual(sorted(od.items()), pairs) # kwds input + od = OrderedDict() + od.update(pairs) + self.assertEqual(list(od.items()), pairs) # pairs input + od = OrderedDict() + od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5) + self.assertEqual(list(od.items()), pairs) # mixed input + + # Make sure that direct calls to update do not clear previous contents + # add that updates items are not moved to the end + d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)]) + d.update([('e', 5), ('f', 6)], g=7, d=4) + self.assertEqual(list(d.items()), + [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)]) + + def test_clear(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + self.assertEqual(len(od), len(pairs)) + od.clear() + self.assertEqual(len(od), 0) + + def test_delitem(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + od = OrderedDict(pairs) + del od['a'] + self.assert_('a' not in od) + with self.assertRaises(KeyError): + del od['a'] + self.assertEqual(list(od.items()), pairs[:2] + pairs[3:]) + + def test_setitem(self): + od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)]) + od['c'] = 10 # existing element + od['f'] = 20 # new element + self.assertEqual(list(od.items()), + [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)]) + + def test_iterators(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + self.assertEqual(list(od), [t[0] for t in pairs]) + self.assertEqual(list(od.keys()), [t[0] for t in pairs]) + self.assertEqual(list(od.values()), [t[1] for t in pairs]) + self.assertEqual(list(od.items()), pairs) + self.assertEqual(list(reversed(od)), + [t[0] for t in reversed(pairs)]) + + def test_popitem(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + while pairs: + self.assertEqual(od.popitem(), pairs.pop()) + with self.assertRaises(KeyError): + od.popitem() + self.assertEqual(len(od), 0) + + def test_pop(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + shuffle(pairs) + while pairs: + k, v = pairs.pop() + self.assertEqual(od.pop(k), v) + with self.assertRaises(KeyError): + od.pop('xyz') + self.assertEqual(len(od), 0) + self.assertEqual(od.pop(k, 12345), 12345) + + def test_equality(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od1 = OrderedDict(pairs) + od2 = OrderedDict(pairs) + self.assertEqual(od1, od2) # same order implies equality + pairs = pairs[2:] + pairs[:2] + od2 = OrderedDict(pairs) + self.assertNotEqual(od1, od2) # different order implies inequality + # comparison to regular dict is not order sensitive + self.assertEqual(od1, dict(od2)) + self.assertEqual(dict(od2), od1) + # different length implied inequality + self.assertNotEqual(od1, OrderedDict(pairs[:-1])) + + def test_copying(self): + # Check that ordered dicts are copyable, deepcopyable, picklable, + # and have a repr/eval round-trip + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + od = OrderedDict(pairs) + update_test = OrderedDict() + update_test.update(od) + for i, dup in enumerate([ + od.copy(), + copy.copy(od), + copy.deepcopy(od), + pickle.loads(pickle.dumps(od, 0)), + pickle.loads(pickle.dumps(od, 1)), + pickle.loads(pickle.dumps(od, 2)), + pickle.loads(pickle.dumps(od, 3)), + pickle.loads(pickle.dumps(od, -1)), + eval(repr(od)), + update_test, + OrderedDict(od), + ]): + self.assert_(dup is not od) + self.assertEquals(dup, od) + self.assertEquals(list(dup.items()), list(od.items())) + self.assertEquals(len(dup), len(od)) + self.assertEquals(type(dup), type(od)) + + def test_repr(self): + od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]) + self.assertEqual(repr(od), + "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])") + self.assertEqual(eval(repr(od)), od) + self.assertEqual(repr(OrderedDict()), "OrderedDict()") + + def test_setdefault(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + pair_order = list(od.items()) + self.assertEqual(od.setdefault('a', 10), 3) + # make sure order didn't change + self.assertEqual(list(od.items()), pair_order) + self.assertEqual(od.setdefault('x', 10), 10) + # make sure 'x' is added to the end + self.assertEqual(list(od.items())[-1], ('x', 10)) + + def test_reinsert(self): + # Given insert a, insert b, delete a, re-insert a, + # verify that a is now later than b. + od = OrderedDict() + od['a'] = 1 + od['b'] = 2 + del od['a'] + od['a'] = 1 + self.assertEqual(list(od.items()), [('b', 2), ('a', 1)]) + + + +class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol): + type2test = OrderedDict + +class MyOrderedDict(OrderedDict): + pass + +class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol): + type2test = MyOrderedDict + + + import doctest, collections def test_main(verbose=None): NamedTupleDocs = doctest.DocTestSuite(module=collections) test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs, - TestCollectionABCs, TestCounter] + TestCollectionABCs, TestCounter, + TestOrderedDict, GeneralMappingTests, SubclassMappingTests] support.run_unittest(*test_classes) support.run_doctest(collections, verbose) Modified: python/branches/io-c/Lib/test/test_httplib.py ============================================================================== --- python/branches/io-c/Lib/test/test_httplib.py (original) +++ python/branches/io-c/Lib/test/test_httplib.py Tue Mar 3 01:13:51 2009 @@ -181,6 +181,8 @@ resp.read() except httplib.IncompleteRead as i: self.assertEquals(i.partial, b'hello world') + self.assertEqual(repr(i),'IncompleteRead(11 bytes read)') + self.assertEqual(str(i),'IncompleteRead(11 bytes read)') else: self.fail('IncompleteRead expected') finally: @@ -194,6 +196,23 @@ self.assertEquals(resp.read(), b'Hello\r\n') resp.close() + def test_incomplete_read(self): + sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n') + resp = httplib.HTTPResponse(sock, method="GET") + resp.begin() + try: + resp.read() + except httplib.IncompleteRead as i: + self.assertEquals(i.partial, b'Hello\r\n') + self.assertEqual(repr(i), + "IncompleteRead(7 bytes read, 3 more expected)") + self.assertEqual(str(i), + "IncompleteRead(7 bytes read, 3 more expected)") + else: + self.fail('IncompleteRead expected') + finally: + resp.close() + class OfflineTest(TestCase): def test_responses(self): Modified: python/branches/io-c/Lib/test/test_pep263.py ============================================================================== --- python/branches/io-c/Lib/test/test_pep263.py (original) +++ python/branches/io-c/Lib/test/test_pep263.py Tue Mar 3 01:13:51 2009 @@ -30,6 +30,12 @@ else: self.fail() + def test_issue4626(self): + c = compile("# coding=latin-1\n\u00c6 = '\u00c6'", "dummy", "exec") + d = {} + exec(c, d) + self.assertEquals(d['\xc6'], '\xc6') + def test_main(): support.run_unittest(PEP263Test) Modified: python/branches/io-c/Misc/ACKS ============================================================================== --- python/branches/io-c/Misc/ACKS (original) +++ python/branches/io-c/Misc/ACKS Tue Mar 3 01:13:51 2009 @@ -767,6 +767,7 @@ Blake Winton Jean-Claude Wippler Lars Wirzenius +Chris Withers Stefan Witzel David Wolever Klaus-Juergen Wolf Modified: python/branches/io-c/Misc/NEWS ============================================================================== --- python/branches/io-c/Misc/NEWS (original) +++ python/branches/io-c/Misc/NEWS Tue Mar 3 01:13:51 2009 @@ -19,6 +19,9 @@ - Issue #5249: time.strftime returned malformed string when format string contained non ascii character on windows. +- Issue #4626: compile(), exec(), and eval() ignore the coding cookie if the + source has already been decoded into str. + - Issue #5186: Reduce hash collisions for objects with no __hash__ method by rotating the object pointer by 4 bits to the right. @@ -170,9 +173,17 @@ - Issue #4748: Lambda generators no longer return a value. +- The re.sub(), re.subn() and re.split() functions now accept a flags parameter. + Library ------- +- PEP 372: Added collections.OrderedDict(). + +- The _asdict() for method for namedtuples now returns an OrderedDict(). + +- configparser now defaults to using an ordered dictionary. + - Issue #1733986: Fixed mmap crash in accessing elements of second map object with same tagname but larger size than first map. (Windows) Modified: python/branches/io-c/Modules/timemodule.c ============================================================================== --- python/branches/io-c/Modules/timemodule.c (original) +++ python/branches/io-c/Modules/timemodule.c Tue Mar 3 01:13:51 2009 @@ -513,6 +513,24 @@ if (format == NULL) return NULL; fmt = PyBytes_AS_STRING(format); + +#ifdef MS_WINDOWS + /* check that the format string contains only valid directives */ + for(outbuf = strchr(fmt, '%'); + outbuf != NULL; + outbuf = strchr(outbuf+2, '%')) + { + if (outbuf[1]=='#') + ++outbuf; /* not documented by python, */ + if (outbuf[1]=='\0' || + !strchr("aAbBcdfHIjmMpSUwWxXyYzZ%", outbuf[1])) + { + PyErr_SetString(PyExc_ValueError, "Invalid format string"); + return 0; + } + } +#endif + fmtlen = strlen(fmt); /* I hate these functions that presume you know how big the output Modified: python/branches/io-c/Parser/parsetok.c ============================================================================== --- python/branches/io-c/Parser/parsetok.c (original) +++ python/branches/io-c/Parser/parsetok.c Tue Mar 3 01:13:51 2009 @@ -49,7 +49,11 @@ initerr(err_ret, filename); - if ((tok = PyTokenizer_FromString(s)) == NULL) { + if (*flags & PyPARSE_IGNORE_COOKIE) + tok = PyTokenizer_FromUTF8(s); + else + tok = PyTokenizer_FromString(s); + if (tok == NULL) { err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM; return NULL; } Modified: python/branches/io-c/Parser/tokenizer.c ============================================================================== --- python/branches/io-c/Parser/tokenizer.c (original) +++ python/branches/io-c/Parser/tokenizer.c Tue Mar 3 01:13:51 2009 @@ -715,6 +715,28 @@ return tok; } +struct tok_state * +PyTokenizer_FromUTF8(const char *str) +{ + struct tok_state *tok = tok_new(); + if (tok == NULL) + return NULL; + tok->decoding_state = STATE_RAW; + tok->read_coding_spec = 1; + tok->enc = NULL; + tok->str = str; + tok->encoding = (char *)PyMem_MALLOC(6); + if (!tok->encoding) { + PyTokenizer_Free(tok); + return NULL; + } + strcpy(tok->encoding, "utf-8"); + + /* XXX: constify members. */ + tok->buf = tok->cur = tok->end = tok->inp = (char*)str; + return tok; +} + /* Set up tokenizer for file */ Modified: python/branches/io-c/Parser/tokenizer.h ============================================================================== --- python/branches/io-c/Parser/tokenizer.h (original) +++ python/branches/io-c/Parser/tokenizer.h Tue Mar 3 01:13:51 2009 @@ -61,6 +61,7 @@ }; extern struct tok_state *PyTokenizer_FromString(const char *); +extern struct tok_state *PyTokenizer_FromUTF8(const char *); extern struct tok_state *PyTokenizer_FromFile(FILE *, char*, char *, char *); extern void PyTokenizer_Free(struct tok_state *); Modified: python/branches/io-c/Python/bltinmodule.c ============================================================================== --- python/branches/io-c/Python/bltinmodule.c (original) +++ python/branches/io-c/Python/bltinmodule.c Tue Mar 3 01:13:51 2009 @@ -494,12 +494,13 @@ static char * -source_as_string(PyObject *cmd, char *funcname, char *what) +source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf) { char *str; Py_ssize_t size; if (PyUnicode_Check(cmd)) { + cf->cf_flags |= PyCF_IGNORE_COOKIE; cmd = _PyUnicode_AsDefaultEncodedString(cmd, NULL); if (cmd == NULL) return NULL; @@ -591,7 +592,7 @@ return result; } - str = source_as_string(cmd, "compile", "string, bytes, AST or code"); + str = source_as_string(cmd, "compile", "string, bytes, AST or code", &cf); if (str == NULL) return NULL; @@ -703,14 +704,14 @@ return PyEval_EvalCode((PyCodeObject *) cmd, globals, locals); } - str = source_as_string(cmd, "eval", "string, bytes or code"); + cf.cf_flags = PyCF_SOURCE_IS_UTF8; + str = source_as_string(cmd, "eval", "string, bytes or code", &cf); if (str == NULL) return NULL; while (*str == ' ' || *str == '\t') str++; - cf.cf_flags = PyCF_SOURCE_IS_UTF8; (void)PyEval_MergeCompilerFlags(&cf); result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf); Py_XDECREF(tmp); @@ -779,12 +780,13 @@ v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals); } else { - char *str = source_as_string(prog, "exec", - "string, bytes or code"); + char *str; PyCompilerFlags cf; + cf.cf_flags = PyCF_SOURCE_IS_UTF8; + str = source_as_string(prog, "exec", + "string, bytes or code", &cf); if (str == NULL) return NULL; - cf.cf_flags = PyCF_SOURCE_IS_UTF8; if (PyEval_MergeCompilerFlags(&cf)) v = PyRun_StringFlags(str, Py_file_input, globals, locals, &cf); Modified: python/branches/io-c/Python/peephole.c ============================================================================== --- python/branches/io-c/Python/peephole.c (original) +++ python/branches/io-c/Python/peephole.c Tue Mar 3 01:13:51 2009 @@ -425,7 +425,7 @@ cumlc = lastlc + 1; j = GETARG(codestr, i); if (codestr[i+3] != POP_JUMP_IF_FALSE || - !ISBASICBLOCK(blocks,i,7) || + !ISBASICBLOCK(blocks,i,6) || !PyObject_IsTrue(PyList_GET_ITEM(consts, j))) continue; memset(codestr+i, NOP, 6); @@ -516,8 +516,10 @@ "if a or b:" "a and b or c" "(a and b) and c" - x:POP_OR_JUMP y y:POP_OR_JUMP z --> x:POP_OR_JUMP z - x:POP_OR_JUMP y y:JUMP_OR_POP z --> x:POP_JUMP_IF_FALSE y+3 + x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z + --> x:JUMP_IF_FALSE_OR_POP z + x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z + --> x:POP_JUMP_IF_FALSE y+3 where y+3 is the instruction following the second test. */ case JUMP_IF_FALSE_OR_POP: Modified: python/branches/io-c/Python/pythonrun.c ============================================================================== --- python/branches/io-c/Python/pythonrun.c (original) +++ python/branches/io-c/Python/pythonrun.c Tue Mar 3 01:13:51 2009 @@ -1002,9 +1002,17 @@ } /* compute parser flags based on compiler flags */ -#define PARSER_FLAGS(flags) \ - ((flags) ? ((((flags)->cf_flags & PyCF_DONT_IMPLY_DEDENT) ? \ - PyPARSE_DONT_IMPLY_DEDENT : 0)) : 0) +static int PARSER_FLAGS(PyCompilerFlags *flags) +{ + int parser_flags = 0; + if (!flags) + return 0; + if (flags->cf_flags & PyCF_DONT_IMPLY_DEDENT) + parser_flags |= PyPARSE_DONT_IMPLY_DEDENT; + if (flags->cf_flags & PyCF_IGNORE_COOKIE) + parser_flags |= PyPARSE_IGNORE_COOKIE; + return parser_flags; +} #if 0 /* Keep an example of flags with future keyword support. */ From python-checkins at python.org Tue Mar 3 01:23:19 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 01:23:19 +0100 (CET) Subject: [Python-checkins] r70116 - python/branches/py3k/Doc/library/configparser.rst Message-ID: <20090303002319.ACC4F1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 01:23:19 2009 New Revision: 70116 Log: Fix markup. Modified: python/branches/py3k/Doc/library/configparser.rst Modified: python/branches/py3k/Doc/library/configparser.rst ============================================================================== --- python/branches/py3k/Doc/library/configparser.rst (original) +++ python/branches/py3k/Doc/library/configparser.rst Tue Mar 3 01:23:19 2009 @@ -64,7 +64,7 @@ options within a section, and for the default values. This class does not support the magical interpolation behavior. - .. versionchanged 3.1 + .. versionchanged:: 3.1 The default *dict_type* is :class:`collections.OrderedDict`. @@ -83,7 +83,7 @@ option names to lower case), the values ``foo %(bar)s`` and ``foo %(BAR)s`` are equivalent. - .. versionchanged 3.1 + .. versionchanged:: 3.1 The default *dict_type* is :class:`collections.OrderedDict`. @@ -96,7 +96,7 @@ .. XXX Need to explain what's safer/more predictable about it. - .. versionchanged 3.1 + .. versionchanged:: 3.1 The default *dict_type* is :class:`collections.OrderedDict`. From buildbot at python.org Tue Mar 3 01:30:25 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 00:30:25 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090303003025.79B931E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/353 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: amaury.forgeotdarc,benjamin.peterson,raymond.hettinger BUILD FAILED: failed compile sincerely, -The Buildbot From buildbot at python.org Tue Mar 3 01:34:24 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 00:34:24 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090303003424.A73E51E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/448 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: amaury.forgeotdarc,benjamin.peterson,raymond.hettinger BUILD FAILED: failed compile sincerely, -The Buildbot From buildbot at python.org Tue Mar 3 01:41:47 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 00:41:47 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090303004148.129C41E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/394 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed compile sincerely, -The Buildbot From python-checkins at python.org Tue Mar 3 01:54:05 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 3 Mar 2009 01:54:05 +0100 (CET) Subject: [Python-checkins] r70117 - in python/branches/py3k/Python: compile.c symtable.c Message-ID: <20090303005405.DA2F61E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 3 01:54:05 2009 New Revision: 70117 Log: instead of hacking __locals__ in during bytecode generation, put it in the symtable Modified: python/branches/py3k/Python/compile.c python/branches/py3k/Python/symtable.c Modified: python/branches/py3k/Python/compile.c ============================================================================== --- python/branches/py3k/Python/compile.c (original) +++ python/branches/py3k/Python/compile.c Tue Mar 3 01:54:05 2009 @@ -1524,23 +1524,14 @@ static int compiler_class(struct compiler *c, stmt_ty s) { - static PyObject *locals = NULL; PyCodeObject *co; PyObject *str; - PySTEntryObject *ste; - int err, i; + int i; asdl_seq* decos = s->v.ClassDef.decorator_list; if (!compiler_decorators(c, decos)) return 0; - /* initialize statics */ - if (locals == NULL) { - locals = PyUnicode_InternFromString("__locals__"); - if (locals == NULL) - return 0; - } - /* ultimately generate code for: = __build_class__(, , *, **) where: @@ -1553,16 +1544,6 @@ This borrows from compiler_call. */ - /* 0. Create a fake argument named __locals__ */ - ste = PySymtable_Lookup(c->c_st, s); - if (ste == NULL) - return 0; - assert(PyList_Check(ste->ste_varnames)); - err = PyList_Append(ste->ste_varnames, locals); - Py_DECREF(ste); - if (err < 0) - return 0; - /* 1. compile the class body into a code object */ if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, s->lineno)) return 0; Modified: python/branches/py3k/Python/symtable.c ============================================================================== --- python/branches/py3k/Python/symtable.c (original) +++ python/branches/py3k/Python/symtable.c Tue Mar 3 01:54:05 2009 @@ -186,7 +186,8 @@ static identifier top = NULL, lambda = NULL, genexpr = NULL, - listcomp = NULL, setcomp = NULL, dictcomp = NULL, __class__ = NULL; + listcomp = NULL, setcomp = NULL, dictcomp = NULL, + __class__ = NULL, __locals__ = NULL; #define GET_IDENTIFIER(VAR) \ ((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR))) @@ -1050,7 +1051,9 @@ (void *)s, s->lineno)) return 0; if (!GET_IDENTIFIER(__class__) || - !symtable_add_def(st, __class__, DEF_LOCAL)) { + !symtable_add_def(st, __class__, DEF_LOCAL) || + !GET_IDENTIFIER(__locals__) || + !symtable_add_def(st, __locals__, DEF_PARAM)) { symtable_exit_block(st, s); return 0; } From buildbot at python.org Tue Mar 3 02:17:23 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 01:17:23 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090303011723.E97B41E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/368 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed compile sincerely, -The Buildbot From buildbot at python.org Tue Mar 3 02:21:37 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 01:21:37 +0000 Subject: [Python-checkins] buildbot failure in x86 XP-4 2.6 Message-ID: <20090303012159.255CF1E400C@bag.python.org> The Buildbot has detected a new failure of x86 XP-4 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20XP-4%202.6/builds/123 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: bolen-windows Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_bsddb3 test_subprocess sincerely, -The Buildbot From python-checkins at python.org Tue Mar 3 02:32:48 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 02:32:48 +0100 (CET) Subject: [Python-checkins] r70118 - python/branches/py3k/Lib/configparser.py Message-ID: <20090303013248.EDD151E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 02:32:48 2009 New Revision: 70118 Log: Fix bootstrapping problem where setup.py was using configparser before _collections had been built. Modified: python/branches/py3k/Lib/configparser.py Modified: python/branches/py3k/Lib/configparser.py ============================================================================== --- python/branches/py3k/Lib/configparser.py (original) +++ python/branches/py3k/Lib/configparser.py Tue Mar 3 02:32:48 2009 @@ -87,8 +87,13 @@ write the configuration state in .ini format """ +try: + from collections import OrderedDict as _default_dict +except ImportError: + # fallback for setup.py which hasn't yet built _collections + _default_dict = dict + import re -from collections import OrderedDict __all__ = ["NoSectionError", "DuplicateSectionError", "NoOptionError", "InterpolationError", "InterpolationDepthError", @@ -216,7 +221,7 @@ class RawConfigParser: - def __init__(self, defaults=None, dict_type=OrderedDict): + def __init__(self, defaults=None, dict_type=_default_dict): self._dict = dict_type self._sections = self._dict() self._defaults = self._dict() From buildbot at python.org Tue Mar 3 02:56:21 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 01:56:21 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090303015621.92DEA1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/355 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed compile sincerely, -The Buildbot From python-checkins at python.org Tue Mar 3 04:20:43 2009 From: python-checkins at python.org (kristjan.jonsson) Date: Tue, 3 Mar 2009 04:20:43 +0100 (CET) Subject: [Python-checkins] r70119 - in python/trunk/Modules: md5module.c shamodule.c Message-ID: <20090303032043.5EA191E4051@bag.python.org> Author: kristjan.jonsson Date: Tue Mar 3 04:20:42 2009 New Revision: 70119 Log: Fix SHA_new and MD5_new, that would crash if not given initial data Modified: python/trunk/Modules/md5module.c python/trunk/Modules/shamodule.c Modified: python/trunk/Modules/md5module.c ============================================================================== --- python/trunk/Modules/md5module.c (original) +++ python/trunk/Modules/md5module.c Tue Mar 3 04:20:42 2009 @@ -272,19 +272,21 @@ if (!PyArg_ParseTuple(args, "|O:new", &data_obj)) return NULL; - GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view, NULL); + if (data_obj) + GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view, NULL); if ((md5p = newmd5object()) == NULL) { - PyBuffer_Release(&view); + if (data_obj) + PyBuffer_Release(&view); return NULL; } if (data_obj) { md5_append(&md5p->md5, (unsigned char*)view.buf, Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); + PyBuffer_Release(&view); } - - PyBuffer_Release(&view); + return (PyObject *)md5p; } Modified: python/trunk/Modules/shamodule.c ============================================================================== --- python/trunk/Modules/shamodule.c (original) +++ python/trunk/Modules/shamodule.c Tue Mar 3 04:20:42 2009 @@ -548,10 +548,12 @@ return NULL; } - GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view, NULL); + if (data_obj) + GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view, NULL); if ((new = newSHAobject()) == NULL) { - PyBuffer_Release(&view); + if (data_obj) + PyBuffer_Release(&view); return NULL; } @@ -559,15 +561,16 @@ if (PyErr_Occurred()) { Py_DECREF(new); - PyBuffer_Release(&view); + if (data_obj) + PyBuffer_Release(&view); return NULL; } if (data_obj) { sha_update(new, (unsigned char*)view.buf, Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); + PyBuffer_Release(&view); } - PyBuffer_Release(&view); return (PyObject *)new; } From buildbot at python.org Tue Mar 3 04:51:21 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 03:51:21 +0000 Subject: [Python-checkins] buildbot failure in OS X x86 trunk Message-ID: <20090303035121.C92371E4002@bag.python.org> The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/201 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: kristjan.jonsson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_copy_reg make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 3 05:45:35 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 05:45:35 +0100 (CET) Subject: [Python-checkins] r70120 - in python/trunk: Doc/library/collections.rst Lib/collections.py Lib/test/test_collections.py Misc/NEWS Message-ID: <20090303044535.4EB721E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 05:45:34 2009 New Revision: 70120 Log: Backport PEP 372: OrderedDict() Modified: python/trunk/Doc/library/collections.rst python/trunk/Lib/collections.py python/trunk/Lib/test/test_collections.py python/trunk/Misc/NEWS Modified: python/trunk/Doc/library/collections.rst ============================================================================== --- python/trunk/Doc/library/collections.rst (original) +++ python/trunk/Doc/library/collections.rst Tue Mar 3 05:45:34 2009 @@ -16,7 +16,7 @@ __name__ = '' This module implements high-performance container datatypes. Currently, -there are three datatypes, :class:`Counter`, :class:`deque` and +there are three datatypes, :class:`Counter`, :class:`deque`, :class:`OrderedDict` and :class:`defaultdict`, and one datatype factory function, :func:`namedtuple`. The specialized containers provided in this module provide alternatives @@ -33,7 +33,7 @@ Added :func:`namedtuple` and added abstract base classes. .. versionchanged:: 2.7 - Added :class:`Counter`. + Added :class:`Counter` and :class:`OrderedDict`. In addition to containers, the collections module provides some ABCs (abstract base classes) that can be used to test whether a class @@ -826,3 +826,31 @@ `Named tuple recipe `_ adapted for Python 2.4. + + +:class:`OrderedDict` objects +---------------------------- + +Ordered dictionaries are just like regular dictionaries but they remember the +order that items were inserted. When iterating over an ordered dictionary, +the items are returned in the order their keys were first added. + +.. class:: OrderedDict([items]) + + Return an instance of a dict subclass, supporting the usual :class:`dict` + methods. An *OrderedDict* is a dict that remembers the order that keys + were first inserted. If a new entry overwrites an existing entry, the + original insertion position is left unchanged. Deleting an entry and + reinserting it will move it to the end. + + .. versionadded:: 2.7 + +The :meth:`popitem` method for ordered dictionaries returns and removes the +last added entry. The key/value pairs are returned in LIFO order. + +Equality tests between :class:`OrderedDict` objects are order-sensitive +and are implemented as ``list(od1.items())==list(od2.items())``. +Equality tests between :class:`OrderedDict` objects and other +:class:`Mapping` objects are order-insensitive like regular dictionaries. +This allows :class:`OrderedDict` objects to be substituted anywhere a +regular dictionary is used. Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Tue Mar 3 05:45:34 2009 @@ -1,4 +1,4 @@ -__all__ = ['Counter', 'deque', 'defaultdict', 'namedtuple'] +__all__ = ['Counter', 'deque', 'defaultdict', 'namedtuple', 'OrderedDict'] # For bootstrapping reasons, the collection ABCs are defined in _abcoll.py. # They should however be considered an integral part of collections.py. from _abcoll import * @@ -6,11 +6,101 @@ __all__ += _abcoll.__all__ from _collections import deque, defaultdict -from operator import itemgetter as _itemgetter +from operator import itemgetter as _itemgetter, eq as _eq from keyword import iskeyword as _iskeyword import sys as _sys import heapq as _heapq -from itertools import repeat as _repeat, chain as _chain, starmap as _starmap, ifilter as _ifilter +from itertools import repeat as _repeat, chain as _chain, starmap as _starmap, \ + ifilter as _ifilter, imap as _imap, izip as _izip + +################################################################################ +### OrderedDict +################################################################################ + +class OrderedDict(dict, MutableMapping): + + def __init__(self, *args, **kwds): + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + if not hasattr(self, '_keys'): + self._keys = [] + self.update(*args, **kwds) + + def clear(self): + del self._keys[:] + dict.clear(self) + + def __setitem__(self, key, value): + if key not in self: + self._keys.append(key) + dict.__setitem__(self, key, value) + + def __delitem__(self, key): + dict.__delitem__(self, key) + self._keys.remove(key) + + def __iter__(self): + return iter(self._keys) + + def __reversed__(self): + return reversed(self._keys) + + def popitem(self): + if not self: + raise KeyError('dictionary is empty') + key = self._keys.pop() + value = dict.pop(self, key) + return key, value + + def __reduce__(self): + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + inst_dict.pop('_keys', None) + return (self.__class__, (items,), inst_dict) + + setdefault = MutableMapping.setdefault + update = MutableMapping.update + pop = MutableMapping.pop + + def keys(self): + return self._keys[:] + + def values(self): + return map(self.__getitem__, self._keys) + + def items(self): + return zip(self._keys, self.values()) + + def iterkeys(self): + return iter(self._keys) + + def itervalues(self): + return _imap(self.__getitem__, self._keys) + + def iteritems(self): + return _izip(self._keys, _imap(self.__getitem__, self._keys)) + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, list(self.items())) + + def copy(self): + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + if isinstance(other, OrderedDict): + return len(self)==len(other) and all(_imap(_eq, self.items(), other.items())) + return dict.__eq__(self, other) + + ################################################################################ ### namedtuple Modified: python/trunk/Lib/test/test_collections.py ============================================================================== --- python/trunk/Lib/test/test_collections.py (original) +++ python/trunk/Lib/test/test_collections.py Tue Mar 3 05:45:34 2009 @@ -1,8 +1,11 @@ + import unittest, doctest +import inspect from test import test_support -from collections import namedtuple, Counter, Mapping +from collections import namedtuple, Counter, OrderedDict +from test import mapping_tests import pickle, cPickle, copy -from random import randrange +from random import randrange, shuffle import operator from collections import Hashable, Iterable, Iterator from collections import Sized, Container, Callable @@ -567,12 +570,198 @@ set_result = setop(set(p.elements()), set(q.elements())) self.assertEqual(counter_result, dict.fromkeys(set_result, 1)) +class TestOrderedDict(unittest.TestCase): + + def test_init(self): + with self.assertRaises(TypeError): + OrderedDict([('a', 1), ('b', 2)], None) # too many args + pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] + self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input + self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input + self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input + self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)], + c=3, e=5).items()), pairs) # mixed input + + # make sure no positional args conflict with possible kwdargs + self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args, + ['self']) + + # Make sure that direct calls to __init__ do not clear previous contents + d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)]) + d.__init__([('e', 5), ('f', 6)], g=7, d=4) + self.assertEqual(list(d.items()), + [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)]) + + def test_update(self): + with self.assertRaises(TypeError): + OrderedDict().update([('a', 1), ('b', 2)], None) # too many args + pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] + od = OrderedDict() + od.update(dict(pairs)) + self.assertEqual(sorted(od.items()), pairs) # dict input + od = OrderedDict() + od.update(**dict(pairs)) + self.assertEqual(sorted(od.items()), pairs) # kwds input + od = OrderedDict() + od.update(pairs) + self.assertEqual(list(od.items()), pairs) # pairs input + od = OrderedDict() + od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5) + self.assertEqual(list(od.items()), pairs) # mixed input + + # Make sure that direct calls to update do not clear previous contents + # add that updates items are not moved to the end + d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)]) + d.update([('e', 5), ('f', 6)], g=7, d=4) + self.assertEqual(list(d.items()), + [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)]) + + def test_clear(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + self.assertEqual(len(od), len(pairs)) + od.clear() + self.assertEqual(len(od), 0) + + def test_delitem(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + od = OrderedDict(pairs) + del od['a'] + self.assert_('a' not in od) + with self.assertRaises(KeyError): + del od['a'] + self.assertEqual(list(od.items()), pairs[:2] + pairs[3:]) + + def test_setitem(self): + od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)]) + od['c'] = 10 # existing element + od['f'] = 20 # new element + self.assertEqual(list(od.items()), + [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)]) + + def test_iterators(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + self.assertEqual(list(od), [t[0] for t in pairs]) + self.assertEqual(list(od.keys()), [t[0] for t in pairs]) + self.assertEqual(list(od.values()), [t[1] for t in pairs]) + self.assertEqual(list(od.items()), pairs) + self.assertEqual(list(reversed(od)), + [t[0] for t in reversed(pairs)]) + + def test_popitem(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + while pairs: + self.assertEqual(od.popitem(), pairs.pop()) + with self.assertRaises(KeyError): + od.popitem() + self.assertEqual(len(od), 0) + + def test_pop(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + shuffle(pairs) + while pairs: + k, v = pairs.pop() + self.assertEqual(od.pop(k), v) + with self.assertRaises(KeyError): + od.pop('xyz') + self.assertEqual(len(od), 0) + self.assertEqual(od.pop(k, 12345), 12345) + + def test_equality(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od1 = OrderedDict(pairs) + od2 = OrderedDict(pairs) + self.assertEqual(od1, od2) # same order implies equality + pairs = pairs[2:] + pairs[:2] + od2 = OrderedDict(pairs) + self.assertNotEqual(od1, od2) # different order implies inequality + # comparison to regular dict is not order sensitive + self.assertEqual(od1, dict(od2)) + self.assertEqual(dict(od2), od1) + # different length implied inequality + self.assertNotEqual(od1, OrderedDict(pairs[:-1])) + + def test_copying(self): + # Check that ordered dicts are copyable, deepcopyable, picklable, + # and have a repr/eval round-trip + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + od = OrderedDict(pairs) + update_test = OrderedDict() + update_test.update(od) + for i, dup in enumerate([ + od.copy(), + copy.copy(od), + copy.deepcopy(od), + pickle.loads(pickle.dumps(od, 0)), + pickle.loads(pickle.dumps(od, 1)), + pickle.loads(pickle.dumps(od, 2)), + pickle.loads(pickle.dumps(od, -1)), + eval(repr(od)), + update_test, + OrderedDict(od), + ]): + self.assert_(dup is not od) + self.assertEquals(dup, od) + self.assertEquals(list(dup.items()), list(od.items())) + self.assertEquals(len(dup), len(od)) + self.assertEquals(type(dup), type(od)) + + def test_repr(self): + od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]) + self.assertEqual(repr(od), + "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])") + self.assertEqual(eval(repr(od)), od) + self.assertEqual(repr(OrderedDict()), "OrderedDict()") + + def test_setdefault(self): + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + shuffle(pairs) + od = OrderedDict(pairs) + pair_order = list(od.items()) + self.assertEqual(od.setdefault('a', 10), 3) + # make sure order didn't change + self.assertEqual(list(od.items()), pair_order) + self.assertEqual(od.setdefault('x', 10), 10) + # make sure 'x' is added to the end + self.assertEqual(list(od.items())[-1], ('x', 10)) + + def test_reinsert(self): + # Given insert a, insert b, delete a, re-insert a, + # verify that a is now later than b. + od = OrderedDict() + od['a'] = 1 + od['b'] = 2 + del od['a'] + od['a'] = 1 + self.assertEqual(list(od.items()), [('b', 2), ('a', 1)]) + + + +class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol): + type2test = OrderedDict + +class MyOrderedDict(OrderedDict): + pass + +class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol): + type2test = MyOrderedDict + + import doctest, collections def test_main(verbose=None): NamedTupleDocs = doctest.DocTestSuite(module=collections) test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs, - TestCollectionABCs, TestCounter] + TestCollectionABCs, TestCounter, + TestOrderedDict, GeneralMappingTests, SubclassMappingTests] test_support.run_unittest(*test_classes) test_support.run_doctest(collections, verbose) Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 3 05:45:34 2009 @@ -168,6 +168,8 @@ Library ------- +- PEP 372: Added collections.OrderedDict(). + - Issue #4308: httplib.IncompleteRead's repr doesn't include all of the data all ready received. From python-checkins at python.org Tue Mar 3 05:51:25 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 05:51:25 +0100 (CET) Subject: [Python-checkins] r70121 - in python/trunk: Doc/library/collections.rst Lib/collections.py Misc/NEWS Message-ID: <20090303045125.6708F1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 05:51:24 2009 New Revision: 70121 Log: Backport 70106: Add OrderedDict support to collections.namedtuple(). Modified: python/trunk/Doc/library/collections.rst python/trunk/Lib/collections.py python/trunk/Misc/NEWS Modified: python/trunk/Doc/library/collections.rst ============================================================================== --- python/trunk/Doc/library/collections.rst (original) +++ python/trunk/Doc/library/collections.rst Tue Mar 3 05:51:24 2009 @@ -676,9 +676,9 @@ def __repr__(self): return 'Point(x=%r, y=%r)' % self - def _asdict(t): - 'Return a new dict which maps field names to their values' - return {'x': t[0], 'y': t[1]} + def _asdict(self): + 'Return a new OrderedDict which maps field names to their values' + return OrderedDict(zip(self._fields, self)) def _replace(self, **kwds): 'Return a new Point object replacing specified fields with new values' @@ -736,10 +736,14 @@ .. method:: somenamedtuple._asdict() - Return a new dict which maps field names to their corresponding values:: + Return a new :class:`OrderedDict` which maps field names to their corresponding + values:: >>> p._asdict() - {'x': 11, 'y': 22} + OrderedDict([('x', 11), ('y', 22)]) + + .. versionchanged 3.1 + Returns an :class:`OrderedDict` instead of a regular :class:`dict`. .. method:: somenamedtuple._replace(kwargs) Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Tue Mar 3 05:51:24 2009 @@ -164,7 +164,6 @@ numfields = len(field_names) argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes reprtxt = ', '.join('%s=%%r' % name for name in field_names) - dicttxt = ', '.join('%r: t[%d]' % (name, pos) for pos, name in enumerate(field_names)) template = '''class %(typename)s(tuple): '%(typename)s(%(argtxt)s)' \n __slots__ = () \n @@ -180,9 +179,9 @@ return result \n def __repr__(self): return '%(typename)s(%(reprtxt)s)' %% self \n - def _asdict(t): - 'Return a new dict which maps field names to their values' - return {%(dicttxt)s} \n + def _asdict(self): + 'Return a new OrderedDict which maps field names to their values' + return OrderedDict(zip(self._fields, self)) \n def _replace(self, **kwds): 'Return a new %(typename)s object replacing specified fields with new values' result = self._make(map(kwds.pop, %(field_names)r, self)) @@ -198,7 +197,8 @@ # Execute the template string in a temporary namespace and # support tracing utilities by setting a value for frame.f_globals['__name__'] - namespace = dict(itemgetter=_itemgetter, __name__='namedtuple_%s' % typename) + namespace = dict(itemgetter=_itemgetter, __name__='namedtuple_%s' % typename, + OrderedDict=OrderedDict) try: exec template in namespace except SyntaxError, e: Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 3 05:51:24 2009 @@ -170,6 +170,8 @@ - PEP 372: Added collections.OrderedDict(). +- The _asdict() for method for namedtuples now returns an OrderedDict(). + - Issue #4308: httplib.IncompleteRead's repr doesn't include all of the data all ready received. From python-checkins at python.org Tue Mar 3 06:00:38 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 06:00:38 +0100 (CET) Subject: [Python-checkins] r70122 - in python/trunk: Doc/library/configparser.rst Lib/ConfigParser.py Misc/NEWS Message-ID: <20090303050038.1FA5E1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 06:00:37 2009 New Revision: 70122 Log: Backport 70111: Let configparser use ordered dicts by default. Modified: python/trunk/Doc/library/configparser.rst python/trunk/Lib/ConfigParser.py python/trunk/Misc/NEWS Modified: python/trunk/Doc/library/configparser.rst ============================================================================== --- python/trunk/Doc/library/configparser.rst (original) +++ python/trunk/Doc/library/configparser.rst Tue Mar 3 06:00:37 2009 @@ -75,6 +75,9 @@ .. versionchanged:: 2.6 *dict_type* was added. + .. versionchanged:: 2.7 + The default *dict_type* is :class:`collections.OrderedDict`. + .. class:: ConfigParser([defaults[, dict_type]]) @@ -91,6 +94,14 @@ option names to lower case), the values ``foo %(bar)s`` and ``foo %(BAR)s`` are equivalent. + .. versionadded:: 2.3 + + .. versionchanged:: 2.6 + *dict_type* was added. + + .. versionchanged:: 2.7 + The default *dict_type* is :class:`collections.OrderedDict`. + .. class:: SafeConfigParser([defaults[, dict_type]]) @@ -103,6 +114,12 @@ .. versionadded:: 2.3 + .. versionchanged:: 2.6 + *dict_type* was added. + + .. versionchanged:: 2.7 + The default *dict_type* is :class:`collections.OrderedDict`. + .. exception:: NoSectionError Modified: python/trunk/Lib/ConfigParser.py ============================================================================== --- python/trunk/Lib/ConfigParser.py (original) +++ python/trunk/Lib/ConfigParser.py Tue Mar 3 06:00:37 2009 @@ -87,6 +87,12 @@ write the configuration state in .ini format """ +try: + from collections import OrderedDict as _default_dict +except ImportError: + # fallback for setup.py which hasn't yet built _collections + _default_dict = dict + import re __all__ = ["NoSectionError", "DuplicateSectionError", "NoOptionError", @@ -215,7 +221,7 @@ class RawConfigParser: - def __init__(self, defaults=None, dict_type=dict): + def __init__(self, defaults=None, dict_type=_default_dict): self._dict = dict_type self._sections = self._dict() self._defaults = self._dict() Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 3 06:00:37 2009 @@ -172,6 +172,8 @@ - The _asdict() for method for namedtuples now returns an OrderedDict(). +- The configparser module now defaults to using an ordered dictionary. + - Issue #4308: httplib.IncompleteRead's repr doesn't include all of the data all ready received. From python-checkins at python.org Tue Mar 3 06:11:56 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 06:11:56 +0100 (CET) Subject: [Python-checkins] r70123 - python/trunk/Doc/library/collections.rst Message-ID: <20090303051156.6383A1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 06:11:56 2009 New Revision: 70123 Log: Fix markup. Modified: python/trunk/Doc/library/collections.rst Modified: python/trunk/Doc/library/collections.rst ============================================================================== --- python/trunk/Doc/library/collections.rst (original) +++ python/trunk/Doc/library/collections.rst Tue Mar 3 06:11:56 2009 @@ -742,7 +742,7 @@ >>> p._asdict() OrderedDict([('x', 11), ('y', 22)]) - .. versionchanged 3.1 + .. versionchanged:: 2.7 Returns an :class:`OrderedDict` instead of a regular :class:`dict`. .. method:: somenamedtuple._replace(kwargs) From python-checkins at python.org Tue Mar 3 06:12:27 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 06:12:27 +0100 (CET) Subject: [Python-checkins] r70124 - python/branches/py3k/Doc/library/collections.rst Message-ID: <20090303051227.D489E1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 06:12:27 2009 New Revision: 70124 Log: Fix markup. Modified: python/branches/py3k/Doc/library/collections.rst Modified: python/branches/py3k/Doc/library/collections.rst ============================================================================== --- python/branches/py3k/Doc/library/collections.rst (original) +++ python/branches/py3k/Doc/library/collections.rst Tue Mar 3 06:12:27 2009 @@ -717,7 +717,7 @@ >>> p._asdict() OrderedDict([('x', 11), ('y', 22)]) - .. versionchanged 3.1 + .. versionchanged:: 3.1 Returns an :class:`OrderedDict` instead of a regular :class:`dict`. .. method:: somenamedtuple._replace(kwargs) From buildbot at python.org Tue Mar 3 06:31:13 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 05:31:13 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu trunk Message-ID: <20090303053113.A091E1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%20trunk/builds/932 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Tue Mar 3 07:00:01 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 06:00:01 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090303060001.705A01E400C@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/209 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Tue Mar 3 07:02:54 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 06:02:54 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090303060254.9B7391E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/701 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 3 07:52:34 2009 From: python-checkins at python.org (kristjan.jonsson) Date: Tue, 3 Mar 2009 07:52:34 +0100 (CET) Subject: [Python-checkins] r70125 - python/branches/py3k/Modules/posixmodule.c Message-ID: <20090303065234.F1CD21E4002@bag.python.org> Author: kristjan.jonsson Date: Tue Mar 3 07:52:34 2009 New Revision: 70125 Log: Issue5407 Broken Py3.1 release build in Visual Studio 2005 The CRT runtime structure that holds ioinfo doesn't appear to match the decleration from the headers provided with the Visual Studio 2005 crt sources. In Release, an extra 8 bytes follow the final BOOL. I cannot explain this, but the code works now, both in 32 bits and 64 Modified: python/branches/py3k/Modules/posixmodule.c Modified: python/branches/py3k/Modules/posixmodule.c ============================================================================== --- python/branches/py3k/Modules/posixmodule.c (original) +++ python/branches/py3k/Modules/posixmodule.c Tue Mar 3 07:52:34 2009 @@ -382,6 +382,12 @@ char pipech2[2]; __int64 startpos; BOOL utf8translations; +#ifndef _DEBUG + /* padding hack. 8 byte extra length observed at + * runtime, for 32 and 64 bits when not in _DEBUG + */ + __int32 _padding[2]; +#endif #endif /* _SAFECRT_IMPL */ } ioinfo; #endif From python-checkins at python.org Tue Mar 3 08:12:09 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 08:12:09 +0100 (CET) Subject: [Python-checkins] r70126 - python/trunk/Lib/test/test_collections.py Message-ID: <20090303071209.5141C1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 08:12:09 2009 New Revision: 70126 Log: Beef-up tests. Modified: python/trunk/Lib/test/test_collections.py Modified: python/trunk/Lib/test/test_collections.py ============================================================================== --- python/trunk/Lib/test/test_collections.py (original) +++ python/trunk/Lib/test/test_collections.py Tue Mar 3 08:12:09 2009 @@ -645,9 +645,12 @@ shuffle(pairs) od = OrderedDict(pairs) self.assertEqual(list(od), [t[0] for t in pairs]) - self.assertEqual(list(od.keys()), [t[0] for t in pairs]) - self.assertEqual(list(od.values()), [t[1] for t in pairs]) - self.assertEqual(list(od.items()), pairs) + self.assertEqual(od.keys()[:], [t[0] for t in pairs]) + self.assertEqual(od.values()[:], [t[1] for t in pairs]) + self.assertEqual(od.items()[:], pairs) + self.assertEqual(list(od.iterkeys()), [t[0] for t in pairs]) + self.assertEqual(list(od.itervalues()), [t[1] for t in pairs]) + self.assertEqual(list(od.iteritems()), pairs) self.assertEqual(list(reversed(od)), [t[0] for t in reversed(pairs)]) From buildbot at python.org Tue Mar 3 08:40:55 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 07:40:55 +0000 Subject: [Python-checkins] buildbot failure in OS X x86 trunk Message-ID: <20090303074055.45A681E4002@bag.python.org> The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/204 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/threading.py", line 477, in run self.__target(*self.__args, **self.__kwargs) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/bsddb/test/test_thread.py", line 306, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/bsddb/dbutils.py", line 68, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') 1 test failed: test_logging make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 3 08:41:50 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 07:41:50 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo trunk Message-ID: <20090303074150.71F1A1E403C@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%20gentoo%20trunk/builds/4699 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 3 08:49:03 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 3 Mar 2009 08:49:03 +0100 (CET) Subject: [Python-checkins] r70127 - in python/branches/py3k/Modules: md5module.c sha1module.c sha256module.c sha512module.c Message-ID: <20090303074903.306261E4027@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 3 08:49:01 2009 New Revision: 70127 Log: Fixed memory leak on failure. This is related to issue5403 but won't crash on py3k. Modified: python/branches/py3k/Modules/md5module.c python/branches/py3k/Modules/sha1module.c python/branches/py3k/Modules/sha256module.c python/branches/py3k/Modules/sha512module.c Modified: python/branches/py3k/Modules/md5module.c ============================================================================== --- python/branches/py3k/Modules/md5module.c (original) +++ python/branches/py3k/Modules/md5module.c Tue Mar 3 08:49:01 2009 @@ -526,18 +526,23 @@ if (data_obj) GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf); - if ((new = newMD5object()) == NULL) + if ((new = newMD5object()) == NULL) { + if (data_obj) + PyBuffer_Release(&buf); return NULL; + } md5_init(&new->hash_state); if (PyErr_Occurred()) { Py_DECREF(new); + if (data_obj) + PyBuffer_Release(&buf); return NULL; } if (data_obj) { md5_process(&new->hash_state, buf.buf, buf.len); - PyBuffer_Release(&buf); + PyBuffer_Release(&buf); } return (PyObject *)new; Modified: python/branches/py3k/Modules/sha1module.c ============================================================================== --- python/branches/py3k/Modules/sha1module.c (original) +++ python/branches/py3k/Modules/sha1module.c Tue Mar 3 08:49:01 2009 @@ -502,18 +502,23 @@ if (data_obj) GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf); - if ((new = newSHA1object()) == NULL) + if ((new = newSHA1object()) == NULL) { + if (data_obj) + PyBuffer_Release(&buf); return NULL; + } sha1_init(&new->hash_state); if (PyErr_Occurred()) { Py_DECREF(new); + if (data_obj) + PyBuffer_Release(&buf); return NULL; } if (data_obj) { sha1_process(&new->hash_state, buf.buf, buf.len); - PyBuffer_Release(&buf); + PyBuffer_Release(&buf); } return (PyObject *)new; Modified: python/branches/py3k/Modules/sha256module.c ============================================================================== --- python/branches/py3k/Modules/sha256module.c (original) +++ python/branches/py3k/Modules/sha256module.c Tue Mar 3 08:49:01 2009 @@ -629,13 +629,18 @@ if (data_obj) GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf); - if ((new = newSHA256object()) == NULL) + if ((new = newSHA256object()) == NULL) { + if (data_obj) + PyBuffer_Release(&buf); return NULL; + } sha_init(new); if (PyErr_Occurred()) { Py_DECREF(new); + if (data_obj) + PyBuffer_Release(&buf); return NULL; } if (data_obj) { @@ -665,13 +670,18 @@ if (data_obj) GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf); - if ((new = newSHA224object()) == NULL) + if ((new = newSHA224object()) == NULL) { + if (data_obj) + PyBuffer_Release(&buf); return NULL; + } sha224_init(new); if (PyErr_Occurred()) { Py_DECREF(new); + if (data_obj) + PyBuffer_Release(&buf); return NULL; } if (data_obj) { Modified: python/branches/py3k/Modules/sha512module.c ============================================================================== --- python/branches/py3k/Modules/sha512module.c (original) +++ python/branches/py3k/Modules/sha512module.c Tue Mar 3 08:49:01 2009 @@ -695,13 +695,18 @@ if (data_obj) GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf); - if ((new = newSHA512object()) == NULL) + if ((new = newSHA512object()) == NULL) { + if (data_obj) + PyBuffer_Release(&buf); return NULL; + } sha512_init(new); if (PyErr_Occurred()) { Py_DECREF(new); + if (data_obj) + PyBuffer_Release(&buf); return NULL; } if (data_obj) { @@ -731,13 +736,18 @@ if (data_obj) GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf); - if ((new = newSHA384object()) == NULL) + if ((new = newSHA384object()) == NULL) { + if (data_obj) + PyBuffer_Release(&buf); return NULL; + } sha384_init(new); if (PyErr_Occurred()) { Py_DECREF(new); + if (data_obj) + PyBuffer_Release(&buf); return NULL; } if (data_obj) { From python-checkins at python.org Tue Mar 3 08:54:32 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 3 Mar 2009 08:54:32 +0100 (CET) Subject: [Python-checkins] r70128 - python/branches/py3k Message-ID: <20090303075432.94E001E4002@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 3 08:54:32 2009 New Revision: 70128 Log: Blocked revisions 70119 via svnmerge ........ r70119 | kristjan.jonsson | 2009-03-03 12:20:42 +0900 | 1 line Fix SHA_new and MD5_new, that would crash if not given initial data ........ Modified: python/branches/py3k/ (props changed) From buildbot at python.org Tue Mar 3 09:25:51 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 08:25:51 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090303082551.71DAB1E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/211 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 3 10:07:52 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 09:07:52 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090303090752.843621E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/399 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Tue Mar 3 10:25:39 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 09:25:39 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090303092539.A62B51E4026@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/372 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From python-checkins at python.org Tue Mar 3 11:52:50 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 11:52:50 +0100 (CET) Subject: [Python-checkins] r70129 - in python/branches/py3k: Lib/test/test_dict.py Misc/NEWS Objects/dictobject.c Message-ID: <20090303105250.1145F1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 11:52:49 2009 New Revision: 70129 Log: Give dict views a helpful __repr__. Modified: python/branches/py3k/Lib/test/test_dict.py python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/dictobject.c Modified: python/branches/py3k/Lib/test/test_dict.py ============================================================================== --- python/branches/py3k/Lib/test/test_dict.py (original) +++ python/branches/py3k/Lib/test/test_dict.py Tue Mar 3 11:52:49 2009 @@ -36,16 +36,16 @@ k = d.keys() self.assert_('a' in d) self.assert_('b' in d) - self.assertRaises(TypeError, d.keys, None) + self.assertEqual(repr(dict(a=1).keys()), "dict_keys(['a'])") def test_values(self): d = {} self.assertEqual(set(d.values()), set()) d = {1:2} self.assertEqual(set(d.values()), {2}) - self.assertRaises(TypeError, d.values, None) + self.assertEqual(repr(dict(a=1).values()), "dict_values([1])") def test_items(self): d = {} @@ -53,8 +53,8 @@ d = {1:2} self.assertEqual(set(d.items()), {(1, 2)}) - self.assertRaises(TypeError, d.items, None) + self.assertEqual(repr(dict(a=1).items()), "dict_items([('a', 1)])") def test_contains(self): d = {} Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 3 11:52:49 2009 @@ -13,6 +13,9 @@ ----------------- ======= + +- Give dict views an informative __repr__. + - Issue #5247: Improve error message when unknown format codes are used when using str.format() with str, int, and float arguments. Modified: python/branches/py3k/Objects/dictobject.c ============================================================================== --- python/branches/py3k/Objects/dictobject.c (original) +++ python/branches/py3k/Objects/dictobject.c Tue Mar 3 11:52:49 2009 @@ -2563,6 +2563,21 @@ return result; } +static PyObject * +dictview_repr(dictviewobject *dv) +{ + PyObject *seq; + PyObject *result; + + seq = PySequence_List((PyObject *)dv); + if (seq == NULL) + return NULL; + + result = PyUnicode_FromFormat("%s(%R)", Py_TYPE(dv)->tp_name, seq); + Py_DECREF(seq); + return result; +} + /*** dict_keys ***/ static PyObject * @@ -2700,7 +2715,7 @@ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - 0, /* tp_repr */ + (reprfunc)dictview_repr, /* tp_repr */ &dictviews_as_number, /* tp_as_number */ &dictkeys_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -2784,7 +2799,7 @@ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - 0, /* tp_repr */ + (reprfunc)dictview_repr, /* tp_repr */ &dictviews_as_number, /* tp_as_number */ &dictitems_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -2849,7 +2864,7 @@ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - 0, /* tp_repr */ + (reprfunc)dictview_repr, /* tp_repr */ 0, /* tp_as_number */ &dictvalues_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ From buildbot at python.org Tue Mar 3 12:46:20 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 11:46:20 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090303114621.069481E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/374 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From buildbot at python.org Tue Mar 3 12:54:23 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 11:54:23 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090303115424.06BBB1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/359 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 3 21:47:29 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 21:47:29 +0100 (CET) Subject: [Python-checkins] r70130 - python/branches/py3k/Lib/collections.py Message-ID: <20090303204729.74C3C1E4024@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 21:47:29 2009 New Revision: 70130 Log: Make the underlying data structure more private. Modified: python/branches/py3k/Lib/collections.py Modified: python/branches/py3k/Lib/collections.py ============================================================================== --- python/branches/py3k/Lib/collections.py (original) +++ python/branches/py3k/Lib/collections.py Tue Mar 3 21:47:29 2009 @@ -22,40 +22,44 @@ def __init__(self, *args, **kwds): if len(args) > 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) - if not hasattr(self, '_keys'): - self._keys = [] + try: + self.__keys + except AttributeError: + # Note the underlying data structure for this class is likely to + # change in the future. Do not rely on it or access it directly. + self.__keys = [] self.update(*args, **kwds) def clear(self): - del self._keys[:] + del self.__keys[:] dict.clear(self) def __setitem__(self, key, value): if key not in self: - self._keys.append(key) + self.__keys.append(key) dict.__setitem__(self, key, value) def __delitem__(self, key): dict.__delitem__(self, key) - self._keys.remove(key) + self.__keys.remove(key) def __iter__(self): - return iter(self._keys) + return iter(self.__keys) def __reversed__(self): - return reversed(self._keys) + return reversed(self.__keys) def popitem(self): if not self: raise KeyError('dictionary is empty') - key = self._keys.pop() + key = self.__keys.pop() value = dict.pop(self, key) return key, value def __reduce__(self): items = [[k, self[k]] for k in self] inst_dict = vars(self).copy() - inst_dict.pop('_keys', None) + inst_dict.pop('__keys', None) return (self.__class__, (items,), inst_dict) setdefault = MutableMapping.setdefault From python-checkins at python.org Tue Mar 3 21:53:51 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 21:53:51 +0100 (CET) Subject: [Python-checkins] r70131 - python/trunk/Lib/collections.py Message-ID: <20090303205351.802431E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 21:53:51 2009 New Revision: 70131 Log: Make the underlying data structure more private. Modified: python/trunk/Lib/collections.py Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Tue Mar 3 21:53:51 2009 @@ -22,40 +22,44 @@ def __init__(self, *args, **kwds): if len(args) > 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) - if not hasattr(self, '_keys'): - self._keys = [] + try: + self.__keys + except AttributeError: + # Note the underlying data structure for this class is likely to + # change in the future. Do not rely on it or access it directly. + self.__keys = [] self.update(*args, **kwds) def clear(self): - del self._keys[:] + del self.__keys[:] dict.clear(self) def __setitem__(self, key, value): if key not in self: - self._keys.append(key) + self.__keys.append(key) dict.__setitem__(self, key, value) def __delitem__(self, key): dict.__delitem__(self, key) - self._keys.remove(key) + self.__keys.remove(key) def __iter__(self): - return iter(self._keys) + return iter(self.__keys) def __reversed__(self): - return reversed(self._keys) + return reversed(self.__keys) def popitem(self): if not self: raise KeyError('dictionary is empty') - key = self._keys.pop() + key = self.__keys.pop() value = dict.pop(self, key) return key, value def __reduce__(self): items = [[k, self[k]] for k in self] inst_dict = vars(self).copy() - inst_dict.pop('_keys', None) + inst_dict.pop('__keys', None) return (self.__class__, (items,), inst_dict) setdefault = MutableMapping.setdefault @@ -63,22 +67,22 @@ pop = MutableMapping.pop def keys(self): - return self._keys[:] + return self.__keys[:] def values(self): - return map(self.__getitem__, self._keys) + return map(self.__getitem__, self.__keys) def items(self): - return zip(self._keys, self.values()) + return zip(self.__keys, self.values()) def iterkeys(self): - return iter(self._keys) + return iter(self.__keys) def itervalues(self): - return _imap(self.__getitem__, self._keys) + return _imap(self.__getitem__, self.__keys) def iteritems(self): - return _izip(self._keys, _imap(self.__getitem__, self._keys)) + return _izip(self.__keys, _imap(self.__getitem__, self.__keys)) def __repr__(self): if not self: From python-checkins at python.org Tue Mar 3 22:13:51 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 22:13:51 +0100 (CET) Subject: [Python-checkins] r70132 - python/trunk/Lib/collections.py Message-ID: <20090303211351.BB8FB1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 22:13:51 2009 New Revision: 70132 Log: Minor simplification. Modified: python/trunk/Lib/collections.py Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Tue Mar 3 22:13:51 2009 @@ -87,7 +87,7 @@ def __repr__(self): if not self: return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, list(self.items())) + return '%s(%r)' % (self.__class__.__name__, self.items()) def copy(self): return self.__class__(self) From python-checkins at python.org Tue Mar 3 22:23:32 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 3 Mar 2009 22:23:32 +0100 (CET) Subject: [Python-checkins] r70133 - python/branches/io-c/Lib/test/test_memoryio.py Message-ID: <20090303212332.89BB81E4033@bag.python.org> Author: benjamin.peterson Date: Tue Mar 3 22:23:32 2009 New Revision: 70133 Log: fix test_newline_property on _pyio.StringIO Modified: python/branches/io-c/Lib/test/test_memoryio.py Modified: python/branches/io-c/Lib/test/test_memoryio.py ============================================================================== --- python/branches/io-c/Lib/test/test_memoryio.py (original) +++ python/branches/io-c/Lib/test/test_memoryio.py Tue Mar 3 22:23:32 2009 @@ -417,6 +417,25 @@ # TextIO-specific behaviour. + def test_newlines_property(self): + memio = self.ioclass(newline=None) + # The C StringIO decodes newlines in write() calls, but the Python + # implementation only does when reading. This function forces them to + # be decoded for testing. + def force_decode(): + memio.seek(0) + memio.read() + self.assertEqual(memio.newlines, None) + memio.write("a\n") + force_decode() + self.assertEqual(memio.newlines, "\n") + memio.write("b\r\n") + force_decode() + self.assertEqual(memio.newlines, ("\n", "\r\n")) + memio.write("c\rd") + force_decode() + self.assertEqual(memio.newlines, ("\r", "\n", "\r\n")) + def test_relative_seek(self): memio = self.ioclass() @@ -515,17 +534,6 @@ self.assertEqual(memio.tell(), len(buf) * 2) self.assertEqual(memio.getvalue(), buf + buf) - # XXX This test fails with the Python version of io.StringIO - def test_newlines_property(self): - memio = self.ioclass(newline=None) - self.assertEqual(memio.newlines, None) - memio.write("a\n") - self.assertEqual(memio.newlines, "\n") - memio.write("b\r\n") - self.assertEqual(memio.newlines, ("\n", "\r\n")) - memio.write("c\rd") - self.assertEqual(memio.newlines, ("\r", "\n", "\r\n")) - def test_main(): tests = [PyBytesIOTest, PyStringIOTest, CBytesIOTest, CStringIOTest] From martin at v.loewis.de Tue Mar 3 22:29:06 2009 From: martin at v.loewis.de (=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=) Date: Tue, 03 Mar 2009 22:29:06 +0100 Subject: [Python-checkins] r70125 - python/branches/py3k/Modules/posixmodule.c In-Reply-To: <20090303065234.F1CD21E4002@bag.python.org> References: <20090303065234.F1CD21E4002@bag.python.org> Message-ID: <49ADA122.8050103@v.loewis.de> > The CRT runtime structure that holds ioinfo doesn't appear to match > the decleration from the headers provided with the Visual Studio 2005 > crt sources. In Release, an extra 8 bytes follow the final BOOL. I > cannot explain this, but the code works now, both in 32 bits and 64 Please don't commit code that you cannot explain in the future. Thanks, Martin From python-checkins at python.org Tue Mar 3 22:31:23 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 3 Mar 2009 22:31:23 +0100 (CET) Subject: [Python-checkins] r70134 - python/branches/py3k Message-ID: <20090303213123.0E1881E40BC@bag.python.org> Author: benjamin.peterson Date: Tue Mar 3 22:31:22 2009 New Revision: 70134 Log: Blocked revisions 70081,70120-70123,70126,70131-70132 via svnmerge ........ r70081 | raymond.hettinger | 2009-02-28 20:04:32 -0600 (Sat, 28 Feb 2009) | 1 line Fix docs for ConfigParser. ........ r70120 | raymond.hettinger | 2009-03-02 22:45:34 -0600 (Mon, 02 Mar 2009) | 1 line Backport PEP 372: OrderedDict() ........ r70121 | raymond.hettinger | 2009-03-02 22:51:24 -0600 (Mon, 02 Mar 2009) | 3 lines Backport 70106: Add OrderedDict support to collections.namedtuple(). ........ r70122 | raymond.hettinger | 2009-03-02 23:00:37 -0600 (Mon, 02 Mar 2009) | 3 lines Backport 70111: Let configparser use ordered dicts by default. ........ r70123 | raymond.hettinger | 2009-03-02 23:11:56 -0600 (Mon, 02 Mar 2009) | 1 line Fix markup. ........ r70126 | raymond.hettinger | 2009-03-03 01:12:09 -0600 (Tue, 03 Mar 2009) | 1 line Beef-up tests. ........ r70131 | raymond.hettinger | 2009-03-03 14:53:51 -0600 (Tue, 03 Mar 2009) | 1 line Make the underlying data structure more private. ........ r70132 | raymond.hettinger | 2009-03-03 15:13:51 -0600 (Tue, 03 Mar 2009) | 1 line Minor simplification. ........ Modified: python/branches/py3k/ (props changed) From g.brandl at gmx.net Tue Mar 3 22:47:19 2009 From: g.brandl at gmx.net (Georg Brandl) Date: Tue, 03 Mar 2009 22:47:19 +0100 Subject: [Python-checkins] r70131 - python/trunk/Lib/collections.py In-Reply-To: <20090303205351.802431E4002@bag.python.org> References: <20090303205351.802431E4002@bag.python.org> Message-ID: raymond.hettinger schrieb: > Author: raymond.hettinger > Date: Tue Mar 3 21:53:51 2009 > New Revision: 70131 > > Log: > Make the underlying data structure more private. > def __reduce__(self): > items = [[k, self[k]] for k in self] > inst_dict = vars(self).copy() > - inst_dict.pop('_keys', None) > + inst_dict.pop('__keys', None) Shouldn't that be '_OrderedDict__keys'? Georg From python-checkins at python.org Tue Mar 3 22:47:30 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 3 Mar 2009 22:47:30 +0100 (CET) Subject: [Python-checkins] r70135 - in python/branches/io-c: Doc/library/io.rst Lib/_pyio.py Message-ID: <20090303214730.6C4101E4012@bag.python.org> Author: benjamin.peterson Date: Tue Mar 3 22:47:30 2009 New Revision: 70135 Log: fix typos and inconsistencies. thanks to Daniel Diniz Modified: python/branches/io-c/Doc/library/io.rst python/branches/io-c/Lib/_pyio.py Modified: python/branches/io-c/Doc/library/io.rst ============================================================================== --- python/branches/io-c/Doc/library/io.rst (original) +++ python/branches/io-c/Doc/library/io.rst Tue Mar 3 22:47:30 2009 @@ -508,7 +508,7 @@ The constructor creates a :class:`BufferedWriter` for the given writeable *raw* stream. If the *buffer_size* is not given, it defaults to - :data:`DEAFULT_BUFFER_SIZE`. If *max_buffer_size* is omitted, it defaults to + :data:`DEFAULT_BUFFER_SIZE`. If *max_buffer_size* is omitted, it defaults to twice the buffer size. :class:`BufferedWriter` provides or overrides these methods in addition to Modified: python/branches/io-c/Lib/_pyio.py ============================================================================== --- python/branches/io-c/Lib/_pyio.py (original) +++ python/branches/io-c/Lib/_pyio.py Tue Mar 3 22:47:30 2009 @@ -263,7 +263,7 @@ stream. IOBase also supports the :keyword:`with` statement. In this example, - fp is closed after the suite of the with statment is complete: + fp is closed after the suite of the with statement is complete: with open('spam.txt', 'r') as fp: fp.write('Spam and eggs!') @@ -960,7 +960,7 @@ The constructor creates a BufferedWriter for the given writeable raw stream. If the buffer_size is not given, it defaults to - DEAFULT_BUFFER_SIZE. If max_buffer_size is omitted, it defaults to + DEFAULT_BUFFER_SIZE. If max_buffer_size is omitted, it defaults to twice the buffer size. """ @@ -1725,7 +1725,9 @@ line = self._get_decoded_chars() start = 0 - decoder = self._decoder or self._get_decoder() + # Make the decoder if it doesn't already exist. + if not self._decoder: + self._get_decoder() pos = endpos = None while True: @@ -1780,8 +1782,7 @@ endpos = limit # reached length limit break - # No line ending seen yet - get more data - more_line = '' + # No line ending seen yet - get more data' while self._read_chunk(): if self._decoded_chars: break From python-checkins at python.org Tue Mar 3 23:05:58 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 3 Mar 2009 23:05:58 +0100 (CET) Subject: [Python-checkins] r70136 - in python/trunk/Modules: sha256module.c sha512module.c Message-ID: <20090303220558.8C8011E400C@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 3 23:05:57 2009 New Revision: 70136 Log: Fixed memory leak. Modified: python/trunk/Modules/sha256module.c python/trunk/Modules/sha512module.c Modified: python/trunk/Modules/sha256module.c ============================================================================== --- python/trunk/Modules/sha256module.c (original) +++ python/trunk/Modules/sha256module.c Tue Mar 3 23:05:57 2009 @@ -629,13 +629,18 @@ if (data_obj) GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf, NULL); - if ((new = newSHA256object()) == NULL) + if ((new = newSHA256object()) == NULL) { + if (data_obj) + PyBuffer_Release(&buf); return NULL; + } sha_init(new); if (PyErr_Occurred()) { Py_DECREF(new); + if (data_obj) + PyBuffer_Release(&buf); return NULL; } if (data_obj) { @@ -665,13 +670,18 @@ if (data_obj) GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf, NULL); - if ((new = newSHA224object()) == NULL) + if ((new = newSHA224object()) == NULL) { + if (data_obj) + PyBuffer_Release(&buf); return NULL; + } sha224_init(new); if (PyErr_Occurred()) { Py_DECREF(new); + if (data_obj) + PyBuffer_Release(&buf); return NULL; } if (data_obj) { Modified: python/trunk/Modules/sha512module.c ============================================================================== --- python/trunk/Modules/sha512module.c (original) +++ python/trunk/Modules/sha512module.c Tue Mar 3 23:05:57 2009 @@ -695,13 +695,18 @@ if (data_obj) GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf, NULL); - if ((new = newSHA512object()) == NULL) + if ((new = newSHA512object()) == NULL) { + if (data_obj) + PyBuffer_Release(&buf); return NULL; + } sha512_init(new); if (PyErr_Occurred()) { Py_DECREF(new); + if (data_obj) + PyBuffer_Release(&buf); return NULL; } if (data_obj) { @@ -731,13 +736,18 @@ if (data_obj) GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf, NULL); - if ((new = newSHA384object()) == NULL) + if ((new = newSHA384object()) == NULL) { + if (data_obj) + PyBuffer_Release(&buf); return NULL; + } sha384_init(new); if (PyErr_Occurred()) { Py_DECREF(new); + if (data_obj) + PyBuffer_Release(&buf); return NULL; } if (data_obj) { From python-checkins at python.org Tue Mar 3 23:18:15 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 3 Mar 2009 23:18:15 +0100 (CET) Subject: [Python-checkins] r70137 - in python/trunk: Lib/subprocess.py Misc/NEWS PC/_subprocess.c Message-ID: <20090303221815.121541E403E@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 3 23:18:14 2009 New Revision: 70137 Log: Issue #5179: Fixed subprocess handle leak on failure on windows. Modified: python/trunk/Lib/subprocess.py python/trunk/Misc/NEWS python/trunk/PC/_subprocess.c Modified: python/trunk/Lib/subprocess.py ============================================================================== --- python/trunk/Lib/subprocess.py (original) +++ python/trunk/Lib/subprocess.py Tue Mar 3 23:18:14 2009 @@ -642,21 +642,13 @@ c2pread, c2pwrite, errread, errwrite) - # On Windows, you cannot just redirect one or two handles: You - # 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. if mswindows: - if stdin is None and p2cwrite is not None: - os.close(p2cwrite) - p2cwrite = None - if stdout is None and c2pread is not None: - os.close(c2pread) - c2pread = None - if stderr is None and errread is not None: - os.close(errread) - errread = None + if p2cwrite is not None: + p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0) + if c2pread is not None: + c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0) + if errread is not None: + errread = msvcrt.open_osfhandle(errread.Detach(), 0) if p2cwrite is not None: self.stdin = os.fdopen(p2cwrite, 'wb', bufsize) @@ -740,13 +732,10 @@ if stdin is None: p2cread = GetStdHandle(STD_INPUT_HANDLE) - if p2cread is not None: - pass - elif stdin is None or stdin == PIPE: + if p2cread is None: + p2cread, _ = CreatePipe(None, 0) + elif stdin == PIPE: p2cread, p2cwrite = CreatePipe(None, 0) - # Detach and turn into fd - p2cwrite = p2cwrite.Detach() - p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0) elif isinstance(stdin, int): p2cread = msvcrt.get_osfhandle(stdin) else: @@ -756,13 +745,10 @@ if stdout is None: c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE) - if c2pwrite is not None: - pass - elif stdout is None or stdout == PIPE: + if c2pwrite is None: + _, c2pwrite = CreatePipe(None, 0) + elif stdout == PIPE: c2pread, c2pwrite = CreatePipe(None, 0) - # Detach and turn into fd - c2pread = c2pread.Detach() - c2pread = msvcrt.open_osfhandle(c2pread, 0) elif isinstance(stdout, int): c2pwrite = msvcrt.get_osfhandle(stdout) else: @@ -772,13 +758,10 @@ if stderr is None: errwrite = GetStdHandle(STD_ERROR_HANDLE) - if errwrite is not None: - pass - elif stderr is None or stderr == PIPE: + if errwrite is None: + _, errwrite = CreatePipe(None, 0) + elif stderr == PIPE: errread, errwrite = CreatePipe(None, 0) - # Detach and turn into fd - errread = errread.Detach() - errread = msvcrt.open_osfhandle(errread, 0) elif stderr == STDOUT: errwrite = c2pwrite elif isinstance(stderr, int): Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 3 23:18:14 2009 @@ -168,6 +168,8 @@ Library ------- +- Issue #5179: Fixed subprocess handle leak on failure on windows. + - PEP 372: Added collections.OrderedDict(). - The _asdict() for method for namedtuples now returns an OrderedDict(). Modified: python/trunk/PC/_subprocess.c ============================================================================== --- python/trunk/PC/_subprocess.c (original) +++ python/trunk/PC/_subprocess.c Tue Mar 3 23:18:14 2009 @@ -87,7 +87,7 @@ handle = self->handle; - self->handle = NULL; + self->handle = INVALID_HANDLE_VALUE; /* note: return the current handle, as an integer */ return HANDLE_TO_PYNUM(handle); From python-checkins at python.org Tue Mar 3 23:19:39 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 3 Mar 2009 23:19:39 +0100 (CET) Subject: [Python-checkins] r70138 - python/branches/py3k Message-ID: <20090303221939.1142D1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 3 23:19:38 2009 New Revision: 70138 Log: Blocked revisions 70136 via svnmerge ........ r70136 | hirokazu.yamamoto | 2009-03-04 07:05:57 +0900 | 1 line Fixed memory leak. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Tue Mar 3 23:20:56 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 23:20:56 +0100 (CET) Subject: [Python-checkins] r70139 - python/branches/py3k/Lib/collections.py Message-ID: <20090303222056.CAFE41E4037@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 23:20:56 2009 New Revision: 70139 Log: Fix-up __reduce__ which could not reach the __keys variable indirectly.' Modified: python/branches/py3k/Lib/collections.py Modified: python/branches/py3k/Lib/collections.py ============================================================================== --- python/branches/py3k/Lib/collections.py (original) +++ python/branches/py3k/Lib/collections.py Tue Mar 3 23:20:56 2009 @@ -58,9 +58,13 @@ def __reduce__(self): items = [[k, self[k]] for k in self] + tmp = self.__keys + del self.__keys inst_dict = vars(self).copy() - inst_dict.pop('__keys', None) - return (self.__class__, (items,), inst_dict) + self.__keys = tmp + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) setdefault = MutableMapping.setdefault update = MutableMapping.update From python-checkins at python.org Tue Mar 3 23:21:10 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 3 Mar 2009 23:21:10 +0100 (CET) Subject: [Python-checkins] r70140 - python/branches/io-c/Lib/test/test_memoryio.py Message-ID: <20090303222110.9B35D1E4036@bag.python.org> Author: benjamin.peterson Date: Tue Mar 3 23:21:10 2009 New Revision: 70140 Log: add the test from #5266 Modified: python/branches/io-c/Lib/test/test_memoryio.py Modified: python/branches/io-c/Lib/test/test_memoryio.py ============================================================================== --- python/branches/io-c/Lib/test/test_memoryio.py (original) +++ python/branches/io-c/Lib/test/test_memoryio.py Tue Mar 3 23:21:10 2009 @@ -470,6 +470,8 @@ self.assertEqual(3, memio.write("c\rd")) memio.seek(0) self.assertEqual(memio.read(), "a\nb\nc\nd") + memio = self.ioclass("a\r\nb", newline=None) + self.assertEqual(memio.read(3), "a\nb") def test_newline_empty(self): # newline="" From buildbot at python.org Tue Mar 3 23:24:36 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 22:24:36 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090303222437.1F07F1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/703 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 3 23:38:24 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 23:38:24 +0100 (CET) Subject: [Python-checkins] r70141 - python/branches/py3k/Lib/test/test_collections.py Message-ID: <20090303223824.D37A41E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 23:38:22 2009 New Revision: 70141 Log: Add another test. Modified: python/branches/py3k/Lib/test/test_collections.py Modified: python/branches/py3k/Lib/test/test_collections.py ============================================================================== --- python/branches/py3k/Lib/test/test_collections.py (original) +++ python/branches/py3k/Lib/test/test_collections.py Tue Mar 3 23:38:22 2009 @@ -719,6 +719,15 @@ self.assertEquals(len(dup), len(od)) self.assertEquals(type(dup), type(od)) + def test_yaml_linkage(self): + # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature. + # In yaml, lists are native but tuples are not. + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + od = OrderedDict(pairs) + # yaml.dump(od) --> + # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n' + self.assert_(all(type(pair)==list for pair in od.__reduce__()[1])) + def test_repr(self): od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]) self.assertEqual(repr(od), From python-checkins at python.org Tue Mar 3 23:41:27 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 3 Mar 2009 23:41:27 +0100 (CET) Subject: [Python-checkins] r70142 - in python/branches/py3k: Lib/subprocess.py Misc/NEWS PC/_subprocess.c Message-ID: <20090303224127.1FD011E4002@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 3 23:41:26 2009 New Revision: 70142 Log: Merged revisions 70137 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70137 | hirokazu.yamamoto | 2009-03-04 07:18:14 +0900 | 1 line Issue #5179: Fixed subprocess handle leak on failure on windows. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/subprocess.py python/branches/py3k/Misc/NEWS python/branches/py3k/PC/_subprocess.c Modified: python/branches/py3k/Lib/subprocess.py ============================================================================== --- python/branches/py3k/Lib/subprocess.py (original) +++ python/branches/py3k/Lib/subprocess.py Tue Mar 3 23:41:26 2009 @@ -638,21 +638,13 @@ c2pread, c2pwrite, errread, errwrite) - # On Windows, you cannot just redirect one or two handles: You - # 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. if mswindows: - if stdin is None and p2cwrite is not None: - os.close(p2cwrite) - p2cwrite = None - if stdout is None and c2pread is not None: - os.close(c2pread) - c2pread = None - if stderr is None and errread is not None: - os.close(errread) - errread = None + if p2cwrite is not None: + p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0) + if c2pread is not None: + c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0) + if errread is not None: + errread = msvcrt.open_osfhandle(errread.Detach(), 0) if bufsize == 0: bufsize = 1 # Nearly unbuffered (XXX for now) @@ -737,13 +729,10 @@ if stdin is None: p2cread = GetStdHandle(STD_INPUT_HANDLE) - if p2cread is not None: - pass - elif stdin is None or stdin == PIPE: + if p2cread is None: + p2cread, _ = CreatePipe(None, 0) + elif stdin == PIPE: p2cread, p2cwrite = CreatePipe(None, 0) - # Detach and turn into fd - p2cwrite = p2cwrite.Detach() - p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0) elif isinstance(stdin, int): p2cread = msvcrt.get_osfhandle(stdin) else: @@ -753,13 +742,10 @@ if stdout is None: c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE) - if c2pwrite is not None: - pass - elif stdout is None or stdout == PIPE: + if c2pwrite is None: + _, c2pwrite = CreatePipe(None, 0) + elif stdout == PIPE: c2pread, c2pwrite = CreatePipe(None, 0) - # Detach and turn into fd - c2pread = c2pread.Detach() - c2pread = msvcrt.open_osfhandle(c2pread, 0) elif isinstance(stdout, int): c2pwrite = msvcrt.get_osfhandle(stdout) else: @@ -769,13 +755,10 @@ if stderr is None: errwrite = GetStdHandle(STD_ERROR_HANDLE) - if errwrite is not None: - pass - elif stderr is None or stderr == PIPE: + if errwrite is None: + _, errwrite = CreatePipe(None, 0) + elif stderr == PIPE: errread, errwrite = CreatePipe(None, 0) - # Detach and turn into fd - errread = errread.Detach() - errread = msvcrt.open_osfhandle(errread, 0) elif stderr == STDOUT: errwrite = c2pwrite elif isinstance(stderr, int): Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 3 23:41:26 2009 @@ -181,6 +181,8 @@ Library ------- +- Issue #5179: Fixed subprocess handle leak on failure on windows. + - PEP 372: Added collections.OrderedDict(). - The _asdict() for method for namedtuples now returns an OrderedDict(). Modified: python/branches/py3k/PC/_subprocess.c ============================================================================== --- python/branches/py3k/PC/_subprocess.c (original) +++ python/branches/py3k/PC/_subprocess.c Tue Mar 3 23:41:26 2009 @@ -84,7 +84,7 @@ handle = self->handle; - self->handle = NULL; + self->handle = INVALID_HANDLE_VALUE; /* note: return the current handle, as an integer */ return HANDLE_TO_PYNUM(handle); From python-checkins at python.org Tue Mar 3 23:42:48 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 23:42:48 +0100 (CET) Subject: [Python-checkins] r70143 - python/branches/py3k/Lib/collections.py Message-ID: <20090303224248.5FC011E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 23:42:48 2009 New Revision: 70143 Log: Now that __keys are fully hidden, switch the underlying structure to deque() which futher reduces the temptation to index or resort. Also, it is a bit faster for some cases. Modified: python/branches/py3k/Lib/collections.py Modified: python/branches/py3k/Lib/collections.py ============================================================================== --- python/branches/py3k/Lib/collections.py (original) +++ python/branches/py3k/Lib/collections.py Tue Mar 3 23:42:48 2009 @@ -27,11 +27,11 @@ except AttributeError: # Note the underlying data structure for this class is likely to # change in the future. Do not rely on it or access it directly. - self.__keys = [] + self.__keys = deque() self.update(*args, **kwds) def clear(self): - del self.__keys[:] + self.__keys.clear() dict.clear(self) def __setitem__(self, key, value): From python-checkins at python.org Tue Mar 3 23:50:05 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 23:50:05 +0100 (CET) Subject: [Python-checkins] r70144 - python/branches/py3k/Lib/test/test_collections.py Message-ID: <20090303225005.110CF1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 23:50:04 2009 New Revision: 70144 Log: Additional test for __reduce__. Modified: python/branches/py3k/Lib/test/test_collections.py Modified: python/branches/py3k/Lib/test/test_collections.py ============================================================================== --- python/branches/py3k/Lib/test/test_collections.py (original) +++ python/branches/py3k/Lib/test/test_collections.py Tue Mar 3 23:50:04 2009 @@ -728,6 +728,14 @@ # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n' self.assert_(all(type(pair)==list for pair in od.__reduce__()[1])) + def test_reduce_not_too_fat(self): + # do not save instance dictionary if not needed + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + od = OrderedDict(pairs) + self.assertEqual(len(od.__reduce__()), 2) + od.x = 10 + self.assertEqual(len(od.__reduce__()), 3) + def test_repr(self): od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]) self.assertEqual(repr(od), From python-checkins at python.org Tue Mar 3 23:51:58 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 3 Mar 2009 23:51:58 +0100 (CET) Subject: [Python-checkins] r70145 - python/trunk/Doc/library/ttk.rst Message-ID: <20090303225158.503FD1E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 3 23:51:57 2009 New Revision: 70145 Log: making the writing more formal Modified: python/trunk/Doc/library/ttk.rst Modified: python/trunk/Doc/library/ttk.rst ============================================================================== --- python/trunk/Doc/library/ttk.rst (original) +++ python/trunk/Doc/library/ttk.rst Tue Mar 3 23:51:57 2009 @@ -8,12 +8,12 @@ .. index:: single: ttk -The :mod:`ttk` module provides access to the Tk themed widget set, which -has been introduced in Tk 8.5. If you do not have Python compiled against -Tk 8.5 you may still use this module as long as you have Tile installed, but -then you will miss some features provided by the new Tk, like anti-aliased font -rendering under X11, window transparency (on X11 you will need a composition -window manager) and others. +The :mod:`ttk` module provides access to the Tk themed widget set, which has +been introduced in Tk 8.5. If Python is not compiled against Tk 8.5 code may +still use this module as long as Tile is installed. However, some features +provided by the new Tk, like anti-aliased font rendering under X11, window +transparency (on X11 you will need a composition window manager) will be +missing. The basic idea of :mod:`ttk` is to separate, to the extent possible, the code implementing a widget's behavior from the code implementing its appearance. @@ -28,15 +28,15 @@ Using Ttk --------- -Basically, to start using Ttk, you have to import its module:: +To start using Ttk, import its module:: import ttk -But if you already have some code that does:: +But code like this:: from Tkinter import * -You may optionally want to use:: +may optionally want to use this:: from Tkinter import * from ttk import * @@ -46,12 +46,11 @@ :class:`Menubutton`, :class:`PanedWindow`, :class:`Radiobutton`, :class:`Scale` and :class:`Scrollbar`) will automatically substitute for the Tk widgets. -This has the direct benefit of using the new widgets, giving better -look & feel across platforms, but you should be aware that they are not -totally compatible. The main difference you will find out is that widget -options such as "fg", "bg" and others related to widget styling are no -longer present in Ttk widgets, instead you will have to use :class:`ttk.Style` -to achieve the same (or better) styling. +This has the direct benefit of using the new widgets, giving better look & feel +across platforms, but be aware that they are not totally compatible. The main +difference is that widget options such as "fg", "bg" and others related to +widget styling are no longer present in Ttk widgets. Use :class:`ttk.Style` to +achieve the same (or better) styling. .. seealso:: @@ -1142,10 +1141,10 @@ ----------- Each widget in :mod:`ttk` is assigned a style, which specifies the set of -elements making up the widget and how they are arranged, along with dynamic -and default settings for element options. By default the style name is the -same as the widget's class name, but it may be overriden by the widget's style -option. If you don't know the class name of a widget, use the method +elements making up the widget and how they are arranged, along with dynamic and +default settings for element options. By default the style name is the same as +the widget's class name, but it may be overriden by the widget's style +option. If the class name of a widget is unkown, use the method :meth:`Misc.winfo_class` (somewidget.winfo_class()). .. seealso:: @@ -1166,8 +1165,8 @@ Each key in *kw* is an option and each value is a string identifying the value for that option. - For example, to change every default button to be a flat button with - some padding and a different background color you could do:: + For example, to change every default button to be a flat button with some + padding and a different background color do:: import ttk import Tkinter @@ -1192,7 +1191,7 @@ something else of your preference. A statespec is compound of one or more states and then a value. - An example may make it more understandable:: + An example:: import Tkinter import ttk @@ -1213,9 +1212,9 @@ There is a thing to note in this previous short example: * The order of the (states, value) sequences for an option does matter, - if you changed the order to [('active', 'blue'), ('pressed', 'red')] - in the foreground option, for example, you would get a blue foreground - when the widget were in active or pressed states. + if the order was changed to [('active', 'blue'), ('pressed', 'red')] in + the foreground option, for example, the style would be a blue + foreground when the widget was in active or pressed states. .. method:: lookup(style, option[, state=None[, default=None]]) @@ -1226,7 +1225,7 @@ states. If the *default* argument is set, it is used as a fallback value in case no specification for option is found. - To check what font a Button uses by default, you would do:: + To check what font a Button uses by default, do:: import ttk From python-checkins at python.org Tue Mar 3 23:53:46 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 3 Mar 2009 23:53:46 +0100 (CET) Subject: [Python-checkins] r70146 - in python/branches/release30-maint: Lib/subprocess.py Misc/NEWS PC/_subprocess.c Message-ID: <20090303225346.B7CBF1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 3 23:53:46 2009 New Revision: 70146 Log: Merged revisions 70142 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70142 | hirokazu.yamamoto | 2009-03-04 07:41:26 +0900 | 9 lines Merged revisions 70137 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70137 | hirokazu.yamamoto | 2009-03-04 07:18:14 +0900 | 1 line Issue #5179: Fixed subprocess handle leak on failure on windows. ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/subprocess.py python/branches/release30-maint/Misc/NEWS python/branches/release30-maint/PC/_subprocess.c Modified: python/branches/release30-maint/Lib/subprocess.py ============================================================================== --- python/branches/release30-maint/Lib/subprocess.py (original) +++ python/branches/release30-maint/Lib/subprocess.py Tue Mar 3 23:53:46 2009 @@ -593,21 +593,13 @@ c2pread, c2pwrite, errread, errwrite) - # On Windows, you cannot just redirect one or two handles: You - # 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. if mswindows: - if stdin is None and p2cwrite is not None: - os.close(p2cwrite) - p2cwrite = None - if stdout is None and c2pread is not None: - os.close(c2pread) - c2pread = None - if stderr is None and errread is not None: - os.close(errread) - errread = None + if p2cwrite is not None: + p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0) + if c2pread is not None: + c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0) + if errread is not None: + errread = msvcrt.open_osfhandle(errread.Detach(), 0) if bufsize == 0: bufsize = 1 # Nearly unbuffered (XXX for now) @@ -692,13 +684,10 @@ if stdin is None: p2cread = GetStdHandle(STD_INPUT_HANDLE) - if p2cread is not None: - pass - elif stdin is None or stdin == PIPE: + if p2cread is None: + p2cread, _ = CreatePipe(None, 0) + elif stdin == PIPE: p2cread, p2cwrite = CreatePipe(None, 0) - # Detach and turn into fd - p2cwrite = p2cwrite.Detach() - p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0) elif isinstance(stdin, int): p2cread = msvcrt.get_osfhandle(stdin) else: @@ -708,13 +697,10 @@ if stdout is None: c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE) - if c2pwrite is not None: - pass - elif stdout is None or stdout == PIPE: + if c2pwrite is None: + _, c2pwrite = CreatePipe(None, 0) + elif stdout == PIPE: c2pread, c2pwrite = CreatePipe(None, 0) - # Detach and turn into fd - c2pread = c2pread.Detach() - c2pread = msvcrt.open_osfhandle(c2pread, 0) elif isinstance(stdout, int): c2pwrite = msvcrt.get_osfhandle(stdout) else: @@ -724,13 +710,10 @@ if stderr is None: errwrite = GetStdHandle(STD_ERROR_HANDLE) - if errwrite is not None: - pass - elif stderr is None or stderr == PIPE: + if errwrite is None: + _, errwrite = CreatePipe(None, 0) + elif stderr == PIPE: errread, errwrite = CreatePipe(None, 0) - # Detach and turn into fd - errread = errread.Detach() - errread = msvcrt.open_osfhandle(errread, 0) elif stderr == STDOUT: errwrite = c2pwrite elif isinstance(stderr, int): Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Tue Mar 3 23:53:46 2009 @@ -21,6 +21,8 @@ Library ------- +- Issue #5179: Fixed subprocess handle leak on failure on windows. + - Issue #5282: Fixed mmap resize on 32bit windows and unix. When offset > 0, The file was resized to wrong size. Modified: python/branches/release30-maint/PC/_subprocess.c ============================================================================== --- python/branches/release30-maint/PC/_subprocess.c (original) +++ python/branches/release30-maint/PC/_subprocess.c Tue Mar 3 23:53:46 2009 @@ -84,7 +84,7 @@ handle = self->handle; - self->handle = NULL; + self->handle = INVALID_HANDLE_VALUE; /* note: return the current handle, as an integer */ return HANDLE_TO_PYNUM(handle); From python-checkins at python.org Tue Mar 3 23:55:01 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 3 Mar 2009 23:55:01 +0100 (CET) Subject: [Python-checkins] r70147 - in python/branches/release26-maint: Lib/subprocess.py Misc/NEWS PC/_subprocess.c Message-ID: <20090303225501.164671E4002@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 3 23:55:00 2009 New Revision: 70147 Log: Merged revisions 70137 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70137 | hirokazu.yamamoto | 2009-03-04 07:18:14 +0900 | 1 line Issue #5179: Fixed subprocess handle leak on failure on windows. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/subprocess.py python/branches/release26-maint/Misc/NEWS python/branches/release26-maint/PC/_subprocess.c Modified: python/branches/release26-maint/Lib/subprocess.py ============================================================================== --- python/branches/release26-maint/Lib/subprocess.py (original) +++ python/branches/release26-maint/Lib/subprocess.py Tue Mar 3 23:55:00 2009 @@ -594,21 +594,13 @@ c2pread, c2pwrite, errread, errwrite) - # On Windows, you cannot just redirect one or two handles: You - # 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. if mswindows: - if stdin is None and p2cwrite is not None: - os.close(p2cwrite) - p2cwrite = None - if stdout is None and c2pread is not None: - os.close(c2pread) - c2pread = None - if stderr is None and errread is not None: - os.close(errread) - errread = None + if p2cwrite is not None: + p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0) + if c2pread is not None: + c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0) + if errread is not None: + errread = msvcrt.open_osfhandle(errread.Detach(), 0) if p2cwrite is not None: self.stdin = os.fdopen(p2cwrite, 'wb', bufsize) @@ -692,13 +684,10 @@ if stdin is None: p2cread = GetStdHandle(STD_INPUT_HANDLE) - if p2cread is not None: - pass - elif stdin is None or stdin == PIPE: + if p2cread is None: + p2cread, _ = CreatePipe(None, 0) + elif stdin == PIPE: p2cread, p2cwrite = CreatePipe(None, 0) - # Detach and turn into fd - p2cwrite = p2cwrite.Detach() - p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0) elif isinstance(stdin, int): p2cread = msvcrt.get_osfhandle(stdin) else: @@ -708,13 +697,10 @@ if stdout is None: c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE) - if c2pwrite is not None: - pass - elif stdout is None or stdout == PIPE: + if c2pwrite is None: + _, c2pwrite = CreatePipe(None, 0) + elif stdout == PIPE: c2pread, c2pwrite = CreatePipe(None, 0) - # Detach and turn into fd - c2pread = c2pread.Detach() - c2pread = msvcrt.open_osfhandle(c2pread, 0) elif isinstance(stdout, int): c2pwrite = msvcrt.get_osfhandle(stdout) else: @@ -724,13 +710,10 @@ if stderr is None: errwrite = GetStdHandle(STD_ERROR_HANDLE) - if errwrite is not None: - pass - elif stderr is None or stderr == PIPE: + if errwrite is None: + _, errwrite = CreatePipe(None, 0) + elif stderr == PIPE: errread, errwrite = CreatePipe(None, 0) - # Detach and turn into fd - errread = errread.Detach() - errread = msvcrt.open_osfhandle(errread, 0) elif stderr == STDOUT: errwrite = c2pwrite elif isinstance(stderr, int): Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Tue Mar 3 23:55:00 2009 @@ -89,6 +89,8 @@ Library ------- +- Issue #5179: Fixed subprocess handle leak on failure on windows. + - Issue #4308: httplib.IncompleteRead's repr doesn't include all of the data all ready received. Modified: python/branches/release26-maint/PC/_subprocess.c ============================================================================== --- python/branches/release26-maint/PC/_subprocess.c (original) +++ python/branches/release26-maint/PC/_subprocess.c Tue Mar 3 23:55:00 2009 @@ -87,7 +87,7 @@ handle = self->handle; - self->handle = NULL; + self->handle = INVALID_HANDLE_VALUE; /* note: return the current handle, as an integer */ return HANDLE_TO_PYNUM(handle); From python-checkins at python.org Tue Mar 3 23:55:56 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 3 Mar 2009 23:55:56 +0100 (CET) Subject: [Python-checkins] r70148 - python/branches/py3k/Doc/Makefile Message-ID: <20090303225556.281111E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 3 23:55:55 2009 New Revision: 70148 Log: don't bother with version in doc builds Modified: python/branches/py3k/Doc/Makefile Modified: python/branches/py3k/Doc/Makefile ============================================================================== --- python/branches/py3k/Doc/Makefile (original) +++ python/branches/py3k/Doc/Makefile Tue Mar 3 23:55:55 2009 @@ -4,7 +4,7 @@ # # You can set these variables from the command line. -PYTHON = python2.5 +PYTHON = python SVNROOT = http://svn.python.org/projects SPHINXOPTS = PAPER = From python-checkins at python.org Tue Mar 3 23:59:26 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 3 Mar 2009 23:59:26 +0100 (CET) Subject: [Python-checkins] r70149 - in python/trunk/Lib: collections.py test/test_collections.py Message-ID: <20090303225926.F009F1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 3 23:59:25 2009 New Revision: 70149 Log: Backport 70140, 70141, 70143, and 70144. Adds tests, switches from list to deque, fixes __reduce__ which was unnecessarily copying __keys. Modified: python/trunk/Lib/collections.py python/trunk/Lib/test/test_collections.py Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Tue Mar 3 23:59:25 2009 @@ -27,11 +27,11 @@ except AttributeError: # Note the underlying data structure for this class is likely to # change in the future. Do not rely on it or access it directly. - self.__keys = [] + self.__keys = deque() self.update(*args, **kwds) def clear(self): - del self.__keys[:] + self.__keys.clear() dict.clear(self) def __setitem__(self, key, value): @@ -58,16 +58,20 @@ def __reduce__(self): items = [[k, self[k]] for k in self] + tmp = self.__keys + del self.__keys inst_dict = vars(self).copy() - inst_dict.pop('__keys', None) - return (self.__class__, (items,), inst_dict) + self.__keys = tmp + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) setdefault = MutableMapping.setdefault update = MutableMapping.update pop = MutableMapping.pop def keys(self): - return self.__keys[:] + return list(self.__keys) def values(self): return map(self.__getitem__, self.__keys) Modified: python/trunk/Lib/test/test_collections.py ============================================================================== --- python/trunk/Lib/test/test_collections.py (original) +++ python/trunk/Lib/test/test_collections.py Tue Mar 3 23:59:25 2009 @@ -717,6 +717,23 @@ self.assertEquals(len(dup), len(od)) self.assertEquals(type(dup), type(od)) + def test_yaml_linkage(self): + # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature. + # In yaml, lists are native but tuples are not. + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + od = OrderedDict(pairs) + # yaml.dump(od) --> + # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n' + self.assert_(all(type(pair)==list for pair in od.__reduce__()[1])) + + def test_reduce_not_too_fat(self): + # do not save instance dictionary if not needed + pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] + od = OrderedDict(pairs) + self.assertEqual(len(od.__reduce__()), 2) + od.x = 10 + self.assertEqual(len(od.__reduce__()), 3) + def test_repr(self): od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]) self.assertEqual(repr(od), From python-checkins at python.org Wed Mar 4 00:03:12 2009 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 4 Mar 2009 00:03:12 +0100 (CET) Subject: [Python-checkins] r70150 - python/branches/py3k Message-ID: <20090303230312.DFD601E4015@bag.python.org> Author: benjamin.peterson Date: Wed Mar 4 00:03:12 2009 New Revision: 70150 Log: Blocked revisions 70149 via svnmerge ........ r70149 | raymond.hettinger | 2009-03-03 16:59:25 -0600 (Tue, 03 Mar 2009) | 5 lines Backport 70140, 70141, 70143, and 70144. Adds tests, switches from list to deque, fixes __reduce__ which was unnecessarily copying __keys. ........ Modified: python/branches/py3k/ (props changed) From buildbot at python.org Wed Mar 4 00:11:01 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 23:11:01 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090303231102.3AADB1E405A@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/362 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: hirokazu.yamamoto,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Wed Mar 4 00:14:06 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 23:14:06 +0000 Subject: [Python-checkins] buildbot failure in OS X x86 trunk Message-ID: <20090303231407.0CF971E404F@bag.python.org> The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/208 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_htmlparser test_pep277 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Mar 4 00:28:30 2009 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 4 Mar 2009 00:28:30 +0100 (CET) Subject: [Python-checkins] r70151 - python/branches/py3k Message-ID: <20090303232830.7321B1E4002@bag.python.org> Author: benjamin.peterson Date: Wed Mar 4 00:28:30 2009 New Revision: 70151 Log: Initialized merge tracking via "svnmerge" with revisions "1-68679" from svn+ssh://pythondev at svn.python.org/python/branches/io-c Modified: python/branches/py3k/ (props changed) From buildbot at python.org Wed Mar 4 00:34:48 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 03 Mar 2009 23:34:48 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090303233448.68E8B1E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/376 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_posix test_subprocess ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_subprocess.py", line 149, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From python-checkins at python.org Wed Mar 4 01:14:52 2009 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 4 Mar 2009 01:14:52 +0100 (CET) Subject: [Python-checkins] r70152 - in python/branches/py3k: Doc/library/io.rst Lib/_pyio.py Lib/importlib/__init__.py Lib/importlib/_bootstrap.py Lib/io.py Lib/test/test_bufio.py Lib/test/test_descr.py Lib/test/test_file.py Lib/test/test_fileio.py Lib/test/test_io.py Lib/test/test_largefile.py Lib/test/test_memoryio.py Lib/test/test_univnewlines.py Lib/test/test_uu.py Makefile.pre.in Misc/NEWS Modules/Setup.dist Modules/_bufferedio.c Modules/_bytesio.c Modules/_fileio.c Modules/_iobase.c Modules/_iomodule.h Modules/_stringio.c Modules/_textio.c Modules/io.c PC/VC6/pythoncore.dsp PC/config.c PCbuild/pythoncore.vcproj Python/pythonrun.c setup.py Message-ID: <20090304001452.B50231E4002@bag.python.org> Author: benjamin.peterson Date: Wed Mar 4 01:14:51 2009 New Revision: 70152 Log: merge the io-c branch: C implementation of the io module The main io module now uses the C implementation. The Python one still exists in Lib/_pyio.py for ease of testing new features and usefulness to other implementers. The rewrite was done by Antoine Pitrou and Amaury Forgeot d'Arc. I was slightly helpful at the end. :) Following are the log messages from the io-c branch: Merged revisions 68683-68685,68687-68689,68693,68704,68741-68743,68745,68747,68752-68754,68756,68758,68812,68816-68817,68820-68822,68824-68825,68828,68876-68877,69037,69044,69104,69115,69194,69626-69629,69636,69638,69641-69642,69644-69654,69656-69661,69671,69677,69812-69815,69817,69827-69830,69839,69841-69845,69848,69850,69852,69854,69860,69865-69866,69868,69872-69873,69885,69888,69891-69893,69911,69913-69916,69963,70033,70035,70038,70041-70048,70067-70070,70075,70112,70133,70135,70140 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/io-c ........ r68683 | antoine.pitrou | 2009-01-17 17:13:48 -0600 (Sat, 17 Jan 2009) | 3 lines Merge in changes from the io-c sandbox. Tests will follow in separate commits. ........ r68684 | antoine.pitrou | 2009-01-17 17:17:26 -0600 (Sat, 17 Jan 2009) | 3 lines Fixes and additions to test_io.py ........ r68685 | antoine.pitrou | 2009-01-17 17:22:04 -0600 (Sat, 17 Jan 2009) | 1 line Fix test_fileio ........ r68687 | antoine.pitrou | 2009-01-17 17:35:11 -0600 (Sat, 17 Jan 2009) | 3 lines Add dependency to _iomodule.h for the various C sources ........ r68688 | antoine.pitrou | 2009-01-17 17:38:18 -0600 (Sat, 17 Jan 2009) | 3 lines These precautions are not needed anymore! ........ r68689 | antoine.pitrou | 2009-01-17 17:41:48 -0600 (Sat, 17 Jan 2009) | 3 lines Fix another test ........ r68693 | antoine.pitrou | 2009-01-17 17:49:58 -0600 (Sat, 17 Jan 2009) | 3 lines Fix test_uu (which was using private attributes of TextIOWrapper) ........ r68704 | antoine.pitrou | 2009-01-17 18:45:29 -0600 (Sat, 17 Jan 2009) | 3 lines Most io sources are Py_ssize_t-clean (I don't know about bytesio and stringio) ........ r68741 | antoine.pitrou | 2009-01-18 15:20:30 -0600 (Sun, 18 Jan 2009) | 3 lines Check return type in TextIOWrapper.__next__ ........ r68742 | antoine.pitrou | 2009-01-18 15:28:48 -0600 (Sun, 18 Jan 2009) | 4 lines Make binary buffered readline and iteration much faster (8x as fast as the IOBase generic implementation) ........ r68743 | antoine.pitrou | 2009-01-18 15:47:47 -0600 (Sun, 18 Jan 2009) | 3 lines Reinsert test_io_after_close (was removed by mistake) ........ r68745 | antoine.pitrou | 2009-01-18 16:16:06 -0600 (Sun, 18 Jan 2009) | 3 lines Add read, read1 and write methods to BufferedIOBase ........ r68747 | antoine.pitrou | 2009-01-18 16:35:58 -0600 (Sun, 18 Jan 2009) | 3 lines Kill test failure ........ r68752 | amaury.forgeotdarc | 2009-01-18 17:05:43 -0600 (Sun, 18 Jan 2009) | 3 lines Fix a segfault when e.g a BufferedReader is created with a FileIO in read mode. ........ r68753 | antoine.pitrou | 2009-01-18 17:13:09 -0600 (Sun, 18 Jan 2009) | 3 lines Add truncate() to text IO objects ........ r68754 | antoine.pitrou | 2009-01-18 17:51:08 -0600 (Sun, 18 Jan 2009) | 3 lines Remove IOBase.__del__ and replace it with custom code with tp_dealloc ........ r68756 | antoine.pitrou | 2009-01-18 18:10:16 -0600 (Sun, 18 Jan 2009) | 3 lines Remove irrelevant comment. ........ r68758 | antoine.pitrou | 2009-01-18 18:36:16 -0600 (Sun, 18 Jan 2009) | 3 lines in importlib:_fileio._FileIO -> _io.FileIO ........ r68812 | antoine.pitrou | 2009-01-20 14:15:51 -0600 (Tue, 20 Jan 2009) | 3 lines Add garbage collection support to FileIO objects ........ r68816 | antoine.pitrou | 2009-01-20 14:56:28 -0600 (Tue, 20 Jan 2009) | 3 lines Add GC support to Buffered and Text IO objects ........ r68817 | antoine.pitrou | 2009-01-20 15:19:45 -0600 (Tue, 20 Jan 2009) | 3 lines Add some file headers ........ r68820 | antoine.pitrou | 2009-01-20 15:29:59 -0600 (Tue, 20 Jan 2009) | 3 lines Add class TextIOBase ........ r68821 | antoine.pitrou | 2009-01-20 15:36:16 -0600 (Tue, 20 Jan 2009) | 3 lines Add properties to TextIOBase ........ r68822 | antoine.pitrou | 2009-01-20 15:41:19 -0600 (Tue, 20 Jan 2009) | 3 lines Disable the pure Python TextIOBase class, and inject C the implementation instead ........ r68824 | antoine.pitrou | 2009-01-20 16:36:28 -0600 (Tue, 20 Jan 2009) | 3 lines Fix two leaks ........ r68825 | antoine.pitrou | 2009-01-20 16:38:29 -0600 (Tue, 20 Jan 2009) | 3 lines FileIO.name is just a plain attribute, we can set it directly ........ r68828 | antoine.pitrou | 2009-01-20 17:06:33 -0600 (Tue, 20 Jan 2009) | 3 lines Speed up closed checks on text IO objects. Good for a 25% speedup on small ops. ........ r68876 | antoine.pitrou | 2009-01-23 17:01:25 -0600 (Fri, 23 Jan 2009) | 3 lines Two typos ........ r68877 | antoine.pitrou | 2009-01-23 18:13:20 -0600 (Fri, 23 Jan 2009) | 3 lines Remove two unused functions ........ r69037 | amaury.forgeotdarc | 2009-01-27 17:10:25 -0600 (Tue, 27 Jan 2009) | 2 lines Update the win32 project files ........ r69044 | antoine.pitrou | 2009-01-27 18:51:07 -0600 (Tue, 27 Jan 2009) | 3 lines Improve heuristic in IncrementalNewlineDecoder + some micro-optimizations ........ r69104 | antoine.pitrou | 2009-01-29 15:23:42 -0600 (Thu, 29 Jan 2009) | 3 lines Fix some crashers found by Victor ........ r69115 | hirokazu.yamamoto | 2009-01-29 20:36:28 -0600 (Thu, 29 Jan 2009) | 1 line Updated VC6 project file. ........ r69194 | antoine.pitrou | 2009-02-01 16:57:18 -0600 (Sun, 01 Feb 2009) | 3 lines Fix downcasting warnings in 32-bit mode with 64-bit offsets (Windows) ........ r69626 | benjamin.peterson | 2009-02-14 17:33:34 -0600 (Sat, 14 Feb 2009) | 1 line only catch AttributeError and UnsupportedOperation ........ r69627 | benjamin.peterson | 2009-02-14 21:35:28 -0600 (Sat, 14 Feb 2009) | 1 line give the IO module its own state and store the os and locale modules in it ........ r69628 | benjamin.peterson | 2009-02-14 22:08:32 -0600 (Sat, 14 Feb 2009) | 1 line put interned strings in the module state structure ........ r69629 | benjamin.peterson | 2009-02-14 22:15:29 -0600 (Sat, 14 Feb 2009) | 1 line put UnsupportedOperation in the module state ........ r69636 | benjamin.peterson | 2009-02-15 08:31:42 -0600 (Sun, 15 Feb 2009) | 1 line dealloc unsupported_operation ........ r69638 | benjamin.peterson | 2009-02-15 09:24:45 -0600 (Sun, 15 Feb 2009) | 1 line actually test the C implementation ........ r69641 | benjamin.peterson | 2009-02-15 10:12:37 -0600 (Sun, 15 Feb 2009) | 5 lines make interned strings globals again ;( putting them in the module state was asking for trouble when the module was dealloced before the classes in it were ........ r69642 | benjamin.peterson | 2009-02-15 10:19:45 -0600 (Sun, 15 Feb 2009) | 1 line actually test the python implementations ........ r69644 | antoine.pitrou | 2009-02-15 11:59:30 -0600 (Sun, 15 Feb 2009) | 3 lines Fix memory leak in destructor when a Python class inherits from IOBase (or an IOBase-derived type) ........ r69645 | antoine.pitrou | 2009-02-15 12:23:26 -0600 (Sun, 15 Feb 2009) | 3 lines Add a warning about the embarassing state of IOBase finalization ........ r69646 | antoine.pitrou | 2009-02-15 13:14:42 -0600 (Sun, 15 Feb 2009) | 3 lines Fix opening of 8-bit filenames with FileIO ........ r69647 | antoine.pitrou | 2009-02-15 13:20:22 -0600 (Sun, 15 Feb 2009) | 3 lines Fix leak in FileIO constructor ........ r69648 | antoine.pitrou | 2009-02-15 13:58:16 -0600 (Sun, 15 Feb 2009) | 3 lines Fix some refleaks ........ r69649 | antoine.pitrou | 2009-02-15 14:05:13 -0600 (Sun, 15 Feb 2009) | 3 lines Fix a leak in IOBase.writelines ........ r69650 | antoine.pitrou | 2009-02-15 14:11:56 -0600 (Sun, 15 Feb 2009) | 3 lines Fix memory leak in BufferedWriter.truncate ........ r69651 | antoine.pitrou | 2009-02-15 14:25:34 -0600 (Sun, 15 Feb 2009) | 3 lines Fix a leak in TextIOWrapper.seek ........ r69652 | antoine.pitrou | 2009-02-15 14:26:28 -0600 (Sun, 15 Feb 2009) | 3 lines Unify implementations of truncate for buffered objects ........ r69653 | antoine.pitrou | 2009-02-15 15:15:15 -0600 (Sun, 15 Feb 2009) | 3 lines Fix more leaks in TextIOWrapper ........ r69654 | antoine.pitrou | 2009-02-15 15:21:57 -0600 (Sun, 15 Feb 2009) | 3 lines Smaller chunk size for a faster test ........ r69656 | benjamin.peterson | 2009-02-15 17:29:48 -0600 (Sun, 15 Feb 2009) | 1 line braces make this much clearer ........ r69657 | benjamin.peterson | 2009-02-15 17:46:07 -0600 (Sun, 15 Feb 2009) | 1 line use the correct macro ........ r69658 | antoine.pitrou | 2009-02-15 19:38:59 -0600 (Sun, 15 Feb 2009) | 5 lines Fix crash in test_urllib2_localnet in debug mode. It was due to an HTTPResponse object being revived when calling its close() method in IOBase's tp_dealloc. _PyIOBase_finalize() starts looking scary... ........ r69659 | benjamin.peterson | 2009-02-15 20:55:48 -0600 (Sun, 15 Feb 2009) | 1 line fix segfault on initialization failing ........ r69660 | benjamin.peterson | 2009-02-15 21:09:31 -0600 (Sun, 15 Feb 2009) | 1 line apparently locale.getprefferedencoding() can raise a ImportError, too ........ r69661 | benjamin.peterson | 2009-02-15 21:54:15 -0600 (Sun, 15 Feb 2009) | 1 line it's amazing this worked at all; I was using the wrong structs! ........ r69671 | benjamin.peterson | 2009-02-16 08:38:27 -0600 (Mon, 16 Feb 2009) | 1 line add garbage collection support to bytesio ........ r69677 | benjamin.peterson | 2009-02-16 10:31:03 -0600 (Mon, 16 Feb 2009) | 5 lines reduce ImportError catching code duplication I'm not sure this makes the code clearer with its new gotos, but at least I added a big fat comment ........ r69812 | antoine.pitrou | 2009-02-20 13:50:16 -0600 (Fri, 20 Feb 2009) | 3 lines _StringIO now belongs to the _io modules, rather to its own _stringio module ........ r69813 | antoine.pitrou | 2009-02-20 13:58:22 -0600 (Fri, 20 Feb 2009) | 3 lines Add a test for StringIO properties ........ r69814 | antoine.pitrou | 2009-02-20 14:06:03 -0600 (Fri, 20 Feb 2009) | 3 lines Reimplement a few trivial StringIO functions and properties in C ........ r69815 | antoine.pitrou | 2009-02-20 14:13:11 -0600 (Fri, 20 Feb 2009) | 3 lines Add the line_buffering property to TextIOWrapper, and test for it ........ r69817 | antoine.pitrou | 2009-02-20 14:45:50 -0600 (Fri, 20 Feb 2009) | 4 lines Allow IncrementalNewlineDecoder to take unicode objects as decoding input if the decoder parameter is None This will help rewriting StringIO to C ........ r69827 | antoine.pitrou | 2009-02-20 19:00:30 -0600 (Fri, 20 Feb 2009) | 3 lines Rewrite most of StringIO in C. Some almost empty stubs remain to be converted. ........ r69828 | antoine.pitrou | 2009-02-20 19:09:25 -0600 (Fri, 20 Feb 2009) | 3 lines Plug a leak, and remove an unused string ........ r69829 | benjamin.peterson | 2009-02-20 20:02:28 -0600 (Fri, 20 Feb 2009) | 1 line this assertions makes more sense here ........ r69830 | benjamin.peterson | 2009-02-20 20:03:04 -0600 (Fri, 20 Feb 2009) | 1 line PyModule_AddObject can fail; simplify this code with a macro ........ r69839 | antoine.pitrou | 2009-02-21 12:54:01 -0600 (Sat, 21 Feb 2009) | 3 lines StringIO is now written entirely in C (and blazingly fast) ........ r69841 | benjamin.peterson | 2009-02-21 14:05:40 -0600 (Sat, 21 Feb 2009) | 1 line split the Python implementation of io into another module and rewrite the tests to test both implementations ........ r69842 | benjamin.peterson | 2009-02-21 14:10:00 -0600 (Sat, 21 Feb 2009) | 1 line closed is not a function ........ r69843 | benjamin.peterson | 2009-02-21 14:13:04 -0600 (Sat, 21 Feb 2009) | 1 line fix __all__ test ........ r69844 | benjamin.peterson | 2009-02-21 14:21:24 -0600 (Sat, 21 Feb 2009) | 1 line fix the rest of the Misc tests ........ r69845 | benjamin.peterson | 2009-02-21 14:26:59 -0600 (Sat, 21 Feb 2009) | 1 line RawIOBase is better for FileIO ........ r69848 | benjamin.peterson | 2009-02-21 15:33:53 -0600 (Sat, 21 Feb 2009) | 1 line fix some more tests broken by bag argument validation ........ r69850 | benjamin.peterson | 2009-02-21 16:16:42 -0600 (Sat, 21 Feb 2009) | 1 line make the python IncrementalNewineDecoder support a None decoder ........ r69852 | benjamin.peterson | 2009-02-21 16:36:09 -0600 (Sat, 21 Feb 2009) | 1 line fix a BlockingIOError.characters_written bug ........ r69854 | benjamin.peterson | 2009-02-21 16:49:02 -0600 (Sat, 21 Feb 2009) | 1 line check whence ........ r69860 | benjamin.peterson | 2009-02-21 17:42:50 -0600 (Sat, 21 Feb 2009) | 1 line fix some of these Misbehaving io tests ........ r69865 | benjamin.peterson | 2009-02-21 18:59:52 -0600 (Sat, 21 Feb 2009) | 1 line don't use super here() ........ r69866 | benjamin.peterson | 2009-02-21 19:05:28 -0600 (Sat, 21 Feb 2009) | 1 line use implementation specific classes ........ r69868 | benjamin.peterson | 2009-02-21 22:12:05 -0600 (Sat, 21 Feb 2009) | 1 line use a more DRY friendly approach to injecting module contents into test classes ........ r69872 | antoine.pitrou | 2009-02-22 13:39:45 -0600 (Sun, 22 Feb 2009) | 3 lines Sanitize destructor behaviour of IOBase. Now Python-defined attributes can be accessed from close(). ........ r69873 | antoine.pitrou | 2009-02-22 13:50:14 -0600 (Sun, 22 Feb 2009) | 4 lines Only set the internal fd after it has been checked to be valid (otherwise, the destructor will attempt to close it) ........ r69885 | benjamin.peterson | 2009-02-22 15:30:14 -0600 (Sun, 22 Feb 2009) | 1 line convert some other tests to use both io implementations ........ r69888 | antoine.pitrou | 2009-02-22 17:03:16 -0600 (Sun, 22 Feb 2009) | 3 lines Silence all exceptions when finalizing ........ r69891 | benjamin.peterson | 2009-02-22 17:27:24 -0600 (Sun, 22 Feb 2009) | 1 line convert another test to test both io implementations ........ r69892 | benjamin.peterson | 2009-02-22 17:32:15 -0600 (Sun, 22 Feb 2009) | 1 line help poor people like me to find their io tests (did I miss any?) ........ r69893 | benjamin.peterson | 2009-02-22 17:37:56 -0600 (Sun, 22 Feb 2009) | 1 line put a big note in the test telling people to write tests for both implementations now ........ r69911 | antoine.pitrou | 2009-02-23 13:57:18 -0600 (Mon, 23 Feb 2009) | 3 lines expose DEFAULT_BUFFER_SIZE again (fixes a bunch of test failures) ........ r69913 | antoine.pitrou | 2009-02-23 14:10:30 -0600 (Mon, 23 Feb 2009) | 4 lines Do the cyclic garbage collection tests only on the C version. The Python version is helpless as it uses __del__. ........ r69914 | antoine.pitrou | 2009-02-23 14:21:41 -0600 (Mon, 23 Feb 2009) | 3 lines Adapt test_largefile to test both implementations ........ r69915 | antoine.pitrou | 2009-02-23 14:25:14 -0600 (Mon, 23 Feb 2009) | 3 lines One small failure ........ r69916 | antoine.pitrou | 2009-02-23 14:28:33 -0600 (Mon, 23 Feb 2009) | 3 lines Add a comment, at BP's request ........ r69963 | antoine.pitrou | 2009-02-25 09:42:59 -0600 (Wed, 25 Feb 2009) | 3 lines Add a test of ABC inheritance ........ r70033 | antoine.pitrou | 2009-02-27 15:49:50 -0600 (Fri, 27 Feb 2009) | 3 lines The base classes now are ABCs. ........ r70035 | benjamin.peterson | 2009-02-27 15:57:41 -0600 (Fri, 27 Feb 2009) | 1 line good house keeping ........ r70038 | antoine.pitrou | 2009-02-27 17:05:23 -0600 (Fri, 27 Feb 2009) | 4 lines Make the buffer allocation overflow tests specific to the C implementation, since the Python implementation resizes its buffers when needed rather than allocating them up front. ........ r70041 | benjamin.peterson | 2009-02-27 18:26:12 -0600 (Fri, 27 Feb 2009) | 1 line kill java naming for sanity ........ r70042 | benjamin.peterson | 2009-02-27 18:28:53 -0600 (Fri, 27 Feb 2009) | 2 lines timingTest is superseded by iobench ........ r70043 | antoine.pitrou | 2009-02-27 19:13:50 -0600 (Fri, 27 Feb 2009) | 3 lines Remove the last traces of java naming in test_io ........ r70044 | antoine.pitrou | 2009-02-27 19:18:34 -0600 (Fri, 27 Feb 2009) | 3 lines Better resource cleanup ........ r70045 | antoine.pitrou | 2009-02-27 19:29:00 -0600 (Fri, 27 Feb 2009) | 3 lines Remove dubious uses of super(), and fix one test ........ r70046 | antoine.pitrou | 2009-02-27 19:31:00 -0600 (Fri, 27 Feb 2009) | 3 lines Bump up CHUNK_SIZE (no need to make the Python version look slower than it is) ........ r70047 | benjamin.peterson | 2009-02-27 20:03:26 -0600 (Fri, 27 Feb 2009) | 1 line fix typo ........ r70048 | benjamin.peterson | 2009-02-27 21:35:11 -0600 (Fri, 27 Feb 2009) | 1 line move code to a better place ........ r70067 | benjamin.peterson | 2009-02-28 10:43:20 -0600 (Sat, 28 Feb 2009) | 4 lines 1. make sure to undo buffered read aheads in BufferedRandom.seek() 2. refill the buffer if have <= 0 3. fix the last failing test_io test! ........ r70068 | benjamin.peterson | 2009-02-28 10:57:50 -0600 (Sat, 28 Feb 2009) | 1 line define read1() on the python implementation's BufferedIOBase ........ r70069 | benjamin.peterson | 2009-02-28 11:01:17 -0600 (Sat, 28 Feb 2009) | 1 line document read1() in BufferedIOBase ........ r70070 | benjamin.peterson | 2009-02-28 11:06:42 -0600 (Sat, 28 Feb 2009) | 1 line give credit where credit is due ........ r70075 | antoine.pitrou | 2009-02-28 13:34:59 -0600 (Sat, 28 Feb 2009) | 3 lines Amaury's name ........ r70112 | antoine.pitrou | 2009-03-02 17:11:55 -0600 (Mon, 02 Mar 2009) | 4 lines Looks like this is necessary in order to build cleanly under Windows (someone correct this if it's wrong, I'm no Windows user) ........ r70133 | benjamin.peterson | 2009-03-03 15:23:32 -0600 (Tue, 03 Mar 2009) | 1 line fix test_newline_property on _pyio.StringIO ........ r70135 | benjamin.peterson | 2009-03-03 15:47:30 -0600 (Tue, 03 Mar 2009) | 1 line fix typos and inconsistencies. thanks to Daniel Diniz ........ r70140 | benjamin.peterson | 2009-03-03 16:21:10 -0600 (Tue, 03 Mar 2009) | 1 line add the test from #5266 ........ Added: python/branches/py3k/Lib/_pyio.py - copied, changed from r69916, /python/branches/io-c/Lib/_pyio.py python/branches/py3k/Modules/_bufferedio.c - copied, changed from r68756, /python/branches/io-c/Modules/_bufferedio.c python/branches/py3k/Modules/_iobase.c - copied, changed from r68756, /python/branches/io-c/Modules/_iobase.c python/branches/py3k/Modules/_iomodule.h - copied, changed from r68756, /python/branches/io-c/Modules/_iomodule.h python/branches/py3k/Modules/_textio.c - copied, changed from r68756, /python/branches/io-c/Modules/_textio.c python/branches/py3k/Modules/io.c - copied, changed from r68756, /python/branches/io-c/Modules/io.c Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/io.rst python/branches/py3k/Lib/importlib/__init__.py python/branches/py3k/Lib/importlib/_bootstrap.py python/branches/py3k/Lib/io.py python/branches/py3k/Lib/test/test_bufio.py python/branches/py3k/Lib/test/test_descr.py python/branches/py3k/Lib/test/test_file.py python/branches/py3k/Lib/test/test_fileio.py python/branches/py3k/Lib/test/test_io.py python/branches/py3k/Lib/test/test_largefile.py python/branches/py3k/Lib/test/test_memoryio.py python/branches/py3k/Lib/test/test_univnewlines.py python/branches/py3k/Lib/test/test_uu.py python/branches/py3k/Makefile.pre.in python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/Setup.dist python/branches/py3k/Modules/_bytesio.c python/branches/py3k/Modules/_fileio.c python/branches/py3k/Modules/_stringio.c python/branches/py3k/PC/VC6/pythoncore.dsp python/branches/py3k/PC/config.c python/branches/py3k/PCbuild/pythoncore.vcproj python/branches/py3k/Python/pythonrun.c python/branches/py3k/setup.py Modified: python/branches/py3k/Doc/library/io.rst ============================================================================== --- python/branches/py3k/Doc/library/io.rst (original) +++ python/branches/py3k/Doc/library/io.rst Wed Mar 4 01:14:51 2009 @@ -6,6 +6,8 @@ .. moduleauthor:: Guido van Rossum .. moduleauthor:: Mike Verdone .. moduleauthor:: Mark Russell +.. moduleauthor:: Antoine Pitrou +.. moduleauthor:: Amaury Forgeot d'Arc .. sectionauthor:: Benjamin Peterson The :mod:`io` module provides the Python interfaces to stream handling. The @@ -364,6 +366,11 @@ A :exc:`BlockingIOError` is raised if the underlying raw stream has no data at the moment. + .. method:: read1([n]) + + Read and return up to *n* bytes, with at most one call to the underlying + raw stream's :meth:`~RawIOBase.read` method. + .. method:: readinto(b) Read up to len(b) bytes into bytearray *b* and return the number of bytes @@ -501,7 +508,7 @@ The constructor creates a :class:`BufferedWriter` for the given writeable *raw* stream. If the *buffer_size* is not given, it defaults to - :data:`DEAFULT_BUFFER_SIZE`. If *max_buffer_size* is omitted, it defaults to + :data:`DEFAULT_BUFFER_SIZE`. If *max_buffer_size* is omitted, it defaults to twice the buffer size. :class:`BufferedWriter` provides or overrides these methods in addition to Copied: python/branches/py3k/Lib/_pyio.py (from r69916, /python/branches/io-c/Lib/_pyio.py) ============================================================================== --- /python/branches/io-c/Lib/_pyio.py (original) +++ python/branches/py3k/Lib/_pyio.py Wed Mar 4 01:14:51 2009 @@ -5,18 +5,22 @@ import os import abc import codecs -#import _fileio # Import _thread instead of threading to reduce startup cost try: from _thread import allocate_lock as Lock except ImportError: from _dummy_thread import allocate_lock as Lock +import io from io import __all__ # open() uses st_blksize whenever we can DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes +# NOTE: Base classes defined here are registered with the "official" ABCs +# defined in io.py. We don't use real inheritance though, because we don't +# want to inherit the C implementations. + class BlockingIOError(IOError): @@ -259,7 +263,7 @@ stream. IOBase also supports the :keyword:`with` statement. In this example, - fp is closed after the suite of the with statment is complete: + fp is closed after the suite of the with statement is complete: with open('spam.txt', 'r') as fp: fp.write('Spam and eggs!') @@ -496,6 +500,8 @@ for line in lines: self.write(line) +io.IOBase.register(IOBase) + class RawIOBase(IOBase): @@ -551,7 +557,7 @@ """ self._unsupported("write") - +io.RawIOBase.register(RawIOBase) from _io import FileIO RawIOBase.register(FileIO) @@ -593,6 +599,10 @@ """ self._unsupported("read") + def read1(self, n: int=None) -> bytes: + """Read up to n bytes with at most one read() system call.""" + self._unsupported("read1") + def readinto(self, b: bytearray) -> int: """Read up to len(b) bytes into b. @@ -627,6 +637,8 @@ """ self._unsupported("write") +io.BufferedIOBase.register(BufferedIOBase) + class _BufferedIOMixin(BufferedIOBase): @@ -908,7 +920,7 @@ def _peek_unlocked(self, n=0): want = min(n, self.buffer_size) have = len(self._read_buf) - self._read_pos - if have < want: + if have < want or have <= 0: to_read = self.buffer_size - have current = self.raw.read(to_read) if current: @@ -921,7 +933,7 @@ # Returns up to n bytes. If at least one byte is buffered, we # only return buffered bytes. Otherwise, we do one raw read. if n < 0: - raise ValueError("number of bytes ot read must be positive") + raise ValueError("number of bytes to read must be positive") if n == 0: return b"" with self._read_lock: @@ -930,7 +942,7 @@ min(n, len(self._read_buf) - self._read_pos)) def tell(self): - return super().tell() - len(self._read_buf) + self._read_pos + return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos def seek(self, pos, whence=0): if not (0 <= whence <= 2): @@ -938,7 +950,7 @@ with self._read_lock: if whence == 1: pos -= len(self._read_buf) - self._read_pos - pos = super().seek(pos, whence) + pos = _BufferedIOMixin.seek(self, pos, whence) self._reset_read_buf() return pos @@ -948,7 +960,7 @@ The constructor creates a BufferedWriter for the given writeable raw stream. If the buffer_size is not given, it defaults to - DEAFULT_BUFFER_SIZE. If max_buffer_size is omitted, it defaults to + DEFAULT_BUFFER_SIZE. If max_buffer_size is omitted, it defaults to twice the buffer size. """ @@ -1026,14 +1038,14 @@ raise BlockingIOError(e.errno, e.strerror, written) def tell(self): - return super().tell() + len(self._write_buf) + return _BufferedIOMixin.tell(self) + len(self._write_buf) def seek(self, pos, whence=0): if not (0 <= whence <= 2): raise ValueError("invalid whence") with self._write_lock: self._flush_unlocked() - return super().seek(pos, whence) + return _BufferedIOMixin.seek(self, pos, whence) class BufferedRWPair(BufferedIOBase): @@ -1122,18 +1134,22 @@ if not (0 <= whence <= 2): raise ValueError("invalid whence") self.flush() + if self._read_buf: + # Undo read ahead. + with self._read_lock: + self.raw.seek(self._read_pos - len(self._read_buf), 1) # First do the raw seek, then empty the read buffer, so that # if the raw seek fails, we don't lose buffered data forever. pos = self.raw.seek(pos, whence) - if pos < 0: - raise IOError("seek() returned invalid position") with self._read_lock: self._reset_read_buf() + if pos < 0: + raise IOError("seek() returned invalid position") return pos def tell(self): if self._write_buf: - return super().tell() + len(self._write_buf) + return BufferedWriter.tell(self) else: return BufferedReader.tell(self) @@ -1218,6 +1234,8 @@ """ return None +io.TextIOBase.register(TextIOBase) + class IncrementalNewlineDecoder(codecs.IncrementalDecoder): r"""Codec used when reading a file in universal newlines mode. It wraps @@ -1328,7 +1346,7 @@ write contains a newline character. """ - _CHUNK_SIZE = 128 + _CHUNK_SIZE = 2048 def __init__(self, buffer, encoding=None, errors=None, newline=None, line_buffering=False): @@ -1707,7 +1725,9 @@ line = self._get_decoded_chars() start = 0 - decoder = self._decoder or self._get_decoder() + # Make the decoder if it doesn't already exist. + if not self._decoder: + self._get_decoder() pos = endpos = None while True: @@ -1762,8 +1782,7 @@ endpos = limit # reached length limit break - # No line ending seen yet - get more data - more_line = '' + # No line ending seen yet - get more data' while self._read_chunk(): if self._decoded_chars: break Modified: python/branches/py3k/Lib/importlib/__init__.py ============================================================================== --- python/branches/py3k/Lib/importlib/__init__.py (original) +++ python/branches/py3k/Lib/importlib/__init__.py Wed Mar 4 01:14:51 2009 @@ -93,12 +93,12 @@ except ImportError: raise ImportError('posix, nt, or os2 module required for importlib') _bootstrap._os = _os -import imp, sys, marshal, errno, _fileio +import imp, sys, marshal, errno, _io _bootstrap.imp = imp _bootstrap.sys = sys _bootstrap.marshal = marshal _bootstrap.errno = errno -_bootstrap._fileio = _fileio +_bootstrap._io = _io import _warnings _bootstrap._warnings = _warnings Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Wed Mar 4 01:14:51 2009 @@ -473,7 +473,7 @@ if source_path is None: return None import tokenize - with closing(_fileio._FileIO(source_path, 'r')) as file: + with closing(_io.FileIO(source_path, 'r')) as file: encoding, lines = tokenize.detect_encoding(file.readline) # XXX Will fail when passed to compile() if the encoding is # anything other than UTF-8. @@ -527,7 +527,7 @@ bytecode_path = self.bytecode_path(name) if not bytecode_path: bytecode_path = self._base_path + suffix_list(imp.PY_COMPILED)[0] - file = _fileio._FileIO(bytecode_path, 'w') + file = _io.FileIO(bytecode_path, 'w') try: with closing(file) as bytecode_file: bytecode_file.write(data) Modified: python/branches/py3k/Lib/io.py ============================================================================== --- python/branches/py3k/Lib/io.py (original) +++ python/branches/py3k/Lib/io.py Wed Mar 4 01:14:51 2009 @@ -34,9 +34,6 @@ """ # New I/O library conforming to PEP 3116. -# This is a prototype; hopefully eventually some of this will be -# reimplemented in C. - # XXX edge cases when switching between reading/writing # XXX need to support 1 meaning line-buffered # XXX whenever an argument is None, use the default value @@ -48,2091 +45,58 @@ __author__ = ("Guido van Rossum , " "Mike Verdone , " - "Mark Russell ") + "Mark Russell , " + "Antoine Pitrou , " + "Amaury Forgeotdarc ") __all__ = ["BlockingIOError", "open", "IOBase", "RawIOBase", "FileIO", "BytesIO", "StringIO", "BufferedIOBase", "BufferedReader", "BufferedWriter", "BufferedRWPair", "BufferedRandom", "TextIOBase", "TextIOWrapper"] -import os -import abc -import codecs -import _fileio -# Import _thread instead of threading to reduce startup cost -try: - from _thread import allocate_lock as Lock -except ImportError: - from _dummy_thread import allocate_lock as Lock +import _io +import abc # open() uses st_blksize whenever we can -DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes - - -class BlockingIOError(IOError): - - """Exception raised when I/O would block on a non-blocking I/O stream.""" - - def __init__(self, errno, strerror, characters_written=0): - IOError.__init__(self, errno, strerror) - self.characters_written = characters_written - - -def open(file, mode="r", buffering=None, encoding=None, errors=None, - newline=None, closefd=True): - - r"""Open file and return a stream. Raise IOError upon failure. - - file is either a text or byte string giving the name (and the path - if the file isn't in the current working directory) of the file to - be opened or an integer file descriptor of the file to be - wrapped. (If a file descriptor is given, it is closed when the - returned I/O object is closed, unless closefd is set to False.) - - mode is an optional string that specifies the mode in which the file - is opened. It defaults to 'r' which means open for reading in text - mode. Other common values are 'w' for writing (truncating the file if - it already exists), and 'a' for appending (which on some Unix systems, - means that all writes append to the end of the file regardless of the - current seek position). In text mode, if encoding is not specified the - encoding used is platform dependent. (For reading and writing raw - bytes use binary mode and leave encoding unspecified.) The available - modes are: - - ========= =============================================================== - Character Meaning - --------- --------------------------------------------------------------- - 'r' open for reading (default) - 'w' open for writing, truncating the file first - 'a' open for writing, appending to the end of the file if it exists - 'b' binary mode - 't' text mode (default) - '+' open a disk file for updating (reading and writing) - 'U' universal newline mode (for backwards compatibility; unneeded - for new code) - ========= =============================================================== - - The default mode is 'rt' (open for reading text). For binary random - access, the mode 'w+b' opens and truncates the file to 0 bytes, while - 'r+b' opens the file without truncation. - - Python distinguishes between files opened in binary and text modes, - even when the underlying operating system doesn't. Files opened in - binary mode (appending 'b' to the mode argument) return contents as - bytes objects without any decoding. In text mode (the default, or when - 't' is appended to the mode argument), the contents of the file are - returned as strings, the bytes having been first decoded using a - platform-dependent encoding or using the specified encoding if given. - - buffering is an optional integer used to set the buffering policy. By - default full buffering is on. Pass 0 to switch buffering off (only - allowed in binary mode), 1 to set line buffering, and an integer > 1 - for full buffering. - - encoding is the name of the encoding used to decode or encode the - file. This should only be used in text mode. The default encoding is - platform dependent, but any encoding supported by Python can be - passed. See the codecs module for the list of supported encodings. - - errors is an optional string that specifies how encoding errors are to - be handled---this argument should not be used in binary mode. Pass - 'strict' to raise a ValueError exception if there is an encoding error - (the default of None has the same effect), or pass 'ignore' to ignore - errors. (Note that ignoring encoding errors can lead to data loss.) - See the documentation for codecs.register for a list of the permitted - encoding error strings. - - newline controls how universal newlines works (it only applies to text - mode). It can be None, '', '\n', '\r', and '\r\n'. It works as - follows: - - * On input, if newline is None, universal newlines mode is - enabled. Lines in the input can end in '\n', '\r', or '\r\n', and - these are translated into '\n' before being returned to the - caller. If it is '', universal newline mode is enabled, but line - endings are returned to the caller untranslated. If it has any of - the other legal values, input lines are only terminated by the given - string, and the line ending is returned to the caller untranslated. - - * On output, if newline is None, any '\n' characters written are - translated to the system default line separator, os.linesep. If - newline is '', no translation takes place. If newline is any of the - other legal values, any '\n' characters written are translated to - the given string. - - If closefd is False, the underlying file descriptor will be kept open - when the file is closed. This does not work when a file name is given - and must be True in that case. - - open() returns a file object whose type depends on the mode, and - through which the standard file operations such as reading and writing - are performed. When open() is used to open a file in a text mode ('w', - 'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open - a file in a binary mode, the returned class varies: in read binary - mode, it returns a BufferedReader; in write binary and append binary - modes, it returns a BufferedWriter, and in read/write mode, it returns - a BufferedRandom. - - It is also possible to use a string or bytearray as a file for both - reading and writing. For strings StringIO can be used like a file - opened in a text mode, and for bytes a BytesIO can be used like a file - opened in a binary mode. - """ - if not isinstance(file, (str, bytes, int)): - raise TypeError("invalid file: %r" % file) - if not isinstance(mode, str): - raise TypeError("invalid mode: %r" % mode) - if buffering is not None and not isinstance(buffering, int): - raise TypeError("invalid buffering: %r" % buffering) - if encoding is not None and not isinstance(encoding, str): - raise TypeError("invalid encoding: %r" % encoding) - if errors is not None and not isinstance(errors, str): - raise TypeError("invalid errors: %r" % errors) - modes = set(mode) - if modes - set("arwb+tU") or len(mode) > len(modes): - raise ValueError("invalid mode: %r" % mode) - reading = "r" in modes - writing = "w" in modes - appending = "a" in modes - updating = "+" in modes - text = "t" in modes - binary = "b" in modes - if "U" in modes: - if writing or appending: - raise ValueError("can't use U and writing mode at once") - reading = True - if text and binary: - raise ValueError("can't have text and binary mode at once") - if reading + writing + appending > 1: - raise ValueError("can't have read/write/append mode at once") - 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 mode doesn't take an encoding argument") - if binary and errors is not None: - raise ValueError("binary mode doesn't take an errors argument") - if binary and newline is not None: - raise ValueError("binary mode doesn't take a newline argument") - raw = FileIO(file, - (reading and "r" or "") + - (writing and "w" or "") + - (appending and "a" or "") + - (updating and "+" or ""), - closefd) - if buffering is None: - buffering = -1 - line_buffering = False - if buffering == 1 or buffering < 0 and raw.isatty(): - buffering = -1 - line_buffering = True - if buffering < 0: - buffering = DEFAULT_BUFFER_SIZE - try: - bs = os.fstat(raw.fileno()).st_blksize - except (os.error, AttributeError): - pass - else: - if bs > 1: - buffering = bs - if buffering < 0: - raise ValueError("invalid buffering size") - if buffering == 0: - if binary: - return raw - raise ValueError("can't have unbuffered text I/O") - if updating: - buffer = BufferedRandom(raw, buffering) - elif writing or appending: - buffer = BufferedWriter(raw, buffering) - elif reading: - buffer = BufferedReader(raw, buffering) - else: - raise ValueError("unknown mode: %r" % mode) - if binary: - return buffer - text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering) - text.mode = mode - return text - -class _DocDescriptor: - """Helper for builtins.open.__doc__ - """ - def __get__(self, obj, typ): - return ( - "open(file, mode='r', buffering=None, encoding=None, " - "errors=None, newline=None, closefd=True)\n\n" + - open.__doc__) - -class OpenWrapper: - """Wrapper for builtins.open - - Trick so that open won't become a bound method when stored - as a class variable (as dbm.dumb does). - - See initstdio() in Python/pythonrun.c. - """ - __doc__ = _DocDescriptor() - - def __new__(cls, *args, **kwargs): - return open(*args, **kwargs) - - -class UnsupportedOperation(ValueError, IOError): +DEFAULT_BUFFER_SIZE = _io.DEFAULT_BUFFER_SIZE +BlockingIOError = _io.BlockingIOError +UnsupportedOperation = _io.UnsupportedOperation +open = _io.open +OpenWrapper = _io.open + +# Declaring ABCs in C is tricky so we do it here. +# Method descriptions and default implementations are inherited from the C +# version however. +class IOBase(_io._IOBase, metaclass=abc.ABCMeta): pass +class RawIOBase(_io._RawIOBase, IOBase): + pass -class IOBase(metaclass=abc.ABCMeta): - - """The abstract base class for all I/O classes, acting on streams of - bytes. There is no public constructor. - - This class provides dummy implementations for many methods that - derived classes can override selectively; the default implementations - represent a file that cannot be read, written or seeked. - - Even though IOBase does not declare read, readinto, or write because - their signatures will vary, implementations and clients should - consider those methods part of the interface. Also, implementations - may raise a IOError when operations they do not support are called. - - The basic type used for binary data read from or written to a file is - bytes. bytearrays are accepted too, and in some cases (such as - readinto) needed. Text I/O classes work with str data. - - Note that calling any method (even inquiries) on a closed stream is - undefined. Implementations may raise IOError in this case. - - IOBase (and its subclasses) support the iterator protocol, meaning - that an IOBase object can be iterated over yielding the lines in a - stream. - - IOBase also supports the :keyword:`with` statement. In this example, - fp is closed after the suite of the with statment is complete: - - with open('spam.txt', 'r') as fp: - fp.write('Spam and eggs!') - """ - - ### Internal ### - - def _unsupported(self, name: str) -> IOError: - """Internal: raise an exception for unsupported operations.""" - raise UnsupportedOperation("%s.%s() not supported" % - (self.__class__.__name__, name)) - - ### Positioning ### - - def seek(self, pos: int, whence: int = 0) -> int: - """Change stream position. - - Change the stream position to byte offset offset. offset is - interpreted relative to the position indicated by whence. Values - for whence are: - - * 0 -- start of stream (the default); offset should be zero or positive - * 1 -- current stream position; offset may be negative - * 2 -- end of stream; offset is usually negative - - Return the new absolute position. - """ - self._unsupported("seek") - - def tell(self) -> int: - """Return current stream position.""" - self._checkClosed() - return self.seek(0, 1) - - def truncate(self, pos: int = None) -> int: - """Truncate file to size bytes. - - Size defaults to the current IO position as reported by tell(). Return - the new size. - """ - self._unsupported("truncate") - - ### Flush and close ### - - def flush(self) -> None: - """Flush write buffers, if applicable. - - This is not implemented for read-only and non-blocking streams. - """ - # XXX Should this return the number of bytes written??? - if self.__closed: - raise ValueError("I/O operation on closed file.") - - __closed = False - - def close(self) -> None: - """Flush and close the IO object. - - This method has no effect if the file is already closed. - """ - if not self.__closed: - try: - self.flush() - except IOError: - pass # If flush() fails, just give up - self.__closed = True - - def __del__(self) -> None: - """Destructor. Calls close().""" - # The try/except block is in case this is called at program - # exit time, when it's possible that globals have already been - # deleted, and then the close() call might fail. Since - # there's nothing we can do about such failures and they annoy - # the end users, we suppress the traceback. - try: - self.close() - except: - pass - - ### Inquiries ### - - def seekable(self) -> bool: - """Return whether object supports random access. - - If False, seek(), tell() and truncate() will raise IOError. - This method may need to do a test seek(). - """ - return False - - def _checkSeekable(self, msg=None): - """Internal: raise an IOError if file is not seekable - """ - if not self.seekable(): - raise IOError("File or stream is not seekable." - if msg is None else msg) - - - def readable(self) -> bool: - """Return whether object was opened for reading. - - If False, read() will raise IOError. - """ - return False - - def _checkReadable(self, msg=None): - """Internal: raise an IOError if file is not readable - """ - if not self.readable(): - raise IOError("File or stream is not readable." - if msg is None else msg) - - def writable(self) -> bool: - """Return whether object was opened for writing. - - If False, write() and truncate() will raise IOError. - """ - return False - - def _checkWritable(self, msg=None): - """Internal: raise an IOError if file is not writable - """ - if not self.writable(): - raise IOError("File or stream is not writable." - if msg is None else msg) - - @property - def closed(self): - """closed: bool. True iff the file has been closed. - - For backwards compatibility, this is a property, not a predicate. - """ - return self.__closed - - def _checkClosed(self, msg=None): - """Internal: raise an ValueError if file is closed - """ - if self.closed: - raise ValueError("I/O operation on closed file." - if msg is None else msg) - - ### Context manager ### - - def __enter__(self) -> "IOBase": # That's a forward reference - """Context management protocol. Returns self.""" - self._checkClosed() - return self - - def __exit__(self, *args) -> None: - """Context management protocol. Calls close()""" - self.close() - - ### Lower-level APIs ### - - # XXX Should these be present even if unimplemented? - - def fileno(self) -> int: - """Returns underlying file descriptor if one exists. - - An IOError is raised if the IO object does not use a file descriptor. - """ - self._unsupported("fileno") - - def isatty(self) -> bool: - """Return whether this is an 'interactive' stream. - - Return False if it can't be determined. - """ - self._checkClosed() - return False - - ### Readline[s] and writelines ### - - def readline(self, limit: int = -1) -> bytes: - r"""Read and return a line from the stream. - - If limit is specified, at most limit bytes will be read. - - The line terminator is always b'\n' for binary files; for text - files, the newlines argument to open can be used to select the line - terminator(s) recognized. - """ - # For backwards compatibility, a (slowish) readline(). - if hasattr(self, "peek"): - def nreadahead(): - readahead = self.peek(1) - if not readahead: - return 1 - n = (readahead.find(b"\n") + 1) or len(readahead) - if limit >= 0: - n = min(n, limit) - return n - else: - def nreadahead(): - return 1 - if limit is None: - limit = -1 - res = bytearray() - while limit < 0 or len(res) < limit: - b = self.read(nreadahead()) - if not b: - break - res += b - if res.endswith(b"\n"): - break - return bytes(res) - - def __iter__(self): - self._checkClosed() - return self - - def __next__(self): - line = self.readline() - if not line: - raise StopIteration - return line - - def readlines(self, hint=None): - """Return a list of lines from the stream. - - hint can be specified to control the number of lines read: no more - lines will be read if the total size (in bytes/characters) of all - lines so far exceeds hint. - """ - if hint is None or hint <= 0: - return list(self) - n = 0 - lines = [] - for line in self: - lines.append(line) - n += len(line) - if n >= hint: - break - return lines - - def writelines(self, lines): - self._checkClosed() - for line in lines: - self.write(line) - - -class RawIOBase(IOBase): - - """Base class for raw binary I/O.""" - - # The read() method is implemented by calling readinto(); derived - # classes that want to support read() only need to implement - # readinto() as a primitive operation. In general, readinto() can be - # more efficient than read(). - - # (It would be tempting to also provide an implementation of - # readinto() in terms of read(), in case the latter is a more suitable - # primitive operation, but that would lead to nasty recursion in case - # a subclass doesn't implement either.) - - def read(self, n: int = -1) -> bytes: - """Read and return up to n bytes. - - Returns an empty bytes object on EOF, or None if the object is - set not to block and has no data to read. - """ - self._checkClosed() - if n is None: - n = -1 - if n < 0: - return self.readall() - b = bytearray(n.__index__()) - n = self.readinto(b) - del b[n:] - return bytes(b) - - def readall(self): - """Read until EOF, using multiple read() call.""" - self._checkClosed() - res = bytearray() - while True: - data = self.read(DEFAULT_BUFFER_SIZE) - if not data: - break - res += data - return bytes(res) - - def readinto(self, b: bytearray) -> int: - """Read up to len(b) bytes into b. - - Returns number of bytes read (0 for EOF), or None if the object - is set not to block as has no data to read. - """ - self._unsupported("readinto") - - def write(self, b: bytes) -> int: - """Write the given buffer to the IO stream. - - Returns the number of bytes written, which may be less than len(b). - """ - self._unsupported("write") - - -class FileIO(_fileio._FileIO, RawIOBase): - - """Raw I/O implementation for OS files.""" - - # This multiply inherits from _FileIO and RawIOBase to make - # isinstance(io.FileIO(), io.RawIOBase) return True without requiring - # that _fileio._FileIO inherits from io.RawIOBase (which would be hard - # to do since _fileio.c is written in C). - - def __init__(self, name, mode="r", closefd=True): - _fileio._FileIO.__init__(self, name, mode, closefd) - self._name = name - - def close(self): - _fileio._FileIO.close(self) - RawIOBase.close(self) - - @property - def name(self): - return self._name - - -class BufferedIOBase(IOBase): - - """Base class for buffered IO objects. - - The main difference with RawIOBase is that the read() method - supports omitting the size argument, and does not have a default - implementation that defers to readinto(). - - In addition, read(), readinto() and write() may raise - BlockingIOError if the underlying raw stream is in non-blocking - mode and not ready; unlike their raw counterparts, they will never - return None. - - A typical implementation should not inherit from a RawIOBase - implementation, but wrap one. - """ - - def read(self, n: int = None) -> bytes: - """Read and return up to n bytes. - - If the argument is omitted, None, or negative, reads and - returns all data until EOF. - - If the argument is positive, and the underlying raw stream is - not 'interactive', multiple raw reads may be issued to satisfy - the byte count (unless EOF is reached first). But for - interactive raw streams (XXX and for pipes?), at most one raw - read will be issued, and a short result does not imply that - EOF is imminent. - - Returns an empty bytes array on EOF. - - Raises BlockingIOError if the underlying raw stream has no - data at the moment. - """ - self._unsupported("read") - - def readinto(self, b: bytearray) -> int: - """Read up to len(b) bytes into b. - - Like read(), this may issue multiple reads to the underlying raw - stream, unless the latter is 'interactive'. - - Returns the number of bytes read (0 for EOF). - - Raises BlockingIOError if the underlying raw stream has no - data at the moment. - """ - # XXX This ought to work with anything that supports the buffer API - self._checkClosed() - data = self.read(len(b)) - n = len(data) - try: - b[:n] = data - except TypeError as err: - import array - if not isinstance(b, array.array): - raise err - b[:n] = array.array('b', data) - return n - - def write(self, b: bytes) -> int: - """Write the given buffer to the IO stream. - - Return the number of bytes written, which is never less than - len(b). - - Raises BlockingIOError if the buffer is full and the - underlying raw stream cannot accept more data at the moment. - """ - self._unsupported("write") - - -class _BufferedIOMixin(BufferedIOBase): - - """A mixin implementation of BufferedIOBase with an underlying raw stream. - - This passes most requests on to the underlying raw stream. It - does *not* provide implementations of read(), readinto() or - write(). - """ - - def __init__(self, raw): - self.raw = raw - - ### Positioning ### - - def seek(self, pos, whence=0): - return self.raw.seek(pos, whence) - - def tell(self): - return self.raw.tell() - - def truncate(self, pos=None): - # Flush the stream. We're mixing buffered I/O with lower-level I/O, - # and a flush may be necessary to synch both views of the current - # file state. - self.flush() - - if pos is None: - pos = self.tell() - # XXX: Should seek() be used, instead of passing the position - # XXX directly to truncate? - return self.raw.truncate(pos) - - ### Flush and close ### - - def flush(self): - self.raw.flush() - - def close(self): - if not self.closed: - try: - self.flush() - except IOError: - pass # If flush() fails, just give up - self.raw.close() - - ### Inquiries ### - - def seekable(self): - return self.raw.seekable() - - def readable(self): - return self.raw.readable() - - def writable(self): - return self.raw.writable() - - @property - def closed(self): - return self.raw.closed - - @property - def name(self): - return self.raw.name - - @property - def mode(self): - return self.raw.mode - - ### Lower-level APIs ### - - def fileno(self): - return self.raw.fileno() - - def isatty(self): - return self.raw.isatty() - - -class _BytesIO(BufferedIOBase): - - """Buffered I/O implementation using an in-memory bytes buffer.""" - - def __init__(self, initial_bytes=None): - buf = bytearray() - if initial_bytes is not None: - buf += initial_bytes - self._buffer = buf - self._pos = 0 - - def getvalue(self): - """Return the bytes value (contents) of the buffer - """ - self._checkClosed() - return bytes(self._buffer) - - def read(self, n=None): - self._checkClosed() - if n is None: - n = -1 - if n < 0: - n = len(self._buffer) - if len(self._buffer) <= self._pos: - return b"" - newpos = min(len(self._buffer), self._pos + n) - b = self._buffer[self._pos : newpos] - self._pos = newpos - return bytes(b) - - def read1(self, n): - """This is the same as read. - """ - return self.read(n) - - def write(self, b): - self._checkClosed() - if isinstance(b, str): - raise TypeError("can't write str to binary stream") - n = len(b) - if n == 0: - return 0 - pos = self._pos - if pos > len(self._buffer): - # Inserts null bytes between the current end of the file - # and the new write position. - padding = b'\x00' * (pos - len(self._buffer)) - self._buffer += padding - self._buffer[pos:pos + n] = b - self._pos += n - return n - - def seek(self, pos, whence=0): - self._checkClosed() - try: - pos = pos.__index__() - except AttributeError as err: - raise TypeError("an integer is required") from err - if whence == 0: - if pos < 0: - raise ValueError("negative seek position %r" % (pos,)) - self._pos = pos - elif whence == 1: - self._pos = max(0, self._pos + pos) - elif whence == 2: - self._pos = max(0, len(self._buffer) + pos) - else: - raise ValueError("invalid whence value") - return self._pos - - def tell(self): - self._checkClosed() - return self._pos - - def truncate(self, pos=None): - self._checkClosed() - if pos is None: - pos = self._pos - elif pos < 0: - raise ValueError("negative truncate position %r" % (pos,)) - del self._buffer[pos:] - return self.seek(pos) - - def readable(self): - return True - - def writable(self): - return True - - def seekable(self): - return True - -# Use the faster implementation of BytesIO if available -try: - import _bytesio - - class BytesIO(_bytesio._BytesIO, BufferedIOBase): - __doc__ = _bytesio._BytesIO.__doc__ - -except ImportError: - BytesIO = _BytesIO - - -class BufferedReader(_BufferedIOMixin): - - """BufferedReader(raw[, buffer_size]) - - A buffer for a readable, sequential BaseRawIO object. - - The constructor creates a BufferedReader for the given readable raw - stream and buffer_size. If buffer_size is omitted, DEFAULT_BUFFER_SIZE - is used. - """ - - def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): - """Create a new buffered reader using the given readable raw IO object. - """ - raw._checkReadable() - _BufferedIOMixin.__init__(self, raw) - self.buffer_size = buffer_size - self._reset_read_buf() - self._read_lock = Lock() - - def _reset_read_buf(self): - self._read_buf = b"" - self._read_pos = 0 - - def read(self, n=None): - """Read n bytes. - - Returns exactly n bytes of data unless the underlying raw IO - stream reaches EOF or if the call would block in non-blocking - mode. If n is negative, read until EOF or until read() would - block. - """ - self._checkClosed() - with self._read_lock: - return self._read_unlocked(n) - - def _read_unlocked(self, n=None): - nodata_val = b"" - empty_values = (b"", None) - buf = self._read_buf - pos = self._read_pos - - # Special case for when the number of bytes to read is unspecified. - if n is None or n == -1: - self._reset_read_buf() - chunks = [buf[pos:]] # Strip the consumed bytes. - current_size = 0 - while True: - # Read until EOF or until read() would block. - chunk = self.raw.read() - if chunk in empty_values: - nodata_val = chunk - break - current_size += len(chunk) - chunks.append(chunk) - return b"".join(chunks) or nodata_val - - # The number of bytes to read is specified, return at most n bytes. - avail = len(buf) - pos # Length of the available buffered data. - if n <= avail: - # Fast path: the data to read is fully buffered. - self._read_pos += n - return buf[pos:pos+n] - # Slow path: read from the stream until enough bytes are read, - # or until an EOF occurs or until read() would block. - chunks = [buf[pos:]] - wanted = max(self.buffer_size, n) - while avail < n: - chunk = self.raw.read(wanted) - if chunk in empty_values: - nodata_val = chunk - break - avail += len(chunk) - chunks.append(chunk) - # n is more then avail only when an EOF occurred or when - # read() would have blocked. - n = min(n, avail) - out = b"".join(chunks) - self._read_buf = out[n:] # Save the extra data in the buffer. - self._read_pos = 0 - return out[:n] if out else nodata_val - - def peek(self, n=0): - """Returns buffered bytes without advancing the position. - - The argument indicates a desired minimal number of bytes; we - do at most one raw read to satisfy it. We never return more - than self.buffer_size. - """ - self._checkClosed() - with self._read_lock: - return self._peek_unlocked(n) - - def _peek_unlocked(self, n=0): - want = min(n, self.buffer_size) - have = len(self._read_buf) - self._read_pos - if have < want: - to_read = self.buffer_size - have - current = self.raw.read(to_read) - if current: - self._read_buf = self._read_buf[self._read_pos:] + current - self._read_pos = 0 - return self._read_buf[self._read_pos:] - - def read1(self, n): - """Reads up to n bytes, with at most one read() system call.""" - # Returns up to n bytes. If at least one byte is buffered, we - # only return buffered bytes. Otherwise, we do one raw read. - self._checkClosed() - if n <= 0: - return b"" - with self._read_lock: - self._peek_unlocked(1) - return self._read_unlocked( - min(n, len(self._read_buf) - self._read_pos)) - - def tell(self): - self._checkClosed() - return self.raw.tell() - len(self._read_buf) + self._read_pos - - def seek(self, pos, whence=0): - self._checkClosed() - with self._read_lock: - if whence == 1: - pos -= len(self._read_buf) - self._read_pos - pos = self.raw.seek(pos, whence) - self._reset_read_buf() - return pos - - -class BufferedWriter(_BufferedIOMixin): - - """A buffer for a writeable sequential RawIO object. - - The constructor creates a BufferedWriter for the given writeable raw - stream. If the buffer_size is not given, it defaults to - DEAFULT_BUFFER_SIZE. If max_buffer_size is omitted, it defaults to - twice the buffer size. - """ - - def __init__(self, raw, - buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): - raw._checkWritable() - _BufferedIOMixin.__init__(self, raw) - self.buffer_size = buffer_size - self.max_buffer_size = (2*buffer_size - if max_buffer_size is None - else max_buffer_size) - self._write_buf = bytearray() - self._write_lock = Lock() - - def write(self, b): - self._checkClosed() - if isinstance(b, str): - raise TypeError("can't write str to binary stream") - with self._write_lock: - # XXX we can implement some more tricks to try and avoid - # partial writes - if len(self._write_buf) > self.buffer_size: - # We're full, so let's pre-flush the buffer - try: - self._flush_unlocked() - except BlockingIOError as e: - # We can't accept anything else. - # XXX Why not just let the exception pass through? - raise BlockingIOError(e.errno, e.strerror, 0) - before = len(self._write_buf) - self._write_buf.extend(b) - written = len(self._write_buf) - before - if len(self._write_buf) > self.buffer_size: - try: - self._flush_unlocked() - except BlockingIOError as e: - if len(self._write_buf) > self.max_buffer_size: - # We've hit max_buffer_size. We have to accept a - # partial write and cut back our buffer. - overage = len(self._write_buf) - self.max_buffer_size - self._write_buf = self._write_buf[:self.max_buffer_size] - raise BlockingIOError(e.errno, e.strerror, overage) - return written - - def truncate(self, pos=None): - self._checkClosed() - with self._write_lock: - self._flush_unlocked() - if pos is None: - pos = self.raw.tell() - return self.raw.truncate(pos) - - def flush(self): - self._checkClosed() - with self._write_lock: - self._flush_unlocked() - - def _flush_unlocked(self): - written = 0 - try: - while self._write_buf: - n = self.raw.write(self._write_buf) - del self._write_buf[:n] - written += n - except BlockingIOError as e: - n = e.characters_written - del self._write_buf[:n] - written += n - raise BlockingIOError(e.errno, e.strerror, written) - - def tell(self): - self._checkClosed() - return self.raw.tell() + len(self._write_buf) - - def seek(self, pos, whence=0): - self._checkClosed() - with self._write_lock: - self._flush_unlocked() - return self.raw.seek(pos, whence) - - -class BufferedRWPair(BufferedIOBase): - - """A buffered reader and writer object together. - - A buffered reader object and buffered writer object put together to - form a sequential IO object that can read and write. This is typically - used with a socket or two-way pipe. - - reader and writer are RawIOBase objects that are readable and - writeable respectively. If the buffer_size is omitted it defaults to - DEFAULT_BUFFER_SIZE. The max_buffer_size (for the buffered writer) - defaults to twice the buffer size. - """ - - # XXX The usefulness of this (compared to having two separate IO - # objects) is questionable. - - def __init__(self, reader, writer, - buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): - """Constructor. - - The arguments are two RawIO instances. - """ - reader._checkReadable() - writer._checkWritable() - self.reader = BufferedReader(reader, buffer_size) - self.writer = BufferedWriter(writer, buffer_size, max_buffer_size) - - def read(self, n=None): - if n is None: - n = -1 - return self.reader.read(n) - - def readinto(self, b): - return self.reader.readinto(b) - - def write(self, b): - return self.writer.write(b) - - def peek(self, n=0): - return self.reader.peek(n) - - def read1(self, n): - return self.reader.read1(n) - - def readable(self): - return self.reader.readable() - - def writable(self): - return self.writer.writable() - - def flush(self): - return self.writer.flush() - - def close(self): - self.writer.close() - self.reader.close() - - def isatty(self): - return self.reader.isatty() or self.writer.isatty() - - @property - def closed(self): - return self.writer.closed - - -class BufferedRandom(BufferedWriter, BufferedReader): - - """A buffered interface to random access streams. - - The constructor creates a reader and writer for a seekable stream, - raw, given in the first argument. If the buffer_size is omitted it - defaults to DEFAULT_BUFFER_SIZE. The max_buffer_size (for the buffered - writer) defaults to twice the buffer size. - """ - - def __init__(self, raw, - buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): - raw._checkSeekable() - BufferedReader.__init__(self, raw, buffer_size) - BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size) - - def seek(self, pos, whence=0): - self.flush() - # First do the raw seek, then empty the read buffer, so that - # if the raw seek fails, we don't lose buffered data forever. - pos = self.raw.seek(pos, whence) - with self._read_lock: - self._reset_read_buf() - return pos - - def tell(self): - self._checkClosed() - if self._write_buf: - return self.raw.tell() + len(self._write_buf) - else: - return BufferedReader.tell(self) - - def truncate(self, pos=None): - if pos is None: - pos = self.tell() - # Use seek to flush the read buffer. - self.seek(pos) - return BufferedWriter.truncate(self) - - def read(self, n=None): - if n is None: - n = -1 - self.flush() - return BufferedReader.read(self, n) - - def readinto(self, b): - self.flush() - return BufferedReader.readinto(self, b) - - def peek(self, n=0): - self.flush() - return BufferedReader.peek(self, n) - - def read1(self, n): - self.flush() - return BufferedReader.read1(self, n) - - def write(self, b): - self._checkClosed() - if self._read_buf: - # Undo readahead - with self._read_lock: - self.raw.seek(self._read_pos - len(self._read_buf), 1) - self._reset_read_buf() - return BufferedWriter.write(self, b) - - -class TextIOBase(IOBase): - - """Base class for text I/O. - - This class provides a character and line based interface to stream - I/O. There is no readinto method because Python's character strings - are immutable. There is no public constructor. - """ - - def read(self, n: int = -1) -> str: - """Read at most n characters from stream. - - Read from underlying buffer until we have n characters or we hit EOF. - If n is negative or omitted, read until EOF. - """ - self._unsupported("read") - - def write(self, s: str) -> int: - """Write string s to stream.""" - self._unsupported("write") - - def truncate(self, pos: int = None) -> int: - """Truncate size to pos.""" - self._unsupported("truncate") - - def readline(self) -> str: - """Read until newline or EOF. - - Returns an empty string if EOF is hit immediately. - """ - self._unsupported("readline") - - @property - def encoding(self): - """Subclasses should override.""" - return None - - @property - def newlines(self): - """Line endings translated so far. - - Only line endings translated during reading are considered. - - Subclasses should override. - """ - return None - - -class IncrementalNewlineDecoder(codecs.IncrementalDecoder): - r"""Codec used when reading a file in universal newlines mode. It wraps - another incremental decoder, translating \r\n and \r into \n. It also - records the types of newlines encountered. When used with - translate=False, it ensures that the newline sequence is returned in - one piece. - """ - def __init__(self, decoder, translate, errors='strict'): - codecs.IncrementalDecoder.__init__(self, errors=errors) - self.translate = translate - self.decoder = decoder - self.seennl = 0 - self.pendingcr = False - - def decode(self, input, final=False): - # decode input (with the eventual \r from a previous pass) - output = self.decoder.decode(input, final=final) - if self.pendingcr and (output or final): - output = "\r" + output - self.pendingcr = False - - # retain last \r even when not translating data: - # then readline() is sure to get \r\n in one pass - if output.endswith("\r") and not final: - output = output[:-1] - self.pendingcr = True - - # Record which newlines are read - crlf = output.count('\r\n') - cr = output.count('\r') - crlf - lf = output.count('\n') - crlf - self.seennl |= (lf and self._LF) | (cr and self._CR) \ - | (crlf and self._CRLF) - - if self.translate: - if crlf: - output = output.replace("\r\n", "\n") - if cr: - output = output.replace("\r", "\n") - - return output - - def getstate(self): - buf, flag = self.decoder.getstate() - flag <<= 1 - if self.pendingcr: - flag |= 1 - return buf, flag - - def setstate(self, state): - buf, flag = state - self.pendingcr = bool(flag & 1) - self.decoder.setstate((buf, flag >> 1)) - - def reset(self): - self.seennl = 0 - self.pendingcr = False - self.decoder.reset() - - _LF = 1 - _CR = 2 - _CRLF = 4 - - @property - def newlines(self): - return (None, - "\n", - "\r", - ("\r", "\n"), - "\r\n", - ("\n", "\r\n"), - ("\r", "\r\n"), - ("\r", "\n", "\r\n") - )[self.seennl] - - -class TextIOWrapper(TextIOBase): - - r"""Character and line based layer over a BufferedIOBase object, buffer. - - encoding gives the name of the encoding that the stream will be - decoded or encoded with. It defaults to locale.getpreferredencoding. - - errors determines the strictness of encoding and decoding (see the - codecs.register) and defaults to "strict". - - newline can be None, '', '\n', '\r', or '\r\n'. It controls the - handling of line endings. If it is None, universal newlines is - enabled. With this enabled, on input, the lines endings '\n', '\r', - or '\r\n' are translated to '\n' before being returned to the - caller. Conversely, on output, '\n' is translated to the system - default line separator, os.linesep. If newline is any other of its - legal values, that newline becomes the newline when the file is read - and it is returned untranslated. On output, '\n' is converted to the - newline. - - If line_buffering is True, a call to flush is implied when a call to - write contains a newline character. - """ - - _CHUNK_SIZE = 2048 - - def __init__(self, buffer, encoding=None, errors=None, newline=None, - line_buffering=False): - if newline not in (None, "", "\n", "\r", "\r\n"): - raise ValueError("illegal newline value: %r" % (newline,)) - if encoding is None: - try: - encoding = os.device_encoding(buffer.fileno()) - except (AttributeError, UnsupportedOperation): - pass - if encoding is None: - try: - import locale - except ImportError: - # Importing locale may fail if Python is being built - encoding = "ascii" - else: - encoding = locale.getpreferredencoding() - - if not isinstance(encoding, str): - raise ValueError("invalid encoding: %r" % encoding) - - if errors is None: - errors = "strict" - else: - if not isinstance(errors, str): - raise ValueError("invalid errors: %r" % errors) - - self.buffer = buffer - self._line_buffering = line_buffering - self._encoding = encoding - self._errors = errors - self._readuniversal = not newline - self._readtranslate = newline is None - self._readnl = newline - self._writetranslate = newline != '' - self._writenl = newline or os.linesep - self._encoder = None - self._decoder = None - self._decoded_chars = '' # buffer for text returned from decoder - self._decoded_chars_used = 0 # offset into _decoded_chars for read() - self._snapshot = None # info for reconstructing decoder state - self._seekable = self._telling = self.buffer.seekable() - - # self._snapshot is either None, or a tuple (dec_flags, next_input) - # where dec_flags is the second (integer) item of the decoder state - # and next_input is the chunk of input bytes that comes next after the - # snapshot point. We use this to reconstruct decoder states in tell(). - - # Naming convention: - # - "bytes_..." for integer variables that count input bytes - # - "chars_..." for integer variables that count decoded characters - - @property - def encoding(self): - return self._encoding - - @property - def errors(self): - return self._errors - - @property - def line_buffering(self): - return self._line_buffering - - def seekable(self): - return self._seekable - - def readable(self): - return self.buffer.readable() - - def writable(self): - return self.buffer.writable() - - def flush(self): - self.buffer.flush() - self._telling = self._seekable - - def close(self): - try: - self.flush() - except: - pass # If flush() fails, just give up - self.buffer.close() - - @property - def closed(self): - return self.buffer.closed - - @property - def name(self): - return self.buffer.name - - def fileno(self): - return self.buffer.fileno() - - def isatty(self): - return self.buffer.isatty() - - def write(self, s: str): - self._checkClosed() - if not isinstance(s, str): - raise TypeError("can't write %s to text stream" % - s.__class__.__name__) - length = len(s) - haslf = (self._writetranslate or self._line_buffering) and "\n" in s - if haslf and self._writetranslate and self._writenl != "\n": - s = s.replace("\n", self._writenl) - encoder = self._encoder or self._get_encoder() - # XXX What if we were just reading? - b = encoder.encode(s) - self.buffer.write(b) - if self._line_buffering and (haslf or "\r" in s): - self.flush() - self._snapshot = None - if self._decoder: - self._decoder.reset() - return length - - def _get_encoder(self): - make_encoder = codecs.getincrementalencoder(self._encoding) - self._encoder = make_encoder(self._errors) - return self._encoder - - def _get_decoder(self): - make_decoder = codecs.getincrementaldecoder(self._encoding) - decoder = make_decoder(self._errors) - if self._readuniversal: - decoder = IncrementalNewlineDecoder(decoder, self._readtranslate) - self._decoder = decoder - return decoder - - # The following three methods implement an ADT for _decoded_chars. - # Text returned from the decoder is buffered here until the client - # requests it by calling our read() or readline() method. - def _set_decoded_chars(self, chars): - """Set the _decoded_chars buffer.""" - self._decoded_chars = chars - self._decoded_chars_used = 0 - - def _get_decoded_chars(self, n=None): - """Advance into the _decoded_chars buffer.""" - offset = self._decoded_chars_used - if n is None: - chars = self._decoded_chars[offset:] - else: - chars = self._decoded_chars[offset:offset + n] - self._decoded_chars_used += len(chars) - return chars - - def _rewind_decoded_chars(self, n): - """Rewind the _decoded_chars buffer.""" - if self._decoded_chars_used < n: - raise AssertionError("rewind decoded_chars out of bounds") - self._decoded_chars_used -= n - - def _read_chunk(self): - """ - Read and decode the next chunk of data from the BufferedReader. - """ - - # The return value is True unless EOF was reached. The decoded - # string is placed in self._decoded_chars (replacing its previous - # value). The entire input chunk is sent to the decoder, though - # some of it may remain buffered in the decoder, yet to be - # converted. - - if self._decoder is None: - raise ValueError("no decoder") - - if self._telling: - # To prepare for tell(), we need to snapshot a point in the - # file where the decoder's input buffer is empty. - - dec_buffer, dec_flags = self._decoder.getstate() - # Given this, we know there was a valid snapshot point - # len(dec_buffer) bytes ago with decoder state (b'', dec_flags). - - # Read a chunk, decode it, and put the result in self._decoded_chars. - input_chunk = self.buffer.read1(self._CHUNK_SIZE) - eof = not input_chunk - self._set_decoded_chars(self._decoder.decode(input_chunk, eof)) - - if self._telling: - # At the snapshot point, len(dec_buffer) bytes before the read, - # the next input to be decoded is dec_buffer + input_chunk. - self._snapshot = (dec_flags, dec_buffer + input_chunk) - - return not eof - - def _pack_cookie(self, position, dec_flags=0, - bytes_to_feed=0, need_eof=0, chars_to_skip=0): - # The meaning of a tell() cookie is: seek to position, set the - # decoder flags to dec_flags, read bytes_to_feed bytes, feed them - # into the decoder with need_eof as the EOF flag, then skip - # chars_to_skip characters of the decoded result. For most simple - # decoders, tell() will often just give a byte offset in the file. - return (position | (dec_flags<<64) | (bytes_to_feed<<128) | - (chars_to_skip<<192) | bool(need_eof)<<256) - - def _unpack_cookie(self, bigint): - rest, position = divmod(bigint, 1<<64) - rest, dec_flags = divmod(rest, 1<<64) - rest, bytes_to_feed = divmod(rest, 1<<64) - need_eof, chars_to_skip = divmod(rest, 1<<64) - return position, dec_flags, bytes_to_feed, need_eof, chars_to_skip - - def tell(self): - self._checkClosed() - if not self._seekable: - raise IOError("underlying stream is not seekable") - if not self._telling: - raise IOError("telling position disabled by next() call") - self.flush() - position = self.buffer.tell() - decoder = self._decoder - if decoder is None or self._snapshot is None: - if self._decoded_chars: - # This should never happen. - raise AssertionError("pending decoded text") - return position - - # Skip backward to the snapshot point (see _read_chunk). - dec_flags, next_input = self._snapshot - position -= len(next_input) - - # How many decoded characters have been used up since the snapshot? - chars_to_skip = self._decoded_chars_used - if chars_to_skip == 0: - # We haven't moved from the snapshot point. - return self._pack_cookie(position, dec_flags) - - # Starting from the snapshot position, we will walk the decoder - # forward until it gives us enough decoded characters. - saved_state = decoder.getstate() - try: - # Note our initial start point. - decoder.setstate((b'', dec_flags)) - start_pos = position - start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0 - need_eof = 0 - - # Feed the decoder one byte at a time. As we go, note the - # nearest "safe start point" before the current location - # (a point where the decoder has nothing buffered, so seek() - # can safely start from there and advance to this location). - next_byte = bytearray(1) - for next_byte[0] in next_input: - bytes_fed += 1 - chars_decoded += len(decoder.decode(next_byte)) - dec_buffer, dec_flags = decoder.getstate() - if not dec_buffer and chars_decoded <= chars_to_skip: - # Decoder buffer is empty, so this is a safe start point. - start_pos += bytes_fed - chars_to_skip -= chars_decoded - start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0 - if chars_decoded >= chars_to_skip: - break - else: - # We didn't get enough decoded data; signal EOF to get more. - chars_decoded += len(decoder.decode(b'', final=True)) - need_eof = 1 - if chars_decoded < chars_to_skip: - raise IOError("can't reconstruct logical file position") - - # The returned cookie corresponds to the last safe start point. - return self._pack_cookie( - start_pos, start_flags, bytes_fed, need_eof, chars_to_skip) - finally: - decoder.setstate(saved_state) - - def truncate(self, pos=None): - self.flush() - if pos is None: - pos = self.tell() - self.seek(pos) - return self.buffer.truncate() - - def seek(self, cookie, whence=0): - self._checkClosed() - if not self._seekable: - raise IOError("underlying stream is not seekable") - if whence == 1: # seek relative to current position - if cookie != 0: - raise IOError("can't do nonzero cur-relative seeks") - # Seeking to the current position should attempt to - # sync the underlying buffer with the current position. - whence = 0 - cookie = self.tell() - if whence == 2: # seek relative to end of file - if cookie != 0: - raise IOError("can't do nonzero end-relative seeks") - self.flush() - position = self.buffer.seek(0, 2) - self._set_decoded_chars('') - self._snapshot = None - if self._decoder: - self._decoder.reset() - return position - if whence != 0: - raise ValueError("invalid whence (%r, should be 0, 1 or 2)" % - (whence,)) - if cookie < 0: - raise ValueError("negative seek position %r" % (cookie,)) - self.flush() - - # The strategy of seek() is to go back to the safe start point - # and replay the effect of read(chars_to_skip) from there. - start_pos, dec_flags, bytes_to_feed, need_eof, chars_to_skip = \ - self._unpack_cookie(cookie) - - # Seek back to the safe start point. - self.buffer.seek(start_pos) - self._set_decoded_chars('') - self._snapshot = None - - # Restore the decoder to its state from the safe start point. - if self._decoder or dec_flags or chars_to_skip: - self._decoder = self._decoder or self._get_decoder() - self._decoder.setstate((b'', dec_flags)) - self._snapshot = (dec_flags, b'') - - if chars_to_skip: - # Just like _read_chunk, feed the decoder and save a snapshot. - input_chunk = self.buffer.read(bytes_to_feed) - self._set_decoded_chars( - self._decoder.decode(input_chunk, need_eof)) - self._snapshot = (dec_flags, input_chunk) - - # Skip chars_to_skip of the decoded characters. - if len(self._decoded_chars) < chars_to_skip: - raise IOError("can't restore logical file position") - self._decoded_chars_used = chars_to_skip - - return cookie - - def read(self, n=None): - self._checkClosed() - if n is None: - n = -1 - decoder = self._decoder or self._get_decoder() - if n < 0: - # Read everything. - result = (self._get_decoded_chars() + - decoder.decode(self.buffer.read(), final=True)) - self._set_decoded_chars('') - self._snapshot = None - return result - else: - # Keep reading chunks until we have n characters to return. - eof = False - result = self._get_decoded_chars(n) - while len(result) < n and not eof: - eof = not self._read_chunk() - result += self._get_decoded_chars(n - len(result)) - return result - - def __next__(self): - self._checkClosed() - self._telling = False - line = self.readline() - if not line: - self._snapshot = None - self._telling = self._seekable - raise StopIteration - return line - - def readline(self, limit=None): - self._checkClosed() - if limit is None: - limit = -1 - - # Grab all the decoded text (we will rewind any extra bits later). - line = self._get_decoded_chars() - - start = 0 - decoder = self._decoder or self._get_decoder() - - pos = endpos = None - while True: - if self._readtranslate: - # Newlines are already translated, only search for \n - pos = line.find('\n', start) - if pos >= 0: - endpos = pos + 1 - break - else: - start = len(line) - - elif self._readuniversal: - # Universal newline search. Find any of \r, \r\n, \n - # The decoder ensures that \r\n are not split in two pieces - - # In C we'd look for these in parallel of course. - nlpos = line.find("\n", start) - crpos = line.find("\r", start) - if crpos == -1: - if nlpos == -1: - # Nothing found - start = len(line) - else: - # Found \n - endpos = nlpos + 1 - break - elif nlpos == -1: - # Found lone \r - endpos = crpos + 1 - break - elif nlpos < crpos: - # Found \n - endpos = nlpos + 1 - break - elif nlpos == crpos + 1: - # Found \r\n - endpos = crpos + 2 - break - else: - # Found \r - endpos = crpos + 1 - break - else: - # non-universal - pos = line.find(self._readnl) - if pos >= 0: - endpos = pos + len(self._readnl) - break - - if limit >= 0 and len(line) >= limit: - endpos = limit # reached length limit - break - - # No line ending seen yet - get more data - more_line = '' - while self._read_chunk(): - if self._decoded_chars: - break - if self._decoded_chars: - line += self._get_decoded_chars() - else: - # end of file - self._set_decoded_chars('') - self._snapshot = None - return line - - if limit >= 0 and endpos > limit: - endpos = limit # don't exceed limit - - # Rewind _decoded_chars to just after the line ending we found. - self._rewind_decoded_chars(len(line) - endpos) - return line[:endpos] - - @property - def newlines(self): - return self._decoder.newlines if self._decoder else None - -class _StringIO(TextIOWrapper): - """Text I/O implementation using an in-memory buffer. - - The initial_value argument sets the value of object. The newline - argument is like the one of TextIOWrapper's constructor. - """ - - # XXX This is really slow, but fully functional - - def __init__(self, initial_value="", newline="\n"): - super(_StringIO, self).__init__(BytesIO(), - encoding="utf-8", - errors="strict", - newline=newline) - if initial_value: - if not isinstance(initial_value, str): - initial_value = str(initial_value) - self.write(initial_value) - self.seek(0) - - def getvalue(self): - self.flush() - return self.buffer.getvalue().decode(self._encoding, self._errors) - -try: - import _stringio - - # This subclass is a reimplementation of the TextIOWrapper - # interface without any of its text decoding facilities. All the - # stored data is manipulated with the efficient - # _stringio._StringIO extension type. Also, the newline decoding - # mechanism of IncrementalNewlineDecoder is reimplemented here for - # efficiency. Doing otherwise, would require us to implement a - # fake decoder which would add an additional and unnecessary layer - # on top of the _StringIO methods. - - class StringIO(_stringio._StringIO, TextIOBase): - """Text I/O implementation using an in-memory buffer. - - The initial_value argument sets the value of object. The newline - argument is like the one of TextIOWrapper's constructor. - """ - - _CHUNK_SIZE = 4096 - - def __init__(self, initial_value="", newline="\n"): - if newline not in (None, "", "\n", "\r", "\r\n"): - raise ValueError("illegal newline value: %r" % (newline,)) - - self._readuniversal = not newline - self._readtranslate = newline is None - self._readnl = newline - self._writetranslate = newline != "" - self._writenl = newline or os.linesep - self._pending = "" - self._seennl = 0 - - # Reset the buffer first, in case __init__ is called - # multiple times. - self.truncate(0) - if initial_value is None: - initial_value = "" - self.write(initial_value) - self.seek(0) - - @property - def buffer(self): - raise UnsupportedOperation("%s.buffer attribute is unsupported" % - self.__class__.__name__) - - # XXX Cruft to support the TextIOWrapper API. This would only - # be meaningful if StringIO supported the buffer attribute. - # Hopefully, a better solution, than adding these pseudo-attributes, - # will be found. - @property - def encoding(self): - return "utf-8" - - @property - def errors(self): - return "strict" - - @property - def line_buffering(self): - return False - - def _decode_newlines(self, input, final=False): - # decode input (with the eventual \r from a previous pass) - if self._pending: - input = self._pending + input - - # retain last \r even when not translating data: - # then readline() is sure to get \r\n in one pass - if input.endswith("\r") and not final: - input = input[:-1] - self._pending = "\r" - else: - self._pending = "" - - # Record which newlines are read - crlf = input.count('\r\n') - cr = input.count('\r') - crlf - lf = input.count('\n') - crlf - self._seennl |= (lf and self._LF) | (cr and self._CR) \ - | (crlf and self._CRLF) - - if self._readtranslate: - if crlf: - output = input.replace("\r\n", "\n") - if cr: - output = input.replace("\r", "\n") - else: - output = input - - return output - - def writable(self): - return True - - def readable(self): - return True - - def seekable(self): - return True - - _read = _stringio._StringIO.read - _write = _stringio._StringIO.write - _tell = _stringio._StringIO.tell - _seek = _stringio._StringIO.seek - _truncate = _stringio._StringIO.truncate - _getvalue = _stringio._StringIO.getvalue - - def getvalue(self) -> str: - """Retrieve the entire contents of the object.""" - self._checkClosed() - return self._getvalue() - - def write(self, s: str) -> int: - """Write string s to file. - - Returns the number of characters written. - """ - self._checkClosed() - if not isinstance(s, str): - raise TypeError("can't write %s to text stream" % - s.__class__.__name__) - length = len(s) - if self._writetranslate and self._writenl != "\n": - s = s.replace("\n", self._writenl) - self._pending = "" - self._write(s) - return length - - def read(self, n: int = None) -> str: - """Read at most n characters, returned as a string. - - If the argument is negative or omitted, read until EOF - is reached. Return an empty string at EOF. - """ - self._checkClosed() - if n is None: - n = -1 - res = self._pending - if n < 0: - res += self._decode_newlines(self._read(), True) - self._pending = "" - return res - else: - res = self._decode_newlines(self._read(n), True) - self._pending = res[n:] - return res[:n] - - def tell(self) -> int: - """Tell the current file position.""" - self._checkClosed() - if self._pending: - return self._tell() - len(self._pending) - else: - return self._tell() - - def seek(self, pos: int = None, whence: int = 0) -> int: - """Change stream position. - - Seek to character offset pos relative to position indicated by whence: - 0 Start of stream (the default). pos should be >= 0; - 1 Current position - pos must be 0; - 2 End of stream - pos must be 0. - Returns the new absolute position. - """ - self._checkClosed() - self._pending = "" - return self._seek(pos, whence) - - def truncate(self, pos: int = None) -> int: - """Truncate size to pos. - - The pos argument defaults to the current file position, as - returned by tell(). Imply an absolute seek to pos. - Returns the new absolute position. - """ - self._checkClosed() - self._pending = "" - return self._truncate(pos) - - def readline(self, limit: int = None) -> str: - self._checkClosed() - if limit is None: - limit = -1 - if limit >= 0: - # XXX: Hack to support limit argument, for backwards - # XXX compatibility - line = self.readline() - if len(line) <= limit: - return line - line, self._pending = line[:limit], line[limit:] + self._pending - return line - - line = self._pending - self._pending = "" - - start = 0 - pos = endpos = None - while True: - if self._readtranslate: - # Newlines are already translated, only search for \n - pos = line.find('\n', start) - if pos >= 0: - endpos = pos + 1 - break - else: - start = len(line) - - elif self._readuniversal: - # Universal newline search. Find any of \r, \r\n, \n - # The decoder ensures that \r\n are not split in two pieces - - # In C we'd look for these in parallel of course. - nlpos = line.find("\n", start) - crpos = line.find("\r", start) - if crpos == -1: - if nlpos == -1: - # Nothing found - start = len(line) - else: - # Found \n - endpos = nlpos + 1 - break - elif nlpos == -1: - # Found lone \r - endpos = crpos + 1 - break - elif nlpos < crpos: - # Found \n - endpos = nlpos + 1 - break - elif nlpos == crpos + 1: - # Found \r\n - endpos = crpos + 2 - break - else: - # Found \r - endpos = crpos + 1 - break - else: - # non-universal - pos = line.find(self._readnl) - if pos >= 0: - endpos = pos + len(self._readnl) - break - - # No line ending seen yet - get more data - more_line = self.read(self._CHUNK_SIZE) - if more_line: - line += more_line - else: - # end of file - return line - - self._pending = line[endpos:] - return line[:endpos] - - _LF = 1 - _CR = 2 - _CRLF = 4 +class BufferedIOBase(_io._BufferedIOBase, IOBase): + pass - @property - def newlines(self): - return (None, - "\n", - "\r", - ("\r", "\n"), - "\r\n", - ("\n", "\r\n"), - ("\r", "\r\n"), - ("\r", "\n", "\r\n") - )[self._seennl] +class TextIOBase(_io._TextIOBase, IOBase): + pass +FileIO = _io.FileIO +BytesIO = _io.BytesIO +StringIO = _io.StringIO +BufferedReader = _io.BufferedReader +BufferedWriter = _io.BufferedWriter +BufferedRWPair = _io.BufferedRWPair +BufferedRandom = _io.BufferedRandom +IncrementalNewlineDecoder = _io.IncrementalNewlineDecoder +TextIOWrapper = _io.TextIOWrapper + +RawIOBase.register(FileIO) + +BufferedIOBase.register(BytesIO) +BufferedIOBase.register(BufferedReader) +BufferedIOBase.register(BufferedWriter) +BufferedIOBase.register(BufferedRandom) +BufferedIOBase.register(BufferedRWPair) -except ImportError: - StringIO = _StringIO +TextIOBase.register(StringIO) +TextIOBase.register(TextIOWrapper) Modified: python/branches/py3k/Lib/test/test_bufio.py ============================================================================== --- python/branches/py3k/Lib/test/test_bufio.py (original) +++ python/branches/py3k/Lib/test/test_bufio.py Wed Mar 4 01:14:51 2009 @@ -1,9 +1,12 @@ import unittest from test import support -# Simple test to ensure that optimizations in fileobject.c deliver -# the expected results. For best testing, run this under a debug-build -# Python too (to exercise asserts in the C code). +import io # C implementation. +import _pyio as pyio # Python implementation. + +# Simple test to ensure that optimizations in the IO library deliver the +# expected results. For best testing, run this under a debug-build Python too +# (to exercise asserts in the C code). lengths = list(range(1, 257)) + [512, 1000, 1024, 2048, 4096, 8192, 10000, 16384, 32768, 65536, 1000000] @@ -18,7 +21,7 @@ # Since C doesn't guarantee we can write/read arbitrary bytes in text # files, use binary mode. - f = open(support.TESTFN, "wb") + f = self.open(support.TESTFN, "wb") try: # write once with \n and once without f.write(s) @@ -58,8 +61,16 @@ def test_nullpat(self): self.drive_one(bytes(1000)) + +class CBufferSizeTest(BufferSizeTest): + open = io.open + +class PyBufferSizeTest(BufferSizeTest): + open = staticmethod(pyio.open) + + def test_main(): - support.run_unittest(BufferSizeTest) + support.run_unittest(CBufferSizeTest, PyBufferSizeTest) if __name__ == "__main__": test_main() Modified: python/branches/py3k/Lib/test/test_descr.py ============================================================================== --- python/branches/py3k/Lib/test/test_descr.py (original) +++ python/branches/py3k/Lib/test/test_descr.py Wed Mar 4 01:14:51 2009 @@ -2605,10 +2605,10 @@ def test_descrdoc(self): # Testing descriptor doc strings... - from _fileio import _FileIO + from _io import FileIO def check(descr, what): self.assertEqual(descr.__doc__, what) - check(_FileIO.closed, "True if the file is closed") # getset descriptor + check(FileIO.closed, "True if the file is closed") # getset descriptor check(complex.real, "the real part of a complex number") # member descriptor def test_doc_descriptor(self): Modified: python/branches/py3k/Lib/test/test_file.py ============================================================================== --- python/branches/py3k/Lib/test/test_file.py (original) +++ python/branches/py3k/Lib/test/test_file.py Wed Mar 4 01:14:51 2009 @@ -4,6 +4,9 @@ from array import array from weakref import proxy +import io +import _pyio as pyio + from test.support import TESTFN, findfile, run_unittest from collections import UserList @@ -11,7 +14,7 @@ # file tests for which a test file is automatically set up def setUp(self): - self.f = open(TESTFN, 'wb') + self.f = self.open(TESTFN, 'wb') def tearDown(self): if self.f: @@ -39,7 +42,7 @@ self.f.write(b'12') self.f.close() a = array('b', b'x'*10) - self.f = open(TESTFN, 'rb') + self.f = self.open(TESTFN, 'rb') n = self.f.readinto(a) self.assertEquals(b'12', a.tostring()[:n]) @@ -47,7 +50,7 @@ # verify readinto refuses text files a = array('b', b'x'*10) self.f.close() - self.f = open(TESTFN, 'r') + self.f = self.open(TESTFN, 'r') if hasattr(self.f, "readinto"): self.assertRaises(TypeError, self.f.readinto, a) @@ -56,7 +59,7 @@ l = UserList([b'1', b'2']) self.f.writelines(l) self.f.close() - self.f = open(TESTFN, 'rb') + self.f = self.open(TESTFN, 'rb') buf = self.f.read() self.assertEquals(buf, b'12') @@ -126,13 +129,20 @@ def testReadWhenWriting(self): self.assertRaises(IOError, self.f.read) +class CAutoFileTests(AutoFileTests): + open = io.open + +class PyAutoFileTests(AutoFileTests): + open = staticmethod(pyio.open) + + class OtherFileTests(unittest.TestCase): def testModeStrings(self): # check invalid mode strings for mode in ("", "aU", "wU+"): try: - f = open(TESTFN, mode) + f = self.open(TESTFN, mode) except ValueError: pass else: @@ -153,7 +163,7 @@ # verify that we get a sensible error message for bad mode argument bad_mode = "qwerty" try: - f = open(TESTFN, bad_mode) + f = self.open(TESTFN, bad_mode) except ValueError as msg: if msg.args[0] != 0: s = str(msg) @@ -170,11 +180,11 @@ # misbehaviour especially with repeated close() calls for s in (-1, 0, 1, 512): try: - f = open(TESTFN, 'wb', s) + f = self.open(TESTFN, 'wb', s) f.write(str(s).encode("ascii")) f.close() f.close() - f = open(TESTFN, 'rb', s) + f = self.open(TESTFN, 'rb', s) d = int(f.read().decode("ascii")) f.close() f.close() @@ -187,13 +197,13 @@ # "file.truncate fault on windows" os.unlink(TESTFN) - f = open(TESTFN, 'wb') + f = self.open(TESTFN, 'wb') try: f.write(b'12345678901') # 11 bytes f.close() - f = open(TESTFN,'rb+') + f = self.open(TESTFN,'rb+') data = f.read(5) if data != b'12345': self.fail("Read on file opened for update failed %r" % data) @@ -233,13 +243,13 @@ try: # Prepare the testfile - bag = open(TESTFN, "wb") + bag = self.open(TESTFN, "wb") bag.write(filler * nchunks) bag.writelines(testlines) bag.close() # Test for appropriate errors mixing read* and iteration for methodname, args in methods: - f = open(TESTFN, 'rb') + f = self.open(TESTFN, 'rb') if next(f) != filler: self.fail, "Broken testfile" meth = getattr(f, methodname) @@ -253,7 +263,7 @@ # ("h", "a", "m", "\n"), so 4096 lines of that should get us # exactly on the buffer boundary for any power-of-2 buffersize # between 4 and 16384 (inclusive). - f = open(TESTFN, 'rb') + f = self.open(TESTFN, 'rb') for i in range(nchunks): next(f) testline = testlines.pop(0) @@ -295,7 +305,7 @@ self.fail("readlines() after next() with empty buffer " "failed. Got %r, expected %r" % (line, testline)) # Reading after iteration hit EOF shouldn't hurt either - f = open(TESTFN, 'rb') + f = self.open(TESTFN, 'rb') try: for line in f: pass @@ -311,12 +321,19 @@ finally: os.unlink(TESTFN) +class COtherFileTests(OtherFileTests): + open = io.open + +class PyOtherFileTests(OtherFileTests): + open = staticmethod(pyio.open) + def test_main(): # Historically, these tests have been sloppy about removing TESTFN. # So get rid of it no matter what. try: - run_unittest(AutoFileTests, OtherFileTests) + run_unittest(CAutoFileTests, PyAutoFileTests, + COtherFileTests, PyOtherFileTests) finally: if os.path.exists(TESTFN): os.unlink(TESTFN) Modified: python/branches/py3k/Lib/test/test_fileio.py ============================================================================== --- python/branches/py3k/Lib/test/test_fileio.py (original) +++ python/branches/py3k/Lib/test/test_fileio.py Wed Mar 4 01:14:51 2009 @@ -10,13 +10,13 @@ make_bad_fd) from collections import UserList -import _fileio +from _io import FileIO as _FileIO class AutoFileTests(unittest.TestCase): # file tests for which a test file is automatically set up def setUp(self): - self.f = _fileio._FileIO(TESTFN, 'w') + self.f = _FileIO(TESTFN, 'w') def tearDown(self): if self.f: @@ -63,13 +63,13 @@ self.f.write(bytes([1, 2])) self.f.close() a = array('b', b'x'*10) - self.f = _fileio._FileIO(TESTFN, 'r') + self.f = _FileIO(TESTFN, 'r') n = self.f.readinto(a) self.assertEquals(array('b', [1, 2]), a[:n]) def testRepr(self): self.assertEquals(repr(self.f), - "_fileio._FileIO(%d, %s)" % (self.f.fileno(), + "io.FileIO(%d, %s)" % (self.f.fileno(), repr(self.f.mode))) def testErrors(self): @@ -80,7 +80,7 @@ self.assertRaises(ValueError, f.read, 10) # Open for reading f.close() self.assert_(f.closed) - f = _fileio._FileIO(TESTFN, 'r') + f = _FileIO(TESTFN, 'r') self.assertRaises(TypeError, f.readinto, "") self.assert_(not f.closed) f.close() @@ -106,7 +106,7 @@ # Windows always returns "[Errno 13]: Permission denied # Unix calls dircheck() and returns "[Errno 21]: Is a directory" try: - _fileio._FileIO('.', 'r') + _FileIO('.', 'r') except IOError as e: self.assertNotEqual(e.errno, 0) self.assertEqual(e.filename, ".") @@ -118,19 +118,19 @@ def testAbles(self): try: - f = _fileio._FileIO(TESTFN, "w") + f = _FileIO(TESTFN, "w") self.assertEquals(f.readable(), False) self.assertEquals(f.writable(), True) self.assertEquals(f.seekable(), True) f.close() - f = _fileio._FileIO(TESTFN, "r") + f = _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+") + f = _FileIO(TESTFN, "a+") self.assertEquals(f.readable(), True) self.assertEquals(f.writable(), True) self.assertEquals(f.seekable(), True) @@ -139,14 +139,14 @@ if sys.platform != "win32": try: - f = _fileio._FileIO("/dev/tty", "a") + f = _FileIO("/dev/tty", "a") except EnvironmentError: # When run in a cron job there just aren't any # ttys, so skip the test. This also handles other # OS'es that don't support /dev/tty. pass else: - f = _fileio._FileIO("/dev/tty", "a") + f = _FileIO("/dev/tty", "a") self.assertEquals(f.readable(), False) self.assertEquals(f.writable(), True) if sys.platform != "darwin" and \ @@ -163,7 +163,7 @@ # check invalid mode strings for mode in ("", "aU", "wU+", "rw", "rt"): try: - f = _fileio._FileIO(TESTFN, mode) + f = _FileIO(TESTFN, mode) except ValueError: pass else: @@ -172,10 +172,26 @@ def testUnicodeOpen(self): # verify repr works for unicode too - f = _fileio._FileIO(str(TESTFN), "w") + f = _FileIO(str(TESTFN), "w") f.close() os.unlink(TESTFN) + def testBytesOpen(self): + # Opening a bytes filename + try: + fn = TESTFN.encode("ascii") + except UnicodeEncodeError: + # Skip test + return + f = _FileIO(fn, "w") + try: + f.write(b"abc") + f.close() + with open(TESTFN, "rb") as f: + self.assertEquals(f.read(), b"abc") + finally: + os.unlink(TESTFN) + def testInvalidFd(self): self.assertRaises(ValueError, _fileio._FileIO, -10) self.assertRaises(OSError, _fileio._FileIO, make_bad_fd()) @@ -184,7 +200,7 @@ # verify that we get a sensible error message for bad mode argument bad_mode = "qwerty" try: - f = _fileio._FileIO(TESTFN, bad_mode) + f = _FileIO(TESTFN, bad_mode) except ValueError as msg: if msg.args[0] != 0: s = str(msg) @@ -200,11 +216,11 @@ def bug801631(): # SF bug # "file.truncate fault on windows" - f = _fileio._FileIO(TESTFN, 'w') + f = _FileIO(TESTFN, 'w') f.write(bytes(range(11))) f.close() - f = _fileio._FileIO(TESTFN,'r+') + f = _FileIO(TESTFN,'r+') data = f.read(5) if data != bytes(range(5)): self.fail("Read on file opened for update failed %r" % data) @@ -244,14 +260,14 @@ pass def testInvalidInit(self): - self.assertRaises(TypeError, _fileio._FileIO, "1", 0, 0) + self.assertRaises(TypeError, _FileIO, "1", 0, 0) def testWarnings(self): with check_warnings() as w: self.assertEqual(w.warnings, []) - self.assertRaises(TypeError, _fileio._FileIO, []) + self.assertRaises(TypeError, _FileIO, []) self.assertEqual(w.warnings, []) - self.assertRaises(ValueError, _fileio._FileIO, "/some/invalid/name", "rt") + self.assertRaises(ValueError, _FileIO, "/some/invalid/name", "rt") self.assertEqual(w.warnings, []) Modified: python/branches/py3k/Lib/test/test_io.py ============================================================================== --- python/branches/py3k/Lib/test/test_io.py (original) +++ python/branches/py3k/Lib/test/test_io.py Wed Mar 4 01:14:51 2009 @@ -1,4 +1,23 @@ -"""Unit tests for io.py.""" +"""Unit tests for the io module.""" + +# Tests of io are scattered over the test suite: +# * test_bufio - tests file buffering +# * test_memoryio - tests BytesIO and StringIO +# * test_fileio - tests FileIO +# * test_file - tests the file interface +# * test_io - tests everything else in the io module +# * test_univnewlines - tests universal newline support +# * test_largefile - tests operations on a file greater than 2**32 bytes +# (only enabled with -ulargefile) + +################################################################################ +# ATTENTION TEST WRITERS!!! +################################################################################ +# When writing tests for io, it's important to test both the C and Python +# implementations. This is usually done by writing a base test that refers to +# the type it is testing as a attribute. Then it provides custom subclasses to +# test both implementations. This file has lots of examples. +################################################################################ import os import sys @@ -7,27 +26,40 @@ import threading import random import unittest -from itertools import chain, cycle +import weakref +import gc +import abc +from itertools import chain, cycle, count +from collections import deque from test import support import codecs -import io # The module under test +import io # C implementation of io +import _pyio as pyio # Python implementation of io + +def _default_chunk_size(): + """Get the default TextIOWrapper chunk size""" + with open(__file__, "r", encoding="latin1") as f: + return f._CHUNK_SIZE -class MockRawIO(io.RawIOBase): + +class MockRawIO: def __init__(self, read_stack=()): self._read_stack = list(read_stack) self._write_stack = [] + self._reads = 0 def read(self, n=None): + self._reads += 1 try: return self._read_stack.pop(0) except: return b"" def write(self, b): - self._write_stack.append(b[:]) + self._write_stack.append(bytes(b)) return len(b) def writable(self): @@ -43,41 +75,148 @@ return True def seek(self, pos, whence): - pass + return 0 # wrong but we gotta return something def tell(self): - return 42 + return 0 # same comment as above + + def readinto(self, buf): + self._reads += 1 + max_len = len(buf) + try: + data = self._read_stack[0] + except IndexError: + return 0 + if data is None: + del self._read_stack[0] + return None + n = len(data) + if len(data) <= max_len: + del self._read_stack[0] + buf[:n] = data + return n + else: + buf[:] = data[:max_len] + self._read_stack[0] = data[max_len:] + return max_len + + def truncate(self, pos=None): + return pos + +class CMockRawIO(MockRawIO, io.RawIOBase): + pass + +class PyMockRawIO(MockRawIO, pyio.RawIOBase): + pass + + +class MisbehavedRawIO(MockRawIO): + def write(self, b): + return super().write(b) * 2 + + def read(self, n=None): + return super().read(n) * 2 + + def seek(self, pos, whence): + return -123 + + def tell(self): + return -456 + + def readinto(self, buf): + super().readinto(buf) + return len(buf) * 5 + +class CMisbehavedRawIO(MisbehavedRawIO, io.RawIOBase): + pass + +class PyMisbehavedRawIO(MisbehavedRawIO, pyio.RawIOBase): + pass + + +class CloseFailureIO(MockRawIO): + closed = 0 + + def close(self): + if not self.closed: + self.closed = 1 + raise IOError + +class CCloseFailureIO(CloseFailureIO, io.RawIOBase): + pass +class PyCloseFailureIO(CloseFailureIO, pyio.RawIOBase): + pass -class MockFileIO(io.BytesIO): + +class MockFileIO: def __init__(self, data): self.read_history = [] - io.BytesIO.__init__(self, data) + super().__init__(data) def read(self, n=None): - res = io.BytesIO.read(self, n) + res = super().read(n) self.read_history.append(None if res is None else len(res)) return res + def readinto(self, b): + res = super().readinto(b) + self.read_history.append(res) + return res + +class CMockFileIO(MockFileIO, io.BytesIO): + pass + +class PyMockFileIO(MockFileIO, pyio.BytesIO): + pass -class MockNonBlockWriterIO(io.RawIOBase): - def __init__(self, blocking_script): - self._blocking_script = list(blocking_script) +class MockNonBlockWriterIO: + + def __init__(self): self._write_stack = [] + self._blocker_char = None - def write(self, b): - self._write_stack.append(b[:]) - n = self._blocking_script.pop(0) - if (n < 0): - raise io.BlockingIOError(0, "test blocking", -n) - else: - return n + def pop_written(self): + s = b"".join(self._write_stack) + self._write_stack[:] = [] + return s + + def block_on(self, char): + """Block when a given char is encountered.""" + self._blocker_char = char + + def readable(self): + return True + + def seekable(self): + return True def writable(self): return True + def write(self, b): + b = bytes(b) + n = -1 + if self._blocker_char: + try: + n = b.index(self._blocker_char) + except ValueError: + pass + else: + self._blocker_char = None + self._write_stack.append(b[:n]) + raise self.BlockingIOError(0, "test blocking", n) + self._write_stack.append(b) + return len(b) + +class CMockNonBlockWriterIO(MockNonBlockWriterIO, io.RawIOBase): + BlockingIOError = io.BlockingIOError + +class PyMockNonBlockWriterIO(MockNonBlockWriterIO, pyio.RawIOBase): + BlockingIOError = pyio.BlockingIOError + class IOTest(unittest.TestCase): @@ -151,13 +290,13 @@ self.assertEqual(f.read(2), b"x") def test_raw_file_io(self): - f = io.open(support.TESTFN, "wb", buffering=0) + f = self.open(support.TESTFN, "wb", buffering=0) self.assertEqual(f.readable(), False) self.assertEqual(f.writable(), True) self.assertEqual(f.seekable(), True) self.write_ops(f) f.close() - f = io.open(support.TESTFN, "rb", buffering=0) + f = self.open(support.TESTFN, "rb", buffering=0) self.assertEqual(f.readable(), True) self.assertEqual(f.writable(), False) self.assertEqual(f.seekable(), True) @@ -165,13 +304,13 @@ f.close() def test_buffered_file_io(self): - f = io.open(support.TESTFN, "wb") + f = self.open(support.TESTFN, "wb") self.assertEqual(f.readable(), False) self.assertEqual(f.writable(), True) self.assertEqual(f.seekable(), True) self.write_ops(f) f.close() - f = io.open(support.TESTFN, "rb") + f = self.open(support.TESTFN, "rb") self.assertEqual(f.readable(), True) self.assertEqual(f.writable(), False) self.assertEqual(f.seekable(), True) @@ -180,22 +319,23 @@ def test_readline(self): f = io.open(support.TESTFN, "wb") - f.write(b"abc\ndef\nxyzzy\nfoo") + f.write(b"abc\ndef\nxyzzy\nfoo\x00bar\nanother line") f.close() - f = io.open(support.TESTFN, "rb") + f = self.open(support.TESTFN, "rb") self.assertEqual(f.readline(), b"abc\n") self.assertEqual(f.readline(10), b"def\n") self.assertEqual(f.readline(2), b"xy") self.assertEqual(f.readline(4), b"zzy\n") - self.assertEqual(f.readline(), b"foo") + self.assertEqual(f.readline(), b"foo\x00bar\n") + self.assertEqual(f.readline(), b"another line") f.close() def test_raw_bytes_io(self): - f = io.BytesIO() + f = self.BytesIO() self.write_ops(f) data = f.getvalue() self.assertEqual(data, b"hello world\n") - f = io.BytesIO(data) + f = self.BytesIO(data) self.read_ops(f, True) def test_large_file_ops(self): @@ -211,12 +351,10 @@ print("Use 'regrtest.py -u largefile test_io' to run it.", file=sys.stderr) return - f = io.open(support.TESTFN, "w+b", 0) - self.large_file_ops(f) - f.close() - f = io.open(support.TESTFN, "w+b") - self.large_file_ops(f) - f.close() + with self.open(support.TESTFN, "w+b", 0) as f: + self.large_file_ops(f) + with self.open(support.TESTFN, "w+b") as f: + self.large_file_ops(f) def test_with_open(self): for bufsize in (0, 1, 100): @@ -235,59 +373,107 @@ # issue 5008 def test_append_mode_tell(self): - with io.open(support.TESTFN, "wb") as f: + with self.open(support.TESTFN, "wb") as f: f.write(b"xxx") - with io.open(support.TESTFN, "ab", buffering=0) as f: + with self.open(support.TESTFN, "ab", buffering=0) as f: self.assertEqual(f.tell(), 3) - with io.open(support.TESTFN, "ab") as f: + with self.open(support.TESTFN, "ab") as f: self.assertEqual(f.tell(), 3) - with io.open(support.TESTFN, "a") as f: + with self.open(support.TESTFN, "a") as f: self.assert_(f.tell() > 0) def test_destructor(self): record = [] - class MyFileIO(io.FileIO): + class MyFileIO(self.FileIO): def __del__(self): record.append(1) - io.FileIO.__del__(self) + try: + f = super().__del__ + except AttributeError: + pass + else: + f() def close(self): record.append(2) - io.FileIO.close(self) + super().close() def flush(self): record.append(3) - io.FileIO.flush(self) - f = MyFileIO(support.TESTFN, "w") - f.write("xxx") + super().flush() + f = MyFileIO(support.TESTFN, "wb") + f.write(b"xxx") del f self.assertEqual(record, [1, 2, 3]) + f = open(support.TESTFN, "rb") + self.assertEqual(f.read(), b"xxx") + + def _check_base_destructor(self, base): + record = [] + class MyIO(base): + def __init__(self): + # This exercises the availability of attributes on object + # destruction. + # (in the C version, close() is called by the tp_dealloc + # function, not by __del__) + self.on_del = 1 + self.on_close = 2 + self.on_flush = 3 + def __del__(self): + record.append(self.on_del) + try: + f = super().__del__ + except AttributeError: + pass + else: + f() + def close(self): + record.append(self.on_close) + super().close() + def flush(self): + record.append(self.on_flush) + super().flush() + f = MyIO() + del f + self.assertEqual(record, [1, 2, 3]) + + def test_IOBase_destructor(self): + self._check_base_destructor(self.IOBase) + + def test_RawIOBase_destructor(self): + self._check_base_destructor(self.RawIOBase) + + def test_BufferedIOBase_destructor(self): + self._check_base_destructor(self.BufferedIOBase) + + def test_TextIOBase_destructor(self): + self._check_base_destructor(self.TextIOBase) def test_close_flushes(self): - f = io.open(support.TESTFN, "wb") + f = self.open(support.TESTFN, "wb") f.write(b"xxx") f.close() - f = io.open(support.TESTFN, "rb") + f = self.open(support.TESTFN, "rb") self.assertEqual(f.read(), b"xxx") f.close() def test_array_writes(self): a = array.array('i', range(10)) n = len(a.tostring()) - f = io.open(support.TESTFN, "wb", 0) + f = self.open(support.TESTFN, "wb", 0) self.assertEqual(f.write(a), n) f.close() - f = io.open(support.TESTFN, "wb") + f = self.open(support.TESTFN, "wb") self.assertEqual(f.write(a), n) f.close() def test_closefd(self): - self.assertRaises(ValueError, io.open, support.TESTFN, 'w', + self.assertRaises(ValueError, self.open, support.TESTFN, 'w', closefd=False) - def testReadClosed(self): - with io.open(support.TESTFN, "w") as f: + def test_read_closed(self): + with self.open(support.TESTFN, "w") as f: f.write("egg\n") - with io.open(support.TESTFN, "r") as f: - file = io.open(f.fileno(), "r", closefd=False) + with self.open(support.TESTFN, "r") as f: + file = self.open(f.fileno(), "r", closefd=False) self.assertEqual(file.read(), "egg\n") file.seek(0) file.close() @@ -295,85 +481,168 @@ def test_no_closefd_with_filename(self): # can't use closefd in combination with a file name - self.assertRaises(ValueError, io.open, support.TESTFN, "r", closefd=False) + self.assertRaises(ValueError, self.open, support.TESTFN, "r", closefd=False) def test_closefd_attr(self): - with io.open(support.TESTFN, "wb") as f: + with self.open(support.TESTFN, "wb") as f: f.write(b"egg\n") - with io.open(support.TESTFN, "r") as f: + with self.open(support.TESTFN, "r") as f: self.assertEqual(f.buffer.raw.closefd, True) - file = io.open(f.fileno(), "r", closefd=False) + file = self.open(f.fileno(), "r", closefd=False) self.assertEqual(file.buffer.raw.closefd, False) + def test_garbage_collection(self): + # FileIO objects are collected, and collecting them flushes + # all data to disk. + f = self.FileIO(support.TESTFN, "wb") + f.write(b"abcxxx") + f.f = f + wr = weakref.ref(f) + del f + gc.collect() + self.assert_(wr() is None, wr) + with open(support.TESTFN, "rb") as f: + self.assertEqual(f.read(), b"abcxxx") -class MemorySeekTestMixin: - - def testInit(self): - buf = self.buftype("1234567890") - bytesIo = self.ioclass(buf) - - def testRead(self): - buf = self.buftype("1234567890") - bytesIo = self.ioclass(buf) - - self.assertEquals(buf[:1], bytesIo.read(1)) - self.assertEquals(buf[1:5], bytesIo.read(4)) - self.assertEquals(buf[5:], bytesIo.read(900)) - self.assertEquals(self.EOF, bytesIo.read()) - - def testReadNoArgs(self): - buf = self.buftype("1234567890") - bytesIo = self.ioclass(buf) - - self.assertEquals(buf, bytesIo.read()) - self.assertEquals(self.EOF, bytesIo.read()) - - def testSeek(self): - buf = self.buftype("1234567890") - bytesIo = self.ioclass(buf) - - bytesIo.read(5) - bytesIo.seek(0) - self.assertEquals(buf, bytesIo.read()) - - bytesIo.seek(3) - self.assertEquals(buf[3:], bytesIo.read()) - self.assertRaises(TypeError, bytesIo.seek, 0.0) - - def testTell(self): - buf = self.buftype("1234567890") - bytesIo = self.ioclass(buf) +class CIOTest(IOTest): + pass - self.assertEquals(0, bytesIo.tell()) - bytesIo.seek(5) - self.assertEquals(5, bytesIo.tell()) - bytesIo.seek(10000) - self.assertEquals(10000, bytesIo.tell()) +class PyIOTest(IOTest): + pass -class BytesIOTest(MemorySeekTestMixin, unittest.TestCase): - @staticmethod - def buftype(s): - return s.encode("utf-8") - ioclass = io.BytesIO - EOF = b"" +class CommonBufferedTests: + # Tests common to BufferedReader, BufferedWriter and BufferedRandom + def test_fileno(self): + rawio = self.MockRawIO() + bufio = self.tp(rawio) -class StringIOTest(MemorySeekTestMixin, unittest.TestCase): - buftype = str - ioclass = io.StringIO - EOF = "" + self.assertEquals(42, bufio.fileno()) + def test_no_fileno(self): + # XXX will we always have fileno() function? If so, kill + # this test. Else, write it. + pass -class BufferedReaderTest(unittest.TestCase): + def test_invalid_args(self): + rawio = self.MockRawIO() + bufio = self.tp(rawio) + # Invalid whence + self.assertRaises(ValueError, bufio.seek, 0, -1) + self.assertRaises(ValueError, bufio.seek, 0, 3) - def testRead(self): - rawio = MockRawIO((b"abc", b"d", b"efg")) - bufio = io.BufferedReader(rawio) + def test_override_destructor(self): + tp = self.tp + record = [] + class MyBufferedIO(tp): + def __del__(self): + record.append(1) + try: + f = super().__del__ + except AttributeError: + pass + else: + f() + def close(self): + record.append(2) + super().close() + def flush(self): + record.append(3) + super().flush() + rawio = self.MockRawIO() + bufio = MyBufferedIO(rawio) + writable = bufio.writable() + del bufio + if writable: + self.assertEqual(record, [1, 2, 3]) + else: + self.assertEqual(record, [1, 2]) + def test_context_manager(self): + # Test usability as a context manager + rawio = self.MockRawIO() + bufio = self.tp(rawio) + def _with(): + with bufio: + pass + _with() + # bufio should now be closed, and using it a second time should raise + # a ValueError. + self.assertRaises(ValueError, _with) + + def test_error_through_destructor(self): + # Test that the exception state is not modified by a destructor, + # even if close() fails. + rawio = self.CloseFailureIO() + def f(): + self.tp(rawio).xyzzy + with support.captured_output("stderr") as s: + self.assertRaises(AttributeError, f) + s = s.getvalue().strip() + if s: + # The destructor *may* have printed an unraisable error, check it + self.assertEqual(len(s.splitlines()), 1) + self.assert_(s.startswith("Exception IOError: "), s) + self.assert_(s.endswith(" ignored"), s) + + +class BufferedReaderTest(unittest.TestCase, CommonBufferedTests): + read_mode = "rb" + + def test_constructor(self): + rawio = self.MockRawIO([b"abc"]) + bufio = self.tp(rawio) + bufio.__init__(rawio) + bufio.__init__(rawio, buffer_size=1024) + bufio.__init__(rawio, buffer_size=16) + self.assertEquals(b"abc", bufio.read()) + self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=0) + self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-16) + self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1) + rawio = self.MockRawIO([b"abc"]) + bufio.__init__(rawio) + self.assertEquals(b"abc", bufio.read()) + + def test_read(self): + rawio = self.MockRawIO((b"abc", b"d", b"efg")) + bufio = self.tp(rawio) self.assertEquals(b"abcdef", bufio.read(6)) + # Invalid args + self.assertRaises(ValueError, bufio.read, -2) - def testBuffering(self): + def test_read1(self): + rawio = self.MockRawIO((b"abc", b"d", b"efg")) + bufio = self.tp(rawio) + self.assertEquals(b"a", bufio.read(1)) + self.assertEquals(b"b", bufio.read1(1)) + self.assertEquals(rawio._reads, 1) + self.assertEquals(b"c", bufio.read1(100)) + self.assertEquals(rawio._reads, 1) + self.assertEquals(b"d", bufio.read1(100)) + self.assertEquals(rawio._reads, 2) + self.assertEquals(b"efg", bufio.read1(100)) + self.assertEquals(rawio._reads, 3) + self.assertEquals(b"", bufio.read1(100)) + # Invalid args + self.assertRaises(ValueError, bufio.read1, -1) + + def test_readinto(self): + rawio = self.MockRawIO((b"abc", b"d", b"efg")) + bufio = self.tp(rawio) + b = bytearray(2) + self.assertEquals(bufio.readinto(b), 2) + self.assertEquals(b, b"ab") + self.assertEquals(bufio.readinto(b), 2) + self.assertEquals(b, b"cd") + self.assertEquals(bufio.readinto(b), 2) + self.assertEquals(b, b"ef") + self.assertEquals(bufio.readinto(b), 1) + self.assertEquals(b, b"gf") + self.assertEquals(bufio.readinto(b), 0) + self.assertEquals(b, b"gf") + + def test_buffering(self): data = b"abcdefghi" dlen = len(data) @@ -384,49 +653,40 @@ ] for bufsize, buf_read_sizes, raw_read_sizes in tests: - rawio = MockFileIO(data) - bufio = io.BufferedReader(rawio, buffer_size=bufsize) + rawio = self.MockFileIO(data) + bufio = self.tp(rawio, buffer_size=bufsize) pos = 0 for nbytes in buf_read_sizes: self.assertEquals(bufio.read(nbytes), data[pos:pos+nbytes]) pos += nbytes + # this is mildly implementation-dependent self.assertEquals(rawio.read_history, raw_read_sizes) - def testReadNonBlocking(self): + def test_read_non_blocking(self): # Inject some None's in there to simulate EWOULDBLOCK - rawio = MockRawIO((b"abc", b"d", None, b"efg", None, None)) - bufio = io.BufferedReader(rawio) + rawio = self.MockRawIO((b"abc", b"d", None, b"efg", None, None, None)) + bufio = self.tp(rawio) self.assertEquals(b"abcd", bufio.read(6)) self.assertEquals(b"e", bufio.read(1)) self.assertEquals(b"fg", bufio.read()) + self.assertEquals(b"", bufio.peek(1)) self.assert_(None is bufio.read()) self.assertEquals(b"", bufio.read()) - def testReadToEof(self): - rawio = MockRawIO((b"abc", b"d", b"efg")) - bufio = io.BufferedReader(rawio) + def test_read_past_eof(self): + rawio = self.MockRawIO((b"abc", b"d", b"efg")) + bufio = self.tp(rawio) self.assertEquals(b"abcdefg", bufio.read(9000)) - def testReadNoArgs(self): - rawio = MockRawIO((b"abc", b"d", b"efg")) - bufio = io.BufferedReader(rawio) + def test_read_all(self): + rawio = self.MockRawIO((b"abc", b"d", b"efg")) + bufio = self.tp(rawio) self.assertEquals(b"abcdefg", bufio.read()) - def testFileno(self): - rawio = MockRawIO((b"abc", b"d", b"efg")) - bufio = io.BufferedReader(rawio) - - self.assertEquals(42, bufio.fileno()) - - def testFilenoNoFileno(self): - # XXX will we always have fileno() function? If so, kill - # this test. Else, write it. - pass - - def testThreads(self): + def test_threads(self): try: # Write out many bytes with exactly the same number of 0's, # 1's... 255's. This will help us check that concurrent reading @@ -437,8 +697,8 @@ s = bytes(bytearray(l)) with io.open(support.TESTFN, "wb") as f: f.write(s) - with io.open(support.TESTFN, "rb", buffering=0) as raw: - bufio = io.BufferedReader(raw, 8) + with io.open(support.TESTFN, self.read_mode, buffering=0) as raw: + bufio = self.tp(raw, 8) errors = [] results = [] def f(): @@ -468,80 +728,230 @@ finally: support.unlink(support.TESTFN) + def test_misbehaved_io(self): + rawio = self.MisbehavedRawIO((b"abc", b"d", b"efg")) + bufio = self.tp(rawio) + self.assertRaises(IOError, bufio.seek, 0) + self.assertRaises(IOError, bufio.tell) + +class CBufferedReaderTest(BufferedReaderTest): + tp = io.BufferedReader + + def test_constructor(self): + BufferedReaderTest.test_constructor(self) + # The allocation can succeed on 32-bit builds, e.g. with more + # than 2GB RAM and a 64-bit kernel. + if sys.maxsize > 0x7FFFFFFF: + rawio = self.MockRawIO() + bufio = self.tp(rawio) + self.assertRaises((OverflowError, MemoryError, ValueError), + bufio.__init__, rawio, sys.maxsize) + + def test_initialization(self): + rawio = self.MockRawIO([b"abc"]) + bufio = self.tp(rawio) + self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=0) + self.assertRaises(ValueError, bufio.read) + self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-16) + self.assertRaises(ValueError, bufio.read) + self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1) + self.assertRaises(ValueError, bufio.read) + + def test_misbehaved_io_read(self): + rawio = self.MisbehavedRawIO((b"abc", b"d", b"efg")) + bufio = self.tp(rawio) + # _pyio.BufferedReader seems to implement reading different, so that + # checking this is not so easy. + self.assertRaises(IOError, bufio.read, 10) + + def test_garbage_collection(self): + # C BufferedReader objects are collected. + # The Python version has __del__, so it ends into gc.garbage instead + rawio = self.FileIO(support.TESTFN, "w+b") + f = self.tp(rawio) + f.f = f + wr = weakref.ref(f) + del f + gc.collect() + self.assert_(wr() is None, wr) +class PyBufferedReaderTest(BufferedReaderTest): + tp = pyio.BufferedReader -class BufferedWriterTest(unittest.TestCase): - def testWrite(self): - # Write to the buffered IO but don't overflow the buffer. - writer = MockRawIO() - bufio = io.BufferedWriter(writer, 8) +class BufferedWriterTest(unittest.TestCase, CommonBufferedTests): + write_mode = "wb" + + def test_constructor(self): + rawio = self.MockRawIO() + bufio = self.tp(rawio) + bufio.__init__(rawio) + bufio.__init__(rawio, buffer_size=1024) + bufio.__init__(rawio, buffer_size=16) + self.assertEquals(3, bufio.write(b"abc")) + bufio.flush() + self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=0) + self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-16) + self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1) + bufio.__init__(rawio) + self.assertEquals(3, bufio.write(b"ghi")) + bufio.flush() + self.assertEquals(b"".join(rawio._write_stack), b"abcghi") + def test_write(self): + # Write to the buffered IO but don't overflow the buffer. + writer = self.MockRawIO() + bufio = self.tp(writer, 8) bufio.write(b"abc") - self.assertFalse(writer._write_stack) - def testWriteOverflow(self): - writer = MockRawIO() - bufio = io.BufferedWriter(writer, 8) - - bufio.write(b"abc") - bufio.write(b"defghijkl") - - self.assertEquals(b"abcdefghijkl", writer._write_stack[0]) - - def testWriteNonBlocking(self): - raw = MockNonBlockWriterIO((9, 2, 22, -6, 10, 12, 12)) - bufio = io.BufferedWriter(raw, 8, 16) - - bufio.write(b"asdf") - bufio.write(b"asdfa") - self.assertEquals(b"asdfasdfa", raw._write_stack[0]) - - bufio.write(b"asdfasdfasdf") - self.assertEquals(b"asdfasdfasdf", raw._write_stack[1]) - bufio.write(b"asdfasdfasdf") - self.assertEquals(b"dfasdfasdf", raw._write_stack[2]) - self.assertEquals(b"asdfasdfasdf", raw._write_stack[3]) - - bufio.write(b"asdfasdfasdf") + def test_write_overflow(self): + writer = self.MockRawIO() + bufio = self.tp(writer, 8) + contents = b"abcdefghijklmnop" + for n in range(0, len(contents), 3): + bufio.write(contents[n:n+3]) + flushed = b"".join(writer._write_stack) + # At least (total - 8) bytes were implicitly flushed, perhaps more + # depending on the implementation. + self.assert_(flushed.startswith(contents[:-8]), flushed) + + def check_writes(self, intermediate_func): + # Lots of writes, test the flushed output is as expected. + contents = bytes(range(256)) * 1000 + n = 0 + writer = self.MockRawIO() + bufio = self.tp(writer, 13) + # Generator of write sizes: repeat each N 15 times then proceed to N+1 + def gen_sizes(): + for size in count(1): + for i in range(15): + yield size + sizes = gen_sizes() + while n < len(contents): + size = min(next(sizes), len(contents) - n) + self.assertEquals(bufio.write(contents[n:n+size]), size) + intermediate_func(bufio) + n += size + bufio.flush() + self.assertEquals(contents, b"".join(writer._write_stack)) - # XXX I don't like this test. It relies too heavily on how the - # algorithm actually works, which we might change. Refactor - # later. + def test_writes(self): + self.check_writes(lambda bufio: None) - def testFileno(self): - rawio = MockRawIO((b"abc", b"d", b"efg")) - bufio = io.BufferedWriter(rawio) + def test_writes_and_flushes(self): + self.check_writes(lambda bufio: bufio.flush()) - self.assertEquals(42, bufio.fileno()) + def test_writes_and_seeks(self): + def _seekabs(bufio): + pos = bufio.tell() + bufio.seek(pos + 1, 0) + bufio.seek(pos - 1, 0) + bufio.seek(pos, 0) + self.check_writes(_seekabs) + def _seekrel(bufio): + pos = bufio.seek(0, 1) + bufio.seek(+1, 1) + bufio.seek(-1, 1) + bufio.seek(pos, 0) + self.check_writes(_seekrel) + + def test_writes_and_truncates(self): + self.check_writes(lambda bufio: bufio.truncate(bufio.tell())) + + def test_write_non_blocking(self): + raw = self.MockNonBlockWriterIO() + bufio = self.tp(raw, 8, 8) + + self.assertEquals(bufio.write(b"abcd"), 4) + self.assertEquals(bufio.write(b"efghi"), 5) + # 1 byte will be written, the rest will be buffered + raw.block_on(b"k") + self.assertEquals(bufio.write(b"jklmn"), 5) - def testFlush(self): - writer = MockRawIO() - bufio = io.BufferedWriter(writer, 8) + # 8 bytes will be written, 8 will be buffered and the rest will be lost + raw.block_on(b"0") + try: + bufio.write(b"opqrwxyz0123456789") + except self.BlockingIOError as e: + written = e.characters_written + else: + self.fail("BlockingIOError should have been raised") + self.assertEquals(written, 16) + self.assertEquals(raw.pop_written(), + b"abcdefghijklmnopqrwxyz") + + self.assertEquals(bufio.write(b"ABCDEFGHI"), 9) + s = raw.pop_written() + # Previously buffered bytes were flushed + self.assertTrue(s.startswith(b"01234567A"), s) + + def test_write_and_rewind(self): + raw = io.BytesIO() + bufio = self.tp(raw, 4) + self.assertEqual(bufio.write(b"abcdef"), 6) + self.assertEqual(bufio.tell(), 6) + bufio.seek(0, 0) + self.assertEqual(bufio.write(b"XY"), 2) + bufio.seek(6, 0) + self.assertEqual(raw.getvalue(), b"XYcdef") + self.assertEqual(bufio.write(b"123456"), 6) + bufio.flush() + self.assertEqual(raw.getvalue(), b"XYcdef123456") + def test_flush(self): + writer = self.MockRawIO() + bufio = self.tp(writer, 8) bufio.write(b"abc") bufio.flush() + self.assertEquals(b"abc", writer._write_stack[0]) + def test_destructor(self): + writer = self.MockRawIO() + bufio = self.tp(writer, 8) + bufio.write(b"abc") + del bufio self.assertEquals(b"abc", writer._write_stack[0]) - def testThreads(self): - # BufferedWriter should not raise exceptions or crash - # when called from multiple threads. + def test_truncate(self): + # Truncate implicitly flushes the buffer. + with io.open(support.TESTFN, self.write_mode, buffering=0) as raw: + bufio = self.tp(raw, 8) + bufio.write(b"abcdef") + self.assertEqual(bufio.truncate(3), 3) + self.assertEqual(bufio.tell(), 3) + with io.open(support.TESTFN, "rb", buffering=0) as f: + self.assertEqual(f.read(), b"abc") + + def test_threads(self): try: + # Write out many bytes from many threads and test they were + # all flushed. + N = 1000 + contents = bytes(range(256)) * N + sizes = cycle([1, 19]) + n = 0 + queue = deque() + while n < len(contents): + size = next(sizes) + queue.append(contents[n:n+size]) + n += size + del contents # We use a real file object because it allows us to # exercise situations where the GIL is released before # writing the buffer to the raw streams. This is in addition # to concurrency issues due to switching threads in the middle # of Python code. - with io.open(support.TESTFN, "wb", buffering=0) as raw: - bufio = io.BufferedWriter(raw, 8) + with io.open(support.TESTFN, self.write_mode, buffering=0) as raw: + bufio = self.tp(raw, 8) errors = [] def f(): try: - # Write enough bytes to flush the buffer - s = b"a" * 19 - for i in range(50): + while True: + try: + s = queue.popleft() + except IndexError: + return bufio.write(s) except Exception as e: errors.append(e) @@ -554,37 +964,102 @@ t.join() self.assertFalse(errors, "the following exceptions were caught: %r" % errors) + bufio.close() + with io.open(support.TESTFN, "rb") as f: + s = f.read() + for i in range(256): + self.assertEquals(s.count(bytes([i])), N) finally: support.unlink(support.TESTFN) + def test_misbehaved_io(self): + rawio = self.MisbehavedRawIO() + bufio = self.tp(rawio, 5) + self.assertRaises(IOError, bufio.seek, 0) + self.assertRaises(IOError, bufio.tell) + self.assertRaises(IOError, bufio.write, b"abcdef") + +class CBufferedWriterTest(BufferedWriterTest): + tp = io.BufferedWriter + + def test_constructor(self): + BufferedWriterTest.test_constructor(self) + # The allocation can succeed on 32-bit builds, e.g. with more + # than 2GB RAM and a 64-bit kernel. + if sys.maxsize > 0x7FFFFFFF: + rawio = self.MockRawIO() + bufio = self.tp(rawio) + self.assertRaises((OverflowError, MemoryError, ValueError), + bufio.__init__, rawio, sys.maxsize) + + def test_initialization(self): + rawio = self.MockRawIO() + bufio = self.tp(rawio) + self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=0) + self.assertRaises(ValueError, bufio.write, b"def") + self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-16) + self.assertRaises(ValueError, bufio.write, b"def") + self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1) + self.assertRaises(ValueError, bufio.write, b"def") + + def test_garbage_collection(self): + # C BufferedWriter objects are collected, and collecting them flushes + # all data to disk. + # The Python version has __del__, so it ends into gc.garbage instead + rawio = self.FileIO(support.TESTFN, "w+b") + f = self.tp(rawio) + f.write(b"123xxx") + f.x = f + wr = weakref.ref(f) + del f + gc.collect() + self.assert_(wr() is None, wr) + with open(support.TESTFN, "rb") as f: + self.assertEqual(f.read(), b"123xxx") + + +class PyBufferedWriterTest(BufferedWriterTest): + tp = pyio.BufferedWriter class BufferedRWPairTest(unittest.TestCase): - def testRWPair(self): - r = MockRawIO(()) - w = MockRawIO() - pair = io.BufferedRWPair(r, w) + def test_basic(self): + r = self.MockRawIO(()) + w = self.MockRawIO() + pair = self.tp(r, w) self.assertFalse(pair.closed) # XXX More Tests +class CBufferedRWPairTest(BufferedRWPairTest): + tp = io.BufferedRWPair + +class PyBufferedRWPairTest(BufferedRWPairTest): + tp = pyio.BufferedRWPair + + +class BufferedRandomTest(BufferedReaderTest, BufferedWriterTest): + read_mode = "rb+" + write_mode = "wb+" -class BufferedRandomTest(unittest.TestCase): + def test_constructor(self): + BufferedReaderTest.test_constructor(self) + BufferedWriterTest.test_constructor(self) - def testReadAndWrite(self): - raw = MockRawIO((b"asdf", b"ghjk")) - rw = io.BufferedRandom(raw, 8, 12) + def test_read_and_write(self): + raw = self.MockRawIO((b"asdf", b"ghjk")) + rw = self.tp(raw, 8, 12) self.assertEqual(b"as", rw.read(2)) rw.write(b"ddd") rw.write(b"eee") self.assertFalse(raw._write_stack) # Buffer writes - self.assertEqual(b"ghjk", rw.read()) # This read forces write flush + self.assertEqual(b"ghjk", rw.read()) self.assertEquals(b"dddeee", raw._write_stack[0]) - def testSeekAndTell(self): - raw = io.BytesIO(b"asdfghjkl") - rw = io.BufferedRandom(raw) + def test_seek_and_tell(self): + raw = self.BytesIO(b"asdfghjkl") + rw = self.tp(raw) self.assertEquals(b"as", rw.read(2)) self.assertEquals(2, rw.tell()) @@ -602,6 +1077,115 @@ self.assertEquals(b"fl", rw.read(11)) self.assertRaises(TypeError, rw.seek, 0.0) + def check_flush_and_read(self, read_func): + raw = self.BytesIO(b"abcdefghi") + bufio = self.tp(raw) + + self.assertEquals(b"ab", read_func(bufio, 2)) + bufio.write(b"12") + self.assertEquals(b"ef", read_func(bufio, 2)) + self.assertEquals(6, bufio.tell()) + bufio.flush() + self.assertEquals(6, bufio.tell()) + self.assertEquals(b"ghi", read_func(bufio)) + raw.seek(0, 0) + raw.write(b"XYZ") + # flush() resets the read buffer + bufio.flush() + bufio.seek(0, 0) + self.assertEquals(b"XYZ", read_func(bufio, 3)) + + def test_flush_and_read(self): + self.check_flush_and_read(lambda bufio, *args: bufio.read(*args)) + + def test_flush_and_readinto(self): + def _readinto(bufio, n=-1): + b = bytearray(n if n >= 0 else 9999) + n = bufio.readinto(b) + return bytes(b[:n]) + self.check_flush_and_read(_readinto) + + def test_flush_and_peek(self): + def _peek(bufio, n=-1): + # This relies on the fact that the buffer can contain the whole + # raw stream, otherwise peek() can return less. + b = bufio.peek(n) + if n != -1: + b = b[:n] + bufio.seek(len(b), 1) + return b + self.check_flush_and_read(_peek) + + def test_flush_and_write(self): + raw = self.BytesIO(b"abcdefghi") + bufio = self.tp(raw) + + bufio.write(b"123") + bufio.flush() + bufio.write(b"45") + bufio.flush() + bufio.seek(0, 0) + self.assertEquals(b"12345fghi", raw.getvalue()) + self.assertEquals(b"12345fghi", bufio.read()) + + def test_threads(self): + BufferedReaderTest.test_threads(self) + BufferedWriterTest.test_threads(self) + + def test_writes_and_peek(self): + def _peek(bufio): + bufio.peek(1) + self.check_writes(_peek) + def _peek(bufio): + pos = bufio.tell() + bufio.seek(-1, 1) + bufio.peek(1) + bufio.seek(pos, 0) + self.check_writes(_peek) + + def test_writes_and_reads(self): + def _read(bufio): + bufio.seek(-1, 1) + bufio.read(1) + self.check_writes(_read) + + def test_writes_and_read1s(self): + def _read1(bufio): + bufio.seek(-1, 1) + bufio.read1(1) + self.check_writes(_read1) + + def test_writes_and_readintos(self): + def _read(bufio): + bufio.seek(-1, 1) + bufio.readinto(bytearray(1)) + self.check_writes(_read) + + def test_misbehaved_io(self): + BufferedReaderTest.test_misbehaved_io(self) + BufferedWriterTest.test_misbehaved_io(self) + +class CBufferedRandomTest(BufferedRandomTest): + tp = io.BufferedRandom + + def test_constructor(self): + BufferedRandomTest.test_constructor(self) + # The allocation can succeed on 32-bit builds, e.g. with more + # than 2GB RAM and a 64-bit kernel. + if sys.maxsize > 0x7FFFFFFF: + rawio = self.MockRawIO() + bufio = self.tp(rawio) + self.assertRaises((OverflowError, MemoryError, ValueError), + bufio.__init__, rawio, sys.maxsize) + + def test_garbage_collection(self): + CBufferedReaderTest.test_garbage_collection(self) + CBufferedWriterTest.test_garbage_collection(self) + +class PyBufferedRandomTest(BufferedRandomTest): + tp = pyio.BufferedRandom + + # To fully exercise seek/tell, the StatefulIncrementalDecoder has these # properties: # - A single output character can correspond to many bytes of input. @@ -735,7 +1319,7 @@ 'm--------------.') ] - def testDecoder(self): + def test_decoder(self): # Try a few one-shot test cases. for input, eof, output in self.test_cases: d = StatefulIncrementalDecoder() @@ -756,10 +1340,24 @@ def tearDown(self): support.unlink(support.TESTFN) - def testLineBuffering(self): - r = io.BytesIO() - b = io.BufferedWriter(r, 1000) - t = io.TextIOWrapper(b, newline="\n", line_buffering=True) + def test_constructor(self): + r = self.BytesIO(b"\xc3\xa9\n\n") + b = self.BufferedReader(r, 1000) + t = self.TextIOWrapper(b) + t.__init__(b, encoding="latin1", newline="\r\n") + self.assertEquals(t.encoding, "latin1") + self.assertEquals(t.line_buffering, False) + t.__init__(b, encoding="utf8", line_buffering=True) + self.assertEquals(t.encoding, "utf8") + self.assertEquals(t.line_buffering, True) + self.assertEquals("\xe9\n", t.readline()) + self.assertRaises(TypeError, t.__init__, b, newline=42) + self.assertRaises(ValueError, t.__init__, b, newline='xyzzy') + + def test_line_buffering(self): + r = self.BytesIO() + b = self.BufferedWriter(r, 1000) + t = self.TextIOWrapper(b, newline="\n", line_buffering=True) t.write("X") self.assertEquals(r.getvalue(), b"") # No flush happened t.write("Y\nZ") @@ -767,83 +1365,58 @@ t.write("A\rB") self.assertEquals(r.getvalue(), b"XY\nZA\rB") - def testEncodingErrorsReading(self): + def test_encoding(self): + # Check the encoding attribute is always set, and valid + b = self.BytesIO() + t = self.TextIOWrapper(b, encoding="utf8") + self.assertEqual(t.encoding, "utf8") + t = self.TextIOWrapper(b) + self.assert_(t.encoding is not None) + codecs.lookup(t.encoding) + + def test_encoding_errors_reading(self): # (1) default - b = io.BytesIO(b"abc\n\xff\n") - t = io.TextIOWrapper(b, encoding="ascii") + b = self.BytesIO(b"abc\n\xff\n") + t = self.TextIOWrapper(b, encoding="ascii") self.assertRaises(UnicodeError, t.read) # (2) explicit strict - b = io.BytesIO(b"abc\n\xff\n") - t = io.TextIOWrapper(b, encoding="ascii", errors="strict") + b = self.BytesIO(b"abc\n\xff\n") + t = self.TextIOWrapper(b, encoding="ascii", errors="strict") self.assertRaises(UnicodeError, t.read) # (3) ignore - b = io.BytesIO(b"abc\n\xff\n") - t = io.TextIOWrapper(b, encoding="ascii", errors="ignore") + b = self.BytesIO(b"abc\n\xff\n") + t = self.TextIOWrapper(b, encoding="ascii", errors="ignore") self.assertEquals(t.read(), "abc\n\n") # (4) replace - b = io.BytesIO(b"abc\n\xff\n") - t = io.TextIOWrapper(b, encoding="ascii", errors="replace") + b = self.BytesIO(b"abc\n\xff\n") + t = self.TextIOWrapper(b, encoding="ascii", errors="replace") self.assertEquals(t.read(), "abc\n\ufffd\n") - def testEncodingErrorsWriting(self): + def test_encoding_errors_writing(self): # (1) default - b = io.BytesIO() - t = io.TextIOWrapper(b, encoding="ascii") + b = self.BytesIO() + t = self.TextIOWrapper(b, encoding="ascii") self.assertRaises(UnicodeError, t.write, "\xff") # (2) explicit strict - b = io.BytesIO() - t = io.TextIOWrapper(b, encoding="ascii", errors="strict") + b = self.BytesIO() + t = self.TextIOWrapper(b, encoding="ascii", errors="strict") self.assertRaises(UnicodeError, t.write, "\xff") # (3) ignore - b = io.BytesIO() - t = io.TextIOWrapper(b, encoding="ascii", errors="ignore", + b = self.BytesIO() + t = self.TextIOWrapper(b, encoding="ascii", errors="ignore", newline="\n") t.write("abc\xffdef\n") t.flush() self.assertEquals(b.getvalue(), b"abcdef\n") # (4) replace - b = io.BytesIO() - t = io.TextIOWrapper(b, encoding="ascii", errors="replace", + b = self.BytesIO() + t = self.TextIOWrapper(b, encoding="ascii", errors="replace", newline="\n") t.write("abc\xffdef\n") t.flush() self.assertEquals(b.getvalue(), b"abc?def\n") - def testNewlinesInput(self): - testdata = b"AAA\nBBB\nCCC\rDDD\rEEE\r\nFFF\r\nGGG" - normalized = testdata.replace(b"\r\n", b"\n").replace(b"\r", b"\n") - for newline, expected in [ - (None, normalized.decode("ascii").splitlines(True)), - ("", testdata.decode("ascii").splitlines(True)), - ("\n", ["AAA\n", "BBB\n", "CCC\rDDD\rEEE\r\n", "FFF\r\n", "GGG"]), - ("\r\n", ["AAA\nBBB\nCCC\rDDD\rEEE\r\n", "FFF\r\n", "GGG"]), - ("\r", ["AAA\nBBB\nCCC\r", "DDD\r", "EEE\r", "\nFFF\r", "\nGGG"]), - ]: - buf = io.BytesIO(testdata) - txt = io.TextIOWrapper(buf, encoding="ascii", newline=newline) - self.assertEquals(txt.readlines(), expected) - txt.seek(0) - self.assertEquals(txt.read(), "".join(expected)) - - def testNewlinesOutput(self): - testdict = { - "": b"AAA\nBBB\nCCC\nX\rY\r\nZ", - "\n": b"AAA\nBBB\nCCC\nX\rY\r\nZ", - "\r": b"AAA\rBBB\rCCC\rX\rY\r\rZ", - "\r\n": b"AAA\r\nBBB\r\nCCC\r\nX\rY\r\r\nZ", - } - tests = [(None, testdict[os.linesep])] + sorted(testdict.items()) - for newline, expected in tests: - buf = io.BytesIO() - txt = io.TextIOWrapper(buf, encoding="ascii", newline=newline) - txt.write("AAA\nB") - txt.write("BB\nCCC\n") - txt.write("X\rY\r\nZ") - txt.flush() - self.assertEquals(buf.closed, False) - self.assertEquals(buf.getvalue(), expected) - - def testNewlines(self): + def test_newlines(self): input_lines = [ "unix\n", "windows\r\n", "os9\r", "last\n", "nonl" ] tests = [ @@ -867,8 +1440,8 @@ for do_reads in (False, True): for bufsize in range(1, 10): for newline, exp_lines in tests: - bufio = io.BufferedReader(io.BytesIO(data), bufsize) - textio = io.TextIOWrapper(bufio, newline=newline, + bufio = self.BufferedReader(self.BytesIO(data), bufsize) + textio = self.TextIOWrapper(bufio, newline=newline, encoding=encoding) if do_reads: got_lines = [] @@ -885,60 +1458,100 @@ self.assertEquals(got_line, exp_line) self.assertEquals(len(got_lines), len(exp_lines)) - def testNewlinesInput(self): - testdata = b"AAA\nBBB\nCCC\rDDD\rEEE\r\nFFF\r\nGGG" + def test_newlines_input(self): + testdata = b"AAA\nBB\x00B\nCCC\rDDD\rEEE\r\nFFF\r\nGGG" normalized = testdata.replace(b"\r\n", b"\n").replace(b"\r", b"\n") for newline, expected in [ (None, normalized.decode("ascii").splitlines(True)), ("", testdata.decode("ascii").splitlines(True)), - ("\n", ["AAA\n", "BBB\n", "CCC\rDDD\rEEE\r\n", "FFF\r\n", "GGG"]), - ("\r\n", ["AAA\nBBB\nCCC\rDDD\rEEE\r\n", "FFF\r\n", "GGG"]), - ("\r", ["AAA\nBBB\nCCC\r", "DDD\r", "EEE\r", "\nFFF\r", "\nGGG"]), + ("\n", ["AAA\n", "BB\x00B\n", "CCC\rDDD\rEEE\r\n", "FFF\r\n", "GGG"]), + ("\r\n", ["AAA\nBB\x00B\nCCC\rDDD\rEEE\r\n", "FFF\r\n", "GGG"]), + ("\r", ["AAA\nBB\x00B\nCCC\r", "DDD\r", "EEE\r", "\nFFF\r", "\nGGG"]), ]: - buf = io.BytesIO(testdata) - txt = io.TextIOWrapper(buf, encoding="ascii", newline=newline) + buf = self.BytesIO(testdata) + txt = self.TextIOWrapper(buf, encoding="ascii", newline=newline) self.assertEquals(txt.readlines(), expected) txt.seek(0) self.assertEquals(txt.read(), "".join(expected)) - def testNewlinesOutput(self): - data = "AAA\nBBB\rCCC\n" - data_lf = b"AAA\nBBB\rCCC\n" - data_cr = b"AAA\rBBB\rCCC\r" - data_crlf = b"AAA\r\nBBB\rCCC\r\n" - save_linesep = os.linesep - try: - for os.linesep, newline, expected in [ - ("\n", None, data_lf), - ("\r\n", None, data_crlf), - ("\n", "", data_lf), - ("\r\n", "", data_lf), - ("\n", "\n", data_lf), - ("\r\n", "\n", data_lf), - ("\n", "\r", data_cr), - ("\r\n", "\r", data_cr), - ("\n", "\r\n", data_crlf), - ("\r\n", "\r\n", data_crlf), - ]: - buf = io.BytesIO() - txt = io.TextIOWrapper(buf, encoding="ascii", newline=newline) - txt.write(data) - txt.close() - self.assertEquals(buf.closed, True) - self.assertRaises(ValueError, buf.getvalue) - finally: - os.linesep = save_linesep + def test_newlines_output(self): + testdict = { + "": b"AAA\nBBB\nCCC\nX\rY\r\nZ", + "\n": b"AAA\nBBB\nCCC\nX\rY\r\nZ", + "\r": b"AAA\rBBB\rCCC\rX\rY\r\rZ", + "\r\n": b"AAA\r\nBBB\r\nCCC\r\nX\rY\r\r\nZ", + } + tests = [(None, testdict[os.linesep])] + sorted(testdict.items()) + for newline, expected in tests: + buf = self.BytesIO() + txt = self.TextIOWrapper(buf, encoding="ascii", newline=newline) + txt.write("AAA\nB") + txt.write("BB\nCCC\n") + txt.write("X\rY\r\nZ") + txt.flush() + self.assertEquals(buf.closed, False) + self.assertEquals(buf.getvalue(), expected) + + def test_destructor(self): + l = [] + base = self.BytesIO + class MyBytesIO(base): + def close(self): + l.append(self.getvalue()) + base.close(self) + b = MyBytesIO() + t = self.TextIOWrapper(b, encoding="ascii") + t.write("abc") + del t + self.assertEquals([b"abc"], l) + + def test_override_destructor(self): + record = [] + class MyTextIO(self.TextIOWrapper): + def __del__(self): + record.append(1) + try: + f = super().__del__ + except AttributeError: + pass + else: + f() + def close(self): + record.append(2) + super().close() + def flush(self): + record.append(3) + super().flush() + b = self.BytesIO() + t = MyTextIO(b, encoding="ascii") + del t + self.assertEqual(record, [1, 2, 3]) + + def test_error_through_destructor(self): + # Test that the exception state is not modified by a destructor, + # even if close() fails. + rawio = self.CloseFailureIO() + def f(): + self.TextIOWrapper(rawio).xyzzy + with support.captured_output("stderr") as s: + self.assertRaises(AttributeError, f) + s = s.getvalue().strip() + if s: + # The destructor *may* have printed an unraisable error, check it + self.assertEqual(len(s.splitlines()), 1) + self.assert_(s.startswith("Exception IOError: "), s) + self.assert_(s.endswith(" ignored"), s) # Systematic tests of the text I/O API - def testBasicIO(self): + def test_basic_io(self): for chunksize in (1, 2, 3, 4, 5, 15, 16, 17, 31, 32, 33, 63, 64, 65): for enc in "ascii", "latin1", "utf8" :# , "utf-16-be", "utf-16-le": - f = io.open(support.TESTFN, "w+", encoding=enc) + f = self.open(support.TESTFN, "w+", encoding=enc) f._CHUNK_SIZE = chunksize self.assertEquals(f.write("abc"), 3) f.close() - f = io.open(support.TESTFN, "r+", encoding=enc) + f = self.open(support.TESTFN, "r+", encoding=enc) f._CHUNK_SIZE = chunksize self.assertEquals(f.tell(), 0) self.assertEquals(f.read(), "abc") @@ -980,8 +1593,8 @@ rlines.append((pos, line)) self.assertEquals(rlines, wlines) - def testTelling(self): - f = io.open(support.TESTFN, "w+", encoding="utf8") + def test_telling(self): + f = self.open(support.TESTFN, "w+", encoding="utf8") p0 = f.tell() f.write("\xff\n") p1 = f.tell() @@ -1000,8 +1613,8 @@ self.assertEquals(f.tell(), p2) f.close() - def testSeeking(self): - chunk_size = io.TextIOWrapper._CHUNK_SIZE + def test_seeking(self): + chunk_size = _default_chunk_size() prefix_size = chunk_size - 2 u_prefix = "a" * prefix_size prefix = bytes(u_prefix.encode("utf-8")) @@ -1009,48 +1622,46 @@ u_suffix = "\u8888\n" suffix = bytes(u_suffix.encode("utf-8")) line = prefix + suffix - f = io.open(support.TESTFN, "wb") + f = self.open(support.TESTFN, "wb") f.write(line*2) f.close() - f = io.open(support.TESTFN, "r", encoding="utf-8") + f = self.open(support.TESTFN, "r", encoding="utf-8") s = f.read(prefix_size) self.assertEquals(s, str(prefix, "ascii")) self.assertEquals(f.tell(), prefix_size) self.assertEquals(f.readline(), u_suffix) - def testSeekingToo(self): + def test_seeking_too(self): # Regression test for a specific bug data = b'\xe0\xbf\xbf\n' - f = io.open(support.TESTFN, "wb") + f = self.open(support.TESTFN, "wb") f.write(data) f.close() - f = io.open(support.TESTFN, "r", encoding="utf-8") + f = self.open(support.TESTFN, "r", encoding="utf-8") f._CHUNK_SIZE # Just test that it exists f._CHUNK_SIZE = 2 f.readline() f.tell() - def testSeekAndTell(self): - """Test seek/tell using the StatefulIncrementalDecoder.""" - # Make this test faster by forcing a smaller (but large enough) - # chunk size. The bigger the chunker size, the slower seek() is, - # as it tries to replay character decoding one byte at a time. - CHUNK_SIZE = 256 + def test_seek_and_tell(self): + #Test seek/tell using the StatefulIncrementalDecoder. + # Make test faster by doing smaller seeks + CHUNK_SIZE = 128 def testSeekAndTellWithData(data, min_pos=0): """Tell/seek to various points within a data stream and ensure that the decoded data returned by read() is consistent.""" - f = io.open(support.TESTFN, 'wb') + f = self.open(support.TESTFN, 'wb') f.write(data) f.close() - f = io.open(support.TESTFN, encoding='test_decoder') + f = self.open(support.TESTFN, encoding='test_decoder') + f._CHUNK_SIZE = CHUNK_SIZE decoded = f.read() f.close() for i in range(min_pos, len(decoded) + 1): # seek positions for j in [1, 5, len(decoded) - i]: # read lengths - f = io.open(support.TESTFN, encoding='test_decoder') - f._CHUNK_SIZE = CHUNK_SIZE + f = self.open(support.TESTFN, encoding='test_decoder') self.assertEquals(f.read(i), decoded[:i]) cookie = f.tell() self.assertEquals(f.read(j), decoded[i:i + j]) @@ -1079,7 +1690,7 @@ finally: StatefulIncrementalDecoder.codecEnabled = 0 - def testEncodedWrites(self): + def test_encoded_writes(self): data = "1234567890" tests = ("utf-16", "utf-16-le", @@ -1088,8 +1699,8 @@ "utf-32-le", "utf-32-be") for encoding in tests: - buf = io.BytesIO() - f = io.TextIOWrapper(buf, encoding=encoding) + buf = self.BytesIO() + f = self.TextIOWrapper(buf, encoding=encoding) # Check if the BOM is written only once (see issue1753). f.write(data) f.write(data) @@ -1097,45 +1708,8 @@ self.assertEquals(f.read(), data * 2) self.assertEquals(buf.getvalue(), (data * 2).encode(encoding)) - def timingTest(self): - timer = time.time - enc = "utf8" - line = "\0\x0f\xff\u0fff\uffff\U000fffff\U0010ffff"*3 + "\n" - nlines = 10000 - nchars = len(line) - nbytes = len(line.encode(enc)) - for chunk_size in (32, 64, 128, 256): - f = io.open(support.TESTFN, "w+", encoding=enc) - f._CHUNK_SIZE = chunk_size - t0 = timer() - for i in range(nlines): - f.write(line) - f.flush() - t1 = timer() - f.seek(0) - for line in f: - pass - t2 = timer() - f.seek(0) - while f.readline(): - pass - t3 = timer() - f.seek(0) - while f.readline(): - f.tell() - t4 = timer() - f.close() - if support.verbose: - print("\nTiming test: %d lines of %d characters (%d bytes)" % - (nlines, nchars, nbytes)) - print("File chunk size: %6s" % f._CHUNK_SIZE) - print("Writing: %6.3f seconds" % (t1-t0)) - print("Reading using iteration: %6.3f seconds" % (t2-t1)) - print("Reading using readline(): %6.3f seconds" % (t3-t2)) - print("Using readline()+tell(): %6.3f seconds" % (t4-t3)) - - def testReadOneByOne(self): - txt = io.TextIOWrapper(io.BytesIO(b"AA\r\nBB")) + def test_read_one_by_one(self): + txt = self.TextIOWrapper(self.BytesIO(b"AA\r\nBB")) reads = "" while True: c = txt.read(1) @@ -1145,9 +1719,9 @@ self.assertEquals(reads, "AA\nBB") # read in amounts equal to TextIOWrapper._CHUNK_SIZE which is 128. - def testReadByChunk(self): + def test_read_by_chunk(self): # make sure "\r\n" straddles 128 char boundary. - txt = io.TextIOWrapper(io.BytesIO(b"A" * 127 + b"\r\nB")) + txt = self.TextIOWrapper(self.BytesIO(b"A" * 127 + b"\r\nB")) reads = "" while True: c = txt.read(128) @@ -1157,7 +1731,7 @@ self.assertEquals(reads, "A"*127+"\nB") def test_issue1395_1(self): - txt = io.TextIOWrapper(io.BytesIO(self.testdata), encoding="ascii") + txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") # read one char at a time reads = "" @@ -1169,7 +1743,7 @@ self.assertEquals(reads, self.normalized) def test_issue1395_2(self): - txt = io.TextIOWrapper(io.BytesIO(self.testdata), encoding="ascii") + txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") txt._CHUNK_SIZE = 4 reads = "" @@ -1181,7 +1755,7 @@ self.assertEquals(reads, self.normalized) def test_issue1395_3(self): - txt = io.TextIOWrapper(io.BytesIO(self.testdata), encoding="ascii") + txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") txt._CHUNK_SIZE = 4 reads = txt.read(4) @@ -1192,7 +1766,7 @@ self.assertEquals(reads, self.normalized) def test_issue1395_4(self): - txt = io.TextIOWrapper(io.BytesIO(self.testdata), encoding="ascii") + txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") txt._CHUNK_SIZE = 4 reads = txt.read(4) @@ -1200,7 +1774,7 @@ self.assertEquals(reads, self.normalized) def test_issue1395_5(self): - txt = io.TextIOWrapper(io.BytesIO(self.testdata), encoding="ascii") + txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") txt._CHUNK_SIZE = 4 reads = txt.read(4) @@ -1210,12 +1784,45 @@ self.assertEquals(txt.read(4), "BBB\n") def test_issue2282(self): - buffer = io.BytesIO(self.testdata) - txt = io.TextIOWrapper(buffer, encoding="ascii") + buffer = self.BytesIO(self.testdata) + txt = self.TextIOWrapper(buffer, encoding="ascii") self.assertEqual(buffer.seekable(), txt.seekable()) - def check_newline_decoder_utf8(self, decoder): +class CTextIOWrapperTest(TextIOWrapperTest): + + def test_initialization(self): + r = self.BytesIO(b"\xc3\xa9\n\n") + b = self.BufferedReader(r, 1000) + t = self.TextIOWrapper(b) + self.assertRaises(TypeError, t.__init__, b, newline=42) + self.assertRaises(ValueError, t.read) + self.assertRaises(ValueError, t.__init__, b, newline='xyzzy') + self.assertRaises(ValueError, t.read) + + def test_garbage_collection(self): + # C TextIOWrapper objects are collected, and collecting them flushes + # all data to disk. + # The Python version has __del__, so it ends in gc.garbage instead. + rawio = io.FileIO(support.TESTFN, "wb") + b = self.BufferedWriter(rawio) + t = self.TextIOWrapper(b, encoding="ascii") + t.write("456def") + t.x = t + wr = weakref.ref(t) + del t + gc.collect() + self.assert_(wr() is None, wr) + with open(support.TESTFN, "rb") as f: + self.assertEqual(f.read(), b"456def") + +class PyTextIOWrapperTest(TextIOWrapperTest): + pass + + +class IncrementalNewlineDecoderTest(unittest.TestCase): + + def check_newline_decoding_utf8(self, decoder): # UTF-8 specific tests for a newline decoder def _check_decode(b, s, **kwargs): # We exercise getstate() / setstate() as well as decode() @@ -1257,12 +1864,20 @@ _check_decode(b'\xe8\xa2\x88\r', "\u8888") _check_decode(b'\n', "\n") - def check_newline_decoder(self, decoder, encoding): + def check_newline_decoding(self, decoder, encoding): result = [] - encoder = codecs.getincrementalencoder(encoding)() - def _decode_bytewise(s): - for b in encoder.encode(s): - result.append(decoder.decode(bytes([b]))) + if encoding is not None: + encoder = codecs.getincrementalencoder(encoding)() + def _decode_bytewise(s): + # Decode one byte at a time + for b in encoder.encode(s): + result.append(decoder.decode(bytes([b]))) + else: + encoder = None + def _decode_bytewise(s): + # Decode one char at a time + for c in s: + result.append(decoder.decode(c)) self.assertEquals(decoder.newlines, None) _decode_bytewise("abc\n\r") self.assertEquals(decoder.newlines, '\n') @@ -1275,22 +1890,34 @@ _decode_bytewise("abc\r") self.assertEquals("".join(result), "abc\n\nabcabc\nabcabc") decoder.reset() - self.assertEquals(decoder.decode("abc".encode(encoding)), "abc") + input = "abc" + if encoder is not None: + encoder.reset() + input = encoder.encode(input) + self.assertEquals(decoder.decode(input), "abc") self.assertEquals(decoder.newlines, None) def test_newline_decoder(self): encodings = ( - 'utf-8', 'latin-1', + # None meaning the IncrementalNewlineDecoder takes unicode input + # rather than bytes input + None, 'utf-8', 'latin-1', 'utf-16', 'utf-16-le', 'utf-16-be', 'utf-32', 'utf-32-le', 'utf-32-be', ) for enc in encodings: - decoder = codecs.getincrementaldecoder(enc)() - decoder = io.IncrementalNewlineDecoder(decoder, translate=True) - self.check_newline_decoder(decoder, enc) + decoder = enc and codecs.getincrementaldecoder(enc)() + decoder = self.IncrementalNewlineDecoder(decoder, translate=True) + self.check_newline_decoding(decoder, enc) decoder = codecs.getincrementaldecoder("utf-8")() - decoder = io.IncrementalNewlineDecoder(decoder, translate=True) - self.check_newline_decoder_utf8(decoder) + decoder = self.IncrementalNewlineDecoder(decoder, translate=True) + self.check_newline_decoding_utf8(decoder) + +class CIncrementalNewlineDecoderTest(IncrementalNewlineDecoderTest): + pass + +class PyIncrementalNewlineDecoderTest(IncrementalNewlineDecoderTest): + pass # XXX Tests for open() @@ -1300,24 +1927,23 @@ def tearDown(self): support.unlink(support.TESTFN) - def testImport__all__(self): - for name in io.__all__: - obj = getattr(io, name, None) + def test___all__(self): + for name in self.io.__all__: + obj = getattr(self.io, name, None) self.assert_(obj is not None, name) if name == "open": continue elif "error" in name.lower(): self.assert_(issubclass(obj, Exception), name) else: - self.assert_(issubclass(obj, io.IOBase)) - + self.assert_(issubclass(obj, self.IOBase), name) def test_attributes(self): - f = io.open(support.TESTFN, "wb", buffering=0) + f = self.open(support.TESTFN, "wb", buffering=0) self.assertEquals(f.mode, "wb") f.close() - f = io.open(support.TESTFN, "U") + f = self.open(support.TESTFN, "U") self.assertEquals(f.name, support.TESTFN) self.assertEquals(f.buffer.name, support.TESTFN) self.assertEquals(f.buffer.raw.name, support.TESTFN) @@ -1326,12 +1952,12 @@ self.assertEquals(f.buffer.raw.mode, "rb") f.close() - f = io.open(support.TESTFN, "w+") + f = self.open(support.TESTFN, "w+") self.assertEquals(f.mode, "w+") self.assertEquals(f.buffer.mode, "rb+") # Does it really matter? self.assertEquals(f.buffer.raw.mode, "rb+") - g = io.open(f.fileno(), "wb", closefd=False) + g = self.open(f.fileno(), "wb", closefd=False) self.assertEquals(g.mode, "wb") self.assertEquals(g.raw.mode, "wb") self.assertEquals(g.name, f.fileno()) @@ -1357,13 +1983,12 @@ {"mode": "w+", "buffering": 2}, {"mode": "w+b", "buffering": 0}, ]: - f = io.open(support.TESTFN, **kwargs) + f = self.open(support.TESTFN, **kwargs) f.close() self.assertRaises(ValueError, f.flush) self.assertRaises(ValueError, f.fileno) self.assertRaises(ValueError, f.isatty) self.assertRaises(ValueError, f.__iter__) - self.assertRaises(ValueError, next, f) if hasattr(f, "peek"): self.assertRaises(ValueError, f.peek, 1) self.assertRaises(ValueError, f.read) @@ -1376,16 +2001,101 @@ self.assertRaises(ValueError, f.seek, 0) self.assertRaises(ValueError, f.tell) self.assertRaises(ValueError, f.truncate) - self.assertRaises(ValueError, f.write, "") + self.assertRaises(ValueError, f.write, + b"" if "b" in kwargs['mode'] else "") self.assertRaises(ValueError, f.writelines, []) + self.assertRaises(ValueError, next, f) + def test_blockingioerror(self): + # Various BlockingIOError issues + self.assertRaises(TypeError, self.BlockingIOError) + self.assertRaises(TypeError, self.BlockingIOError, 1) + self.assertRaises(TypeError, self.BlockingIOError, 1, 2, 3, 4) + self.assertRaises(TypeError, self.BlockingIOError, 1, "", None) + b = self.BlockingIOError(1, "") + self.assertEqual(b.characters_written, 0) + class C(str): + pass + c = C("") + b = self.BlockingIOError(1, c) + c.b = b + b.c = c + wr = weakref.ref(c) + del c, b + gc.collect() + self.assert_(wr() is None, wr) + + def test_abcs(self): + # Test the visible base classes are ABCs. + self.assertTrue(isinstance(self.IOBase, abc.ABCMeta)) + self.assertTrue(isinstance(self.RawIOBase, abc.ABCMeta)) + self.assertTrue(isinstance(self.BufferedIOBase, abc.ABCMeta)) + self.assertTrue(isinstance(self.TextIOBase, abc.ABCMeta)) + + def _check_abc_inheritance(self, abcmodule): + with self.open(support.TESTFN, "wb", buffering=0) as f: + self.assertTrue(isinstance(f, abcmodule.IOBase)) + self.assertTrue(isinstance(f, abcmodule.RawIOBase)) + self.assertFalse(isinstance(f, abcmodule.BufferedIOBase)) + self.assertFalse(isinstance(f, abcmodule.TextIOBase)) + with self.open(support.TESTFN, "wb") as f: + self.assertTrue(isinstance(f, abcmodule.IOBase)) + self.assertFalse(isinstance(f, abcmodule.RawIOBase)) + self.assertTrue(isinstance(f, abcmodule.BufferedIOBase)) + self.assertFalse(isinstance(f, abcmodule.TextIOBase)) + with self.open(support.TESTFN, "w") as f: + self.assertTrue(isinstance(f, abcmodule.IOBase)) + self.assertFalse(isinstance(f, abcmodule.RawIOBase)) + self.assertFalse(isinstance(f, abcmodule.BufferedIOBase)) + self.assertTrue(isinstance(f, abcmodule.TextIOBase)) + + def test_abc_inheritance(self): + # Test implementations inherit from their respective ABCs + self._check_abc_inheritance(self) + + def test_abc_inheritance_official(self): + # Test implementations inherit from the official ABCs of the + # baseline "io" module. + self._check_abc_inheritance(io) + +class CMiscIOTest(MiscIOTest): + io = io + +class PyMiscIOTest(MiscIOTest): + io = pyio def test_main(): - support.run_unittest(IOTest, BytesIOTest, StringIOTest, - BufferedReaderTest, BufferedWriterTest, - BufferedRWPairTest, BufferedRandomTest, - StatefulIncrementalDecoderTest, - TextIOWrapperTest, MiscIOTest) + tests = (CIOTest, PyIOTest, + CBufferedReaderTest, PyBufferedReaderTest, + CBufferedWriterTest, PyBufferedWriterTest, + CBufferedRWPairTest, PyBufferedRWPairTest, + CBufferedRandomTest, PyBufferedRandomTest, + StatefulIncrementalDecoderTest, + CIncrementalNewlineDecoderTest, PyIncrementalNewlineDecoderTest, + CTextIOWrapperTest, PyTextIOWrapperTest, + CMiscIOTest, PyMiscIOTest,) + + # Put the namespaces of the IO module we are testing and some useful mock + # classes in the __dict__ of each test. + mocks = (MockRawIO, MisbehavedRawIO, MockFileIO, CloseFailureIO, + MockNonBlockWriterIO) + all_members = io.__all__ + ["IncrementalNewlineDecoder"] + c_io_ns = {name : getattr(io, name) for name in all_members} + py_io_ns = {name : getattr(pyio, name) for name in all_members} + globs = globals() + c_io_ns.update((x.__name__, globs["C" + x.__name__]) for x in mocks) + py_io_ns.update((x.__name__, globs["Py" + x.__name__]) for x in mocks) + # Avoid turning open into a bound method. + py_io_ns["open"] = pyio.OpenWrapper + for test in tests: + if test.__name__.startswith("C"): + for name, obj in c_io_ns.items(): + setattr(test, name, obj) + elif test.__name__.startswith("Py"): + for name, obj in py_io_ns.items(): + setattr(test, name, obj) + + support.run_unittest(*tests) if __name__ == "__main__": - unittest.main() + test_main() Modified: python/branches/py3k/Lib/test/test_largefile.py ============================================================================== --- python/branches/py3k/Lib/test/test_largefile.py (original) +++ python/branches/py3k/Lib/test/test_largefile.py Wed Mar 4 01:14:51 2009 @@ -7,6 +7,8 @@ import unittest from test.support import run_unittest, TESTFN, verbose, requires, \ TestSkipped, unlink +import io # C implementation of io +import _pyio as pyio # Python implementation of io try: import signal @@ -21,7 +23,7 @@ size = 2500000000 -class TestCase(unittest.TestCase): +class LargeFileTest(unittest.TestCase): """Test that each file function works as expected for a large (i.e. > 2GB, do we have to check > 4GB) files. @@ -34,7 +36,7 @@ def test_seek(self): if verbose: print('create large file via seek (may be sparse file) ...') - with open(TESTFN, 'wb') as f: + with self.open(TESTFN, 'wb') as f: f.write(b'z') f.seek(0) f.seek(size) @@ -52,7 +54,7 @@ def test_seek_read(self): if verbose: print('play around with seek() and read() with the built largefile') - with open(TESTFN, 'rb') as f: + with self.open(TESTFN, 'rb') as f: self.assertEqual(f.tell(), 0) self.assertEqual(f.read(1), b'z') self.assertEqual(f.tell(), 1) @@ -85,7 +87,7 @@ def test_lseek(self): if verbose: print('play around with os.lseek() with the built largefile') - with open(TESTFN, 'rb') as f: + with self.open(TESTFN, 'rb') as f: self.assertEqual(os.lseek(f.fileno(), 0, 0), 0) self.assertEqual(os.lseek(f.fileno(), 42, 0), 42) self.assertEqual(os.lseek(f.fileno(), 42, 1), 84) @@ -100,7 +102,7 @@ def test_truncate(self): if verbose: print('try truncate') - with open(TESTFN, 'r+b') as f: + with self.open(TESTFN, 'r+b') as f: # this is already decided before start running the test suite # but we do it anyway for extra protection if not hasattr(f, 'truncate'): @@ -143,7 +145,7 @@ # Only run if the current filesystem supports large files. # (Skip this test on Windows, since we now always support # large files.) - f = open(TESTFN, 'wb') + f = open(TESTFN, 'wb', buffering=0) try: # 2**31 == 2147483648 f.seek(2147483649) @@ -158,14 +160,19 @@ else: f.close() suite = unittest.TestSuite() - suite.addTest(TestCase('test_seek')) - suite.addTest(TestCase('test_osstat')) - suite.addTest(TestCase('test_seek_read')) - suite.addTest(TestCase('test_lseek')) - with open(TESTFN, 'w') as f: - if hasattr(f, 'truncate'): - suite.addTest(TestCase('test_truncate')) - unlink(TESTFN) + for _open, prefix in [(io.open, 'C'), (pyio.open, 'Py')]: + class TestCase(LargeFileTest): + pass + TestCase.open = staticmethod(_open) + TestCase.__name__ = prefix + LargeFileTest.__name__ + suite.addTest(TestCase('test_seek')) + suite.addTest(TestCase('test_osstat')) + suite.addTest(TestCase('test_seek_read')) + suite.addTest(TestCase('test_lseek')) + with _open(TESTFN, 'wb') as f: + if hasattr(f, 'truncate'): + suite.addTest(TestCase('test_truncate')) + unlink(TESTFN) try: run_unittest(suite) finally: Modified: python/branches/py3k/Lib/test/test_memoryio.py ============================================================================== --- python/branches/py3k/Lib/test/test_memoryio.py (original) +++ python/branches/py3k/Lib/test/test_memoryio.py Wed Mar 4 01:14:51 2009 @@ -7,13 +7,52 @@ from test import support import io +import _pyio as pyio import sys -try: - import _bytesio, _stringio - has_c_implementation = True -except ImportError: - has_c_implementation = False +class MemorySeekTestMixin: + + def testInit(self): + buf = self.buftype("1234567890") + bytesIo = self.ioclass(buf) + + def testRead(self): + buf = self.buftype("1234567890") + bytesIo = self.ioclass(buf) + + self.assertEquals(buf[:1], bytesIo.read(1)) + self.assertEquals(buf[1:5], bytesIo.read(4)) + self.assertEquals(buf[5:], bytesIo.read(900)) + self.assertEquals(self.EOF, bytesIo.read()) + + def testReadNoArgs(self): + buf = self.buftype("1234567890") + bytesIo = self.ioclass(buf) + + self.assertEquals(buf, bytesIo.read()) + self.assertEquals(self.EOF, bytesIo.read()) + + def testSeek(self): + buf = self.buftype("1234567890") + bytesIo = self.ioclass(buf) + + bytesIo.read(5) + bytesIo.seek(0) + self.assertEquals(buf, bytesIo.read()) + + bytesIo.seek(3) + self.assertEquals(buf[3:], bytesIo.read()) + self.assertRaises(TypeError, bytesIo.seek, 0.0) + + def testTell(self): + buf = self.buftype("1234567890") + bytesIo = self.ioclass(buf) + + self.assertEquals(0, bytesIo.tell()) + bytesIo.seek(5) + self.assertEquals(5, bytesIo.tell()) + bytesIo.seek(10000) + self.assertEquals(10000, bytesIo.tell()) class MemoryTestMixin: @@ -148,7 +187,7 @@ self.assertEqual(memio.readline(), self.EOF) memio.seek(0) self.assertEqual(type(memio.readline()), type(buf)) - self.assertEqual(memio.readline(None), buf) + self.assertEqual(memio.readline(), buf) self.assertRaises(TypeError, memio.readline, '') memio.close() self.assertRaises(ValueError, memio.readline) @@ -296,11 +335,11 @@ self.assertEqual(test2(), buf) -class PyBytesIOTest(MemoryTestMixin, unittest.TestCase): +class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase): @staticmethod def buftype(s): return s.encode("ascii") - ioclass = io._BytesIO + ioclass = pyio.BytesIO EOF = b"" def test_read1(self): @@ -371,11 +410,32 @@ self.assertEqual(memio.getvalue(), buf) -class PyStringIOTest(MemoryTestMixin, unittest.TestCase): +class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase): buftype = str - ioclass = io._StringIO + ioclass = pyio.StringIO EOF = "" + # TextIO-specific behaviour. + + def test_newlines_property(self): + memio = self.ioclass(newline=None) + # The C StringIO decodes newlines in write() calls, but the Python + # implementation only does when reading. This function forces them to + # be decoded for testing. + def force_decode(): + memio.seek(0) + memio.read() + self.assertEqual(memio.newlines, None) + memio.write("a\n") + force_decode() + self.assertEqual(memio.newlines, "\n") + memio.write("b\r\n") + force_decode() + self.assertEqual(memio.newlines, ("\n", "\r\n")) + memio.write("c\rd") + force_decode() + self.assertEqual(memio.newlines, ("\r", "\n", "\r\n")) + def test_relative_seek(self): memio = self.ioclass() @@ -386,32 +446,99 @@ self.assertRaises(IOError, memio.seek, 1, 1) self.assertRaises(IOError, memio.seek, 1, 2) + def test_textio_properties(self): + memio = self.ioclass() + + # These are just dummy values but we nevertheless check them for fear + # of unexpected breakage. + self.assertEqual(memio.encoding, "utf-8") + self.assertEqual(memio.errors, "strict") + self.assertEqual(memio.line_buffering, False) + + def test_newline_none(self): + # newline=None + memio = self.ioclass("a\nb\r\nc\rd", newline=None) + self.assertEqual(list(memio), ["a\n", "b\n", "c\n", "d"]) + memio.seek(0) + self.assertEqual(memio.read(1), "a") + self.assertEqual(memio.read(2), "\nb") + self.assertEqual(memio.read(2), "\nc") + self.assertEqual(memio.read(1), "\n") + memio = self.ioclass(newline=None) + self.assertEqual(2, memio.write("a\n")) + self.assertEqual(3, memio.write("b\r\n")) + self.assertEqual(3, memio.write("c\rd")) + memio.seek(0) + self.assertEqual(memio.read(), "a\nb\nc\nd") + memio = self.ioclass("a\r\nb", newline=None) + self.assertEqual(memio.read(3), "a\nb") + + def test_newline_empty(self): + # newline="" + memio = self.ioclass("a\nb\r\nc\rd", newline="") + self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"]) + memio.seek(0) + self.assertEqual(memio.read(4), "a\nb\r") + self.assertEqual(memio.read(2), "\nc") + self.assertEqual(memio.read(1), "\r") + memio = self.ioclass(newline="") + self.assertEqual(2, memio.write("a\n")) + self.assertEqual(2, memio.write("b\r")) + self.assertEqual(2, memio.write("\nc")) + self.assertEqual(2, memio.write("\rd")) + memio.seek(0) + self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"]) + + def test_newline_lf(self): + # newline="\n" + memio = self.ioclass("a\nb\r\nc\rd") + self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + + def test_newline_cr(self): + # newline="\r" + memio = self.ioclass("a\nb\r\nc\rd", newline="\r") + memio.seek(0) + self.assertEqual(memio.read(), "a\rb\r\rc\rd") + memio.seek(0) + self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"]) + + def test_newline_crlf(self): + # newline="\r\n" + memio = self.ioclass("a\nb\r\nc\rd", newline="\r\n") + memio.seek(0) + self.assertEqual(memio.read(), "a\r\nb\r\r\nc\rd") + memio.seek(0) + self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"]) + + def test_issue5265(self): + # StringIO can duplicate newlines in universal newlines mode + memio = self.ioclass("a\r\nb\r\n", newline=None) + self.assertEqual(memio.read(5), "a\nb\n") + + +class CBytesIOTest(PyBytesIOTest): + ioclass = io.BytesIO + +class CStringIOTest(PyStringIOTest): + ioclass = io.StringIO + # XXX: For the Python version of io.StringIO, this is highly # dependent on the encoding used for the underlying buffer. - # def test_widechar(self): - # buf = self.buftype("\U0002030a\U00020347") - # memio = self.ioclass(buf) - # - # self.assertEqual(memio.getvalue(), buf) - # self.assertEqual(memio.write(buf), len(buf)) - # self.assertEqual(memio.tell(), len(buf)) - # self.assertEqual(memio.getvalue(), buf) - # self.assertEqual(memio.write(buf), len(buf)) - # self.assertEqual(memio.tell(), len(buf) * 2) - # self.assertEqual(memio.getvalue(), buf + buf) - -if has_c_implementation: - class CBytesIOTest(PyBytesIOTest): - ioclass = io.BytesIO + def test_widechar(self): + buf = self.buftype("\U0002030a\U00020347") + memio = self.ioclass(buf) - class CStringIOTest(PyStringIOTest): - ioclass = io.StringIO + self.assertEqual(memio.getvalue(), buf) + self.assertEqual(memio.write(buf), len(buf)) + self.assertEqual(memio.tell(), len(buf)) + self.assertEqual(memio.getvalue(), buf) + self.assertEqual(memio.write(buf), len(buf)) + self.assertEqual(memio.tell(), len(buf) * 2) + self.assertEqual(memio.getvalue(), buf + buf) def test_main(): - tests = [PyBytesIOTest, PyStringIOTest] - if has_c_implementation: - tests.extend([CBytesIOTest, CStringIOTest]) + tests = [PyBytesIOTest, PyStringIOTest, CBytesIOTest, CStringIOTest] support.run_unittest(*tests) if __name__ == '__main__': Modified: python/branches/py3k/Lib/test/test_univnewlines.py ============================================================================== --- python/branches/py3k/Lib/test/test_univnewlines.py (original) +++ python/branches/py3k/Lib/test/test_univnewlines.py Wed Mar 4 01:14:51 2009 @@ -1,4 +1,6 @@ # Tests universal newline support for both reading and parsing files. +import io +import _pyio as pyio import unittest import os import sys @@ -35,7 +37,7 @@ WRITEMODE = 'wb' def setUp(self): - fp = open(support.TESTFN, self.WRITEMODE) + fp = self.open(support.TESTFN, self.WRITEMODE) data = self.DATA if "b" in self.WRITEMODE: data = data.encode("ascii") @@ -49,19 +51,19 @@ pass def test_read(self): - fp = open(support.TESTFN, self.READMODE) + fp = self.open(support.TESTFN, self.READMODE) data = fp.read() self.assertEqual(data, DATA_LF) self.assertEqual(repr(fp.newlines), repr(self.NEWLINE)) def test_readlines(self): - fp = open(support.TESTFN, self.READMODE) + fp = self.open(support.TESTFN, self.READMODE) data = fp.readlines() self.assertEqual(data, DATA_SPLIT) self.assertEqual(repr(fp.newlines), repr(self.NEWLINE)) def test_readline(self): - fp = open(support.TESTFN, self.READMODE) + fp = self.open(support.TESTFN, self.READMODE) data = [] d = fp.readline() while d: @@ -71,7 +73,7 @@ self.assertEqual(repr(fp.newlines), repr(self.NEWLINE)) def test_seek(self): - fp = open(support.TESTFN, self.READMODE) + fp = self.open(support.TESTFN, self.READMODE) fp.readline() pos = fp.tell() data = fp.readlines() @@ -94,7 +96,7 @@ DATA = DATA_CRLF def test_tell(self): - fp = open(support.TESTFN, self.READMODE) + fp = self.open(support.TESTFN, self.READMODE) self.assertEqual(repr(fp.newlines), repr(None)) data = fp.readline() pos = fp.tell() @@ -106,12 +108,22 @@ def test_main(): - support.run_unittest( - TestCRNewlines, - TestLFNewlines, - TestCRLFNewlines, - TestMixedNewlines - ) + base_tests = (TestCRNewlines, + TestLFNewlines, + TestCRLFNewlines, + TestMixedNewlines) + tests = [] + # Test the C and Python implementations. + for test in base_tests: + class CTest(test): + open = io.open + CTest.__name__ = "C" + test.__name__ + class PyTest(test): + open = staticmethod(pyio.open) + PyTest.__name__ = "Py" + test.__name__ + tests.append(CTest) + tests.append(PyTest) + support.run_unittest(*tests) if __name__ == '__main__': test_main() Modified: python/branches/py3k/Lib/test/test_uu.py ============================================================================== --- python/branches/py3k/Lib/test/test_uu.py (original) +++ python/branches/py3k/Lib/test/test_uu.py Wed Mar 4 01:14:51 2009 @@ -32,6 +32,8 @@ encoding=encoding, errors=errors, newline=newline) + self._encoding = encoding + self._errors = errors if initial_value: if not isinstance(initial_value, str): initial_value = str(initial_value) Modified: python/branches/py3k/Makefile.pre.in ============================================================================== --- python/branches/py3k/Makefile.pre.in (original) +++ python/branches/py3k/Makefile.pre.in Wed Mar 4 01:14:51 2009 @@ -193,6 +193,15 @@ # Used of signalmodule.o is not available SIGNAL_OBJS= @SIGNAL_OBJS@ +IO_H= Modules/_iomodule.h + +IO_OBJS= \ + Modules/io.o \ + Modules/_iobase.o \ + Modules/_fileio.o \ + Modules/_bufferedio.o \ + Modules/_textio.o \ + Modules/_bytesio.o ########################################################################## # Grammar @@ -521,6 +530,7 @@ Modules/python.o: $(srcdir)/Modules/python.c $(MAINCC) -c $(PY_CFLAGS) -o $@ $(srcdir)/Modules/python.c +$(IO_OBJS): $(IO_H) $(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT) -@$(INSTALL) -d Include Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Mar 4 01:14:51 2009 @@ -14,6 +14,8 @@ ======= +- The io module has been reimplemented in C for speed. + - Give dict views an informative __repr__. - Issue #5247: Improve error message when unknown format codes are Modified: python/branches/py3k/Modules/Setup.dist ============================================================================== --- python/branches/py3k/Modules/Setup.dist (original) +++ python/branches/py3k/Modules/Setup.dist Wed Mar 4 01:14:51 2009 @@ -111,10 +111,10 @@ # if $HOME is not set _sre _sre.c # Fredrik Lundh's new regular expressions _codecs _codecsmodule.c # access to the builtin codecs and codec registry -_fileio _fileio.c # Standard I/O baseline _weakref _weakref.c # weak references -_bytesio _bytesio.c # For Lib/io.py -_stringio _stringio.c # For Lib/io.py + +# Standard I/O baseline +_io io.c _iobase.c _fileio.c _bytesio.c _bufferedio.c _textio.c _stringio.c # The zipimport module is always imported at startup. Having it as a # builtin module avoids some bootstrapping problems and reduces overhead. @@ -164,7 +164,6 @@ #_collections _collectionsmodule.c # Container types #itertools itertoolsmodule.c # Functions creating iterators for efficient looping #atexit atexitmodule.c # Register functions to be run at interpreter-shutdown -#_functools _functoolsmodule.c # Tools for working with functions and callable objects #_elementtree -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI _elementtree.c # elementtree accelerator #_pickle _pickle.c # pickle accelerator #datetime datetimemodule.c # date/time type Copied: python/branches/py3k/Modules/_bufferedio.c (from r68756, /python/branches/io-c/Modules/_bufferedio.c) ============================================================================== --- /python/branches/io-c/Modules/_bufferedio.c (original) +++ python/branches/py3k/Modules/_bufferedio.c Wed Mar 4 01:14:51 2009 @@ -1,3 +1,12 @@ +/* + An implementation of Buffered I/O as defined by PEP 3116 - "New I/O" + + Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter, + BufferedRandom. + + Written by Amaury Forgeot d'Arc and Antoine Pitrou +*/ + #define PY_SSIZE_T_CLEAN #include "Python.h" #include "structmember.h" @@ -60,7 +69,7 @@ static PyObject * BufferedIOBase_unsupported(const char *message) { - PyErr_SetString(PyIOExc_UnsupportedOperation, message); + PyErr_SetString(IO_STATE->unsupported_operation, message); return NULL; } @@ -127,7 +136,7 @@ PyTypeObject PyBufferedIOBase_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "BufferedIOBase", /*tp_name*/ + "_io._BufferedIOBase", /*tp_name*/ 0, /*tp_basicsize*/ 0, /*tp_itemsize*/ 0, /*tp_dealloc*/ @@ -285,8 +294,9 @@ static void BufferedObject_dealloc(BufferedObject *self) { - if (_PyIOBase_finalize((PyObject *) self) < 0) + if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0) return; + _PyObject_GC_UNTRACK(self); self->ok = 0; if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *)self); @@ -303,6 +313,24 @@ Py_TYPE(self)->tp_free((PyObject *)self); } +static int +Buffered_traverse(BufferedObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->raw); + Py_VISIT(self->dict); + return 0; +} + +static int +Buffered_clear(BufferedObject *self) +{ + if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0) + return -1; + self->ok = 0; + Py_CLEAR(self->raw); + Py_CLEAR(self->dict); + return 0; +} /* * _BufferedIOMixin methods @@ -310,45 +338,6 @@ * by BufferedReader and BufferedWriter */ -/* Positioning */ - -static PyObject * -BufferedIOMixin_truncate(BufferedObject *self, PyObject *args) -{ - PyObject *pos = Py_None; - PyObject *res; - - CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) { - return NULL; - } - - /* Flush the stream. We're mixing buffered I/O with lower-level I/O, - * and a flush may be necessary to synch both views of the current - * file state. - */ - res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL); - if (res == NULL) - return NULL; - Py_DECREF(res); - - if (pos == Py_None) { - pos = PyObject_CallMethod(self->raw, "tell", NULL); - if (pos == NULL) - return NULL; - } - else - Py_INCREF(pos); - - /* XXX: Should seek() be used, instead of passing the position - * XXX directly to truncate? - */ - res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL); - Py_DECREF(pos); - - return res; -} - /* Flush and close */ static PyObject * @@ -715,7 +704,7 @@ all `n` bytes asked by the caller (and possibly more, so as to fill our buffer for the next reads). */ - have = READAHEAD(self); + have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); if (have > 0) { if (n > have) n = have; @@ -783,7 +772,7 @@ ENTER_BUFFERED(self) /* First, try to find a line in the buffer */ - n = READAHEAD(self); + n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); if (limit >= 0 && n > limit) n = limit; start = self->buffer + self->pos; @@ -871,7 +860,7 @@ goto end; } Py_CLEAR(res); - res = _PyBytes_Join(PyBytes_FromStringAndSize(NULL, 0), chunks); + res = _PyBytes_Join(_PyIO_empty_bytes, chunks); end: LEAVE_BUFFERED(self) @@ -987,9 +976,6 @@ return NULL; } - if (pos != Py_None) - Py_INCREF(pos); - ENTER_BUFFERED(self) if (self->writable) { @@ -1140,7 +1126,7 @@ { Py_ssize_t start, len, n; if (VALID_READ_BUFFER(self)) - start = self->read_end; + start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t); else start = 0; len = self->buffer_size - start; @@ -1167,7 +1153,7 @@ return NULL; /* First copy what we have in the current buffer. */ - current_size = READAHEAD(self); + current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); data = NULL; if (current_size) { data = PyBytes_FromStringAndSize( @@ -1236,7 +1222,7 @@ } /* The number of bytes to read is specified, return at most n bytes. */ - current_size = READAHEAD(self); + current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); if (n <= current_size) { /* Fast path: the data to read is fully buffered. */ res = PyBytes_FromStringAndSize(self->buffer + self->pos, n); @@ -1331,7 +1317,7 @@ { Py_ssize_t have, r; - have = READAHEAD(self); + have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); /* Constraints: 1. we don't want to advance the file position. 2. we don't want to lose block alignment, so we can't shift the buffer @@ -1355,7 +1341,6 @@ static PyMethodDef BufferedReader_methods[] = { /* BufferedIOMixin methods */ - {"truncate", (PyCFunction)BufferedIOMixin_truncate, METH_VARARGS}, {"flush", (PyCFunction)BufferedIOMixin_flush, METH_NOARGS}, {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS}, {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS}, @@ -1370,6 +1355,7 @@ {"readline", (PyCFunction)Buffered_readline, METH_VARARGS}, {"seek", (PyCFunction)Buffered_seek, METH_VARARGS}, {"tell", (PyCFunction)Buffered_tell, METH_NOARGS}, + {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS}, {NULL, NULL} }; @@ -1388,7 +1374,7 @@ PyTypeObject PyBufferedReader_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "BufferedReader", /*tp_name*/ + "_io.BufferedReader", /*tp_name*/ sizeof(BufferedObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)BufferedObject_dealloc, /*tp_dealloc*/ @@ -1406,12 +1392,13 @@ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ BufferedReader_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (traverseproc)Buffered_traverse, /* tp_traverse */ + (inquiry)Buffered_clear, /* tp_clear */ 0, /* tp_richcompare */ - offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/ + offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/ 0, /* tp_iter */ (iternextfunc)Buffered_iternext, /* tp_iternext */ BufferedReader_methods, /* tp_methods */ @@ -1532,7 +1519,8 @@ while (self->write_pos < self->write_end) { n = _BufferedWriter_raw_write(self, self->buffer + self->write_pos, - self->write_end - self->write_pos); + Py_SAFE_DOWNCAST(self->write_end - self->write_pos, + Py_off_t, Py_ssize_t)); if (n == -1) { Py_ssize_t *w = _Buffered_check_blocking_error(); if (w == NULL) @@ -1546,7 +1534,7 @@ } self->write_pos += n; self->raw_pos = self->write_pos; - written += n; + written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t); } if (restore_pos) { @@ -1593,7 +1581,7 @@ self->pos = 0; self->raw_pos = 0; } - avail = self->buffer_size - self->pos; + avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t); if (buf.len <= avail) { memcpy(self->buffer + self->pos, buf.buf, buf.len); if (!VALID_WRITE_BUFFER(self)) { @@ -1617,12 +1605,14 @@ /* Make some place by shifting the buffer. */ assert(VALID_WRITE_BUFFER(self)); memmove(self->buffer, self->buffer + self->write_pos, - self->write_end - self->write_pos); + Py_SAFE_DOWNCAST(self->write_end - self->write_pos, + Py_off_t, Py_ssize_t)); self->write_end -= self->write_pos; self->raw_pos -= self->write_pos; self->pos -= self->write_pos; self->write_pos = 0; - avail = self->buffer_size - self->write_end; + avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end, + Py_off_t, Py_ssize_t); if (buf.len <= avail) { /* Everything can be buffered */ PyErr_Clear(); @@ -1722,7 +1712,7 @@ PyTypeObject PyBufferedWriter_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "BufferedWriter", /*tp_name*/ + "_io.BufferedWriter", /*tp_name*/ sizeof(BufferedObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)BufferedObject_dealloc, /*tp_dealloc*/ @@ -1740,10 +1730,11 @@ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ BufferedWriter_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (traverseproc)Buffered_traverse, /* tp_traverse */ + (inquiry)Buffered_clear, /* tp_clear */ 0, /* tp_richcompare */ offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/ 0, /* tp_iter */ @@ -1789,6 +1780,7 @@ BufferedObject *reader; BufferedObject *writer; PyObject *dict; + PyObject *weakreflist; } BufferedRWPairObject; static int @@ -1835,11 +1827,30 @@ return 0; } +static int +BufferedRWPair_traverse(BufferedRWPairObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->dict); + return 0; +} + +static int +BufferedRWPair_clear(BufferedRWPairObject *self) +{ + Py_CLEAR(self->reader); + Py_CLEAR(self->writer); + Py_CLEAR(self->dict); + return 0; +} + static void BufferedRWPair_dealloc(BufferedRWPairObject *self) { + _PyObject_GC_UNTRACK(self); Py_CLEAR(self->reader); Py_CLEAR(self->writer); + Py_CLEAR(self->dict); + Py_TYPE(self)->tp_free((PyObject *) self); } static PyObject * @@ -1946,8 +1957,8 @@ PyTypeObject PyBufferedRWPair_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "BufferedRWPair", /*tp_name*/ - sizeof(BufferedRWPairObject), /*tp_basicsize*/ + "_io.BufferedRWPair", /*tp_name*/ + sizeof(BufferedRWPairObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)BufferedRWPair_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ @@ -1964,17 +1975,18 @@ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_HAVE_GC, /* tp_flags */ BufferedRWPair_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (traverseproc)BufferedRWPair_traverse, /* tp_traverse */ + (inquiry)BufferedRWPair_clear, /* tp_clear */ 0, /* tp_richcompare */ - offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/ + offsetof(BufferedRWPairObject, weakreflist), /*tp_weaklistoffset*/ 0, /* tp_iter */ 0, /* tp_iternext */ BufferedRWPair_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ + 0, /* tp_members */ + 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ @@ -2076,7 +2088,7 @@ PyTypeObject PyBufferedRandom_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "BufferedRandom", /*tp_name*/ + "_io.BufferedRandom", /*tp_name*/ sizeof(BufferedObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)BufferedObject_dealloc, /*tp_dealloc*/ @@ -2094,10 +2106,11 @@ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ BufferedRandom_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (traverseproc)Buffered_traverse, /* tp_traverse */ + (inquiry)Buffered_clear, /* tp_clear */ 0, /* tp_richcompare */ offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/ 0, /* tp_iter */ Modified: python/branches/py3k/Modules/_bytesio.c ============================================================================== --- python/branches/py3k/Modules/_bytesio.c (original) +++ python/branches/py3k/Modules/_bytesio.c Wed Mar 4 01:14:51 2009 @@ -1,4 +1,6 @@ #include "Python.h" +#include "structmember.h" /* for offsetof() */ +#include "_iomodule.h" typedef struct { PyObject_HEAD @@ -6,6 +8,8 @@ Py_ssize_t pos; Py_ssize_t string_size; size_t buf_size; + PyObject *dict; + PyObject *weakreflist; } BytesIOObject; #define CHECK_CLOSED(self) \ @@ -144,10 +148,12 @@ static PyObject * bytesio_get_closed(BytesIOObject *self) { - if (self->buf == NULL) + if (self->buf == NULL) { Py_RETURN_TRUE; - else + } + else { Py_RETURN_FALSE; + } } /* Generic getter for the writable, readable and seekable properties */ @@ -532,22 +538,22 @@ static PyObject * bytesio_write(BytesIOObject *self, PyObject *obj) { - const char *bytes; - Py_ssize_t size; Py_ssize_t n = 0; + Py_buffer buf; + PyObject *result = NULL; CHECK_CLOSED(self); - if (PyObject_AsReadBuffer(obj, (void *)&bytes, &size) < 0) + if (PyObject_GetBuffer(obj, &buf, PyBUF_CONTIG_RO) < 0) return NULL; - if (size != 0) { - n = write_bytes(self, bytes, size); - if (n < 0) - return NULL; - } + if (buf.len != 0) + n = write_bytes(self, buf.buf, buf.len); + if (n >= 0) + result = PyLong_FromSsize_t(n); - return PyLong_FromSsize_t(n); + PyBuffer_Release(&buf); + return result; } PyDoc_STRVAR(writelines_doc, @@ -607,6 +613,7 @@ PyMem_Free(self->buf); self->buf = NULL; } + Py_TYPE(self)->tp_clear((PyObject *)self); Py_TYPE(self)->tp_free(self); } @@ -656,6 +663,24 @@ return 0; } +static int +bytesio_traverse(BytesIOObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->dict); + Py_VISIT(self->weakreflist); + return 0; +} + +static int +bytesio_clear(BytesIOObject *self) +{ + Py_CLEAR(self->dict); + if (self->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *)self); + return 0; +} + + static PyGetSetDef bytesio_getsetlist[] = { {"closed", (getter)bytesio_get_closed, NULL, "True if the file is closed."}, @@ -689,9 +714,9 @@ "Create a buffered I/O implementation using an in-memory bytes\n" "buffer, ready for reading and writing."); -static PyTypeObject BytesIO_Type = { +PyTypeObject PyBytesIO_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "_bytesio._BytesIO", /*tp_name*/ + "_io.BytesIO", /*tp_name*/ sizeof(BytesIOObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)bytesio_dealloc, /*tp_dealloc*/ @@ -709,12 +734,13 @@ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC, /*tp_flags*/ bytesio_doc, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ + (traverseproc)bytesio_traverse, /*tp_traverse*/ + (inquiry)bytesio_clear, /*tp_clear*/ 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ + offsetof(BytesIOObject, weakreflist), /*tp_weaklistoffset*/ PyObject_SelfIter, /*tp_iter*/ (iternextfunc)bytesio_iternext, /*tp_iternext*/ bytesio_methods, /*tp_methods*/ @@ -724,36 +750,8 @@ 0, /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ + offsetof(BytesIOObject, dict), /*tp_dictoffset*/ (initproc)bytesio_init, /*tp_init*/ 0, /*tp_alloc*/ bytesio_new, /*tp_new*/ }; - - -static struct PyModuleDef _bytesiomodule = { - PyModuleDef_HEAD_INIT, - "_bytesio", - NULL, - -1, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__bytesio(void) -{ - PyObject *m; - - if (PyType_Ready(&BytesIO_Type) < 0) - return NULL; - m = PyModule_Create(&_bytesiomodule); - if (m == NULL) - return NULL; - Py_INCREF(&BytesIO_Type); - PyModule_AddObject(m, "_BytesIO", (PyObject *)&BytesIO_Type); - return m; -} Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Wed Mar 4 01:14:51 2009 @@ -6,6 +6,7 @@ #include #include #include /* For offsetof */ +#include "_iomodule.h" /* * Known likely problems: @@ -49,14 +50,19 @@ int seekable : 2; /* -1 means unknown */ int closefd : 1; PyObject *weakreflist; + PyObject *dict; } PyFileIOObject; PyTypeObject PyFileIO_Type; #define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type)) -static PyObject * -portable_lseek(int fd, PyObject *posobj, int whence); + +int +_PyFileIO_closed(PyObject *self) +{ + return ((PyFileIOObject *)self)->fd < 0; +} /* Returns 0 on success, -1 with exception set on failure. */ static int @@ -88,14 +94,18 @@ self->fd = -1; Py_RETURN_NONE; } - if (internal_close(self)) + errno = internal_close(self); + if (errno < 0) { + PyErr_SetFromErrno(PyExc_IOError); return NULL; + } - Py_RETURN_NONE; + return PyObject_CallMethod((PyObject*)&PyRawIOBase_Type, + "close", "O", self); } static PyObject * -fileio_new(PyTypeObject *type, PyObject *args, PyObject *kews) +fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyFileIOObject *self; @@ -119,7 +129,7 @@ directories, so we need a check. */ static int -dircheck(PyFileIOObject* self, char *name) +dircheck(PyFileIOObject* self, const char *name) { #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR) struct stat buf; @@ -146,7 +156,7 @@ { #if defined(HAVE_FSTAT) struct stat buf; - if (!_PyVerify_fd(fd) || (fstat(fd, &buf) < 0 && errno == EBADF)) { + if (fstat(fd, &buf) < 0 && errno == EBADF) { PyObject *exc; char *msg = strerror(EBADF); exc = PyObject_CallFunction(PyExc_OSError, "(is)", @@ -165,7 +175,8 @@ { PyFileIOObject *self = (PyFileIOObject *) oself; static char *kwlist[] = {"file", "mode", "closefd", NULL}; - char *name = NULL; + const char *name = NULL; + PyObject *nameobj; char *mode = "r"; char *s; #ifdef MS_WINDOWS @@ -184,42 +195,58 @@ return -1; } - if (PyArg_ParseTupleAndKeywords(args, kwds, "i|si:fileio", - kwlist, &fd, &mode, &closefd)) { - if (fd < 0) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|si:fileio", + kwlist, &nameobj, &mode, &closefd)) + return -1; + + if (PyFloat_Check(nameobj)) { + PyErr_SetString(PyExc_TypeError, + "integer argument expected, got float"); + return -1; + } + + fd = PyLong_AsLong(nameobj); + if (fd < 0) { + if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, "Negative filedescriptor"); return -1; } - if (check_fd(fd)) - return -1; - } - else { PyErr_Clear(); + } #ifdef Py_WIN_WIDE_FILENAMES - if (GetVersion() < 0x80000000) { + if (GetVersion() < 0x80000000) { /* On NT, so wide API available */ - PyObject *po; - if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:fileio", - kwlist, &po, &mode, &closefd) - ) { - widename = PyUnicode_AS_UNICODE(po); - } else { - /* Drop the argument parsing error as narrow - strings are also valid. */ - PyErr_Clear(); - } - } - if (widename == NULL) -#endif - { - if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:fileio", - kwlist, - Py_FileSystemDefaultEncoding, - &name, &mode, &closefd)) - return -1; - } + if (PyUnicode_Check(nameobj)) + widename = PyUnicode_AS_UNICODE(nameobj); + } + if (widename == NULL) +#endif + if (fd < 0) + { + if (PyBytes_Check(nameobj) || PyByteArray_Check(nameobj)) { + if (PyObject_AsCharBuffer(nameobj, &name, NULL) < 0) + return -1; + } + else { + PyObject *s; + PyObject *u = PyUnicode_FromObject(nameobj); + + if (u == NULL) + return -1; + + s = PyUnicode_AsEncodedString( + u, Py_FileSystemDefaultEncoding, NULL); + Py_DECREF(u); + if (s == NULL) + return -1; + if (!PyBytes_Check(s)) { + PyErr_SetString(PyExc_TypeError, + "encoder failed to return bytes"); + } + name = PyBytes_AS_STRING(s); + } } s = mode; @@ -287,6 +314,8 @@ if (fd >= 0) { self->fd = fd; self->closefd = closefd; + if (check_fd(fd)) + goto error; } else { self->closefd = 1; @@ -318,15 +347,8 @@ goto error; } - if (append) { - /* For consistent behaviour, we explicitly seek to the - end of file (otherwise, it might be done only on the - first write()). */ - PyObject *pos = portable_lseek(self->fd, NULL, 2); - if (pos == NULL) - goto error; - Py_DECREF(pos); - } + if (PyObject_SetAttrString((PyObject *)self, "name", nameobj) < 0) + goto error; goto done; @@ -334,21 +356,32 @@ ret = -1; done: - PyMem_Free(name); return ret; } +static int +fileio_traverse(PyFileIOObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->dict); + return 0; +} + +static int +fileio_clear(PyFileIOObject *self) +{ + Py_CLEAR(self->dict); + return 0; +} + static void fileio_dealloc(PyFileIOObject *self) { + if (_PyIOBase_finalize((PyObject *) self) < 0) + return; + _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); - - if (self->fd >= 0 && self->closefd) { - if(internal_close(self)) - PyErr_WriteUnraisable((PyObject*)self); - } - + Py_CLEAR(self->dict); Py_TYPE(self)->tp_free((PyObject *)self); } @@ -437,6 +470,31 @@ return PyLong_FromSsize_t(n); } +static size_t +new_buffersize(PyFileIOObject *self, size_t currentsize) +{ +#ifdef HAVE_FSTAT + off_t pos, end; + struct stat st; + if (fstat(self->fd, &st) == 0) { + end = st.st_size; + pos = lseek(self->fd, 0L, SEEK_CUR); + if (end >= pos && pos >= 0) + return currentsize + end - pos + 1; + /* Add 1 so if the file were to grow we'd notice. */ + } +#endif + if (currentsize > SMALLCHUNK) { + /* Keep doubling until we reach BIGCHUNK; + then keep adding BIGCHUNK. */ + if (currentsize <= BIGCHUNK) + return currentsize + currentsize; + else + return currentsize + BIGCHUNK; + } + return currentsize + SMALLCHUNK; +} + static PyObject * fileio_readall(PyFileIOObject *self) { @@ -449,17 +507,7 @@ return NULL; while (1) { - Py_ssize_t newsize = (total < SMALLCHUNK) ? SMALLCHUNK : total; - - /* Keep doubling until we reach BIGCHUNK; - then keep adding BIGCHUNK. */ - if (newsize <= BIGCHUNK) { - newsize += newsize; - } - else { - /* NOTE: overflow impossible due to limits on BUFSIZ */ - newsize += BIGCHUNK; - } + Py_ssize_t newsize = new_buffersize(self, total); if (PyBytes_GET_SIZE(result) < newsize) { if (_PyBytes_Resize(&result, newsize) < 0) { @@ -583,12 +631,6 @@ /* XXX Windows support below is likely incomplete */ -#if defined(MS_WIN64) || defined(MS_WINDOWS) -typedef PY_LONG_LONG Py_off_t; -#else -typedef off_t Py_off_t; -#endif - /* Cribbed from posix_lseek() */ static PyObject * portable_lseek(int fd, PyObject *posobj, int whence) @@ -755,9 +797,9 @@ fileio_repr(PyFileIOObject *self) { if (self->fd < 0) - return PyUnicode_FromFormat("_fileio._FileIO(-1)"); + return PyUnicode_FromFormat("io.FileIO(-1)"); - return PyUnicode_FromFormat("_fileio._FileIO(%d, '%s')", + return PyUnicode_FromFormat("io.FileIO(%d, '%s')", self->fd, mode_string(self)); } @@ -899,15 +941,15 @@ }; PyTypeObject PyFileIO_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "_FileIO", + PyVarObject_HEAD_INIT(NULL, 0) + "FileIO", sizeof(PyFileIOObject), 0, (destructor)fileio_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_reserved */ + 0, /* tp_compare */ (reprfunc)fileio_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -918,10 +960,11 @@ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_HAVE_GC, /* tp_flags */ fileio_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (traverseproc)fileio_traverse, /* tp_traverse */ + (inquiry)fileio_clear, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyFileIOObject, weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ @@ -933,40 +976,9 @@ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ + offsetof(PyFileIOObject, dict), /* tp_dictoffset */ fileio_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ fileio_new, /* tp_new */ - PyObject_Del, /* tp_free */ -}; - -static PyMethodDef module_methods[] = { - {NULL, NULL} -}; - -static struct PyModuleDef fileiomodule = { - PyModuleDef_HEAD_INIT, - "_fileio", - "Fast implementation of io.FileIO.", - -1, - module_methods, - NULL, - NULL, - NULL, - NULL + PyObject_GC_Del, /* tp_free */ }; - -PyMODINIT_FUNC -PyInit__fileio(void) -{ - PyObject *m; /* a module object */ - - m = PyModule_Create(&fileiomodule); - if (m == NULL) - return NULL; - if (PyType_Ready(&PyFileIO_Type) < 0) - return NULL; - Py_INCREF(&PyFileIO_Type); - PyModule_AddObject(m, "_FileIO", (PyObject *) &PyFileIO_Type); - return m; -} Copied: python/branches/py3k/Modules/_iobase.c (from r68756, /python/branches/io-c/Modules/_iobase.c) ============================================================================== --- /python/branches/io-c/Modules/_iobase.c (original) +++ python/branches/py3k/Modules/_iobase.c Wed Mar 4 01:14:51 2009 @@ -1,3 +1,13 @@ +/* + An implementation of the I/O abstract base classes hierarchy + as defined by PEP 3116 - "New I/O" + + Classes defined here: IOBase, RawIOBase. + + Written by Amaury Forgeot d'Arc and Antoine Pitrou +*/ + + #define PY_SSIZE_T_CLEAN #include "Python.h" #include "structmember.h" @@ -7,6 +17,13 @@ * IOBase class, an abstract class */ +typedef struct { + PyObject_HEAD + + PyObject *dict; + PyObject *weakreflist; +} IOBaseObject; + PyDoc_STRVAR(IOBase_doc, "The abstract base class for all I/O classes, acting on streams of\n" "bytes. There is no public constructor.\n" @@ -48,7 +65,7 @@ static PyObject * IOBase_unsupported(const char *message) { - PyErr_SetString(PyIOExc_UnsupportedOperation, message); + PyErr_SetString(IO_STATE->unsupported_operation, message); return NULL; } @@ -91,7 +108,7 @@ static PyObject * IOBase_truncate(PyObject *self, PyObject *args) { - return IOBase_unsupported("seek"); + return IOBase_unsupported("truncate"); } /* Flush and close methods */ @@ -176,7 +193,7 @@ Py_RETURN_NONE; } -/* Destructor */ +/* Finalization and garbage collection support */ int _PyIOBase_finalize(PyObject *self) @@ -184,12 +201,17 @@ PyObject *res; PyObject *tp, *v, *tb; int closed = 1; + int is_zombie; + + /* If _PyIOBase_finalize() is called from a destructor, we need to + resurrect the object as calling close() can invoke arbitrary code. */ + is_zombie = (Py_REFCNT(self) == 0); + if (is_zombie) { + ++Py_REFCNT(self); + } PyErr_Fetch(&tp, &v, &tb); - /* We need to resurrect the object as calling close() can invoke - arbitrary code. */ - ((PyObject *) self)->ob_refcnt++; - /* The object could already be in an usable state, so we'll take any - error as meaning "stop, nothing to see here". */ + /* If `closed` doesn't exist or can't be evaluated as bool, then the + object is probably in an unusable state, so ignore. */ res = PyObject_GetAttr(self, _PyIO_str_closed); if (res == NULL) PyErr_Clear(); @@ -202,22 +224,79 @@ if (closed == 0) { res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_close, NULL); + /* Silencing I/O errors is bad, but printing spurious tracebacks is + equally as bad, and potentially more frequent (because of + shutdown issues). */ if (res == NULL) PyErr_Clear(); else Py_DECREF(res); } PyErr_Restore(tp, v, tb); - if (--((PyObject *) self)->ob_refcnt != 0) + if (is_zombie) { + if (--Py_REFCNT(self) != 0) { + /* The object lives again. The following code is taken from + slot_tp_del in typeobject.c. */ + Py_ssize_t refcnt = Py_REFCNT(self); + _Py_NewReference(self); + Py_REFCNT(self) = refcnt; + /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so + * we need to undo that. */ + _Py_DEC_REFTOTAL; + /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object + * chain, so no more to do there. + * If COUNT_ALLOCS, the original decref bumped tp_frees, and + * _Py_NewReference bumped tp_allocs: both of those need to be + * undone. + */ +#ifdef COUNT_ALLOCS + --Py_TYPE(self)->tp_frees; + --Py_TYPE(self)->tp_allocs; +#endif + return -1; + } + } + return 0; +} + +static int +IOBase_traverse(IOBaseObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->dict); + return 0; +} + +static int +IOBase_clear(IOBaseObject *self) +{ + if (_PyIOBase_finalize((PyObject *) self) < 0) return -1; + Py_CLEAR(self->dict); return 0; } +/* Destructor */ + static void -IOBase_dealloc(PyObject *self) +IOBase_dealloc(IOBaseObject *self) { - if (_PyIOBase_finalize(self) == 0) - Py_TYPE(self)->tp_free(self); + /* NOTE: since IOBaseObject has its own dict, Python-defined attributes + are still available here for close() to use. + However, if the derived class declares a __slots__, those slots are + already gone. + */ + if (_PyIOBase_finalize((PyObject *) self) < 0) { + /* When called from a heap type's dealloc, the type will be + decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */ + if (PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) + Py_INCREF(Py_TYPE(self)); + return; + } + _PyObject_GC_UNTRACK(self); + if (self->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) self); + Py_CLEAR(self->dict); + Py_TYPE(self)->tp_free((PyObject *) self); } /* Inquiry methods */ @@ -517,8 +596,11 @@ return NULL; if (hint <= 0) { + /* XXX special-casing this made sense in the Python version in order + to remove the bytecode interpretation overhead, but it could + probably be removed here. */ PyObject *ret = PyObject_CallMethod(result, "extend", "O", self); - if( ret == NULL) { + if (ret == NULL) { Py_DECREF(result); return NULL; } @@ -534,7 +616,7 @@ return NULL; } else - break; /* SopIteration raised */ + break; /* StopIteration raised */ } if (PyList_Append(result, line) < 0) { @@ -569,7 +651,7 @@ while (1) { PyObject *line = PyIter_Next(iter); - if(line == NULL) { + if (line == NULL) { if (PyErr_Occurred()) { Py_DECREF(iter); return NULL; @@ -586,6 +668,7 @@ } Py_DECREF(res); } + Py_DECREF(iter); Py_RETURN_NONE; } @@ -626,10 +709,10 @@ PyTypeObject PyIOBase_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "IOBase", /*tp_name*/ - 0, /*tp_basicsize*/ + "_io._IOBase", /*tp_name*/ + sizeof(IOBaseObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ - IOBase_dealloc, /*tp_dealloc*/ + (destructor)IOBase_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ @@ -644,12 +727,13 @@ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ IOBase_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (traverseproc)IOBase_traverse, /* tp_traverse */ + (inquiry)IOBase_clear, /* tp_clear */ 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + offsetof(IOBaseObject, weakreflist), /* tp_weaklistoffset */ IOBase_iter, /* tp_iter */ IOBase_iternext, /* tp_iternext */ IOBase_methods, /* tp_methods */ @@ -659,21 +743,12 @@ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ + offsetof(IOBaseObject, dict), /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ }; - /* * RawIOBase class, Inherits from IOBase. @@ -790,7 +865,7 @@ PyTypeObject PyRawIOBase_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "RawIOBase", /*tp_name*/ + "_io._RawIOBase", /*tp_name*/ 0, /*tp_basicsize*/ 0, /*tp_itemsize*/ 0, /*tp_dealloc*/ Copied: python/branches/py3k/Modules/_iomodule.h (from r68756, /python/branches/io-c/Modules/_iomodule.h) ============================================================================== --- /python/branches/io-c/Modules/_iomodule.h (original) +++ python/branches/py3k/Modules/_iomodule.h Wed Mar 4 01:14:51 2009 @@ -2,11 +2,16 @@ * Declarations shared between the different parts of the io module */ -extern PyTypeObject PyFileIO_Type; -extern PyTypeObject PyBytesIO_Type; +/* ABCs */ extern PyTypeObject PyIOBase_Type; extern PyTypeObject PyRawIOBase_Type; extern PyTypeObject PyBufferedIOBase_Type; +extern PyTypeObject PyTextIOBase_Type; + +/* Concrete classes */ +extern PyTypeObject PyFileIO_Type; +extern PyTypeObject PyBytesIO_Type; +extern PyTypeObject PyStringIO_Type; extern PyTypeObject PyBufferedReader_Type; extern PyTypeObject PyBufferedWriter_Type; extern PyTypeObject PyBufferedRWPair_Type; @@ -23,14 +28,33 @@ extern PyObject* _PyIOBase_checkSeekable(PyObject *self, PyObject *args); extern PyObject* _PyIOBase_checkClosed(PyObject *self, PyObject *args); -extern PyObject* PyIOExc_UnsupportedOperation; - /* Helper for finalization. This function will revive an object ready to be deallocated and try to close() it. It returns 0 if the object can be destroyed, or -1 if it is alive again. */ extern int _PyIOBase_finalize(PyObject *self); +/* Returns true if the given FileIO object is closed. + Doesn't check the argument type, so be careful! */ +extern int _PyFileIO_closed(PyObject *self); + +/* Shortcut to the core of the IncrementalNewlineDecoder.decode method */ +extern PyObject *_PyIncrementalNewlineDecoder_decode( + PyObject *self, PyObject *input, int final); + +/* Finds the first line ending between `start` and `end`. + If found, returns the index after the line ending and doesn't touch + `*consumed`. + If not found, returns -1 and sets `*consumed` to the number of characters + which can be safely put aside until another search. + + NOTE: for performance reasons, `end` must point to a NUL character ('\0'). + Otherwise, the function will scan further and return garbage. */ +extern Py_ssize_t _PyIO_find_line_ending( + int translated, int universal, PyObject *readnl, + Py_UNICODE *start, Py_UNICODE *end, Py_ssize_t *consumed); + + #define DEFAULT_BUFFER_SIZE (8 * 1024) /* bytes */ typedef struct { @@ -84,6 +108,21 @@ /* Implementation details */ +/* IO module structure */ + +extern PyModuleDef _PyIO_Module; + +typedef struct { + int initialized; + PyObject *os_module; + PyObject *locale_module; + + PyObject *unsupported_operation; +} _PyIO_State; + +#define IO_MOD_STATE(mod) ((_PyIO_State *)PyModule_GetState(mod)) +#define IO_STATE IO_MOD_STATE(PyState_FindModule(&_PyIO_Module)) + extern PyObject *_PyIO_str_close; extern PyObject *_PyIO_str_closed; extern PyObject *_PyIO_str_decode; @@ -93,14 +132,19 @@ extern PyObject *_PyIO_str_getstate; extern PyObject *_PyIO_str_isatty; extern PyObject *_PyIO_str_newlines; +extern PyObject *_PyIO_str_nl; extern PyObject *_PyIO_str_read; extern PyObject *_PyIO_str_read1; extern PyObject *_PyIO_str_readable; extern PyObject *_PyIO_str_readinto; extern PyObject *_PyIO_str_readline; +extern PyObject *_PyIO_str_reset; extern PyObject *_PyIO_str_seek; extern PyObject *_PyIO_str_seekable; extern PyObject *_PyIO_str_tell; extern PyObject *_PyIO_str_truncate; extern PyObject *_PyIO_str_writable; extern PyObject *_PyIO_str_write; + +extern PyObject *_PyIO_empty_str; +extern PyObject *_PyIO_empty_bytes; Modified: python/branches/py3k/Modules/_stringio.c ============================================================================== --- python/branches/py3k/Modules/_stringio.c (original) +++ python/branches/py3k/Modules/_stringio.c Wed Mar 4 01:14:51 2009 @@ -1,8 +1,11 @@ +#define PY_SSIZE_T_CLEAN #include "Python.h" +#include "structmember.h" +#include "_iomodule.h" -/* This module is a stripped down version of _bytesio.c with a Py_UNICODE - buffer. Most of the functionality is provided by subclassing _StringIO. */ - +/* Implementation note: the buffer is always at least one character longer + than the enclosed string, for proper functioning of _PyIO_find_line_ending. +*/ typedef struct { PyObject_HEAD @@ -10,8 +13,39 @@ Py_ssize_t pos; Py_ssize_t string_size; size_t buf_size; + + char ok; /* initialized? */ + char closed; + char readuniversal; + char readtranslate; + PyObject *decoder; + PyObject *readnl; + PyObject *writenl; + + PyObject *dict; + PyObject *weakreflist; } StringIOObject; +#define CHECK_INITIALIZED(self) \ + if (self->ok <= 0) { \ + PyErr_SetString(PyExc_ValueError, \ + "I/O operation on uninitialized object"); \ + return NULL; \ + } + +#define CHECK_CLOSED(self) \ + if (self->closed) { \ + PyErr_SetString(PyExc_ValueError, \ + "I/O operation on closed file"); \ + return NULL; \ + } + +PyDoc_STRVAR(stringio_doc, + "Text I/O implementation using an in-memory buffer.\n" + "\n" + "The initial_value argument sets the value of object. The newline\n" + "argument is like the one of TextIOWrapper's constructor."); + /* Internal routine for changing the size, in terms of characters, of the buffer of StringIO objects. The caller should ensure that the 'size' @@ -26,6 +60,8 @@ assert(self->buf != NULL); + /* Reserve one more char for line ending detection. */ + size = size + 1; /* For simplicity, stay in the range of the signed type. Anyway, Python doesn't allow strings to be longer than this. */ if (size > PY_SSIZE_T_MAX) @@ -67,13 +103,38 @@ return -1; } -/* Internal routine for writing a string of characters to the buffer of a - StringIO object. Returns the number of bytes wrote, or -1 on error. */ +/* Internal routine for writing a whole PyUnicode object to the buffer of a + StringIO object. Returns 0 on success, or -1 on error. */ static Py_ssize_t -write_str(StringIOObject *self, const Py_UNICODE *str, Py_ssize_t len) +write_str(StringIOObject *self, PyObject *obj) { + Py_UNICODE *str; + Py_ssize_t len; + PyObject *decoded = NULL; assert(self->buf != NULL); assert(self->pos >= 0); + + if (self->decoder != NULL) { + decoded = _PyIncrementalNewlineDecoder_decode( + self->decoder, obj, 1 /* always final */); + } + else { + decoded = obj; + Py_INCREF(decoded); + } + if (self->writenl) { + PyObject *translated = PyUnicode_Replace( + decoded, _PyIO_str_nl, self->writenl, -1); + Py_DECREF(decoded); + decoded = translated; + } + if (decoded == NULL) + return -1; + + assert(PyUnicode_Check(decoded)); + str = PyUnicode_AS_UNICODE(decoded); + len = PyUnicode_GET_SIZE(decoded); + assert(len >= 0); /* This overflow check is not strictly necessary. However, it avoids us to @@ -82,11 +143,11 @@ if (self->pos > PY_SSIZE_T_MAX - len) { PyErr_SetString(PyExc_OverflowError, "new position too large"); - return -1; + goto fail; } if (self->pos + len > self->string_size) { if (resize_buffer(self, self->pos + len) < 0) - return -1; + goto fail; } if (self->pos > self->string_size) { @@ -108,26 +169,47 @@ memcpy(self->buf + self->pos, str, len * sizeof(Py_UNICODE)); self->pos += len; - /* Set the new length of the internal string if it has changed */ + /* Set the new length of the internal string if it has changed. */ if (self->string_size < self->pos) { self->string_size = self->pos; } - return len; + Py_DECREF(decoded); + return 0; + +fail: + Py_XDECREF(decoded); + return -1; } +PyDoc_STRVAR(stringio_getvalue_doc, + "Retrieve the entire contents of the object."); + static PyObject * stringio_getvalue(StringIOObject *self) { + CHECK_INITIALIZED(self); + CHECK_CLOSED(self); return PyUnicode_FromUnicode(self->buf, self->string_size); } +PyDoc_STRVAR(stringio_tell_doc, + "Tell the current file position."); + static PyObject * stringio_tell(StringIOObject *self) { + CHECK_INITIALIZED(self); + CHECK_CLOSED(self); return PyLong_FromSsize_t(self->pos); } +PyDoc_STRVAR(stringio_read_doc, + "Read at most n characters, returned as a string.\n" + "\n" + "If the argument is negative or omitted, read until EOF\n" + "is reached. Return an empty string at EOF.\n"); + static PyObject * stringio_read(StringIOObject *self, PyObject *args) { @@ -135,11 +217,13 @@ Py_UNICODE *output; PyObject *arg = Py_None; + CHECK_INITIALIZED(self); if (!PyArg_ParseTuple(args, "|O:read", &arg)) return NULL; + CHECK_CLOSED(self); - if (PyLong_Check(arg)) { - size = PyLong_AsSsize_t(arg); + if (PyNumber_Check(arg)) { + size = PyNumber_AsSsize_t(arg, PyExc_OverflowError); if (size == -1 && PyErr_Occurred()) return NULL; } @@ -161,24 +245,127 @@ size = 0; } - assert(self->buf != NULL); output = self->buf + self->pos; self->pos += size; - return PyUnicode_FromUnicode(output, size); } +/* Internal helper, used by stringio_readline and stringio_iternext */ +static PyObject * +_stringio_readline(StringIOObject *self, Py_ssize_t limit) +{ + Py_UNICODE *start, *end, old_char; + Py_ssize_t len, consumed; + + /* In case of overseek, return the empty string */ + if (self->pos >= self->string_size) + return PyUnicode_FromString(""); + + start = self->buf + self->pos; + if (limit < 0 || limit > self->string_size - self->pos) + limit = self->string_size - self->pos; + + end = start + limit; + old_char = *end; + *end = '\0'; + len = _PyIO_find_line_ending( + self->readtranslate, self->readuniversal, self->readnl, + start, end, &consumed); + *end = old_char; + /* If we haven't found any line ending, we just return everything + (`consumed` is ignored). */ + if (len < 0) + len = limit; + self->pos += len; + return PyUnicode_FromUnicode(start, len); +} + +PyDoc_STRVAR(stringio_readline_doc, + "Read until newline or EOF.\n" + "\n" + "Returns an empty string if EOF is hit immediately.\n"); + +static PyObject * +stringio_readline(StringIOObject *self, PyObject *args) +{ + PyObject *arg = Py_None; + Py_ssize_t limit = -1; + + CHECK_INITIALIZED(self); + if (!PyArg_ParseTuple(args, "|O:readline", &arg)) + return NULL; + CHECK_CLOSED(self); + + if (PyNumber_Check(arg)) { + limit = PyNumber_AsSsize_t(arg, PyExc_OverflowError); + if (limit == -1 && PyErr_Occurred()) + return NULL; + } + else if (arg != Py_None) { + PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'", + Py_TYPE(arg)->tp_name); + return NULL; + } + return _stringio_readline(self, limit); +} + +static PyObject * +stringio_iternext(StringIOObject *self) +{ + PyObject *line; + + CHECK_INITIALIZED(self); + CHECK_CLOSED(self); + + if (Py_TYPE(self) == &PyStringIO_Type) { + /* Skip method call overhead for speed */ + line = _stringio_readline(self, -1); + } + else { + /* XXX is subclassing StringIO really supported? */ + line = PyObject_CallMethodObjArgs((PyObject *)self, + _PyIO_str_readline, NULL); + if (line && !PyUnicode_Check(line)) { + PyErr_Format(PyExc_IOError, + "readline() should have returned an str object, " + "not '%.200s'", Py_TYPE(line)->tp_name); + Py_DECREF(line); + return NULL; + } + } + + if (line == NULL) + return NULL; + + if (PyUnicode_GET_SIZE(line) == 0) { + /* Reached EOF */ + Py_DECREF(line); + return NULL; + } + + return line; +} + +PyDoc_STRVAR(stringio_truncate_doc, + "Truncate size to pos.\n" + "\n" + "The pos argument defaults to the current file position, as\n" + "returned by tell(). Imply an absolute seek to pos.\n" + "Returns the new absolute position.\n"); + static PyObject * stringio_truncate(StringIOObject *self, PyObject *args) { Py_ssize_t size; PyObject *arg = Py_None; + CHECK_INITIALIZED(self); if (!PyArg_ParseTuple(args, "|O:truncate", &arg)) return NULL; + CHECK_CLOSED(self); - if (PyLong_Check(arg)) { - size = PyLong_AsSsize_t(arg); + if (PyNumber_Check(arg)) { + size = PyNumber_AsSsize_t(arg, PyExc_OverflowError); if (size == -1 && PyErr_Occurred()) return NULL; } @@ -199,23 +386,34 @@ } if (size < self->string_size) { - self->string_size = size; if (resize_buffer(self, size) < 0) return NULL; + self->string_size = size; } self->pos = size; return PyLong_FromSsize_t(size); } +PyDoc_STRVAR(stringio_seek_doc, + "Change stream position.\n" + "\n" + "Seek to character offset pos relative to position indicated by whence:\n" + " 0 Start of stream (the default). pos should be >= 0;\n" + " 1 Current position - pos must be 0;\n" + " 2 End of stream - pos must be 0.\n" + "Returns the new absolute position.\n"); + static PyObject * stringio_seek(StringIOObject *self, PyObject *args) { Py_ssize_t pos; int mode = 0; + CHECK_INITIALIZED(self); if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &mode)) return NULL; + CHECK_CLOSED(self); if (mode != 0 && mode != 1 && mode != 2) { PyErr_Format(PyExc_ValueError, @@ -248,36 +446,76 @@ return PyLong_FromSsize_t(self->pos); } +PyDoc_STRVAR(stringio_write_doc, + "Write string to file.\n" + "\n" + "Returns the number of characters written, which is always equal to\n" + "the length of the string.\n"); + static PyObject * stringio_write(StringIOObject *self, PyObject *obj) { - const Py_UNICODE *str; Py_ssize_t size; - Py_ssize_t n = 0; - if (PyUnicode_Check(obj)) { - str = PyUnicode_AsUnicode(obj); - size = PyUnicode_GetSize(obj); - } - else { + CHECK_INITIALIZED(self); + if (!PyUnicode_Check(obj)) { PyErr_Format(PyExc_TypeError, "string argument expected, got '%s'", Py_TYPE(obj)->tp_name); return NULL; } + CHECK_CLOSED(self); + size = PyUnicode_GET_SIZE(obj); - if (size != 0) { - n = write_str(self, str, size); - if (n < 0) - return NULL; - } + if (size > 0 && write_str(self, obj) < 0) + return NULL; + + return PyLong_FromSsize_t(size); +} - return PyLong_FromSsize_t(n); +PyDoc_STRVAR(stringio_close_doc, + "Close the IO object. Attempting any further operation after the\n" + "object is closed will raise a ValueError.\n" + "\n" + "This method has no effect if the file is already closed.\n"); + +static PyObject * +stringio_close(StringIOObject *self) +{ + self->closed = 1; + /* Free up some memory */ + if (resize_buffer(self, 0) < 0) + return NULL; + Py_CLEAR(self->readnl); + Py_CLEAR(self->writenl); + Py_CLEAR(self->decoder); + Py_RETURN_NONE; +} + +static int +stringio_traverse(StringIOObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->dict); + return 0; +} + +static int +stringio_clear(StringIOObject *self) +{ + Py_CLEAR(self->dict); + return 0; } static void stringio_dealloc(StringIOObject *self) { - PyMem_Free(self->buf); + _PyObject_GC_UNTRACK(self); + Py_CLEAR(self->readnl); + Py_CLEAR(self->writenl); + Py_CLEAR(self->decoder); + if (self->buf) + PyMem_Free(self->buf); + if (self->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) self); Py_TYPE(self)->tp_free(self); } @@ -303,19 +541,194 @@ return (PyObject *)self; } +static int +stringio_init(StringIOObject *self, PyObject *args, PyObject *kwds) +{ + char *kwlist[] = {"initial_value", "newline", NULL}; + PyObject *value = NULL; + char *newline = "\n"; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oz:__init__", kwlist, + &value, &newline)) + return -1; + + if (newline && newline[0] != '\0' + && !(newline[0] == '\n' && newline[1] == '\0') + && !(newline[0] == '\r' && newline[1] == '\0') + && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) { + PyErr_Format(PyExc_ValueError, + "illegal newline value: %s", newline); + return -1; + } + if (value && value != Py_None && !PyUnicode_Check(value)) { + PyErr_Format(PyExc_ValueError, + "initial_value must be str or None, not %.200s", + Py_TYPE(value)->tp_name); + return -1; + } + + self->ok = 0; + + Py_CLEAR(self->readnl); + Py_CLEAR(self->writenl); + Py_CLEAR(self->decoder); + + if (newline) { + self->readnl = PyUnicode_FromString(newline); + if (self->readnl == NULL) + return -1; + } + self->readuniversal = (newline == NULL || newline[0] == '\0'); + self->readtranslate = (newline == NULL); + /* If newline == "", we don't translate anything. + If newline == "\n" or newline == None, we translate to "\n", which is + a no-op. + (for newline == None, TextIOWrapper translates to os.sepline, but it + is pointless for StringIO) + */ + if (newline != NULL && newline[0] == '\r') { + self->writenl = self->readnl; + Py_INCREF(self->writenl); + } + + if (self->readuniversal) { + self->decoder = PyObject_CallFunction( + (PyObject *)&PyIncrementalNewlineDecoder_Type, + "Oi", Py_None, (int) self->readtranslate); + if (self->decoder == NULL) + return -1; + } + + /* Now everything is set up, resize buffer to size of initial value, + and copy it */ + self->string_size = 0; + if (value && value != Py_None) { + Py_ssize_t len = PyUnicode_GetSize(value); + /* This is a heuristic, for newline translation might change + the string length. */ + if (resize_buffer(self, len) < 0) + return -1; + self->pos = 0; + if (write_str(self, value) < 0) + return -1; + } + else { + if (resize_buffer(self, 0) < 0) + return -1; + } + self->pos = 0; + + self->closed = 0; + self->ok = 1; + return 0; +} + +/* Properties and pseudo-properties */ +static PyObject * +stringio_seekable(StringIOObject *self, PyObject *args) +{ + CHECK_INITIALIZED(self); + Py_RETURN_TRUE; +} + +static PyObject * +stringio_readable(StringIOObject *self, PyObject *args) +{ + CHECK_INITIALIZED(self); + Py_RETURN_TRUE; +} + +static PyObject * +stringio_writable(StringIOObject *self, PyObject *args) +{ + CHECK_INITIALIZED(self); + Py_RETURN_TRUE; +} + +static PyObject * +stringio_buffer(StringIOObject *self, void *context) +{ + PyErr_SetString(IO_STATE->unsupported_operation, + "buffer attribute is unsupported on type StringIO"); + return NULL; +} + +static PyObject * +stringio_closed(StringIOObject *self, void *context) +{ + CHECK_INITIALIZED(self); + return PyBool_FromLong(self->closed); +} + +static PyObject * +stringio_encoding(StringIOObject *self, void *context) +{ + CHECK_INITIALIZED(self); + CHECK_CLOSED(self); + return PyUnicode_FromString("utf-8"); +} + +static PyObject * +stringio_errors(StringIOObject *self, void *context) +{ + CHECK_INITIALIZED(self); + CHECK_CLOSED(self); + return PyUnicode_FromString("strict"); +} + +static PyObject * +stringio_line_buffering(StringIOObject *self, void *context) +{ + CHECK_INITIALIZED(self); + CHECK_CLOSED(self); + Py_RETURN_FALSE; +} + +static PyObject * +stringio_newlines(StringIOObject *self, void *context) +{ + CHECK_INITIALIZED(self); + CHECK_CLOSED(self); + if (self->decoder == NULL) + Py_RETURN_NONE; + return PyObject_GetAttr(self->decoder, _PyIO_str_newlines); +} + static struct PyMethodDef stringio_methods[] = { - {"getvalue", (PyCFunction)stringio_getvalue, METH_VARARGS, NULL}, - {"read", (PyCFunction)stringio_read, METH_VARARGS, NULL}, - {"tell", (PyCFunction)stringio_tell, METH_NOARGS, NULL}, - {"truncate", (PyCFunction)stringio_truncate, METH_VARARGS, NULL}, - {"seek", (PyCFunction)stringio_seek, METH_VARARGS, NULL}, - {"write", (PyCFunction)stringio_write, METH_O, NULL}, + {"close", (PyCFunction)stringio_close, METH_NOARGS, stringio_close_doc}, + {"getvalue", (PyCFunction)stringio_getvalue, METH_VARARGS, stringio_getvalue_doc}, + {"read", (PyCFunction)stringio_read, METH_VARARGS, stringio_read_doc}, + {"readline", (PyCFunction)stringio_readline, METH_VARARGS, stringio_readline_doc}, + {"tell", (PyCFunction)stringio_tell, METH_NOARGS, stringio_tell_doc}, + {"truncate", (PyCFunction)stringio_truncate, METH_VARARGS, stringio_truncate_doc}, + {"seek", (PyCFunction)stringio_seek, METH_VARARGS, stringio_seek_doc}, + {"write", (PyCFunction)stringio_write, METH_O, stringio_write_doc}, + + {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS}, + {"readable", (PyCFunction)stringio_readable, METH_NOARGS}, + {"writable", (PyCFunction)stringio_writable, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; -static PyTypeObject StringIO_Type = { +static PyGetSetDef stringio_getset[] = { + {"closed", (getter)stringio_closed, NULL, NULL}, + {"newlines", (getter)stringio_newlines, NULL, NULL}, + /* (following comments straight off of the original Python wrapper:) + XXX Cruft to support the TextIOWrapper API. This would only + be meaningful if StringIO supported the buffer attribute. + Hopefully, a better solution, than adding these pseudo-attributes, + will be found. + */ + {"buffer", (getter)stringio_buffer, NULL, NULL}, + {"encoding", (getter)stringio_encoding, NULL, NULL}, + {"errors", (getter)stringio_errors, NULL, NULL}, + {"line_buffering", (getter)stringio_line_buffering, NULL, NULL}, + {0} +}; + +PyTypeObject PyStringIO_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "_stringio._StringIO", /*tp_name*/ + "_io.StringIO", /*tp_name*/ sizeof(StringIOObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)stringio_dealloc, /*tp_dealloc*/ @@ -333,51 +746,24 @@ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + stringio_doc, /*tp_doc*/ + (traverseproc)stringio_traverse, /*tp_traverse*/ + (inquiry)stringio_clear, /*tp_clear*/ 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ + offsetof(StringIOObject, weakreflist), /*tp_weaklistoffset*/ 0, /*tp_iter*/ - 0, /*tp_iternext*/ + (iternextfunc)stringio_iternext, /*tp_iternext*/ stringio_methods, /*tp_methods*/ 0, /*tp_members*/ - 0, /*tp_getset*/ + stringio_getset, /*tp_getset*/ 0, /*tp_base*/ 0, /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ + offsetof(StringIOObject, dict), /*tp_dictoffset*/ + (initproc)stringio_init, /*tp_init*/ 0, /*tp_alloc*/ stringio_new, /*tp_new*/ }; - -static struct PyModuleDef _stringiomodule = { - PyModuleDef_HEAD_INIT, - "_stringio", - NULL, - -1, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__stringio(void) -{ - PyObject *m; - - if (PyType_Ready(&StringIO_Type) < 0) - return NULL; - m = PyModule_Create(&_stringiomodule); - if (m == NULL) - return NULL; - Py_INCREF(&StringIO_Type); - if (PyModule_AddObject(m, "_StringIO", (PyObject *)&StringIO_Type) < 0) - return NULL; - return m; -} Copied: python/branches/py3k/Modules/_textio.c (from r68756, /python/branches/io-c/Modules/_textio.c) ============================================================================== --- /python/branches/io-c/Modules/_textio.c (original) +++ python/branches/py3k/Modules/_textio.c Wed Mar 4 01:14:51 2009 @@ -1,3 +1,11 @@ +/* + An implementation of Text I/O as defined by PEP 3116 - "New I/O" + + Classes defined here: TextIOBase, IncrementalNewlineDecoder, TextIOWrapper. + + Written by Amaury Forgeot d'Arc and Antoine Pitrou +*/ + #define PY_SSIZE_T_CLEAN #include "Python.h" #include "structmember.h" @@ -16,30 +24,128 @@ static PyObject * _unsupported(const char *message) { - PyErr_SetString(PyIOExc_UnsupportedOperation, message); + PyErr_SetString(IO_STATE->unsupported_operation, message); return NULL; } +PyDoc_STRVAR(TextIOBase_read_doc, + "Read at most n characters from stream.\n" + "\n" + "Read from underlying buffer until we have n characters or we hit EOF.\n" + "If n is negative or omitted, read until EOF.\n" + ); + static PyObject * TextIOBase_read(PyObject *self, PyObject *args) { return _unsupported("read"); } +PyDoc_STRVAR(TextIOBase_readline_doc, + "Read until newline or EOF.\n" + "\n" + "Returns an empty string if EOF is hit immediately.\n" + ); + +static PyObject * +TextIOBase_readline(PyObject *self, PyObject *args) +{ + return _unsupported("readline"); +} + +PyDoc_STRVAR(TextIOBase_write_doc, + "Write string to stream.\n" + "Returns the number of characters written (which is always equal to\n" + "the length of the string).\n" + ); + static PyObject * TextIOBase_write(PyObject *self, PyObject *args) { - return _unsupported("read"); + return _unsupported("write"); } +PyDoc_STRVAR(TextIOBase_encoding_doc, + "Encoding of the text stream.\n" + "\n" + "Subclasses should override.\n" + ); + static PyObject * -TextIOBase_readline(PyObject *self, PyObject *args) +TextIOBase_encoding_get(PyObject *self, void *context) { - return _unsupported("read"); + Py_RETURN_NONE; } -/* XXX properties: encoding, newlines */ - +PyDoc_STRVAR(TextIOBase_newlines_doc, + "Line endings translated so far.\n" + "\n" + "Only line endings translated during reading are considered.\n" + "\n" + "Subclasses should override.\n" + ); + +static PyObject * +TextIOBase_newlines_get(PyObject *self, void *context) +{ + Py_RETURN_NONE; +} + + +static PyMethodDef TextIOBase_methods[] = { + {"read", TextIOBase_read, METH_VARARGS, TextIOBase_read_doc}, + {"readline", TextIOBase_readline, METH_VARARGS, TextIOBase_readline_doc}, + {"write", TextIOBase_write, METH_VARARGS, TextIOBase_write_doc}, + {NULL, NULL} +}; + +static PyGetSetDef TextIOBase_getset[] = { + {"encoding", (getter)TextIOBase_encoding_get, NULL, TextIOBase_encoding_doc}, + {"newlines", (getter)TextIOBase_newlines_get, NULL, TextIOBase_newlines_doc}, + {0} +}; + +PyTypeObject PyTextIOBase_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_io._TextIOBase", /*tp_name*/ + 0, /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*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*/ + TextIOBase_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + TextIOBase_methods, /* tp_methods */ + 0, /* tp_members */ + TextIOBase_getset, /* tp_getset */ + &PyIOBase_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + /* IncrementalNewlineDecoder */ @@ -48,7 +154,9 @@ "another incremental decoder, translating \\r\\n and \\r into \\n. It also\n" "records the types of newlines encountered. When used with\n" "translate=False, it ensures that the newline sequence is returned in\n" - "one piece.\n" + "one piece. When used with decoder=None, it expects unicode strings as\n" + "decode input and translates newlines without first invoking an external\n" + "decoder.\n" ); typedef struct { @@ -106,12 +214,13 @@ #define SEEN_CRLF 4 #define SEEN_ALL (SEEN_CR | SEEN_LF | SEEN_CRLF) -static PyObject * -_IncrementalNewlineDecoder_decode(PyNewLineDecoderObject *self, - PyObject *input, int final) +PyObject * +_PyIncrementalNewlineDecoder_decode(PyObject *_self, + PyObject *input, int final) { PyObject *output; Py_ssize_t output_len; + PyNewLineDecoderObject *self = (PyNewLineDecoderObject *) _self; if (self->decoder == NULL) { PyErr_SetString(PyExc_ValueError, @@ -120,8 +229,15 @@ } /* decode input (with the eventual \r from a previous pass) */ - output = PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_decode, - input, final ? Py_True : Py_False, NULL); + if (self->decoder != Py_None) { + output = PyObject_CallMethodObjArgs(self->decoder, + _PyIO_str_decode, input, final ? Py_True : Py_False, NULL); + } + else { + output = input; + Py_INCREF(output); + } + if (output == NULL) return NULL; @@ -177,7 +293,7 @@ Py_UNICODE *in_str; Py_ssize_t len; int seennl = self->seennl; - int only_lf; + int only_lf = 0; in_str = PyUnicode_AS_UNICODE(output); len = PyUnicode_GET_SIZE(output); @@ -188,8 +304,16 @@ /* If, up to now, newlines are consistently \n, do a quick check for the \r *byte* with the libc's optimized memchr. */ - only_lf = ((seennl == SEEN_LF) - && !memchr(in_str, '\r', len * sizeof(Py_UNICODE))); + if (seennl == SEEN_LF || seennl == 0) { + int has_cr, has_lf; + has_lf = (seennl == SEEN_LF) || + (memchr(in_str, '\n', len * sizeof(Py_UNICODE)) != NULL); + has_cr = (memchr(in_str, '\r', len * sizeof(Py_UNICODE)) != NULL); + if (has_lf && !has_cr) { + only_lf = 1; + seennl = SEEN_LF; + } + } if (!self->translate) { Py_UNICODE *s, *end; @@ -301,26 +425,31 @@ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:IncrementalNewlineDecoder", kwlist, &input, &final)) return NULL; - return _IncrementalNewlineDecoder_decode(self, input, final); + return _PyIncrementalNewlineDecoder_decode((PyObject *) self, input, final); } static PyObject * IncrementalNewlineDecoder_getstate(PyNewLineDecoderObject *self, PyObject *args) { - PyObject *state = PyObject_CallMethodObjArgs(self->decoder, - _PyIO_str_getstate, NULL); PyObject *buffer; unsigned PY_LONG_LONG flag; - if (state == NULL) - return NULL; - - if (!PyArg_Parse(state, "(OK)", &buffer, &flag)) { + if (self->decoder != Py_None) { + PyObject *state = PyObject_CallMethodObjArgs(self->decoder, + _PyIO_str_getstate, NULL); + if (state == NULL) + return NULL; + if (!PyArg_Parse(state, "(OK)", &buffer, &flag)) { + Py_DECREF(state); + return NULL; + } + Py_INCREF(buffer); Py_DECREF(state); - return NULL; } - Py_INCREF(buffer); - Py_DECREF(state); + else { + buffer = PyBytes_FromString(""); + flag = 0; + } flag <<= 1; if (self->pendingcr) flag |= 1; @@ -339,7 +468,11 @@ self->pendingcr = (int) flag & 1; flag >>= 1; - return PyObject_CallMethod(self->decoder, "setstate", "((OK))", buffer, flag); + if (self->decoder != Py_None) + return PyObject_CallMethod(self->decoder, + "setstate", "((OK))", buffer, flag); + else + Py_RETURN_NONE; } static PyObject * @@ -347,7 +480,10 @@ { self->seennl = 0; self->pendingcr = 0; - return PyObject_CallMethod(self->decoder, "reset", NULL); + if (self->decoder != Py_None) + return PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_reset, NULL); + else + Py_RETURN_NONE; } static PyObject * @@ -390,7 +526,7 @@ PyTypeObject PyIncrementalNewlineDecoder_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "IncrementalNewlineDecoder", /*tp_name*/ + "_io.IncrementalNewlineDecoder", /*tp_name*/ sizeof(PyNewLineDecoderObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)IncrementalNewlineDecoder_dealloc, /*tp_dealloc*/ @@ -470,12 +606,12 @@ PyObject *readnl; PyObject *errors; const char *writenl; /* utf-8 encoded, NULL stands for \n */ - int line_buffering:1; - int readuniversal:1; - int readtranslate:1; - int writetranslate:1; - int seekable:1; - int telling:1; + char line_buffering; + char readuniversal; + char readtranslate; + char writetranslate; + char seekable; + char telling; /* Specialized encoding func (see below) */ encodefunc_t encodefunc; @@ -500,6 +636,9 @@ * snapshot point. We use this to reconstruct decoder states in tell(). */ + /* Cache raw object if it's a FileIO object */ + PyObject *raw; + PyObject *weakreflist; PyObject *dict; } PyTextIOWrapperObject; @@ -591,11 +730,12 @@ char *kwlist[] = {"buffer", "encoding", "errors", "newline", "line_buffering", NULL}; - PyObject *buffer; + PyObject *buffer, *raw; char *encoding = NULL; char *errors = NULL; char *newline = NULL; int line_buffering = 0; + _PyIO_State *state = IO_STATE; PyObject *res; int r; @@ -624,27 +764,29 @@ Py_CLEAR(self->pending_bytes); Py_CLEAR(self->snapshot); Py_CLEAR(self->errors); + Py_CLEAR(self->raw); self->decoded_chars_used = 0; self->pending_bytes_count = 0; self->encodefunc = NULL; if (encoding == NULL) { /* Try os.device_encoding(fileno) */ - PyObject *fileno, *os;; + PyObject *fileno; fileno = PyObject_CallMethod(buffer, "fileno", NULL); - /* Ignore any error */ - /* XXX only AttributeError and UnsupportedOperation */ - if (fileno == NULL) - PyErr_Clear(); - else { - os = PyImport_ImportModule("os"); - if (os == NULL) { - Py_DECREF(fileno); + /* Ignore only AttributeError and UnsupportedOperation */ + if (fileno == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError) || + PyErr_ExceptionMatches(state->unsupported_operation)) { + PyErr_Clear(); + } + else { goto error; } - self->encoding = PyObject_CallMethod(os, "device_encoding", + } + else { + self->encoding = PyObject_CallMethod(state->os_module, + "device_encoding", "N", fileno); - Py_DECREF(os); if (self->encoding == NULL) goto error; else if (!PyUnicode_Check(self->encoding)) @@ -652,19 +794,33 @@ } } if (encoding == NULL && self->encoding == NULL) { - /* try locale.getpreferredencoding() */ - PyObject *locale = PyImport_ImportModule("locale"); - if (locale == NULL) { - PyErr_Clear(); - self->encoding = PyUnicode_FromString("ascii"); + if (state->locale_module == NULL) { + state->locale_module = PyImport_ImportModule("locale"); + if (state->locale_module == NULL) + goto catch_ImportError; + else + goto use_locale; } else { + use_locale: self->encoding = PyObject_CallMethod( - locale, "getpreferredencoding", NULL); - Py_DECREF(locale); - if (self->encoding == NULL) - goto error; - if (!PyUnicode_Check(self->encoding)) + state->locale_module, "getpreferredencoding", NULL); + if (self->encoding == NULL) { + catch_ImportError: + /* + Importing locale can raise a ImportError because of + _functools, and locale.getpreferredencoding can raise a + ImportError if _locale is not available. These will happen + during module building. + */ + if (PyErr_ExceptionMatches(PyExc_ImportError)) { + PyErr_Clear(); + self->encoding = PyUnicode_FromString("ascii"); + } + else + goto error; + } + else if (!PyUnicode_Check(self->encoding)) Py_CLEAR(self->encoding); } } @@ -690,8 +846,11 @@ self->readuniversal = (newline == NULL || newline[0] == '\0'); self->line_buffering = line_buffering; self->readtranslate = (newline == NULL); - if (newline) + if (newline) { self->readnl = PyUnicode_FromString(newline); + if (self->readnl == NULL) + return -1; + } self->writetranslate = (newline == NULL || newline[0] != '\0'); if (!self->readuniversal && self->readnl) { self->writenl = _PyUnicode_AsString(self->readnl); @@ -765,6 +924,19 @@ self->buffer = buffer; Py_INCREF(buffer); + + if (Py_TYPE(buffer) == &PyBufferedReader_Type || + Py_TYPE(buffer) == &PyBufferedWriter_Type || + Py_TYPE(buffer) == &PyBufferedRandom_Type) { + raw = PyObject_GetAttrString(buffer, "raw"); + /* Cache the raw FileIO object to speed up 'closed' checks */ + if (raw == NULL) + PyErr_Clear(); + else if (Py_TYPE(raw) == &PyFileIO_Type) + self->raw = raw; + else + Py_DECREF(raw); + } res = PyObject_CallMethod(buffer, "seekable", NULL); if (res == NULL) @@ -779,11 +951,11 @@ return -1; } -static void -TextIOWrapper_dealloc(PyTextIOWrapperObject *self) +static int +_TextIOWrapper_clear(PyTextIOWrapperObject *self) { - if (_PyIOBase_finalize((PyObject *) self) < 0) - return; + if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0) + return -1; self->ok = 0; Py_CLEAR(self->buffer); Py_CLEAR(self->encoding); @@ -791,31 +963,72 @@ Py_CLEAR(self->decoder); Py_CLEAR(self->readnl); Py_CLEAR(self->decoded_chars); + Py_CLEAR(self->pending_bytes); Py_CLEAR(self->snapshot); + Py_CLEAR(self->errors); + Py_CLEAR(self->raw); + return 0; +} + +static void +TextIOWrapper_dealloc(PyTextIOWrapperObject *self) +{ + if (_TextIOWrapper_clear(self) < 0) + return; + _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *)self); Py_CLEAR(self->dict); Py_TYPE(self)->tp_free((PyObject *)self); } +static int +TextIOWrapper_traverse(PyTextIOWrapperObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->buffer); + Py_VISIT(self->encoding); + Py_VISIT(self->encoder); + Py_VISIT(self->decoder); + Py_VISIT(self->readnl); + Py_VISIT(self->decoded_chars); + Py_VISIT(self->pending_bytes); + Py_VISIT(self->snapshot); + Py_VISIT(self->errors); + Py_VISIT(self->raw); + + Py_VISIT(self->dict); + return 0; +} + +static int +TextIOWrapper_clear(PyTextIOWrapperObject *self) +{ + if (_TextIOWrapper_clear(self) < 0) + return -1; + Py_CLEAR(self->dict); + return 0; +} + static PyObject * TextIOWrapper_closed_get(PyTextIOWrapperObject *self, void *context); -/* This macro takes some shortcuts to make the common case faster. We could - specialize even more, by detecting that the underlying buffer is a - BufferedObject. */ +/* This macro takes some shortcuts to make the common case faster. */ #define CHECK_CLOSED(self) \ do { \ int r; \ PyObject *_res; \ if (Py_TYPE(self) == &PyTextIOWrapper_Type) { \ - _res = TextIOWrapper_closed_get(self, NULL); \ - if (_res == NULL) \ - return NULL; \ - r = PyObject_IsTrue(_res); \ - Py_DECREF(_res); \ - if (r < 0) \ - return NULL; \ + if (self->raw != NULL) \ + r = _PyFileIO_closed(self->raw); \ + else { \ + _res = TextIOWrapper_closed_get(self, NULL); \ + if (_res == NULL) \ + return NULL; \ + r = PyObject_IsTrue(_res); \ + Py_DECREF(_res); \ + if (r < 0) \ + return NULL; \ + } \ if (r > 0) { \ PyErr_SetString(PyExc_ValueError, \ "I/O operation on closed file."); \ @@ -862,7 +1075,7 @@ if (self->pending_bytes == NULL) return 0; - b = _PyBytes_Join(PyBytes_FromStringAndSize(NULL, 0), self->pending_bytes); + b = _PyBytes_Join(_PyIO_empty_bytes, self->pending_bytes); if (b == NULL) return -1; ret = PyObject_CallMethodObjArgs(self->buffer, @@ -1009,28 +1222,6 @@ return chars; } -/* Rewind the _decoded_chars buffer. */ -static int -TextIOWrapper_rewind_decoded_chars(PyTextIOWrapperObject *self, Py_ssize_t n) -{ - if (self->decoded_chars_used < n) { - PyErr_SetString(PyExc_ValueError, - "rewind decoded_chars out of bounds"); - return -1; - } - self->decoded_chars_used -= n; - return self->decoded_chars_used; -} - -static Py_ssize_t -TextIOWrapper_decoded_chars_length(PyTextIOWrapperObject *self, Py_ssize_t n) -{ - if (self->decoded_chars == NULL) - return 0; - return PyUnicode_GetSize(self->decoded_chars) - self->decoded_chars_used; -} - - /* Read and decode the next chunk of data from the BufferedReader. */ static int @@ -1088,8 +1279,8 @@ eof = (PyBytes_Size(input_chunk) == 0); if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type) { - decoded_chars = _IncrementalNewlineDecoder_decode( - (PyNewLineDecoderObject *) self->decoder, input_chunk, eof); + decoded_chars = _PyIncrementalNewlineDecoder_decode( + self->decoder, input_chunk, eof); } else { decoded_chars = PyObject_CallMethodObjArgs(self->decoder, @@ -1201,8 +1392,7 @@ if (result != NULL && PyList_Append(chunks, result) < 0) goto fail; Py_CLEAR(result); - result = PyUnicode_Join(PyUnicode_FromStringAndSize(NULL, 0), - chunks); + result = PyUnicode_Join(_PyIO_empty_str, chunks); if (result == NULL) goto fail; Py_CLEAR(chunks); @@ -1234,22 +1424,14 @@ } } -/* Finds the first line ending between start and end. - If not found, returns -1 and sets (*consumed) to the number of characters - which can be safely put aside before another search. - If found, returns the index after the line ending and doesn't touch - (*consumed). - - NOTE: `end` must point to the real end of the Py_UNICODE storage, - that is to the NUL character. Otherwise the function will produce - incorrect results. */ -static Py_ssize_t -find_line_ending(PyTextIOWrapperObject *self, - Py_UNICODE *start, Py_UNICODE *end, Py_ssize_t *consumed) +Py_ssize_t +_PyIO_find_line_ending( + int translated, int universal, PyObject *readnl, + Py_UNICODE *start, Py_UNICODE *end, Py_ssize_t *consumed) { Py_ssize_t len = end - start; - if (self->readtranslate) { + if (translated) { /* Newlines are already translated, only search for \n */ Py_UNICODE *pos = find_control_char(start, end, '\n'); if (pos != NULL) @@ -1259,7 +1441,7 @@ return -1; } } - else if (self->readuniversal) { + else if (universal) { /* Universal newline search. Find any of \r, \r\n, \n * The decoder ensures that \r\n are not split in two pieces */ @@ -1287,8 +1469,8 @@ } else { /* Non-universal mode. */ - Py_ssize_t readnl_len = PyUnicode_GET_SIZE(self->readnl); - Py_UNICODE *nl = PyUnicode_AS_UNICODE(self->readnl); + Py_ssize_t readnl_len = PyUnicode_GET_SIZE(readnl); + Py_UNICODE *nl = PyUnicode_AS_UNICODE(readnl); if (readnl_len == 1) { Py_UNICODE *pos = find_control_char(start, end, nl[0]); if (pos != NULL) @@ -1381,7 +1563,9 @@ ptr = PyUnicode_AS_UNICODE(line); line_len = PyUnicode_GET_SIZE(line); - endpos = find_line_ending(self, ptr + start, ptr + line_len, &consumed); + endpos = _PyIO_find_line_ending( + self->readtranslate, self->readuniversal, self->readnl, + ptr + start, ptr + line_len, &consumed); if (endpos >= 0) { endpos += start; if (limit >= 0 && (endpos - start) + chunked >= limit) @@ -1460,7 +1644,7 @@ if (line != NULL && PyList_Append(chunks, line) < 0) goto error; Py_CLEAR(line); - line = PyUnicode_Join(PyUnicode_FromStringAndSize(NULL, 0), chunks); + line = PyUnicode_Join(_PyIO_empty_str, chunks); if (line == NULL) goto error; Py_DECREF(chunks); @@ -1588,7 +1772,7 @@ utf-16, that we are expecting a BOM). */ if (cookie->start_pos == 0 && cookie->dec_flags == 0) - res = PyObject_CallMethod(self->decoder, "reset", NULL); + res = PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_reset, NULL); else res = PyObject_CallMethod(self->decoder, "setstate", "((yi))", "", cookie->dec_flags); @@ -1601,7 +1785,7 @@ static PyObject * TextIOWrapper_seek(PyTextIOWrapperObject *self, PyObject *args) { - PyObject *cookieObj; + PyObject *cookieObj, *posobj; CookieStruct cookie; int whence = 0; static PyObject *zero = NULL; @@ -1618,10 +1802,10 @@ if (!PyArg_ParseTuple(args, "O|i:seek", &cookieObj, &whence)) return NULL; - Py_INCREF(cookieObj); - CHECK_CLOSED(self); + Py_INCREF(cookieObj); + if (!self->seekable) { PyErr_SetString(PyExc_IOError, "underlying stream is not seekable"); @@ -1676,6 +1860,7 @@ } res = PyObject_CallMethod(self->buffer, "seek", "ii", 0, 2); + Py_XDECREF(cookieObj); return res; } else if (whence != 0) { @@ -1694,7 +1879,7 @@ goto fail; } - res = PyObject_CallMethod((PyObject *)self, "flush", NULL); + res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL); if (res == NULL) goto fail; Py_DECREF(res); @@ -1706,8 +1891,12 @@ goto fail; /* Seek back to the safe start point. */ - res = PyObject_CallMethod(self->buffer, "seek", - "L", (PY_LONG_LONG)cookie.start_pos); + posobj = PyLong_FromOff_t(cookie.start_pos); + if (posobj == NULL) + goto fail; + res = PyObject_CallMethodObjArgs(self->buffer, + _PyIO_str_seek, posobj, NULL); + Py_DECREF(posobj); if (res == NULL) goto fail; Py_DECREF(res); @@ -1719,9 +1908,6 @@ if (self->decoder) { if (_TextIOWrapper_decoder_setstate(self, &cookie) < 0) goto fail; - self->snapshot = Py_BuildValue("iy", cookie.dec_flags, ""); - if (self->snapshot == NULL) - goto fail; } if (cookie.chars_to_skip) { @@ -1735,14 +1921,14 @@ assert (PyBytes_Check(input_chunk)); - self->snapshot = Py_BuildValue("iO", cookie.dec_flags, input_chunk); + self->snapshot = Py_BuildValue("iN", cookie.dec_flags, input_chunk); if (self->snapshot == NULL) { Py_DECREF(input_chunk); goto fail; } decoded = PyObject_CallMethod(self->decoder, "decode", - "Ni", input_chunk, (int)cookie.need_eof); + "Oi", input_chunk, (int)cookie.need_eof); if (decoded == NULL) goto fail; @@ -1756,6 +1942,11 @@ } self->decoded_chars_used = cookie.chars_to_skip; } + else { + self->snapshot = Py_BuildValue("iy", cookie.dec_flags, ""); + if (self->snapshot == NULL) + goto fail; + } return cookieObj; fail: @@ -1896,6 +2087,7 @@ goto fail; assert (PyUnicode_Check(decoded)); chars_decoded += PyUnicode_GET_SIZE(decoded); + Py_DECREF(decoded); cookie.need_eof = 1; if (chars_decoded < chars_to_skip) { @@ -2139,6 +2331,7 @@ static PyMemberDef TextIOWrapper_members[] = { {"encoding", T_OBJECT, offsetof(PyTextIOWrapperObject, encoding), READONLY}, {"buffer", T_OBJECT, offsetof(PyTextIOWrapperObject, buffer), READONLY}, + {"line_buffering", T_BOOL, offsetof(PyTextIOWrapperObject, line_buffering), READONLY}, {NULL} }; @@ -2155,7 +2348,7 @@ PyTypeObject PyTextIOWrapper_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "TextIOWrapper", /*tp_name*/ + "_io.TextIOWrapper", /*tp_name*/ sizeof(PyTextIOWrapperObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TextIOWrapper_dealloc, /*tp_dealloc*/ @@ -2173,10 +2366,11 @@ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ TextIOWrapper_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (traverseproc)TextIOWrapper_traverse, /* tp_traverse */ + (inquiry)TextIOWrapper_clear, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyTextIOWrapperObject, weakreflist), /*tp_weaklistoffset*/ 0, /* tp_iter */ Copied: python/branches/py3k/Modules/io.c (from r68756, /python/branches/io-c/Modules/io.c) ============================================================================== --- /python/branches/io-c/Modules/io.c (original) +++ python/branches/py3k/Modules/io.c Wed Mar 4 01:14:51 2009 @@ -1,3 +1,12 @@ +/* + An implementation of the new I/O lib as defined by PEP 3116 - "New I/O" + + Classes defined here: UnsupportedOperation, BlockingIOError. + Functions defined here: open(). + + Mostly written by Amaury Forgeot d'Arc +*/ + #define PY_SSIZE_T_CLEAN #include "Python.h" #include "structmember.h" @@ -11,7 +20,6 @@ #include #endif /* HAVE_SYS_STAT_H */ -PyObject *PyIOExc_UnsupportedOperation; /* Various interned strings */ @@ -24,11 +32,13 @@ PyObject *_PyIO_str_getstate; PyObject *_PyIO_str_isatty; PyObject *_PyIO_str_newlines; +PyObject *_PyIO_str_nl; PyObject *_PyIO_str_read; PyObject *_PyIO_str_read1; PyObject *_PyIO_str_readable; PyObject *_PyIO_str_readinto; PyObject *_PyIO_str_readline; +PyObject *_PyIO_str_reset; PyObject *_PyIO_str_seek; PyObject *_PyIO_str_seekable; PyObject *_PyIO_str_tell; @@ -36,6 +46,9 @@ PyObject *_PyIO_str_writable; PyObject *_PyIO_str_write; +PyObject *_PyIO_empty_str; +PyObject *_PyIO_empty_bytes; + PyDoc_STRVAR(module_doc, "The io module provides the Python interfaces to stream handling. The\n" @@ -82,41 +95,29 @@ BlockingIOError_init(PyBlockingIOErrorObject *self, PyObject *args, PyObject *kwds) { - PyObject *myerrno = NULL, *strerror = NULL, *written; + PyObject *myerrno = NULL, *strerror = NULL; PyObject *baseargs = NULL; + Py_ssize_t written = 0; assert(PyTuple_Check(args)); - if (PyTuple_GET_SIZE(args) <= 1 || PyTuple_GET_SIZE(args) > 3) - return 0; + self->written = 0; + if (!PyArg_ParseTuple(args, "OO|n:BlockingIOError", + &myerrno, &strerror, &written)) + return -1; - baseargs = PyTuple_GetSlice(args, 0, 2); + baseargs = PyTuple_Pack(2, myerrno, strerror); if (baseargs == NULL) return -1; - + /* This will take care of initializing of myerrno and strerror members */ if (((PyTypeObject *)PyExc_IOError)->tp_init( (PyObject *)self, baseargs, kwds) == -1) { Py_DECREF(baseargs); return -1; } - Py_DECREF(baseargs); - if (!PyArg_UnpackTuple(args, "BlockingIOError", 2, 3, - &myerrno, &strerror, &written)) { - return -1; - } - - Py_INCREF(myerrno); - self->myerrno = myerrno; - - Py_INCREF(strerror); - self->strerror = strerror; - - self->written = PyNumber_AsSsize_t(written, PyExc_ValueError); - if(self->written == -1 && PyErr_Occurred()) - return -1; - + self->written = written; return 0; } @@ -125,7 +126,6 @@ {NULL} /* Sentinel */ }; - static PyTypeObject _PyExc_BlockingIOError = { PyVarObject_HEAD_INIT(NULL, 0) "BlockingIOError", /*tp_name*/ @@ -146,8 +146,9 @@ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - PyDoc_STR("Exception raised when I/O would block on a non-blocking I/O stream"), /* tp_doc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + PyDoc_STR("Exception raised when I/O would block " + "on a non-blocking I/O stream"), /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ @@ -558,6 +559,36 @@ return result; } +static int +iomodule_traverse(PyObject *mod, visitproc visit, void *arg) { + _PyIO_State *state = IO_MOD_STATE(mod); + if (!state->initialized) + return 0; + Py_VISIT(state->os_module); + if (state->locale_module != NULL) { + Py_VISIT(state->locale_module); + } + Py_VISIT(state->unsupported_operation); + return 0; +} + +static int +iomodule_clear(PyObject *mod) { + _PyIO_State *state = IO_MOD_STATE(mod); + if (!state->initialized) + return 0; + Py_CLEAR(state->os_module); + if (state->locale_module != NULL) + Py_CLEAR(state->locale_module); + Py_CLEAR(state->unsupported_operation); + return 0; +} + +static void +iomodule_free(PyObject *mod) { + iomodule_clear(mod); +} + /* * Module definition */ @@ -567,116 +598,104 @@ {NULL, NULL} }; -static struct PyModuleDef iomodule = { +struct PyModuleDef _PyIO_Module = { PyModuleDef_HEAD_INIT, "io", module_doc, - -1, + sizeof(_PyIO_State), module_methods, NULL, - NULL, - NULL, - NULL + iomodule_traverse, + iomodule_clear, + (freefunc)iomodule_free, }; PyMODINIT_FUNC PyInit__io(void) { - PyObject *m = PyModule_Create(&iomodule); - PyTypeObject *base; + PyObject *m = PyModule_Create(&_PyIO_Module); + _PyIO_State *state = NULL; if (m == NULL) + return NULL; + state = IO_MOD_STATE(m); + state->initialized = 0; + + /* put os in the module state */ + state->os_module = PyImport_ImportModule("os"); + if (state->os_module == NULL) + goto fail; + +#define ADD_TYPE(type, name) \ + if (PyType_Ready(type) < 0) \ + goto fail; \ + Py_INCREF(type); \ + if (PyModule_AddObject(m, name, (PyObject *)type) < 0) { \ + Py_DECREF(type); \ + goto fail; \ + } + + /* DEFAULT_BUFFER_SIZE */ + if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0) goto fail; /* UnsupportedOperation inherits from ValueError and IOError */ - PyIOExc_UnsupportedOperation = PyObject_CallFunction( + state->unsupported_operation = PyObject_CallFunction( (PyObject *)&PyType_Type, "s(OO){}", "UnsupportedOperation", PyExc_ValueError, PyExc_IOError); - if (PyIOExc_UnsupportedOperation == NULL) + if (state->unsupported_operation == NULL) goto fail; - PyModule_AddObject(m, "UnsupportedOperation", - PyIOExc_UnsupportedOperation); - - /* BlockingIOError */ - base = (PyTypeObject *)PyExc_IOError; - _PyExc_BlockingIOError.tp_base = base; - if (PyType_Ready(&_PyExc_BlockingIOError) < 0) + Py_INCREF(state->unsupported_operation); + if (PyModule_AddObject(m, "UnsupportedOperation", + state->unsupported_operation) < 0) goto fail; - Py_INCREF(&_PyExc_BlockingIOError); - PyModule_AddObject(m, "BlockingIOError", - (PyObject *)&_PyExc_BlockingIOError); - if (PyType_Ready(&PyIOBase_Type) < 0) - goto fail; - Py_INCREF(&PyIOBase_Type); - PyModule_AddObject(m, "IOBase", - (PyObject *)&PyIOBase_Type); + /* BlockingIOError */ + _PyExc_BlockingIOError.tp_base = (PyTypeObject *) PyExc_IOError; + ADD_TYPE(&_PyExc_BlockingIOError, "BlockingIOError"); - if (PyType_Ready(&PyRawIOBase_Type) < 0) - goto fail; - Py_INCREF(&PyRawIOBase_Type); - PyModule_AddObject(m, "RawIOBase", - (PyObject *)&PyRawIOBase_Type); + /* Concrete base types of the IO ABCs. + (the ABCs themselves are declared through inheritance in io.py) + */ + ADD_TYPE(&PyIOBase_Type, "_IOBase"); + ADD_TYPE(&PyRawIOBase_Type, "_RawIOBase"); + ADD_TYPE(&PyBufferedIOBase_Type, "_BufferedIOBase"); + ADD_TYPE(&PyTextIOBase_Type, "_TextIOBase"); + /* Implementation of concrete IO objects. */ /* FileIO */ PyFileIO_Type.tp_base = &PyRawIOBase_Type; - if (PyType_Ready(&PyFileIO_Type) < 0) - goto fail; - Py_INCREF(&PyFileIO_Type); - PyModule_AddObject(m, "FileIO", (PyObject *) &PyFileIO_Type); - - /* BufferedIOBase */ - if (PyType_Ready(&PyBufferedIOBase_Type) < 0) - goto fail; - Py_INCREF(&PyBufferedIOBase_Type); - PyModule_AddObject(m, "BufferedIOBase", (PyObject *) &PyBufferedIOBase_Type); + ADD_TYPE(&PyFileIO_Type, "FileIO"); /* BytesIO */ PyBytesIO_Type.tp_base = &PyBufferedIOBase_Type; - if (PyType_Ready(&PyBytesIO_Type) < 0) - goto fail; - Py_INCREF(&PyBytesIO_Type); - PyModule_AddObject(m, "BytesIO", (PyObject *) &PyBytesIO_Type); + ADD_TYPE(&PyBytesIO_Type, "BytesIO"); + + /* StringIO */ + PyStringIO_Type.tp_base = &PyTextIOBase_Type; + ADD_TYPE(&PyStringIO_Type, "StringIO"); /* BufferedReader */ PyBufferedReader_Type.tp_base = &PyBufferedIOBase_Type; - if (PyType_Ready(&PyBufferedReader_Type) < 0) - goto fail; - Py_INCREF(&PyBufferedReader_Type); - PyModule_AddObject(m, "BufferedReader", (PyObject *) &PyBufferedReader_Type); + ADD_TYPE(&PyBufferedReader_Type, "BufferedReader"); /* BufferedWriter */ PyBufferedWriter_Type.tp_base = &PyBufferedIOBase_Type; - if (PyType_Ready(&PyBufferedWriter_Type) < 0) - goto fail; - Py_INCREF(&PyBufferedWriter_Type); - PyModule_AddObject(m, "BufferedWriter", (PyObject *) &PyBufferedWriter_Type); + ADD_TYPE(&PyBufferedWriter_Type, "BufferedWriter"); /* BufferedRWPair */ PyBufferedRWPair_Type.tp_base = &PyBufferedIOBase_Type; - if (PyType_Ready(&PyBufferedRWPair_Type) < 0) - goto fail; - Py_INCREF(&PyBufferedRWPair_Type); - PyModule_AddObject(m, "BufferedRWPair", (PyObject *) &PyBufferedRWPair_Type); + ADD_TYPE(&PyBufferedRWPair_Type, "BufferedRWPair"); /* BufferedRandom */ PyBufferedRandom_Type.tp_base = &PyBufferedIOBase_Type; - if (PyType_Ready(&PyBufferedRandom_Type) < 0) - goto fail; - Py_INCREF(&PyBufferedRandom_Type); - PyModule_AddObject(m, "BufferedRandom", (PyObject *) &PyBufferedRandom_Type); + ADD_TYPE(&PyBufferedRandom_Type, "BufferedRandom"); /* TextIOWrapper */ - PyTextIOWrapper_Type.tp_base = &PyIOBase_Type; - if (PyType_Ready(&PyTextIOWrapper_Type) < 0) - goto fail; - Py_INCREF(&PyTextIOWrapper_Type); - PyModule_AddObject(m, "TextIOWrapper", (PyObject *) &PyTextIOWrapper_Type); + PyTextIOWrapper_Type.tp_base = &PyTextIOBase_Type; + ADD_TYPE(&PyTextIOWrapper_Type, "TextIOWrapper"); - /* TextIOWrapper */ - if (PyType_Ready(&PyIncrementalNewlineDecoder_Type) < 0) - goto fail; - Py_INCREF(&PyIncrementalNewlineDecoder_Type); - PyModule_AddObject(m, "IncrementalNewlineDecoder", (PyObject *) &PyIncrementalNewlineDecoder_Type); + /* IncrementalNewlineDecoder */ + ADD_TYPE(&PyIncrementalNewlineDecoder_Type, "IncrementalNewlineDecoder"); /* Interned strings */ if (!(_PyIO_str_close = PyUnicode_InternFromString("close"))) @@ -697,6 +716,8 @@ goto fail; if (!(_PyIO_str_newlines = PyUnicode_InternFromString("newlines"))) goto fail; + if (!(_PyIO_str_nl = PyUnicode_InternFromString("\n"))) + goto fail; if (!(_PyIO_str_read = PyUnicode_InternFromString("read"))) goto fail; if (!(_PyIO_str_read1 = PyUnicode_InternFromString("read1"))) @@ -707,6 +728,8 @@ goto fail; if (!(_PyIO_str_readline = PyUnicode_InternFromString("readline"))) goto fail; + if (!(_PyIO_str_reset = PyUnicode_InternFromString("reset"))) + goto fail; if (!(_PyIO_str_seek = PyUnicode_InternFromString("seek"))) goto fail; if (!(_PyIO_str_seekable = PyUnicode_InternFromString("seekable"))) @@ -719,10 +742,19 @@ goto fail; if (!(_PyIO_str_writable = PyUnicode_InternFromString("writable"))) goto fail; + + if (!(_PyIO_empty_str = PyUnicode_FromStringAndSize(NULL, 0))) + goto fail; + if (!(_PyIO_empty_bytes = PyBytes_FromStringAndSize(NULL, 0))) + goto fail; + + state->initialized = 1; return m; fail: - Py_XDECREF(m); + Py_XDECREF(state->os_module); + Py_XDECREF(state->unsupported_operation); + Py_DECREF(m); return NULL; } Modified: python/branches/py3k/PC/VC6/pythoncore.dsp ============================================================================== --- python/branches/py3k/PC/VC6/pythoncore.dsp (original) +++ python/branches/py3k/PC/VC6/pythoncore.dsp Wed Mar 4 01:14:51 2009 @@ -97,6 +97,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Modules\_bufferedio.c +# End Source File +# Begin Source File + SOURCE=..\..\Modules\_bytesio.c # End Source File # Begin Source File @@ -149,6 +153,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Modules\_iobase.c +# End Source File +# Begin Source File + SOURCE=..\..\Modules\_json.c # End Source File # Begin Source File @@ -185,6 +193,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Modules\_textio.c +# End Source File +# Begin Source File + SOURCE=..\..\Modules\_threadmodule.c # End Source File # Begin Source File @@ -463,6 +475,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Modules\io.c +# End Source File +# Begin Source File + SOURCE=..\..\Objects\iterobject.c # End Source File # Begin Source File Modified: python/branches/py3k/PC/config.c ============================================================================== --- python/branches/py3k/PC/config.c (original) +++ python/branches/py3k/PC/config.c Wed Mar 4 01:14:51 2009 @@ -58,9 +58,7 @@ extern PyObject* PyInit__subprocess(void); extern PyObject* PyInit__lsprof(void); extern PyObject* PyInit__ast(void); -extern PyObject* PyInit__fileio(void); -extern PyObject* PyInit__bytesio(void); -extern PyObject* PyInit__stringio(void); +extern PyObject* PyInit__io(void); extern PyObject* PyInit__pickle(void); extern PyObject* PyInit_atexit(void); extern PyObject* _PyWarnings_Init(void); @@ -150,9 +148,7 @@ {"sys", NULL}, {"_warnings", _PyWarnings_Init}, - {"_fileio", PyInit__fileio}, - {"_bytesio", PyInit__bytesio}, - {"_stringio", PyInit__stringio}, + {"_io", PyInit__io}, {"_pickle", PyInit__pickle}, {"atexit", PyInit_atexit}, Modified: python/branches/py3k/PCbuild/pythoncore.vcproj ============================================================================== --- python/branches/py3k/PCbuild/pythoncore.vcproj (original) +++ python/branches/py3k/PCbuild/pythoncore.vcproj Wed Mar 4 01:14:51 2009 @@ -975,6 +975,10 @@ > + + @@ -1003,6 +1007,14 @@ > + + + + @@ -1035,6 +1047,10 @@ > + + @@ -1075,6 +1091,10 @@ > + + Modified: python/branches/py3k/Python/pythonrun.c ============================================================================== --- python/branches/py3k/Python/pythonrun.c (original) +++ python/branches/py3k/Python/pythonrun.c Wed Mar 4 01:14:51 2009 @@ -769,7 +769,7 @@ } text = PyUnicode_FromString(name); - if (text == NULL || PyObject_SetAttrString(raw, "_name", text) < 0) + if (text == NULL || PyObject_SetAttrString(raw, "name", text) < 0) goto error; res = PyObject_CallMethod(raw, "isatty", ""); if (res == NULL) Modified: python/branches/py3k/setup.py ============================================================================== --- python/branches/py3k/setup.py (original) +++ python/branches/py3k/setup.py Wed Mar 4 01:14:51 2009 @@ -982,8 +982,6 @@ # Thomas Heller's _ctypes module self.detect_ctypes(inc_dirs, lib_dirs) - # _fileio -- supposedly cross platform - exts.append(Extension('_fileio', ['_fileio.c'])) # Richard Oudkerk's multiprocessing module if platform == 'win32': # Windows macros = dict() From buildbot at python.org Wed Mar 4 01:39:57 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Mar 2009 00:39:57 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090304003957.8C6DF1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/460 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 6 tests failed: test_fileio test_importlib test_io test_ttk_textonly test_urllib2_localnet test_urllibnet ====================================================================== ERROR: testBytesOpen (test.test_fileio.OtherFileTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/test/test_fileio.py", line 186, in testBytesOpen f = _FileIO(fn, "w") SystemError: null argument to internal routine ====================================================================== ERROR: testInvalidFd (test.test_fileio.OtherFileTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/test/test_fileio.py", line 196, in testInvalidFd self.assertRaises(ValueError, _fileio._FileIO, -10) NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bad_bytecode (importlib.test.source.test_loader.BadBytecodeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 242, in test_bad_bytecode self.import_(mapping['_temp'], '_temp') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 216, in import_ module = loader.load_module(module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bad_magic (importlib.test.source.test_loader.BadBytecodeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 228, in test_bad_magic self.import_(mapping['_temp'], '_temp') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 216, in import_ module = loader.load_module(module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bad_marshal (importlib.test.source.test_loader.BadBytecodeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 260, in test_bad_marshal '_temp') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/unittest.py", line 344, in failUnlessRaises callableObj(*args, **kwargs) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 216, in import_ module = loader.load_module(module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bad_magic (importlib.test.source.test_loader.BadDataTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 148, in test_bad_magic self.assertRaises(ImportError, loader.load_module, '_temp') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/unittest.py", line 344, in failUnlessRaises callableObj(*args, **kwargs) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bytecode_not_written (importlib.test.source.test_loader.DontWriteBytecodeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 127, in test_bytecode_not_written self.run_test(fxn) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 116, in run_test loader.load_module('_temp') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bytecode_written (importlib.test.source.test_loader.DontWriteBytecodeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 122, in test_bytecode_written self.run_test(fxn) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 116, in run_test loader.load_module('_temp') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bad_syntax (importlib.test.source.test_loader.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 101, in test_bad_syntax self.assertRaises(SyntaxError, loader.load_module, '_temp') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/unittest.py", line 344, in failUnlessRaises callableObj(*args, **kwargs) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_lacking_parent (importlib.test.source.test_loader.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 47, in test_lacking_parent module = loader.load_module('_pkg.mod') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_module (importlib.test.source.test_loader.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 23, in test_module module = loader.load_module('_temp') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_module_reuse (importlib.test.source.test_loader.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 61, in test_module_reuse module = loader.load_module('_temp') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_package (importlib.test.source.test_loader.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 34, in test_package module = loader.load_module('_pkg') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_state_after_failure (importlib.test.source.test_loader.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 91, in test_state_after_failure self.assertRaises(SyntaxError, loader.load_module, name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/unittest.py", line 344, in failUnlessRaises callableObj(*args, **kwargs) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_basic_package (importlib.test.source.test_loader.SourceBytecodeInteraction) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 190, in test_basic_package self.run_test('pkg.__init__', pkg=True) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 179, in run_test module = loader.load_module(import_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_basic_sub_module (importlib.test.source.test_loader.SourceBytecodeInteraction) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 194, in test_basic_sub_module self.run_test('pkg.sub', 'pkg.__init__') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 179, in run_test module = loader.load_module(import_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_basic_sub_package (importlib.test.source.test_loader.SourceBytecodeInteraction) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 198, in test_basic_sub_package self.run_test('pkg.sub.__init__', 'pkg.__init__', pkg=True) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 179, in run_test module = loader.load_module(import_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_basic_top_level (importlib.test.source.test_loader.SourceBytecodeInteraction) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 186, in test_basic_top_level self.run_test('top_level') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_loader.py", line 179, in run_test module = loader.load_module(import_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bom (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 74, in test_bom self.run_test(codecs.BOM_UTF8 + self.source_line.encode('utf-8')) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bom_and_utf_8 (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 79, in test_bom_and_utf_8 self.run_test(source) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bom_conflict (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 84, in test_bom_conflict self.assertRaises(SyntaxError, self.run_test, source) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/unittest.py", line 344, in failUnlessRaises callableObj(*args, **kwargs) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_default_encoding (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 59, in test_default_encoding self.run_test(self.source_line.encode('utf-8')) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_encoding_on_first_line (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 65, in test_encoding_on_first_line self.run_test(source) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_encoding_on_second_line (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 70, in test_encoding_on_second_line self.run_test(source) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_non_obvious_encoding (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 55, in test_non_obvious_encoding self.run_test(source) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_cr (importlib.test.source.test_source_encoding.LineEndingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 105, in test_cr self.run_test(b'\r') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 101, in run_test return loader.load_module(module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_crlf (importlib.test.source.test_source_encoding.LineEndingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 109, in test_crlf self.run_test(b'\r\n') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 101, in run_test return loader.load_module(module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_lf (importlib.test.source.test_source_encoding.LineEndingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 113, in test_lf self.run_test(b'\n') File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/test/source/test_source_encoding.py", line 101, in run_test return loader.load_module(module_name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== FAIL: test_append_mode_tell (test.test_io.CIOTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/test/test_io.py", line 379, in test_append_mode_tell self.assertEqual(f.tell(), 3) AssertionError: 0 != 3 ====================================================================== FAIL: test_append_mode_tell (test.test_io.PyIOTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/test/test_io.py", line 379, in test_append_mode_tell self.assertEqual(f.tell(), 3) AssertionError: 0 != 3 Traceback (most recent call last): File "./Lib/test/regrtest.py", line 605, in runtest_inner indirect_test() File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/test/test_ttk_textonly.py", line 8, in test_main *runtktests.get_tests(gui=False, packages=['test_ttk'])) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/tkinter/test/runtktests.py", line 65, in get_tests for module in get_tests_modules(gui=gui, packages=packages): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/tkinter/test/runtktests.py", line 50, in get_tests_modules "tkinter.test") File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/__init__.py", line 136, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 781, in _gcd_import _gcd_import(parent) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 789, in _gcd_import loader.load_module(name) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_chunked (test.test_urllib2_localnet.TestUrlopen) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/test/test_urllib2_localnet.py", line 392, in test_chunked data = self.urlopen("http://localhost:%s/" % handler.port) File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/test/test_urllib2_localnet.py", line 348, in urlopen l.extend(f.readlines(200)) ValueError: I/O operation on closed file. ====================================================================== ERROR: test_readlines (test.test_urllibnet.urlopenNetworkTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/test/test_urllibnet.py", line 78, in test_readlines self.assert_(isinstance(open_url.readlines(), list), ValueError: I/O operation on closed file. make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Mar 4 02:00:54 2009 From: python-checkins at python.org (brett.cannon) Date: Wed, 4 Mar 2009 02:00:54 +0100 (CET) Subject: [Python-checkins] r70153 - in python/trunk/Lib: importlib/__init__.py test/test_importlib.py Message-ID: <20090304010054.2C41A1E4002@bag.python.org> Author: brett.cannon Date: Wed Mar 4 02:00:53 2009 New Revision: 70153 Log: Fix some more bugs caused by the backport from 3.x for importlib. Do a more exact copy of the final 3.x code to resolve bugs and add appropriate tests. Modified: python/trunk/Lib/importlib/__init__.py python/trunk/Lib/test/test_importlib.py Modified: python/trunk/Lib/importlib/__init__.py ============================================================================== --- python/trunk/Lib/importlib/__init__.py (original) +++ python/trunk/Lib/importlib/__init__.py Wed Mar 4 02:00:53 2009 @@ -5,24 +5,16 @@ def _resolve_name(name, package, level): """Return the absolute name of the module to be imported.""" - level -= 1 - try: - if package.count('.') < level: + if not hasattr(package, 'rindex'): + raise ValueError("'package' not set to a string") + dot = len(package) + for x in xrange(level, 1, -1): + try: + dot = package.rindex('.', 0, dot) + except ValueError: raise ValueError("attempted relative import beyond top-level " "package") - except AttributeError: - raise ValueError("'package' not set to a string") - try: - # rpartition is more "correct" and rfind is just as easy to use, but - # neither are in Python 2.3. - dot_rindex = package.rindex('.', level) - base = package[:dot_rindex] - except ValueError: - base = package - if name: - return "%s.%s" % (base, name) - else: - return base + return "%s.%s" % (package[:dot], name) def import_module(name, package=None): @@ -42,10 +34,5 @@ break level += 1 name = _resolve_name(name[level:], package, level) - # Try to import specifying the level to be as accurate as possible, but - # realize that keyword arguments are not found in Python 2.3. - try: - __import__(name, level=0) - except TypeError: - __import__(name) + __import__(name) return sys.modules[name] Modified: python/trunk/Lib/test/test_importlib.py ============================================================================== --- python/trunk/Lib/test/test_importlib.py (original) +++ python/trunk/Lib/test/test_importlib.py Wed Mar 4 02:00:53 2009 @@ -135,20 +135,20 @@ module = importlib.import_module(name) self.assertEqual(module.__name__, name) - def test_relative_package_import(self): + def test_shallow_relative_package_import(self): + modules = ['a.__init__', 'a.b.__init__', 'a.b.c.__init__', 'a.b.c.d'] + with mock_modules(*modules) as mock: + with import_state(meta_path=[mock]): + module = importlib.import_module('.d', 'a.b.c') + self.assertEqual(module.__name__, 'a.b.c.d') + + def test_deep_relative_package_import(self): # Test importing a module from a package through a relatve import. - pkg_name = 'pkg' - pkg_long_name = '{0}.__init__'.format(pkg_name) - module_name = 'mod' - subpkg_name = '{0}.subpkg'.format(pkg_name) - subpkg_long_name = '{0}.__init__'.format(subpkg_name) - absolute_name = '{0}.{1}'.format(pkg_name, module_name) - relative_name = '..{0}'.format(module_name) - with mock_modules(pkg_long_name, subpkg_long_name, - absolute_name) as mock: + modules = ['a.__init__', 'a.b.__init__', 'a.c'] + with mock_modules(*modules) as mock: with import_state(meta_path=[mock]): - module = importlib.import_module(relative_name, subpkg_name) - self.assertEqual(module.__name__, absolute_name) + module = importlib.import_module('..c', 'a.b') + self.assertEqual(module.__name__, 'a.c') def test_absolute_import_with_package(self): # Test importing a module from a package with an absolute name with From buildbot at python.org Wed Mar 4 02:02:43 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Mar 2009 01:02:43 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090304010243.ED9071E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/364 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 6 tests failed: test_fileio test_importlib test_io test_ttk_textonly test_urllib2_localnet test_urllibnet ====================================================================== ERROR: testBytesOpen (test.test_fileio.OtherFileTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_fileio.py", line 186, in testBytesOpen f = _FileIO(fn, "w") SystemError: null argument to internal routine ====================================================================== ERROR: testInvalidFd (test.test_fileio.OtherFileTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_fileio.py", line 196, in testInvalidFd self.assertRaises(ValueError, _fileio._FileIO, -10) NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bad_bytecode (importlib.test.source.test_loader.BadBytecodeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 242, in test_bad_bytecode self.import_(mapping['_temp'], '_temp') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 216, in import_ module = loader.load_module(module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bad_magic (importlib.test.source.test_loader.BadBytecodeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 228, in test_bad_magic self.import_(mapping['_temp'], '_temp') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 216, in import_ module = loader.load_module(module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bad_marshal (importlib.test.source.test_loader.BadBytecodeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 260, in test_bad_marshal '_temp') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/unittest.py", line 344, in failUnlessRaises callableObj(*args, **kwargs) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 216, in import_ module = loader.load_module(module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bad_magic (importlib.test.source.test_loader.BadDataTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 148, in test_bad_magic self.assertRaises(ImportError, loader.load_module, '_temp') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/unittest.py", line 344, in failUnlessRaises callableObj(*args, **kwargs) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bytecode_not_written (importlib.test.source.test_loader.DontWriteBytecodeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 127, in test_bytecode_not_written self.run_test(fxn) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 116, in run_test loader.load_module('_temp') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bytecode_written (importlib.test.source.test_loader.DontWriteBytecodeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 122, in test_bytecode_written self.run_test(fxn) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 116, in run_test loader.load_module('_temp') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bad_syntax (importlib.test.source.test_loader.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 101, in test_bad_syntax self.assertRaises(SyntaxError, loader.load_module, '_temp') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/unittest.py", line 344, in failUnlessRaises callableObj(*args, **kwargs) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_lacking_parent (importlib.test.source.test_loader.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 47, in test_lacking_parent module = loader.load_module('_pkg.mod') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_module (importlib.test.source.test_loader.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 23, in test_module module = loader.load_module('_temp') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_module_reuse (importlib.test.source.test_loader.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 61, in test_module_reuse module = loader.load_module('_temp') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_package (importlib.test.source.test_loader.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 34, in test_package module = loader.load_module('_pkg') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_state_after_failure (importlib.test.source.test_loader.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 91, in test_state_after_failure self.assertRaises(SyntaxError, loader.load_module, name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/unittest.py", line 344, in failUnlessRaises callableObj(*args, **kwargs) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_basic_package (importlib.test.source.test_loader.SourceBytecodeInteraction) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 190, in test_basic_package self.run_test('pkg.__init__', pkg=True) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 179, in run_test module = loader.load_module(import_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_basic_sub_module (importlib.test.source.test_loader.SourceBytecodeInteraction) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 194, in test_basic_sub_module self.run_test('pkg.sub', 'pkg.__init__') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 179, in run_test module = loader.load_module(import_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_basic_sub_package (importlib.test.source.test_loader.SourceBytecodeInteraction) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 198, in test_basic_sub_package self.run_test('pkg.sub.__init__', 'pkg.__init__', pkg=True) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 179, in run_test module = loader.load_module(import_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_basic_top_level (importlib.test.source.test_loader.SourceBytecodeInteraction) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 186, in test_basic_top_level self.run_test('top_level') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_loader.py", line 179, in run_test module = loader.load_module(import_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 395, in get_code data = self.get_data(bytecode_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bom (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 74, in test_bom self.run_test(codecs.BOM_UTF8 + self.source_line.encode('utf-8')) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bom_and_utf_8 (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 79, in test_bom_and_utf_8 self.run_test(source) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_bom_conflict (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 84, in test_bom_conflict self.assertRaises(SyntaxError, self.run_test, source) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/unittest.py", line 344, in failUnlessRaises callableObj(*args, **kwargs) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_default_encoding (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 59, in test_default_encoding self.run_test(self.source_line.encode('utf-8')) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_encoding_on_first_line (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 65, in test_encoding_on_first_line self.run_test(source) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_encoding_on_second_line (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 70, in test_encoding_on_second_line self.run_test(source) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_non_obvious_encoding (importlib.test.source.test_source_encoding.EncodingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 55, in test_non_obvious_encoding self.run_test(source) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 40, in run_test return loader.load_module(self.module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_cr (importlib.test.source.test_source_encoding.LineEndingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 105, in test_cr self.run_test(b'\r') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 101, in run_test return loader.load_module(module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_crlf (importlib.test.source.test_source_encoding.LineEndingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 109, in test_crlf self.run_test(b'\r\n') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 101, in run_test return loader.load_module(module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_lf (importlib.test.source.test_source_encoding.LineEndingTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 113, in test_lf self.run_test(b'\n') File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/test/source/test_source_encoding.py", line 101, in run_test return loader.load_module(module_name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== FAIL: test_append_mode_tell (test.test_io.CIOTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_io.py", line 379, in test_append_mode_tell self.assertEqual(f.tell(), 3) AssertionError: 0 != 3 ====================================================================== FAIL: test_append_mode_tell (test.test_io.PyIOTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_io.py", line 379, in test_append_mode_tell self.assertEqual(f.tell(), 3) AssertionError: 0 != 3 Traceback (most recent call last): File "./Lib/test/regrtest.py", line 605, in runtest_inner indirect_test() File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_ttk_textonly.py", line 8, in test_main *runtktests.get_tests(gui=False, packages=['test_ttk'])) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/tkinter/test/runtktests.py", line 65, in get_tests for module in get_tests_modules(gui=gui, packages=packages): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/tkinter/test/runtktests.py", line 50, in get_tests_modules "tkinter.test") File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/__init__.py", line 136, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 781, in _gcd_import _gcd_import(parent) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 789, in _gcd_import loader.load_module(name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 309, in decorated return fxn(self, module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 385, in load_module return self._load_module(module) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 336, in _load_module code_object = self.get_code(module.__name__) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 423, in get_code code_object = super().get_code(fullname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 350, in get_code source = self.get_data(source_path) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/importlib/_bootstrap.py", line 485, in get_data return _fileio._FileIO(path, 'r').read() NameError: global name '_fileio' is not defined ====================================================================== ERROR: test_chunked (test.test_urllib2_localnet.TestUrlopen) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_urllib2_localnet.py", line 392, in test_chunked data = self.urlopen("http://localhost:%s/" % handler.port) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_urllib2_localnet.py", line 348, in urlopen l.extend(f.readlines(200)) ValueError: I/O operation on closed file. ====================================================================== ERROR: test_readlines (test.test_urllibnet.urlopenNetworkTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_urllibnet.py", line 78, in test_readlines self.assert_(isinstance(open_url.readlines(), list), ValueError: I/O operation on closed file. make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Mar 4 02:02:54 2009 From: python-checkins at python.org (brett.cannon) Date: Wed, 4 Mar 2009 02:02:54 +0100 (CET) Subject: [Python-checkins] r70154 - python/branches/py3k/Lib/importlib/test/test_api.py Message-ID: <20090304010254.E7E561E400C@bag.python.org> Author: brett.cannon Date: Wed Mar 4 02:02:54 2009 New Revision: 70154 Log: Add a test for importlib.import_module. Modified: python/branches/py3k/Lib/importlib/test/test_api.py Modified: python/branches/py3k/Lib/importlib/test/test_api.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/test_api.py (original) +++ python/branches/py3k/Lib/importlib/test/test_api.py Wed Mar 4 02:02:54 2009 @@ -26,7 +26,7 @@ module = importlib.import_module(name) self.assertEqual(module.__name__, name) - def test_relative_package_import(self): + def test_shallow_relative_package_import(self): # Test importing a module from a package through a relatve import. pkg_name = 'pkg' pkg_long_name = '{0}.__init__'.format(pkg_name) @@ -39,6 +39,15 @@ module = importlib.import_module(relative_name, pkg_name) self.assertEqual(module.__name__, absolute_name) + def test_deep_relative_package_import(self): + modules = ['a.__init__', 'a.b.__init__', 'a.c'] + with util.mock_modules(*modules) as mock: + with util.import_state(meta_path=[mock]): + importlib.import_module('a') + importlib.import_module('a.b') + module = importlib.import_module('..c', 'a.b') + self.assertEqual(module.__name__, 'a.c') + def test_absolute_import_with_package(self): # Test importing a module from a package with an absolute name with # the 'package' argument given. From buildbot at python.org Wed Mar 4 02:03:40 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Mar 2009 01:03:40 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 2.6 Message-ID: <20090304010341.161091E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%202.6/builds/154 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From brett at python.org Wed Mar 4 02:04:43 2009 From: brett at python.org (Brett Cannon) Date: Tue, 3 Mar 2009 17:04:43 -0800 Subject: [Python-checkins] r70099 - in python/branches/py3k: Doc/library/importlib.rstLib/importlib/NOTES Lib/importlib/test/test_util.py Lib/importlib/util.py In-Reply-To: References: <20090302143826.8BC691E4002@bag.python.org> Message-ID: On Mon, Mar 2, 2009 at 07:06, Antoine Pitrou wrote: > writes: > > > > Log: > > Expose importlib.util.set___package__. > > I'm not sure there's an underscore run-length restriction in PEP8, but what > about simply naming it set_package ? :-) It's more descriptive. =) I don't know, I have a slight worry someone will misunderstand what the decorator does if I just say 'set_package'. Anyone else have an opinion? -Brett -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Wed Mar 4 02:06:25 2009 From: python-checkins at python.org (brett.cannon) Date: Wed, 4 Mar 2009 02:06:25 +0100 (CET) Subject: [Python-checkins] r70155 - python/branches/py3k Message-ID: <20090304010625.3AC5D1E400C@bag.python.org> Author: brett.cannon Date: Wed Mar 4 02:06:24 2009 New Revision: 70155 Log: Blocked revisions 70153 via svnmerge ........ r70153 | brett.cannon | 2009-03-03 17:00:53 -0800 (Tue, 03 Mar 2009) | 4 lines Fix some more bugs caused by the backport from 3.x for importlib. Do a more exact copy of the final 3.x code to resolve bugs and add appropriate tests. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Wed Mar 4 02:10:09 2009 From: python-checkins at python.org (brett.cannon) Date: Wed, 4 Mar 2009 02:10:09 +0100 (CET) Subject: [Python-checkins] r70156 - python/branches/py3k/Lib/importlib/_bootstrap.py Message-ID: <20090304011009.74DF11E4002@bag.python.org> Author: brett.cannon Date: Wed Mar 4 02:10:09 2009 New Revision: 70156 Log: Move importlib over to _io. Modified: python/branches/py3k/Lib/importlib/_bootstrap.py Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Wed Mar 4 02:10:09 2009 @@ -7,8 +7,8 @@ """ -# Injected modules are '_warnings', 'imp', 'sys', 'marshal', 'errno', and '_os' -# (a.k.a. 'posix', 'nt' or 'os2'). +# Injected modules are '_warnings', 'imp', 'sys', 'marshal', 'errno', '_io', +# and '_os' (a.k.a. 'posix', 'nt' or 'os2'). # Injected attribute is path_sep. # # When editing this code be aware that code executed at import time CANNOT @@ -473,7 +473,7 @@ if source_path is None: return None import tokenize - with closing(_io.FileIO(source_path, 'r')) as file: + with closing(_io.FileIO(source_path, 'r')) as file: # Assuming bytes. encoding, lines = tokenize.detect_encoding(file.readline) # XXX Will fail when passed to compile() if the encoding is # anything other than UTF-8. @@ -482,7 +482,7 @@ def get_data(self, path): """Return the data from path as raw bytes.""" - return _fileio._FileIO(path, 'r').read() + return _io.FileIO(path, 'r').read() # Assuming bytes. @check_name def is_package(self, fullname): @@ -527,7 +527,7 @@ bytecode_path = self.bytecode_path(name) if not bytecode_path: bytecode_path = self._base_path + suffix_list(imp.PY_COMPILED)[0] - file = _io.FileIO(bytecode_path, 'w') + file = _io.FileIO(bytecode_path, 'w') # Assuming bytes. try: with closing(file) as bytecode_file: bytecode_file.write(data) From buildbot at python.org Wed Mar 4 02:14:08 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Mar 2009 01:14:08 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090304011408.670E41E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/192 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_distutils test_posix ====================================================================== FAIL: test_get_python_inc (distutils.tests.test_sysconfig.SysconfigTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/distutils/tests/test_sysconfig.py", line 45, in test_get_python_inc self.assert_(os.path.isdir(inc_dir), inc_dir) AssertionError: /home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/Include ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From buildbot at python.org Wed Mar 4 02:34:51 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Mar 2009 01:34:51 +0000 Subject: [Python-checkins] buildbot failure in OS X x86 trunk Message-ID: <20090304013451.DA7091E4002@bag.python.org> The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/210 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_sqlite make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Mar 4 02:52:11 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Wed, 4 Mar 2009 02:52:11 +0100 (CET) Subject: [Python-checkins] r70157 - python/branches/py3k/Python/import.c Message-ID: <20090304015211.3E7E31E4002@bag.python.org> Author: hirokazu.yamamoto Date: Wed Mar 4 02:52:10 2009 New Revision: 70157 Log: Issue #5273: Fixed import failure on unicode path. (especially on windows) Modified: python/branches/py3k/Python/import.c Modified: python/branches/py3k/Python/import.c ============================================================================== --- python/branches/py3k/Python/import.c (original) +++ python/branches/py3k/Python/import.c Wed Mar 4 02:52:10 2009 @@ -990,13 +990,15 @@ { PyObject *oldname, *newname; - if (!PyUnicode_CompareWithASCIIString(co->co_filename, pathname)) - return 0; - - newname = PyUnicode_FromString(pathname); + newname = PyUnicode_DecodeFSDefault(pathname); if (newname == NULL) return -1; + if (!PyUnicode_Compare(co->co_filename, newname)) { + Py_DECREF(newname); + return 0; + } + oldname = co->co_filename; Py_INCREF(oldname); update_code_filenames(co, oldname, newname); From python-checkins at python.org Wed Mar 4 02:58:09 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Wed, 4 Mar 2009 02:58:09 +0100 (CET) Subject: [Python-checkins] r70158 - in python/branches/release30-maint: Python/import.c Message-ID: <20090304015809.840251E4002@bag.python.org> Author: hirokazu.yamamoto Date: Wed Mar 4 02:58:09 2009 New Revision: 70158 Log: Merged revisions 70157 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70157 | hirokazu.yamamoto | 2009-03-04 10:52:10 +0900 | 1 line Issue #5273: Fixed import failure on unicode path. (especially on windows) ........ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Python/import.c Modified: python/branches/release30-maint/Python/import.c ============================================================================== --- python/branches/release30-maint/Python/import.c (original) +++ python/branches/release30-maint/Python/import.c Wed Mar 4 02:58:09 2009 @@ -988,13 +988,15 @@ { PyObject *oldname, *newname; - if (!PyUnicode_CompareWithASCIIString(co->co_filename, pathname)) - return 0; - - newname = PyUnicode_FromString(pathname); + newname = PyUnicode_DecodeFSDefault(pathname); if (newname == NULL) return -1; + if (!PyUnicode_Compare(co->co_filename, newname)) { + Py_DECREF(newname); + return 0; + } + oldname = co->co_filename; Py_INCREF(oldname); update_code_filenames(co, oldname, newname); From buildbot at python.org Wed Mar 4 03:04:17 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Mar 2009 02:04:17 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090304020417.D74A01E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/705 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_poplib.py", line 131, in run asyncore.loop(timeout=0.1, count=1) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 204, in loop poll_fun(timeout, map) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 141, in poll read(obj) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 78, in read obj.handle_error() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 74, in read obj.handle_read_event() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 413, in handle_read_event self.handle_read() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_ssl.py", line 408, in handle_read self.send(data.lower()) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 519, in send self.initiate_send() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 506, in initiate_send num_sent = dispatcher.send(self, self.out_buffer[:512]) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 349, in send result = self.socket.send(data) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/socket.py", line 165, in _dummy raise error(EBADF, 'Bad file descriptor') error: [Errno 9] Bad file descriptor sincerely, -The Buildbot From python-checkins at python.org Wed Mar 4 03:27:13 2009 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 4 Mar 2009 03:27:13 +0100 (CET) Subject: [Python-checkins] r70159 - python/branches/py3k/PC/VS8.0/pythoncore.vcproj Message-ID: <20090304022713.AA6881E4002@bag.python.org> Author: raymond.hettinger Date: Wed Mar 4 03:27:13 2009 New Revision: 70159 Log: Update project file. Modified: python/branches/py3k/PC/VS8.0/pythoncore.vcproj Modified: python/branches/py3k/PC/VS8.0/pythoncore.vcproj ============================================================================== --- python/branches/py3k/PC/VS8.0/pythoncore.vcproj (original) +++ python/branches/py3k/PC/VS8.0/pythoncore.vcproj Wed Mar 4 03:27:13 2009 @@ -994,6 +994,22 @@ RelativePath="..\..\Modules\_bytesio.c" > + + + + + + + + From buildbot at python.org Wed Mar 4 03:48:34 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Mar 2009 02:48:34 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090304024834.61E821E400C@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/362 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,hirokazu.yamamoto,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 3 tests failed: test_float test_fractions test_itertools ====================================================================== ERROR: test_floatasratio (test.test_float.GeneralFloatCases) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_float.py", line 103, in test_floatasratio self.assertEqual(R(0, 1), File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testApproximateCos1 (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 393, in testApproximateCos1 x = F(1) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testApproximatePi (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 380, in testApproximatePi three = F(3) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testArithmetic (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 228, in testArithmetic self.assertEquals(F(1, 2), F(1, 10) + F(2, 5)) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testBigComplexComparisons (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 349, in testBigComplexComparisons self.assertFalse(F(10**23) == complex(10**23)) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testBigFloatComparisons (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 340, in testBigFloatComparisons self.assertFalse(F(10**23) == float(10**23)) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testComparisons (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 307, in testComparisons self.assertTrue(F(1, 2) < F(2, 3)) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testConversions (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 197, in testConversions self.assertTypedEquals(-1, math.trunc(F(-11, 10))) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testFromDecimal (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 164, in testFromDecimal self.assertRaises(TypeError, F.from_decimal, 3+4j) AttributeError: type object 'Fraction' has no attribute 'from_decimal' ====================================================================== ERROR: testFromFloat (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 138, in testFromFloat self.assertEquals((10, 1), _components(F.from_float(10))) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 112, in from_float return cls(f) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testFromString (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 72, in testFromString self.assertEquals((5, 1), _components(F("5"))) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testHash (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 373, in testHash self.assertEquals(hash(2.5), hash(F(5, 2))) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testImmutable (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 121, in testImmutable r = F(7, 3) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testInit (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 52, in testInit self.assertEquals((0, 1), _components(F())) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testLimitDenominator (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 187, in testLimitDenominator rpi = F('3.1415926535897932') File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testMixedArithmetic (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 243, in testMixedArithmetic self.assertTypedEquals(F(11, 10), F(1, 10) + 1) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testMixedEqual (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 354, in testMixedEqual self.assertTrue(0.5 == F(1, 2)) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testMixedLess (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 318, in testMixedLess self.assertTrue(2 < F(5, 2)) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testMixedLessEqual (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 329, in testMixedLessEqual self.assertTrue(0.5 <= F(1, 2)) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testMixingWithDecimal (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 303, in testMixingWithDecimal operator.add, F(3,11), Decimal('3.1415926')) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testRound (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 220, in testRound self.assertTypedEquals(F(-200), round(F(-150), -2)) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: testStringification (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 364, in testStringification self.assertEquals("Fraction(7, 3)", repr(F(7, 3))) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: test_copy_deepcopy_pickle (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 405, in test_copy_deepcopy_pickle r = F(13, 7) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: test_slots (test.test_fractions.FractionTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_fractions.py", line 412, in test_slots r = F(13, 7) File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator ====================================================================== ERROR: test_count_with_stride (test.test_itertools.TestBasicOps) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test_itertools.py", line 369, in test_count_with_stride self.assertEqual(take(3, count(Fraction(2,3), Fraction(1,7))), File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/fractions.py", line 63, in __new__ self = super(Fraction, cls).__new__(cls) TypeError: Can't instantiate abstract class Fraction with abstract methods __abs__, __add__, __ceil__, __eq__, __floor__, __floordiv__, __le__, __lt__, __mod__, __mul__, __neg__, __pos__, __pow__, __radd__, __rfloordiv__, __rmod__, __rmul__, __round__, __rpow__, __rtruediv__, __truediv__, __trunc__, denominator, numerator make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Mar 4 05:09:32 2009 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 4 Mar 2009 05:09:32 +0100 (CET) Subject: [Python-checkins] r70160 - python/branches/py3k Message-ID: <20090304040932.A5DB11E404C@bag.python.org> Author: benjamin.peterson Date: Wed Mar 4 05:09:32 2009 New Revision: 70160 Log: Removed merge tracking for "svnmerge" for svn+ssh://pythondev at svn.python.org/python/branches/io-c Modified: python/branches/py3k/ (props changed) From buildbot at python.org Wed Mar 4 05:27:33 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Mar 2009 04:27:33 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090304042733.DF3511E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/406 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,brett.cannon,hirokazu.yamamoto,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 4 tests failed: test_fileio test_io test_urllib2_localnet test_urllibnet ====================================================================== ERROR: testBytesOpen (test.test_fileio.OtherFileTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ppc/build/Lib/test/test_fileio.py", line 186, in testBytesOpen f = _FileIO(fn, "w") SystemError: null argument to internal routine ====================================================================== ERROR: testInvalidFd (test.test_fileio.OtherFileTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ppc/build/Lib/test/test_fileio.py", line 196, in testInvalidFd self.assertRaises(ValueError, _fileio._FileIO, -10) NameError: global name '_fileio' is not defined ====================================================================== FAIL: test_append_mode_tell (test.test_io.CIOTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ppc/build/Lib/test/test_io.py", line 379, in test_append_mode_tell self.assertEqual(f.tell(), 3) AssertionError: 0 != 3 ====================================================================== FAIL: test_append_mode_tell (test.test_io.PyIOTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ppc/build/Lib/test/test_io.py", line 379, in test_append_mode_tell self.assertEqual(f.tell(), 3) AssertionError: 0 != 3 ====================================================================== ERROR: test_chunked (test.test_urllib2_localnet.TestUrlopen) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ppc/build/Lib/test/test_urllib2_localnet.py", line 392, in test_chunked data = self.urlopen("http://localhost:%s/" % handler.port) File "/home/pybot/buildarea/3.x.klose-debian-ppc/build/Lib/test/test_urllib2_localnet.py", line 348, in urlopen l.extend(f.readlines(200)) ValueError: I/O operation on closed file. ====================================================================== ERROR: test_readlines (test.test_urllibnet.urlopenNetworkTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ppc/build/Lib/test/test_urllibnet.py", line 78, in test_readlines self.assert_(isinstance(open_url.readlines(), list), ValueError: I/O operation on closed file. make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Wed Mar 4 05:47:29 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Mar 2009 04:47:29 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090304044729.D02D81E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/378 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,brett.cannon,hirokazu.yamamoto,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Wed Mar 4 12:14:02 2009 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 4 Mar 2009 12:14:02 +0100 (CET) Subject: [Python-checkins] r70161 - in python/branches/py3k: Lib/test/test_fileio.py Modules/_fileio.c Message-ID: <20090304111402.974651E4002@bag.python.org> Author: antoine.pitrou Date: Wed Mar 4 12:14:01 2009 New Revision: 70161 Log: Fix failures introduced by buggy merge (1) Modified: python/branches/py3k/Lib/test/test_fileio.py python/branches/py3k/Modules/_fileio.c Modified: python/branches/py3k/Lib/test/test_fileio.py ============================================================================== --- python/branches/py3k/Lib/test/test_fileio.py (original) +++ python/branches/py3k/Lib/test/test_fileio.py Wed Mar 4 12:14:01 2009 @@ -193,8 +193,8 @@ os.unlink(TESTFN) def testInvalidFd(self): - self.assertRaises(ValueError, _fileio._FileIO, -10) - self.assertRaises(OSError, _fileio._FileIO, make_bad_fd()) + self.assertRaises(ValueError, _FileIO, -10) + self.assertRaises(OSError, _FileIO, make_bad_fd()) def testBadModeArgument(self): # verify that we get a sensible error message for bad mode argument Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Wed Mar 4 12:14:01 2009 @@ -57,13 +57,15 @@ #define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type)) - int _PyFileIO_closed(PyObject *self) { return ((PyFileIOObject *)self)->fd < 0; } +static PyObject * +portable_lseek(int fd, PyObject *posobj, int whence); + /* Returns 0 on success, -1 with exception set on failure. */ static int internal_close(PyFileIOObject *self) @@ -156,7 +158,7 @@ { #if defined(HAVE_FSTAT) struct stat buf; - if (fstat(fd, &buf) < 0 && errno == EBADF) { + if (!_PyVerify_fd(fd) || (fstat(fd, &buf) < 0 && errno == EBADF)) { PyObject *exc; char *msg = strerror(EBADF); exc = PyObject_CallFunction(PyExc_OSError, "(is)", @@ -176,7 +178,7 @@ PyFileIOObject *self = (PyFileIOObject *) oself; static char *kwlist[] = {"file", "mode", "closefd", NULL}; const char *name = NULL; - PyObject *nameobj; + PyObject *nameobj, *stringobj = NULL; char *mode = "r"; char *s; #ifdef MS_WINDOWS @@ -226,26 +228,27 @@ if (fd < 0) { if (PyBytes_Check(nameobj) || PyByteArray_Check(nameobj)) { - if (PyObject_AsCharBuffer(nameobj, &name, NULL) < 0) + Py_ssize_t namelen; + if (PyObject_AsCharBuffer(nameobj, &name, &namelen) < 0) return -1; } else { - PyObject *s; PyObject *u = PyUnicode_FromObject(nameobj); if (u == NULL) return -1; - s = PyUnicode_AsEncodedString( + stringobj = PyUnicode_AsEncodedString( u, Py_FileSystemDefaultEncoding, NULL); Py_DECREF(u); - if (s == NULL) + if (stringobj == NULL) return -1; - if (!PyBytes_Check(s)) { + if (!PyBytes_Check(stringobj)) { PyErr_SetString(PyExc_TypeError, "encoder failed to return bytes"); + goto error; } - name = PyBytes_AS_STRING(s); + name = PyBytes_AS_STRING(stringobj); } } @@ -312,10 +315,10 @@ #endif if (fd >= 0) { - self->fd = fd; - self->closefd = closefd; if (check_fd(fd)) goto error; + self->fd = fd; + self->closefd = closefd; } else { self->closefd = 1; @@ -350,12 +353,23 @@ if (PyObject_SetAttrString((PyObject *)self, "name", nameobj) < 0) goto error; + if (append) { + /* For consistent behaviour, we explicitly seek to the + end of file (otherwise, it might be done only on the + first write()). */ + PyObject *pos = portable_lseek(self->fd, NULL, 2); + if (pos == NULL) + goto error; + Py_DECREF(pos); + } + goto done; error: ret = -1; done: + Py_CLEAR(stringobj); return ret; } @@ -942,14 +956,14 @@ PyTypeObject PyFileIO_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "FileIO", + "_io.FileIO", sizeof(PyFileIOObject), 0, (destructor)fileio_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc)fileio_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ From python-checkins at python.org Wed Mar 4 12:18:53 2009 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 4 Mar 2009 12:18:53 +0100 (CET) Subject: [Python-checkins] r70162 - in python/branches/py3k: Lib/io.py Modules/_iobase.c Message-ID: <20090304111853.21C1B1E4033@bag.python.org> Author: antoine.pitrou Date: Wed Mar 4 12:18:52 2009 New Revision: 70162 Log: Fix failures introduced by buggy merge (2) Modified: python/branches/py3k/Lib/io.py python/branches/py3k/Modules/_iobase.c Modified: python/branches/py3k/Lib/io.py ============================================================================== --- python/branches/py3k/Lib/io.py (original) +++ python/branches/py3k/Lib/io.py Wed Mar 4 12:18:52 2009 @@ -47,7 +47,7 @@ "Mike Verdone , " "Mark Russell , " "Antoine Pitrou , " - "Amaury Forgeotdarc ") + "Amaury Forgeot d'Arc ") __all__ = ["BlockingIOError", "open", "IOBase", "RawIOBase", "FileIO", "BytesIO", "StringIO", "BufferedIOBase", Modified: python/branches/py3k/Modules/_iobase.c ============================================================================== --- python/branches/py3k/Modules/_iobase.c (original) +++ python/branches/py3k/Modules/_iobase.c Wed Mar 4 12:18:52 2009 @@ -459,9 +459,6 @@ return NULL; } - if (_PyIOBase_checkClosed(self, Py_True) == NULL) - return NULL; - if (PyObject_HasAttrString(self, "peek")) has_peek = 1; From ncoghlan at gmail.com Wed Mar 4 12:58:17 2009 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 04 Mar 2009 21:58:17 +1000 Subject: [Python-checkins] r70099 - in python/branches/py3k: Doc/library/importlib.rstLib/importlib/NOTES Lib/importlib/test/test_util.py Lib/importlib/util.py In-Reply-To: References: <20090302143826.8BC691E4002@bag.python.org> Message-ID: <49AE6CD9.9080201@gmail.com> Brett Cannon wrote: > > > On Mon, Mar 2, 2009 at 07:06, Antoine Pitrou > wrote: > > writes: > > > > Log: > > Expose importlib.util.set___package__. > > I'm not sure there's an underscore run-length restriction in PEP8, > but what > about simply naming it set_package ? :-) > > > It's more descriptive. =) I don't know, I have a slight worry someone > will misunderstand what the decorator does if I just say 'set_package'. > Anyone else have an opinion? I'd say lose the extra underscores - anyone that can figure out the import system well enough to write their own module loader isn't going to be confused about what @set_package does just because they only have to type 1 underscore instead of 4 :) Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- From python-checkins at python.org Wed Mar 4 17:07:01 2009 From: python-checkins at python.org (brett.cannon) Date: Wed, 4 Mar 2009 17:07:01 +0100 (CET) Subject: [Python-checkins] r70163 - in python/branches/py3k: Doc/library/importlib.rst Lib/importlib/_bootstrap.py Lib/importlib/test/test_util.py Lib/importlib/util.py Message-ID: <20090304160701.1F4B31E4002@bag.python.org> Author: brett.cannon Date: Wed Mar 4 17:07:00 2009 New Revision: 70163 Log: Rename importlib.util.set___package__ to set_package. Modified: python/branches/py3k/Doc/library/importlib.rst python/branches/py3k/Lib/importlib/_bootstrap.py python/branches/py3k/Lib/importlib/test/test_util.py python/branches/py3k/Lib/importlib/util.py Modified: python/branches/py3k/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k/Doc/library/importlib.rst (original) +++ python/branches/py3k/Doc/library/importlib.rst Wed Mar 4 17:07:00 2009 @@ -185,7 +185,7 @@ loader should initialize as specified by :pep:`302`. -.. function:: set___package__(method) +.. function:: set_package(method) A :term:`decorator` for a :term:`loader` to set the :attr:`__package__` attribute on the module returned by the loader. If :attr:`__package__` is Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Wed Mar 4 17:07:00 2009 @@ -97,7 +97,7 @@ new.__dict__.update(old.__dict__) -def set___package__(fxn): +def set_package(fxn): """Set __package__ on the returned module.""" def wrapper(*args, **kwargs): module = fxn(*args, **kwargs) @@ -131,7 +131,7 @@ return cls if imp.is_builtin(fullname) else None @classmethod - @set___package__ + @set_package def load_module(cls, fullname): """Load a built-in module.""" if fullname not in sys.builtin_module_names: @@ -160,7 +160,7 @@ return cls if imp.is_frozen(fullname) else None @classmethod - @set___package__ + @set_package def load_module(cls, fullname): """Load a frozen module.""" if cls.find_module(fullname) is None: @@ -248,7 +248,7 @@ raise ValueError("extension modules cannot be packages") @check_name - @set___package__ + @set_package def load_module(self, fullname): """Load an extension module.""" is_reload = fullname in sys.modules Modified: python/branches/py3k/Lib/importlib/test/test_util.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/test_util.py (original) +++ python/branches/py3k/Lib/importlib/test/test_util.py Wed Mar 4 17:07:00 2009 @@ -63,13 +63,13 @@ class SetPackageTests(unittest.TestCase): - """Tests for importlib.util.set___package__.""" + """Tests for importlib.util.set_package.""" def verify(self, module, expect): """Verify the module has the expected value for __package__ after - passing through set___package__.""" + passing through set_package.""" fxn = lambda: module - wrapped = util.set___package__(fxn) + wrapped = util.set_package(fxn) wrapped() self.assert_(hasattr(module, '__package__')) self.assertEqual(expect, module.__package__) Modified: python/branches/py3k/Lib/importlib/util.py ============================================================================== --- python/branches/py3k/Lib/importlib/util.py (original) +++ python/branches/py3k/Lib/importlib/util.py Wed Mar 4 17:07:00 2009 @@ -1,3 +1,3 @@ """Utility code for constructing importers, etc.""" from ._bootstrap import module_for_loader -from ._bootstrap import set___package__ +from ._bootstrap import set_package From brett at python.org Wed Mar 4 17:07:28 2009 From: brett at python.org (Brett Cannon) Date: Wed, 4 Mar 2009 08:07:28 -0800 Subject: [Python-checkins] r70099 - in python/branches/py3k: Doc/library/importlib.rstLib/importlib/NOTES Lib/importlib/test/test_util.py Lib/importlib/util.py In-Reply-To: <49AE6CD9.9080201@gmail.com> References: <20090302143826.8BC691E4002@bag.python.org> <49AE6CD9.9080201@gmail.com> Message-ID: On Wed, Mar 4, 2009 at 03:58, Nick Coghlan wrote: > Brett Cannon wrote: > > > > > > On Mon, Mar 2, 2009 at 07:06, Antoine Pitrou > > wrote: > > > > writes: > > > > > > Log: > > > Expose importlib.util.set___package__. > > > > I'm not sure there's an underscore run-length restriction in PEP8, > > but what > > about simply naming it set_package ? :-) > > > > > > It's more descriptive. =) I don't know, I have a slight worry someone > > will misunderstand what the decorator does if I just say 'set_package'. > > Anyone else have an opinion? > > I'd say lose the extra underscores - anyone that can figure out the > import system well enough to write their own module loader isn't going > to be confused about what @set_package does just because they only have > to type 1 underscore instead of 4 :) > OK, you two convinced me: changed in 70163. -Brett -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Wed Mar 4 17:20:31 2009 From: python-checkins at python.org (brett.cannon) Date: Wed, 4 Mar 2009 17:20:31 +0100 (CET) Subject: [Python-checkins] r70164 - sandbox/trunk/importlib/README Message-ID: <20090304162031.3891F1E4002@bag.python.org> Author: brett.cannon Date: Wed Mar 4 17:20:30 2009 New Revision: 70164 Log: Fix a typo. Modified: sandbox/trunk/importlib/README Modified: sandbox/trunk/importlib/README ============================================================================== --- sandbox/trunk/importlib/README (original) +++ sandbox/trunk/importlib/README Wed Mar 4 17:20:30 2009 @@ -6,6 +6,6 @@ version of Python prior to 2.7 or in 3.0 have the function readily available. The code in no way deviates from what can be found in the 2.7 trunk. -For documentaition, see the `importlib docs`_ for Python 2.7. +For documentation, see the `importlib docs`_ for Python 2.7. .. _importlib docs: http://docs.python.org/dev/library/importlib.html From python-checkins at python.org Wed Mar 4 17:22:49 2009 From: python-checkins at python.org (brett.cannon) Date: Wed, 4 Mar 2009 17:22:49 +0100 (CET) Subject: [Python-checkins] r70165 - sandbox/trunk/importlib/setup.py Message-ID: <20090304162249.012951E4076@bag.python.org> Author: brett.cannon Date: Wed Mar 4 17:22:48 2009 New Revision: 70165 Log: Bump the version number to cover bug fixes. Modified: sandbox/trunk/importlib/setup.py Modified: sandbox/trunk/importlib/setup.py ============================================================================== --- sandbox/trunk/importlib/setup.py (original) +++ sandbox/trunk/importlib/setup.py Wed Mar 4 17:22:48 2009 @@ -24,7 +24,7 @@ setup( name='importlib', - version='1.0', + version='1.0.1', description='Backport of importlib.import_module() from Python 2.7', long_description=detailed_description, author='Brett Cannon', From python-checkins at python.org Wed Mar 4 19:24:42 2009 From: python-checkins at python.org (georg.brandl) Date: Wed, 4 Mar 2009 19:24:42 +0100 (CET) Subject: [Python-checkins] r70166 - python/trunk/Doc/library/string.rst Message-ID: <20090304182442.240551E4002@bag.python.org> Author: georg.brandl Date: Wed Mar 4 19:24:41 2009 New Revision: 70166 Log: Remove obsolete stuff from string module docs. Modified: python/trunk/Doc/library/string.rst Modified: python/trunk/Doc/library/string.rst ============================================================================== --- python/trunk/Doc/library/string.rst (original) +++ python/trunk/Doc/library/string.rst Wed Mar 4 19:24:41 2009 @@ -62,10 +62,9 @@ .. data:: lowercase A string containing all the characters that are considered lowercase letters. - On most systems this is the string ``'abcdefghijklmnopqrstuvwxyz'``. Do not - change its definition --- the effect on the routines :func:`upper` and - :func:`swapcase` is undefined. The specific value is locale-dependent, and will - be updated when :func:`locale.setlocale` is called. + On most systems this is the string ``'abcdefghijklmnopqrstuvwxyz'``. The + specific value is locale-dependent, and will be updated when + :func:`locale.setlocale` is called. .. data:: octdigits @@ -89,18 +88,16 @@ .. data:: uppercase A string containing all the characters that are considered uppercase letters. - On most systems this is the string ``'ABCDEFGHIJKLMNOPQRSTUVWXYZ'``. Do not - change its definition --- the effect on the routines :func:`lower` and - :func:`swapcase` is undefined. The specific value is locale-dependent, and will - be updated when :func:`locale.setlocale` is called. + On most systems this is the string ``'ABCDEFGHIJKLMNOPQRSTUVWXYZ'``. The + specific value is locale-dependent, and will be updated when + :func:`locale.setlocale` is called. .. data:: whitespace A string containing all characters that are considered whitespace. On most systems this includes the characters space, tab, linefeed, return, formfeed, and - vertical tab. Do not change its definition --- the effect on the routines - :func:`strip` and :func:`split` is undefined. + vertical tab. .. _new-string-formatting: @@ -599,7 +596,7 @@ Don't use strings derived from :const:`lowercase` and :const:`uppercase` as arguments; in some locales, these don't have the same length. For case - conversions, always use :func:`lower` and :func:`upper`. + conversions, always use :meth:`str.lower` and :meth:`str.upper`. Deprecated string functions From python-checkins at python.org Wed Mar 4 22:07:20 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 22:07:20 +0100 (CET) Subject: [Python-checkins] r70167 - in python/trunk/Mac/BuildScript: build-installer.py scripts/postflight.patch-profile Message-ID: <20090304210720.42B631E4002@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 22:07:19 2009 New Revision: 70167 Log: Fix issue 5224. Modified: python/trunk/Mac/BuildScript/build-installer.py python/trunk/Mac/BuildScript/scripts/postflight.patch-profile Modified: python/trunk/Mac/BuildScript/build-installer.py ============================================================================== --- python/trunk/Mac/BuildScript/build-installer.py (original) +++ python/trunk/Mac/BuildScript/build-installer.py Wed Mar 4 22:07:19 2009 @@ -1031,8 +1031,7 @@ buildPythonDocs() fn = os.path.join(WORKDIR, "_root", "Applications", "Python %s"%(getVersion(),), "Update Shell Profile.command") - patchFile("scripts/postflight.patch-profile", fn) - os.chmod(fn, 0755) + patchScript("scripts/postflight.patch-profile", fn) folder = os.path.join(WORKDIR, "_root", "Applications", "Python %s"%( getVersion(),)) Modified: python/trunk/Mac/BuildScript/scripts/postflight.patch-profile ============================================================================== --- python/trunk/Mac/BuildScript/scripts/postflight.patch-profile (original) +++ python/trunk/Mac/BuildScript/scripts/postflight.patch-profile Wed Mar 4 22:07:19 2009 @@ -5,8 +5,8 @@ echo "These changes will be effective only in shell windows that you open" echo "after running this script." -PYVER=2.7 -PYTHON_ROOT="/Library/Frameworks/Python.framework/Versions/Current" +PYVER="@PYVER@" +PYTHON_ROOT="/Library/Frameworks/Python.framework/Versions/@PYVER@" if [ `id -ur` = 0 ]; then # Run from the installer, do some trickery to fetch the information From python-checkins at python.org Wed Mar 4 22:10:17 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 22:10:17 +0100 (CET) Subject: [Python-checkins] r70168 - in python/branches/release26-maint: Mac/BuildScript/build-installer.py Mac/BuildScript/scripts/postflight.patch-profile Message-ID: <20090304211017.4A7461E4017@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 22:10:17 2009 New Revision: 70168 Log: Merged revisions 70167 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70167 | ronald.oussoren | 2009-03-04 22:07:19 +0100 (Wed, 04 Mar 2009) | 2 lines Fix issue 5224. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Mac/BuildScript/build-installer.py python/branches/release26-maint/Mac/BuildScript/scripts/postflight.patch-profile Modified: python/branches/release26-maint/Mac/BuildScript/build-installer.py ============================================================================== --- python/branches/release26-maint/Mac/BuildScript/build-installer.py (original) +++ python/branches/release26-maint/Mac/BuildScript/build-installer.py Wed Mar 4 22:10:17 2009 @@ -1031,8 +1031,7 @@ buildPythonDocs() fn = os.path.join(WORKDIR, "_root", "Applications", "Python %s"%(getVersion(),), "Update Shell Profile.command") - patchFile("scripts/postflight.patch-profile", fn) - os.chmod(fn, 0755) + patchScript("scripts/postflight.patch-profile", fn) folder = os.path.join(WORKDIR, "_root", "Applications", "Python %s"%( getVersion(),)) Modified: python/branches/release26-maint/Mac/BuildScript/scripts/postflight.patch-profile ============================================================================== --- python/branches/release26-maint/Mac/BuildScript/scripts/postflight.patch-profile (original) +++ python/branches/release26-maint/Mac/BuildScript/scripts/postflight.patch-profile Wed Mar 4 22:10:17 2009 @@ -5,8 +5,8 @@ echo "These changes will be effective only in shell windows that you open" echo "after running this script." -PYVER=2.6 -PYTHON_ROOT="/Library/Frameworks/Python.framework/Versions/Current" +PYVER="@PYVER@" +PYTHON_ROOT="/Library/Frameworks/Python.framework/Versions/@PYVER@" if [ `id -ur` = 0 ]; then # Run from the installer, do some trickery to fetch the information From python-checkins at python.org Wed Mar 4 22:12:17 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 22:12:17 +0100 (CET) Subject: [Python-checkins] r70169 - in python/trunk/Mac/BuildScript/resources: ReadMe.txt Welcome.rtf Message-ID: <20090304211217.EA61C1E4002@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 22:12:17 2009 New Revision: 70169 Log: Fix for issue 5226. Modified: python/trunk/Mac/BuildScript/resources/ReadMe.txt python/trunk/Mac/BuildScript/resources/Welcome.rtf Modified: python/trunk/Mac/BuildScript/resources/ReadMe.txt ============================================================================== --- python/trunk/Mac/BuildScript/resources/ReadMe.txt (original) +++ python/trunk/Mac/BuildScript/resources/ReadMe.txt Wed Mar 4 22:12:17 2009 @@ -14,10 +14,9 @@ MacPython consists of the Python programming language interpreter, plus a set of programs to allow easy -access to it for Mac users (an integrated development -environment, an applet builder), plus a set of pre-built -extension modules that open up specific Macintosh technologies -to Python programs (Carbon, AppleScript, Quicktime, more). +access to it for Mac users including an integrated development +environment, IDLE, plus a set of pre-built extension modules +that open up specific Macintosh technologies to Python programs. The installer puts the applications in "Python $VERSION" in your Applications folder, command-line tools in @@ -25,7 +24,7 @@ $PYTHONFRAMEWORKINSTALLDIR. More information on MacPython can be found at -http://www.cwi.nl/~jack/macpython and -http://pythonmac.org/. More information on -Python in general can be found at +http://www.python.org/download/mac/. + +More information on Python in general can be found at http://www.python.org. Modified: python/trunk/Mac/BuildScript/resources/Welcome.rtf ============================================================================== --- python/trunk/Mac/BuildScript/resources/Welcome.rtf (original) +++ python/trunk/Mac/BuildScript/resources/Welcome.rtf Wed Mar 4 22:12:17 2009 @@ -10,9 +10,9 @@ \f1\b Mac OS X $MACOSX_DEPLOYMENT_TARGET \f0\b0 .\ \ -MacPython consists of the Python programming language interpreter, plus a set of programs to allow easy access to it for Mac users (an integrated development environment, an applet builder), plus a set of pre-built extension modules that open up specific Macintosh technologies to Python programs (Carbon, AppleScript, Quicktime, more).\ +MacPython consists of the Python programming language interpreter, plus a set of programs to allow easy access to it for Mac users including an integrated development environment \b IDLE\b0 plus a set of pre-built extension modules that open up specific Macintosh technologies to Python programs.\ \ See the ReadMe file for more information.\ \ \ -This package will by default update your shell profile to ensure that this version of Python is on the search path of your shell. Please deselect the "Shell profile updater" package on the package customization screen if you want to avoid this modification. } \ No newline at end of file +This package will by default update your shell profile to ensure that this version of Python is on the search path of your shell. Please deselect the "Shell profile updater" package on the package customization screen if you want to avoid this modification. Double-click \b Update Shell Profile\b0 at any time to make $FULL_VERSION the default Python.} \ No newline at end of file From python-checkins at python.org Wed Mar 4 22:13:03 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 22:13:03 +0100 (CET) Subject: [Python-checkins] r70170 - in python/branches/release26-maint: Mac/BuildScript/resources/ReadMe.txt Mac/BuildScript/resources/Welcome.rtf Message-ID: <20090304211303.9611E1E4002@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 22:13:03 2009 New Revision: 70170 Log: Merged revisions 70169 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70169 | ronald.oussoren | 2009-03-04 22:12:17 +0100 (Wed, 04 Mar 2009) | 2 lines Fix for issue 5226. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Mac/BuildScript/resources/ReadMe.txt python/branches/release26-maint/Mac/BuildScript/resources/Welcome.rtf Modified: python/branches/release26-maint/Mac/BuildScript/resources/ReadMe.txt ============================================================================== --- python/branches/release26-maint/Mac/BuildScript/resources/ReadMe.txt (original) +++ python/branches/release26-maint/Mac/BuildScript/resources/ReadMe.txt Wed Mar 4 22:13:03 2009 @@ -14,10 +14,9 @@ MacPython consists of the Python programming language interpreter, plus a set of programs to allow easy -access to it for Mac users (an integrated development -environment, an applet builder), plus a set of pre-built -extension modules that open up specific Macintosh technologies -to Python programs (Carbon, AppleScript, Quicktime, more). +access to it for Mac users including an integrated development +environment, IDLE, plus a set of pre-built extension modules +that open up specific Macintosh technologies to Python programs. The installer puts the applications in "Python $VERSION" in your Applications folder, command-line tools in @@ -25,7 +24,7 @@ $PYTHONFRAMEWORKINSTALLDIR. More information on MacPython can be found at -http://www.cwi.nl/~jack/macpython and -http://pythonmac.org/. More information on -Python in general can be found at +http://www.python.org/download/mac/. + +More information on Python in general can be found at http://www.python.org. Modified: python/branches/release26-maint/Mac/BuildScript/resources/Welcome.rtf ============================================================================== --- python/branches/release26-maint/Mac/BuildScript/resources/Welcome.rtf (original) +++ python/branches/release26-maint/Mac/BuildScript/resources/Welcome.rtf Wed Mar 4 22:13:03 2009 @@ -10,9 +10,9 @@ \f1\b Mac OS X $MACOSX_DEPLOYMENT_TARGET \f0\b0 .\ \ -MacPython consists of the Python programming language interpreter, plus a set of programs to allow easy access to it for Mac users (an integrated development environment, an applet builder), plus a set of pre-built extension modules that open up specific Macintosh technologies to Python programs (Carbon, AppleScript, Quicktime, more).\ +MacPython consists of the Python programming language interpreter, plus a set of programs to allow easy access to it for Mac users including an integrated development environment \b IDLE\b0 plus a set of pre-built extension modules that open up specific Macintosh technologies to Python programs.\ \ See the ReadMe file for more information.\ \ \ -This package will by default update your shell profile to ensure that this version of Python is on the search path of your shell. Please deselect the "Shell profile updater" package on the package customization screen if you want to avoid this modification. } \ No newline at end of file +This package will by default update your shell profile to ensure that this version of Python is on the search path of your shell. Please deselect the "Shell profile updater" package on the package customization screen if you want to avoid this modification. Double-click \b Update Shell Profile\b0 at any time to make $FULL_VERSION the default Python.} \ No newline at end of file From python-checkins at python.org Wed Mar 4 22:18:17 2009 From: python-checkins at python.org (facundo.batista) Date: Wed, 4 Mar 2009 22:18:17 +0100 (CET) Subject: [Python-checkins] r70171 - python/trunk/Doc/library/struct.rst Message-ID: <20090304211817.B0BA51E4013@bag.python.org> Author: facundo.batista Date: Wed Mar 4 22:18:17 2009 New Revision: 70171 Log: Fixed a typo. Modified: python/trunk/Doc/library/struct.rst Modified: python/trunk/Doc/library/struct.rst ============================================================================== --- python/trunk/Doc/library/struct.rst (original) +++ python/trunk/Doc/library/struct.rst Wed Mar 4 22:18:17 2009 @@ -50,7 +50,7 @@ .. function:: unpack_from(fmt, buffer[,offset=0]) - Unpack the *buffer* according to tthe given format. The result is a tuple even + Unpack the *buffer* according to the given format. The result is a tuple even if it contains exactly one item. The *buffer* must contain at least the amount of data required by the format (``len(buffer[offset:])`` must be at least ``calcsize(fmt)``). From python-checkins at python.org Wed Mar 4 22:30:13 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 22:30:13 +0100 (CET) Subject: [Python-checkins] r70172 - python/trunk/setup.py Message-ID: <20090304213013.04BD81E4002@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 22:30:12 2009 New Revision: 70172 Log: Change framework search order when looking for Tcl/Tk on OSX. This is needed because the system linker looks in /Library/Framework before it looks in /System/Library frameworks. Without this patch _tkinter will be unusable when it is compiled on a system that has Tk 8.5 installed in /Library/Frameworks (and the Apple 8.4 install in /System/Library/Frameworks) Modified: python/trunk/setup.py Modified: python/trunk/setup.py ============================================================================== --- python/trunk/setup.py (original) +++ python/trunk/setup.py Wed Mar 4 22:30:12 2009 @@ -1443,8 +1443,8 @@ # different the UNIX search logic is not sharable. from os.path import join, exists framework_dirs = [ - '/System/Library/Frameworks/', '/Library/Frameworks', + '/System/Library/Frameworks/', join(os.getenv('HOME'), '/Library/Frameworks') ] From python-checkins at python.org Wed Mar 4 22:30:53 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 22:30:53 +0100 (CET) Subject: [Python-checkins] r70173 - in python/branches/release26-maint: setup.py Message-ID: <20090304213053.6965E1E4002@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 22:30:52 2009 New Revision: 70173 Log: Merged revisions 70172 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70172 | ronald.oussoren | 2009-03-04 22:30:12 +0100 (Wed, 04 Mar 2009) | 7 lines Change framework search order when looking for Tcl/Tk on OSX. This is needed because the system linker looks in /Library/Framework before it looks in /System/Library frameworks. Without this patch _tkinter will be unusable when it is compiled on a system that has Tk 8.5 installed in /Library/Frameworks (and the Apple 8.4 install in /System/Library/Frameworks) ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/setup.py Modified: python/branches/release26-maint/setup.py ============================================================================== --- python/branches/release26-maint/setup.py (original) +++ python/branches/release26-maint/setup.py Wed Mar 4 22:30:52 2009 @@ -1450,8 +1450,8 @@ # different the UNIX search logic is not sharable. from os.path import join, exists framework_dirs = [ - '/System/Library/Frameworks/', '/Library/Frameworks', + '/System/Library/Frameworks/', join(os.getenv('HOME'), '/Library/Frameworks') ] From python-checkins at python.org Wed Mar 4 22:32:48 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 22:32:48 +0100 (CET) Subject: [Python-checkins] r70174 - in python/branches/py3k: setup.py Message-ID: <20090304213248.B264C1E4002@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 22:32:48 2009 New Revision: 70174 Log: Merged revisions 70172 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70172 | ronald.oussoren | 2009-03-04 22:30:12 +0100 (Wed, 04 Mar 2009) | 7 lines Change framework search order when looking for Tcl/Tk on OSX. This is needed because the system linker looks in /Library/Framework before it looks in /System/Library frameworks. Without this patch _tkinter will be unusable when it is compiled on a system that has Tk 8.5 installed in /Library/Frameworks (and the Apple 8.4 install in /System/Library/Frameworks) ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/setup.py Modified: python/branches/py3k/setup.py ============================================================================== --- python/branches/py3k/setup.py (original) +++ python/branches/py3k/setup.py Wed Mar 4 22:32:48 2009 @@ -1083,8 +1083,8 @@ # different the UNIX search logic is not sharable. from os.path import join, exists framework_dirs = [ - '/System/Library/Frameworks/', '/Library/Frameworks', + '/System/Library/Frameworks/', join(os.getenv('HOME'), '/Library/Frameworks') ] From python-checkins at python.org Wed Mar 4 22:33:19 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 22:33:19 +0100 (CET) Subject: [Python-checkins] r70175 - in python/branches/release30-maint: setup.py Message-ID: <20090304213319.7E62B1E4076@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 22:33:19 2009 New Revision: 70175 Log: Merged revisions 70174 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70174 | ronald.oussoren | 2009-03-04 22:32:48 +0100 (Wed, 04 Mar 2009) | 14 lines Merged revisions 70172 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70172 | ronald.oussoren | 2009-03-04 22:30:12 +0100 (Wed, 04 Mar 2009) | 7 lines Change framework search order when looking for Tcl/Tk on OSX. This is needed because the system linker looks in /Library/Framework before it looks in /System/Library frameworks. Without this patch _tkinter will be unusable when it is compiled on a system that has Tk 8.5 installed in /Library/Frameworks (and the Apple 8.4 install in /System/Library/Frameworks) ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/setup.py Modified: python/branches/release30-maint/setup.py ============================================================================== --- python/branches/release30-maint/setup.py (original) +++ python/branches/release30-maint/setup.py Wed Mar 4 22:33:19 2009 @@ -1097,8 +1097,8 @@ # different the UNIX search logic is not sharable. from os.path import join, exists framework_dirs = [ - '/System/Library/Frameworks/', '/Library/Frameworks', + '/System/Library/Frameworks/', join(os.getenv('HOME'), '/Library/Frameworks') ] From python-checkins at python.org Wed Mar 4 22:35:05 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 22:35:05 +0100 (CET) Subject: [Python-checkins] r70176 - in python/trunk: Lib/idlelib/Bindings.py Lib/idlelib/EditorWindow.py Lib/idlelib/MultiCall.py Lib/idlelib/configDialog.py Lib/idlelib/keybindingDialog.py Lib/idlelib/macosxSupport.py Mac/IDLE/idlemain.py Message-ID: <20090304213505.571071E400C@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 22:35:05 2009 New Revision: 70176 Log: Fixes issues 3883 and 5194 Modified: python/trunk/Lib/idlelib/Bindings.py python/trunk/Lib/idlelib/EditorWindow.py python/trunk/Lib/idlelib/MultiCall.py python/trunk/Lib/idlelib/configDialog.py python/trunk/Lib/idlelib/keybindingDialog.py python/trunk/Lib/idlelib/macosxSupport.py python/trunk/Mac/IDLE/idlemain.py Modified: python/trunk/Lib/idlelib/Bindings.py ============================================================================== --- python/trunk/Lib/idlelib/Bindings.py (original) +++ python/trunk/Lib/idlelib/Bindings.py Wed Mar 4 22:35:05 2009 @@ -10,6 +10,7 @@ """ import sys from configHandler import idleConf +import macosxSupport menudefs = [ # underscore prefixes character to underscore @@ -80,8 +81,7 @@ ]), ] -import sys -if sys.platform == 'darwin' and '.app' in sys.executable: +if macosxSupport.runningAsOSXApp(): # Running as a proper MacOS application bundle. This block restructures # the menus a little to make them conform better to the HIG. Modified: python/trunk/Lib/idlelib/EditorWindow.py ============================================================================== --- python/trunk/Lib/idlelib/EditorWindow.py (original) +++ python/trunk/Lib/idlelib/EditorWindow.py Wed Mar 4 22:35:05 2009 @@ -368,7 +368,7 @@ menudict[name] = menu = Menu(mbar, name=name) mbar.add_cascade(label=label, menu=menu, underline=underline) - if sys.platform == 'darwin' and '.framework' in sys.executable: + if macosxSupport.runningAsOSXApp(): # Insert the application menu menudict['application'] = menu = Menu(mbar, name='apple') mbar.add_cascade(label='IDLE', menu=menu) Modified: python/trunk/Lib/idlelib/MultiCall.py ============================================================================== --- python/trunk/Lib/idlelib/MultiCall.py (original) +++ python/trunk/Lib/idlelib/MultiCall.py Wed Mar 4 22:35:05 2009 @@ -33,6 +33,7 @@ import string import re import Tkinter +import macosxSupport # the event type constants, which define the meaning of mc_type MC_KEYPRESS=0; MC_KEYRELEASE=1; MC_BUTTONPRESS=2; MC_BUTTONRELEASE=3; @@ -45,7 +46,7 @@ MC_OPTION = 1<<6; MC_COMMAND = 1<<7 # define the list of modifiers, to be used in complex event types. -if sys.platform == "darwin" and sys.executable.count(".app"): +if macosxSupport.runningAsOSXApp(): _modifiers = (("Shift",), ("Control",), ("Option",), ("Command",)) _modifier_masks = (MC_SHIFT, MC_CONTROL, MC_OPTION, MC_COMMAND) else: Modified: python/trunk/Lib/idlelib/configDialog.py ============================================================================== --- python/trunk/Lib/idlelib/configDialog.py (original) +++ python/trunk/Lib/idlelib/configDialog.py Wed Mar 4 22:35:05 2009 @@ -19,6 +19,7 @@ from keybindingDialog import GetKeysDialog from configSectionNameDialog import GetCfgSectionNameDialog from configHelpSourceEdit import GetHelpSourceDialog +import macosxSupport class ConfigDialog(Toplevel): @@ -69,18 +70,25 @@ page_names=['Fonts/Tabs','Highlighting','Keys','General']) frameActionButtons = Frame(self,pady=2) #action buttons + if macosxSupport.runningAsOSXApp(): + # Changing the default padding on OSX results in unreadable + # text in the buttons + paddingArgs={} + else: + paddingArgs={'padx':6, 'pady':3} + self.buttonHelp = Button(frameActionButtons,text='Help', command=self.Help,takefocus=FALSE, - padx=6,pady=3) + **paddingArgs) self.buttonOk = Button(frameActionButtons,text='Ok', command=self.Ok,takefocus=FALSE, - padx=6,pady=3) + **paddingArgs) self.buttonApply = Button(frameActionButtons,text='Apply', command=self.Apply,takefocus=FALSE, - padx=6,pady=3) + **paddingArgs) self.buttonCancel = Button(frameActionButtons,text='Cancel', command=self.Cancel,takefocus=FALSE, - padx=6,pady=3) + **paddingArgs) self.CreatePageFontTab() self.CreatePageHighlight() self.CreatePageKeys() Modified: python/trunk/Lib/idlelib/keybindingDialog.py ============================================================================== --- python/trunk/Lib/idlelib/keybindingDialog.py (original) +++ python/trunk/Lib/idlelib/keybindingDialog.py Wed Mar 4 22:35:05 2009 @@ -132,8 +132,8 @@ order is also important: key binding equality depends on it, so config-keys.def must use the same ordering. """ - import sys - if sys.platform == 'darwin' and sys.argv[0].count('.app'): + import macosxSupport + if macosxSupport.runningAsOSXApp(): self.modifiers = ['Shift', 'Control', 'Option', 'Command'] else: self.modifiers = ['Control', 'Alt', 'Shift'] Modified: python/trunk/Lib/idlelib/macosxSupport.py ============================================================================== --- python/trunk/Lib/idlelib/macosxSupport.py (original) +++ python/trunk/Lib/idlelib/macosxSupport.py Wed Mar 4 22:35:05 2009 @@ -6,8 +6,12 @@ import Tkinter def runningAsOSXApp(): - """ Returns True iff running from the IDLE.app bundle on OSX """ - return (sys.platform == 'darwin' and 'IDLE.app' in sys.argv[0]) + """ + Returns True if Python is running from within an app on OSX. + If so, assume that Python was built with Aqua Tcl/Tk rather than + X11 Tck/Tk. + """ + return (sys.platform == 'darwin' and '.app' in sys.executable) def addOpenEventSupport(root, flist): """ Modified: python/trunk/Mac/IDLE/idlemain.py ============================================================================== --- python/trunk/Mac/IDLE/idlemain.py (original) +++ python/trunk/Mac/IDLE/idlemain.py Wed Mar 4 22:35:05 2009 @@ -3,8 +3,6 @@ """ import sys, os -from idlelib.PyShell import main - # Change the current directory the user's home directory, that way we'll get # a more useful default location in the open/save dialogs. os.chdir(os.path.expanduser('~/Documents')) @@ -13,10 +11,54 @@ # Make sure sys.executable points to the python interpreter inside the # framework, instead of at the helper executable inside the application # bundle (the latter works, but doesn't allow access to the window server) -if sys.executable.endswith('-32'): - sys.executable = os.path.join(sys.prefix, 'bin', 'python-32') -else: - sys.executable = os.path.join(sys.prefix, 'bin', 'python') +# +# .../IDLE.app/ +# Contents/ +# MacOS/ +# IDLE (a python script) +# Python{-32} (symlink) +# Resources/ +# idlemain.py (this module) +# ... +# +# ../IDLE.app/Contents/MacOS/Python{-32} is symlinked to +# ..Library/Frameworks/Python.framework/Versions/m.n +# /Resources/Python.app/Contents/MacOS/Python{-32} +# which is the Python interpreter executable +# +# The flow of control is as follows: +# 1. IDLE.app is launched which starts python running the IDLE script +# 2. IDLE script exports +# PYTHONEXECUTABLE = .../IDLE.app/Contents/MacOS/Python{-32} +# (the symlink to the framework python) +# 3. IDLE script alters sys.argv and uses os.execve to replace itself with +# idlemain.py running under the symlinked python. +# This is the magic step. +# 4. During interpreter initialization, because PYTHONEXECUTABLE is defined, +# sys.executable may get set to an unuseful value. +# +# (Note that the IDLE script and the setting of PYTHONEXECUTABLE is +# generated automatically by bundlebuilder in the Python 2.x build. +# Also, IDLE invoked via command line, i.e. bin/idle, bypasses all of +# this.) +# +# Now fix up the execution environment before importing idlelib. + +# Reset sys.executable to its normal value, the actual path of +# the interpreter in the framework, by following the symlink +# exported in PYTHONEXECUTABLE. +pyex = os.environ['PYTHONEXECUTABLE'] +sys.executable = os.path.join(os.path.dirname(pyex), os.readlink(pyex)) + +# Remove any sys.path entries for the Resources dir in the IDLE.app bundle. +p = pyex.partition('.app') +if p[2].startswith('/Contents/MacOS/Python'): + sys.path = [value for value in sys.path if + value.partition('.app') != (p[0], p[1], '/Contents/Resources')] + +# Unexport PYTHONEXECUTABLE so that the other Python processes started +# by IDLE have a normal sys.executable. +del os.environ['PYTHONEXECUTABLE'] # Look for the -psn argument that the launcher adds and remove it, it will # only confuse the IDLE startup code. @@ -25,6 +67,7 @@ del sys.argv[idx] break -#argvemulator.ArgvCollector().mainloop() +# Now it is safe to import idlelib. +from idlelib.PyShell import main if __name__ == '__main__': main() From python-checkins at python.org Wed Mar 4 22:35:38 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 22:35:38 +0100 (CET) Subject: [Python-checkins] r70177 - in python/branches/release26-maint: Lib/idlelib/Bindings.py Lib/idlelib/EditorWindow.py Lib/idlelib/MultiCall.py Lib/idlelib/configDialog.py Lib/idlelib/keybindingDialog.py Lib/idlelib/macosxSupport.py Mac/IDLE/idlemain.py Message-ID: <20090304213538.E3AE41E4050@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 22:35:38 2009 New Revision: 70177 Log: Merged revisions 70176 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70176 | ronald.oussoren | 2009-03-04 22:35:05 +0100 (Wed, 04 Mar 2009) | 2 lines Fixes issues 3883 and 5194 ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/idlelib/Bindings.py python/branches/release26-maint/Lib/idlelib/EditorWindow.py python/branches/release26-maint/Lib/idlelib/MultiCall.py python/branches/release26-maint/Lib/idlelib/configDialog.py python/branches/release26-maint/Lib/idlelib/keybindingDialog.py python/branches/release26-maint/Lib/idlelib/macosxSupport.py python/branches/release26-maint/Mac/IDLE/idlemain.py Modified: python/branches/release26-maint/Lib/idlelib/Bindings.py ============================================================================== --- python/branches/release26-maint/Lib/idlelib/Bindings.py (original) +++ python/branches/release26-maint/Lib/idlelib/Bindings.py Wed Mar 4 22:35:38 2009 @@ -10,6 +10,7 @@ """ import sys from configHandler import idleConf +import macosxSupport menudefs = [ # underscore prefixes character to underscore @@ -80,8 +81,7 @@ ]), ] -import sys -if sys.platform == 'darwin' and '.app' in sys.executable: +if macosxSupport.runningAsOSXApp(): # Running as a proper MacOS application bundle. This block restructures # the menus a little to make them conform better to the HIG. Modified: python/branches/release26-maint/Lib/idlelib/EditorWindow.py ============================================================================== --- python/branches/release26-maint/Lib/idlelib/EditorWindow.py (original) +++ python/branches/release26-maint/Lib/idlelib/EditorWindow.py Wed Mar 4 22:35:38 2009 @@ -368,7 +368,7 @@ menudict[name] = menu = Menu(mbar, name=name) mbar.add_cascade(label=label, menu=menu, underline=underline) - if sys.platform == 'darwin' and '.framework' in sys.executable: + if macosxSupport.runningAsOSXApp(): # Insert the application menu menudict['application'] = menu = Menu(mbar, name='apple') mbar.add_cascade(label='IDLE', menu=menu) Modified: python/branches/release26-maint/Lib/idlelib/MultiCall.py ============================================================================== --- python/branches/release26-maint/Lib/idlelib/MultiCall.py (original) +++ python/branches/release26-maint/Lib/idlelib/MultiCall.py Wed Mar 4 22:35:38 2009 @@ -33,6 +33,7 @@ import string import re import Tkinter +import macosxSupport # the event type constants, which define the meaning of mc_type MC_KEYPRESS=0; MC_KEYRELEASE=1; MC_BUTTONPRESS=2; MC_BUTTONRELEASE=3; @@ -45,7 +46,7 @@ MC_OPTION = 1<<6; MC_COMMAND = 1<<7 # define the list of modifiers, to be used in complex event types. -if sys.platform == "darwin" and sys.executable.count(".app"): +if macosxSupport.runningAsOSXApp(): _modifiers = (("Shift",), ("Control",), ("Option",), ("Command",)) _modifier_masks = (MC_SHIFT, MC_CONTROL, MC_OPTION, MC_COMMAND) else: Modified: python/branches/release26-maint/Lib/idlelib/configDialog.py ============================================================================== --- python/branches/release26-maint/Lib/idlelib/configDialog.py (original) +++ python/branches/release26-maint/Lib/idlelib/configDialog.py Wed Mar 4 22:35:38 2009 @@ -19,6 +19,7 @@ from keybindingDialog import GetKeysDialog from configSectionNameDialog import GetCfgSectionNameDialog from configHelpSourceEdit import GetHelpSourceDialog +import macosxSupport class ConfigDialog(Toplevel): @@ -69,18 +70,25 @@ page_names=['Fonts/Tabs','Highlighting','Keys','General']) frameActionButtons = Frame(self,pady=2) #action buttons + if macosxSupport.runningAsOSXApp(): + # Changing the default padding on OSX results in unreadable + # text in the buttons + paddingArgs={} + else: + paddingArgs={'padx':6, 'pady':3} + self.buttonHelp = Button(frameActionButtons,text='Help', command=self.Help,takefocus=FALSE, - padx=6,pady=3) + **paddingArgs) self.buttonOk = Button(frameActionButtons,text='Ok', command=self.Ok,takefocus=FALSE, - padx=6,pady=3) + **paddingArgs) self.buttonApply = Button(frameActionButtons,text='Apply', command=self.Apply,takefocus=FALSE, - padx=6,pady=3) + **paddingArgs) self.buttonCancel = Button(frameActionButtons,text='Cancel', command=self.Cancel,takefocus=FALSE, - padx=6,pady=3) + **paddingArgs) self.CreatePageFontTab() self.CreatePageHighlight() self.CreatePageKeys() Modified: python/branches/release26-maint/Lib/idlelib/keybindingDialog.py ============================================================================== --- python/branches/release26-maint/Lib/idlelib/keybindingDialog.py (original) +++ python/branches/release26-maint/Lib/idlelib/keybindingDialog.py Wed Mar 4 22:35:38 2009 @@ -132,8 +132,8 @@ order is also important: key binding equality depends on it, so config-keys.def must use the same ordering. """ - import sys - if sys.platform == 'darwin' and sys.argv[0].count('.app'): + import macosxSupport + if macosxSupport.runningAsOSXApp(): self.modifiers = ['Shift', 'Control', 'Option', 'Command'] else: self.modifiers = ['Control', 'Alt', 'Shift'] Modified: python/branches/release26-maint/Lib/idlelib/macosxSupport.py ============================================================================== --- python/branches/release26-maint/Lib/idlelib/macosxSupport.py (original) +++ python/branches/release26-maint/Lib/idlelib/macosxSupport.py Wed Mar 4 22:35:38 2009 @@ -6,8 +6,12 @@ import Tkinter def runningAsOSXApp(): - """ Returns True iff running from the IDLE.app bundle on OSX """ - return (sys.platform == 'darwin' and 'IDLE.app' in sys.argv[0]) + """ + Returns True if Python is running from within an app on OSX. + If so, assume that Python was built with Aqua Tcl/Tk rather than + X11 Tck/Tk. + """ + return (sys.platform == 'darwin' and '.app' in sys.executable) def addOpenEventSupport(root, flist): """ Modified: python/branches/release26-maint/Mac/IDLE/idlemain.py ============================================================================== --- python/branches/release26-maint/Mac/IDLE/idlemain.py (original) +++ python/branches/release26-maint/Mac/IDLE/idlemain.py Wed Mar 4 22:35:38 2009 @@ -3,8 +3,6 @@ """ import sys, os -from idlelib.PyShell import main - # Change the current directory the user's home directory, that way we'll get # a more useful default location in the open/save dialogs. os.chdir(os.path.expanduser('~/Documents')) @@ -13,10 +11,54 @@ # Make sure sys.executable points to the python interpreter inside the # framework, instead of at the helper executable inside the application # bundle (the latter works, but doesn't allow access to the window server) -if sys.executable.endswith('-32'): - sys.executable = os.path.join(sys.prefix, 'bin', 'python-32') -else: - sys.executable = os.path.join(sys.prefix, 'bin', 'python') +# +# .../IDLE.app/ +# Contents/ +# MacOS/ +# IDLE (a python script) +# Python{-32} (symlink) +# Resources/ +# idlemain.py (this module) +# ... +# +# ../IDLE.app/Contents/MacOS/Python{-32} is symlinked to +# ..Library/Frameworks/Python.framework/Versions/m.n +# /Resources/Python.app/Contents/MacOS/Python{-32} +# which is the Python interpreter executable +# +# The flow of control is as follows: +# 1. IDLE.app is launched which starts python running the IDLE script +# 2. IDLE script exports +# PYTHONEXECUTABLE = .../IDLE.app/Contents/MacOS/Python{-32} +# (the symlink to the framework python) +# 3. IDLE script alters sys.argv and uses os.execve to replace itself with +# idlemain.py running under the symlinked python. +# This is the magic step. +# 4. During interpreter initialization, because PYTHONEXECUTABLE is defined, +# sys.executable may get set to an unuseful value. +# +# (Note that the IDLE script and the setting of PYTHONEXECUTABLE is +# generated automatically by bundlebuilder in the Python 2.x build. +# Also, IDLE invoked via command line, i.e. bin/idle, bypasses all of +# this.) +# +# Now fix up the execution environment before importing idlelib. + +# Reset sys.executable to its normal value, the actual path of +# the interpreter in the framework, by following the symlink +# exported in PYTHONEXECUTABLE. +pyex = os.environ['PYTHONEXECUTABLE'] +sys.executable = os.path.join(os.path.dirname(pyex), os.readlink(pyex)) + +# Remove any sys.path entries for the Resources dir in the IDLE.app bundle. +p = pyex.partition('.app') +if p[2].startswith('/Contents/MacOS/Python'): + sys.path = [value for value in sys.path if + value.partition('.app') != (p[0], p[1], '/Contents/Resources')] + +# Unexport PYTHONEXECUTABLE so that the other Python processes started +# by IDLE have a normal sys.executable. +del os.environ['PYTHONEXECUTABLE'] # Look for the -psn argument that the launcher adds and remove it, it will # only confuse the IDLE startup code. @@ -25,6 +67,7 @@ del sys.argv[idx] break -#argvemulator.ArgvCollector().mainloop() +# Now it is safe to import idlelib. +from idlelib.PyShell import main if __name__ == '__main__': main() From buildbot at python.org Wed Mar 4 22:55:56 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Mar 2009 21:55:56 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090304215557.51A2B1E400C@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/216 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl,ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ppc/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/home/pybot/buildarea/trunk.klose-debian-ppc/build/Lib/threading.py", line 477, in run self.__target(*self.__args, **self.__kwargs) File "/home/pybot/buildarea/trunk.klose-debian-ppc/build/Lib/bsddb/test/test_thread.py", line 306, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home/pybot/buildarea/trunk.klose-debian-ppc/build/Lib/bsddb/dbutils.py", line 68, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30994, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Wed Mar 4 23:24:27 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Mar 2009 22:24:27 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090304222427.D17F61E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/371 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Wed Mar 4 23:39:30 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 04 Mar 2009 22:39:30 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090304223930.3CA5F1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/160 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Wed Mar 4 23:49:36 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 23:49:36 +0100 (CET) Subject: [Python-checkins] r70178 - python/trunk/Mac/Modules/OSATerminology.c Message-ID: <20090304224936.BC4581E400C@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 23:49:36 2009 New Revision: 70178 Log: Fix for issue #1113328. Modified: python/trunk/Mac/Modules/OSATerminology.c Modified: python/trunk/Mac/Modules/OSATerminology.c ============================================================================== --- python/trunk/Mac/Modules/OSATerminology.c (original) +++ python/trunk/Mac/Modules/OSATerminology.c Wed Mar 4 23:49:36 2009 @@ -1,10 +1,13 @@ /* -** This module is a one-trick pony: given an FSSpec it gets the aeut -** resources. It was written by Donovan Preston and slightly modified -** by Jack. +** An interface to the application scripting related functions of the OSA API. ** -** It should be considered a placeholder, it will probably be replaced -** by a full interface to OpenScripting. +** GetAppTerminology - given an FSSpec/posix path to an application, +** returns its aevt (scripting terminology) resource(s) +** +** GetSysTerminology - returns the AppleScript language component's +** aeut (scripting terminology) resource +** +** Written by Donovan Preston and slightly modified by Jack and HAS. */ #include "Python.h" #include "pymactoolbox.h" @@ -26,12 +29,19 @@ if (!PyArg_ParseTuple(args, "O&|i", PyMac_GetFSSpec, &fss, &modeFlags)) return NULL; + /* + ** Note that we have to use the AppleScript component here. Who knows why + ** OSAGetAppTerminology should require a scripting component in the + ** first place, but it does. Note: doesn't work with the generic scripting + ** component, which is unfortunate as the AS component is currently very + ** slow (~1 sec?) to load, but we just have to live with this. + */ defaultComponent = OpenDefaultComponent (kOSAComponentType, 'ascr'); err = GetComponentInstanceError (defaultComponent); if (err) return PyMac_Error(err); err = OSAGetAppTerminology ( defaultComponent, - modeFlags, + kOSAModeNull, &fss, defaultTerminology, &didLaunch, @@ -45,29 +55,23 @@ PyOSA_GetSysTerminology(PyObject* self, PyObject* args) { AEDesc theDesc = {0,0}; - FSSpec fss; ComponentInstance defaultComponent = NULL; SInt16 defaultTerminology = 0; - Boolean didLaunch = 0; OSAError err; - long modeFlags = 0; - - if (!PyArg_ParseTuple(args, "O&|i", PyMac_GetFSSpec, &fss, &modeFlags)) - return NULL; + /* Accept any args for sake of backwards compatibility, then ignore them. */ + defaultComponent = OpenDefaultComponent (kOSAComponentType, 'ascr'); err = GetComponentInstanceError (defaultComponent); if (err) return PyMac_Error(err); - err = OSAGetAppTerminology ( + err = OSAGetSysTerminology ( defaultComponent, - modeFlags, - &fss, + kOSAModeNull, defaultTerminology, - &didLaunch, &theDesc ); if (err) return PyMac_Error(err); - return Py_BuildValue("O&i", AEDesc_New, &theDesc, didLaunch); + return Py_BuildValue("O&", AEDesc_New, &theDesc); } #endif /* !__LP64__ */ @@ -80,11 +84,11 @@ {"GetAppTerminology", (PyCFunction) PyOSA_GetAppTerminology, METH_VARARGS, - "Get an applications terminology, as an AEDesc object."}, + "Get an application's terminology. GetAppTerminology(path) --> AEDesc"}, {"GetSysTerminology", (PyCFunction) PyOSA_GetSysTerminology, METH_VARARGS, - "Get an applications system terminology, as an AEDesc object."}, + "Get the AppleScript language's terminology. GetSysTerminology() --> AEDesc"}, #endif /* !__LP64__ */ {NULL, (PyCFunction) NULL, 0, NULL} }; From python-checkins at python.org Wed Mar 4 23:57:10 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 23:57:10 +0100 (CET) Subject: [Python-checkins] r70179 - python/branches/py3k/Lib/test/test_osx_env.py Message-ID: <20090304225710.ADE971E4002@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 23:57:10 2009 New Revision: 70179 Log: Fix for issue #5408. This only enables test_osx_env when the current build is actually a framework build on OSX (the only environment where this test is valid). Modified: python/branches/py3k/Lib/test/test_osx_env.py Modified: python/branches/py3k/Lib/test/test_osx_env.py ============================================================================== --- python/branches/py3k/Lib/test/test_osx_env.py (original) +++ python/branches/py3k/Lib/test/test_osx_env.py Wed Mar 4 23:57:10 2009 @@ -27,7 +27,9 @@ self._check_sys('PYTHONEXECUTABLE', '==', 'sys.executable') def test_main(): - if sys.platform == 'darwin': + from distutils import sysconfig + + if sys.platform == 'darwin' and sysconfig.get_config_var('WITH_NEXT_FRAMEWORK'): run_unittest(OSXEnvironmentVariableTestCase) if __name__ == "__main__": From python-checkins at python.org Wed Mar 4 23:58:07 2009 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 4 Mar 2009 23:58:07 +0100 (CET) Subject: [Python-checkins] r70180 - in python/branches/release30-maint: Lib/test/test_osx_env.py Message-ID: <20090304225807.CA4441E4002@bag.python.org> Author: ronald.oussoren Date: Wed Mar 4 23:58:06 2009 New Revision: 70180 Log: Merged revisions 70179 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70179 | ronald.oussoren | 2009-03-04 23:57:10 +0100 (Wed, 04 Mar 2009) | 4 lines Fix for issue #5408. This only enables test_osx_env when the current build is actually a framework build on OSX (the only environment where this test is valid). ........ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/test/test_osx_env.py Modified: python/branches/release30-maint/Lib/test/test_osx_env.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_osx_env.py (original) +++ python/branches/release30-maint/Lib/test/test_osx_env.py Wed Mar 4 23:58:06 2009 @@ -27,7 +27,9 @@ self._check_sys('PYTHONEXECUTABLE', '==', 'sys.executable') def test_main(): - if sys.platform == 'darwin': + from distutils import sysconfig + + if sys.platform == 'darwin' and sysconfig.get_config_var('WITH_NEXT_FRAMEWORK'): run_unittest(OSXEnvironmentVariableTestCase) if __name__ == "__main__": From python-checkins at python.org Thu Mar 5 00:21:07 2009 From: python-checkins at python.org (ronald.oussoren) Date: Thu, 5 Mar 2009 00:21:07 +0100 (CET) Subject: [Python-checkins] r70181 - in python/branches/py3k/Lib/plat-darwin: IN.py regen Message-ID: <20090304232107.6B6A71E400C@bag.python.org> Author: ronald.oussoren Date: Thu Mar 5 00:21:07 2009 New Revision: 70181 Log: These are present in the trunk but no longer in 3.x, which causes problems during the build of the Mac binary installer. Added: python/branches/py3k/Lib/plat-darwin/ python/branches/py3k/Lib/plat-darwin/IN.py (contents, props changed) python/branches/py3k/Lib/plat-darwin/regen (contents, props changed) Added: python/branches/py3k/Lib/plat-darwin/IN.py ============================================================================== --- (empty file) +++ python/branches/py3k/Lib/plat-darwin/IN.py Thu Mar 5 00:21:07 2009 @@ -0,0 +1,662 @@ +# Generated by h2py from /usr/include/netinet/in.h + +# Included from sys/appleapiopts.h + +# Included from sys/_types.h + +# Included from sys/cdefs.h +def __P(protos): return protos + +def __STRING(x): return #x + +def __P(protos): return () + +def __STRING(x): return "x" + +def __attribute__(x): return + +def __COPYRIGHT(s): return __IDSTRING(copyright,s) + +def __RCSID(s): return __IDSTRING(rcsid,s) + +def __SCCSID(s): return __IDSTRING(sccsid,s) + +def __PROJECT_VERSION(s): return __IDSTRING(project_version,s) + +__DARWIN_UNIX03 = 1 +__DARWIN_UNIX03 = 0 +__DARWIN_UNIX03 = 0 +__DARWIN_UNIX03 = 1 +__DARWIN_64_BIT_INO_T = 1 +__DARWIN_64_BIT_INO_T = 0 +__DARWIN_64_BIT_INO_T = 0 +__DARWIN_NON_CANCELABLE = 0 +__DARWIN_VERS_1050 = 1 +__DARWIN_VERS_1050 = 0 +__DARWIN_SUF_UNIX03 = "$UNIX2003" +__DARWIN_SUF_UNIX03_SET = 1 +__DARWIN_SUF_UNIX03_SET = 0 +__DARWIN_SUF_64_BIT_INO_T = "$INODE64" +__DARWIN_SUF_NON_CANCELABLE = "$NOCANCEL" +__DARWIN_SUF_1050 = "$1050" +__DARWIN_SUF_UNIX03_SET = 0 +__DARWIN_SUF_EXTSN = "$DARWIN_EXTSN" +__DARWIN_LONG_DOUBLE_IS_DOUBLE = 0 +def __DARWIN_LDBL_COMPAT(x): return + +def __DARWIN_LDBL_COMPAT2(x): return + +__DARWIN_LONG_DOUBLE_IS_DOUBLE = 1 +def __DARWIN_LDBL_COMPAT(x): return + +def __DARWIN_LDBL_COMPAT2(x): return + +__DARWIN_LONG_DOUBLE_IS_DOUBLE = 0 +_DARWIN_FEATURE_LONG_DOUBLE_IS_DOUBLE = 1 +_DARWIN_FEATURE_UNIX_CONFORMANCE = 3 +_DARWIN_FEATURE_64_BIT_INODE = 1 + +# Included from machine/_types.h +__PTHREAD_SIZE__ = 1168 +__PTHREAD_ATTR_SIZE__ = 56 +__PTHREAD_MUTEXATTR_SIZE__ = 8 +__PTHREAD_MUTEX_SIZE__ = 56 +__PTHREAD_CONDATTR_SIZE__ = 8 +__PTHREAD_COND_SIZE__ = 40 +__PTHREAD_ONCE_SIZE__ = 8 +__PTHREAD_RWLOCK_SIZE__ = 192 +__PTHREAD_RWLOCKATTR_SIZE__ = 16 +__PTHREAD_SIZE__ = 596 +__PTHREAD_ATTR_SIZE__ = 36 +__PTHREAD_MUTEXATTR_SIZE__ = 8 +__PTHREAD_MUTEX_SIZE__ = 40 +__PTHREAD_CONDATTR_SIZE__ = 4 +__PTHREAD_COND_SIZE__ = 24 +__PTHREAD_ONCE_SIZE__ = 4 +__PTHREAD_RWLOCK_SIZE__ = 124 +__PTHREAD_RWLOCKATTR_SIZE__ = 12 +__DARWIN_NULL = 0 + +# Included from stdint.h +__WORDSIZE = 64 +__WORDSIZE = 32 +INT8_MAX = 127 +INT16_MAX = 32767 +INT32_MAX = 2147483647 +INT8_MIN = -128 +INT16_MIN = -32768 +INT32_MIN = (-INT32_MAX-1) +UINT8_MAX = 255 +UINT16_MAX = 65535 +INT_LEAST8_MIN = INT8_MIN +INT_LEAST16_MIN = INT16_MIN +INT_LEAST32_MIN = INT32_MIN +INT_LEAST8_MAX = INT8_MAX +INT_LEAST16_MAX = INT16_MAX +INT_LEAST32_MAX = INT32_MAX +UINT_LEAST8_MAX = UINT8_MAX +UINT_LEAST16_MAX = UINT16_MAX +INT_FAST8_MIN = INT8_MIN +INT_FAST16_MIN = INT16_MIN +INT_FAST32_MIN = INT32_MIN +INT_FAST8_MAX = INT8_MAX +INT_FAST16_MAX = INT16_MAX +INT_FAST32_MAX = INT32_MAX +UINT_FAST8_MAX = UINT8_MAX +UINT_FAST16_MAX = UINT16_MAX +INTPTR_MIN = INT32_MIN +INTPTR_MAX = INT32_MAX +PTRDIFF_MIN = INT32_MIN +PTRDIFF_MAX = INT32_MAX +WCHAR_MAX = 0x7fffffff +WCHAR_MIN = 0 +WCHAR_MIN = (-WCHAR_MAX-1) +WINT_MIN = INT32_MIN +WINT_MAX = INT32_MAX +SIG_ATOMIC_MIN = INT32_MIN +SIG_ATOMIC_MAX = INT32_MAX +def INT8_C(v): return (v) + +def INT16_C(v): return (v) + +def INT32_C(v): return (v) + + +# Included from sys/socket.h + +# Included from machine/_param.h +SOCK_STREAM = 1 +SOCK_DGRAM = 2 +SOCK_RAW = 3 +SOCK_RDM = 4 +SOCK_SEQPACKET = 5 +SO_DEBUG = 0x0001 +SO_ACCEPTCONN = 0x0002 +SO_REUSEADDR = 0x0004 +SO_KEEPALIVE = 0x0008 +SO_DONTROUTE = 0x0010 +SO_BROADCAST = 0x0020 +SO_USELOOPBACK = 0x0040 +SO_LINGER = 0x0080 +SO_LINGER = 0x1080 +SO_OOBINLINE = 0x0100 +SO_REUSEPORT = 0x0200 +SO_TIMESTAMP = 0x0400 +SO_ACCEPTFILTER = 0x1000 +SO_DONTTRUNC = 0x2000 +SO_WANTMORE = 0x4000 +SO_WANTOOBFLAG = 0x8000 +SO_SNDBUF = 0x1001 +SO_RCVBUF = 0x1002 +SO_SNDLOWAT = 0x1003 +SO_RCVLOWAT = 0x1004 +SO_SNDTIMEO = 0x1005 +SO_RCVTIMEO = 0x1006 +SO_ERROR = 0x1007 +SO_TYPE = 0x1008 +SO_NREAD = 0x1020 +SO_NKE = 0x1021 +SO_NOSIGPIPE = 0x1022 +SO_NOADDRERR = 0x1023 +SO_NWRITE = 0x1024 +SO_REUSESHAREUID = 0x1025 +SO_NOTIFYCONFLICT = 0x1026 +SO_LINGER_SEC = 0x1080 +SO_RESTRICTIONS = 0x1081 +SO_RESTRICT_DENYIN = 0x00000001 +SO_RESTRICT_DENYOUT = 0x00000002 +SO_RESTRICT_DENYSET = (-2147483648) +SO_LABEL = 0x1010 +SO_PEERLABEL = 0x1011 +SOL_SOCKET = 0xffff +AF_UNSPEC = 0 +AF_UNIX = 1 +AF_LOCAL = AF_UNIX +AF_INET = 2 +AF_IMPLINK = 3 +AF_PUP = 4 +AF_CHAOS = 5 +AF_NS = 6 +AF_ISO = 7 +AF_OSI = AF_ISO +AF_ECMA = 8 +AF_DATAKIT = 9 +AF_CCITT = 10 +AF_SNA = 11 +AF_DECnet = 12 +AF_DLI = 13 +AF_LAT = 14 +AF_HYLINK = 15 +AF_APPLETALK = 16 +AF_ROUTE = 17 +AF_LINK = 18 +pseudo_AF_XTP = 19 +AF_COIP = 20 +AF_CNT = 21 +pseudo_AF_RTIP = 22 +AF_IPX = 23 +AF_SIP = 24 +pseudo_AF_PIP = 25 +AF_NDRV = 27 +AF_ISDN = 28 +AF_E164 = AF_ISDN +pseudo_AF_KEY = 29 +AF_INET6 = 30 +AF_NATM = 31 +AF_SYSTEM = 32 +AF_NETBIOS = 33 +AF_PPP = 34 +AF_ATM = 30 +pseudo_AF_HDRCMPLT = 35 +AF_RESERVED_36 = 36 +AF_NETGRAPH = 32 +AF_MAX = 37 +SOCK_MAXADDRLEN = 255 +_SS_MAXSIZE = 128 +PF_UNSPEC = AF_UNSPEC +PF_LOCAL = AF_LOCAL +PF_UNIX = PF_LOCAL +PF_INET = AF_INET +PF_IMPLINK = AF_IMPLINK +PF_PUP = AF_PUP +PF_CHAOS = AF_CHAOS +PF_NS = AF_NS +PF_ISO = AF_ISO +PF_OSI = AF_ISO +PF_ECMA = AF_ECMA +PF_DATAKIT = AF_DATAKIT +PF_CCITT = AF_CCITT +PF_SNA = AF_SNA +PF_DECnet = AF_DECnet +PF_DLI = AF_DLI +PF_LAT = AF_LAT +PF_HYLINK = AF_HYLINK +PF_APPLETALK = AF_APPLETALK +PF_ROUTE = AF_ROUTE +PF_LINK = AF_LINK +PF_XTP = pseudo_AF_XTP +PF_COIP = AF_COIP +PF_CNT = AF_CNT +PF_SIP = AF_SIP +PF_IPX = AF_IPX +PF_RTIP = pseudo_AF_RTIP +PF_PIP = pseudo_AF_PIP +PF_NDRV = AF_NDRV +PF_ISDN = AF_ISDN +PF_KEY = pseudo_AF_KEY +PF_INET6 = AF_INET6 +PF_NATM = AF_NATM +PF_SYSTEM = AF_SYSTEM +PF_NETBIOS = AF_NETBIOS +PF_PPP = AF_PPP +PF_RESERVED_36 = AF_RESERVED_36 +PF_ATM = AF_ATM +PF_NETGRAPH = AF_NETGRAPH +PF_MAX = AF_MAX +NET_MAXID = AF_MAX +NET_RT_DUMP = 1 +NET_RT_FLAGS = 2 +NET_RT_IFLIST = 3 +NET_RT_STAT = 4 +NET_RT_TRASH = 5 +NET_RT_IFLIST2 = 6 +NET_RT_DUMP2 = 7 +NET_RT_MAXID = 8 +SOMAXCONN = 128 +MSG_OOB = 0x1 +MSG_PEEK = 0x2 +MSG_DONTROUTE = 0x4 +MSG_EOR = 0x8 +MSG_TRUNC = 0x10 +MSG_CTRUNC = 0x20 +MSG_WAITALL = 0x40 +MSG_DONTWAIT = 0x80 +MSG_EOF = 0x100 +MSG_WAITSTREAM = 0x200 +MSG_FLUSH = 0x400 +MSG_HOLD = 0x800 +MSG_SEND = 0x1000 +MSG_HAVEMORE = 0x2000 +MSG_RCVMORE = 0x4000 +MSG_NEEDSA = 0x10000 +CMGROUP_MAX = 16 +SCM_RIGHTS = 0x01 +SCM_TIMESTAMP = 0x02 +SCM_CREDS = 0x03 +SHUT_RD = 0 +SHUT_WR = 1 +SHUT_RDWR = 2 + +# Included from machine/endian.h + +# Included from sys/_endian.h +def ntohl(x): return (x) + +def ntohs(x): return (x) + +def htonl(x): return (x) + +def htons(x): return (x) + +def NTOHL(x): return (x) + +def NTOHS(x): return (x) + +def HTONL(x): return (x) + +def HTONS(x): return (x) + + +# Included from libkern/_OSByteOrder.h +def __DARWIN_OSSwapConstInt16(x): return \ + +def __DARWIN_OSSwapConstInt32(x): return \ + +def __DARWIN_OSSwapConstInt64(x): return \ + + +# Included from libkern/i386/_OSByteOrder.h +def __DARWIN_OSSwapInt16(x): return \ + +def __DARWIN_OSSwapInt32(x): return \ + +def __DARWIN_OSSwapInt64(x): return \ + +def __DARWIN_OSSwapInt16(x): return _OSSwapInt16(x) + +def __DARWIN_OSSwapInt32(x): return _OSSwapInt32(x) + +def __DARWIN_OSSwapInt64(x): return _OSSwapInt64(x) + +def ntohs(x): return __DARWIN_OSSwapInt16(x) + +def htons(x): return __DARWIN_OSSwapInt16(x) + +def ntohl(x): return __DARWIN_OSSwapInt32(x) + +def htonl(x): return __DARWIN_OSSwapInt32(x) + +IPPROTO_IP = 0 +IPPROTO_HOPOPTS = 0 +IPPROTO_ICMP = 1 +IPPROTO_IGMP = 2 +IPPROTO_GGP = 3 +IPPROTO_IPV4 = 4 +IPPROTO_IPIP = IPPROTO_IPV4 +IPPROTO_TCP = 6 +IPPROTO_ST = 7 +IPPROTO_EGP = 8 +IPPROTO_PIGP = 9 +IPPROTO_RCCMON = 10 +IPPROTO_NVPII = 11 +IPPROTO_PUP = 12 +IPPROTO_ARGUS = 13 +IPPROTO_EMCON = 14 +IPPROTO_XNET = 15 +IPPROTO_CHAOS = 16 +IPPROTO_UDP = 17 +IPPROTO_MUX = 18 +IPPROTO_MEAS = 19 +IPPROTO_HMP = 20 +IPPROTO_PRM = 21 +IPPROTO_IDP = 22 +IPPROTO_TRUNK1 = 23 +IPPROTO_TRUNK2 = 24 +IPPROTO_LEAF1 = 25 +IPPROTO_LEAF2 = 26 +IPPROTO_RDP = 27 +IPPROTO_IRTP = 28 +IPPROTO_TP = 29 +IPPROTO_BLT = 30 +IPPROTO_NSP = 31 +IPPROTO_INP = 32 +IPPROTO_SEP = 33 +IPPROTO_3PC = 34 +IPPROTO_IDPR = 35 +IPPROTO_XTP = 36 +IPPROTO_DDP = 37 +IPPROTO_CMTP = 38 +IPPROTO_TPXX = 39 +IPPROTO_IL = 40 +IPPROTO_IPV6 = 41 +IPPROTO_SDRP = 42 +IPPROTO_ROUTING = 43 +IPPROTO_FRAGMENT = 44 +IPPROTO_IDRP = 45 +IPPROTO_RSVP = 46 +IPPROTO_GRE = 47 +IPPROTO_MHRP = 48 +IPPROTO_BHA = 49 +IPPROTO_ESP = 50 +IPPROTO_AH = 51 +IPPROTO_INLSP = 52 +IPPROTO_SWIPE = 53 +IPPROTO_NHRP = 54 +IPPROTO_ICMPV6 = 58 +IPPROTO_NONE = 59 +IPPROTO_DSTOPTS = 60 +IPPROTO_AHIP = 61 +IPPROTO_CFTP = 62 +IPPROTO_HELLO = 63 +IPPROTO_SATEXPAK = 64 +IPPROTO_KRYPTOLAN = 65 +IPPROTO_RVD = 66 +IPPROTO_IPPC = 67 +IPPROTO_ADFS = 68 +IPPROTO_SATMON = 69 +IPPROTO_VISA = 70 +IPPROTO_IPCV = 71 +IPPROTO_CPNX = 72 +IPPROTO_CPHB = 73 +IPPROTO_WSN = 74 +IPPROTO_PVP = 75 +IPPROTO_BRSATMON = 76 +IPPROTO_ND = 77 +IPPROTO_WBMON = 78 +IPPROTO_WBEXPAK = 79 +IPPROTO_EON = 80 +IPPROTO_VMTP = 81 +IPPROTO_SVMTP = 82 +IPPROTO_VINES = 83 +IPPROTO_TTP = 84 +IPPROTO_IGP = 85 +IPPROTO_DGP = 86 +IPPROTO_TCF = 87 +IPPROTO_IGRP = 88 +IPPROTO_OSPFIGP = 89 +IPPROTO_SRPC = 90 +IPPROTO_LARP = 91 +IPPROTO_MTP = 92 +IPPROTO_AX25 = 93 +IPPROTO_IPEIP = 94 +IPPROTO_MICP = 95 +IPPROTO_SCCSP = 96 +IPPROTO_ETHERIP = 97 +IPPROTO_ENCAP = 98 +IPPROTO_APES = 99 +IPPROTO_GMTP = 100 +IPPROTO_IPCOMP = 108 +IPPROTO_PIM = 103 +IPPROTO_PGM = 113 +IPPROTO_DIVERT = 254 +IPPROTO_RAW = 255 +IPPROTO_MAX = 256 +IPPROTO_DONE = 257 +__DARWIN_IPPORT_RESERVED = 1024 +IPPORT_RESERVED = __DARWIN_IPPORT_RESERVED +IPPORT_USERRESERVED = 5000 +IPPORT_HIFIRSTAUTO = 49152 +IPPORT_HILASTAUTO = 65535 +IPPORT_RESERVEDSTART = 600 +def IN_CLASSA(i): return (((u_int32_t)(i) & (-2147483648)) == 0) + +IN_CLASSA_NET = (-16777216) +IN_CLASSA_NSHIFT = 24 +IN_CLASSA_HOST = 0x00ffffff +IN_CLASSA_MAX = 128 +def IN_CLASSB(i): return (((u_int32_t)(i) & (-1073741824)) == (-2147483648)) + +IN_CLASSB_NET = (-65536) +IN_CLASSB_NSHIFT = 16 +IN_CLASSB_HOST = 0x0000ffff +IN_CLASSB_MAX = 65536 +def IN_CLASSC(i): return (((u_int32_t)(i) & (-536870912)) == (-1073741824)) + +IN_CLASSC_NET = (-256) +IN_CLASSC_NSHIFT = 8 +IN_CLASSC_HOST = 0x000000ff +def IN_CLASSD(i): return (((u_int32_t)(i) & (-268435456)) == (-536870912)) + +IN_CLASSD_NET = (-268435456) +IN_CLASSD_NSHIFT = 28 +IN_CLASSD_HOST = 0x0fffffff +def IN_MULTICAST(i): return IN_CLASSD(i) + +def IN_EXPERIMENTAL(i): return (((u_int32_t)(i) & (-268435456)) == (-268435456)) + +def IN_BADCLASS(i): return (((u_int32_t)(i) & (-268435456)) == (-268435456)) + +INADDR_NONE = (-1) +def IN_LINKLOCAL(i): return (((u_int32_t)(i) & IN_CLASSB_NET) == IN_LINKLOCALNETNUM) + +IN_LOOPBACKNET = 127 +INET_ADDRSTRLEN = 16 +IP_OPTIONS = 1 +IP_HDRINCL = 2 +IP_TOS = 3 +IP_TTL = 4 +IP_RECVOPTS = 5 +IP_RECVRETOPTS = 6 +IP_RECVDSTADDR = 7 +IP_RETOPTS = 8 +IP_MULTICAST_IF = 9 +IP_MULTICAST_TTL = 10 +IP_MULTICAST_LOOP = 11 +IP_ADD_MEMBERSHIP = 12 +IP_DROP_MEMBERSHIP = 13 +IP_MULTICAST_VIF = 14 +IP_RSVP_ON = 15 +IP_RSVP_OFF = 16 +IP_RSVP_VIF_ON = 17 +IP_RSVP_VIF_OFF = 18 +IP_PORTRANGE = 19 +IP_RECVIF = 20 +IP_IPSEC_POLICY = 21 +IP_FAITH = 22 +IP_STRIPHDR = 23 +IP_RECVTTL = 24 +IP_FW_ADD = 40 +IP_FW_DEL = 41 +IP_FW_FLUSH = 42 +IP_FW_ZERO = 43 +IP_FW_GET = 44 +IP_FW_RESETLOG = 45 +IP_OLD_FW_ADD = 50 +IP_OLD_FW_DEL = 51 +IP_OLD_FW_FLUSH = 52 +IP_OLD_FW_ZERO = 53 +IP_OLD_FW_GET = 54 +IP_NAT__XXX = 55 +IP_OLD_FW_RESETLOG = 56 +IP_DUMMYNET_CONFIGURE = 60 +IP_DUMMYNET_DEL = 61 +IP_DUMMYNET_FLUSH = 62 +IP_DUMMYNET_GET = 64 +IP_TRAFFIC_MGT_BACKGROUND = 65 +IP_FORCE_OUT_IFP = 69 +TRAFFIC_MGT_SO_BACKGROUND = 0x0001 +TRAFFIC_MGT_SO_BG_SUPPRESSED = 0x0002 +IP_DEFAULT_MULTICAST_TTL = 1 +IP_DEFAULT_MULTICAST_LOOP = 1 +IP_MAX_MEMBERSHIPS = 20 +IP_PORTRANGE_DEFAULT = 0 +IP_PORTRANGE_HIGH = 1 +IP_PORTRANGE_LOW = 2 +IPPROTO_MAXID = (IPPROTO_AH + 1) +IPCTL_FORWARDING = 1 +IPCTL_SENDREDIRECTS = 2 +IPCTL_DEFTTL = 3 +IPCTL_DEFMTU = 4 +IPCTL_RTEXPIRE = 5 +IPCTL_RTMINEXPIRE = 6 +IPCTL_RTMAXCACHE = 7 +IPCTL_SOURCEROUTE = 8 +IPCTL_DIRECTEDBROADCAST = 9 +IPCTL_INTRQMAXLEN = 10 +IPCTL_INTRQDROPS = 11 +IPCTL_STATS = 12 +IPCTL_ACCEPTSOURCEROUTE = 13 +IPCTL_FASTFORWARDING = 14 +IPCTL_KEEPFAITH = 15 +IPCTL_GIF_TTL = 16 +IPCTL_MAXID = 17 + +# Included from netinet6/in6.h +__KAME_VERSION = "20010528/apple-darwin" +IPV6PORT_RESERVED = 1024 +IPV6PORT_ANONMIN = 49152 +IPV6PORT_ANONMAX = 65535 +IPV6PORT_RESERVEDMIN = 600 +IPV6PORT_RESERVEDMAX = (IPV6PORT_RESERVED-1) +INET6_ADDRSTRLEN = 46 +def IN6_IS_ADDR_UNSPECIFIED(a): return \ + +def IN6_IS_ADDR_LOOPBACK(a): return \ + +def IN6_IS_ADDR_V4COMPAT(a): return \ + +def IN6_IS_ADDR_V4MAPPED(a): return \ + +__IPV6_ADDR_SCOPE_NODELOCAL = 0x01 +__IPV6_ADDR_SCOPE_LINKLOCAL = 0x02 +__IPV6_ADDR_SCOPE_SITELOCAL = 0x05 +__IPV6_ADDR_SCOPE_ORGLOCAL = 0x08 +__IPV6_ADDR_SCOPE_GLOBAL = 0x0e +def IN6_IS_ADDR_LINKLOCAL(a): return \ + +def IN6_IS_ADDR_SITELOCAL(a): return \ + +def IN6_IS_ADDR_MC_NODELOCAL(a): return \ + +def IN6_IS_ADDR_MC_LINKLOCAL(a): return \ + +def IN6_IS_ADDR_MC_SITELOCAL(a): return \ + +def IN6_IS_ADDR_MC_ORGLOCAL(a): return \ + +def IN6_IS_ADDR_MC_GLOBAL(a): return \ + +IPV6_OPTIONS = 1 +IPV6_RECVOPTS = 5 +IPV6_RECVRETOPTS = 6 +IPV6_RECVDSTADDR = 7 +IPV6_RETOPTS = 8 +IPV6_SOCKOPT_RESERVED1 = 3 +IPV6_UNICAST_HOPS = 4 +IPV6_MULTICAST_IF = 9 +IPV6_MULTICAST_HOPS = 10 +IPV6_MULTICAST_LOOP = 11 +IPV6_JOIN_GROUP = 12 +IPV6_LEAVE_GROUP = 13 +IPV6_PORTRANGE = 14 +ICMP6_FILTER = 18 +IPV6_PKTINFO = 19 +IPV6_HOPLIMIT = 20 +IPV6_NEXTHOP = 21 +IPV6_HOPOPTS = 22 +IPV6_DSTOPTS = 23 +IPV6_RTHDR = 24 +IPV6_PKTOPTIONS = 25 +IPV6_CHECKSUM = 26 +IPV6_V6ONLY = 27 +IPV6_BINDV6ONLY = IPV6_V6ONLY +IPV6_IPSEC_POLICY = 28 +IPV6_FAITH = 29 +IPV6_FW_ADD = 30 +IPV6_FW_DEL = 31 +IPV6_FW_FLUSH = 32 +IPV6_FW_ZERO = 33 +IPV6_FW_GET = 34 +IPV6_RTHDR_LOOSE = 0 +IPV6_RTHDR_STRICT = 1 +IPV6_RTHDR_TYPE_0 = 0 +IPV6_DEFAULT_MULTICAST_HOPS = 1 +IPV6_DEFAULT_MULTICAST_LOOP = 1 +IPV6_PORTRANGE_DEFAULT = 0 +IPV6_PORTRANGE_HIGH = 1 +IPV6_PORTRANGE_LOW = 2 +IPV6PROTO_MAXID = (IPPROTO_PIM + 1) +IPV6CTL_FORWARDING = 1 +IPV6CTL_SENDREDIRECTS = 2 +IPV6CTL_DEFHLIM = 3 +IPV6CTL_DEFMTU = 4 +IPV6CTL_FORWSRCRT = 5 +IPV6CTL_STATS = 6 +IPV6CTL_MRTSTATS = 7 +IPV6CTL_MRTPROTO = 8 +IPV6CTL_MAXFRAGPACKETS = 9 +IPV6CTL_SOURCECHECK = 10 +IPV6CTL_SOURCECHECK_LOGINT = 11 +IPV6CTL_ACCEPT_RTADV = 12 +IPV6CTL_KEEPFAITH = 13 +IPV6CTL_LOG_INTERVAL = 14 +IPV6CTL_HDRNESTLIMIT = 15 +IPV6CTL_DAD_COUNT = 16 +IPV6CTL_AUTO_FLOWLABEL = 17 +IPV6CTL_DEFMCASTHLIM = 18 +IPV6CTL_GIF_HLIM = 19 +IPV6CTL_KAME_VERSION = 20 +IPV6CTL_USE_DEPRECATED = 21 +IPV6CTL_RR_PRUNE = 22 +IPV6CTL_MAPPED_ADDR = 23 +IPV6CTL_V6ONLY = 24 +IPV6CTL_RTEXPIRE = 25 +IPV6CTL_RTMINEXPIRE = 26 +IPV6CTL_RTMAXCACHE = 27 +IPV6CTL_USETEMPADDR = 32 +IPV6CTL_TEMPPLTIME = 33 +IPV6CTL_TEMPVLTIME = 34 +IPV6CTL_AUTO_LINKLOCAL = 35 +IPV6CTL_RIP6STATS = 36 +IPV6CTL_MAXFRAGS = 41 +IPV6CTL_MAXID = 42 Added: python/branches/py3k/Lib/plat-darwin/regen ============================================================================== --- (empty file) +++ python/branches/py3k/Lib/plat-darwin/regen Thu Mar 5 00:21:07 2009 @@ -0,0 +1,3 @@ +#! /bin/sh +set -v +python$EXE ../../Tools/scripts/h2py.py -i '(u_long)' /usr/include/netinet/in.h From python-checkins at python.org Thu Mar 5 00:24:32 2009 From: python-checkins at python.org (ronald.oussoren) Date: Thu, 5 Mar 2009 00:24:32 +0100 (CET) Subject: [Python-checkins] r70182 - in python/branches/release30-maint: Lib/plat-darwin Message-ID: <20090304232432.4CCC21E4011@bag.python.org> Author: ronald.oussoren Date: Thu Mar 5 00:24:32 2009 New Revision: 70182 Log: Merged revisions 70181 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70181 | ronald.oussoren | 2009-03-05 00:21:07 +0100 (Thu, 05 Mar 2009) | 3 lines These are present in the trunk but no longer in 3.x, which causes problems during the build of the Mac binary installer. ........ Added: python/branches/release30-maint/Lib/plat-darwin/ - copied from r70181, /python/branches/py3k/Lib/plat-darwin/ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Thu Mar 5 01:07:21 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 00:07:21 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo 2.6 Message-ID: <20090305000722.0B5A11E4002@bag.python.org> The Buildbot has detected a new failure of x86 gentoo 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20gentoo%202.6/builds/163 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Thu Mar 5 01:15:41 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 00:15:41 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090305001542.2567A1E4034@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/194 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_posix test_subprocess ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_subprocess.py", line 115, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From buildbot at python.org Thu Mar 5 01:16:55 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 00:16:55 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.0 Message-ID: <20090305001656.B55911E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.0/builds/167 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_doctest make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Mar 5 01:17:57 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 5 Mar 2009 01:17:57 +0100 (CET) Subject: [Python-checkins] r70183 - python/trunk/Doc/library/symtable.rst Message-ID: <20090305001757.C6F931E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 5 01:17:57 2009 New Revision: 70183 Log: add example Modified: python/trunk/Doc/library/symtable.rst Modified: python/trunk/Doc/library/symtable.rst ============================================================================== --- python/trunk/Doc/library/symtable.rst (original) +++ python/trunk/Doc/library/symtable.rst Thu Mar 5 01:17:57 2009 @@ -164,6 +164,12 @@ If the name is used as the target of a function or class statement, this will be true. + For example:: + + >>> table = symtable.symtable("def some_func(): pass", "string", "exec") + >>> table.lookup("some_func").is_namespace() + True + Note that a single name can be bound to multiple objects. If the result is ``True``, the name may also be bound to other objects, like an int or list, that does not introduce a new namespace. From buildbot at python.org Thu Mar 5 01:37:45 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 00:37:45 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090305003745.A798D1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/469 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_pipes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Mar 5 01:42:09 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 5 Mar 2009 01:42:09 +0100 (CET) Subject: [Python-checkins] r70184 - in python/branches/py3k/Lib: _pyio.py test/test_io.py Message-ID: <20090305004209.C84E21E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 5 01:42:09 2009 New Revision: 70184 Log: fix #4862 in _pyio: reset the decoder on seek(0) Modified: python/branches/py3k/Lib/_pyio.py python/branches/py3k/Lib/test/test_io.py Modified: python/branches/py3k/Lib/_pyio.py ============================================================================== --- python/branches/py3k/Lib/_pyio.py (original) +++ python/branches/py3k/Lib/_pyio.py Thu Mar 5 01:42:09 2009 @@ -1667,7 +1667,9 @@ self._snapshot = None # Restore the decoder to its state from the safe start point. - if self._decoder or dec_flags or chars_to_skip: + if cookie == 0 and self._decoder: + self._decoder.reset() + elif self._decoder or dec_flags or chars_to_skip: self._decoder = self._decoder or self._get_decoder() self._decoder.setstate((b'', dec_flags)) self._snapshot = (dec_flags, b'') Modified: python/branches/py3k/Lib/test/test_io.py ============================================================================== --- python/branches/py3k/Lib/test/test_io.py (original) +++ python/branches/py3k/Lib/test/test_io.py Thu Mar 5 01:42:09 2009 @@ -1706,6 +1706,8 @@ f.write(data) f.seek(0) self.assertEquals(f.read(), data * 2) + f.seek(0) + self.assertEquals(f.read(), data * 2) self.assertEquals(buf.getvalue(), (data * 2).encode(encoding)) def test_read_one_by_one(self): From python-checkins at python.org Thu Mar 5 01:49:54 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 5 Mar 2009 01:49:54 +0100 (CET) Subject: [Python-checkins] r70185 - python/branches/py3k/Lib/test/test_io.py Message-ID: <20090305004954.5FBF51E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 5 01:49:53 2009 New Revision: 70185 Log: rename Modified: python/branches/py3k/Lib/test/test_io.py Modified: python/branches/py3k/Lib/test/test_io.py ============================================================================== --- python/branches/py3k/Lib/test/test_io.py (original) +++ python/branches/py3k/Lib/test/test_io.py Thu Mar 5 01:49:53 2009 @@ -1648,7 +1648,7 @@ # Make test faster by doing smaller seeks CHUNK_SIZE = 128 - def testSeekAndTellWithData(data, min_pos=0): + def test_seek_and_tell_with_data(data, min_pos=0): """Tell/seek to various points within a data stream and ensure that the decoded data returned by read() is consistent.""" f = self.open(support.TESTFN, 'wb') @@ -1676,7 +1676,7 @@ try: # Try each test case. for input, _, _ in StatefulIncrementalDecoderTest.test_cases: - testSeekAndTellWithData(input) + test_seek_and_tell_with_data(input) # Position each test case so that it crosses a chunk boundary. for input, _, _ in StatefulIncrementalDecoderTest.test_cases: @@ -1684,7 +1684,7 @@ prefix = b'.'*offset # Don't bother seeking into the prefix (takes too long). min_pos = offset*2 - testSeekAndTellWithData(prefix + input, min_pos) + test_seek_and_tell_with_data(prefix + input, min_pos) # Ensure our test decoder won't interfere with subsequent tests. finally: From python-checkins at python.org Thu Mar 5 01:50:16 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 5 Mar 2009 01:50:16 +0100 (CET) Subject: [Python-checkins] r70186 - python/branches/py3k/Lib/_pyio.py Message-ID: <20090305005016.1CA751E4018@bag.python.org> Author: benjamin.peterson Date: Thu Mar 5 01:50:15 2009 New Revision: 70186 Log: rather pointless XXX Modified: python/branches/py3k/Lib/_pyio.py Modified: python/branches/py3k/Lib/_pyio.py ============================================================================== --- python/branches/py3k/Lib/_pyio.py (original) +++ python/branches/py3k/Lib/_pyio.py Thu Mar 5 01:50:15 2009 @@ -1815,8 +1815,6 @@ argument is like the one of TextIOWrapper's constructor. """ - # XXX This is really slow, but fully functional - def __init__(self, initial_value="", newline="\n"): super(StringIO, self).__init__(BytesIO(), encoding="utf-8", From python-checkins at python.org Thu Mar 5 01:55:57 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 5 Mar 2009 01:55:57 +0100 (CET) Subject: [Python-checkins] r70187 - in python/branches/py3k: Doc/library/io.rst Modules/_fileio.c Message-ID: <20090305005557.251991E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 5 01:55:56 2009 New Revision: 70187 Log: FileIO.readinto() isn't going anywhere Modified: python/branches/py3k/Doc/library/io.rst python/branches/py3k/Modules/_fileio.c Modified: python/branches/py3k/Doc/library/io.rst ============================================================================== --- python/branches/py3k/Doc/library/io.rst (original) +++ python/branches/py3k/Doc/library/io.rst Thu Mar 5 01:55:56 2009 @@ -438,9 +438,6 @@ the number actually written. Only one system call is made, so it is possible that only some of the data is written. - Note that the inherited ``readinto()`` method should not be used on - :class:`FileIO` objects. - Buffered Streams ---------------- Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Thu Mar 5 01:55:56 2009 @@ -887,7 +887,7 @@ "tell() -> int. Current file position"); PyDoc_STRVAR(readinto_doc, -"readinto() -> Undocumented. Don't use this; it may go away."); +"readinto() -> Same as RawIOBase.readinto()."); PyDoc_STRVAR(close_doc, "close() -> None. Close the file.\n" From buildbot at python.org Thu Mar 5 02:00:59 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 01:00:59 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090305010059.379C61E4014@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/373 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Thu Mar 5 03:02:35 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 02:02:35 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090305020236.5147C1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/709 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_asynchat make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Mar 5 10:34:14 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Thu, 5 Mar 2009 10:34:14 +0100 (CET) Subject: [Python-checkins] r70188 - python/trunk/Objects/bytearrayobject.c Message-ID: <20090305093414.CDFE11E400C@bag.python.org> Author: hirokazu.yamamoto Date: Thu Mar 5 10:34:14 2009 New Revision: 70188 Log: Fixed memory leak on failure. Modified: python/trunk/Objects/bytearrayobject.c Modified: python/trunk/Objects/bytearrayobject.c ============================================================================== --- python/trunk/Objects/bytearrayobject.c (original) +++ python/trunk/Objects/bytearrayobject.c Thu Mar 5 10:34:14 2009 @@ -298,7 +298,7 @@ size = va.len + vb.len; if (size < 0) { - return PyErr_NoMemory(); + PyErr_NoMemory(); goto done; } From python-checkins at python.org Thu Mar 5 15:21:12 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Thu, 5 Mar 2009 15:21:12 +0100 (CET) Subject: [Python-checkins] r70189 - in python/trunk: Lib/test/test_mmap.py Misc/NEWS Modules/mmapmodule.c Message-ID: <20090305142112.588DB1E402F@bag.python.org> Author: hirokazu.yamamoto Date: Thu Mar 5 15:21:12 2009 New Revision: 70189 Log: Issue #5385: Fixed mmap crash after resize failure on windows. Now uses NULL instead of INVALID_HANDLE_VALUE as invalid map handle because CreateFileMapping returns NULL when error occurs. Modified: python/trunk/Lib/test/test_mmap.py python/trunk/Misc/NEWS python/trunk/Modules/mmapmodule.c Modified: python/trunk/Lib/test/test_mmap.py ============================================================================== --- python/trunk/Lib/test/test_mmap.py (original) +++ python/trunk/Lib/test/test_mmap.py Thu Mar 5 15:21:12 2009 @@ -504,6 +504,7 @@ data1 = "0123456789" data2 = "abcdefghij" assert len(data1) == len(data2) + # Test same tag m1 = mmap.mmap(-1, len(data1), tagname="foo") m1[:] = data1 @@ -511,6 +512,9 @@ m2[:] = data2 self.assertEquals(m1[:], data2) self.assertEquals(m2[:], data2) + m2.close() + m1.close() + # Test differnt tag m1 = mmap.mmap(-1, len(data1), tagname="foo") m1[:] = data1 @@ -518,14 +522,42 @@ m2[:] = data2 self.assertEquals(m1[:], data1) self.assertEquals(m2[:], data2) + m2.close() + m1.close() - def test_tagname_crash(self): + def test_crasher_on_windows(self): # Should not crash (Issue 1733986) m = mmap.mmap(-1, 1000, tagname="foo") try: mmap.mmap(-1, 5000, tagname="foo")[:] # same tagname, but larger size except: pass + m.close() + + # Should not crash (Issue 5385) + m = mmap.mmap(-1, 1000) + try: + m.resize(0) + except: + pass + try: + m[:] + except: + pass + m.close() + + m1 = mmap.mmap(-1, 1000) + m2 = mmap.mmap(-1, 1000) + try: + m2.resize(5000) + except: + pass + try: + m2[:] + except: + pass + m2.close() + m1.close() def test_main(): Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Thu Mar 5 15:21:12 2009 @@ -168,6 +168,8 @@ Library ------- +- Issue #5385: Fixed mmap crash after resize failure on windows. + - Issue #5179: Fixed subprocess handle leak on failure on windows. - PEP 372: Added collections.OrderedDict(). Modified: python/trunk/Modules/mmapmodule.c ============================================================================== --- python/trunk/Modules/mmapmodule.c (original) +++ python/trunk/Modules/mmapmodule.c Thu Mar 5 15:21:12 2009 @@ -112,7 +112,7 @@ #ifdef MS_WINDOWS if (m_obj->data != NULL) UnmapViewOfFile (m_obj->data); - if (m_obj->map_handle != INVALID_HANDLE_VALUE) + if (m_obj->map_handle != NULL) CloseHandle (m_obj->map_handle); if (m_obj->file_handle != INVALID_HANDLE_VALUE) CloseHandle (m_obj->file_handle); @@ -147,9 +147,9 @@ UnmapViewOfFile(self->data); self->data = NULL; } - if (self->map_handle != INVALID_HANDLE_VALUE) { + if (self->map_handle != NULL) { CloseHandle(self->map_handle); - self->map_handle = INVALID_HANDLE_VALUE; + self->map_handle = NULL; } if (self->file_handle != INVALID_HANDLE_VALUE) { CloseHandle(self->file_handle); @@ -173,7 +173,7 @@ #ifdef MS_WINDOWS #define CHECK_VALID(err) \ do { \ - if (self->map_handle == INVALID_HANDLE_VALUE) { \ + if (self->map_handle == NULL) { \ PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \ return err; \ } \ @@ -441,8 +441,10 @@ DWORD off_hi, off_lo, newSizeLow, newSizeHigh; /* First, unmap the file view */ UnmapViewOfFile(self->data); + self->data = NULL; /* Close the mapping object */ CloseHandle(self->map_handle); + self->map_handle = NULL; /* Move to the desired EOF position */ #if SIZEOF_SIZE_T > 4 newSizeHigh = (DWORD)((self->offset + new_size) >> 32); @@ -479,6 +481,8 @@ return Py_None; } else { dwErrCode = GetLastError(); + CloseHandle(self->map_handle); + self->map_handle = NULL; } } else { dwErrCode = GetLastError(); @@ -1279,7 +1283,7 @@ destruct the object in the face of failure */ m_obj->data = NULL; m_obj->file_handle = INVALID_HANDLE_VALUE; - m_obj->map_handle = INVALID_HANDLE_VALUE; + m_obj->map_handle = NULL; m_obj->tagname = NULL; m_obj->offset = offset; @@ -1376,8 +1380,11 @@ m_obj->size); if (m_obj->data != NULL) return (PyObject *)m_obj; - else + else { dwErr = GetLastError(); + CloseHandle(m_obj->map_handle); + m_obj->map_handle = NULL; + } } else dwErr = GetLastError(); Py_DECREF(m_obj); From python-checkins at python.org Thu Mar 5 15:30:13 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Thu, 5 Mar 2009 15:30:13 +0100 (CET) Subject: [Python-checkins] r70190 - in python/branches/release26-maint: Lib/test/test_mmap.py Misc/NEWS Modules/mmapmodule.c Message-ID: <20090305143013.945211E4002@bag.python.org> Author: hirokazu.yamamoto Date: Thu Mar 5 15:30:13 2009 New Revision: 70190 Log: Merged revisions 70189 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70189 | hirokazu.yamamoto | 2009-03-05 23:21:12 +0900 | 4 lines Issue #5385: Fixed mmap crash after resize failure on windows. Now uses NULL instead of INVALID_HANDLE_VALUE as invalid map handle because CreateFileMapping returns NULL when error occurs. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_mmap.py python/branches/release26-maint/Misc/NEWS python/branches/release26-maint/Modules/mmapmodule.c Modified: python/branches/release26-maint/Lib/test/test_mmap.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_mmap.py (original) +++ python/branches/release26-maint/Lib/test/test_mmap.py Thu Mar 5 15:30:13 2009 @@ -504,6 +504,7 @@ data1 = "0123456789" data2 = "abcdefghij" assert len(data1) == len(data2) + # Test same tag m1 = mmap.mmap(-1, len(data1), tagname="foo") m1[:] = data1 @@ -511,6 +512,9 @@ m2[:] = data2 self.assertEquals(m1[:], data2) self.assertEquals(m2[:], data2) + m2.close() + m1.close() + # Test differnt tag m1 = mmap.mmap(-1, len(data1), tagname="foo") m1[:] = data1 @@ -518,14 +522,42 @@ m2[:] = data2 self.assertEquals(m1[:], data1) self.assertEquals(m2[:], data2) + m2.close() + m1.close() - def test_tagname_crash(self): + def test_crasher_on_windows(self): # Should not crash (Issue 1733986) m = mmap.mmap(-1, 1000, tagname="foo") try: mmap.mmap(-1, 5000, tagname="foo")[:] # same tagname, but larger size except: pass + m.close() + + # Should not crash (Issue 5385) + m = mmap.mmap(-1, 1000) + try: + m.resize(0) + except: + pass + try: + m[:] + except: + pass + m.close() + + m1 = mmap.mmap(-1, 1000) + m2 = mmap.mmap(-1, 1000) + try: + m2.resize(5000) + except: + pass + try: + m2[:] + except: + pass + m2.close() + m1.close() def test_main(): Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Thu Mar 5 15:30:13 2009 @@ -89,6 +89,8 @@ Library ------- +- Issue #5385: Fixed mmap crash after resize failure on windows. + - Issue #5179: Fixed subprocess handle leak on failure on windows. - Issue #4308: httplib.IncompleteRead's repr doesn't include all of the data all Modified: python/branches/release26-maint/Modules/mmapmodule.c ============================================================================== --- python/branches/release26-maint/Modules/mmapmodule.c (original) +++ python/branches/release26-maint/Modules/mmapmodule.c Thu Mar 5 15:30:13 2009 @@ -112,7 +112,7 @@ #ifdef MS_WINDOWS if (m_obj->data != NULL) UnmapViewOfFile (m_obj->data); - if (m_obj->map_handle != INVALID_HANDLE_VALUE) + if (m_obj->map_handle != NULL) CloseHandle (m_obj->map_handle); if (m_obj->file_handle != INVALID_HANDLE_VALUE) CloseHandle (m_obj->file_handle); @@ -147,9 +147,9 @@ UnmapViewOfFile(self->data); self->data = NULL; } - if (self->map_handle != INVALID_HANDLE_VALUE) { + if (self->map_handle != NULL) { CloseHandle(self->map_handle); - self->map_handle = INVALID_HANDLE_VALUE; + self->map_handle = NULL; } if (self->file_handle != INVALID_HANDLE_VALUE) { CloseHandle(self->file_handle); @@ -173,7 +173,7 @@ #ifdef MS_WINDOWS #define CHECK_VALID(err) \ do { \ - if (self->map_handle == INVALID_HANDLE_VALUE) { \ + if (self->map_handle == NULL) { \ PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \ return err; \ } \ @@ -441,8 +441,10 @@ DWORD off_hi, off_lo, newSizeLow, newSizeHigh; /* First, unmap the file view */ UnmapViewOfFile(self->data); + self->data = NULL; /* Close the mapping object */ CloseHandle(self->map_handle); + self->map_handle = NULL; /* Move to the desired EOF position */ #if SIZEOF_SIZE_T > 4 newSizeHigh = (DWORD)((self->offset + new_size) >> 32); @@ -479,6 +481,8 @@ return Py_None; } else { dwErrCode = GetLastError(); + CloseHandle(self->map_handle); + self->map_handle = NULL; } } else { dwErrCode = GetLastError(); @@ -1279,7 +1283,7 @@ destruct the object in the face of failure */ m_obj->data = NULL; m_obj->file_handle = INVALID_HANDLE_VALUE; - m_obj->map_handle = INVALID_HANDLE_VALUE; + m_obj->map_handle = NULL; m_obj->tagname = NULL; m_obj->offset = offset; @@ -1376,8 +1380,11 @@ m_obj->size); if (m_obj->data != NULL) return (PyObject *)m_obj; - else + else { dwErr = GetLastError(); + CloseHandle(m_obj->map_handle); + m_obj->map_handle = NULL; + } } else dwErr = GetLastError(); Py_DECREF(m_obj); From python-checkins at python.org Thu Mar 5 15:33:02 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Thu, 5 Mar 2009 15:33:02 +0100 (CET) Subject: [Python-checkins] r70191 - in python/branches/py3k: Lib/test/test_mmap.py Misc/NEWS Modules/mmapmodule.c Message-ID: <20090305143302.A3ECA1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Thu Mar 5 15:33:01 2009 New Revision: 70191 Log: Merged revisions 70189 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70189 | hirokazu.yamamoto | 2009-03-05 23:21:12 +0900 | 4 lines Issue #5385: Fixed mmap crash after resize failure on windows. Now uses NULL instead of INVALID_HANDLE_VALUE as invalid map handle because CreateFileMapping returns NULL when error occurs. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_mmap.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/mmapmodule.c Modified: python/branches/py3k/Lib/test/test_mmap.py ============================================================================== --- python/branches/py3k/Lib/test/test_mmap.py (original) +++ python/branches/py3k/Lib/test/test_mmap.py Thu Mar 5 15:33:01 2009 @@ -509,6 +509,7 @@ data1 = b"0123456789" data2 = b"abcdefghij" assert len(data1) == len(data2) + # Test same tag m1 = mmap.mmap(-1, len(data1), tagname="foo") m1[:] = data1 @@ -516,6 +517,9 @@ m2[:] = data2 self.assertEquals(m1[:], data2) self.assertEquals(m2[:], data2) + m2.close() + m1.close() + # Test differnt tag m1 = mmap.mmap(-1, len(data1), tagname="foo") m1[:] = data1 @@ -523,14 +527,42 @@ m2[:] = data2 self.assertEquals(m1[:], data1) self.assertEquals(m2[:], data2) + m2.close() + m1.close() - def test_tagname_crash(self): + def test_crasher_on_windows(self): # Should not crash (Issue 1733986) m = mmap.mmap(-1, 1000, tagname="foo") try: mmap.mmap(-1, 5000, tagname="foo")[:] # same tagname, but larger size except: pass + m.close() + + # Should not crash (Issue 5385) + m = mmap.mmap(-1, 1000) + try: + m.resize(0) + except: + pass + try: + m[:] + except: + pass + m.close() + + m1 = mmap.mmap(-1, 1000) + m2 = mmap.mmap(-1, 1000) + try: + m2.resize(5000) + except: + pass + try: + m2[:] + except: + pass + m2.close() + m1.close() def test_main(): Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Mar 5 15:33:01 2009 @@ -183,6 +183,8 @@ Library ------- +- Issue #5385: Fixed mmap crash after resize failure on windows. + - Issue #5179: Fixed subprocess handle leak on failure on windows. - PEP 372: Added collections.OrderedDict(). Modified: python/branches/py3k/Modules/mmapmodule.c ============================================================================== --- python/branches/py3k/Modules/mmapmodule.c (original) +++ python/branches/py3k/Modules/mmapmodule.c Thu Mar 5 15:33:01 2009 @@ -113,7 +113,7 @@ #ifdef MS_WINDOWS if (m_obj->data != NULL) UnmapViewOfFile (m_obj->data); - if (m_obj->map_handle != INVALID_HANDLE_VALUE) + if (m_obj->map_handle != NULL) CloseHandle (m_obj->map_handle); if (m_obj->file_handle != INVALID_HANDLE_VALUE) CloseHandle (m_obj->file_handle); @@ -153,9 +153,9 @@ UnmapViewOfFile(self->data); self->data = NULL; } - if (self->map_handle != INVALID_HANDLE_VALUE) { + if (self->map_handle != NULL) { CloseHandle(self->map_handle); - self->map_handle = INVALID_HANDLE_VALUE; + self->map_handle = NULL; } if (self->file_handle != INVALID_HANDLE_VALUE) { CloseHandle(self->file_handle); @@ -179,7 +179,7 @@ #ifdef MS_WINDOWS #define CHECK_VALID(err) \ do { \ - if (self->map_handle == INVALID_HANDLE_VALUE) { \ + if (self->map_handle == NULL) { \ PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \ return err; \ } \ @@ -452,8 +452,10 @@ DWORD off_hi, off_lo, newSizeLow, newSizeHigh; /* First, unmap the file view */ UnmapViewOfFile(self->data); + self->data = NULL; /* Close the mapping object */ CloseHandle(self->map_handle); + self->map_handle = NULL; /* Move to the desired EOF position */ #if SIZEOF_SIZE_T > 4 newSizeHigh = (DWORD)((self->offset + new_size) >> 32); @@ -490,6 +492,8 @@ return Py_None; } else { dwErrCode = GetLastError(); + CloseHandle(self->map_handle); + self->map_handle = NULL; } } else { dwErrCode = GetLastError(); @@ -1202,7 +1206,7 @@ destruct the object in the face of failure */ m_obj->data = NULL; m_obj->file_handle = INVALID_HANDLE_VALUE; - m_obj->map_handle = INVALID_HANDLE_VALUE; + m_obj->map_handle = NULL; m_obj->tagname = NULL; m_obj->offset = offset; @@ -1300,8 +1304,11 @@ m_obj->size); if (m_obj->data != NULL) return (PyObject *)m_obj; - else + else { dwErr = GetLastError(); + CloseHandle(m_obj->map_handle); + m_obj->map_handle = NULL; + } } else dwErr = GetLastError(); Py_DECREF(m_obj); From python-checkins at python.org Thu Mar 5 15:44:34 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Thu, 5 Mar 2009 15:44:34 +0100 (CET) Subject: [Python-checkins] r70192 - in python/branches/release30-maint: Lib/test/test_mmap.py Misc/NEWS Modules/mmapmodule.c Message-ID: <20090305144434.6B1491E4002@bag.python.org> Author: hirokazu.yamamoto Date: Thu Mar 5 15:44:34 2009 New Revision: 70192 Log: Merged revisions 70191 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70191 | hirokazu.yamamoto | 2009-03-05 23:33:01 +0900 | 12 lines Merged revisions 70189 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70189 | hirokazu.yamamoto | 2009-03-05 23:21:12 +0900 | 4 lines Issue #5385: Fixed mmap crash after resize failure on windows. Now uses NULL instead of INVALID_HANDLE_VALUE as invalid map handle because CreateFileMapping returns NULL when error occurs. ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/test/test_mmap.py python/branches/release30-maint/Misc/NEWS python/branches/release30-maint/Modules/mmapmodule.c Modified: python/branches/release30-maint/Lib/test/test_mmap.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_mmap.py (original) +++ python/branches/release30-maint/Lib/test/test_mmap.py Thu Mar 5 15:44:34 2009 @@ -509,6 +509,7 @@ data1 = b"0123456789" data2 = b"abcdefghij" assert len(data1) == len(data2) + # Test same tag m1 = mmap.mmap(-1, len(data1), tagname="foo") m1[:] = data1 @@ -516,6 +517,9 @@ m2[:] = data2 self.assertEquals(m1[:], data2) self.assertEquals(m2[:], data2) + m2.close() + m1.close() + # Test differnt tag m1 = mmap.mmap(-1, len(data1), tagname="foo") m1[:] = data1 @@ -523,14 +527,42 @@ m2[:] = data2 self.assertEquals(m1[:], data1) self.assertEquals(m2[:], data2) + m2.close() + m1.close() - def test_tagname_crash(self): + def test_crasher_on_windows(self): # Should not crash (Issue 1733986) m = mmap.mmap(-1, 1000, tagname="foo") try: mmap.mmap(-1, 5000, tagname="foo")[:] # same tagname, but larger size except: pass + m.close() + + # Should not crash (Issue 5385) + m = mmap.mmap(-1, 1000) + try: + m.resize(0) + except: + pass + try: + m[:] + except: + pass + m.close() + + m1 = mmap.mmap(-1, 1000) + m2 = mmap.mmap(-1, 1000) + try: + m2.resize(5000) + except: + pass + try: + m2[:] + except: + pass + m2.close() + m1.close() def test_main(): Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Thu Mar 5 15:44:34 2009 @@ -149,6 +149,8 @@ Library ------- +- Issue #5385: Fixed mmap crash after resize failure on windows. + - Issue #1733986: Fixed mmap crash in accessing elements of second map object with same tagname but larger size than first map. (Windows) Modified: python/branches/release30-maint/Modules/mmapmodule.c ============================================================================== --- python/branches/release30-maint/Modules/mmapmodule.c (original) +++ python/branches/release30-maint/Modules/mmapmodule.c Thu Mar 5 15:44:34 2009 @@ -113,7 +113,7 @@ #ifdef MS_WINDOWS if (m_obj->data != NULL) UnmapViewOfFile (m_obj->data); - if (m_obj->map_handle != INVALID_HANDLE_VALUE) + if (m_obj->map_handle != NULL) CloseHandle (m_obj->map_handle); if (m_obj->file_handle != INVALID_HANDLE_VALUE) CloseHandle (m_obj->file_handle); @@ -153,9 +153,9 @@ UnmapViewOfFile(self->data); self->data = NULL; } - if (self->map_handle != INVALID_HANDLE_VALUE) { + if (self->map_handle != NULL) { CloseHandle(self->map_handle); - self->map_handle = INVALID_HANDLE_VALUE; + self->map_handle = NULL; } if (self->file_handle != INVALID_HANDLE_VALUE) { CloseHandle(self->file_handle); @@ -179,7 +179,7 @@ #ifdef MS_WINDOWS #define CHECK_VALID(err) \ do { \ - if (self->map_handle == INVALID_HANDLE_VALUE) { \ + if (self->map_handle == NULL) { \ PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \ return err; \ } \ @@ -452,8 +452,10 @@ DWORD off_hi, off_lo, newSizeLow, newSizeHigh; /* First, unmap the file view */ UnmapViewOfFile(self->data); + self->data = NULL; /* Close the mapping object */ CloseHandle(self->map_handle); + self->map_handle = NULL; /* Move to the desired EOF position */ #if SIZEOF_SIZE_T > 4 newSizeHigh = (DWORD)((self->offset + new_size) >> 32); @@ -490,6 +492,8 @@ return Py_None; } else { dwErrCode = GetLastError(); + CloseHandle(self->map_handle); + self->map_handle = NULL; } } else { dwErrCode = GetLastError(); @@ -1202,7 +1206,7 @@ destruct the object in the face of failure */ m_obj->data = NULL; m_obj->file_handle = INVALID_HANDLE_VALUE; - m_obj->map_handle = INVALID_HANDLE_VALUE; + m_obj->map_handle = NULL; m_obj->tagname = NULL; m_obj->offset = offset; @@ -1300,8 +1304,11 @@ m_obj->size); if (m_obj->data != NULL) return (PyObject *)m_obj; - else + else { dwErr = GetLastError(); + CloseHandle(m_obj->map_handle); + m_obj->map_handle = NULL; + } } else dwErr = GetLastError(); Py_DECREF(m_obj); From python-checkins at python.org Thu Mar 5 15:52:44 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Thu, 5 Mar 2009 15:52:44 +0100 (CET) Subject: [Python-checkins] r70193 - python/trunk/Lib/test/test_mmap.py Message-ID: <20090305145244.A3B571E4002@bag.python.org> Author: hirokazu.yamamoto Date: Thu Mar 5 15:52:44 2009 New Revision: 70193 Log: mmap.resize for anonymous map is not working yet, so changed to real file mapping... Modified: python/trunk/Lib/test/test_mmap.py Modified: python/trunk/Lib/test/test_mmap.py ============================================================================== --- python/trunk/Lib/test/test_mmap.py (original) +++ python/trunk/Lib/test/test_mmap.py Thu Mar 5 15:52:44 2009 @@ -535,9 +535,12 @@ m.close() # Should not crash (Issue 5385) - m = mmap.mmap(-1, 1000) + open(TESTFN, "wb").write("x"*10) + f = open(TESTFN, "r+b") + m = mmap.mmap(f.fileno(), 0) + f.close() try: - m.resize(0) + m.resize(0) # will raise WindowsError except: pass try: @@ -546,19 +549,6 @@ pass m.close() - m1 = mmap.mmap(-1, 1000) - m2 = mmap.mmap(-1, 1000) - try: - m2.resize(5000) - except: - pass - try: - m2[:] - except: - pass - m2.close() - m1.close() - def test_main(): run_unittest(MmapTests) From python-checkins at python.org Thu Mar 5 15:58:35 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Thu, 5 Mar 2009 15:58:35 +0100 (CET) Subject: [Python-checkins] r70194 - in python/branches/release26-maint: Lib/test/test_mmap.py Message-ID: <20090305145835.0B7041E4002@bag.python.org> Author: hirokazu.yamamoto Date: Thu Mar 5 15:58:34 2009 New Revision: 70194 Log: Merged revisions 70193 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70193 | hirokazu.yamamoto | 2009-03-05 23:52:44 +0900 | 1 line mmap.resize for anonymous map is not working yet, so changed to real file mapping... ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_mmap.py Modified: python/branches/release26-maint/Lib/test/test_mmap.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_mmap.py (original) +++ python/branches/release26-maint/Lib/test/test_mmap.py Thu Mar 5 15:58:34 2009 @@ -535,9 +535,12 @@ m.close() # Should not crash (Issue 5385) - m = mmap.mmap(-1, 1000) + open(TESTFN, "wb").write("x"*10) + f = open(TESTFN, "r+b") + m = mmap.mmap(f.fileno(), 0) + f.close() try: - m.resize(0) + m.resize(0) # will raise WindowsError except: pass try: @@ -546,19 +549,6 @@ pass m.close() - m1 = mmap.mmap(-1, 1000) - m2 = mmap.mmap(-1, 1000) - try: - m2.resize(5000) - except: - pass - try: - m2[:] - except: - pass - m2.close() - m1.close() - def test_main(): run_unittest(MmapTests) From python-checkins at python.org Thu Mar 5 16:00:28 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Thu, 5 Mar 2009 16:00:28 +0100 (CET) Subject: [Python-checkins] r70195 - in python/branches/py3k: Lib/test/test_mmap.py Message-ID: <20090305150028.B96941E4030@bag.python.org> Author: hirokazu.yamamoto Date: Thu Mar 5 16:00:28 2009 New Revision: 70195 Log: Merged revisions 70193 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70193 | hirokazu.yamamoto | 2009-03-05 23:52:44 +0900 | 1 line mmap.resize for anonymous map is not working yet, so changed to real file mapping... ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_mmap.py Modified: python/branches/py3k/Lib/test/test_mmap.py ============================================================================== --- python/branches/py3k/Lib/test/test_mmap.py (original) +++ python/branches/py3k/Lib/test/test_mmap.py Thu Mar 5 16:00:28 2009 @@ -540,9 +540,12 @@ m.close() # Should not crash (Issue 5385) - m = mmap.mmap(-1, 1000) + open(TESTFN, "wb").write(b"x"*10) + f = open(TESTFN, "r+b") + m = mmap.mmap(f.fileno(), 0) + f.close() try: - m.resize(0) + m.resize(0) # will raise WindowsError except: pass try: @@ -551,19 +554,6 @@ pass m.close() - m1 = mmap.mmap(-1, 1000) - m2 = mmap.mmap(-1, 1000) - try: - m2.resize(5000) - except: - pass - try: - m2[:] - except: - pass - m2.close() - m1.close() - def test_main(): run_unittest(MmapTests) From python-checkins at python.org Thu Mar 5 16:05:07 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Thu, 5 Mar 2009 16:05:07 +0100 (CET) Subject: [Python-checkins] r70196 - in python/branches/release30-maint: Lib/test/test_mmap.py Message-ID: <20090305150507.BADBF1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Thu Mar 5 16:05:07 2009 New Revision: 70196 Log: Merged revisions 70195 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70195 | hirokazu.yamamoto | 2009-03-06 00:00:28 +0900 | 9 lines Merged revisions 70193 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70193 | hirokazu.yamamoto | 2009-03-05 23:52:44 +0900 | 1 line mmap.resize for anonymous map is not working yet, so changed to real file mapping... ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/test/test_mmap.py Modified: python/branches/release30-maint/Lib/test/test_mmap.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_mmap.py (original) +++ python/branches/release30-maint/Lib/test/test_mmap.py Thu Mar 5 16:05:07 2009 @@ -540,9 +540,12 @@ m.close() # Should not crash (Issue 5385) - m = mmap.mmap(-1, 1000) + open(TESTFN, "wb").write(b"x"*10) + f = open(TESTFN, "r+b") + m = mmap.mmap(f.fileno(), 0) + f.close() try: - m.resize(0) + m.resize(0) # will raise WindowsError except: pass try: @@ -551,19 +554,6 @@ pass m.close() - m1 = mmap.mmap(-1, 1000) - m2 = mmap.mmap(-1, 1000) - try: - m2.resize(5000) - except: - pass - try: - m2[:] - except: - pass - m2.close() - m1.close() - def test_main(): run_unittest(MmapTests) From buildbot at python.org Thu Mar 5 16:19:39 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 15:19:39 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090305151939.B826D1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/162 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Thu Mar 5 16:43:22 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 15:43:22 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 2.6 Message-ID: <20090305154322.A6FFC1E400C@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%202.6/builds/157 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 ====================================================================== FAIL: test01_basic_replication (bsddb.test.test_replication.DBReplicationManager) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.6.klose-debian-ppc/build/Lib/bsddb/test/test_replication.py", line 134, in test01_basic_replication self.assertTrue(time.time() The Buildbot has detected a new failure of i386 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%202.6/builds/166 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Thu Mar 5 17:49:56 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 16:49:56 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090305164956.3AC041E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/221 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Thu Mar 5 18:04:08 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 17:04:08 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090305170408.B1B991E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/370 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Thu Mar 5 18:15:22 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 17:15:22 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090305171522.AA0121E4048@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/196 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: 3 tests failed: test_distutils test_posix test_subprocess ====================================================================== FAIL: test_get_python_inc (distutils.tests.test_sysconfig.SysconfigTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/distutils/tests/test_sysconfig.py", line 45, in test_get_python_inc self.assert_(os.path.isdir(inc_dir), inc_dir) AssertionError: /home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/Include ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_subprocess.py", line 115, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From buildbot at python.org Thu Mar 5 19:40:15 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 18:40:15 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.0 Message-ID: <20090305184015.AC7281E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.0/builds/192 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Thu Mar 5 20:37:37 2009 From: python-checkins at python.org (jesus.cea) Date: Thu, 5 Mar 2009 20:37:37 +0100 (CET) Subject: [Python-checkins] r70197 - python/trunk/Doc/library/bsddb.rst Message-ID: <20090305193737.C93891E4002@bag.python.org> Author: jesus.cea Date: Thu Mar 5 20:37:37 2009 New Revision: 70197 Log: Minor bsddb documentation glitch Modified: python/trunk/Doc/library/bsddb.rst Modified: python/trunk/Doc/library/bsddb.rst ============================================================================== --- python/trunk/Doc/library/bsddb.rst (original) +++ python/trunk/Doc/library/bsddb.rst Thu Mar 5 20:37:37 2009 @@ -17,7 +17,7 @@ objects the user must serialize them somehow, typically using :func:`marshal.dumps` or :func:`pickle.dumps`. -The :mod:`bsddb` module requires a Berkeley DB library version from 3.3 thru +The :mod:`bsddb` module requires a Berkeley DB library version from 4.0 thru 4.7. From buildbot at python.org Thu Mar 5 20:46:04 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 19:46:04 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 2.6 Message-ID: <20090305194604.C1AFF1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%202.6/builds/157 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/home/pybot/buildarea/2.6.klose-debian-ia64/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/home/pybot/buildarea/2.6.klose-debian-ia64/build/Lib/threading.py", line 477, in run self.__target(*self.__args, **self.__kwargs) File "/home/pybot/buildarea/2.6.klose-debian-ia64/build/Lib/bsddb/test/test_thread.py", line 306, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home/pybot/buildarea/2.6.klose-debian-ia64/build/Lib/bsddb/dbutils.py", line 68, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30994, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') Traceback (most recent call last): File "/home/pybot/buildarea/2.6.klose-debian-ia64/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/home/pybot/buildarea/2.6.klose-debian-ia64/build/Lib/threading.py", line 477, in run self.__target(*self.__args, **self.__kwargs) File "/home/pybot/buildarea/2.6.klose-debian-ia64/build/Lib/bsddb/test/test_thread.py", line 306, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home/pybot/buildarea/2.6.klose-debian-ia64/build/Lib/bsddb/dbutils.py", line 68, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30994, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') 1 test failed: test_urllib2 ====================================================================== ERROR: test_file (test.test_urllib2.HandlerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.6.klose-debian-ia64/build/Lib/test/test_urllib2.py", line 653, in test_file h.file_open, Request(url)) File "/home/pybot/buildarea/2.6.klose-debian-ia64/build/Lib/unittest.py", line 336, in failUnlessRaises callableObj(*args, **kwargs) File "/home/pybot/buildarea/2.6.klose-debian-ia64/build/Lib/urllib2.py", line 1226, in file_open return self.open_local_file(req) File "/home/pybot/buildarea/2.6.klose-debian-ia64/build/Lib/urllib2.py", line 1257, in open_local_file (not port and socket.gethostbyname(host) in self.get_names()): gaierror: [Errno -2] Name or service not known make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Mar 5 22:41:51 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 5 Mar 2009 22:41:51 +0100 (CET) Subject: [Python-checkins] r70198 - python/branches/py3k/Modules/_iomodule.h Message-ID: <20090305214151.33D5A1E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 5 22:41:50 2009 New Revision: 70198 Log: properly export PyExc_BlockingIOError Modified: python/branches/py3k/Modules/_iomodule.h Modified: python/branches/py3k/Modules/_iomodule.h ============================================================================== --- python/branches/py3k/Modules/_iomodule.h (original) +++ python/branches/py3k/Modules/_iomodule.h Thu Mar 5 22:41:50 2009 @@ -64,7 +64,7 @@ PyObject *filename; /* Not used, but part of the IOError object */ Py_ssize_t written; } PyBlockingIOErrorObject; -PyObject *PyExc_BlockingIOError; +PyAPI_DATA(PyObject *) PyExc_BlockingIOError; /* * Offset type for positioning. From python-checkins at python.org Thu Mar 5 22:47:34 2009 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 5 Mar 2009 22:47:34 +0100 (CET) Subject: [Python-checkins] r70199 - python/branches/release25-maint/Objects/unicodeobject.c Message-ID: <20090305214734.2AFD91E4002@bag.python.org> Author: guido.van.rossum Date: Thu Mar 5 22:47:33 2009 New Revision: 70199 Log: Avoid potential for undefined variable 'startinpos' in PyUnicode_DecodeUTF7(). See issue #5389. Modified: python/branches/release25-maint/Objects/unicodeobject.c Modified: python/branches/release25-maint/Objects/unicodeobject.c ============================================================================== --- python/branches/release25-maint/Objects/unicodeobject.c (original) +++ python/branches/release25-maint/Objects/unicodeobject.c Thu Mar 5 22:47:33 2009 @@ -1012,7 +1012,7 @@ } } else if (SPECIAL(ch,0,0)) { errmsg = "unexpected special character"; - goto utf7Error; + goto utf7Error; } else { *p++ = ch; } @@ -1036,9 +1036,10 @@ } } else if (SPECIAL(ch,0,0)) { + startinpos = s-starts; errmsg = "unexpected special character"; s++; - goto utf7Error; + goto utf7Error; } else { *p++ = ch; From python-checkins at python.org Thu Mar 5 22:49:41 2009 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 5 Mar 2009 22:49:41 +0100 (CET) Subject: [Python-checkins] r70200 - python/branches/release25-maint/Misc/NEWS Message-ID: <20090305214941.371F91E4002@bag.python.org> Author: guido.van.rossum Date: Thu Mar 5 22:49:40 2009 New Revision: 70200 Log: News for issue 5389 fix. Modified: python/branches/release25-maint/Misc/NEWS Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Thu Mar 5 22:49:40 2009 @@ -12,6 +12,9 @@ Core and builtins ----------------- +- Issue #5389: Avoid potential for undefined variable 'startinpos' in + PyUnicode_DecodeUTF7(). + - Revert patch for #1706039, as it can crash the interpreter. - Added test case to ensure attempts to read from a file opened for writing From buildbot at python.org Thu Mar 5 23:05:51 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 22:05:51 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090305220551.B55F21E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/377 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Mar 5 23:33:59 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 5 Mar 2009 23:33:59 +0100 (CET) Subject: [Python-checkins] r70201 - in python/branches/py3k: Doc/library/io.rst Lib/_pyio.py Message-ID: <20090305223359.7BD171E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 5 23:33:59 2009 New Revision: 70201 Log: remove usage of the deprecated max_buffer_size Modified: python/branches/py3k/Doc/library/io.rst python/branches/py3k/Lib/_pyio.py Modified: python/branches/py3k/Doc/library/io.rst ============================================================================== --- python/branches/py3k/Doc/library/io.rst (original) +++ python/branches/py3k/Doc/library/io.rst Thu Mar 5 23:33:59 2009 @@ -505,8 +505,9 @@ The constructor creates a :class:`BufferedWriter` for the given writeable *raw* stream. If the *buffer_size* is not given, it defaults to - :data:`DEFAULT_BUFFER_SIZE`. If *max_buffer_size* is omitted, it defaults to - twice the buffer size. + :data:`DEFAULT_BUFFER_SIZE`. + + *max_buffer_size* is unused and deprecated. :class:`BufferedWriter` provides or overrides these methods in addition to those from :class:`BufferedIOBase` and :class:`IOBase`: @@ -532,8 +533,9 @@ *reader* and *writer* are :class:`RawIOBase` objects that are readable and writeable respectively. If the *buffer_size* is omitted it defaults to - :data:`DEFAULT_BUFFER_SIZE`. The *max_buffer_size* (for the buffered writer) - defaults to twice the buffer size. + :data:`DEFAULT_BUFFER_SIZE`. + + *max_buffer_size* is unused and deprecated. :class:`BufferedRWPair` implements all of :class:`BufferedIOBase`\'s methods. @@ -545,8 +547,9 @@ The constructor creates a reader and writer for a seekable raw stream, given in the first argument. If the *buffer_size* is omitted it defaults to - :data:`DEFAULT_BUFFER_SIZE`. The *max_buffer_size* (for the buffered writer) - defaults to twice the buffer size. + :data:`DEFAULT_BUFFER_SIZE`. + + *max_buffer_size* is unused and deprecated. :class:`BufferedRandom` is capable of anything :class:`BufferedReader` or :class:`BufferedWriter` can do. Modified: python/branches/py3k/Lib/_pyio.py ============================================================================== --- python/branches/py3k/Lib/_pyio.py (original) +++ python/branches/py3k/Lib/_pyio.py Thu Mar 5 23:33:59 2009 @@ -971,9 +971,6 @@ if buffer_size <= 0: raise ValueError("invalid buffer size") self.buffer_size = buffer_size - self.max_buffer_size = (2*buffer_size - if max_buffer_size is None - else max_buffer_size) self._write_buf = bytearray() self._write_lock = Lock() @@ -1000,12 +997,12 @@ try: self._flush_unlocked() except BlockingIOError as e: - if len(self._write_buf) > self.max_buffer_size: - # We've hit max_buffer_size. We have to accept a - # partial write and cut back our buffer. - overage = len(self._write_buf) - self.max_buffer_size + if len(self._write_buf) > self.buffer_size: + # We've hit the buffer_size. We have to accept a partial + # write and cut back our buffer. + overage = len(self._write_buf) - self.buffer_size written -= overage - self._write_buf = self._write_buf[:self.max_buffer_size] + self._write_buf = self._write_buf[:self.buffer_size] raise BlockingIOError(e.errno, e.strerror, written) return written From buildbot at python.org Thu Mar 5 23:53:05 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 05 Mar 2009 22:53:05 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090305225305.76CA51E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/475 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_pipes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Mar 5 23:53:54 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 5 Mar 2009 23:53:54 +0100 (CET) Subject: [Python-checkins] r70202 - python/branches/py3k Message-ID: <20090305225354.DE4441E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 5 23:53:54 2009 New Revision: 70202 Log: Blocked revisions 70166-70167,70169,70176,70178,70197 via svnmerge ........ r70166 | georg.brandl | 2009-03-04 12:24:41 -0600 (Wed, 04 Mar 2009) | 2 lines Remove obsolete stuff from string module docs. ........ r70167 | ronald.oussoren | 2009-03-04 15:07:19 -0600 (Wed, 04 Mar 2009) | 2 lines Fix issue 5224. ........ r70169 | ronald.oussoren | 2009-03-04 15:12:17 -0600 (Wed, 04 Mar 2009) | 2 lines Fix for issue 5226. ........ r70176 | ronald.oussoren | 2009-03-04 15:35:05 -0600 (Wed, 04 Mar 2009) | 2 lines Fixes issues 3883 and 5194 ........ r70178 | ronald.oussoren | 2009-03-04 16:49:36 -0600 (Wed, 04 Mar 2009) | 2 lines Fix for issue #1113328. ........ r70197 | jesus.cea | 2009-03-05 13:37:37 -0600 (Thu, 05 Mar 2009) | 1 line Minor bsddb documentation glitch ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Fri Mar 6 04:04:07 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Fri, 6 Mar 2009 04:04:07 +0100 (CET) Subject: [Python-checkins] r70203 - in python/branches/py3k: Lib/test/test_array.py Misc/NEWS Modules/arraymodule.c Message-ID: <20090306030407.9D03A1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Fri Mar 6 04:04:07 2009 New Revision: 70203 Log: Issue #5334: array.fromfile() failed to insert values when EOFError was raised. Reviewed by Benjamin Peterson. Modified: python/branches/py3k/Lib/test/test_array.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/arraymodule.c Modified: python/branches/py3k/Lib/test/test_array.py ============================================================================== --- python/branches/py3k/Lib/test/test_array.py (original) +++ python/branches/py3k/Lib/test/test_array.py Fri Mar 6 04:04:07 2009 @@ -174,9 +174,8 @@ b.fromfile(f, len(self.example)) self.assertEqual(b, array.array(self.typecode, self.example)) self.assertNotEqual(a, b) - b.fromfile(f, len(self.example)) + self.assertRaises(EOFError, b.fromfile, f, len(self.example)+1) self.assertEqual(a, b) - self.assertRaises(EOFError, b.fromfile, f, 1) f.close() finally: if not f.closed: Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Mar 6 04:04:07 2009 @@ -183,6 +183,8 @@ Library ------- +- Issue #5334: array.fromfile() failed to insert values when EOFError was raised. + - Issue #5385: Fixed mmap crash after resize failure on windows. - Issue #5179: Fixed subprocess handle leak on failure on windows. Modified: python/branches/py3k/Modules/arraymodule.c ============================================================================== --- python/branches/py3k/Modules/arraymodule.c (original) +++ python/branches/py3k/Modules/arraymodule.c Fri Mar 6 04:04:07 2009 @@ -1201,6 +1201,7 @@ PyObject *f, *b, *res; Py_ssize_t itemsize = self->ob_descr->itemsize; Py_ssize_t n, nbytes; + int not_enough_bytes; if (!PyArg_ParseTuple(args, "On:fromfile", &f, &n)) return NULL; @@ -1222,12 +1223,7 @@ return NULL; } - if (PyBytes_GET_SIZE(b) != nbytes) { - PyErr_SetString(PyExc_EOFError, - "read() didn't return enough bytes"); - Py_DECREF(b); - return NULL; - } + not_enough_bytes = (PyBytes_GET_SIZE(b) != nbytes); args = Py_BuildValue("(O)", b); Py_DECREF(b); @@ -1236,6 +1232,15 @@ res = array_fromstring(self, args); Py_DECREF(args); + if (res == NULL) + return NULL; + + if (not_enough_bytes) { + PyErr_SetString(PyExc_EOFError, + "read() didn't return enough bytes"); + Py_DECREF(res); + return NULL; + } return res; } From python-checkins at python.org Fri Mar 6 04:19:56 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Fri, 6 Mar 2009 04:19:56 +0100 (CET) Subject: [Python-checkins] r70204 - in python/branches/release30-maint: Lib/test/test_array.py Misc/NEWS Modules/arraymodule.c Message-ID: <20090306031956.7E7411E4002@bag.python.org> Author: hirokazu.yamamoto Date: Fri Mar 6 04:19:56 2009 New Revision: 70204 Log: Merged revisions 70203 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70203 | hirokazu.yamamoto | 2009-03-06 12:04:07 +0900 | 2 lines Issue #5334: array.fromfile() failed to insert values when EOFError was raised. Reviewed by Benjamin Peterson. ........ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/test/test_array.py python/branches/release30-maint/Misc/NEWS python/branches/release30-maint/Modules/arraymodule.c Modified: python/branches/release30-maint/Lib/test/test_array.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_array.py (original) +++ python/branches/release30-maint/Lib/test/test_array.py Fri Mar 6 04:19:56 2009 @@ -174,9 +174,8 @@ b.fromfile(f, len(self.example)) self.assertEqual(b, array.array(self.typecode, self.example)) self.assertNotEqual(a, b) - b.fromfile(f, len(self.example)) + self.assertRaises(EOFError, b.fromfile, f, len(self.example)+1) self.assertEqual(a, b) - self.assertRaises(EOFError, b.fromfile, f, 1) f.close() finally: if not f.closed: Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Fri Mar 6 04:19:56 2009 @@ -149,6 +149,8 @@ Library ------- +- Issue #5334: array.fromfile() failed to insert values when EOFError was raised. + - Issue #5385: Fixed mmap crash after resize failure on windows. - Issue #1733986: Fixed mmap crash in accessing elements of second map object Modified: python/branches/release30-maint/Modules/arraymodule.c ============================================================================== --- python/branches/release30-maint/Modules/arraymodule.c (original) +++ python/branches/release30-maint/Modules/arraymodule.c Fri Mar 6 04:19:56 2009 @@ -1201,6 +1201,7 @@ PyObject *f, *b, *res; Py_ssize_t itemsize = self->ob_descr->itemsize; Py_ssize_t n, nbytes; + int not_enough_bytes; if (!PyArg_ParseTuple(args, "On:fromfile", &f, &n)) return NULL; @@ -1222,12 +1223,7 @@ return NULL; } - if (PyBytes_GET_SIZE(b) != nbytes) { - PyErr_SetString(PyExc_EOFError, - "read() didn't return enough bytes"); - Py_DECREF(b); - return NULL; - } + not_enough_bytes = (PyBytes_GET_SIZE(b) != nbytes); args = Py_BuildValue("(O)", b); Py_DECREF(b); @@ -1236,6 +1232,15 @@ res = array_fromstring(self, args); Py_DECREF(args); + if (res == NULL) + return NULL; + + if (not_enough_bytes) { + PyErr_SetString(PyExc_EOFError, + "read() didn't return enough bytes"); + Py_DECREF(res); + return NULL; + } return res; } From buildbot at python.org Fri Mar 6 04:27:04 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 06 Mar 2009 03:27:04 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090306032704.9CC241E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/380 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Fri Mar 6 04:49:25 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 06 Mar 2009 03:49:25 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.0 Message-ID: <20090306034928.3C9511E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.0/builds/171 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Fri Mar 6 05:07:12 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 06 Mar 2009 04:07:12 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090306040712.98E781E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/418 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Fri Mar 6 05:37:01 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 06 Mar 2009 04:37:01 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090306043701.C81461E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/198 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: 6 tests failed: test_codecs test_distutils test_io test_posix test_subprocess test_traceback ====================================================================== ERROR: test_basics (test.test_codecs.BasicUnicodeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_codecs.py", line 1344, in test_basics encodedresult += encoder.encode(c) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 22, in encode return codecs.ascii_encode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_encode' ====================================================================== ERROR: test_decoder_state (test.test_codecs.BasicUnicodeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_codecs.py", line 1429, in test_decoder_state self.check_state_handling_decode(encoding, u, u.encode(encoding)) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_codecs.py", line 30, in check_state_handling_decode part1 = d.decode(s[:i]) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_decode' ====================================================================== FAIL: test_get_python_inc (distutils.tests.test_sysconfig.SysconfigTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/distutils/tests/test_sysconfig.py", line 45, in test_get_python_inc self.assert_(os.path.isdir(inc_dir), inc_dir) AssertionError: /home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/Include ====================================================================== ERROR: testBasicIO (test.test_io.TextIOWrapperTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_io.py", line 939, in testBasicIO self.assertEquals(f.write("abc"), 3) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1494, in write b = encoder.encode(s) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 22, in encode return codecs.ascii_encode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_encode' ====================================================================== ERROR: testEncodingErrorsReading (test.test_io.TextIOWrapperTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_io.py", line 774, in testEncodingErrorsReading self.assertRaises(UnicodeError, t.read) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/unittest.py", line 311, in failUnlessRaises callableObj(*args, **kwargs) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1728, in read decoder.decode(self.buffer.read(), final=True)) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1299, in decode output = self.decoder.decode(input, final=final) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_decode' ====================================================================== ERROR: testEncodingErrorsWriting (test.test_io.TextIOWrapperTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_io.py", line 792, in testEncodingErrorsWriting self.assertRaises(UnicodeError, t.write, "\xff") File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/unittest.py", line 311, in failUnlessRaises callableObj(*args, **kwargs) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1494, in write b = encoder.encode(s) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 22, in encode return codecs.ascii_encode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_encode' ====================================================================== ERROR: testNewlinesInput (test.test_io.TextIOWrapperTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_io.py", line 900, in testNewlinesInput self.assertEquals(txt.readlines(), expected) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 536, in readlines return list(self) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1744, in __next__ line = self.readline() File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1817, in readline while self._read_chunk(): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1565, in _read_chunk self._set_decoded_chars(self._decoder.decode(input_chunk, eof)) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1299, in decode output = self.decoder.decode(input, final=final) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_decode' ====================================================================== ERROR: testNewlinesOutput (test.test_io.TextIOWrapperTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_io.py", line 925, in testNewlinesOutput txt.write(data) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1494, in write b = encoder.encode(s) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 22, in encode return codecs.ascii_encode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_encode' ====================================================================== ERROR: test_issue1395_1 (test.test_io.TextIOWrapperTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_io.py", line 1161, in test_issue1395_1 c = txt.read(1) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1737, in read eof = not self._read_chunk() File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1565, in _read_chunk self._set_decoded_chars(self._decoder.decode(input_chunk, eof)) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1299, in decode output = self.decoder.decode(input, final=final) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_decode' ====================================================================== ERROR: test_issue1395_2 (test.test_io.TextIOWrapperTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_io.py", line 1173, in test_issue1395_2 c = txt.read(4) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1737, in read eof = not self._read_chunk() File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1565, in _read_chunk self._set_decoded_chars(self._decoder.decode(input_chunk, eof)) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1299, in decode output = self.decoder.decode(input, final=final) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_decode' ====================================================================== ERROR: test_issue1395_3 (test.test_io.TextIOWrapperTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_io.py", line 1183, in test_issue1395_3 reads = txt.read(4) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1737, in read eof = not self._read_chunk() File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1565, in _read_chunk self._set_decoded_chars(self._decoder.decode(input_chunk, eof)) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1299, in decode output = self.decoder.decode(input, final=final) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_decode' ====================================================================== ERROR: test_issue1395_4 (test.test_io.TextIOWrapperTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_io.py", line 1194, in test_issue1395_4 reads = txt.read(4) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1737, in read eof = not self._read_chunk() File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1565, in _read_chunk self._set_decoded_chars(self._decoder.decode(input_chunk, eof)) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1299, in decode output = self.decoder.decode(input, final=final) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_decode' ====================================================================== ERROR: test_issue1395_5 (test.test_io.TextIOWrapperTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_io.py", line 1202, in test_issue1395_5 reads = txt.read(4) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1737, in read eof = not self._read_chunk() File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1565, in _read_chunk self._set_decoded_chars(self._decoder.decode(input_chunk, eof)) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1299, in decode output = self.decoder.decode(input, final=final) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_decode' ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_subprocess.py", line 115, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 ====================================================================== ERROR: test_encoded_file (test.test_traceback.SyntaxTracebackCases) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_traceback.py", line 145, in test_encoded_file do_test("", "foo", "ascii", 3) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_traceback.py", line 117, in do_test """.format(firstlines, message)) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/io.py", line 1494, in write b = encoder.encode(s) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/encodings/ascii.py", line 22, in encode return codecs.ascii_encode(input, self.errors)[0] AttributeError: 'NoneType' object has no attribute 'ascii_encode' sincerely, -The Buildbot From solipsis at pitrou.net Fri Mar 6 14:45:51 2009 From: solipsis at pitrou.net (Antoine Pitrou) Date: Fri, 6 Mar 2009 13:45:51 +0000 (UTC) Subject: [Python-checkins] =?utf-8?q?r70198_-_python/branches/py3k/Modules?= =?utf-8?q?/=5Fiomodule=2Eh?= References: <20090305214151.33D5A1E4002@bag.python.org> Message-ID: >benjamin.peterson> writes: > > Author: benjamin.peterson > Date: Thu Mar 5 22:41:50 2009 > New Revision: 70198 > > Log: > properly export PyExc_BlockingIOError Do we need this? Stuff declared in _iomodule.h is for internal consumption of the _io module, normally. From benjamin at python.org Fri Mar 6 20:54:51 2009 From: benjamin at python.org (Benjamin Peterson) Date: Fri, 6 Mar 2009 14:54:51 -0500 Subject: [Python-checkins] r70198 - python/branches/py3k/Modules/_iomodule.h In-Reply-To: References: <20090305214151.33D5A1E4002@bag.python.org> Message-ID: <1afaf6160903061154w58d08fb9q378955c2edf8eb92@mail.gmail.com> 2009/3/6 Antoine Pitrou : >>benjamin.peterson> writes: >> >> Author: benjamin.peterson >> Date: Thu Mar ?5 22:41:50 2009 >> New Revision: 70198 >> >> Log: >> properly export PyExc_BlockingIOError > > Do we need this? Stuff declared in _iomodule.h is for internal consumption of > the _io module, normally. It seems to be needed for http://bugs.python.org/issue5427. -- Regards, Benjamin From python-checkins at python.org Fri Mar 6 22:49:03 2009 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 6 Mar 2009 22:49:03 +0100 (CET) Subject: [Python-checkins] r70205 - python/branches/py3k/Modules/_textio.c Message-ID: <20090306214903.55BCB1E4002@bag.python.org> Author: antoine.pitrou Date: Fri Mar 6 22:49:02 2009 New Revision: 70205 Log: Issue #5429: unaligned access in TextIOWrapper cookie parsing (segfaults on SPARC CPUs, and possibly others) Modified: python/branches/py3k/Modules/_textio.c Modified: python/branches/py3k/Modules/_textio.c ============================================================================== --- python/branches/py3k/Modules/_textio.c (original) +++ python/branches/py3k/Modules/_textio.c Fri Mar 6 22:49:02 2009 @@ -1736,11 +1736,11 @@ } Py_DECREF(cookieLong); - cookie->start_pos = * (Py_off_t *)(buffer + OFF_START_POS); - cookie->dec_flags = * (int *) (buffer + OFF_DEC_FLAGS); - cookie->bytes_to_feed = * (int *) (buffer + OFF_BYTES_TO_FEED); - cookie->chars_to_skip = * (int *) (buffer + OFF_CHARS_TO_SKIP); - cookie->need_eof = * (char *) (buffer + OFF_NEED_EOF); + memcpy(&cookie->start_pos, buffer + OFF_START_POS, sizeof(cookie->start_pos)); + memcpy(&cookie->dec_flags, buffer + OFF_DEC_FLAGS, sizeof(cookie->dec_flags)); + memcpy(&cookie->bytes_to_feed, buffer + OFF_BYTES_TO_FEED, sizeof(cookie->bytes_to_feed)); + memcpy(&cookie->chars_to_skip, buffer + OFF_CHARS_TO_SKIP, sizeof(cookie->chars_to_skip)); + memcpy(&cookie->need_eof, buffer + OFF_NEED_EOF, sizeof(cookie->need_eof)); return 0; } @@ -1750,11 +1750,11 @@ { unsigned char buffer[COOKIE_BUF_LEN]; - * (Py_off_t *)(buffer + OFF_START_POS) = cookie->start_pos; - * (int *) (buffer + OFF_DEC_FLAGS) = cookie->dec_flags; - * (int *) (buffer + OFF_BYTES_TO_FEED) = cookie->bytes_to_feed; - * (int *) (buffer + OFF_CHARS_TO_SKIP) = cookie->chars_to_skip; - * (char *) (buffer + OFF_NEED_EOF) = cookie->need_eof; + memcpy(buffer + OFF_START_POS, &cookie->start_pos, sizeof(cookie->start_pos)); + memcpy(buffer + OFF_DEC_FLAGS, &cookie->dec_flags, sizeof(cookie->dec_flags)); + memcpy(buffer + OFF_BYTES_TO_FEED, &cookie->bytes_to_feed, sizeof(cookie->bytes_to_feed)); + memcpy(buffer + OFF_CHARS_TO_SKIP, &cookie->chars_to_skip, sizeof(cookie->chars_to_skip)); + memcpy(buffer + OFF_NEED_EOF, &cookie->need_eof, sizeof(cookie->need_eof)); return _PyLong_FromByteArray(buffer, sizeof(buffer), IS_LITTLE_ENDIAN, 0); } From python-checkins at python.org Fri Mar 6 23:11:02 2009 From: python-checkins at python.org (brett.cannon) Date: Fri, 6 Mar 2009 23:11:02 +0100 (CET) Subject: [Python-checkins] r70206 - peps/trunk/pep-0374.txt Message-ID: <20090306221102.6F4E71E4002@bag.python.org> Author: brett.cannon Date: Fri Mar 6 23:11:00 2009 New Revision: 70206 Log: Update for Mercurial 1.2. Modified: peps/trunk/pep-0374.txt Modified: peps/trunk/pep-0374.txt ============================================================================== --- peps/trunk/pep-0374.txt (original) +++ peps/trunk/pep-0374.txt Fri Mar 6 23:11:00 2009 @@ -204,7 +204,7 @@ Name Short Name Version 2.x Trunk Mirror 3.x Trunk Mirror ---------- ---------- ------- ----------------------------------- ------------------------------------------ Bazaar_ bzr 1.12 http://code.python.org/python/trunk http://code.python.org/python/3.0 -Mercurial_ hg 1.1.2 http://code.python.org/hg/trunk/ http://code.python.org/hg/branches/py3k/ +Mercurial_ hg 1.2.0 http://code.python.org/hg/trunk/ http://code.python.org/hg/branches/py3k/ git_ N/A 1.6.1 git://code.python.org/python/trunk git://code.python.org/python/branches/py3k ========== ========== ======= =================================== ========================================== @@ -1191,11 +1191,8 @@ while Mercurial and git require you to rely on a third-party for binaries. Both bzr and hg have a tortoise version while git does not. -Bazaar also has the benefit of being written in pure Python, making -a Python VM the bare minimum requirement to work. It does have Pyrex -extensions which are optional, but highly recommended for -performance reasons. Mercurial requires the compilation of an -extension module and git is pure C and thus also requires a compiler. +Bazaar and Mercurial also has the benefit of being available in pure +Python with optional extensions available for performance. CRLF -> LF Support From buildbot at python.org Fri Mar 6 23:50:02 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 06 Mar 2009 22:50:02 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090306225003.A17A91E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/445 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_multiprocessing sincerely, -The Buildbot From python-checkins at python.org Sat Mar 7 00:28:54 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 7 Mar 2009 00:28:54 +0100 (CET) Subject: [Python-checkins] r70207 - python/branches/release30-maint/Lib/queue.py Message-ID: <20090306232854.2DC021E4002@bag.python.org> Author: raymond.hettinger Date: Sat Mar 7 00:28:53 2009 New Revision: 70207 Log: Document the suggested alternative to emtpy() and full(). Modified: python/branches/release30-maint/Lib/queue.py Modified: python/branches/release30-maint/Lib/queue.py ============================================================================== --- python/branches/release30-maint/Lib/queue.py (original) +++ python/branches/release30-maint/Lib/queue.py Sat Mar 7 00:28:53 2009 @@ -91,14 +91,22 @@ return n def empty(self): - """Return True if the queue is empty, False otherwise (not reliable!).""" + """Return True if the queue is empty, False otherwise (not reliable!). + + This method is likely to be removed at some point. Use qsize() instead. + + """ self.mutex.acquire() n = not self._qsize() self.mutex.release() return n def full(self): - """Return True if the queue is full, False otherwise (not reliable!).""" + """Return True if the queue is full, False otherwise (not reliable!). + + This method is likely to be removed at some point. Use qsize() instead. + + """ self.mutex.acquire() n = 0 < self.maxsize == self._qsize() self.mutex.release() From python-checkins at python.org Sat Mar 7 00:40:56 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 7 Mar 2009 00:40:56 +0100 (CET) Subject: [Python-checkins] r70208 - in python/branches/py3k: Lib/test/test_io.py Modules/_textio.c Message-ID: <20090306234056.DBC291E4043@bag.python.org> Author: antoine.pitrou Date: Sat Mar 7 00:40:56 2009 New Revision: 70208 Log: Issue #5433: Excessive newline detection optimization in IncrementalNewlineDecoder Modified: python/branches/py3k/Lib/test/test_io.py python/branches/py3k/Modules/_textio.c Modified: python/branches/py3k/Lib/test/test_io.py ============================================================================== --- python/branches/py3k/Lib/test/test_io.py (original) +++ python/branches/py3k/Lib/test/test_io.py Sat Mar 7 00:40:56 2009 @@ -1915,6 +1915,19 @@ decoder = self.IncrementalNewlineDecoder(decoder, translate=True) self.check_newline_decoding_utf8(decoder) + def test_newline_bytes(self): + # Issue 5433: Excessive optimization in IncrementalNewlineDecoder + def _check(dec): + self.assertEquals(dec.newlines, None) + self.assertEquals(dec.decode("\u0D00"), "\u0D00") + self.assertEquals(dec.newlines, None) + self.assertEquals(dec.decode("\u0A00"), "\u0A00") + self.assertEquals(dec.newlines, None) + dec = self.IncrementalNewlineDecoder(None, translate=False) + _check(dec) + dec = self.IncrementalNewlineDecoder(None, translate=True) + _check(dec) + class CIncrementalNewlineDecoderTest(IncrementalNewlineDecoderTest): pass Modified: python/branches/py3k/Modules/_textio.c ============================================================================== --- python/branches/py3k/Modules/_textio.c (original) +++ python/branches/py3k/Modules/_textio.c Sat Mar 7 00:40:56 2009 @@ -305,22 +305,40 @@ for the \r *byte* with the libc's optimized memchr. */ if (seennl == SEEN_LF || seennl == 0) { - int has_cr, has_lf; - has_lf = (seennl == SEEN_LF) || - (memchr(in_str, '\n', len * sizeof(Py_UNICODE)) != NULL); - has_cr = (memchr(in_str, '\r', len * sizeof(Py_UNICODE)) != NULL); - if (has_lf && !has_cr) { - only_lf = 1; - seennl = SEEN_LF; - } + only_lf = !(memchr(in_str, '\r', len * sizeof(Py_UNICODE)) != NULL); } - if (!self->translate) { + if (only_lf) { + /* If not already seen, quick scan for a possible "\n" character. + (there's nothing else to be done, even when in translation mode) + */ + if (seennl == 0 && + memchr(in_str, '\n', len * sizeof(Py_UNICODE)) != NULL) { + Py_UNICODE *s, *end; + s = in_str; + end = in_str + len; + for (;;) { + Py_UNICODE c; + /* Fast loop for non-control characters */ + while (*s > '\n') + s++; + c = *s++; + if (c == '\n') { + seennl |= SEEN_LF; + break; + } + if (s > end) + break; + } + } + /* Finished: we have scanned for newlines, and none of them + need translating */ + } + else if (!self->translate) { Py_UNICODE *s, *end; + /* We have already seen all newline types, no need to scan again */ if (seennl == SEEN_ALL) goto endscan; - if (only_lf) - goto endscan; s = in_str; end = in_str + len; for (;;) { @@ -347,7 +365,7 @@ endscan: ; } - else if (!only_lf) { + else { PyObject *translated = NULL; Py_UNICODE *out_str; Py_UNICODE *in, *out, *end; From python-checkins at python.org Sat Mar 7 00:55:28 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 7 Mar 2009 00:55:28 +0100 (CET) Subject: [Python-checkins] r70209 - python/branches/py3k/Lib/queue.py Message-ID: <20090306235528.AFA221E4002@bag.python.org> Author: raymond.hettinger Date: Sat Mar 7 00:55:28 2009 New Revision: 70209 Log: Document the suggested alternative to emtpy() and full(). Modified: python/branches/py3k/Lib/queue.py Modified: python/branches/py3k/Lib/queue.py ============================================================================== --- python/branches/py3k/Lib/queue.py (original) +++ python/branches/py3k/Lib/queue.py Sat Mar 7 00:55:28 2009 @@ -91,14 +91,31 @@ return n def empty(self): - """Return True if the queue is empty, False otherwise (not reliable!).""" + """Return True if the queue is empty, False otherwise (not reliable!). + + This method is likely to be removed at some point. Use qsize() == 0 + as a direct substitute, but be aware that either approach risks a race + condition where a queue can grow before the result of empty() or + qsize() can be used. + + To create code that needs to wait for all queued tasks to be + completed, the preferred technique is to use the join() method. + + """ self.mutex.acquire() n = not self._qsize() self.mutex.release() return n def full(self): - """Return True if the queue is full, False otherwise (not reliable!).""" + """Return True if the queue is full, False otherwise (not reliable!). + + This method is likely to be removed at some point. Use qsize() == n + as a direct substitute, but be aware that either approach risks a race + condition where a queue can shrink before the result of full() or + qsize() can be used. + + """ self.mutex.acquire() n = 0 < self.maxsize == self._qsize() self.mutex.release() From python-checkins at python.org Sat Mar 7 00:57:20 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 7 Mar 2009 00:57:20 +0100 (CET) Subject: [Python-checkins] r70210 - python/branches/py3k/Modules/_textio.c Message-ID: <20090306235720.B82E71E4002@bag.python.org> Author: antoine.pitrou Date: Sat Mar 7 00:57:20 2009 New Revision: 70210 Log: Remove double negative Modified: python/branches/py3k/Modules/_textio.c Modified: python/branches/py3k/Modules/_textio.c ============================================================================== --- python/branches/py3k/Modules/_textio.c (original) +++ python/branches/py3k/Modules/_textio.c Sat Mar 7 00:57:20 2009 @@ -305,7 +305,7 @@ for the \r *byte* with the libc's optimized memchr. */ if (seennl == SEEN_LF || seennl == 0) { - only_lf = !(memchr(in_str, '\r', len * sizeof(Py_UNICODE)) != NULL); + only_lf = (memchr(in_str, '\r', len * sizeof(Py_UNICODE)) == NULL); } if (only_lf) { From python-checkins at python.org Sat Mar 7 00:59:29 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 7 Mar 2009 00:59:29 +0100 (CET) Subject: [Python-checkins] r70211 - python/branches/py3k/Lib/io.py Message-ID: <20090306235929.EE90D1E400C@bag.python.org> Author: benjamin.peterson Date: Sat Mar 7 00:59:29 2009 New Revision: 70211 Log: simplify and beautify code Modified: python/branches/py3k/Lib/io.py Modified: python/branches/py3k/Lib/io.py ============================================================================== --- python/branches/py3k/Lib/io.py (original) +++ python/branches/py3k/Lib/io.py Sat Mar 7 00:59:29 2009 @@ -58,12 +58,12 @@ import _io import abc -# open() uses st_blksize whenever we can -DEFAULT_BUFFER_SIZE = _io.DEFAULT_BUFFER_SIZE -BlockingIOError = _io.BlockingIOError -UnsupportedOperation = _io.UnsupportedOperation -open = _io.open -OpenWrapper = _io.open +from _io import (DEFAULT_BUFFER_SIZE, BlockingIOError, UnsupportedOperation, + open, FileIO, BytesIO, StringIO, BufferedReader, + BufferedWriter, BufferedRWPair, BufferedRandom, + IncrementalNewlineDecoder, TextIOWrapper) + +OpenWrapper = _io.open # for compatibility with _pyio # Declaring ABCs in C is tricky so we do it here. # Method descriptions and default implementations are inherited from the C @@ -80,23 +80,12 @@ class TextIOBase(_io._TextIOBase, IOBase): pass -FileIO = _io.FileIO -BytesIO = _io.BytesIO -StringIO = _io.StringIO -BufferedReader = _io.BufferedReader -BufferedWriter = _io.BufferedWriter -BufferedRWPair = _io.BufferedRWPair -BufferedRandom = _io.BufferedRandom -IncrementalNewlineDecoder = _io.IncrementalNewlineDecoder -TextIOWrapper = _io.TextIOWrapper - RawIOBase.register(FileIO) -BufferedIOBase.register(BytesIO) -BufferedIOBase.register(BufferedReader) -BufferedIOBase.register(BufferedWriter) -BufferedIOBase.register(BufferedRandom) -BufferedIOBase.register(BufferedRWPair) - -TextIOBase.register(StringIO) -TextIOBase.register(TextIOWrapper) +for klass in (BytesIO, BufferedReader, BufferedWriter, BufferedRandom, + BufferedRWPair): + BufferedIOBase.register(klass) + +for klass in (StringIO, TextIOWrapper): + TextIOBase.register(klass) +del klass From buildbot at python.org Sat Mar 7 01:25:58 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 00:25:58 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090307002558.EA0191E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/479 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sat Mar 7 01:32:45 2009 From: python-checkins at python.org (tarek.ziade) Date: Sat, 7 Mar 2009 01:32:45 +0100 (CET) Subject: [Python-checkins] r70212 - in python/trunk: Lib/distutils/msvc9compiler.py Lib/distutils/tests/test_msvc9compiler.py Misc/NEWS Message-ID: <20090307003245.CECCD1E4002@bag.python.org> Author: tarek.ziade Date: Sat Mar 7 01:32:45 2009 New Revision: 70212 Log: Issue #5394: removed > 2.3 syntax from distutils.msvc9compiler Modified: python/trunk/Lib/distutils/msvc9compiler.py python/trunk/Lib/distutils/tests/test_msvc9compiler.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/distutils/msvc9compiler.py ============================================================================== --- python/trunk/Lib/distutils/msvc9compiler.py (original) +++ python/trunk/Lib/distutils/msvc9compiler.py Sat Mar 7 01:32:45 2009 @@ -17,10 +17,11 @@ import os import subprocess import sys -from distutils.errors import (DistutilsExecError, DistutilsPlatformError, - CompileError, LibError, LinkError) -from distutils.ccompiler import (CCompiler, gen_preprocess_options, - gen_lib_options) + +from distutils.errors import DistutilsExecError, DistutilsPlatformError, \ + CompileError, LibError, LinkError +from distutils.ccompiler import CCompiler, gen_preprocess_options, \ + gen_lib_options from distutils import log from distutils.util import get_platform @@ -53,15 +54,14 @@ """Helper class to read values from the registry """ - @classmethod def get_value(cls, path, key): for base in HKEYS: d = cls.read_values(base, path) if d and key in d: return d[key] raise KeyError(key) + get_value = classmethod(get_value) - @classmethod def read_keys(cls, base, key): """Return list of registry keys.""" try: @@ -78,8 +78,8 @@ L.append(k) i += 1 return L + read_keys = classmethod(read_keys) - @classmethod def read_values(cls, base, key): """Return dict of registry keys and values. @@ -100,8 +100,8 @@ d[cls.convert_mbcs(name)] = cls.convert_mbcs(value) i += 1 return d + read_values = classmethod(read_values) - @staticmethod def convert_mbcs(s): dec = getattr(s, "decode", None) if dec is not None: @@ -110,6 +110,7 @@ except UnicodeError: pass return s + convert_mbcs = staticmethod(convert_mbcs) class MacroExpander: @@ -131,7 +132,7 @@ "sdkinstallrootv2.0") else: raise KeyError("sdkinstallrootv2.0") - except KeyError as exc: # + except KeyError: raise DistutilsPlatformError( """Python was built with Visual Studio 2008; extensions must be built with a compiler than can generate compatible binaries. @@ -479,7 +480,7 @@ try: self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt]) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise CompileError(msg) continue elif ext in self._mc_extensions: @@ -506,7 +507,7 @@ self.spawn([self.rc] + ["/fo" + obj] + [rc_file]) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise CompileError(msg) continue else: @@ -519,7 +520,7 @@ self.spawn([self.cc] + compile_opts + pp_opts + [input_opt, output_opt] + extra_postargs) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise CompileError(msg) return objects @@ -544,7 +545,7 @@ pass # XXX what goes here? try: self.spawn([self.lib] + lib_args) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise LibError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) @@ -633,7 +634,7 @@ self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise LinkError(msg) # embed the manifest @@ -641,12 +642,15 @@ # will still consider the DLL up-to-date, but it will not have a # manifest. Maybe we should link to a temp file? OTOH, that # implies a build environment error that shouldn't go undetected. - mfid = 1 if target_desc == CCompiler.EXECUTABLE else 2 + if target_desc == CCompiler.EXECUTABLE: + mfid = 1 + else: + mfid = 2 out_arg = '-outputresource:%s;%s' % (output_filename, mfid) try: self.spawn(['mt.exe', '-nologo', '-manifest', temp_manifest, out_arg]) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) Modified: python/trunk/Lib/distutils/tests/test_msvc9compiler.py ============================================================================== --- python/trunk/Lib/distutils/tests/test_msvc9compiler.py (original) +++ python/trunk/Lib/distutils/tests/test_msvc9compiler.py Sat Mar 7 01:32:45 2009 @@ -30,6 +30,28 @@ finally: msvc9compiler.find_vcvarsall = old_find_vcvarsall + def test_reg_class(self): + if sys.platform != 'win32': + # this test is only for win32 + return + + from distutils.msvc9compiler import Reg + self.assertRaises(KeyError, Reg.get_value, 'xxx', 'xxx') + + # looking for values that should exist on all + # windows registeries versions. + path = r'Software\Microsoft\Notepad' + v = Reg.get_value(path, u"lfitalic") + self.assert_(v in (0, 1)) + + import _winreg + HKCU = _winreg.HKEY_CURRENT_USER + keys = Reg.read_keys(HKCU, 'xxxx') + self.assertEquals(keys, None) + + keys = Reg.read_keys(HKCU, r'Software\Microsoft') + self.assert_('Notepad' in keys) + def test_suite(): return unittest.makeSuite(msvc9compilerTestCase) Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sat Mar 7 01:32:45 2009 @@ -168,6 +168,9 @@ Library ------- +- Issue #5394: removed > 2.3 syntax from distutils.msvc9compiler. + Original patch by Akira Kitada. + - Issue #5385: Fixed mmap crash after resize failure on windows. - Issue #5179: Fixed subprocess handle leak on failure on windows. From python-checkins at python.org Sat Mar 7 01:35:00 2009 From: python-checkins at python.org (tarek.ziade) Date: Sat, 7 Mar 2009 01:35:00 +0100 (CET) Subject: [Python-checkins] r70213 - python/branches/release26-maint Message-ID: <20090307003500.98FE71E4002@bag.python.org> Author: tarek.ziade Date: Sat Mar 7 01:35:00 2009 New Revision: 70213 Log: Blocked revisions 70212 via svnmerge ........ r70212 | tarek.ziade | 2009-03-07 01:32:45 +0100 (Sat, 07 Mar 2009) | 1 line Issue #5394: removed > 2.3 syntax from distutils.msvc9compiler ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Sat Mar 7 01:51:54 2009 From: python-checkins at python.org (tarek.ziade) Date: Sat, 7 Mar 2009 01:51:54 +0100 (CET) Subject: [Python-checkins] r70214 - in python/branches/py3k: Lib/distutils/msvc9compiler.py Lib/distutils/tests/test_msvc9compiler.py Misc/NEWS Message-ID: <20090307005154.4DD551E400C@bag.python.org> Author: tarek.ziade Date: Sat Mar 7 01:51:53 2009 New Revision: 70214 Log: Merged revisions 70212 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70212 | tarek.ziade | 2009-03-07 01:32:45 +0100 (Sat, 07 Mar 2009) | 1 line Issue #5394: removed > 2.3 syntax from distutils.msvc9compiler ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/distutils/msvc9compiler.py python/branches/py3k/Lib/distutils/tests/test_msvc9compiler.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/distutils/msvc9compiler.py ============================================================================== --- python/branches/py3k/Lib/distutils/msvc9compiler.py (original) +++ python/branches/py3k/Lib/distutils/msvc9compiler.py Sat Mar 7 01:51:53 2009 @@ -17,10 +17,11 @@ import os import subprocess import sys -from distutils.errors import (DistutilsExecError, DistutilsPlatformError, - CompileError, LibError, LinkError) -from distutils.ccompiler import (CCompiler, gen_preprocess_options, - gen_lib_options) + +from distutils.errors import DistutilsExecError, DistutilsPlatformError, \ + CompileError, LibError, LinkError +from distutils.ccompiler import CCompiler, gen_preprocess_options, \ + gen_lib_options from distutils import log from distutils.util import get_platform @@ -53,15 +54,14 @@ """Helper class to read values from the registry """ - @classmethod def get_value(cls, path, key): for base in HKEYS: d = cls.read_values(base, path) if d and key in d: return d[key] raise KeyError(key) + get_value = classmethod(get_value) - @classmethod def read_keys(cls, base, key): """Return list of registry keys.""" try: @@ -78,8 +78,8 @@ L.append(k) i += 1 return L + read_keys = classmethod(read_keys) - @classmethod def read_values(cls, base, key): """Return dict of registry keys and values. @@ -100,8 +100,8 @@ d[cls.convert_mbcs(name)] = cls.convert_mbcs(value) i += 1 return d + read_values = classmethod(read_values) - @staticmethod def convert_mbcs(s): dec = getattr(s, "decode", None) if dec is not None: @@ -110,6 +110,7 @@ except UnicodeError: pass return s + convert_mbcs = staticmethod(convert_mbcs) class MacroExpander: @@ -131,7 +132,7 @@ "sdkinstallrootv2.0") else: raise KeyError("sdkinstallrootv2.0") - except KeyError as exc: # + except KeyError: raise DistutilsPlatformError( """Python was built with Visual Studio 2008; extensions must be built with a compiler than can generate compatible binaries. @@ -478,7 +479,7 @@ try: self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt]) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise CompileError(msg) continue elif ext in self._mc_extensions: @@ -505,7 +506,7 @@ self.spawn([self.rc] + ["/fo" + obj] + [rc_file]) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise CompileError(msg) continue else: @@ -518,7 +519,7 @@ self.spawn([self.cc] + compile_opts + pp_opts + [input_opt, output_opt] + extra_postargs) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise CompileError(msg) return objects @@ -543,7 +544,7 @@ pass # XXX what goes here? try: self.spawn([self.lib] + lib_args) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise LibError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) @@ -632,7 +633,7 @@ self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise LinkError(msg) # embed the manifest @@ -640,12 +641,15 @@ # will still consider the DLL up-to-date, but it will not have a # manifest. Maybe we should link to a temp file? OTOH, that # implies a build environment error that shouldn't go undetected. - mfid = 1 if target_desc == CCompiler.EXECUTABLE else 2 + if target_desc == CCompiler.EXECUTABLE: + mfid = 1 + else: + mfid = 2 out_arg = '-outputresource:%s;%s' % (output_filename, mfid) try: self.spawn(['mt.exe', '-nologo', '-manifest', temp_manifest, out_arg]) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) Modified: python/branches/py3k/Lib/distutils/tests/test_msvc9compiler.py ============================================================================== --- python/branches/py3k/Lib/distutils/tests/test_msvc9compiler.py (original) +++ python/branches/py3k/Lib/distutils/tests/test_msvc9compiler.py Sat Mar 7 01:51:53 2009 @@ -30,6 +30,28 @@ finally: msvc9compiler.find_vcvarsall = old_find_vcvarsall + def test_reg_class(self): + if sys.platform != 'win32': + # this test is only for win32 + return + + from distutils.msvc9compiler import Reg + self.assertRaises(KeyError, Reg.get_value, 'xxx', 'xxx') + + # looking for values that should exist on all + # windows registeries versions. + path = r'Software\Microsoft\Notepad' + v = Reg.get_value(path, "lfitalic") + self.assert_(v in (0, 1)) + + import _winreg + HKCU = _winreg.HKEY_CURRENT_USER + keys = Reg.read_keys(HKCU, 'xxxx') + self.assertEquals(keys, None) + + keys = Reg.read_keys(HKCU, r'Software\Microsoft') + self.assert_('Notepad' in keys) + def test_suite(): return unittest.makeSuite(msvc9compilerTestCase) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Mar 7 01:51:53 2009 @@ -183,6 +183,9 @@ Library ------- +- Issue #5394: removed > 2.3 syntax from distutils.msvc9compiler. + Original patch by Akira Kitada. + - Issue #5334: array.fromfile() failed to insert values when EOFError was raised. - Issue #5385: Fixed mmap crash after resize failure on windows. From solipsis at pitrou.net Sat Mar 7 01:56:46 2009 From: solipsis at pitrou.net (Antoine Pitrou) Date: Sat, 7 Mar 2009 00:56:46 +0000 (UTC) Subject: [Python-checkins] =?utf-8?q?r70214_-_in_python/branches/py3k=3A?= =?utf-8?q?=09Lib/distutils/msvc9compiler=2Epy=09Lib/distutils/test?= =?utf-8?q?s/test=5Fmsvc9compiler=2Epy_Misc/NEWS?= References: <20090307005154.4DD551E400C@bag.python.org> Message-ID: writes: > ........ > r70212 | tarek.ziade | 2009-03-07 01:32:45 +0100 (Sat, 07 Mar 2009) | 1 line > > Issue #5394: removed > 2.3 syntax from distutils.msvc9compiler > ........ This should be reverted. There are constructs in there which don't work under py3k (e.g. "except Exception, e"). From python-checkins at python.org Sat Mar 7 01:58:16 2009 From: python-checkins at python.org (tarek.ziade) Date: Sat, 7 Mar 2009 01:58:16 +0100 (CET) Subject: [Python-checkins] r70215 - python/branches/release30-maint Message-ID: <20090307005816.818601E4012@bag.python.org> Author: tarek.ziade Date: Sat Mar 7 01:58:16 2009 New Revision: 70215 Log: Blocked revisions 70214 via svnmerge ................ r70214 | tarek.ziade | 2009-03-07 01:51:53 +0100 (Sat, 07 Mar 2009) | 9 lines Merged revisions 70212 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70212 | tarek.ziade | 2009-03-07 01:32:45 +0100 (Sat, 07 Mar 2009) | 1 line Issue #5394: removed > 2.3 syntax from distutils.msvc9compiler ........ ................ Modified: python/branches/release30-maint/ (props changed) From ziade.tarek at gmail.com Sat Mar 7 02:08:35 2009 From: ziade.tarek at gmail.com (=?ISO-8859-1?Q?Tarek_Ziad=E9?=) Date: Sat, 7 Mar 2009 02:08:35 +0100 Subject: [Python-checkins] r70214 - in python/branches/py3k: Lib/distutils/msvc9compiler.py Lib/distutils/tests/test_msvc9compiler.py Misc/NEWS In-Reply-To: References: <20090307005154.4DD551E400C@bag.python.org> Message-ID: <94bdd2610903061708l11a275cexc606d06f04cf3c9b@mail.gmail.com> On Sat, Mar 7, 2009 at 1:56 AM, Antoine Pitrou wrote: > writes: >> ........ >> ? r70212 | tarek.ziade | 2009-03-07 01:32:45 +0100 (Sat, 07 Mar 2009) | 1 line >> >> ? Issue #5394: removed > 2.3 syntax from distutils.msvc9compiler >> ........ > > This should be reverted. There are constructs in there which don't work under > py3k (e.g. "except Exception, e"). > right. doing this now. I will also add an extra test that covers theses lines. > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > -- Tarek Ziad? | Association AfPy | www.afpy.org Blog FR | http://programmation-python.org Blog EN | http://tarekziade.wordpress.com/ From python-checkins at python.org Sat Mar 7 02:12:09 2009 From: python-checkins at python.org (tarek.ziade) Date: Sat, 7 Mar 2009 02:12:09 +0100 (CET) Subject: [Python-checkins] r70216 - python/branches/py3k/Lib/distutils/msvc9compiler.py Message-ID: <20090307011209.778511E4002@bag.python.org> Author: tarek.ziade Date: Sat Mar 7 02:12:09 2009 New Revision: 70216 Log: fixed except syntax for py3 Modified: python/branches/py3k/Lib/distutils/msvc9compiler.py Modified: python/branches/py3k/Lib/distutils/msvc9compiler.py ============================================================================== --- python/branches/py3k/Lib/distutils/msvc9compiler.py (original) +++ python/branches/py3k/Lib/distutils/msvc9compiler.py Sat Mar 7 02:12:09 2009 @@ -479,7 +479,7 @@ try: self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt]) - except DistutilsExecError, msg: + except DistutilsExecError as msg: raise CompileError(msg) continue elif ext in self._mc_extensions: @@ -506,7 +506,7 @@ self.spawn([self.rc] + ["/fo" + obj] + [rc_file]) - except DistutilsExecError, msg: + except DistutilsExecError as msg: raise CompileError(msg) continue else: @@ -519,7 +519,7 @@ self.spawn([self.cc] + compile_opts + pp_opts + [input_opt, output_opt] + extra_postargs) - except DistutilsExecError, msg: + except DistutilsExecError as msg: raise CompileError(msg) return objects @@ -544,7 +544,7 @@ pass # XXX what goes here? try: self.spawn([self.lib] + lib_args) - except DistutilsExecError, msg: + except DistutilsExecError as msg: raise LibError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) @@ -633,7 +633,7 @@ self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) - except DistutilsExecError, msg: + except DistutilsExecError as msg: raise LinkError(msg) # embed the manifest @@ -649,7 +649,7 @@ try: self.spawn(['mt.exe', '-nologo', '-manifest', temp_manifest, out_arg]) - except DistutilsExecError, msg: + except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) From python-checkins at python.org Sat Mar 7 02:13:29 2009 From: python-checkins at python.org (tarek.ziade) Date: Sat, 7 Mar 2009 02:13:29 +0100 (CET) Subject: [Python-checkins] r70217 - python/branches/release30-maint Message-ID: <20090307011329.2E5CA1E4002@bag.python.org> Author: tarek.ziade Date: Sat Mar 7 02:13:29 2009 New Revision: 70217 Log: Blocked revisions 70216 via svnmerge ........ r70216 | tarek.ziade | 2009-03-07 02:12:09 +0100 (Sat, 07 Mar 2009) | 1 line fixed except syntax for py3 ........ Modified: python/branches/release30-maint/ (props changed) From python-checkins at python.org Sat Mar 7 02:19:12 2009 From: python-checkins at python.org (guilherme.polo) Date: Sat, 7 Mar 2009 02:19:12 +0100 (CET) Subject: [Python-checkins] r70218 - in python/trunk: Lib/lib-tk/Tkinter.py Misc/NEWS Message-ID: <20090307011912.C6BF11E4002@bag.python.org> Author: guilherme.polo Date: Sat Mar 7 02:19:12 2009 New Revision: 70218 Log: Fixed issue #5193: Guarantee that Tkinter.Text.search returns a string. Modified: python/trunk/Lib/lib-tk/Tkinter.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/lib-tk/Tkinter.py ============================================================================== --- python/trunk/Lib/lib-tk/Tkinter.py (original) +++ python/trunk/Lib/lib-tk/Tkinter.py Sat Mar 7 02:19:12 2009 @@ -3046,7 +3046,7 @@ args.append(pattern) args.append(index) if stopindex: args.append(stopindex) - return self.tk.call(tuple(args)) + return str(self.tk.call(tuple(args))) def see(self, index): """Scroll such that the character at INDEX is visible.""" self.tk.call(self._w, 'see', index) Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sat Mar 7 02:19:12 2009 @@ -168,6 +168,8 @@ Library ------- +- Issue #5193: Guarantee that Tkinter.Text.search returns a string. + - Issue #5394: removed > 2.3 syntax from distutils.msvc9compiler. Original patch by Akira Kitada. From buildbot at python.org Sat Mar 7 02:38:25 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 01:38:25 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo trunk Message-ID: <20090307013825.6353C1E4002@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%20gentoo%20trunk/builds/4713 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: guilherme.polo BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Killed sincerely, -The Buildbot From buildbot at python.org Sat Mar 7 02:41:12 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 01:41:12 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090307014112.DB69E1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/713 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: jesus.cea,tarek.ziade BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sat Mar 7 02:47:49 2009 From: python-checkins at python.org (guilherme.polo) Date: Sat, 7 Mar 2009 02:47:49 +0100 (CET) Subject: [Python-checkins] r70219 - in python/trunk: Misc/NEWS Modules/_tkinter.c Message-ID: <20090307014749.ABF251E4002@bag.python.org> Author: guilherme.polo Date: Sat Mar 7 02:47:49 2009 New Revision: 70219 Log: Fixed issue #4792: Prevent a segfault in _tkinter by using the guaranteed to be safe interp argument given to the PythonCmd in place of the Tcl interpreter taken from a PythonCmd_ClientData. Modified: python/trunk/Misc/NEWS python/trunk/Modules/_tkinter.c Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sat Mar 7 02:47:49 2009 @@ -168,6 +168,10 @@ Library ------- +- Issue #4792: Prevent a segfault in _tkinter by using the + guaranteed to be safe interp argument given to the PythonCmd in place of + the Tcl interpreter taken from a PythonCmd_ClientData. + - Issue #5193: Guarantee that Tkinter.Text.search returns a string. - Issue #5394: removed > 2.3 syntax from distutils.msvc9compiler. Modified: python/trunk/Modules/_tkinter.c ============================================================================== --- python/trunk/Modules/_tkinter.c (original) +++ python/trunk/Modules/_tkinter.c Sat Mar 7 02:47:49 2009 @@ -2070,7 +2070,7 @@ return PythonCmd_Error(interp); } else { - Tcl_SetObjResult(Tkapp_Interp(self), obj_res); + Tcl_SetObjResult(interp, obj_res); rv = TCL_OK; } From python-checkins at python.org Sat Mar 7 02:51:49 2009 From: python-checkins at python.org (guilherme.polo) Date: Sat, 7 Mar 2009 02:51:49 +0100 (CET) Subject: [Python-checkins] r70220 - in python/branches/release26-maint: Lib/lib-tk/Tkinter.py Misc/NEWS Modules/_tkinter.c Message-ID: <20090307015149.1BF9F1E401C@bag.python.org> Author: guilherme.polo Date: Sat Mar 7 02:51:48 2009 New Revision: 70220 Log: Merged revisions 70218-70219 via svnmerge from svn+ssh://pythondev/python/trunk ........ r70218 | guilherme.polo | 2009-03-06 22:19:12 -0300 (Fri, 06 Mar 2009) | 1 line Fixed issue #5193: Guarantee that Tkinter.Text.search returns a string. ........ r70219 | guilherme.polo | 2009-03-06 22:47:49 -0300 (Fri, 06 Mar 2009) | 4 lines Fixed issue #4792: Prevent a segfault in _tkinter by using the guaranteed to be safe interp argument given to the PythonCmd in place of the Tcl interpreter taken from a PythonCmd_ClientData. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/lib-tk/Tkinter.py python/branches/release26-maint/Misc/NEWS python/branches/release26-maint/Modules/_tkinter.c Modified: python/branches/release26-maint/Lib/lib-tk/Tkinter.py ============================================================================== --- python/branches/release26-maint/Lib/lib-tk/Tkinter.py (original) +++ python/branches/release26-maint/Lib/lib-tk/Tkinter.py Sat Mar 7 02:51:48 2009 @@ -3046,7 +3046,7 @@ args.append(pattern) args.append(index) if stopindex: args.append(stopindex) - return self.tk.call(tuple(args)) + return str(self.tk.call(tuple(args))) def see(self, index): """Scroll such that the character at INDEX is visible.""" self.tk.call(self._w, 'see', index) Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Sat Mar 7 02:51:48 2009 @@ -89,6 +89,12 @@ Library ------- +- Issue #4792: Prevent a segfault in _tkinter by using the + guaranteed to be safe interp argument given to the PythonCmd in place of + the Tcl interpreter taken from a PythonCmd_ClientData. + +- Issue #5193: Guarantee that Tkinter.Text.search returns a string. + - Issue #5385: Fixed mmap crash after resize failure on windows. - Issue #5179: Fixed subprocess handle leak on failure on windows. Modified: python/branches/release26-maint/Modules/_tkinter.c ============================================================================== --- python/branches/release26-maint/Modules/_tkinter.c (original) +++ python/branches/release26-maint/Modules/_tkinter.c Sat Mar 7 02:51:48 2009 @@ -2030,7 +2030,7 @@ return PythonCmd_Error(interp); } else { - Tcl_SetObjResult(Tkapp_Interp(self), obj_res); + Tcl_SetObjResult(interp, obj_res); rv = TCL_OK; } From python-checkins at python.org Sat Mar 7 02:54:57 2009 From: python-checkins at python.org (guilherme.polo) Date: Sat, 7 Mar 2009 02:54:57 +0100 (CET) Subject: [Python-checkins] r70221 - in python/branches/py3k: Lib/tkinter/__init__.py Misc/NEWS Modules/_tkinter.c Message-ID: <20090307015457.4E4351E4002@bag.python.org> Author: guilherme.polo Date: Sat Mar 7 02:54:57 2009 New Revision: 70221 Log: Merged revisions 70218-70219 via svnmerge from svn+ssh://pythondev/python/trunk ........ r70218 | guilherme.polo | 2009-03-06 22:19:12 -0300 (Fri, 06 Mar 2009) | 1 line Fixed issue #5193: Guarantee that Tkinter.Text.search returns a string. ........ r70219 | guilherme.polo | 2009-03-06 22:47:49 -0300 (Fri, 06 Mar 2009) | 4 lines Fixed issue #4792: Prevent a segfault in _tkinter by using the guaranteed to be safe interp argument given to the PythonCmd in place of the Tcl interpreter taken from a PythonCmd_ClientData. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/tkinter/__init__.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_tkinter.c Modified: python/branches/py3k/Lib/tkinter/__init__.py ============================================================================== --- python/branches/py3k/Lib/tkinter/__init__.py (original) +++ python/branches/py3k/Lib/tkinter/__init__.py Sat Mar 7 02:54:57 2009 @@ -3030,7 +3030,7 @@ args.append(pattern) args.append(index) if stopindex: args.append(stopindex) - return self.tk.call(tuple(args)) + return str(self.tk.call(tuple(args))) def see(self, index): """Scroll such that the character at INDEX is visible.""" self.tk.call(self._w, 'see', index) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Mar 7 02:54:57 2009 @@ -183,6 +183,12 @@ Library ------- +- Issue #4792: Prevent a segfault in _tkinter by using the + guaranteed to be safe interp argument given to the PythonCmd in place of + the Tcl interpreter taken from a PythonCmd_ClientData. + +- Issue #5193: Guarantee that tkinter.Text.search returns a string. + - Issue #5394: removed > 2.3 syntax from distutils.msvc9compiler. Original patch by Akira Kitada. Modified: python/branches/py3k/Modules/_tkinter.c ============================================================================== --- python/branches/py3k/Modules/_tkinter.c (original) +++ python/branches/py3k/Modules/_tkinter.c Sat Mar 7 02:54:57 2009 @@ -2026,7 +2026,7 @@ return PythonCmd_Error(interp); } else { - Tcl_SetObjResult(Tkapp_Interp(self), obj_res); + Tcl_SetObjResult(interp, obj_res); rv = TCL_OK; } From python-checkins at python.org Sat Mar 7 02:58:16 2009 From: python-checkins at python.org (guilherme.polo) Date: Sat, 7 Mar 2009 02:58:16 +0100 (CET) Subject: [Python-checkins] r70222 - in python/branches/release30-maint: Lib/tkinter/__init__.py Misc/NEWS Modules/_tkinter.c Message-ID: <20090307015816.D665E1E4002@bag.python.org> Author: guilherme.polo Date: Sat Mar 7 02:58:16 2009 New Revision: 70222 Log: Merged revisions 70221 via svnmerge from svn+ssh://pythondev/python/branches/py3k ................ r70221 | guilherme.polo | 2009-03-06 22:54:57 -0300 (Fri, 06 Mar 2009) | 15 lines Merged revisions 70218-70219 via svnmerge from svn+ssh://pythondev/python/trunk ........ r70218 | guilherme.polo | 2009-03-06 22:19:12 -0300 (Fri, 06 Mar 2009) | 1 line Fixed issue #5193: Guarantee that Tkinter.Text.search returns a string. ........ r70219 | guilherme.polo | 2009-03-06 22:47:49 -0300 (Fri, 06 Mar 2009) | 4 lines Fixed issue #4792: Prevent a segfault in _tkinter by using the guaranteed to be safe interp argument given to the PythonCmd in place of the Tcl interpreter taken from a PythonCmd_ClientData. ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/tkinter/__init__.py python/branches/release30-maint/Misc/NEWS python/branches/release30-maint/Modules/_tkinter.c Modified: python/branches/release30-maint/Lib/tkinter/__init__.py ============================================================================== --- python/branches/release30-maint/Lib/tkinter/__init__.py (original) +++ python/branches/release30-maint/Lib/tkinter/__init__.py Sat Mar 7 02:58:16 2009 @@ -3030,7 +3030,7 @@ args.append(pattern) args.append(index) if stopindex: args.append(stopindex) - return self.tk.call(tuple(args)) + return str(self.tk.call(tuple(args))) def see(self, index): """Scroll such that the character at INDEX is visible.""" self.tk.call(self._w, 'see', index) Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Sat Mar 7 02:58:16 2009 @@ -149,6 +149,12 @@ Library ------- +- Issue #4792: Prevent a segfault in _tkinter by using the + guaranteed to be safe interp argument given to the PythonCmd in place of + the Tcl interpreter taken from a PythonCmd_ClientData. + +- Issue #5193: Guarantee that tkinter.Text.search returns a string. + - Issue #5334: array.fromfile() failed to insert values when EOFError was raised. - Issue #5385: Fixed mmap crash after resize failure on windows. Modified: python/branches/release30-maint/Modules/_tkinter.c ============================================================================== --- python/branches/release30-maint/Modules/_tkinter.c (original) +++ python/branches/release30-maint/Modules/_tkinter.c Sat Mar 7 02:58:16 2009 @@ -1986,7 +1986,7 @@ return PythonCmd_Error(interp); } else { - Tcl_SetObjResult(Tkapp_Interp(self), obj_res); + Tcl_SetObjResult(interp, obj_res); rv = TCL_OK; } From python-checkins at python.org Sat Mar 7 03:14:39 2009 From: python-checkins at python.org (guilherme.polo) Date: Sat, 7 Mar 2009 03:14:39 +0100 (CET) Subject: [Python-checkins] r70223 - in python/trunk: Lib/lib-tk/tkSimpleDialog.py Misc/NEWS Message-ID: <20090307021439.4C3E31E4002@bag.python.org> Author: guilherme.polo Date: Sat Mar 7 03:14:38 2009 New Revision: 70223 Log: Fixed issue #2638: Show a window constructed with tkSimpleDialog.Dialog only after it is has been populated and properly configured in order to prevent window flashing. Modified: python/trunk/Lib/lib-tk/tkSimpleDialog.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/lib-tk/tkSimpleDialog.py ============================================================================== --- python/trunk/Lib/lib-tk/tkSimpleDialog.py (original) +++ python/trunk/Lib/lib-tk/tkSimpleDialog.py Sat Mar 7 03:14:38 2009 @@ -46,6 +46,7 @@ ''' Toplevel.__init__(self, parent) + self.withdraw() # remain invisible for now # If the master is not viewable, don't # make the child transient, or else it # would be opened withdrawn @@ -65,8 +66,6 @@ self.buttonbox() - self.wait_visibility() # window needs to be visible for the grab - self.grab_set() if not self.initial_focus: self.initial_focus = self @@ -77,8 +76,13 @@ self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50)) + self.deiconify() # become visibile now + self.initial_focus.focus_set() + # wait for window to appear on screen before calling grab_set + self.wait_visibility() + self.grab_set() self.wait_window(self) def destroy(self): Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sat Mar 7 03:14:38 2009 @@ -168,6 +168,10 @@ Library ------- +- Issue #2638: Show a window constructed with tkSimpleDialog.Dialog only after + it is has been populated and properly configured in order to prevent + window flashing. + - Issue #4792: Prevent a segfault in _tkinter by using the guaranteed to be safe interp argument given to the PythonCmd in place of the Tcl interpreter taken from a PythonCmd_ClientData. From python-checkins at python.org Sat Mar 7 03:15:50 2009 From: python-checkins at python.org (guilherme.polo) Date: Sat, 7 Mar 2009 03:15:50 +0100 (CET) Subject: [Python-checkins] r70224 - python/branches/release26-maint Message-ID: <20090307021550.A0C111E400C@bag.python.org> Author: guilherme.polo Date: Sat Mar 7 03:15:50 2009 New Revision: 70224 Log: Blocked revisions 70223 via svnmerge ........ r70223 | guilherme.polo | 2009-03-06 23:14:38 -0300 (Fri, 06 Mar 2009) | 4 lines Fixed issue #2638: Show a window constructed with tkSimpleDialog.Dialog only after it is has been populated and properly configured in order to prevent window flashing. ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Sat Mar 7 03:19:14 2009 From: python-checkins at python.org (guilherme.polo) Date: Sat, 7 Mar 2009 03:19:14 +0100 (CET) Subject: [Python-checkins] r70225 - in python/branches/py3k: Lib/tkinter/simpledialog.py Misc/NEWS Message-ID: <20090307021914.CFCB91E4002@bag.python.org> Author: guilherme.polo Date: Sat Mar 7 03:19:14 2009 New Revision: 70225 Log: Merged revisions 70223 via svnmerge from svn+ssh://pythondev/python/trunk ........ r70223 | guilherme.polo | 2009-03-06 23:14:38 -0300 (Fri, 06 Mar 2009) | 4 lines Fixed issue #2638: Show a window constructed with tkSimpleDialog.Dialog only after it is has been populated and properly configured in order to prevent window flashing. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/tkinter/simpledialog.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/tkinter/simpledialog.py ============================================================================== --- python/branches/py3k/Lib/tkinter/simpledialog.py (original) +++ python/branches/py3k/Lib/tkinter/simpledialog.py Sat Mar 7 03:19:14 2009 @@ -130,6 +130,7 @@ ''' Toplevel.__init__(self, parent) + self.withdraw() # remain invisible for now # If the master is not viewable, don't # make the child transient, or else it # would be opened withdrawn @@ -149,9 +150,6 @@ self.buttonbox() - self.wait_visibility() # window needs to be visible for the grab - self.grab_set() - if not self.initial_focus: self.initial_focus = self @@ -161,8 +159,13 @@ self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50)) + self.deiconify() # become visible now + self.initial_focus.focus_set() + # wait for window to appear on screen before calling grab_set + self.wait_visibility() + self.grab_set() self.wait_window(self) def destroy(self): Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Mar 7 03:19:14 2009 @@ -183,6 +183,10 @@ Library ------- +- Issue #2638: Show a window constructed with tkSimpleDialog.Dialog only after + it is has been populated and properly configured in order to prevent + window flashing. + - Issue #4792: Prevent a segfault in _tkinter by using the guaranteed to be safe interp argument given to the PythonCmd in place of the Tcl interpreter taken from a PythonCmd_ClientData. From python-checkins at python.org Sat Mar 7 03:20:24 2009 From: python-checkins at python.org (guilherme.polo) Date: Sat, 7 Mar 2009 03:20:24 +0100 (CET) Subject: [Python-checkins] r70226 - python/branches/release30-maint Message-ID: <20090307022024.B101B1E4002@bag.python.org> Author: guilherme.polo Date: Sat Mar 7 03:20:24 2009 New Revision: 70226 Log: Blocked revisions 70225 via svnmerge ................ r70225 | guilherme.polo | 2009-03-06 23:19:14 -0300 (Fri, 06 Mar 2009) | 11 lines Merged revisions 70223 via svnmerge from svn+ssh://pythondev/python/trunk ........ r70223 | guilherme.polo | 2009-03-06 23:14:38 -0300 (Fri, 06 Mar 2009) | 4 lines Fixed issue #2638: Show a window constructed with tkSimpleDialog.Dialog only after it is has been populated and properly configured in order to prevent window flashing. ........ ................ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Sat Mar 7 03:52:07 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 02:52:07 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090307025208.411521E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/385 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: tarek.ziade BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_modulefinder.py", line 261, in test_maybe_new self._do_test(maybe_test_new) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_modulefinder.py", line 226, in _do_test mf.import_hook(import_this) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 123, in import_hook m = self.load_tail(q, tail) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 200, in load_tail m = self.import_module(head, mname, m) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 270, in import_module m = self.load_module(fqname, fp, pathname, stuff) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 301, in load_module self.scan_code(co, m) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 406, in scan_code self._safe_import_hook(name, m, fromlist, level=0) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 319, in _safe_import_hook self.import_hook(name, caller, level=level) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 122, in import_hook q, tail = self.find_head_package(parent, name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 178, in find_head_package q = self.import_module(head, qname, parent) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 270, in import_module m = self.load_module(fqname, fp, pathname, stuff) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 282, in load_module m = self.load_package(fqname, pathname) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 454, in load_package self.load_module(fqname, fp, buf, stuff) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 301, in load_module self.scan_code(co, m) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 406, in scan_code self._safe_import_hook(name, m, fromlist, level=0) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 319, in _safe_import_hook self.import_hook(name, caller, level=level) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 122, in import_hook q, tail = self.find_head_package(parent, name) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 178, in find_head_package q = self.import_module(head, qname, parent) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/modulefinder.py", line 272, in import_module if fp: fp.close() IOError: [Errno -1] Unknown error 18446744073709551615 1 test failed: test_modulefinder make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sat Mar 7 04:04:19 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 03:04:19 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090307030419.79D6B1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/482 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: tarek.ziade BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_multiprocessing sincerely, -The Buildbot From buildbot at python.org Sat Mar 7 04:21:34 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 03:21:34 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090307032134.D0F4A1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/378 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: antoine.pitrou,benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_modulefinder make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sat Mar 7 04:38:34 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 03:38:34 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090307033834.E584C1E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/200 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: tarek.ziade BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_distutils test_posix ====================================================================== FAIL: test_get_python_inc (distutils.tests.test_sysconfig.SysconfigTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/distutils/tests/test_sysconfig.py", line 45, in test_get_python_inc self.assert_(os.path.isdir(inc_dir), inc_dir) AssertionError: /home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/Include ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From buildbot at python.org Sat Mar 7 04:41:45 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 03:41:45 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.0 Message-ID: <20090307034145.BB4AD1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.0/builds/195 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: tarek.ziade BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Sat Mar 7 05:22:10 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 04:22:10 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu trunk Message-ID: <20090307042211.1AC2C1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%20trunk/builds/949 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: guilherme.polo BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Sat Mar 7 05:30:52 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 04:30:52 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090307043054.43BAF1E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/393 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: antoine.pitrou,benjamin.peterson,raymond.hettinger,tarek.ziade BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_posix test_subprocess ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_subprocess.py", line 149, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From buildbot at python.org Sat Mar 7 06:08:18 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 05:08:18 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.0 Message-ID: <20090307050818.D7D881E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.0/builds/175 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: guilherme.polo BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sat Mar 7 15:07:38 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 7 Mar 2009 15:07:38 +0100 (CET) Subject: [Python-checkins] r70227 - python/branches/py3k/Doc/library/queue.rst Message-ID: <20090307140738.2DE5C1E4002@bag.python.org> Author: raymond.hettinger Date: Sat Mar 7 15:07:37 2009 New Revision: 70227 Log: Redocument the empty() and full() methods. Modified: python/branches/py3k/Doc/library/queue.rst Modified: python/branches/py3k/Doc/library/queue.rst ============================================================================== --- python/branches/py3k/Doc/library/queue.rst (original) +++ python/branches/py3k/Doc/library/queue.rst Sat Mar 7 15:07:37 2009 @@ -78,6 +78,22 @@ guarantee that put() will not block. +.. method:: Queue.empty() + + Return ``True`` if the queue is empty, ``False`` otherwise. If empty() + returns ``True`` it doesn't guarantee that a subsequent call to put() + will not block. Similarly, if empty() returns ``False`` it doesn't + guarantee that a subsequent call to get() will not block. + + +.. method:: Queue.full() + + Return ``True`` if the queue is full, ``False`` otherwise. If full() + returns ``True`` it doesn't guarantee that a subsequent call to get() + will not block. Similarly, if full() returns ``False`` it doesn't + guarantee that a subsequent call to put() will not block. + + .. method:: Queue.put(item[, block[, timeout]]) Put *item* into the queue. If optional args *block* is true and *timeout* is From python-checkins at python.org Sat Mar 7 15:12:00 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 7 Mar 2009 15:12:00 +0100 (CET) Subject: [Python-checkins] r70228 - python/branches/release30-maint/Doc/library/queue.rst Message-ID: <20090307141200.97AA21E400C@bag.python.org> Author: raymond.hettinger Date: Sat Mar 7 15:12:00 2009 New Revision: 70228 Log: Redocument the empty() and full() methods. Modified: python/branches/release30-maint/Doc/library/queue.rst Modified: python/branches/release30-maint/Doc/library/queue.rst ============================================================================== --- python/branches/release30-maint/Doc/library/queue.rst (original) +++ python/branches/release30-maint/Doc/library/queue.rst Sat Mar 7 15:12:00 2009 @@ -78,6 +78,22 @@ guarantee that put() will not block. +.. method:: Queue.empty() + + Return ``True`` if the queue is empty, ``False`` otherwise. If empty() + returns ``True`` it doesn't guarantee that a subsequent call to put() + will not block. Similarly, if empty() returns ``False`` it doesn't + guarantee that a subsequent call to get() will not block. + + +.. method:: Queue.full() + + Return ``True`` if the queue is full, ``False`` otherwise. If full() + returns ``True`` it doesn't guarantee that a subsequent call to get() + will not block. Similarly, if full() returns ``False`` it doesn't + guarantee that a subsequent call to put() will not block. + + .. method:: Queue.put(item[, block[, timeout]]) Put *item* into the queue. If optional args *block* is true and *timeout* is From python-checkins at python.org Sat Mar 7 17:20:25 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 7 Mar 2009 17:20:25 +0100 (CET) Subject: [Python-checkins] r70229 - in python/branches/py3k/Misc/RPM: python-3.0.spec python-3.1.spec Message-ID: <20090307162025.5DFF11E4002@bag.python.org> Author: benjamin.peterson Date: Sat Mar 7 17:20:24 2009 New Revision: 70229 Log: update rpm filename Added: python/branches/py3k/Misc/RPM/python-3.1.spec - copied unchanged from r70228, /python/branches/py3k/Misc/RPM/python-3.0.spec Removed: python/branches/py3k/Misc/RPM/python-3.0.spec Deleted: python/branches/py3k/Misc/RPM/python-3.0.spec ============================================================================== --- python/branches/py3k/Misc/RPM/python-3.0.spec Sat Mar 7 17:20:24 2009 +++ (empty file) @@ -1,387 +0,0 @@ -########################## -# User-modifiable configs -########################## - -# Is the resulting package and the installed binary named "python" or -# "python2"? -#WARNING: Commenting out doesn't work. Last line is what's used. -%define config_binsuffix none -%define config_binsuffix 2.6 - -# Build tkinter? "auto" enables it if /usr/bin/wish exists. -#WARNING: Commenting out doesn't work. Last line is what's used. -%define config_tkinter no -%define config_tkinter yes -%define config_tkinter auto - -# Use pymalloc? The last line (commented or not) determines wether -# pymalloc is used. -#WARNING: Commenting out doesn't work. Last line is what's used. -%define config_pymalloc no -%define config_pymalloc yes - -# Enable IPV6? -#WARNING: Commenting out doesn't work. Last line is what's used. -%define config_ipv6 yes -%define config_ipv6 no - -# Location of the HTML directory. -%define config_htmldir /var/www/html/python - -################################# -# End of user-modifiable configs -################################# - -%define name python -#--start constants-- -%define version 3.0rc3 -%define libver 3.0 -#--end constants-- -%define release 1pydotorg -%define __prefix /usr - -# kludge to get around rpm define weirdness -%define ipv6 %(if [ "%{config_ipv6}" = yes ]; then echo --enable-ipv6; else echo --disable-ipv6; fi) -%define pymalloc %(if [ "%{config_pymalloc}" = yes ]; then echo --with-pymalloc; else echo --without-pymalloc; fi) -%define binsuffix %(if [ "%{config_binsuffix}" = none ]; then echo ; else echo "%{config_binsuffix}"; fi) -%define include_tkinter %(if [ \\( "%{config_tkinter}" = auto -a -f /usr/bin/wish \\) -o "%{config_tkinter}" = yes ]; then echo 1; else echo 0; fi) -%define libdirname %(( uname -m | egrep -q '_64$' && [ -d /usr/lib64 ] && echo lib64 ) || echo lib) - -# detect if documentation is available -%define include_docs %(if [ -f "%{_sourcedir}/html-%{version}.tar.bz2" ]; then echo 1; else echo 0; fi) - -Summary: An interpreted, interactive, object-oriented programming language. -Name: %{name}%{binsuffix} -Version: %{version} -Release: %{release} -Copyright: Modified CNRI Open Source License -Group: Development/Languages -Source: Python-%{version}.tar.bz2 -%if %{include_docs} -Source1: html-%{version}.tar.bz2 -%endif -BuildRoot: %{_tmppath}/%{name}-%{version}-root -BuildPrereq: expat-devel -BuildPrereq: db4-devel -BuildPrereq: gdbm-devel -BuildPrereq: sqlite-devel -Prefix: %{__prefix} -Packager: Sean Reifschneider - -%description -Python is an interpreted, interactive, object-oriented programming -language. It incorporates modules, exceptions, dynamic typing, very high -level dynamic data types, and classes. Python combines remarkable power -with very clear syntax. It has interfaces to many system calls and -libraries, as well as to various window systems, and is extensible in C or -C++. It is also usable as an extension language for applications that need -a programmable interface. Finally, Python is portable: it runs on many -brands of UNIX, on PCs under Windows, MS-DOS, and OS/2, and on the -Mac. - -%package devel -Summary: The libraries and header files needed for Python extension development. -Prereq: python%{binsuffix} = %{PACKAGE_VERSION} -Group: Development/Libraries - -%description devel -The Python programming language's interpreter can be extended with -dynamically loaded extensions and can be embedded in other programs. -This package contains the header files and libraries needed to do -these types of tasks. - -Install python-devel if you want to develop Python extensions. The -python package will also need to be installed. You'll probably also -want to install the python-docs package, which contains Python -documentation. - -%if %{include_tkinter} -%package tkinter -Summary: A graphical user interface for the Python scripting language. -Group: Development/Languages -Prereq: python%{binsuffix} = %{PACKAGE_VERSION}-%{release} - -%description tkinter -The Tkinter (Tk interface) program is an graphical user interface for -the Python scripting language. - -You should install the tkinter package if you'd like to use a graphical -user interface for Python programming. -%endif - -%package tools -Summary: A collection of development tools included with Python. -Group: Development/Tools -Prereq: python%{binsuffix} = %{PACKAGE_VERSION}-%{release} - -%description tools -The Python package includes several development tools that are used -to build python programs. This package contains a selection of those -tools, including the IDLE Python IDE. - -Install python-tools if you want to use these tools to develop -Python programs. You will also need to install the python and -tkinter packages. - -%if %{include_docs} -%package docs -Summary: Python-related documentation. -Group: Development/Documentation - -%description docs -Documentation relating to the Python programming language in HTML and info -formats. -%endif - -%changelog -* Mon Dec 20 2004 Sean Reifschneider [2.4-2pydotorg] -- Changing the idle wrapper so that it passes arguments to idle. - -* Tue Oct 19 2004 Sean Reifschneider [2.4b1-1pydotorg] -- Updating to 2.4. - -* Thu Jul 22 2004 Sean Reifschneider [2.3.4-3pydotorg] -- Paul Tiemann fixes for %{prefix}. -- Adding permission changes for directory as suggested by reimeika.ca -- Adding code to detect when it should be using lib64. -- Adding a define for the location of /var/www/html for docs. - -* Thu May 27 2004 Sean Reifschneider [2.3.4-2pydotorg] -- Including changes from Ian Holsman to build under Red Hat 7.3. -- Fixing some problems with the /usr/local path change. - -* Sat Mar 27 2004 Sean Reifschneider [2.3.2-3pydotorg] -- Being more agressive about finding the paths to fix for - #!/usr/local/bin/python. - -* Sat Feb 07 2004 Sean Reifschneider [2.3.3-2pydotorg] -- Adding code to remove "#!/usr/local/bin/python" from particular files and - causing the RPM build to terminate if there are any unexpected files - which have that line in them. - -* Mon Oct 13 2003 Sean Reifschneider [2.3.2-1pydotorg] -- Adding code to detect wether documentation is available to build. - -* Fri Sep 19 2003 Sean Reifschneider [2.3.1-1pydotorg] -- Updating to the 2.3.1 release. - -* Mon Feb 24 2003 Sean Reifschneider [2.3b1-1pydotorg] -- Updating to 2.3b1 release. - -* Mon Feb 17 2003 Sean Reifschneider [2.3a1-1] -- Updating to 2.3 release. - -* Sun Dec 23 2001 Sean Reifschneider -[Release 2.2-2] -- Added -docs package. -- Added "auto" config_tkinter setting which only enables tk if - /usr/bin/wish exists. - -* Sat Dec 22 2001 Sean Reifschneider -[Release 2.2-1] -- Updated to 2.2. -- Changed the extension to "2" from "2.2". - -* Tue Nov 18 2001 Sean Reifschneider -[Release 2.2c1-1] -- Updated to 2.2c1. - -* Thu Nov 1 2001 Sean Reifschneider -[Release 2.2b1-3] -- Changed the way the sed for fixing the #! in pydoc works. - -* Wed Oct 24 2001 Sean Reifschneider -[Release 2.2b1-2] -- Fixed missing "email" package, thanks to anonymous report on sourceforge. -- Fixed missing "compiler" package. - -* Mon Oct 22 2001 Sean Reifschneider -[Release 2.2b1-1] -- Updated to 2.2b1. - -* Mon Oct 9 2001 Sean Reifschneider -[Release 2.2a4-4] -- otto at balinor.mat.unimi.it mentioned that the license file is missing. - -* Sun Sep 30 2001 Sean Reifschneider -[Release 2.2a4-3] -- Ignacio Vazquez-Abrams pointed out that I had a spruious double-quote in - the spec files. Thanks. - -* Wed Jul 25 2001 Sean Reifschneider -[Release 2.2a1-1] -- Updated to 2.2a1 release. -- Changed idle and pydoc to use binsuffix macro - -####### -# PREP -####### -%prep -%setup -n Python-%{version} - -######## -# BUILD -######## -%build -./configure --enable-unicode=ucs4 %{ipv6} %{pymalloc} --prefix=%{__prefix} -make - -########## -# INSTALL -########## -%install -# set the install path -echo '[install_scripts]' >setup.cfg -echo 'install_dir='"${RPM_BUILD_ROOT}%{__prefix}/bin" >>setup.cfg - -[ -d "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT -mkdir -p $RPM_BUILD_ROOT%{__prefix}/%{libdirname}/python%{libvers}/lib-dynload -make prefix=$RPM_BUILD_ROOT%{__prefix} install - -# REPLACE PATH IN PYDOC -if [ ! -z "%{binsuffix}" ] -then - ( - cd $RPM_BUILD_ROOT%{__prefix}/bin - mv pydoc pydoc.old - sed 's|#!.*|#!%{__prefix}/bin/env python'%{binsuffix}'|' \ - pydoc.old >pydoc - chmod 755 pydoc - rm -f pydoc.old - ) -fi - -# add the binsuffix -if [ ! -z "%{binsuffix}" ] -then - ( cd $RPM_BUILD_ROOT%{__prefix}/bin; rm -f python[0-9a-zA-Z]*; - mv -f python python"%{binsuffix}" ) - ( cd $RPM_BUILD_ROOT%{__prefix}/man/man1; mv python.1 python%{binsuffix}.1 ) - ( cd $RPM_BUILD_ROOT%{__prefix}/bin; mv -f pydoc pydoc"%{binsuffix}" ) - ( cd $RPM_BUILD_ROOT%{__prefix}/bin; mv -f idle idle"%{binsuffix}" ) -fi - -######## -# Tools -echo '#!%{__prefix}/bin/env python%{binsuffix}' >${RPM_BUILD_ROOT}%{__prefix}/bin/idle%{binsuffix} -echo 'import os, sys' >>${RPM_BUILD_ROOT}%{__prefix}/bin/idle%{binsuffix} -echo 'os.execvp("%{__prefix}/bin/python%{binsuffix}", ["%{__prefix}/bin/python%{binsuffix}", "%{__prefix}/lib/python%{libvers}/idlelib/idle.py"] + sys.argv[1:])' >>${RPM_BUILD_ROOT}%{__prefix}/bin/idle%{binsuffix} -echo 'print "Failed to exec Idle"' >>${RPM_BUILD_ROOT}%{__prefix}/bin/idle%{binsuffix} -echo 'sys.exit(1)' >>${RPM_BUILD_ROOT}%{__prefix}/bin/idle%{binsuffix} -chmod 755 $RPM_BUILD_ROOT%{__prefix}/bin/idle%{binsuffix} -cp -a Tools $RPM_BUILD_ROOT%{__prefix}/%{libdirname}/python%{libvers} - -# MAKE FILE LISTS -rm -f mainpkg.files -find "$RPM_BUILD_ROOT""%{__prefix}"/%{libdirname}/python%{libvers}/lib-dynload -type f | - sed "s|^${RPM_BUILD_ROOT}|/|" | - grep -v -e '_tkinter.so$' >mainpkg.files -find "$RPM_BUILD_ROOT""%{__prefix}"/bin -type f | - sed "s|^${RPM_BUILD_ROOT}|/|" | - grep -v -e '/bin/idle%{binsuffix}$' >>mainpkg.files - -rm -f tools.files -find "$RPM_BUILD_ROOT""%{__prefix}"/%{libdirname}/python%{libvers}/idlelib \ - "$RPM_BUILD_ROOT""%{__prefix}"/%{libdirname}/python%{libvers}/Tools -type f | - sed "s|^${RPM_BUILD_ROOT}|/|" >tools.files -echo "%{__prefix}"/bin/idle%{binsuffix} >>tools.files - -###### -# Docs -%if %{include_docs} -mkdir -p "$RPM_BUILD_ROOT"%{config_htmldir} -( - cd "$RPM_BUILD_ROOT"%{config_htmldir} - bunzip2 < %{SOURCE1} | tar x -) -%endif - -# fix the #! line in installed files -find "$RPM_BUILD_ROOT" -type f -print0 | - xargs -0 grep -l /usr/local/bin/python | while read file -do - FIXFILE="$file" - sed 's|^#!.*python|#!%{__prefix}/bin/env python'"%{binsuffix}"'|' \ - "$FIXFILE" >/tmp/fix-python-path.$$ - cat /tmp/fix-python-path.$$ >"$FIXFILE" - rm -f /tmp/fix-python-path.$$ -done - -# check to see if there are any straggling #! lines -find "$RPM_BUILD_ROOT" -type f | xargs egrep -n '^#! */usr/local/bin/python' \ - | grep ':1:#!' >/tmp/python-rpm-files.$$ || true -if [ -s /tmp/python-rpm-files.$$ ] -then - echo '*****************************************************' - cat /tmp/python-rpm-files.$$ - cat <<@EOF - ***************************************************** - There are still files referencing /usr/local/bin/python in the - install directory. They are listed above. Please fix the .spec - file and try again. If you are an end-user, you probably want - to report this to jafo-rpms at tummy.com as well. - ***************************************************** - at EOF - rm -f /tmp/python-rpm-files.$$ - exit 1 -fi -rm -f /tmp/python-rpm-files.$$ - -######## -# CLEAN -######## -%clean -[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf $RPM_BUILD_ROOT -rm -f mainpkg.files tools.files - -######## -# FILES -######## -%files -f mainpkg.files -%defattr(-,root,root) -%doc Misc/README Misc/cheatsheet Misc/Porting -%doc LICENSE Misc/ACKS Misc/HISTORY Misc/NEWS -%{__prefix}/man/man1/python%{binsuffix}.1* - -%attr(755,root,root) %dir %{__prefix}/include/python%{libvers} -%attr(755,root,root) %dir %{__prefix}/%{libdirname}/python%{libvers}/ -%{__prefix}/%{libdirname}/python%{libvers}/*.txt -%{__prefix}/%{libdirname}/python%{libvers}/*.py* -%{__prefix}/%{libdirname}/python%{libvers}/pdb.doc -%{__prefix}/%{libdirname}/python%{libvers}/profile.doc -%{__prefix}/%{libdirname}/python%{libvers}/curses -%{__prefix}/%{libdirname}/python%{libvers}/distutils -%{__prefix}/%{libdirname}/python%{libvers}/encodings -%{__prefix}/%{libdirname}/python%{libvers}/plat-linux2 -%{__prefix}/%{libdirname}/python%{libvers}/site-packages -%{__prefix}/%{libdirname}/python%{libvers}/test -%{__prefix}/%{libdirname}/python%{libvers}/xml -%{__prefix}/%{libdirname}/python%{libvers}/email -%{__prefix}/%{libdirname}/python%{libvers}/email/mime -%{__prefix}/%{libdirname}/python%{libvers}/sqlite3 -%{__prefix}/%{libdirname}/python%{libvers}/compiler -%{__prefix}/%{libdirname}/python%{libvers}/bsddb -%{__prefix}/%{libdirname}/python%{libvers}/hotshot -%{__prefix}/%{libdirname}/python%{libvers}/logging -%{__prefix}/%{libdirname}/python%{libvers}/lib-old - -%files devel -%defattr(-,root,root) -%{__prefix}/include/python%{libvers}/*.h -%{__prefix}/%{libdirname}/python%{libvers}/config - -%files -f tools.files tools -%defattr(-,root,root) - -%if %{include_tkinter} -%files tkinter -%defattr(-,root,root) -%{__prefix}/%{libdirname}/python%{libvers}/tkinter -%{__prefix}/%{libdirname}/python%{libvers}/lib-dynload/_tkinter.so* -%endif - -%if %{include_docs} -%files docs -%defattr(-,root,root) -%{config_htmldir}/* -%endif From python-checkins at python.org Sat Mar 7 17:34:40 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 7 Mar 2009 17:34:40 +0100 (CET) Subject: [Python-checkins] r70230 - in python/branches/py3k: Include/patchlevel.h Lib/distutils/__init__.py Lib/idlelib/idlever.py Misc/NEWS Misc/RPM/python-3.1.spec README Message-ID: <20090307163440.516491E4002@bag.python.org> Author: benjamin.peterson Date: Sat Mar 7 17:34:40 2009 New Revision: 70230 Log: bump version to 3.1a1 Modified: python/branches/py3k/Include/patchlevel.h python/branches/py3k/Lib/distutils/__init__.py python/branches/py3k/Lib/idlelib/idlever.py python/branches/py3k/Misc/NEWS python/branches/py3k/Misc/RPM/python-3.1.spec python/branches/py3k/README Modified: python/branches/py3k/Include/patchlevel.h ============================================================================== --- python/branches/py3k/Include/patchlevel.h (original) +++ python/branches/py3k/Include/patchlevel.h Sat Mar 7 17:34:40 2009 @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 1 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 0 +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.1a0" +#define PY_VERSION "3.1a1" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository) */ Modified: python/branches/py3k/Lib/distutils/__init__.py ============================================================================== --- python/branches/py3k/Lib/distutils/__init__.py (original) +++ python/branches/py3k/Lib/distutils/__init__.py Sat Mar 7 17:34:40 2009 @@ -15,5 +15,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.1a0" +__version__ = "3.1a1" #--end constants-- Modified: python/branches/py3k/Lib/idlelib/idlever.py ============================================================================== --- python/branches/py3k/Lib/idlelib/idlever.py (original) +++ python/branches/py3k/Lib/idlelib/idlever.py Sat Mar 7 17:34:40 2009 @@ -1 +1 @@ -IDLE_VERSION = "3.1a0" +IDLE_VERSION = "3.1a1" Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Mar 7 17:34:40 2009 @@ -4,10 +4,10 @@ (editors: check NEWS.help for information about editing NEWS using ReST.) -What's New in Python 3.1 alpha 0 +What's New in Python 3.1 alpha 1 ================================ -*Release date: XX-XXX-200X* +*Release date: 2009-03-07* Core and Builtins ----------------- Modified: python/branches/py3k/Misc/RPM/python-3.1.spec ============================================================================== --- python/branches/py3k/Misc/RPM/python-3.1.spec (original) +++ python/branches/py3k/Misc/RPM/python-3.1.spec Sat Mar 7 17:34:40 2009 @@ -34,8 +34,8 @@ %define name python #--start constants-- -%define version 3.0rc3 -%define libver 3.0 +%define version 3.1a1 +%define libver 3.1 #--end constants-- %define release 1pydotorg %define __prefix /usr Modified: python/branches/py3k/README ============================================================================== --- python/branches/py3k/README (original) +++ python/branches/py3k/README Sat Mar 7 17:34:40 2009 @@ -1,4 +1,4 @@ -This is Python version 3.1 alpha 0 +This is Python version 3.1 alpha 1 ================================== For notes specific to this release, see RELNOTES in this directory. @@ -20,7 +20,7 @@ Release Schedule ---------------- -See PEP XXX for release details: http://www.python.org/dev/peps/pep-XXX/ +See PEP 375 for release details: http://www.python.org/dev/peps/pep-0375/ Documentation From python-checkins at python.org Sat Mar 7 17:37:32 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 7 Mar 2009 17:37:32 +0100 (CET) Subject: [Python-checkins] r70231 - python/tags/r31a1 Message-ID: <20090307163732.1AA801E4041@bag.python.org> Author: benjamin.peterson Date: Sat Mar 7 17:37:31 2009 New Revision: 70231 Log: tag 3.1a1 Added: python/tags/r31a1/ - copied from r70230, /python/branches/py3k/ From buildbot at python.org Sat Mar 7 18:30:11 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 17:30:11 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090307173011.80C071E4010@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/395 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_posix test_subprocess ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_subprocess.py", line 149, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From python-checkins at python.org Sat Mar 7 19:46:21 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 7 Mar 2009 19:46:21 +0100 (CET) Subject: [Python-checkins] r70232 - in python/branches/py3k: Include/patchlevel.h Misc/NEWS Message-ID: <20090307184621.C4E041E4002@bag.python.org> Author: benjamin.peterson Date: Sat Mar 7 19:46:21 2009 New Revision: 70232 Log: let's get cracking on 3.1a2! Modified: python/branches/py3k/Include/patchlevel.h python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Include/patchlevel.h ============================================================================== --- python/branches/py3k/Include/patchlevel.h (original) +++ python/branches/py3k/Include/patchlevel.h Sat Mar 7 19:46:21 2009 @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.1a1" +#define PY_VERSION "3.1a1+" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository) */ Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Mar 7 19:46:21 2009 @@ -4,6 +4,18 @@ (editors: check NEWS.help for information about editing NEWS using ReST.) +What's New in Python 3.1 alpha 2? +================================= + +*Release date: XXX* + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.1 alpha 1 ================================ From buildbot at python.org Sat Mar 7 20:10:04 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 07 Mar 2009 19:10:04 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090307191004.90D901E400C@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/388 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sun Mar 8 00:40:50 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 8 Mar 2009 00:40:50 +0100 (CET) Subject: [Python-checkins] r70233 - in python/branches/py3k/Lib/test: support.py test_bigmem.py Message-ID: <20090307234050.48F091E400C@bag.python.org> Author: antoine.pitrou Date: Sun Mar 8 00:40:49 2009 New Revision: 70233 Log: Issue #3700: make test_bigmem py3k-compatible, and add bytes/bytearray tests (please note: some of the tests /do/ fail when run with a sufficiently large memory parameter (-M), perhaps because of the str/bytes/bytearray overhaul) Modified: python/branches/py3k/Lib/test/support.py python/branches/py3k/Lib/test/test_bigmem.py Modified: python/branches/py3k/Lib/test/support.py ============================================================================== --- python/branches/py3k/Lib/test/support.py (original) +++ python/branches/py3k/Lib/test/support.py Sun Mar 8 00:40:49 2009 @@ -609,6 +609,10 @@ """ def decorator(f): def wrapper(self): + # Retrieve values in case someone decided to adjust them + minsize = wrapper.minsize + memuse = wrapper.memuse + overhead = wrapper.overhead if not max_memuse: # If max_memuse is 0 (the default), # we still want to run the tests with size set to a few kb, @@ -636,6 +640,9 @@ def precisionbigmemtest(size, memuse, overhead=5*_1M): def decorator(f): def wrapper(self): + size = wrapper.size + memuse = wrapper.memuse + overhead = wrapper.overhead if not real_max_memuse: maxsize = 5147 else: Modified: python/branches/py3k/Lib/test/test_bigmem.py ============================================================================== --- python/branches/py3k/Lib/test/test_bigmem.py (original) +++ python/branches/py3k/Lib/test/test_bigmem.py Sun Mar 8 00:40:49 2009 @@ -4,6 +4,7 @@ import unittest import operator import sys +import functools # Bigmem testing houserules: # @@ -13,7 +14,7 @@ # value has been created. Use 'del s' before the create_largestring call. # # - Do *not* compare large objects using assertEquals or similar. It's a -# lengty operation and the errormessage will be utterly useless due to +# lengthy operation and the errormessage will be utterly useless due to # its size. To make sure whether a result has the right contents, better # to use the strip or count methods, or compare meaningful slices. # @@ -32,19 +33,24 @@ # memuse-per-size should remain sane (less than a few thousand); if your # test uses more, adjust 'size' upward, instead. -class StrTest(unittest.TestCase): +character_size = 4 if sys.maxunicode > 0xFFFF else 2 + + +class BaseStrTest: + @bigmemtest(minsize=_2G, memuse=2) def test_capitalize(self, size): - SUBSTR = ' abc def ghi' - s = '-' * size + SUBSTR + _ = self.from_latin1 + SUBSTR = self.from_latin1(' abc def ghi') + s = _('-') * size + SUBSTR caps = s.capitalize() self.assertEquals(caps[-len(SUBSTR):], SUBSTR.capitalize()) - self.assertEquals(caps.lstrip('-'), SUBSTR) + self.assertEquals(caps.lstrip(_('-')), SUBSTR) @bigmemtest(minsize=_2G + 10, memuse=1) def test_center(self, size): - SUBSTR = ' abc def ghi' + SUBSTR = self.from_latin1(' abc def ghi') s = SUBSTR.center(size) self.assertEquals(len(s), size) lpadsize = rpadsize = (len(s) - len(SUBSTR)) // 2 @@ -53,318 +59,283 @@ self.assertEquals(s[lpadsize:-rpadsize], SUBSTR) self.assertEquals(s.strip(), SUBSTR.strip()) - @precisionbigmemtest(size=_2G - 1, memuse=1) - def test_center_unicode(self, size): - SUBSTR = ' abc def ghi' - try: - s = SUBSTR.center(size) - except OverflowError: - pass # acceptable on 32-bit - else: - self.assertEquals(len(s), size) - lpadsize = rpadsize = (len(s) - len(SUBSTR)) // 2 - if len(s) % 2: - lpadsize += 1 - self.assertEquals(s[lpadsize:-rpadsize], SUBSTR) - self.assertEquals(s.strip(), SUBSTR.strip()) - del s - @bigmemtest(minsize=_2G, memuse=2) def test_count(self, size): - SUBSTR = ' abc def ghi' - s = '.' * size + SUBSTR - self.assertEquals(s.count('.'), size) - s += '.' - self.assertEquals(s.count('.'), size + 1) - self.assertEquals(s.count(' '), 3) - self.assertEquals(s.count('i'), 1) - self.assertEquals(s.count('j'), 0) - - @bigmemtest(minsize=_2G + 2, memuse=3) - def test_decode(self, size): - s = b'.' * size - self.assertEquals(len(s.decode('utf-8')), size) - - def basic_encode_test(self, size, enc, c='.', expectedsize=None): - if expectedsize is None: - expectedsize = size - - s = c * size - self.assertEquals(len(s.encode(enc)), expectedsize) - - @bigmemtest(minsize=_2G + 2, memuse=3) - def test_encode(self, size): - return self.basic_encode_test(size, 'utf-8') - - @precisionbigmemtest(size=_4G / 6 + 2, memuse=2) - def test_encode_raw_unicode_escape(self, size): - try: - return self.basic_encode_test(size, 'raw_unicode_escape') - except MemoryError: - pass # acceptable on 32-bit - - @precisionbigmemtest(size=_4G / 5 + 70, memuse=3) - def test_encode_utf7(self, size): - try: - return self.basic_encode_test(size, 'utf7') - except MemoryError: - pass # acceptable on 32-bit - - @precisionbigmemtest(size=_4G / 4 + 5, memuse=6) - def test_encode_utf32(self, size): - try: - return self.basic_encode_test(size, 'utf32', expectedsize=4*size+4) - except MemoryError: - pass # acceptable on 32-bit - - @precisionbigmemtest(size=_2G-1, memuse=2) - def test_decodeascii(self, size): - return self.basic_encode_test(size, 'ascii', c='A') - - @precisionbigmemtest(size=_4G / 5, memuse=6+2) - def test_unicode_repr_oflw(self, size): - try: - s = "\uAAAA"*size - r = repr(s) - except MemoryError: - pass # acceptable on 32-bit - else: - self.failUnless(s == eval(r)) + _ = self.from_latin1 + SUBSTR = _(' abc def ghi') + s = _('.') * size + SUBSTR + self.assertEquals(s.count(_('.')), size) + s += _('.') + self.assertEquals(s.count(_('.')), size + 1) + self.assertEquals(s.count(_(' ')), 3) + self.assertEquals(s.count(_('i')), 1) + self.assertEquals(s.count(_('j')), 0) @bigmemtest(minsize=_2G, memuse=2) def test_endswith(self, size): - SUBSTR = ' abc def ghi' - s = '-' * size + SUBSTR + _ = self.from_latin1 + SUBSTR = _(' abc def ghi') + s = _('-') * size + SUBSTR self.failUnless(s.endswith(SUBSTR)) self.failUnless(s.endswith(s)) - s2 = '...' + s + s2 = _('...') + s self.failUnless(s2.endswith(s)) - self.failIf(s.endswith('a' + SUBSTR)) + self.failIf(s.endswith(_('a') + SUBSTR)) self.failIf(SUBSTR.endswith(s)) @bigmemtest(minsize=_2G + 10, memuse=2) def test_expandtabs(self, size): - s = '-' * size + _ = self.from_latin1 + s = _('-') * size tabsize = 8 self.assertEquals(s.expandtabs(), s) del s slen, remainder = divmod(size, tabsize) - s = ' \t' * slen + s = _(' \t') * slen s = s.expandtabs(tabsize) self.assertEquals(len(s), size - remainder) - self.assertEquals(len(s.strip(' ')), 0) + self.assertEquals(len(s.strip(_(' '))), 0) @bigmemtest(minsize=_2G, memuse=2) def test_find(self, size): - SUBSTR = ' abc def ghi' + _ = self.from_latin1 + SUBSTR = _(' abc def ghi') sublen = len(SUBSTR) - s = ''.join([SUBSTR, '-' * size, SUBSTR]) - self.assertEquals(s.find(' '), 0) + s = _('').join([SUBSTR, _('-') * size, SUBSTR]) + self.assertEquals(s.find(_(' ')), 0) self.assertEquals(s.find(SUBSTR), 0) - self.assertEquals(s.find(' ', sublen), sublen + size) + self.assertEquals(s.find(_(' '), sublen), sublen + size) self.assertEquals(s.find(SUBSTR, len(SUBSTR)), sublen + size) - self.assertEquals(s.find('i'), SUBSTR.find('i')) - self.assertEquals(s.find('i', sublen), - sublen + size + SUBSTR.find('i')) - self.assertEquals(s.find('i', size), - sublen + size + SUBSTR.find('i')) - self.assertEquals(s.find('j'), -1) + self.assertEquals(s.find(_('i')), SUBSTR.find(_('i'))) + self.assertEquals(s.find(_('i'), sublen), + sublen + size + SUBSTR.find(_('i'))) + self.assertEquals(s.find(_('i'), size), + sublen + size + SUBSTR.find(_('i'))) + self.assertEquals(s.find(_('j')), -1) @bigmemtest(minsize=_2G, memuse=2) def test_index(self, size): - SUBSTR = ' abc def ghi' + _ = self.from_latin1 + SUBSTR = _(' abc def ghi') sublen = len(SUBSTR) - s = ''.join([SUBSTR, '-' * size, SUBSTR]) - self.assertEquals(s.index(' '), 0) + s = _('').join([SUBSTR, _('-') * size, SUBSTR]) + self.assertEquals(s.index(_(' ')), 0) self.assertEquals(s.index(SUBSTR), 0) - self.assertEquals(s.index(' ', sublen), sublen + size) + self.assertEquals(s.index(_(' '), sublen), sublen + size) self.assertEquals(s.index(SUBSTR, sublen), sublen + size) - self.assertEquals(s.index('i'), SUBSTR.index('i')) - self.assertEquals(s.index('i', sublen), - sublen + size + SUBSTR.index('i')) - self.assertEquals(s.index('i', size), - sublen + size + SUBSTR.index('i')) - self.assertRaises(ValueError, s.index, 'j') + self.assertEquals(s.index(_('i')), SUBSTR.index(_('i'))) + self.assertEquals(s.index(_('i'), sublen), + sublen + size + SUBSTR.index(_('i'))) + self.assertEquals(s.index(_('i'), size), + sublen + size + SUBSTR.index(_('i'))) + self.assertRaises(ValueError, s.index, _('j')) @bigmemtest(minsize=_2G, memuse=2) def test_isalnum(self, size): - SUBSTR = '123456' - s = 'a' * size + SUBSTR + _ = self.from_latin1 + SUBSTR = _('123456') + s = _('a') * size + SUBSTR self.failUnless(s.isalnum()) - s += '.' + s += _('.') self.failIf(s.isalnum()) @bigmemtest(minsize=_2G, memuse=2) def test_isalpha(self, size): - SUBSTR = 'zzzzzzz' - s = 'a' * size + SUBSTR + _ = self.from_latin1 + SUBSTR = _('zzzzzzz') + s = _('a') * size + SUBSTR self.failUnless(s.isalpha()) - s += '.' + s += _('.') self.failIf(s.isalpha()) @bigmemtest(minsize=_2G, memuse=2) def test_isdigit(self, size): - SUBSTR = '123456' - s = '9' * size + SUBSTR + _ = self.from_latin1 + SUBSTR = _('123456') + s = _('9') * size + SUBSTR self.failUnless(s.isdigit()) - s += 'z' + s += _('z') self.failIf(s.isdigit()) @bigmemtest(minsize=_2G, memuse=2) def test_islower(self, size): - chars = ''.join([ chr(c) for c in range(255) if not chr(c).isupper() ]) + _ = self.from_latin1 + chars = _(''.join( + chr(c) for c in range(255) if not chr(c).isupper())) repeats = size // len(chars) + 2 s = chars * repeats self.failUnless(s.islower()) - s += 'A' + s += _('A') self.failIf(s.islower()) @bigmemtest(minsize=_2G, memuse=2) def test_isspace(self, size): - whitespace = ' \f\n\r\t\v' + _ = self.from_latin1 + whitespace = _(' \f\n\r\t\v') repeats = size // len(whitespace) + 2 s = whitespace * repeats self.failUnless(s.isspace()) - s += 'j' + s += _('j') self.failIf(s.isspace()) @bigmemtest(minsize=_2G, memuse=2) def test_istitle(self, size): - SUBSTR = '123456' - s = ''.join(['A', 'a' * size, SUBSTR]) + _ = self.from_latin1 + SUBSTR = _('123456') + s = _('').join([_('A'), _('a') * size, SUBSTR]) self.failUnless(s.istitle()) - s += 'A' + s += _('A') self.failUnless(s.istitle()) - s += 'aA' + s += _('aA') self.failIf(s.istitle()) @bigmemtest(minsize=_2G, memuse=2) def test_isupper(self, size): - chars = ''.join([ chr(c) for c in range(255) if not chr(c).islower() ]) + _ = self.from_latin1 + chars = _(''.join( + chr(c) for c in range(255) if not chr(c).islower())) repeats = size // len(chars) + 2 s = chars * repeats self.failUnless(s.isupper()) - s += 'a' + s += _('a') self.failIf(s.isupper()) @bigmemtest(minsize=_2G, memuse=2) def test_join(self, size): - s = 'A' * size - x = s.join(['aaaaa', 'bbbbb']) - self.assertEquals(x.count('a'), 5) - self.assertEquals(x.count('b'), 5) - self.failUnless(x.startswith('aaaaaA')) - self.failUnless(x.endswith('Abbbbb')) + _ = self.from_latin1 + s = _('A') * size + x = s.join([_('aaaaa'), _('bbbbb')]) + self.assertEquals(x.count(_('a')), 5) + self.assertEquals(x.count(_('b')), 5) + self.failUnless(x.startswith(_('aaaaaA'))) + self.failUnless(x.endswith(_('Abbbbb'))) @bigmemtest(minsize=_2G + 10, memuse=1) def test_ljust(self, size): - SUBSTR = ' abc def ghi' + _ = self.from_latin1 + SUBSTR = _(' abc def ghi') s = SUBSTR.ljust(size) - self.failUnless(s.startswith(SUBSTR + ' ')) + self.failUnless(s.startswith(SUBSTR + _(' '))) self.assertEquals(len(s), size) self.assertEquals(s.strip(), SUBSTR.strip()) @bigmemtest(minsize=_2G + 10, memuse=2) def test_lower(self, size): - s = 'A' * size + _ = self.from_latin1 + s = _('A') * size s = s.lower() self.assertEquals(len(s), size) - self.assertEquals(s.count('a'), size) + self.assertEquals(s.count(_('a')), size) @bigmemtest(minsize=_2G + 10, memuse=1) def test_lstrip(self, size): - SUBSTR = 'abc def ghi' + _ = self.from_latin1 + SUBSTR = _('abc def ghi') s = SUBSTR.rjust(size) self.assertEquals(len(s), size) self.assertEquals(s.lstrip(), SUBSTR.lstrip()) del s s = SUBSTR.ljust(size) self.assertEquals(len(s), size) - stripped = s.lstrip() - self.failUnless(stripped is s) + # Type-specific optimization + if isinstance(s, (str, bytes)): + stripped = s.lstrip() + self.failUnless(stripped is s) @bigmemtest(minsize=_2G + 10, memuse=2) def test_replace(self, size): - replacement = 'a' - s = ' ' * size - s = s.replace(' ', replacement) + _ = self.from_latin1 + replacement = _('a') + s = _(' ') * size + s = s.replace(_(' '), replacement) self.assertEquals(len(s), size) self.assertEquals(s.count(replacement), size) - s = s.replace(replacement, ' ', size - 4) + s = s.replace(replacement, _(' '), size - 4) self.assertEquals(len(s), size) self.assertEquals(s.count(replacement), 4) - self.assertEquals(s[-10:], ' aaaa') + self.assertEquals(s[-10:], _(' aaaa')) @bigmemtest(minsize=_2G, memuse=2) def test_rfind(self, size): - SUBSTR = ' abc def ghi' + _ = self.from_latin1 + SUBSTR = _(' abc def ghi') sublen = len(SUBSTR) - s = ''.join([SUBSTR, '-' * size, SUBSTR]) - self.assertEquals(s.rfind(' '), sublen + size + SUBSTR.rfind(' ')) + s = _('').join([SUBSTR, _('-') * size, SUBSTR]) + self.assertEquals(s.rfind(_(' ')), sublen + size + SUBSTR.rfind(_(' '))) self.assertEquals(s.rfind(SUBSTR), sublen + size) - self.assertEquals(s.rfind(' ', 0, size), SUBSTR.rfind(' ')) + self.assertEquals(s.rfind(_(' '), 0, size), SUBSTR.rfind(_(' '))) self.assertEquals(s.rfind(SUBSTR, 0, sublen + size), 0) - self.assertEquals(s.rfind('i'), sublen + size + SUBSTR.rfind('i')) - self.assertEquals(s.rfind('i', 0, sublen), SUBSTR.rfind('i')) - self.assertEquals(s.rfind('i', 0, sublen + size), - SUBSTR.rfind('i')) - self.assertEquals(s.rfind('j'), -1) + self.assertEquals(s.rfind(_('i')), sublen + size + SUBSTR.rfind(_('i'))) + self.assertEquals(s.rfind(_('i'), 0, sublen), SUBSTR.rfind(_('i'))) + self.assertEquals(s.rfind(_('i'), 0, sublen + size), + SUBSTR.rfind(_('i'))) + self.assertEquals(s.rfind(_('j')), -1) @bigmemtest(minsize=_2G, memuse=2) def test_rindex(self, size): - SUBSTR = ' abc def ghi' + _ = self.from_latin1 + SUBSTR = _(' abc def ghi') sublen = len(SUBSTR) - s = ''.join([SUBSTR, '-' * size, SUBSTR]) - self.assertEquals(s.rindex(' '), - sublen + size + SUBSTR.rindex(' ')) + s = _('').join([SUBSTR, _('-') * size, SUBSTR]) + self.assertEquals(s.rindex(_(' ')), + sublen + size + SUBSTR.rindex(_(' '))) self.assertEquals(s.rindex(SUBSTR), sublen + size) - self.assertEquals(s.rindex(' ', 0, sublen + size - 1), - SUBSTR.rindex(' ')) + self.assertEquals(s.rindex(_(' '), 0, sublen + size - 1), + SUBSTR.rindex(_(' '))) self.assertEquals(s.rindex(SUBSTR, 0, sublen + size), 0) - self.assertEquals(s.rindex('i'), - sublen + size + SUBSTR.rindex('i')) - self.assertEquals(s.rindex('i', 0, sublen), SUBSTR.rindex('i')) - self.assertEquals(s.rindex('i', 0, sublen + size), - SUBSTR.rindex('i')) - self.assertRaises(ValueError, s.rindex, 'j') + self.assertEquals(s.rindex(_('i')), + sublen + size + SUBSTR.rindex(_('i'))) + self.assertEquals(s.rindex(_('i'), 0, sublen), SUBSTR.rindex(_('i'))) + self.assertEquals(s.rindex(_('i'), 0, sublen + size), + SUBSTR.rindex(_('i'))) + self.assertRaises(ValueError, s.rindex, _('j')) @bigmemtest(minsize=_2G + 10, memuse=1) def test_rjust(self, size): - SUBSTR = ' abc def ghi' + _ = self.from_latin1 + SUBSTR = _(' abc def ghi') s = SUBSTR.ljust(size) - self.failUnless(s.startswith(SUBSTR + ' ')) + self.failUnless(s.startswith(SUBSTR + _(' '))) self.assertEquals(len(s), size) self.assertEquals(s.strip(), SUBSTR.strip()) @bigmemtest(minsize=_2G + 10, memuse=1) def test_rstrip(self, size): - SUBSTR = ' abc def ghi' + _ = self.from_latin1 + SUBSTR = _(' abc def ghi') s = SUBSTR.ljust(size) self.assertEquals(len(s), size) self.assertEquals(s.rstrip(), SUBSTR.rstrip()) del s s = SUBSTR.rjust(size) self.assertEquals(len(s), size) - stripped = s.rstrip() - self.failUnless(stripped is s) + # Type-specific optimization + if isinstance(s, (str, bytes)): + stripped = s.rstrip() + self.failUnless(stripped is s) # The test takes about size bytes to build a string, and then about # sqrt(size) substrings of sqrt(size) in size and a list to # hold sqrt(size) items. It's close but just over 2x size. @bigmemtest(minsize=_2G, memuse=2.1) def test_split_small(self, size): + _ = self.from_latin1 # Crudely calculate an estimate so that the result of s.split won't # take up an inordinate amount of memory chunksize = int(size ** 0.5 + 2) - SUBSTR = 'a' + ' ' * chunksize + SUBSTR = _('a') + _(' ') * chunksize s = SUBSTR * chunksize l = s.split() self.assertEquals(len(l), chunksize) - self.assertEquals(set(l), set(['a'])) + expected = _('a') + for item in l: + self.assertEquals(item, expected) del l - l = s.split('a') + l = s.split(_('a')) self.assertEquals(len(l), chunksize + 1) - self.assertEquals(set(l), set(['', ' ' * chunksize])) + expected = _(' ') * chunksize + for item in filter(None, l): + self.assertEquals(item, expected) # Allocates a string of twice size (and briefly two) and a list of # size. Because of internal affairs, the s.split() call produces a @@ -374,37 +345,43 @@ # 8*size bytes. @bigmemtest(minsize=_2G + 5, memuse=10) def test_split_large(self, size): - s = ' a' * size + ' ' + _ = self.from_latin1 + s = _(' a') * size + _(' ') l = s.split() self.assertEquals(len(l), size) - self.assertEquals(set(l), set(['a'])) + self.assertEquals(set(l), set([_('a')])) del l - l = s.split('a') + l = s.split(_('a')) self.assertEquals(len(l), size + 1) - self.assertEquals(set(l), set([' '])) + self.assertEquals(set(l), set([_(' ')])) @bigmemtest(minsize=_2G, memuse=2.1) def test_splitlines(self, size): + _ = self.from_latin1 # Crudely calculate an estimate so that the result of s.split won't # take up an inordinate amount of memory chunksize = int(size ** 0.5 + 2) // 2 - SUBSTR = ' ' * chunksize + '\n' + ' ' * chunksize + '\r\n' + SUBSTR = _(' ') * chunksize + _('\n') + _(' ') * chunksize + _('\r\n') s = SUBSTR * chunksize l = s.splitlines() self.assertEquals(len(l), chunksize * 2) - self.assertEquals(set(l), set([' ' * chunksize])) + expected = _(' ') * chunksize + for item in l: + self.assertEquals(item, expected) @bigmemtest(minsize=_2G, memuse=2) def test_startswith(self, size): - SUBSTR = ' abc def ghi' - s = '-' * size + SUBSTR + _ = self.from_latin1 + SUBSTR = _(' abc def ghi') + s = _('-') * size + SUBSTR self.failUnless(s.startswith(s)) - self.failUnless(s.startswith('-' * size)) + self.failUnless(s.startswith(_('-') * size)) self.failIf(s.startswith(SUBSTR)) @bigmemtest(minsize=_2G, memuse=1) def test_strip(self, size): - SUBSTR = ' abc def ghi ' + _ = self.from_latin1 + SUBSTR = _(' abc def ghi ') s = SUBSTR.rjust(size) self.assertEquals(len(s), size) self.assertEquals(s.strip(), SUBSTR.strip()) @@ -415,7 +392,8 @@ @bigmemtest(minsize=_2G, memuse=2) def test_swapcase(self, size): - SUBSTR = "aBcDeFG12.'\xa9\x00" + _ = self.from_latin1 + SUBSTR = _("aBcDeFG12.'\xa9\x00") sublen = len(SUBSTR) repeats = size // sublen + 2 s = SUBSTR * repeats @@ -426,7 +404,8 @@ @bigmemtest(minsize=_2G, memuse=2) def test_title(self, size): - SUBSTR = 'SpaaHAaaAaham' + _ = self.from_latin1 + SUBSTR = _('SpaaHAaaAaham') s = SUBSTR * (size // len(SUBSTR) + 2) s = s.title() self.failUnless(s.startswith((SUBSTR * 3).title())) @@ -434,8 +413,19 @@ @bigmemtest(minsize=_2G, memuse=2) def test_translate(self, size): - trans = {ord('.'):'-', ord('a'):'!', ord('Z'):'$'} - SUBSTR = 'aZz.z.Aaz.' + _ = self.from_latin1 + trans = { + ord(_('.')): _('-'), + ord(_('a')): _('!'), + ord(_('Z')): _('$'), + } + SUBSTR = _('aZz.z.Aaz.') + if not isinstance(SUBSTR, str): + # Workaround the inexistence of bytes.maketrans() + chars = bytearray(range(256)) + for k, v in trans.items(): + chars[k] = ord(v) + trans = chars sublen = len(SUBSTR) repeats = size // sublen + 2 s = SUBSTR * repeats @@ -443,106 +433,54 @@ self.assertEquals(len(s), repeats * sublen) self.assertEquals(s[:sublen], SUBSTR.translate(trans)) self.assertEquals(s[-sublen:], SUBSTR.translate(trans)) - self.assertEquals(s.count('.'), 0) - self.assertEquals(s.count('!'), repeats * 2) - self.assertEquals(s.count('z'), repeats * 3) + self.assertEquals(s.count(_('.')), 0) + self.assertEquals(s.count(_('!')), repeats * 2) + self.assertEquals(s.count(_('z')), repeats * 3) @bigmemtest(minsize=_2G + 5, memuse=2) def test_upper(self, size): - s = 'a' * size + _ = self.from_latin1 + s = _('a') * size s = s.upper() self.assertEquals(len(s), size) - self.assertEquals(s.count('A'), size) + self.assertEquals(s.count(_('A')), size) @bigmemtest(minsize=_2G + 20, memuse=1) def test_zfill(self, size): - SUBSTR = '-568324723598234' + _ = self.from_latin1 + SUBSTR = _('-568324723598234') s = SUBSTR.zfill(size) - self.failUnless(s.endswith('0' + SUBSTR[1:])) - self.failUnless(s.startswith('-0')) + self.failUnless(s.endswith(_('0') + SUBSTR[1:])) + self.failUnless(s.startswith(_('-0'))) self.assertEquals(len(s), size) - self.assertEquals(s.count('0'), size - len(SUBSTR)) - - @bigmemtest(minsize=_2G + 10, memuse=2) - def test_format(self, size): - s = '-' * size - sf = '%s' % (s,) - self.assertEqual(s, sf) - del sf - sf = '..%s..' % (s,) - self.assertEquals(len(sf), len(s) + 4) - self.failUnless(sf.startswith('..-')) - self.failUnless(sf.endswith('-..')) - del s, sf - - size //= 2 - edge = '-' * size - s = ''.join([edge, '%s', edge]) - del edge - s = s % '...' - self.assertEquals(len(s), size * 2 + 3) - self.assertEquals(s.count('.'), 3) - self.assertEquals(s.count('-'), size * 2) - - @bigmemtest(minsize=_2G + 10, memuse=2) - def test_repr_small(self, size): - s = '-' * size - s = repr(s) - self.assertEquals(len(s), size + 2) - self.assertEquals(s[0], "'") - self.assertEquals(s[-1], "'") - self.assertEquals(s.count('-'), size) - del s - # repr() will create a string four times as large as this 'binary - # string', but we don't want to allocate much more than twice - # size in total. (We do extra testing in test_repr_large()) - size = size // 5 * 2 - s = '\x00' * size - s = repr(s) - self.assertEquals(len(s), size * 4 + 2) - self.assertEquals(s[0], "'") - self.assertEquals(s[-1], "'") - self.assertEquals(s.count('\\'), size) - self.assertEquals(s.count('0'), size * 2) - - @bigmemtest(minsize=_2G + 10, memuse=5) - def test_repr_large(self, size): - s = '\x00' * size - s = repr(s) - self.assertEquals(len(s), size * 4 + 2) - self.assertEquals(s[0], "'") - self.assertEquals(s[-1], "'") - self.assertEquals(s.count('\\'), size) - self.assertEquals(s.count('0'), size * 2) - - @bigmemtest(minsize=2**32 / 5, memuse=6+2) - def test_unicode_repr(self, size): - s = "\uAAAA" * size - self.failUnless(len(repr(s)) > size) + self.assertEquals(s.count(_('0')), size - len(SUBSTR)) # This test is meaningful even with size < 2G, as long as the # doubled string is > 2G (but it tests more if both are > 2G :) @bigmemtest(minsize=_1G + 2, memuse=3) def test_concat(self, size): - s = '.' * size + _ = self.from_latin1 + s = _('.') * size self.assertEquals(len(s), size) s = s + s self.assertEquals(len(s), size * 2) - self.assertEquals(s.count('.'), size * 2) + self.assertEquals(s.count(_('.')), size * 2) # This test is meaningful even with size < 2G, as long as the # repeated string is > 2G (but it tests more if both are > 2G :) @bigmemtest(minsize=_1G + 2, memuse=3) def test_repeat(self, size): - s = '.' * size + _ = self.from_latin1 + s = _('.') * size self.assertEquals(len(s), size) s = s * 2 self.assertEquals(len(s), size * 2) - self.assertEquals(s.count('.'), size * 2) + self.assertEquals(s.count(_('.')), size * 2) - @bigmemtest(minsize=_2G + 20, memuse=1) + @bigmemtest(minsize=_2G + 20, memuse=2) def test_slice_and_getitem(self, size): - SUBSTR = '0123456789' + _ = self.from_latin1 + SUBSTR = _('0123456789') sublen = len(SUBSTR) s = SUBSTR * (size // sublen) stepsize = len(s) // 100 @@ -560,9 +498,9 @@ self.assertEquals(s[-1], SUBSTR[-1]) self.assertEquals(s[len(s) - 10], SUBSTR[0]) self.assertEquals(s[-sublen], SUBSTR[0]) - self.assertEquals(s[len(s):], '') - self.assertEquals(s[len(s) - 1:], SUBSTR[-1]) - self.assertEquals(s[-1:], SUBSTR[-1]) + self.assertEquals(s[len(s):], _('')) + self.assertEquals(s[len(s) - 1:], SUBSTR[-1:]) + self.assertEquals(s[-1:], SUBSTR[-1:]) self.assertEquals(s[len(s) - sublen:], SUBSTR) self.assertEquals(s[-sublen:], SUBSTR) self.assertEquals(len(s[:]), len(s)) @@ -575,27 +513,29 @@ @bigmemtest(minsize=_2G, memuse=2) def test_contains(self, size): - SUBSTR = '0123456789' - edge = '-' * (size // 2) - s = ''.join([edge, SUBSTR, edge]) + _ = self.from_latin1 + SUBSTR = _('0123456789') + edge = _('-') * (size // 2) + s = _('').join([edge, SUBSTR, edge]) del edge self.failUnless(SUBSTR in s) self.failIf(SUBSTR * 2 in s) - self.failUnless('-' in s) - self.failIf('a' in s) - s += 'a' - self.failUnless('a' in s) + self.failUnless(_('-') in s) + self.failIf(_('a') in s) + s += _('a') + self.failUnless(_('a') in s) @bigmemtest(minsize=_2G + 10, memuse=2) def test_compare(self, size): - s1 = '-' * size - s2 = '-' * size + _ = self.from_latin1 + s1 = _('-') * size + s2 = _('-') * size self.assertEqual(s1, s2) del s2 - s2 = s1 + 'a' + s2 = s1 + _('a') self.failIf(s1 == s2) del s2 - s2 = '.' * size + s2 = _('.') * size self.failIf(s1 == s2) @bigmemtest(minsize=_2G + 10, memuse=1) @@ -606,12 +546,181 @@ # test is dodgy (there's no *guarantee* that the two things should # have a different hash, even if they, in the current # implementation, almost always do.) - s = '\x00' * size + _ = self.from_latin1 + s = _('\x00') * size h1 = hash(s) del s - s = '\x00' * (size + 1) + s = _('\x00') * (size + 1) self.failIf(h1 == hash(s)) + +class StrTest(unittest.TestCase, BaseStrTest): + + def from_latin1(self, s): + return s + + def basic_encode_test(self, size, enc, c='.', expectedsize=None): + if expectedsize is None: + expectedsize = size + + s = c * size + self.assertEquals(len(s.encode(enc)), expectedsize) + + def setUp(self): + # HACK: adjust memory use of tests inherited from BaseStrTest + # according to character size. + self._adjusted = {} + for name in dir(BaseStrTest): + if not name.startswith('test_'): + continue + meth = getattr(type(self), name) + try: + memuse = meth.memuse + except AttributeError: + continue + meth.memuse = character_size * memuse + self._adjusted[name] = memuse + + def tearDown(self): + for name, memuse in self._adjusted.items(): + getattr(type(self), name).memuse = memuse + + @bigmemtest(minsize=_2G + 2, memuse=character_size + 1) + def test_encode(self, size): + return self.basic_encode_test(size, 'utf-8') + + @precisionbigmemtest(size=_4G // 6 + 2, memuse=character_size + 1) + def test_encode_raw_unicode_escape(self, size): + try: + return self.basic_encode_test(size, 'raw_unicode_escape') + except MemoryError: + pass # acceptable on 32-bit + + @precisionbigmemtest(size=_4G // 5 + 70, memuse=character_size + 1) + def test_encode_utf7(self, size): + try: + return self.basic_encode_test(size, 'utf7') + except MemoryError: + pass # acceptable on 32-bit + + @precisionbigmemtest(size=_4G // 4 + 5, memuse=character_size + 4) + def test_encode_utf32(self, size): + try: + return self.basic_encode_test(size, 'utf32', expectedsize=4*size+4) + except MemoryError: + pass # acceptable on 32-bit + + @precisionbigmemtest(size=_2G - 1, memuse=character_size + 1) + def test_encode_ascii(self, size): + return self.basic_encode_test(size, 'ascii', c='A') + + @precisionbigmemtest(size=_4G // 5, memuse=character_size * (6 + 1)) + def test_unicode_repr_overflow(self, size): + try: + s = "\uAAAA"*size + r = repr(s) + except MemoryError: + pass # acceptable on 32-bit + else: + self.failUnless(s == eval(r)) + + @bigmemtest(minsize=_2G + 10, memuse=character_size * 2) + def test_format(self, size): + s = '-' * size + sf = '%s' % (s,) + self.assertEqual(s, sf) + del sf + sf = '..%s..' % (s,) + self.assertEquals(len(sf), len(s) + 4) + self.failUnless(sf.startswith('..-')) + self.failUnless(sf.endswith('-..')) + del s, sf + + size //= 2 + edge = '-' * size + s = ''.join([edge, '%s', edge]) + del edge + s = s % '...' + self.assertEquals(len(s), size * 2 + 3) + self.assertEquals(s.count('.'), 3) + self.assertEquals(s.count('-'), size * 2) + + @bigmemtest(minsize=_2G + 10, memuse=character_size * 2) + def test_repr_small(self, size): + s = '-' * size + s = repr(s) + self.assertEquals(len(s), size + 2) + self.assertEquals(s[0], "'") + self.assertEquals(s[-1], "'") + self.assertEquals(s.count('-'), size) + del s + # repr() will create a string four times as large as this 'binary + # string', but we don't want to allocate much more than twice + # size in total. (We do extra testing in test_repr_large()) + size = size // 5 * 2 + s = '\x00' * size + s = repr(s) + self.assertEquals(len(s), size * 4 + 2) + self.assertEquals(s[0], "'") + self.assertEquals(s[-1], "'") + self.assertEquals(s.count('\\'), size) + self.assertEquals(s.count('0'), size * 2) + + @bigmemtest(minsize=_2G + 10, memuse=character_size * 5) + def test_repr_large(self, size): + s = '\x00' * size + s = repr(s) + self.assertEquals(len(s), size * 4 + 2) + self.assertEquals(s[0], "'") + self.assertEquals(s[-1], "'") + self.assertEquals(s.count('\\'), size) + self.assertEquals(s.count('0'), size * 2) + + @bigmemtest(minsize=2**32 / 5, memuse=character_size * 7) + def test_unicode_repr(self, size): + s = "\uAAAA" * size + for f in (repr, ascii): + r = f(s) + self.failUnless(len(r) > size) + self.failUnless(r.endswith(r"\uaaaa'"), r[-10:]) + del r + + # The character takes 4 bytes even in UCS-2 builds because it will + # be decomposed into surrogates. + @bigmemtest(minsize=2**32 / 5, memuse=4 + character_size * 9) + def test_unicode_repr_wide(self, size): + s = "\U0001AAAA" * size + for f in (repr, ascii): + r = f(s) + self.failUnless(len(r) > size) + self.failUnless(r.endswith(r"\U0001aaaa'"), r[-12:]) + del r + + +class BytesTest(unittest.TestCase, BaseStrTest): + + def from_latin1(self, s): + return s.encode("latin1") + + @bigmemtest(minsize=_2G + 2, memuse=1 + character_size) + def test_decode(self, size): + s = self.from_latin1('.') * size + self.assertEquals(len(s.decode('utf-8')), size) + + +class BytearrayTest(unittest.TestCase, BaseStrTest): + + def from_latin1(self, s): + return bytearray(s.encode("latin1")) + + @bigmemtest(minsize=_2G + 2, memuse=1 + character_size) + def test_decode(self, size): + s = self.from_latin1('.') * size + self.assertEquals(len(s.decode('utf-8')), size) + + test_hash = None + test_split_large = None + class TupleTest(unittest.TestCase): # Tuples have a small, fixed-sized head and an array of pointers to @@ -1048,7 +1157,8 @@ self.assertEquals(l[-10:], [5] * 10) def test_main(): - support.run_unittest(StrTest, TupleTest, ListTest) + support.run_unittest(StrTest, BytesTest, BytearrayTest, + TupleTest, ListTest) if __name__ == '__main__': if len(sys.argv) > 1: From python-checkins at python.org Sun Mar 8 00:52:26 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 8 Mar 2009 00:52:26 +0100 (CET) Subject: [Python-checkins] r70234 - python/branches/py3k/Lib/test/test_bigmem.py Message-ID: <20090307235226.B05D91E4002@bag.python.org> Author: antoine.pitrou Date: Sun Mar 8 00:52:26 2009 New Revision: 70234 Log: Add notice about strange behaviour of the bigmem tests Modified: python/branches/py3k/Lib/test/test_bigmem.py Modified: python/branches/py3k/Lib/test/test_bigmem.py ============================================================================== --- python/branches/py3k/Lib/test/test_bigmem.py (original) +++ python/branches/py3k/Lib/test/test_bigmem.py Sun Mar 8 00:52:26 2009 @@ -33,6 +33,10 @@ # memuse-per-size should remain sane (less than a few thousand); if your # test uses more, adjust 'size' upward, instead. +# BEWARE: it seems that one failing test can yield other subsequent tests to +# fail as well. I do not know whether it is due to memory fragmentation +# issues, or other specifics of the platform malloc() routine. + character_size = 4 if sys.maxunicode > 0xFFFF else 2 From python-checkins at python.org Sun Mar 8 01:21:17 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 8 Mar 2009 01:21:17 +0100 (CET) Subject: [Python-checkins] r70235 - python/trunk/Objects/bytearrayobject.c Message-ID: <20090308002117.C7F791E4002@bag.python.org> Author: benjamin.peterson Date: Sun Mar 8 01:21:17 2009 New Revision: 70235 Log: fix funky indentation Modified: python/trunk/Objects/bytearrayobject.c Modified: python/trunk/Objects/bytearrayobject.c ============================================================================== --- python/trunk/Objects/bytearrayobject.c (original) +++ python/trunk/Objects/bytearrayobject.c Sun Mar 8 01:21:17 2009 @@ -1095,11 +1095,11 @@ static void bytes_dealloc(PyByteArrayObject *self) { - if (self->ob_exports > 0) { - PyErr_SetString(PyExc_SystemError, + if (self->ob_exports > 0) { + PyErr_SetString(PyExc_SystemError, "deallocated bytearray object has exported buffers"); - PyErr_Print(); - } + PyErr_Print(); + } if (self->ob_bytes != 0) { PyMem_Free(self->ob_bytes); } From buildbot at python.org Sun Mar 8 01:37:14 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 08 Mar 2009 00:37:14 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090308003714.54C031E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/397 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_posix test_subprocess ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_subprocess.py", line 149, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From python-checkins at python.org Sun Mar 8 02:11:18 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 8 Mar 2009 02:11:18 +0100 (CET) Subject: [Python-checkins] r70236 - sandbox/trunk/dbm_sqlite/alt/dbsqlite.py Message-ID: <20090308011118.DCFE71E4002@bag.python.org> Author: raymond.hettinger Date: Sun Mar 8 02:11:18 2009 New Revision: 70236 Log: Add optimization note. Modified: sandbox/trunk/dbm_sqlite/alt/dbsqlite.py Modified: sandbox/trunk/dbm_sqlite/alt/dbsqlite.py ============================================================================== --- sandbox/trunk/dbm_sqlite/alt/dbsqlite.py (original) +++ sandbox/trunk/dbm_sqlite/alt/dbsqlite.py Sun Mar 8 02:11:18 2009 @@ -11,6 +11,7 @@ # ??? Any difference between blobs and text # ??? does default encoding affect str-->bytes or PySqlite3 always use UTF-8 # ??? what is the correct isolation mode + # !!! Issue "PRAGMA synchronous=OFF" for much improved responsiveness ''' From python-checkins at python.org Sun Mar 8 04:52:42 2009 From: python-checkins at python.org (nick.coghlan) Date: Sun, 8 Mar 2009 04:52:42 +0100 (CET) Subject: [Python-checkins] r70237 - peps/trunk/pep-0377.txt Message-ID: <20090308035242.13A3D1E4002@bag.python.org> Author: nick.coghlan Date: Sun Mar 8 04:52:41 2009 New Revision: 70237 Log: New PEP to cover problems with being to implement contextlib.nested() properly Added: peps/trunk/pep-0377.txt (contents, props changed) Added: peps/trunk/pep-0377.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-0377.txt Sun Mar 8 04:52:41 2009 @@ -0,0 +1,199 @@ +PEP: 377 +Title: Allow __enter__() methods to skip the statement body +Version: $Revision$ +Last-Modified: $Date$ +Author: Nick Coghlan +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 8-Mar-2009 +Python-Version: 2.7, 3.1 +Post-History: 8-Mar-2009 + + +Abstract +======== + +This PEP proposes a backwards compatible mechanism that allows ``__enter__()`` +methods to skip the body of the associated ``with`` statment. The lack of +this ability currently means the ``contextlib.nested`` context manager +is unable to fulfil its specification of being equivalent to writing out +multiple nested ``with`` statements [1]. + +The proposed change is to introduce a new flow control exception +``SkipStatement``, and skip the execution of the ``with`` +statement body if ``__enter__()`` raises this exception. + + +Proposed Change +=============== + +The semantics of the ``with`` statement will be changed to include a +new ``try``/``except``/``else`` block around the call to ``__enter__()``. +If ``SkipStatement`` is raised by the ``__enter__()`` method, then +the main section of the ``with`` statement (now located in the ``else`` +clause) will not be executed. To avoid leaving the names in any ``as`` +clause unbound in this case, a new ``StatementSkipped`` singleton +(similar to the existing ``NotImplemented`` singleton) will be +assigned to all names that appear in the ``as`` clause. + +The components of the ``with`` statement remain as described in PEP 343 [2]:: + + with EXPR as VAR: + BLOCK + +After the modification, the ``with`` statement semantics would +be as follows:: + + mgr = (EXPR) + exit = mgr.__exit__ # Not calling it yet + try: + value = mgr.__enter__() + except SkipStatement: + VAR = StatementSkipped + # Only if "as VAR" is present and + # VAR is a single name + # If VAR is a tuple of names, then StatementSkipped + # will be assigned to each name in the tuple + else: + exc = True + try: + try: + VAR = value # Only if "as VAR" is present + BLOCK + except: + # The exceptional case is handled here + exc = False + if not exit(*sys.exc_info()): + raise + # The exception is swallowed if exit() returns true + finally: + # The normal and non-local-goto cases are handled here + if exc: + exit(None, None, None) + +With the above change in place for the ``with`` statement semantics, +``contextlib.contextmanager()`` will then be modified to raise +``SkipStatement`` instead of ``RuntimeError`` when the underlying +generator doesn't yield. + +Rationale for Change +==================== + +Currently, some apparently innocuous context managers may raise +``RuntimeError`` when executed. This occurs when the context +manager's ``__enter__()`` method encounters a situation where +the written out version of the code corresponding to the +context manager would skip the code that is now the body +of the ``with`` statement. Since the ``__enter__()`` method +has no mechanism available to signal this to the interpreter, +it is instead forced to raise an exception that not only +skips the body of the ``with`` statement, but also jumps over +all code until the nearest exception handler. This goes against +one of the design goals of the ``with`` statement, which was to +be able to factor out arbitrary common exception handling code +into a single context manager by putting into a generator +function and replacing the variant part of the code with a +``yield`` statement. + +Specifically, the following examples behave differently if +``cmB().__enter__()`` raises an exception which ``cmA().__exit__()`` +then handles and suppresses:: + + with cmA(): + with cmB(): + do_stuff() + # This will resume here without executing "do_stuff()" + + @contextlib.contextmanager + def combined(): + with cmA(): + with cmB(): + yield + + with combined(): + do_stuff() + # This will raise a RuntimeError complaining that the context + # manager's underlying generator didn't yield + + with contextlib.nested(cmA(), cmB()): + do_stuff() + # This will raise the same RuntimeError as the contextmanager() + # example (unsurprising, given that the nested() implementation + # uses contextmanager()) + + # The following class based version shows that the issue isn't + # specific to contextlib.contextmanager() (it also shows how + # much simpler it is to write context managers as generators + # instead of as classes!) + class CM(object): + def __init__(self): + self.cmA = None + self.cmB = None + + def __enter__(self): + if self.cmA is not None: + raise RuntimeError("Can't re-use this CM") + self.cmA = cmA() + self.cmA.__enter__() + try: + self.cmB = cmB() + self.cmB.__enter__() + except: + self.cmA.__exit__(*sys.exc_info()) + # Can't suppress in __enter__(), so must raise + raise + + def __exit__(self, *args): + suppress = False + try: + if self.cmB is not None: + suppress = self.cmB.__exit__(*args) + except: + suppress = self.cmA.__exit__(*sys.exc_info()): + if not suppress: + # Exception has changed, so reraise explicitly + raise + else: + if suppress: + # cmB already suppressed the exception, + # so don't pass it to cmA + suppress = self.cmA.__exit__(None, None, None): + else: + suppress = self.cmA.__exit__(*args): + return suppress + + +Reference Implementation +======================== + +In work. + + +Acknowledgements +================ + +James William Pye both raised the issue and suggested the solution +described in this PEP. + +References +========== + +.. [1] Issue 5251: contextlib.nested inconsistent with nested with statements + (http://bugs.python.org/issue5251) + +.. [2] PEP 343: The "with" Statement + (http://www.python.org/dev/peps/pep-0343/) + +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 + End: From python-checkins at python.org Sun Mar 8 05:14:02 2009 From: python-checkins at python.org (nick.coghlan) Date: Sun, 8 Mar 2009 05:14:02 +0100 (CET) Subject: [Python-checkins] r70238 - peps/trunk/pep-0377.txt Message-ID: <20090308041402.2009A1E4002@bag.python.org> Author: nick.coghlan Date: Sun Mar 8 05:14:01 2009 New Revision: 70238 Log: Minor formatting fix Modified: peps/trunk/pep-0377.txt Modified: peps/trunk/pep-0377.txt ============================================================================== --- peps/trunk/pep-0377.txt (original) +++ peps/trunk/pep-0377.txt Sun Mar 8 05:14:01 2009 @@ -77,6 +77,7 @@ ``SkipStatement`` instead of ``RuntimeError`` when the underlying generator doesn't yield. + Rationale for Change ==================== From python-checkins at python.org Sun Mar 8 10:09:11 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 8 Mar 2009 10:09:11 +0100 (CET) Subject: [Python-checkins] r70239 - in tracker/instances/python-dev: html/issue.item.html schema.py Message-ID: <20090308090911.A8A3D1E4002@bag.python.org> Author: martin.v.loewis Date: Sun Mar 8 10:09:11 2009 New Revision: 70239 Log: Issue #130: Allow creator to close his own issues. Also fix permission check on assignee menu. Modified: tracker/instances/python-dev/html/issue.item.html tracker/instances/python-dev/schema.py Modified: tracker/instances/python-dev/html/issue.item.html ============================================================================== --- tracker/instances/python-dev/html/issue.item.html (original) +++ tracker/instances/python-dev/html/issue.item.html Sun Mar 8 10:09:11 2009 @@ -117,7 +117,7 @@ Assigned To: - + + Author: martin.v.loewis Date: Sun Mar 8 14:11:09 2009 New Revision: 70243 Log: Issue #238: Update initial_data. Modified: tracker/instances/python-dev/initial_data.py Modified: tracker/instances/python-dev/initial_data.py ============================================================================== --- tracker/instances/python-dev/initial_data.py (original) +++ tracker/instances/python-dev/initial_data.py Sun Mar 8 14:11:09 2009 @@ -3,6 +3,20 @@ # # TRACKER INITIAL PRIORITY AND STATUS VALUES # +stage = db.getclass('stage') +stage.create(name='test needed', order='2', + description='A test which exercises the issue and can be used as' + ' a unit test is needed') +stage.create(name='needs patch', order='3', + description='A patch is needed to fix the issue') +stage.create(name='patch review', order='4', + description='A patch is available and is awaiting a review by a' + ' trusted developer') +stage.create(name='commit review', order='5', + description='A patch is available and is awaiting a review by a' + ' core developer') +stage.create(name='committed/rejected', order='6', + description='The issue has been resolved') issue_type = db.getclass('issue_type') issue_type.create(name='crash', order='1') @@ -10,38 +24,38 @@ issue_type.create(name='resource usage', order='3') issue_type.create(name='security', order='4') issue_type.create(name='behavior', order='5') -issue_type.create(name='rfe', order='6') +issue_type.create(name='performance', order='6') +issue_type.create(name='feature request', order='7') component = db.getclass('component') -component.create(name="Build", order="1") -component.create(name="Demos and Tools", order="2") -component.create(name="Distutils", order="3") -component.create(name="Documentation", order="4") -component.create(name="Extension Modules", order="5") -component.create(name="IDLE", order="6") -component.create(name="Installation", order="7") -component.create(name="Interpreter Core", order="8") -component.create(name="Library (Lib)", order="9") -component.create(name="Macintosh", order="10") -component.create(name="Regular Expressions", order="11") -component.create(name="Tests", order="12") -component.create(name="Tkinter", order="13") -component.create(name="Unicode", order="14") -component.create(name="Windows", order="15") -component.create(name="XML", order="16") +component.create(name="None", order="1") +component.create(name="2to3 (2.x to 3.0 conversion tool)", order="2") +component.create(name="Build", order="3") +component.create(name="ctypes", order="4") +component.create(name="Demos and Tools", order="5") +component.create(name="Distutils", order="6") +component.create(name="Documentation", order="7") +component.create(name="Extension Modules", order="8") +component.create(name="IDLE", order="9") +component.create(name="Installation", order="10") +component.create(name="Interpreter Core", order="11") +component.create(name="Library (Lib)", order="12") +component.create(name="Macintosh", order="13") +component.create(name="Regular Expressions", order="14") +component.create(name="Tests", order="15") +component.create(name="Tkinter", order="16") +component.create(name="Unicode", order="17") +component.create(name="Windows", order="18") +component.create(name="XML", order="19") version = db.getclass('version') -version.create(name='Python 2.6', order='1') -version.create(name='Python 2.5', order='2') -version.create(name='Python 2.4', order='3') -version.create(name='Python 2.3', order='4') -version.create(name='Python 2.2.3', order='5') -version.create(name='Python 2.2.2', order='6') -version.create(name='Python 2.2.1', order='7') -version.create(name='Python 2.2', order='8') -version.create(name='Python 2.1.2', order='9') -version.create(name='Python 2.1.1', order='10') -version.create(name='3rd party', order='11') +version.create(name='Python 3.1', order='1') +version.create(name='Python 3.0', order='2') +version.create(name='Python 2.7', order='3') +version.create(name='Python 2.6', order='4') +version.create(name='Python 2.5', order='5') +version.create(name='Python 2.4', order='6') +version.create(name='3rd party', order='7') severity = db.getclass('severity') @@ -52,16 +66,22 @@ severity.create(name='minor', order='5') priority = db.getclass('priority') -priority.create(name='immediate', order='1') -priority.create(name='urgent', order='2') -priority.create(name='high', order='3') -priority.create(name='normal', order='4') -priority.create(name='low', order='5') +priority.create(name='release blocker', order='1', + description='Blocks a release') +priority.create(name='deferred blocker', order='2', + description='Blocks a future release') +priority.create(name='critical', order='3', + description='Might block a future release') +priority.create(name='high', order='4', + description='Important but will not block') +priority.create(name='normal', order='5') +priority.create(name='low', order='6', + description='E.g. spelling errors in documentation') status = db.getclass('status') status.create(name='open', order='1') status.create(name='closed', order='2') -status.create(name='pending', description='user feedback required', order='3') +status.create(name='pending', order='3', description='user feedback required') resolution = db.getclass('resolution') resolution.create(name='accepted', order='1') @@ -77,8 +97,18 @@ resolution.create(name='works for me', order='11') keyword = db.getclass("keyword") -keyword.create(name="py3k", description="Python 3000 bugs") -keyword.create(name="patch", description="Contains patch") +keyword.create(name="26backport", + description="Backport 3.0 feature from 2.6") +keyword.create(name="64bit", + description="Affects 64-bit platforms only") +keyword.create(name="easy", + description="This is an easy task (e.g. suitable for GHOP or " + "bug day beginners)") +keyword.create(name="needs review", + description="This issue has a patch which needs the review of" + " a developer.") +keyword.create(name="patch", + description="Contains patch") # # create the two default users From python-checkins at python.org Sun Mar 8 15:06:19 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 8 Mar 2009 15:06:19 +0100 (CET) Subject: [Python-checkins] r70244 - python/trunk/Misc/developers.txt Message-ID: <20090308140619.B58B21E4002@bag.python.org> Author: martin.v.loewis Date: Sun Mar 8 15:06:19 2009 New Revision: 70244 Log: Add Chris Withers. Modified: python/trunk/Misc/developers.txt Modified: python/trunk/Misc/developers.txt ============================================================================== --- python/trunk/Misc/developers.txt (original) +++ python/trunk/Misc/developers.txt Sun Mar 8 15:06:19 2009 @@ -17,7 +17,10 @@ Permissions History ------------------- -- Tarek Ziad? as given SVN access on Decmeber 21 2008 by NCN, +- Chris Withers was given SVN access on March 8 2009 by MvL, + after recommendation by GvR. + +- Tarek Ziad? was given SVN access on December 21 2008 by NCN, for maintenance of distutils. - Hirokazu Yamamoto was given SVN access on August 12 2008 by MvL, From python-checkins at python.org Sun Mar 8 21:49:47 2009 From: python-checkins at python.org (brett.cannon) Date: Sun, 8 Mar 2009 21:49:47 +0100 (CET) Subject: [Python-checkins] r70245 - python/branches/py3k/Python/import.c Message-ID: <20090308204947.7AEE71E4002@bag.python.org> Author: brett.cannon Date: Sun Mar 8 21:49:47 2009 New Revision: 70245 Log: Fix a typo in a comment. Modified: python/branches/py3k/Python/import.c Modified: python/branches/py3k/Python/import.c ============================================================================== --- python/branches/py3k/Python/import.c (original) +++ python/branches/py3k/Python/import.c Sun Mar 8 21:49:47 2009 @@ -1952,7 +1952,7 @@ } /* Initialize a frozen module. - Return 1 for succes, 0 if the module is not found, and -1 with + Return 1 for success, 0 if the module is not found, and -1 with an exception set if the initialization failed. This function is also used from frozenmain.c */ From python-checkins at python.org Sun Mar 8 21:50:32 2009 From: python-checkins at python.org (brett.cannon) Date: Sun, 8 Mar 2009 21:50:32 +0100 (CET) Subject: [Python-checkins] r70246 - python/branches/py3k/Lib/importlib/test/extension/test_case_sensitivity.py Message-ID: <20090308205032.3F6871E4002@bag.python.org> Author: brett.cannon Date: Sun Mar 8 21:50:32 2009 New Revision: 70246 Log: Skip case-sensitivity tests for extension modules if _testcapi cannot be found. Modified: python/branches/py3k/Lib/importlib/test/extension/test_case_sensitivity.py Modified: python/branches/py3k/Lib/importlib/test/extension/test_case_sensitivity.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/extension/test_case_sensitivity.py (original) +++ python/branches/py3k/Lib/importlib/test/extension/test_case_sensitivity.py Sun Mar 8 21:50:32 2009 @@ -32,6 +32,8 @@ def test_main(): + if ext_util.FILENAME is None: + return support.run_unittest(ExtensionModuleCaseSensitivityTest) From python-checkins at python.org Sun Mar 8 21:53:50 2009 From: python-checkins at python.org (brett.cannon) Date: Sun, 8 Mar 2009 21:53:50 +0100 (CET) Subject: [Python-checkins] r70247 - python/branches/py3k/Lib/importlib/_bootstrap.py Message-ID: <20090308205350.D24091E4002@bag.python.org> Author: brett.cannon Date: Sun Mar 8 21:53:50 2009 New Revision: 70247 Log: Minor changes to Python source base loader. Fixed a bug where 'self' was left off a method call. Was masked by the fact the source/bytecode loader subclass is always used. Cleaned up when the source path is fetched. Also made sure ImportError is raised when a source path cannot be found. Modified: python/branches/py3k/Lib/importlib/_bootstrap.py Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Sun Mar 8 21:53:50 2009 @@ -327,26 +327,30 @@ @module_for_loader def load_module(self, module): """Load a source module.""" - return _load_module(module) + return self._load_module(module) def _load_module(self, module): """Initialize a module from source.""" name = module.__name__ - source_path = self.source_path(name) code_object = self.get_code(module.__name__) + # __file__ may have been set by the caller, e.g. bytecode path. if not hasattr(module, '__file__'): - module.__file__ = source_path + module.__file__ = self.source_path(name) if self.is_package(name): module.__path__ = [module.__file__.rsplit(path_sep, 1)[0]] module.__package__ = module.__name__ if not hasattr(module, '__path__'): module.__package__ = module.__package__.rpartition('.')[0] + module.__loader__ = self exec(code_object, module.__dict__) return module def get_code(self, fullname): """Get a code object from source.""" source_path = self.source_path(fullname) + if source_path is None: + message = "a source path must exist to load {0}".format(fullname) + raise ImportError(message) source = self.get_data(source_path) # Convert to universal newlines. line_endings = b'\n' From buildbot at python.org Sun Mar 8 22:18:25 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 08 Mar 2009 21:18:25 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090308211826.4326B1E4021@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/391 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sun Mar 8 22:38:12 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 08 Mar 2009 21:38:12 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090308213812.6E64D1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/488 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Sun Mar 8 22:39:55 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 08 Mar 2009 21:39:55 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090308213956.53E4A1E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/399 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From buildbot at python.org Sun Mar 8 22:41:40 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 08 Mar 2009 21:41:40 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090308214140.67B5E1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/453 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Sun Mar 8 22:51:00 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 08 Mar 2009 21:51:00 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090308215101.722741E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/428 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Sun Mar 8 22:57:41 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 08 Mar 2009 21:57:41 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090308215742.1A41E1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/384 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Mon Mar 9 00:51:13 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 9 Mar 2009 00:51:13 +0100 (CET) Subject: [Python-checkins] r70248 - python/branches/py3k/Doc/c-api/unicode.rst Message-ID: <20090308235113.719DF1E401E@bag.python.org> Author: benjamin.peterson Date: Mon Mar 9 00:51:13 2009 New Revision: 70248 Log: PyObject_Unicode -> PyObject_Str Modified: python/branches/py3k/Doc/c-api/unicode.rst Modified: python/branches/py3k/Doc/c-api/unicode.rst ============================================================================== --- python/branches/py3k/Doc/c-api/unicode.rst (original) +++ python/branches/py3k/Doc/c-api/unicode.rst Mon Mar 9 00:51:13 2009 @@ -291,7 +291,7 @@ | | | *NULL*). | +-------------------+---------------------+--------------------------------+ | :attr:`%S` | PyObject\* | The result of calling | - | | | :func:`PyObject_Unicode`. | + | | | :func:`PyObject_Str`. | +-------------------+---------------------+--------------------------------+ | :attr:`%R` | PyObject\* | The result of calling | | | | :func:`PyObject_Repr`. | From python-checkins at python.org Mon Mar 9 01:02:02 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 9 Mar 2009 01:02:02 +0100 (CET) Subject: [Python-checkins] r70249 - python/branches/py3k/Lib/importlib/test/source/util.py Message-ID: <20090309000202.1E8E31E4002@bag.python.org> Author: brett.cannon Date: Mon Mar 9 01:02:01 2009 New Revision: 70249 Log: Make importlib.test.source.util.write_bytecode reset sys.dont_write_bytecode. Modified: python/branches/py3k/Lib/importlib/test/source/util.py Modified: python/branches/py3k/Lib/importlib/test/source/util.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/source/util.py (original) +++ python/branches/py3k/Lib/importlib/test/source/util.py Mon Mar 9 01:02:01 2009 @@ -14,7 +14,11 @@ if sys.dont_write_bytecode: return lambda *args, **kwargs: None else: - return fxn + def wrapper(*args, **kwargs): + to_return = fxn(*args, **kwargs) + sys.dont_write_bytecode = False + return to_return + return wrapper def bytecode_path(source_path): From python-checkins at python.org Mon Mar 9 01:02:56 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Mon, 9 Mar 2009 01:02:56 +0100 (CET) Subject: [Python-checkins] r70250 - sandbox/trunk/mmap Message-ID: <20090309000256.4729F1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Mon Mar 9 01:02:56 2009 New Revision: 70250 Log: Out of dated Removed: sandbox/trunk/mmap/ From python-checkins at python.org Mon Mar 9 01:07:03 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 9 Mar 2009 01:07:03 +0100 (CET) Subject: [Python-checkins] r70251 - in python/branches/py3k: Lib/_pyio.py Lib/test/test_io.py Modules/_textio.c Message-ID: <20090309000703.EED631E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 9 01:07:03 2009 New Revision: 70251 Log: give TextIOWrapper a repr that tells you the encoding Modified: python/branches/py3k/Lib/_pyio.py python/branches/py3k/Lib/test/test_io.py python/branches/py3k/Modules/_textio.c Modified: python/branches/py3k/Lib/_pyio.py ============================================================================== --- python/branches/py3k/Lib/_pyio.py (original) +++ python/branches/py3k/Lib/_pyio.py Mon Mar 9 01:07:03 2009 @@ -1399,6 +1399,9 @@ # - "bytes_..." for integer variables that count input bytes # - "chars_..." for integer variables that count decoded characters + def __repr__(self): + return "".format(self.encoding) + @property def encoding(self): return self._encoding Modified: python/branches/py3k/Lib/test/test_io.py ============================================================================== --- python/branches/py3k/Lib/test/test_io.py (original) +++ python/branches/py3k/Lib/test/test_io.py Mon Mar 9 01:07:03 2009 @@ -1354,6 +1354,12 @@ self.assertRaises(TypeError, t.__init__, b, newline=42) self.assertRaises(ValueError, t.__init__, b, newline='xyzzy') + def test_repr(self): + raw = self.BytesIO("hello".encode("utf-8")) + b = self.BufferedReader(raw) + t = self.TextIOWrapper(b, encoding="utf-8") + self.assertEqual(repr(t), "") + def test_line_buffering(self): r = self.BytesIO() b = self.BufferedWriter(r, 1000) Modified: python/branches/py3k/Modules/_textio.c ============================================================================== --- python/branches/py3k/Modules/_textio.c (original) +++ python/branches/py3k/Modules/_textio.c Mon Mar 9 01:07:03 2009 @@ -2171,6 +2171,14 @@ return PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_truncate, NULL); } +static PyObject * +TextIOWrapper_repr(PyTextIOWrapperObject *self) +{ + CHECK_INITIALIZED(self); + return PyUnicode_FromFormat("", self->encoding); +} + + /* Inquiries */ static PyObject * @@ -2372,9 +2380,9 @@ (destructor)TextIOWrapper_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ - 0, /*tp_setattr*/ + 0, /*tps_etattr*/ 0, /*tp_compare */ - 0, /*tp_repr*/ + (reprfunc)TextIOWrapper_repr,/*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ From python-checkins at python.org Mon Mar 9 01:09:44 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 9 Mar 2009 01:09:44 +0100 (CET) Subject: [Python-checkins] r70252 - python/branches/py3k/Lib/_pyio.py Message-ID: <20090309000944.8396A1E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 9 01:09:44 2009 New Revision: 70252 Log: hack StringIO's repr, so it doesn't give an encoding Modified: python/branches/py3k/Lib/_pyio.py Modified: python/branches/py3k/Lib/_pyio.py ============================================================================== --- python/branches/py3k/Lib/_pyio.py (original) +++ python/branches/py3k/Lib/_pyio.py Mon Mar 9 01:09:44 2009 @@ -1829,3 +1829,8 @@ def getvalue(self): self.flush() return self.buffer.getvalue().decode(self._encoding, self._errors) + + def __repr__(self): + # TextIOWrapper tells the encoding in its repr. In StringIO, + # that's a implementation detail. + return object.__repr__(self) From python-checkins at python.org Mon Mar 9 01:14:37 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 9 Mar 2009 01:14:37 +0100 (CET) Subject: [Python-checkins] r70253 - python/branches/py3k/Lib/importlib/_bootstrap.py Message-ID: <20090309001437.89C2F1E4002@bag.python.org> Author: brett.cannon Date: Mon Mar 9 01:14:37 2009 New Revision: 70253 Log: Fix importlib._bootstrap.PyPycLoader.load_module() to better handle source/bytecode paths and what to do when they don't exist. Modified: python/branches/py3k/Lib/importlib/_bootstrap.py Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Mon Mar 9 01:14:37 2009 @@ -383,9 +383,16 @@ def load_module(self, module): """Load a module from source or bytecode.""" name = module.__name__ - source_path = self.source_path(name) - bytecode_path = self.bytecode_path(name) - module.__file__ = source_path if source_path else bytecode_path + try: + source_path = self.source_path(name) + except ImportError: + source_path = None + try: + bytecode_path = self.bytecode_path(name) + except ImportError: + bytecode_path = None + # get_code can worry about no viable paths existing. + module.__file__ = source_path or bytecode_path return self._load_module(module) def get_code(self, fullname): From buildbot at python.org Mon Mar 9 01:31:12 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 09 Mar 2009 00:31:12 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090309003112.8709A1E4023@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/490 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_pipes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Mon Mar 9 02:19:18 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 09 Mar 2009 01:19:18 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090309011919.4032E1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/455 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Mon Mar 9 02:27:05 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 09 Mar 2009 01:27:05 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090309012706.2D5321E402C@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/401 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From python-checkins at python.org Mon Mar 9 02:58:14 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 9 Mar 2009 02:58:14 +0100 (CET) Subject: [Python-checkins] r70254 - python/branches/py3k/Lib/importlib/test/import_/test_relative_imports.py Message-ID: <20090309015814.2F1B81E4002@bag.python.org> Author: brett.cannon Date: Mon Mar 9 02:58:13 2009 New Revision: 70254 Log: Remove a dead XXX comment. Modified: python/branches/py3k/Lib/importlib/test/import_/test_relative_imports.py Modified: python/branches/py3k/Lib/importlib/test/import_/test_relative_imports.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/import_/test_relative_imports.py (original) +++ python/branches/py3k/Lib/importlib/test/import_/test_relative_imports.py Mon Mar 9 02:58:13 2009 @@ -176,7 +176,6 @@ # Test importing from a different package than the caller. # in pkg.subpkg1.mod # from ..subpkg2 import mod - # XXX create = ['__runpy_pkg__.__init__', '__runpy_pkg__.__runpy_pkg__.__init__', '__runpy_pkg__.uncle.__init__', From python-checkins at python.org Mon Mar 9 03:02:24 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 9 Mar 2009 03:02:24 +0100 (CET) Subject: [Python-checkins] r70255 - python/branches/py3k/Doc/library/io.rst Message-ID: <20090309020224.6615B1E400C@bag.python.org> Author: benjamin.peterson Date: Mon Mar 9 03:02:23 2009 New Revision: 70255 Log: fix StringIO constructor docs #5452 Modified: python/branches/py3k/Doc/library/io.rst Modified: python/branches/py3k/Doc/library/io.rst ============================================================================== --- python/branches/py3k/Doc/library/io.rst (original) +++ python/branches/py3k/Doc/library/io.rst Mon Mar 9 03:02:23 2009 @@ -637,13 +637,13 @@ Whether line buffering is enabled. -.. class:: StringIO([initial_value[, encoding[, errors[, newline]]]]) +.. class:: StringIO([initial_value[, newline]]) An in-memory stream for text. It inherits :class:`TextIOWrapper`. - Create a new StringIO stream with an initial value, encoding, error handling, - and newline setting. See :class:`TextIOWrapper`\'s constructor for more - information. + The initial value of the buffer (an empty string by default) can be set by + providing *initial_value*. The *newline* argument works like that of + :class:`TextIOWrapper`. The default is to do no newline translation. :class:`StringIO` provides this method in addition to those from :class:`TextIOWrapper` and its parents: From python-checkins at python.org Mon Mar 9 04:35:51 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 9 Mar 2009 04:35:51 +0100 (CET) Subject: [Python-checkins] r70256 - in python/branches/py3k: Doc/library/importlib.rst Lib/importlib/NOTES Lib/importlib/_bootstrap.py Lib/importlib/abc.py Lib/importlib/test/abc.py Lib/importlib/test/source/test_abc_loader.py Lib/importlib/test/source/test_file_loader.py Lib/importlib/test/source/test_loader.py Lib/importlib/test/source/util.py Lib/importlib/test/test_abc.py Message-ID: <20090309033551.2A7601E400C@bag.python.org> Author: brett.cannon Date: Mon Mar 9 04:35:50 2009 New Revision: 70256 Log: Introduce importlib.abc. The module contains various ABCs related to imports (mostly stuff specified by PEP 302). There are two ABCs, PyLoader and PyPycLoader, which help with implementing source and source/bytecode loaders by implementing load_module in terms of other methods. This removes a lot of gritty details loaders typically have to worry about. Added: python/branches/py3k/Lib/importlib/abc.py python/branches/py3k/Lib/importlib/test/source/test_abc_loader.py python/branches/py3k/Lib/importlib/test/source/test_file_loader.py - copied, changed from r70247, /python/branches/py3k/Lib/importlib/test/source/test_loader.py python/branches/py3k/Lib/importlib/test/test_abc.py Removed: python/branches/py3k/Lib/importlib/test/source/test_loader.py Modified: python/branches/py3k/Doc/library/importlib.rst python/branches/py3k/Lib/importlib/NOTES python/branches/py3k/Lib/importlib/_bootstrap.py python/branches/py3k/Lib/importlib/test/abc.py python/branches/py3k/Lib/importlib/test/source/util.py Modified: python/branches/py3k/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k/Doc/library/importlib.rst (original) +++ python/branches/py3k/Doc/library/importlib.rst Mon Mar 9 04:35:50 2009 @@ -82,6 +82,175 @@ occuring from to already be imported (i.e., *package* must already be imported). +:mod:`importlib.abc` -- Abstract base classes related to import +--------------------------------------------------------------- + +.. module:: importlib.abc + :synopsis: Abstract base classes related to import + +The :mod:`importlib.abc` module contains all of the core abstract base classes +used by :keyword:`import`. Some subclasses of the core abstract base classes +are also provided to help in implementing the core ABCs. + + +.. class:: Finder + + An abstract base class representing a :term:`finder`. + + ..method:: find_module(fullname, path=None) + + An abstract method for finding a :term:`loader` for the specified + module. If the :term:`finder` is found on :data:`sys.meta_path` and the + module to be searched for is a subpackage or module then *path* is set + to the value of :attr:`__path__` from the parent package. If a loader + cannot be found, :keyword:`None` is returned. + + The exact definition of a :term:`finder` can be found in :pep:`302`. + + +.. class:: Loader + + An abstract base class for a :term:`loader`. + + ..method:: load_module(fullname) + + An abstract method for loading a module. If the module cannot be + loaded, :exc:`ImportError` is raised, otherwise the loaded module is + returned. + + If the requested module is already exists in :data:`sys.modules`, that + module should be used and reloaded. + Otherwise a new module is to be created by the loader and inserted into + :data:`sys.modules`before any loading begins to prevent recursion from + the import. If the loader inserted into a module and the load fails it + must be removed by the loader from :data:`sys.modules`; modules already + in :data:`sys.modules` before the loader began execution should be left + alone. The :func:`importlib.util.module_for_loader` decorator handles + all of these details. + + The loader is expected to set several attributes on the module when + adding a new module to :data:`sys.modules`. + + - :attr:`__name__` + The name of the module. + + - :attr:`__file__` + The path to where the module data is stored (not set for built-in + modules). + + - :attr:`__path__` + Set to a list of strings specifying the search path within a + package. This attribute is not set on modules. + + - :attr:`__package__` + The parent package for the module/package. If the module is + top-level then it has a value of the empty string. The + :func:`importlib.util.set_package` decorator can handle the details + for :attr:`__package__`. + + - :attr:`__loader__` + Set to the loader used to load the module. + + See :pep:`302` for the exact definition for a loader. + + +.. class:: ResourceLoader + + An abstract base class for a :term:`loader` which implements the optional + :pep:`302` protocol for loading arbitrary resources from the storage + back-end. + + ..method:: get_data(path) + + An abstract method to return the bytes for the data located at *path*. + Loaders that have a file-like storage back-end can implement this + abstract method to give direct access + to the data stored. :exc:`IOError` is to be raised if the *path* cannot + be found. The *path* is expected to be constructed using a module's + :attr:`__path__` attribute or an item from :attr:`__path__`. + + +.. class:: InspectLoader + + An abstract base class for a :term:`loader` which implements the optional + :pep:`302` protocol for loaders which inspect modules. + + ..method:: is_package(fullname) + + An abstract method to return a true value if the module is a package, a + false value otherwise. :exc:`ImportError` is raised if the + :term:`loader` cannot find the module. + + ..method:: get_source(fullname) + + An abstract method to return the source of a module. It is returned as + a string with universal newline support. Returns :keyword:`None` if no + source is available (e.g. a built-in module). Raises :exc:`ImportError` + if the loader cannot find the module specified. + + ..method:: get_code(fullname) + + An abstract method to return the :class:`code` object for a module. + :keyword:`None` is returned if the module does not have a code object + (e.g. built-in module). :exc:`ImportError` is raised if loader cannot + find the requested module. + + +.. class:: PyLoader + + An abstract base class inheriting from :class:`importlib.abc.InspectLoader` + and :class:`importlib.abc.ResourceLoader` designed to ease the loading of + Python source modules (bytecode is not handled; see + :class:`importlib.abc.PyPycLoader` for a source/bytecode ABC). A subclass + implementing this ABC will only need to worry about exposing how the source + code is stored; all other details for loading Python source code will be + handled by the concrete implementations of key methods. + + ..method:: source_path(fullname) + + An abstract method that returns the path to the source code for a + module. Should return :keyword:`None` if there is no source code. + :exc:`ImportError` if the module cannot be found. + + ..method:: load_module(fullname) + + A concrete implementation of :meth:`importlib.abc.Loader.load_module` + that loads Python source code. + + ..method:: get_code(fullname) + + A concrete implementation of + :meth:`importlib.abc.InspectLoader.get_code` that creates code objects + from Python source code. + + +.. class:: PyPycLoader + + An abstract base class inheriting from :class:`importlib.abc.PyLoader`. + This ABC is meant to help in creating loaders that support both Python + source and bytecode. + + ..method:: source_mtime(fullname) + + An abstract method which returns the modification time for the source + code of the specified module. The modification time should be an + integer. If there is no source code, return :keyword:`None. If the + module cannot be found then :exc:`ImportError` is raised. + + ..method:: bytecode_path(fullname) + + An abstract method which returns the path to the bytecode for the + specified module. :keyword:`None` is returned if there is no bytecode. + :exc:`ImportError` is raised if the module is not found. + + ..method:: write_bytecode(fullname, bytecode) + + An abstract method which has the loader write *bytecode* for future + use. If the bytecode is written, return :keyword:`True`. Return + :keyword:`False` if the bytecode could not be written. This method + should not be called if :data:`sys.dont_write_bytecode` is true. + + :mod:`importlib.machinery` -- Importers and path hooks ------------------------------------------------------ @@ -93,44 +262,27 @@ .. class:: BuiltinImporter - :term:`Importer` for built-in modules. All known built-in modules are - listed in :data:`sys.builtin_module_names`. + An :term:`importer` for built-in modules. All known built-in modules are + listed in :data:`sys.builtin_module_names`. This class implements the + :class:`importlib.abc.Finder` and :class:`importlib.abc.Loader` ABCs. Only class methods are defined by this class to alleviate the need for instantiation. - .. classmethod:: find_module(fullname, path=None) - - Class method that allows this class to be a :term:`finder` for built-in - modules. - - .. classmethod:: load_module(fullname) - - Class method that allows this class to be a :term:`loader` for built-in - modules. - .. class:: FrozenImporter - :term:`Importer` for frozen modules. + An :term:`importer` for frozen modules. This class implements the + :class:`importlib.abc.Finder` and :class:`importlib.abc.Loader` ABCs. Only class methods are defined by this class to alleviate the need for instantiation. - .. classmethod:: find_module(fullname, path=None) - - Class method that allows this class to be a :term:`finder` for frozen - modules. - - .. classmethod:: load_module(fullname) - - Class method that allows this class to be a :term:`loader` for frozen - modules. - .. class:: PathFinder - :term:`Finder` for :data:`sys.path`. + :term:`Finder` for :data:`sys.path`. This class implements the + :class:`importlib.abc.Finder` ABC. This class does not perfectly mirror the semantics of :keyword:`import` in terms of :data:`sys.path`. No implicit path hooks are assumed for @@ -142,15 +294,15 @@ .. classmethod:: find_module(fullname, path=None) Class method that attempts to find a :term:`loader` for the module - specified by *fullname* either on :data:`sys.path` or, if defined, on + specified by *fullname* on :data:`sys.path` or, if defined, on *path*. For each path entry that is searched, :data:`sys.path_importer_cache` is checked. If an non-false object is - found then it is used as the :term:`finder` to query for the module - being searched for. For no entry is found in + found then it is used as the :term:`finder` to look for the module + being searched for. If no entry is found in :data:`sys.path_importer_cache`, then :data:`sys.path_hooks` is searched for a finder for the path entry and, if found, is stored in :data:`sys.path_importer_cache` along with being queried about the - module. + module. If no finder is ever found then :keyword:`None` is returned. :mod:`importlib.util` -- Utility code for importers @@ -166,10 +318,11 @@ A :term:`decorator` for a :term:`loader` which handles selecting the proper module object to load with. The decorated method is expected to have a call - signature of ``method(self, module_object)`` for which the second argument - will be the module object to be used by the loader (note that the decorator + signature taking two positional arguments + (e.g. ``load_module(self, module)``) for which the second argument + will be the module object to be used by the loader. Note that the decorator will not work on static methods because of the assumption of two - arguments). + arguments. The decorated method will take in the name of the module to be loaded as expected for a :term:`loader`. If the module is not found in Modified: python/branches/py3k/Lib/importlib/NOTES ============================================================================== --- python/branches/py3k/Lib/importlib/NOTES (original) +++ python/branches/py3k/Lib/importlib/NOTES Mon Mar 9 04:35:50 2009 @@ -3,42 +3,12 @@ * Public API left to expose (w/ docs!) - + abc + + abc.PyLoader.get_source + + util.set_loader - - Finder +* Implement InspectLoader for BuiltinImporter and FrozenImporter. - * find_module - - - Loader - - * load_module - - - ResourceLoader(Loader) - - * get_data - - - InspectLoader(Loader) - - * is_package - * get_code - * get_source - - - PyLoader(ResourceLoader) - - * source_path - - - PyPycLoader(PyLoader) - - * source_mtime - * bytecode_path - * write_bytecode - - + test (Really want to worry about compatibility with future versions?) - - - abc - - * FinderTests [doc] - * LoaderTests [doc] + + Expose function to see if a frozen module is a package. * Remove ``import *`` from importlib.__init__. @@ -68,3 +38,4 @@ + imp + py_compile + compileall + + zipimport Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Mon Mar 9 04:35:50 2009 @@ -383,14 +383,8 @@ def load_module(self, module): """Load a module from source or bytecode.""" name = module.__name__ - try: - source_path = self.source_path(name) - except ImportError: - source_path = None - try: - bytecode_path = self.bytecode_path(name) - except ImportError: - bytecode_path = None + source_path = self.source_path(name) + bytecode_path = self.bytecode_path(name) # get_code can worry about no viable paths existing. module.__file__ = source_path or bytecode_path return self._load_module(module) Added: python/branches/py3k/Lib/importlib/abc.py ============================================================================== --- (empty file) +++ python/branches/py3k/Lib/importlib/abc.py Mon Mar 9 04:35:50 2009 @@ -0,0 +1,110 @@ +"""Abstract base classes related to import.""" +from . import _bootstrap +from . import machinery +import abc +import types + + +class Loader(metaclass=abc.ABCMeta): + + """Abstract base class for import loaders. + + See PEP 302 for details. + + """ + + def load_module(self, fullname:str) -> types.ModuleType: + raise NotImplementedError + +Loader.register(machinery.BuiltinImporter) +Loader.register(machinery.FrozenImporter) + + +class Finder(metaclass=abc.ABCMeta): + + """Abstract base class for import finders. + + See PEP 302 for details. + + """ + + @abc.abstractmethod + def find_module(self, fullname:str, path:[str]=None) -> Loader: + raise NotImplementedError + +Finder.register(machinery.BuiltinImporter) +Finder.register(machinery.FrozenImporter) +Finder.register(machinery.PathFinder) + + +class Importer(Finder, Loader): + + """Abstract base class for importers.""" + + + +class ResourceLoader(Loader): + + """Abstract base class for loaders which can return data from the back-end + storage. + + This ABC represents one of the optional protocols specified by PEP 302. + + """ + + @abc.abstractmethod + def get_data(self, path:str) -> bytes: + raise NotImplementedError + + +class InspectLoader(Loader): + + """Abstract base class for loaders which supports introspection. + + This ABC represents one of the optional protocols specified by PEP 302. + + """ + + @abc.abstractmethod + def is_package(self, fullname:str) -> bool: + return NotImplementedError + + @abc.abstractmethod + def get_code(self, fullname:str) -> types.CodeType: + return NotImplementedError + + @abc.abstractmethod + def get_source(self, fullname:str) -> str: + return NotImplementedError + + +class PyLoader(_bootstrap.PyLoader, InspectLoader): + + """Abstract base class that implements the core parts needed to load Python + source code.""" + + # load_module and get_code are implemented. + + @abc.abstractmethod + def source_path(self, fullname:str) -> object: + raise NotImplementedError + + +class PyPycLoader(_bootstrap.PyPycLoader, PyLoader): + + """Abstract base class that implements the core parts needed to load Python + source and bytecode.""" + + # Implements load_module and get_code. + + @abc.abstractmethod + def source_mtime(self, fullname:str) -> int: + raise NotImplementedError + + @abc.abstractmethod + def bytecode_path(self, fullname:str) -> object: + raise NotImplementedError + + @abc.abstractmethod + def write_bytecode(self, fullname:str, bytecode:bytes): + raise NotImplementedError Modified: python/branches/py3k/Lib/importlib/test/abc.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/abc.py (original) +++ python/branches/py3k/Lib/importlib/test/abc.py Mon Mar 9 04:35:50 2009 @@ -65,10 +65,11 @@ Attributes to verify: - * __file__ - * __loader__ * __name__ + * __file__ + * __package__ * __path__ + * __loader__ """ pass Added: python/branches/py3k/Lib/importlib/test/source/test_abc_loader.py ============================================================================== --- (empty file) +++ python/branches/py3k/Lib/importlib/test/source/test_abc_loader.py Mon Mar 9 04:35:50 2009 @@ -0,0 +1,390 @@ +import importlib +from importlib import abc +from .. import abc as testing_abc +from .. import util +from . import util as source_util +import imp +import marshal +import os +import sys +import types +import unittest + + +class PyLoaderMock(abc.PyLoader): + + # Globals that should be defined for all modules. + source = ("_ = '::'.join([__name__, __file__, __package__, " + "repr(__loader__)])") + + def __init__(self, data): + """Take a dict of 'module_name: path' pairings. + + Paths should have no file extension, allowing packages to be denoted by + ending in '__init__'. + + """ + self.module_paths = data + self.path_to_module = {val:key for key,val in data.items()} + + def get_data(self, path): + if path not in self.path_to_module: + raise IOError + return self.source.encode('utf-8') + + def is_package(self, name): + try: + return '__init__' in self.module_paths[name] + except KeyError: + raise ImportError + + def get_source(self, name): # Should not be needed. + raise NotImplementedError + + def source_path(self, name): + try: + return self.module_paths[name] + except KeyError: + raise ImportError + + +class PyPycLoaderMock(abc.PyPycLoader, PyLoaderMock): + + default_mtime = 1 + + def __init__(self, source, bc={}): + """Initialize mock. + + 'bc' is a dict keyed on a module's name. The value is dict with + possible keys of 'path', 'mtime', 'magic', and 'bc'. Except for 'path', + each of those keys control if any part of created bytecode is to + deviate from default values. + + """ + super().__init__(source) + self.module_bytecode = {} + self.path_to_bytecode = {} + self.bytecode_to_path = {} + for name, data in bc.items(): + self.path_to_bytecode[data['path']] = name + self.bytecode_to_path[name] = data['path'] + magic = data.get('magic', imp.get_magic()) + mtime = importlib._w_long(data.get('mtime', self.default_mtime)) + if 'bc' in data: + bc = data['bc'] + else: + bc = self.compile_bc(name) + self.module_bytecode[name] = magic + mtime + bc + + def compile_bc(self, name): + source_path = self.module_paths.get(name, '') or '' + code = compile(self.source, source_path, 'exec') + return marshal.dumps(code) + + def source_mtime(self, name): + if name in self.module_paths: + return self.default_mtime + elif name in self.module_bytecode: + return None + else: + raise ImportError + + def bytecode_path(self, name): + try: + return self.bytecode_to_path[name] + except KeyError: + if name in self.module_paths: + return None + else: + raise ImportError + + def write_bytecode(self, name, bytecode): + self.module_bytecode[name] = bytecode + return True + + def get_data(self, path): + if path in self.path_to_module: + return super().get_data(path) + elif path in self.path_to_bytecode: + name = self.path_to_bytecode[path] + return self.module_bytecode[name] + else: + raise IOError + + def is_package(self, name): + try: + return super().is_package(name) + except TypeError: + return '__init__' in self.bytecode_to_path[name] + + +class PyLoaderTests(testing_abc.LoaderTests): + + """Tests for importlib.abc.PyLoader.""" + + mocker = PyLoaderMock + + def eq_attrs(self, ob, **kwargs): + for attr, val in kwargs.items(): + self.assertEqual(getattr(ob, attr), val) + + def test_module(self): + name = '' + path = 'path/to/module' + mock = self.mocker({name: path}) + with util.uncache(name): + module = mock.load_module(name) + self.assert_(name in sys.modules) + self.eq_attrs(module, __name__=name, __file__=path, __package__='', + __loader__=mock) + self.assert_(not hasattr(module, '__path__')) + return mock, name + + def test_package(self): + name = '' + path = '/path/to//__init__' + mock = self.mocker({name: path}) + with util.uncache(name): + module = mock.load_module(name) + self.assert_(name in sys.modules) + self.eq_attrs(module, __name__=name, __file__=path, + __path__=[os.path.dirname(path)], __package__=name, + __loader__=mock) + return mock, name + + def test_lacking_parent(self): + name = 'pkg.mod' + path = 'path/to/pkg/mod' + mock = self.mocker({name: path}) + with util.uncache(name): + module = mock.load_module(name) + self.assert_(name in sys.modules) + self.eq_attrs(module, __name__=name, __file__=path, __package__='pkg', + __loader__=mock) + self.assert_(not hasattr(module, '__path__')) + return mock, name + + def test_module_reuse(self): + name = 'mod' + path = 'path/to/mod' + module = imp.new_module(name) + mock = self.mocker({name: path}) + with util.uncache(name): + sys.modules[name] = module + loaded_module = mock.load_module(name) + self.assert_(loaded_module is module) + self.assert_(sys.modules[name] is module) + return mock, name + + def test_state_after_failure(self): + name = "mod" + module = imp.new_module(name) + module.blah = None + mock = self.mocker({name: 'path/to/mod'}) + mock.source = "1/0" + with util.uncache(name): + sys.modules[name] = module + self.assertRaises(ZeroDivisionError, mock.load_module, name) + self.assert_(sys.modules[name] is module) + self.assert_(hasattr(module, 'blah')) + return mock + + def test_unloadable(self): + name = "mod" + mock = self.mocker({name: 'path/to/mod'}) + mock.source = "1/0" + with util.uncache(name): + self.assertRaises(ZeroDivisionError, mock.load_module, name) + self.assert_(name not in sys.modules) + return mock + + +class PyLoaderInterfaceTests(unittest.TestCase): + + + def test_no_source_path(self): + # No source path should lead to ImportError. + name = 'mod' + mock = PyLoaderMock({}) + with util.uncache(name): + self.assertRaises(ImportError, mock.load_module, name) + + def test_source_path_is_None(self): + name = 'mod' + mock = PyLoaderMock({name: None}) + with util.uncache(name): + self.assertRaises(ImportError, mock.load_module, name) + + +class PyPycLoaderTests(PyLoaderTests): + + """Tests for importlib.abc.PyPycLoader.""" + + mocker = PyPycLoaderMock + + @source_util.writes_bytecode + def verify_bytecode(self, mock, name): + assert name in mock.module_paths + self.assert_(name in mock.module_bytecode) + magic = mock.module_bytecode[name][:4] + self.assertEqual(magic, imp.get_magic()) + mtime = importlib._r_long(mock.module_bytecode[name][4:8]) + self.assertEqual(mtime, 1) + bc = mock.module_bytecode[name][8:] + + + def test_module(self): + mock, name = super().test_module() + self.verify_bytecode(mock, name) + + def test_package(self): + mock, name = super().test_package() + self.verify_bytecode(mock, name) + + def test_lacking_parent(self): + mock, name = super().test_lacking_parent() + self.verify_bytecode(mock, name) + + def test_module_reuse(self): + mock, name = super().test_module_reuse() + self.verify_bytecode(mock, name) + + def test_state_after_failure(self): + super().test_state_after_failure() + + def test_unloadable(self): + super().test_unloadable() + + +class SkipWritingBytecodeTests(unittest.TestCase): + + """Test that bytecode is properly handled based on + sys.dont_write_bytecode.""" + + @source_util.writes_bytecode + def run_test(self, dont_write_bytecode): + name = 'mod' + mock = PyPycLoaderMock({name: 'path/to/mod'}) + sys.dont_write_bytecode = dont_write_bytecode + with util.uncache(name): + mock.load_module(name) + self.assert_((name in mock.module_bytecode) is not + dont_write_bytecode) + + def test_no_bytecode_written(self): + self.run_test(True) + + def test_bytecode_written(self): + self.run_test(False) + + +class RegeneratedBytecodeTests(unittest.TestCase): + + """Test that bytecode is regenerated as expected.""" + + @source_util.writes_bytecode + def test_different_magic(self): + # A different magic number should lead to new bytecode. + name = 'mod' + bad_magic = b'\x00\x00\x00\x00' + assert bad_magic != imp.get_magic() + mock = PyPycLoaderMock({name: 'path/to/mod'}, + {name: {'path': 'path/to/mod.bytecode', + 'magic': bad_magic}}) + with util.uncache(name): + mock.load_module(name) + self.assert_(name in mock.module_bytecode) + magic = mock.module_bytecode[name][:4] + self.assertEqual(magic, imp.get_magic()) + + @source_util.writes_bytecode + def test_old_mtime(self): + # Bytecode with an older mtime should be regenerated. + name = 'mod' + old_mtime = PyPycLoaderMock.default_mtime - 1 + mock = PyPycLoaderMock({name: 'path/to/mod'}, + {name: {'path': 'path/to/mod.bytecode', 'mtime': old_mtime}}) + with util.uncache(name): + mock.load_module(name) + self.assert_(name in mock.module_bytecode) + mtime = importlib._r_long(mock.module_bytecode[name][4:8]) + self.assertEqual(mtime, PyPycLoaderMock.default_mtime) + + +class BadBytecodeFailureTests(unittest.TestCase): + + """Test import failures when there is no source and parts of the bytecode + is bad.""" + + def test_bad_magic(self): + # A bad magic number should lead to an ImportError. + name = 'mod' + bad_magic = b'\x00\x00\x00\x00' + mock = PyPycLoaderMock({}, {name: {'path': 'path/to/mod', + 'magic': bad_magic}}) + with util.uncache(name): + self.assertRaises(ImportError, mock.load_module, name) + + def test_bad_bytecode(self): + # Bad code object bytecode should elad to an ImportError. + name = 'mod' + mock = PyPycLoaderMock({}, {name: {'path': '/path/to/mod', 'bc': b''}}) + with util.uncache(name): + self.assertRaises(ImportError, mock.load_module, name) + + +def raise_ImportError(*args, **kwargs): + raise ImportError + +class MissingPathsTests(unittest.TestCase): + + """Test what happens when a source or bytecode path does not exist (either + from *_path returning None or raising ImportError).""" + + def test_source_path_None(self): + # Bytecode should be used when source_path returns None, along with + # __file__ being set to the bytecode path. + name = 'mod' + bytecode_path = 'path/to/mod' + mock = PyPycLoaderMock({name: None}, {name: {'path': bytecode_path}}) + with util.uncache(name): + module = mock.load_module(name) + self.assertEqual(module.__file__, bytecode_path) + + # Testing for bytecode_path returning None handled by all tests where no + # bytecode initially exists. + + def test_all_paths_None(self): + # If all *_path methods return None, raise ImportError. + name = 'mod' + mock = PyPycLoaderMock({name: None}) + with util.uncache(name): + self.assertRaises(ImportError, mock.load_module, name) + + def test_source_path_ImportError(self): + # An ImportError from source_path should trigger an ImportError. + name = 'mod' + mock = PyPycLoaderMock({}, {name: {'path': 'path/to/mod'}}) + with util.uncache(name): + self.assertRaises(ImportError, mock.load_module, name) + + def test_bytecode_path_ImportError(self): + # An ImportError from bytecode_path should trigger an ImportError. + name = 'mod' + mock = PyPycLoaderMock({name: 'path/to/mod'}) + bad_meth = types.MethodType(raise_ImportError, mock) + mock.bytecode_path = bad_meth + with util.uncache(name): + self.assertRaises(ImportError, mock.load_module, name) + + +def test_main(): + from test.support import run_unittest + run_unittest(PyLoaderTests, PyLoaderInterfaceTests, + PyPycLoaderTests, SkipWritingBytecodeTests, + RegeneratedBytecodeTests, BadBytecodeFailureTests, + MissingPathsTests) + + +if __name__ == '__main__': + test_main() Copied: python/branches/py3k/Lib/importlib/test/source/test_file_loader.py (from r70247, /python/branches/py3k/Lib/importlib/test/source/test_loader.py) ============================================================================== --- /python/branches/py3k/Lib/importlib/test/source/test_loader.py (original) +++ python/branches/py3k/Lib/importlib/test/source/test_file_loader.py Mon Mar 9 04:35:50 2009 @@ -102,102 +102,6 @@ self.assert_('_temp' not in sys.modules) -class DontWriteBytecodeTest(unittest.TestCase): - - """If sys.dont_write_bytcode is true then no bytecode should be created.""" - - def tearDown(self): - sys.dont_write_bytecode = False - - @source_util.writes_bytecode - def run_test(self, assertion): - with source_util.create_modules('_temp') as mapping: - loader = importlib.PyPycFileLoader('_temp', mapping['_temp'], False) - loader.load_module('_temp') - bytecode_path = source_util.bytecode_path(mapping['_temp']) - assertion(bytecode_path) - - def test_bytecode_written(self): - fxn = lambda bc_path: self.assert_(os.path.exists(bc_path)) - self.run_test(fxn) - - def test_bytecode_not_written(self): - sys.dont_write_bytecode = True - fxn = lambda bc_path: self.assert_(not os.path.exists(bc_path)) - self.run_test(fxn) - - -class BadDataTest(unittest.TestCase): - - """If the bytecode has a magic number that does not match the - interpreters', ImportError is raised [bad magic]. The timestamp can have - any value. And bad marshal data raises ValueError. - - """ - - # [bad magic] - def test_bad_magic(self): - with source_util.create_modules('_temp') as mapping: - py_compile.compile(mapping['_temp']) - os.unlink(mapping['_temp']) - bytecode_path = source_util.bytecode_path(mapping['_temp']) - with open(bytecode_path, 'r+b') as file: - file.seek(0) - file.write(b'\x00\x00\x00\x00') - loader = importlib.PyPycFileLoader('_temp', mapping['_temp'], False) - self.assertRaises(ImportError, loader.load_module, '_temp') - self.assert_('_temp' not in sys.modules) - - -class SourceBytecodeInteraction(unittest.TestCase): - - """When both source and bytecode are present, certain rules dictate which - version of the code takes precedent. All things being equal, the bytecode - is used with the value of __file__ set to the source [basic top-level], - [basic package], [basic sub-module], [basic sub-package]. - - """ - - def import_(self, file, module, *, pkg=False): - loader = importlib.PyPycFileLoader(module, file, pkg) - return loader.load_module(module) - - def run_test(self, test, *create, pkg=False): - create += (test,) - with source_util.create_modules(*create) as mapping: - for name in create: - py_compile.compile(mapping[name]) - if pkg: - import_name = test.rsplit('.', 1)[0] - else: - import_name = test - loader = importlib.PyPycFileLoader(import_name, mapping[test], pkg) - # Because some platforms only have a granularity to the second for - # atime you can't check the physical files. Instead just make it an - # exception trigger if source was read. - loader.get_source = lambda self, x: 42 - module = loader.load_module(import_name) - self.assertEqual(module.__file__, mapping[name]) - self.assert_(import_name in sys.modules) - self.assertEqual(id(module), id(sys.modules[import_name])) - - # [basic top-level] - def test_basic_top_level(self): - self.run_test('top_level') - - # [basic package] - def test_basic_package(self): - self.run_test('pkg.__init__', pkg=True) - - # [basic sub-module] - def test_basic_sub_module(self): - self.run_test('pkg.sub', 'pkg.__init__') - - # [basic sub-package] - def test_basic_sub_package(self): - self.run_test('pkg.sub.__init__', 'pkg.__init__', pkg=True) - - class BadBytecodeTest(unittest.TestCase): """But there are several things about the bytecode which might lead to the Deleted: python/branches/py3k/Lib/importlib/test/source/test_loader.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/source/test_loader.py Mon Mar 9 04:35:50 2009 +++ (empty file) @@ -1,271 +0,0 @@ -import importlib -from .. import abc -from . import util as source_util - -import imp -import os -import py_compile -import sys -import unittest - - -class SimpleTest(unittest.TestCase): - - """Should have no issue importing a source module [basic]. And if there is - a syntax error, it should raise a SyntaxError [syntax error]. - - """ - - # [basic] - def test_module(self): - with source_util.create_modules('_temp') as mapping: - loader = importlib.PyPycFileLoader('_temp', mapping['_temp'], False) - module = loader.load_module('_temp') - self.assert_('_temp' in sys.modules) - check = {'__name__': '_temp', '__file__': mapping['_temp'], - '__package__': ''} - for attr, value in check.items(): - self.assertEqual(getattr(module, attr), value) - - def test_package(self): - with source_util.create_modules('_pkg.__init__') as mapping: - loader = importlib.PyPycFileLoader('_pkg', mapping['_pkg.__init__'], - True) - module = loader.load_module('_pkg') - self.assert_('_pkg' in sys.modules) - check = {'__name__': '_pkg', '__file__': mapping['_pkg.__init__'], - '__path__': [os.path.dirname(mapping['_pkg.__init__'])], - '__package__': '_pkg'} - for attr, value in check.items(): - self.assertEqual(getattr(module, attr), value) - - - def test_lacking_parent(self): - with source_util.create_modules('_pkg.__init__', '_pkg.mod')as mapping: - loader = importlib.PyPycFileLoader('_pkg.mod', mapping['_pkg.mod'], - False) - module = loader.load_module('_pkg.mod') - self.assert_('_pkg.mod' in sys.modules) - check = {'__name__': '_pkg.mod', '__file__': mapping['_pkg.mod'], - '__package__': '_pkg'} - for attr, value in check.items(): - self.assertEqual(getattr(module, attr), value) - - def fake_mtime(self, fxn): - """Fake mtime to always be higher than expected.""" - return lambda name: fxn(name) + 1 - - def test_module_reuse(self): - with source_util.create_modules('_temp') as mapping: - loader = importlib.PyPycFileLoader('_temp', mapping['_temp'], False) - module = loader.load_module('_temp') - module_id = id(module) - module_dict_id = id(module.__dict__) - with open(mapping['_temp'], 'w') as file: - file.write("testing_var = 42\n") - # For filesystems where the mtime is only to a second granularity, - # everything that has happened above can be too fast; - # force an mtime on the source that is guaranteed to be different - # than the original mtime. - loader.source_mtime = self.fake_mtime(loader.source_mtime) - module = loader.load_module('_temp') - self.assert_('testing_var' in module.__dict__, - "'testing_var' not in " - "{0}".format(list(module.__dict__.keys()))) - self.assertEqual(module, sys.modules['_temp']) - self.assertEqual(id(module), module_id) - self.assertEqual(id(module.__dict__), module_dict_id) - - def test_state_after_failure(self): - # A failed reload should leave the original module intact. - attributes = ('__file__', '__path__', '__package__') - value = '' - name = '_temp' - with source_util.create_modules(name) as mapping: - orig_module = imp.new_module(name) - for attr in attributes: - setattr(orig_module, attr, value) - with open(mapping[name], 'w') as file: - file.write('+++ bad syntax +++') - loader = importlib.PyPycFileLoader('_temp', mapping['_temp'], False) - self.assertRaises(SyntaxError, loader.load_module, name) - for attr in attributes: - self.assertEqual(getattr(orig_module, attr), value) - - # [syntax error] - def test_bad_syntax(self): - with source_util.create_modules('_temp') as mapping: - with open(mapping['_temp'], 'w') as file: - file.write('=') - loader = importlib.PyPycFileLoader('_temp', mapping['_temp'], False) - self.assertRaises(SyntaxError, loader.load_module, '_temp') - self.assert_('_temp' not in sys.modules) - - -class DontWriteBytecodeTest(unittest.TestCase): - - """If sys.dont_write_bytcode is true then no bytecode should be created.""" - - def tearDown(self): - sys.dont_write_bytecode = False - - @source_util.writes_bytecode - def run_test(self, assertion): - with source_util.create_modules('_temp') as mapping: - loader = importlib.PyPycFileLoader('_temp', mapping['_temp'], False) - loader.load_module('_temp') - bytecode_path = source_util.bytecode_path(mapping['_temp']) - assertion(bytecode_path) - - def test_bytecode_written(self): - fxn = lambda bc_path: self.assert_(os.path.exists(bc_path)) - self.run_test(fxn) - - def test_bytecode_not_written(self): - sys.dont_write_bytecode = True - fxn = lambda bc_path: self.assert_(not os.path.exists(bc_path)) - self.run_test(fxn) - - -class BadDataTest(unittest.TestCase): - - """If the bytecode has a magic number that does not match the - interpreters', ImportError is raised [bad magic]. The timestamp can have - any value. And bad marshal data raises ValueError. - - """ - - # [bad magic] - def test_bad_magic(self): - with source_util.create_modules('_temp') as mapping: - py_compile.compile(mapping['_temp']) - os.unlink(mapping['_temp']) - bytecode_path = source_util.bytecode_path(mapping['_temp']) - with open(bytecode_path, 'r+b') as file: - file.seek(0) - file.write(b'\x00\x00\x00\x00') - loader = importlib.PyPycFileLoader('_temp', mapping['_temp'], False) - self.assertRaises(ImportError, loader.load_module, '_temp') - self.assert_('_temp' not in sys.modules) - - -class SourceBytecodeInteraction(unittest.TestCase): - - """When both source and bytecode are present, certain rules dictate which - version of the code takes precedent. All things being equal, the bytecode - is used with the value of __file__ set to the source [basic top-level], - [basic package], [basic sub-module], [basic sub-package]. - - """ - - def import_(self, file, module, *, pkg=False): - loader = importlib.PyPycFileLoader(module, file, pkg) - return loader.load_module(module) - - def run_test(self, test, *create, pkg=False): - create += (test,) - with source_util.create_modules(*create) as mapping: - for name in create: - py_compile.compile(mapping[name]) - if pkg: - import_name = test.rsplit('.', 1)[0] - else: - import_name = test - loader = importlib.PyPycFileLoader(import_name, mapping[test], pkg) - # Because some platforms only have a granularity to the second for - # atime you can't check the physical files. Instead just make it an - # exception trigger if source was read. - loader.get_source = lambda self, x: 42 - module = loader.load_module(import_name) - self.assertEqual(module.__file__, mapping[name]) - self.assert_(import_name in sys.modules) - self.assertEqual(id(module), id(sys.modules[import_name])) - - # [basic top-level] - def test_basic_top_level(self): - self.run_test('top_level') - - # [basic package] - def test_basic_package(self): - self.run_test('pkg.__init__', pkg=True) - - # [basic sub-module] - def test_basic_sub_module(self): - self.run_test('pkg.sub', 'pkg.__init__') - - # [basic sub-package] - def test_basic_sub_package(self): - self.run_test('pkg.sub.__init__', 'pkg.__init__', pkg=True) - - -class BadBytecodeTest(unittest.TestCase): - - """But there are several things about the bytecode which might lead to the - source being preferred. If the magic number differs from what the - interpreter uses, then the source is used with the bytecode regenerated. - If the timestamp is older than the modification time for the source then - the bytecode is not used [bad timestamp]. - - But if the marshal data is bad, even if the magic number and timestamp - work, a ValueError is raised and the source is not used [bad marshal]. - - """ - - def import_(self, file, module_name): - loader = importlib.PyPycFileLoader(module_name, file, False) - module = loader.load_module(module_name) - self.assert_(module_name in sys.modules) - - # [bad magic] - @source_util.writes_bytecode - def test_bad_magic(self): - with source_util.create_modules('_temp') as mapping: - py_compile.compile(mapping['_temp']) - bytecode_path = source_util.bytecode_path(mapping['_temp']) - with open(bytecode_path, 'r+b') as bytecode_file: - bytecode_file.seek(0) - bytecode_file.write(b'\x00\x00\x00\x00') - self.import_(mapping['_temp'], '_temp') - with open(bytecode_path, 'rb') as bytecode_file: - self.assertEqual(bytecode_file.read(4), imp.get_magic()) - - # [bad timestamp] - @source_util.writes_bytecode - def test_bad_bytecode(self): - zeros = b'\x00\x00\x00\x00' - with source_util.create_modules('_temp') as mapping: - py_compile.compile(mapping['_temp']) - bytecode_path = source_util.bytecode_path(mapping['_temp']) - with open(bytecode_path, 'r+b') as bytecode_file: - bytecode_file.seek(4) - bytecode_file.write(zeros) - self.import_(mapping['_temp'], '_temp') - source_mtime = os.path.getmtime(mapping['_temp']) - source_timestamp = importlib._w_long(source_mtime) - with open(bytecode_path, 'rb') as bytecode_file: - bytecode_file.seek(4) - self.assertEqual(bytecode_file.read(4), source_timestamp) - - # [bad marshal] - def test_bad_marshal(self): - with source_util.create_modules('_temp') as mapping: - bytecode_path = source_util.bytecode_path(mapping['_temp']) - source_mtime = os.path.getmtime(mapping['_temp']) - source_timestamp = importlib._w_long(source_mtime) - with open(bytecode_path, 'wb') as bytecode_file: - bytecode_file.write(imp.get_magic()) - bytecode_file.write(source_timestamp) - bytecode_file.write(b'AAAA') - self.assertRaises(ValueError, self.import_, mapping['_temp'], - '_temp') - self.assert_('_temp' not in sys.modules) - - -def test_main(): - from test.support import run_unittest - run_unittest(SimpleTest, DontWriteBytecodeTest, BadDataTest, - SourceBytecodeInteraction, BadBytecodeTest) - - -if __name__ == '__main__': - test_main() Modified: python/branches/py3k/Lib/importlib/test/source/util.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/source/util.py (original) +++ python/branches/py3k/Lib/importlib/test/source/util.py Mon Mar 9 04:35:50 2009 @@ -1,5 +1,6 @@ from .. import util import contextlib +import functools import imp import os import os.path @@ -9,11 +10,24 @@ def writes_bytecode(fxn): + """Decorator to protect sys.dont_write_bytecode from mutation.""" + @functools.wraps(fxn) + def wrapper(*args, **kwargs): + original = sys.dont_write_bytecode + sys.dont_write_bytecode = False + to_return = fxn(*args, **kwargs) + sys.dont_write_bytecode = original + return to_return + return wrapper + + +def writes_bytecode_files(fxn): """Decorator that returns the function if writing bytecode is enabled, else a stub function that accepts anything and simply returns None.""" if sys.dont_write_bytecode: return lambda *args, **kwargs: None else: + @functools.wraps(fxn) def wrapper(*args, **kwargs): to_return = fxn(*args, **kwargs) sys.dont_write_bytecode = False Added: python/branches/py3k/Lib/importlib/test/test_abc.py ============================================================================== --- (empty file) +++ python/branches/py3k/Lib/importlib/test/test_abc.py Mon Mar 9 04:35:50 2009 @@ -0,0 +1,31 @@ +from importlib import abc +from importlib import machinery +import unittest + + +class SubclassTests(unittest.TestCase): + + """Test that the various classes in importlib are subclasses of the + expected ABCS.""" + + def verify(self, ABC, *classes): + """Verify the classes are subclasses of the ABC.""" + for cls in classes: + self.assert_(issubclass(cls, ABC)) + + def test_Finder(self): + self.verify(abc.Finder, machinery.BuiltinImporter, + machinery.FrozenImporter, machinery.PathFinder) + + def test_Loader(self): + self.verify(abc.Loader, machinery.BuiltinImporter, + machinery.FrozenImporter) + + +def test_main(): + from test.support import run_unittest + run_unittest(SubclassTests) + + +if __name__ == '__main__': + test_main() From buildbot at python.org Mon Mar 9 04:59:54 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 09 Mar 2009 03:59:54 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090309035954.468D81E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/395 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Mon Mar 9 05:21:53 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 09 Mar 2009 04:21:53 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090309042153.E8CA21E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/457 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Mon Mar 9 05:33:06 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 09 Mar 2009 04:33:06 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090309043306.84BA91E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/403 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_posix test_subprocess ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_subprocess.py", line 149, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 9 07:17:56 2009 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 9 Mar 2009 07:17:56 +0100 (CET) Subject: [Python-checkins] r70257 - tracker/roundup-src/roundup/cgi/actions.py Message-ID: <20090309061756.63F171E4002@bag.python.org> Author: martin.v.loewis Date: Mon Mar 9 07:17:56 2009 New Revision: 70257 Log: In retire, check whether an artificial attribute __retired__ can be edited to determine whether the user has permission to retire the object. Modified: tracker/roundup-src/roundup/cgi/actions.py Modified: tracker/roundup-src/roundup/cgi/actions.py ============================================================================== --- tracker/roundup-src/roundup/cgi/actions.py (original) +++ tracker/roundup-src/roundup/cgi/actions.py Mon Mar 9 07:17:56 2009 @@ -59,12 +59,12 @@ '%(action)s the %(classname)s class.')%info _marker = [] - def hasPermission(self, permission, classname=_marker, itemid=None): + def hasPermission(self, permission, classname=_marker, itemid=None, property=None): """Check whether the user has 'permission' on the current class.""" if classname is self._marker: classname = self.client.classname return self.db.security.hasPermission(permission, self.client.userid, - classname=classname, itemid=itemid) + classname=classname, itemid=itemid, property=property) def gettext(self, msgid): """Return the localized translation of msgid""" @@ -127,7 +127,7 @@ def hasPermission(self, permission, classname=Action._marker, itemid=None): if itemid is None: itemid = self.nodeid - return Action.hasPermission(self, permission, classname, itemid) + return Action.hasPermission(self, permission, classname, itemid, '__retired__') class SearchAction(Action): name = 'search' From python-checkins at python.org Mon Mar 9 07:19:15 2009 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 9 Mar 2009 07:19:15 +0100 (CET) Subject: [Python-checkins] r70258 - tracker/roundup-src/roundup/cgi/client.py Message-ID: <20090309061915.87BE91E4002@bag.python.org> Author: martin.v.loewis Date: Mon Mar 9 07:19:15 2009 New Revision: 70258 Log: Temporary disable editcsv, for security reasons. Modified: tracker/roundup-src/roundup/cgi/client.py Modified: tracker/roundup-src/roundup/cgi/client.py ============================================================================== --- tracker/roundup-src/roundup/cgi/client.py (original) +++ tracker/roundup-src/roundup/cgi/client.py Mon Mar 9 07:19:15 2009 @@ -866,7 +866,7 @@ # these are the actions that are available actions = ( ('edit', EditItemAction), - ('editcsv', EditCSVAction), + # ('editcsv', EditCSVAction), ('new', NewItemAction), ('register', RegisterAction), ('confrego', ConfRegoAction), From gki at pldtdsl.net Mon Mar 9 23:50:59 2009 From: gki at pldtdsl.net (Global Knowledge PH) Date: Mon, 9 Mar 2009 14:50:59 -0800 Subject: [Python-checkins] EnCase Computer Forensics I on March 16-19, 2009 Message-ID: <018601c9a109$83a05430$3301a8c0@userfd9ed37f9b> EnCase? Computer Forensics I on March 16-19, 2009 Php85,000.00 Inclusive of 12%VAT, Training Materials, Certificate and AM/PM Snack and Lunch) Venue: 25th Flr. Unit 2502b West Tower, Philippine Stock Exchange, Ortigas Center Pasig City CPE credits: 32 Level: Introductory Prerequisites: Basic computer skills. Advance preparation for this course is not required. Delivery method: Group-Live & Instructor Led Course Description: This hands-on course involves practical exercises and real-life simulations. The class provides participants with an understanding of the proper handling of digital evidence from the initial seizure of the computer/media to acquisition, and then progresses to the analysis of the data. It concludes with archiving and validating the data. Day 1 Day one starts with an introduction to EnCase? Forensic v6 and examination methodology. Attendees are shown how to use EnCase Forensic to acquire a complete copy of the data from a removable disk in a forensically sound manner. The concept of digital evidence and how computers work (paying particular regard to the associated impact on forensic examination) are also included. The main areas covered: . EnCase Forensic methodology . Navigating within the EnCase Forensic environment . EnCase Forensic concepts . Understanding the concept of digital evidence and its impact on an investigation . The basics of acquiring a forensically sound copy of data from a removable disk . Understanding how computers work Day 2 Day two expands upon the information provided in day one, and begins with a detailed discussion of the FAT file systems as well as an overview of the NT file system. Hard disk acquisition is covered, using both a forensically sound Linux CD, as well as the use of a hardware write-blocking device. Attendees will learn how to properly preview a computer system prior to acquisition as well as explore keyword searching and bookmarking of relevant data. The main areas covered: . NT/FAT File Systems . Acquisition of a hard disk Day 3 Day three includes more complex bookmarking of data. Instruction is given on the use of file signatures to properly identify file types. The principal and practical usage of digital fingerprints (hash value) to identify files of interest and exclude known files is also covered. Attendees will install external viewers within EnCase Forensic and learn how to copy data from within an evidence file. Restoring an evidence file back to physical media is also covered. The main areas covered on Day 3 include: . File types . Reviewing search hits and bookmarking . Signature analysis . Hash analysis . Installing external viewers . Detailed copy/UnErase options . Restoring evidence Day 4 Day four explores how to reacquire evidence in order to modify evidence-file parameters but still maintain data integrity. Attendees are given advice and guidance for archiving as well as instruction on how to restore and open an archived case. Attendees will observe first hand how EnCase Forensic can detect and identify any changes to the content of an evidence file. Practical instruction will then be given concerning the use of the Timeline viewer within EnCase Forensic and the recovery of deleted data from the unallocated space of a computer disk. Following this the importance of proper evidence handling will be discussed with the attendees being shown examples of good practice in this area. The main areas covered on Day 4 include: . Archiving and reopening an archived case . Verification of an evidence file . Timeline view . Location and recovery of evidence in unallocated space . The importance and practicalities of evidence handlingTM Guidance Software, Inc. is registered with the National Association of State Boards of Accountancy (NASBA) as a sponsor of continuing professional education on the National Registry of CPE Sponsors. State boards of accountancy have final authority on the acceptance of individual courses for CPE credit. Complaints regarding registered sponsors may be addressed to the National Registry of CPE sponsors, 150 Fourth Avenue North, Nashville, TN, 37219-2417. Web site: www.nasba.org About Guidance Software (GUID) Guidance Software is recognized worldwide as the industry leader in digital investigative solutions. Its EnCase? platform provides the foundation for government, corporate and law enforcement organizations to conduct thorough, network-enabled, and court-validated computer investigations of any kind, such as responding to eDiscovery requests, conducting internal investigations, responding to regulatory inquiries or performing data and compliance auditing - all while maintaining the integrity of the data. There are more than 27,000 licensed users of the EnCase technology worldwide, and thousands attend Guidance Software's renowned training programs annually. Validated by numerous courts, corporate legal departments, government agencies and law enforcement organizations worldwide, EnCase has been honored with industry awards and recognition from eWEEK, SC Magazine, Network Computing, and the Socha-Gelbmann survey. For more information about Guidance Software, visit www.guidancesoftware.com ENROLL NOW! GLOBALKNOWLEDGE PHILIPPINES INC. 25th flr. Unit no. 2502b West Tower Philippine Stock Exchange, Ortigas Center Pasig City, 1605 Philippines Tel. No. (632) 683-0969 / 637-3657 Mobile: +63 920-709-8298 Email: sandra at globalknowledgeph.com YM: sandra_medalla at yahoo.com URL: www.gkphilippines.com If you have received this email by mistake, kindly accept our apologies and send a blank email with the word "remove" in the subject line to sandramedalla at gmail.com. Thank you. _____ If you want to unsubscribe from this mailing list. Please Click it -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Mon Mar 9 08:53:10 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 9 Mar 2009 08:53:10 +0100 (CET) Subject: [Python-checkins] r70259 - python/branches/py3k/Doc/library/importlib.rst Message-ID: <20090309075310.5ED0C1E4002@bag.python.org> Author: brett.cannon Date: Mon Mar 9 08:53:09 2009 New Revision: 70259 Log: Clarify an assumption that importlib.abc.PyLoader makes when importing a package and setting __path__. Modified: python/branches/py3k/Doc/library/importlib.rst Modified: python/branches/py3k/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k/Doc/library/importlib.rst (original) +++ python/branches/py3k/Doc/library/importlib.rst Mon Mar 9 08:53:09 2009 @@ -215,7 +215,10 @@ ..method:: load_module(fullname) A concrete implementation of :meth:`importlib.abc.Loader.load_module` - that loads Python source code. + that loads Python source code. All needed information comes from the + abstract methods required by this ABC. The only pertinent assumption + made by this method is that when loading a package + :attr:`__path__` is set to ``[os.path.dirname(__file__)]``. ..method:: get_code(fullname) From python-checkins at python.org Mon Mar 9 08:54:34 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 9 Mar 2009 08:54:34 +0100 (CET) Subject: [Python-checkins] r70260 - python/branches/py3k/Lib/importlib/NOTES Message-ID: <20090309075434.080ED1E4002@bag.python.org> Author: brett.cannon Date: Mon Mar 9 08:54:33 2009 New Revision: 70260 Log: Clean up importlib NOTES so it only contains short term goals. Modified: python/branches/py3k/Lib/importlib/NOTES Modified: python/branches/py3k/Lib/importlib/NOTES ============================================================================== --- python/branches/py3k/Lib/importlib/NOTES (original) +++ python/branches/py3k/Lib/importlib/NOTES Mon Mar 9 08:54:33 2009 @@ -23,19 +23,3 @@ semantics of import that can be referenced from the package's documentation (even if it is in the package documentation itself, although it might be best in the language specification). - -* Write benchmark suite. - -* OPTIMIZE! - - + Fast path absolute name. - + Fast path pulling from sys.modules. - -* Bootstrap importlib as implementation of builtins.__import__ - -* Replace standard library modules. - - + imp - + py_compile - + compileall - + zipimport From buildbot at python.org Mon Mar 9 09:11:01 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 09 Mar 2009 08:11:01 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090309081101.E0E1C1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/493 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_pipes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 9 12:31:39 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 9 Mar 2009 12:31:39 +0100 (CET) Subject: [Python-checkins] r70261 - python/trunk/Doc/library/itertools.rst Message-ID: <20090309113139.474F21E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 9 12:31:39 2009 New Revision: 70261 Log: Issue 5443: Fix typo. Modified: python/trunk/Doc/library/itertools.rst Modified: python/trunk/Doc/library/itertools.rst ============================================================================== --- python/trunk/Doc/library/itertools.rst (original) +++ python/trunk/Doc/library/itertools.rst Mon Mar 9 12:31:39 2009 @@ -55,7 +55,7 @@ :func:`ifilter` pred, seq elements of seq where pred(elem) is True :func:`ifilterfalse` pred, seq elements of seq where pred(elem) is False :func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] - :func:`imap` func, p, q, ... func(p0, q0), fun(p1, q1), ... + :func:`imap` func, p, q, ... func(p0, q0), func(p1, q1), ... :func:`starmap` func, seq func(\*seq[0]), fun(\*seq[1]), ... :func:`tee` it, n it1, it2 , ... itn splits one iterator into n :func:`takewhile` pred, seq seq[0], seq[1], until pred fails From python-checkins at python.org Mon Mar 9 12:37:57 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 9 Mar 2009 12:37:57 +0100 (CET) Subject: [Python-checkins] r70262 - python/branches/py3k/Doc/library/itertools.rst Message-ID: <20090309113757.E7FFB1E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 9 12:37:57 2009 New Revision: 70262 Log: Issue 5443: Fix typo. Modified: python/branches/py3k/Doc/library/itertools.rst Modified: python/branches/py3k/Doc/library/itertools.rst ============================================================================== --- python/branches/py3k/Doc/library/itertools.rst (original) +++ python/branches/py3k/Doc/library/itertools.rst Mon Mar 9 12:37:57 2009 @@ -52,7 +52,7 @@ :func:`filterfalse` pred, seq elements of seq where pred(elem) is False :func:`groupby` iterable[, keyfunc] sub-iterators grouped by value of keyfunc(v) :func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] - :func:`starmap` func, seq func(\*seq[0]), fun(\*seq[1]), ... + :func:`starmap` func, seq func(\*seq[0]), func(\*seq[1]), ... :func:`tee` it, n it1, it2 , ... itn splits one iterator into n :func:`takewhile` pred, seq seq[0], seq[1], until pred fails :func:`zip_longest` p, q, ... (p[0], q[0]), (p[1], q[1]), ... From python-checkins at python.org Mon Mar 9 12:39:03 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 9 Mar 2009 12:39:03 +0100 (CET) Subject: [Python-checkins] r70263 - python/branches/release26-maint/Doc/library/itertools.rst Message-ID: <20090309113903.8CAAE1E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 9 12:39:03 2009 New Revision: 70263 Log: Issue 5443: Fix typo. Modified: python/branches/release26-maint/Doc/library/itertools.rst Modified: python/branches/release26-maint/Doc/library/itertools.rst ============================================================================== --- python/branches/release26-maint/Doc/library/itertools.rst (original) +++ python/branches/release26-maint/Doc/library/itertools.rst Mon Mar 9 12:39:03 2009 @@ -54,7 +54,7 @@ :func:`ifilter` pred, seq elements of seq where pred(elem) is True :func:`ifilterfalse` pred, seq elements of seq where pred(elem) is False :func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] - :func:`imap` func, p, q, ... func(p0, q0), fun(p1, q1), ... + :func:`imap` func, p, q, ... func(p0, q0), func(p1, q1), ... :func:`starmap` func, seq func(\*seq[0]), fun(\*seq[1]), ... :func:`tee` it, n it1, it2 , ... itn splits one iterator into n :func:`takewhile` pred, seq seq[0], seq[1], until pred fails From python-checkins at python.org Mon Mar 9 12:39:53 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 9 Mar 2009 12:39:53 +0100 (CET) Subject: [Python-checkins] r70264 - python/branches/release30-maint/Doc/library/itertools.rst Message-ID: <20090309113953.338EF1E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 9 12:39:53 2009 New Revision: 70264 Log: Issue 5443: Fix typo. Modified: python/branches/release30-maint/Doc/library/itertools.rst Modified: python/branches/release30-maint/Doc/library/itertools.rst ============================================================================== --- python/branches/release30-maint/Doc/library/itertools.rst (original) +++ python/branches/release30-maint/Doc/library/itertools.rst Mon Mar 9 12:39:53 2009 @@ -51,7 +51,7 @@ :func:`filterfalse` pred, seq elements of seq where pred(elem) is False :func:`groupby` iterable[, keyfunc] sub-iterators grouped by value of keyfunc(v) :func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] - :func:`starmap` func, seq func(\*seq[0]), fun(\*seq[1]), ... + :func:`starmap` func, seq func(\*seq[0]), func(\*seq[1]), ... :func:`tee` it, n it1, it2 , ... itn splits one iterator into n :func:`takewhile` pred, seq seq[0], seq[1], until pred fails :func:`zip_longest` p, q, ... (p[0], q[0]), (p[1], q[1]), ... From python-checkins at python.org Mon Mar 9 12:55:26 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 9 Mar 2009 12:55:26 +0100 (CET) Subject: [Python-checkins] r70265 - python/branches/py3k/Doc/library/itertools.rst Message-ID: <20090309115526.1269C1E4021@bag.python.org> Author: raymond.hettinger Date: Mon Mar 9 12:55:25 2009 New Revision: 70265 Log: Add consume() recipe to itertools docs. Modified: python/branches/py3k/Doc/library/itertools.rst Modified: python/branches/py3k/Doc/library/itertools.rst ============================================================================== --- python/branches/py3k/Doc/library/itertools.rst (original) +++ python/branches/py3k/Doc/library/itertools.rst Mon Mar 9 12:55:25 2009 @@ -615,6 +615,10 @@ "Return function(0), function(1), ..." return map(function, count(start)) + def consume(iterator, n): + "Advance the iterator n-steps ahead. If n is none, consume entirely." + collections.deque(islice(iterator, n), maxlen=0) + def nth(iterable, n, default=None): "Returns the nth item or a default value" return next(islice(iterable, n, None), default) From python-checkins at python.org Mon Mar 9 12:56:53 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 9 Mar 2009 12:56:53 +0100 (CET) Subject: [Python-checkins] r70266 - python/branches/release30-maint/Doc/library/itertools.rst Message-ID: <20090309115653.220701E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 9 12:56:52 2009 New Revision: 70266 Log: Add consume() recipe to itertools docs. Modified: python/branches/release30-maint/Doc/library/itertools.rst Modified: python/branches/release30-maint/Doc/library/itertools.rst ============================================================================== --- python/branches/release30-maint/Doc/library/itertools.rst (original) +++ python/branches/release30-maint/Doc/library/itertools.rst Mon Mar 9 12:56:52 2009 @@ -549,6 +549,10 @@ "Return function(0), function(1), ..." return map(function, count(start)) + def consume(iterator, n): + "Advance the iterator n-steps ahead. If n is none, consume entirely." + collections.deque(islice(iterator, n), maxlen=0) + def nth(iterable, n, default=None): "Returns the nth item or a default value" return next(islice(iterable, n, None), default) From python-checkins at python.org Mon Mar 9 12:57:29 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 9 Mar 2009 12:57:29 +0100 (CET) Subject: [Python-checkins] r70267 - python/trunk/Doc/library/itertools.rst Message-ID: <20090309115729.5CF281E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 9 12:57:29 2009 New Revision: 70267 Log: Add consume() recipe to itertools docs. Modified: python/trunk/Doc/library/itertools.rst Modified: python/trunk/Doc/library/itertools.rst ============================================================================== --- python/trunk/Doc/library/itertools.rst (original) +++ python/trunk/Doc/library/itertools.rst Mon Mar 9 12:57:29 2009 @@ -701,6 +701,10 @@ "Return function(0), function(1), ..." return imap(function, count(start)) + def consume(iterator, n): + "Advance the iterator n-steps ahead. If n is none, consume entirely." + collections.deque(islice(iterator, n), maxlen=0) + def nth(iterable, n, default=None): "Returns the nth item or a default value" return next(islice(iterable, n, None), default) From python-checkins at python.org Mon Mar 9 12:58:33 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 9 Mar 2009 12:58:33 +0100 (CET) Subject: [Python-checkins] r70268 - python/branches/release26-maint/Doc/library/itertools.rst Message-ID: <20090309115833.53CF11E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 9 12:58:33 2009 New Revision: 70268 Log: Add consume() recipe to itertools docs. Modified: python/branches/release26-maint/Doc/library/itertools.rst Modified: python/branches/release26-maint/Doc/library/itertools.rst ============================================================================== --- python/branches/release26-maint/Doc/library/itertools.rst (original) +++ python/branches/release26-maint/Doc/library/itertools.rst Mon Mar 9 12:58:33 2009 @@ -635,6 +635,10 @@ "Return function(0), function(1), ..." return imap(function, count(start)) + def consume(iterator, n): + "Advance the iterator n-steps ahead. If n is none, consume entirely." + collections.deque(islice(iterator, n), maxlen=0) + def nth(iterable, n, default=None): "Returns the nth item or a default value" return next(islice(iterable, n, None), default) From python-checkins at python.org Mon Mar 9 13:54:36 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 9 Mar 2009 13:54:36 +0100 (CET) Subject: [Python-checkins] r70269 - python/branches/py3k/Doc/library/queue.rst Message-ID: <20090309125436.0B9141E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 9 13:54:35 2009 New Revision: 70269 Log: Add cross-reference to the collections docs. Modified: python/branches/py3k/Doc/library/queue.rst Modified: python/branches/py3k/Doc/library/queue.rst ============================================================================== --- python/branches/py3k/Doc/library/queue.rst (original) +++ python/branches/py3k/Doc/library/queue.rst Mon Mar 9 13:54:35 2009 @@ -61,6 +61,12 @@ Exception raised when non-blocking :meth:`put` (or :meth:`put_nowait`) is called on a :class:`Queue` object which is full. +.. seealso:: + + :class:`collections.deque` is an alternative implementation of unbounded + queues with fast atomic :func:`append` and :func:`popleft` operations that + do not require locking. + .. _queueobjects: From python-checkins at python.org Mon Mar 9 13:55:53 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 9 Mar 2009 13:55:53 +0100 (CET) Subject: [Python-checkins] r70270 - python/branches/release30-maint/Doc/library/queue.rst Message-ID: <20090309125553.150801E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 9 13:55:52 2009 New Revision: 70270 Log: Add cross-reference to the collections docs. Modified: python/branches/release30-maint/Doc/library/queue.rst Modified: python/branches/release30-maint/Doc/library/queue.rst ============================================================================== --- python/branches/release30-maint/Doc/library/queue.rst (original) +++ python/branches/release30-maint/Doc/library/queue.rst Mon Mar 9 13:55:52 2009 @@ -61,6 +61,12 @@ Exception raised when non-blocking :meth:`put` (or :meth:`put_nowait`) is called on a :class:`Queue` object which is full. +.. seealso:: + + :class:`collections.deque` is an alternative implementation of unbounded + queues with fast atomic :func:`append` and :func:`popleft` operations that + do not require locking. + .. _queueobjects: From python-checkins at python.org Mon Mar 9 13:56:23 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 9 Mar 2009 13:56:23 +0100 (CET) Subject: [Python-checkins] r70271 - python/trunk/Doc/library/queue.rst Message-ID: <20090309125623.617E11E400C@bag.python.org> Author: raymond.hettinger Date: Mon Mar 9 13:56:23 2009 New Revision: 70271 Log: Add cross-reference to the collections docs. Modified: python/trunk/Doc/library/queue.rst Modified: python/trunk/Doc/library/queue.rst ============================================================================== --- python/trunk/Doc/library/queue.rst (original) +++ python/trunk/Doc/library/queue.rst Mon Mar 9 13:56:23 2009 @@ -66,6 +66,12 @@ Exception raised when non-blocking :meth:`put` (or :meth:`put_nowait`) is called on a :class:`Queue` object which is full. +.. seealso:: + + :class:`collections.deque` is an alternative implementation of unbounded + queues with fast atomic :func:`append` and :func:`popleft` operations that + do not require locking. + .. _queueobjects: From python-checkins at python.org Mon Mar 9 13:57:55 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 9 Mar 2009 13:57:55 +0100 (CET) Subject: [Python-checkins] r70272 - python/branches/release26-maint/Doc/library/queue.rst Message-ID: <20090309125755.6F3F01E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 9 13:57:55 2009 New Revision: 70272 Log: Add cross-reference to the collections docs. Modified: python/branches/release26-maint/Doc/library/queue.rst Modified: python/branches/release26-maint/Doc/library/queue.rst ============================================================================== --- python/branches/release26-maint/Doc/library/queue.rst (original) +++ python/branches/release26-maint/Doc/library/queue.rst Mon Mar 9 13:57:55 2009 @@ -66,6 +66,12 @@ Exception raised when non-blocking :meth:`put` (or :meth:`put_nowait`) is called on a :class:`Queue` object which is full. +.. seealso:: + + :class:`collections.deque` is an alternative implementation of unbounded + queues with fast atomic :func:`append` and :func:`popleft` operations that + do not require locking. + .. _queueobjects: From python-checkins at python.org Mon Mar 9 17:28:17 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 9 Mar 2009 17:28:17 +0100 (CET) Subject: [Python-checkins] r70274 - python/branches/py3k/Doc/library/importlib.rst Message-ID: <20090309162817.E14DA1E4002@bag.python.org> Author: brett.cannon Date: Mon Mar 9 17:28:16 2009 New Revision: 70274 Log: Fix some reST mishaps. Modified: python/branches/py3k/Doc/library/importlib.rst Modified: python/branches/py3k/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k/Doc/library/importlib.rst (original) +++ python/branches/py3k/Doc/library/importlib.rst Mon Mar 9 17:28:16 2009 @@ -97,7 +97,7 @@ An abstract base class representing a :term:`finder`. - ..method:: find_module(fullname, path=None) + .. method:: find_module(fullname, path=None) An abstract method for finding a :term:`loader` for the specified module. If the :term:`finder` is found on :data:`sys.meta_path` and the @@ -112,7 +112,7 @@ An abstract base class for a :term:`loader`. - ..method:: load_module(fullname) + .. method:: load_module(fullname) An abstract method for loading a module. If the module cannot be loaded, :exc:`ImportError` is raised, otherwise the loaded module is @@ -160,7 +160,7 @@ :pep:`302` protocol for loading arbitrary resources from the storage back-end. - ..method:: get_data(path) + .. method:: get_data(path) An abstract method to return the bytes for the data located at *path*. Loaders that have a file-like storage back-end can implement this @@ -175,20 +175,20 @@ An abstract base class for a :term:`loader` which implements the optional :pep:`302` protocol for loaders which inspect modules. - ..method:: is_package(fullname) + .. method:: is_package(fullname) An abstract method to return a true value if the module is a package, a false value otherwise. :exc:`ImportError` is raised if the :term:`loader` cannot find the module. - ..method:: get_source(fullname) + .. method:: get_source(fullname) An abstract method to return the source of a module. It is returned as a string with universal newline support. Returns :keyword:`None` if no source is available (e.g. a built-in module). Raises :exc:`ImportError` if the loader cannot find the module specified. - ..method:: get_code(fullname) + .. method:: get_code(fullname) An abstract method to return the :class:`code` object for a module. :keyword:`None` is returned if the module does not have a code object @@ -206,13 +206,13 @@ code is stored; all other details for loading Python source code will be handled by the concrete implementations of key methods. - ..method:: source_path(fullname) + .. method:: source_path(fullname) An abstract method that returns the path to the source code for a module. Should return :keyword:`None` if there is no source code. :exc:`ImportError` if the module cannot be found. - ..method:: load_module(fullname) + .. method:: load_module(fullname) A concrete implementation of :meth:`importlib.abc.Loader.load_module` that loads Python source code. All needed information comes from the @@ -220,7 +220,7 @@ made by this method is that when loading a package :attr:`__path__` is set to ``[os.path.dirname(__file__)]``. - ..method:: get_code(fullname) + .. method:: get_code(fullname) A concrete implementation of :meth:`importlib.abc.InspectLoader.get_code` that creates code objects @@ -233,20 +233,20 @@ This ABC is meant to help in creating loaders that support both Python source and bytecode. - ..method:: source_mtime(fullname) + .. method:: source_mtime(fullname) An abstract method which returns the modification time for the source code of the specified module. The modification time should be an integer. If there is no source code, return :keyword:`None. If the module cannot be found then :exc:`ImportError` is raised. - ..method:: bytecode_path(fullname) + .. method:: bytecode_path(fullname) An abstract method which returns the path to the bytecode for the specified module. :keyword:`None` is returned if there is no bytecode. :exc:`ImportError` is raised if the module is not found. - ..method:: write_bytecode(fullname, bytecode) + .. method:: write_bytecode(fullname, bytecode) An abstract method which has the loader write *bytecode* for future use. If the bytecode is written, return :keyword:`True`. Return From python-checkins at python.org Mon Mar 9 17:35:48 2009 From: python-checkins at python.org (georg.brandl) Date: Mon, 9 Mar 2009 17:35:48 +0100 (CET) Subject: [Python-checkins] r70275 - python/trunk/Doc/library/gzip.rst Message-ID: <20090309163548.CC2C91E4002@bag.python.org> Author: georg.brandl Date: Mon Mar 9 17:35:48 2009 New Revision: 70275 Log: Add missing space. Modified: python/trunk/Doc/library/gzip.rst Modified: python/trunk/Doc/library/gzip.rst ============================================================================== --- python/trunk/Doc/library/gzip.rst (original) +++ python/trunk/Doc/library/gzip.rst Mon Mar 9 17:35:48 2009 @@ -53,7 +53,7 @@ ``9`` is slowest and produces the most compression. The default is ``9``. The *mtime* argument is an optional numeric timestamp to be written to - the stream when compressing. All :program:`gzip`compressed streams are + the stream when compressing. All :program:`gzip` compressed streams are required to contain a timestamp. If omitted or ``None``, the current time is used. This module ignores the timestamp when decompressing; however, some programs, such as :program:`gunzip`\ , make use of it. From python-checkins at python.org Mon Mar 9 18:12:41 2009 From: python-checkins at python.org (guido.van.rossum) Date: Mon, 9 Mar 2009 18:12:41 +0100 (CET) Subject: [Python-checkins] r70276 - peps/trunk/pep-0239.txt Message-ID: <20090309171241.C1C1D1E4002@bag.python.org> Author: guido.van.rossum Date: Mon Mar 9 18:12:41 2009 New Revision: 70276 Log: Add pointer to PEP 3141. Modified: peps/trunk/pep-0239.txt Modified: peps/trunk/pep-0239.txt ============================================================================== --- peps/trunk/pep-0239.txt (original) +++ peps/trunk/pep-0239.txt Mon Mar 9 18:12:41 2009 @@ -27,6 +27,10 @@ was the default 'exact' arithmetic in ABC and it did not work out as expected". See the python-dev discussion on 17 June 2005. + *Postscript:* With the acceptance of PEP 3141, "A Type Hierarchy + for Numbers", a 'Rational' numeric abstract base class was added + with a concrete implementation in the 'fraction' module. + Rationale While sometimes slower and more memory intensive (in general, From python-checkins at python.org Mon Mar 9 18:13:35 2009 From: python-checkins at python.org (guido.van.rossum) Date: Mon, 9 Mar 2009 18:13:35 +0100 (CET) Subject: [Python-checkins] r70277 - peps/trunk/pep-0239.txt Message-ID: <20090309171335.9D9381E4002@bag.python.org> Author: guido.van.rossum Date: Mon Mar 9 18:13:35 2009 New Revision: 70277 Log: It's fractions.py, not fraction.py. Modified: peps/trunk/pep-0239.txt Modified: peps/trunk/pep-0239.txt ============================================================================== --- peps/trunk/pep-0239.txt (original) +++ peps/trunk/pep-0239.txt Mon Mar 9 18:13:35 2009 @@ -29,7 +29,7 @@ *Postscript:* With the acceptance of PEP 3141, "A Type Hierarchy for Numbers", a 'Rational' numeric abstract base class was added - with a concrete implementation in the 'fraction' module. + with a concrete implementation in the 'fractions' module. Rationale From python-checkins at python.org Mon Mar 9 21:21:17 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 9 Mar 2009 21:21:17 +0100 (CET) Subject: [Python-checkins] r70278 - peps/trunk/pep-0375.txt Message-ID: <20090309202117.14F891E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 9 21:21:16 2009 New Revision: 70278 Log: add str.format() request Modified: peps/trunk/pep-0375.txt Modified: peps/trunk/pep-0375.txt ============================================================================== --- peps/trunk/pep-0375.txt (original) +++ peps/trunk/pep-0375.txt Mon Mar 9 21:21:16 2009 @@ -54,6 +54,7 @@ - Update simplejson to the latest external version [#simplejson]_. - Ordered dictionary for collections [#ordered]_. - Fixing contextlib.nested() [#contextlib]_. +- auto-numbered replacement fields in str.format() strings [#strformat]_ Footnotes @@ -71,6 +72,9 @@ .. [#contextlib] http://bugs.python.org/issue5251 +.. [#strformat] + http://bugs.python.org/issue5237 + Copyright From python-checkins at python.org Mon Mar 9 21:21:53 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 9 Mar 2009 21:21:53 +0100 (CET) Subject: [Python-checkins] r70279 - peps/trunk/pep-0375.txt Message-ID: <20090309202153.6E00D1E4022@bag.python.org> Author: benjamin.peterson Date: Mon Mar 9 21:21:53 2009 New Revision: 70279 Log: remove draft note Modified: peps/trunk/pep-0375.txt Modified: peps/trunk/pep-0375.txt ============================================================================== --- peps/trunk/pep-0375.txt (original) +++ peps/trunk/pep-0375.txt Mon Mar 9 21:21:53 2009 @@ -34,8 +34,6 @@ Release Schedule ================ -Draft schedule: - - 3.1a1 March 7, 2009 - 3.1a2 April 4, 2009 - 3.1b1 May 2, 2009 From python-checkins at python.org Mon Mar 9 21:37:13 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 9 Mar 2009 21:37:13 +0100 (CET) Subject: [Python-checkins] r70280 - python/branches/py3k Message-ID: <20090309203713.CB4821E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 9 21:37:13 2009 New Revision: 70280 Log: Blocked revisions 70261,70267,70271,70273 via svnmerge ........ r70261 | raymond.hettinger | 2009-03-09 06:31:39 -0500 (Mon, 09 Mar 2009) | 1 line Issue 5443: Fix typo. ........ r70267 | raymond.hettinger | 2009-03-09 06:57:29 -0500 (Mon, 09 Mar 2009) | 1 line Add consume() recipe to itertools docs. ........ r70271 | raymond.hettinger | 2009-03-09 07:56:23 -0500 (Mon, 09 Mar 2009) | 1 line Add cross-reference to the collections docs. ........ r70273 | georg.brandl | 2009-03-09 09:25:07 -0500 (Mon, 09 Mar 2009) | 2 lines #5458: add a note when we started to raise RuntimeErrors. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Mon Mar 9 21:38:57 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 9 Mar 2009 21:38:57 +0100 (CET) Subject: [Python-checkins] r70281 - in python/trunk/Doc/library: bz2.rst gzip.rst Message-ID: <20090309203857.0AD7A1E4054@bag.python.org> Author: benjamin.peterson Date: Mon Mar 9 21:38:56 2009 New Revision: 70281 Log: gzip and bz2 are context managers Modified: python/trunk/Doc/library/bz2.rst python/trunk/Doc/library/gzip.rst Modified: python/trunk/Doc/library/bz2.rst ============================================================================== --- python/trunk/Doc/library/bz2.rst (original) +++ python/trunk/Doc/library/bz2.rst Mon Mar 9 21:38:56 2009 @@ -60,6 +60,11 @@ reading. Instances support iteration in the same way as normal :class:`file` instances. + :class:`BZ2File` supports the :keyword:`with` statement. + + .. versionchanged:: 2.7 + Support for the :keyword:`with` statement was added. + .. method:: close() Modified: python/trunk/Doc/library/gzip.rst ============================================================================== --- python/trunk/Doc/library/gzip.rst (original) +++ python/trunk/Doc/library/gzip.rst Mon Mar 9 21:38:56 2009 @@ -67,6 +67,11 @@ writing as *fileobj*, and retrieve the resulting memory buffer using the :class:`StringIO` object's :meth:`getvalue` method. + :class:`GzipFile` supports the :keyword:`with` statement. + + .. versionchanged:: 2.7 + Support for the :keyword:`with` statement was added. + .. function:: open(filename[, mode[, compresslevel]]) From python-checkins at python.org Mon Mar 9 22:04:34 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 9 Mar 2009 22:04:34 +0100 (CET) Subject: [Python-checkins] r70282 - in python/branches/py3k: Doc/howto/curses.rst Doc/library/bz2.rst Doc/library/filecmp.rst Doc/library/gzip.rst Doc/library/mmap.rst Doc/library/stdtypes.rst Doc/library/struct.rst Doc/library/symtable.rst Doc/library/time.rst Doc/whatsnew/2.6.rst Lib/mimetypes.py Misc/NEWS Misc/developers.txt Objects/bytearrayobject.c Message-ID: <20090309210434.626891E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 9 22:04:33 2009 New Revision: 70282 Log: Merged revisions 69998-69999,70002,70022-70023,70025-70026,70061,70086,70145,70171,70183,70188,70235,70244,70275,70281 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r69998 | benjamin.peterson | 2009-02-26 13:04:40 -0600 (Thu, 26 Feb 2009) | 1 line the startship is rather outdated now ........ r69999 | benjamin.peterson | 2009-02-26 13:05:59 -0600 (Thu, 26 Feb 2009) | 1 line comma ........ r70002 | andrew.kuchling | 2009-02-26 16:34:30 -0600 (Thu, 26 Feb 2009) | 1 line The curses panel library is now supported ........ r70022 | georg.brandl | 2009-02-27 10:23:18 -0600 (Fri, 27 Feb 2009) | 1 line #5361: fix typo. ........ r70023 | georg.brandl | 2009-02-27 10:39:26 -0600 (Fri, 27 Feb 2009) | 1 line #5363: fix cmpfiles() docs. Another instance where a prose description is twice as long as the code. ........ r70025 | georg.brandl | 2009-02-27 10:52:55 -0600 (Fri, 27 Feb 2009) | 1 line #5344: fix punctuation. ........ r70026 | georg.brandl | 2009-02-27 10:59:03 -0600 (Fri, 27 Feb 2009) | 1 line #5365: add quick look conversion table for different time representations. ........ r70061 | hirokazu.yamamoto | 2009-02-28 09:24:00 -0600 (Sat, 28 Feb 2009) | 1 line Binary flag is needed on windows. ........ r70086 | benjamin.peterson | 2009-03-01 21:35:12 -0600 (Sun, 01 Mar 2009) | 1 line fix a silly problem of caching gone wrong #5401 ........ r70145 | benjamin.peterson | 2009-03-03 16:51:57 -0600 (Tue, 03 Mar 2009) | 1 line making the writing more formal ........ r70171 | facundo.batista | 2009-03-04 15:18:17 -0600 (Wed, 04 Mar 2009) | 3 lines Fixed a typo. ........ r70183 | benjamin.peterson | 2009-03-04 18:17:57 -0600 (Wed, 04 Mar 2009) | 1 line add example ........ r70188 | hirokazu.yamamoto | 2009-03-05 03:34:14 -0600 (Thu, 05 Mar 2009) | 1 line Fixed memory leak on failure. ........ r70235 | benjamin.peterson | 2009-03-07 18:21:17 -0600 (Sat, 07 Mar 2009) | 1 line fix funky indentation ........ r70244 | martin.v.loewis | 2009-03-08 09:06:19 -0500 (Sun, 08 Mar 2009) | 2 lines Add Chris Withers. ........ r70275 | georg.brandl | 2009-03-09 11:35:48 -0500 (Mon, 09 Mar 2009) | 2 lines Add missing space. ........ r70281 | benjamin.peterson | 2009-03-09 15:38:56 -0500 (Mon, 09 Mar 2009) | 1 line gzip and bz2 are context managers ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/howto/curses.rst python/branches/py3k/Doc/library/bz2.rst python/branches/py3k/Doc/library/filecmp.rst python/branches/py3k/Doc/library/gzip.rst python/branches/py3k/Doc/library/mmap.rst python/branches/py3k/Doc/library/stdtypes.rst python/branches/py3k/Doc/library/struct.rst python/branches/py3k/Doc/library/symtable.rst python/branches/py3k/Doc/library/time.rst python/branches/py3k/Doc/whatsnew/2.6.rst python/branches/py3k/Lib/mimetypes.py python/branches/py3k/Misc/NEWS python/branches/py3k/Misc/developers.txt python/branches/py3k/Objects/bytearrayobject.c Modified: python/branches/py3k/Doc/howto/curses.rst ============================================================================== --- python/branches/py3k/Doc/howto/curses.rst (original) +++ python/branches/py3k/Doc/howto/curses.rst Mon Mar 9 22:04:33 2009 @@ -426,7 +426,7 @@ Because the curses API is so large, some functions aren't supported in the Python interface, not because they're difficult to implement, but because no one has needed them yet. Feel free to add them and then submit a patch. Also, we -don't yet have support for the menus or panels libraries associated with +don't yet have support for the menu library associated with ncurses; feel free to add that. If you write an interesting little program, feel free to contribute it as Modified: python/branches/py3k/Doc/library/bz2.rst ============================================================================== --- python/branches/py3k/Doc/library/bz2.rst (original) +++ python/branches/py3k/Doc/library/bz2.rst Mon Mar 9 22:04:33 2009 @@ -58,6 +58,11 @@ reading. Instances support iteration in the same way as normal :class:`file` instances. + :class:`BZ2File` supports the :keyword:`with` statement. + + .. versionchanged:: 2.7 + Support for the :keyword:`with` statement was added. + .. method:: close() Modified: python/branches/py3k/Doc/library/filecmp.rst ============================================================================== --- python/branches/py3k/Doc/library/filecmp.rst (original) +++ python/branches/py3k/Doc/library/filecmp.rst Mon Mar 9 22:04:33 2009 @@ -31,17 +31,24 @@ .. function:: cmpfiles(dir1, dir2, common[, shallow]) - Returns three lists of file names: *match*, *mismatch*, *errors*. *match* - contains the list of files match in both directories, *mismatch* includes the - names of those that don't, and *errros* lists the names of files which could not - be compared. Files may be listed in *errors* because the user may lack - permission to read them or many other reasons, but always that the comparison - could not be done for some reason. + Compare the files in the two directories *dir1* and *dir2* whose names are + given by *common*. - The *common* parameter is a list of file names found in both directories. The - *shallow* parameter has the same meaning and default value as for + Returns three lists of file names: *match*, *mismatch*, + *errors*. *match* contains the list of files that match, *mismatch* contains + the names of those that don't, and *errors* lists the names of files which + could not be compared. Files are listed in *errors* if they don't exist in + one of the directories, the user lacks permission to read them or if the + comparison could not be done for some other reason. + + The *shallow* parameter has the same meaning and default value as for :func:`filecmp.cmp`. + For example, ``cmpfiles('a', 'b', ['c', 'd/e'])`` will compare ``a/c`` with + ``b/c`` and ``a/d/e`` with ``b/d/e``. ``'c'`` and ``'d/e'`` will each be in + one of the three returned lists. + + Example:: >>> import filecmp Modified: python/branches/py3k/Doc/library/gzip.rst ============================================================================== --- python/branches/py3k/Doc/library/gzip.rst (original) +++ python/branches/py3k/Doc/library/gzip.rst Mon Mar 9 22:04:33 2009 @@ -53,7 +53,7 @@ ``9`` is slowest and produces the most compression. The default is ``9``. The *mtime* argument is an optional numeric timestamp to be written to - the stream when compressing. All :program:`gzip`compressed streams are + the stream when compressing. All :program:`gzip` compressed streams are required to contain a timestamp. If omitted or ``None``, the current time is used. This module ignores the timestamp when decompressing; however, some programs, such as :program:`gunzip`\ , make use of it. @@ -67,6 +67,11 @@ writing as *fileobj*, and retrieve the resulting memory buffer using the :class:`StringIO` object's :meth:`getvalue` method. + :class:`GzipFile` supports the :keyword:`with` statement. + + .. versionchanged:: 2.7 + Support for the :keyword:`with` statement was added. + .. function:: open(filename[, mode[, compresslevel]]) Modified: python/branches/py3k/Doc/library/mmap.rst ============================================================================== --- python/branches/py3k/Doc/library/mmap.rst (original) +++ python/branches/py3k/Doc/library/mmap.rst Mon Mar 9 22:04:33 2009 @@ -93,10 +93,10 @@ import mmap # write a simple example file - with open("hello.txt", "w") as f: + with open("hello.txt", "wb") as f: f.write("Hello Python!\n") - with open("hello.txt", "r+") as f: + with open("hello.txt", "r+b") as f: # memory-map the file, size 0 means whole file map = mmap.mmap(f.fileno(), 0) # read content via standard file methods Modified: python/branches/py3k/Doc/library/stdtypes.rst ============================================================================== --- python/branches/py3k/Doc/library/stdtypes.rst (original) +++ python/branches/py3k/Doc/library/stdtypes.rst Mon Mar 9 22:04:33 2009 @@ -1247,7 +1247,7 @@ +------------+-----------------------------------------------------+-------+ | ``'o'`` | Signed octal value. | \(1) | +------------+-----------------------------------------------------+-------+ -| ``'u'`` | Obselete type -- it is identical to ``'d'``. | \(7) | +| ``'u'`` | Obsolete type -- it is identical to ``'d'``. | \(7) | +------------+-----------------------------------------------------+-------+ | ``'x'`` | Signed hexadecimal (lowercase). | \(2) | +------------+-----------------------------------------------------+-------+ Modified: python/branches/py3k/Doc/library/struct.rst ============================================================================== --- python/branches/py3k/Doc/library/struct.rst (original) +++ python/branches/py3k/Doc/library/struct.rst Mon Mar 9 22:04:33 2009 @@ -48,7 +48,7 @@ .. function:: unpack_from(fmt, buffer[,offset=0]) - Unpack the *buffer* according to tthe given format. The result is a tuple even + Unpack the *buffer* according to the given format. The result is a tuple even if it contains exactly one item. The *buffer* must contain at least the amount of data required by the format (``len(buffer[offset:])`` must be at least ``calcsize(fmt)``). Modified: python/branches/py3k/Doc/library/symtable.rst ============================================================================== --- python/branches/py3k/Doc/library/symtable.rst (original) +++ python/branches/py3k/Doc/library/symtable.rst Mon Mar 9 22:04:33 2009 @@ -164,6 +164,12 @@ If the name is used as the target of a function or class statement, this will be true. + For example:: + + >>> table = symtable.symtable("def some_func(): pass", "string", "exec") + >>> table.lookup("some_func").is_namespace() + True + Note that a single name can be bound to multiple objects. If the result is ``True``, the name may also be bound to other objects, like an int or list, that does not introduce a new namespace. Modified: python/branches/py3k/Doc/library/time.rst ============================================================================== --- python/branches/py3k/Doc/library/time.rst (original) +++ python/branches/py3k/Doc/library/time.rst Mon Mar 9 22:04:33 2009 @@ -114,6 +114,25 @@ :class:`struct_time`, or having elements of the wrong type, a :exc:`TypeError` is raised. +* Use the following functions to convert between time representations: + + +-------------------------+-------------------------+-------------------------+ + | From | To | Use | + +=========================+=========================+=========================+ + | seconds since the epoch | :class:`struct_time` in | :func:`gmtime` | + | | UTC | | + +-------------------------+-------------------------+-------------------------+ + | seconds since the epoch | :class:`struct_time` in | :func:`localtime` | + | | local time | | + +-------------------------+-------------------------+-------------------------+ + | :class:`struct_time` in | seconds since the epoch | :func:`calendar.timegm` | + | UTC | | | + +-------------------------+-------------------------+-------------------------+ + | :class:`struct_time` in | seconds since the epoch | :func:`mktime` | + | local time | | | + +-------------------------+-------------------------+-------------------------+ + + The module defines the following functions and data items: Modified: python/branches/py3k/Doc/whatsnew/2.6.rst ============================================================================== --- python/branches/py3k/Doc/whatsnew/2.6.rst (original) +++ python/branches/py3k/Doc/whatsnew/2.6.rst Mon Mar 9 22:04:33 2009 @@ -274,7 +274,7 @@ The expression is evaluated, and it should result in an object that supports the context management protocol (that is, has :meth:`__enter__` and :meth:`__exit__` -methods. +methods). The object's :meth:`__enter__` is called before *with-block* is executed and therefore can run set-up code. It also may return a value that is bound to the Modified: python/branches/py3k/Lib/mimetypes.py ============================================================================== --- python/branches/py3k/Lib/mimetypes.py (original) +++ python/branches/py3k/Lib/mimetypes.py Mon Mar 9 22:04:33 2009 @@ -237,7 +237,8 @@ Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ - init() + if not inited: + init() return guess_type(url, strict) @@ -254,7 +255,8 @@ Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ - init() + if not inited: + init() return guess_all_extensions(type, strict) def guess_extension(type, strict=True): @@ -269,7 +271,8 @@ Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ - init() + if not inited: + init() return guess_extension(type, strict) def add_type(type, ext, strict=True): @@ -284,7 +287,8 @@ list of standard types, else to the list of non-standard types. """ - init() + if not inited: + init() return add_type(type, ext, strict) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Mon Mar 9 22:04:33 2009 @@ -220,6 +220,9 @@ - configparser now defaults to using an ordered dictionary. +- Issue #5401: Fixed a performance problem in mimetypes when ``from mimetypes + import guess_extension`` was used. + - Issue #1733986: Fixed mmap crash in accessing elements of second map object with same tagname but larger size than first map. (Windows) Modified: python/branches/py3k/Misc/developers.txt ============================================================================== --- python/branches/py3k/Misc/developers.txt (original) +++ python/branches/py3k/Misc/developers.txt Mon Mar 9 22:04:33 2009 @@ -17,7 +17,10 @@ Permissions History ------------------- -- Tarek Ziad? as given SVN access on Decmeber 21 2008 by NCN, +- Chris Withers was given SVN access on March 8 2009 by MvL, + after recommendation by GvR. + +- Tarek Ziad? was given SVN access on December 21 2008 by NCN, for maintenance of distutils. - Hirokazu Yamamoto was given SVN access on August 12 2008 by MvL, Modified: python/branches/py3k/Objects/bytearrayobject.c ============================================================================== --- python/branches/py3k/Objects/bytearrayobject.c (original) +++ python/branches/py3k/Objects/bytearrayobject.c Mon Mar 9 22:04:33 2009 @@ -249,7 +249,7 @@ size = va.len + vb.len; if (size < 0) { - return PyErr_NoMemory(); + PyErr_NoMemory(); goto done; } @@ -1019,11 +1019,11 @@ static void bytes_dealloc(PyByteArrayObject *self) { - if (self->ob_exports > 0) { - PyErr_SetString(PyExc_SystemError, + if (self->ob_exports > 0) { + PyErr_SetString(PyExc_SystemError, "deallocated bytearray object has exported buffers"); - PyErr_Print(); - } + PyErr_Print(); + } if (self->ob_bytes != 0) { PyMem_Free(self->ob_bytes); } From python-checkins at python.org Mon Mar 9 22:08:48 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 9 Mar 2009 22:08:48 +0100 (CET) Subject: [Python-checkins] r70283 - in python/branches/py3k/Doc/library: bz2.rst gzip.rst Message-ID: <20090309210848.072731E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 9 22:08:47 2009 New Revision: 70283 Log: fix versionchanged Modified: python/branches/py3k/Doc/library/bz2.rst python/branches/py3k/Doc/library/gzip.rst Modified: python/branches/py3k/Doc/library/bz2.rst ============================================================================== --- python/branches/py3k/Doc/library/bz2.rst (original) +++ python/branches/py3k/Doc/library/bz2.rst Mon Mar 9 22:08:47 2009 @@ -60,7 +60,7 @@ :class:`BZ2File` supports the :keyword:`with` statement. - .. versionchanged:: 2.7 + .. versionchanged:: 3.1 Support for the :keyword:`with` statement was added. Modified: python/branches/py3k/Doc/library/gzip.rst ============================================================================== --- python/branches/py3k/Doc/library/gzip.rst (original) +++ python/branches/py3k/Doc/library/gzip.rst Mon Mar 9 22:08:47 2009 @@ -69,7 +69,7 @@ :class:`GzipFile` supports the :keyword:`with` statement. - .. versionchanged:: 2.7 + .. versionchanged:: 3.1 Support for the :keyword:`with` statement was added. From python-checkins at python.org Mon Mar 9 22:12:36 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 9 Mar 2009 22:12:36 +0100 (CET) Subject: [Python-checkins] r70284 - in python/branches/release30-maint: Doc/howto/curses.rst Doc/library/bz2.rst Doc/library/filecmp.rst Doc/library/gzip.rst Doc/library/mmap.rst Doc/library/stdtypes.rst Doc/library/struct.rst Doc/library/symtable.rst Doc/library/time.rst Doc/whatsnew/2.6.rst Lib/mimetypes.py Misc/NEWS Misc/developers.txt Objects/bytearrayobject.c Message-ID: <20090309211236.BFC0A1E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 9 22:12:36 2009 New Revision: 70284 Log: Merged revisions 70282-70283 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70282 | benjamin.peterson | 2009-03-09 16:04:33 -0500 (Mon, 09 Mar 2009) | 73 lines Merged revisions 69998-69999,70002,70022-70023,70025-70026,70061,70086,70145,70171,70183,70188,70235,70244,70275,70281 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r69998 | benjamin.peterson | 2009-02-26 13:04:40 -0600 (Thu, 26 Feb 2009) | 1 line the startship is rather outdated now ........ r69999 | benjamin.peterson | 2009-02-26 13:05:59 -0600 (Thu, 26 Feb 2009) | 1 line comma ........ r70002 | andrew.kuchling | 2009-02-26 16:34:30 -0600 (Thu, 26 Feb 2009) | 1 line The curses panel library is now supported ........ r70022 | georg.brandl | 2009-02-27 10:23:18 -0600 (Fri, 27 Feb 2009) | 1 line #5361: fix typo. ........ r70023 | georg.brandl | 2009-02-27 10:39:26 -0600 (Fri, 27 Feb 2009) | 1 line #5363: fix cmpfiles() docs. Another instance where a prose description is twice as long as the code. ........ r70025 | georg.brandl | 2009-02-27 10:52:55 -0600 (Fri, 27 Feb 2009) | 1 line #5344: fix punctuation. ........ r70026 | georg.brandl | 2009-02-27 10:59:03 -0600 (Fri, 27 Feb 2009) | 1 line #5365: add quick look conversion table for different time representations. ........ r70061 | hirokazu.yamamoto | 2009-02-28 09:24:00 -0600 (Sat, 28 Feb 2009) | 1 line Binary flag is needed on windows. ........ r70086 | benjamin.peterson | 2009-03-01 21:35:12 -0600 (Sun, 01 Mar 2009) | 1 line fix a silly problem of caching gone wrong #5401 ........ r70145 | benjamin.peterson | 2009-03-03 16:51:57 -0600 (Tue, 03 Mar 2009) | 1 line making the writing more formal ........ r70171 | facundo.batista | 2009-03-04 15:18:17 -0600 (Wed, 04 Mar 2009) | 3 lines Fixed a typo. ........ r70183 | benjamin.peterson | 2009-03-04 18:17:57 -0600 (Wed, 04 Mar 2009) | 1 line add example ........ r70188 | hirokazu.yamamoto | 2009-03-05 03:34:14 -0600 (Thu, 05 Mar 2009) | 1 line Fixed memory leak on failure. ........ r70235 | benjamin.peterson | 2009-03-07 18:21:17 -0600 (Sat, 07 Mar 2009) | 1 line fix funky indentation ........ r70244 | martin.v.loewis | 2009-03-08 09:06:19 -0500 (Sun, 08 Mar 2009) | 2 lines Add Chris Withers. ........ r70275 | georg.brandl | 2009-03-09 11:35:48 -0500 (Mon, 09 Mar 2009) | 2 lines Add missing space. ........ r70281 | benjamin.peterson | 2009-03-09 15:38:56 -0500 (Mon, 09 Mar 2009) | 1 line gzip and bz2 are context managers ........ ................ r70283 | benjamin.peterson | 2009-03-09 16:08:47 -0500 (Mon, 09 Mar 2009) | 1 line fix versionchanged ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Doc/howto/curses.rst python/branches/release30-maint/Doc/library/bz2.rst python/branches/release30-maint/Doc/library/filecmp.rst python/branches/release30-maint/Doc/library/gzip.rst python/branches/release30-maint/Doc/library/mmap.rst python/branches/release30-maint/Doc/library/stdtypes.rst python/branches/release30-maint/Doc/library/struct.rst python/branches/release30-maint/Doc/library/symtable.rst python/branches/release30-maint/Doc/library/time.rst python/branches/release30-maint/Doc/whatsnew/2.6.rst python/branches/release30-maint/Lib/mimetypes.py python/branches/release30-maint/Misc/NEWS python/branches/release30-maint/Misc/developers.txt python/branches/release30-maint/Objects/bytearrayobject.c Modified: python/branches/release30-maint/Doc/howto/curses.rst ============================================================================== --- python/branches/release30-maint/Doc/howto/curses.rst (original) +++ python/branches/release30-maint/Doc/howto/curses.rst Mon Mar 9 22:12:36 2009 @@ -426,7 +426,7 @@ Because the curses API is so large, some functions aren't supported in the Python interface, not because they're difficult to implement, but because no one has needed them yet. Feel free to add them and then submit a patch. Also, we -don't yet have support for the menus or panels libraries associated with +don't yet have support for the menu library associated with ncurses; feel free to add that. If you write an interesting little program, feel free to contribute it as Modified: python/branches/release30-maint/Doc/library/bz2.rst ============================================================================== --- python/branches/release30-maint/Doc/library/bz2.rst (original) +++ python/branches/release30-maint/Doc/library/bz2.rst Mon Mar 9 22:12:36 2009 @@ -58,7 +58,6 @@ reading. Instances support iteration in the same way as normal :class:`file` instances. - .. method:: close() Close the file. Sets data attribute :attr:`closed` to true. A closed file Modified: python/branches/release30-maint/Doc/library/filecmp.rst ============================================================================== --- python/branches/release30-maint/Doc/library/filecmp.rst (original) +++ python/branches/release30-maint/Doc/library/filecmp.rst Mon Mar 9 22:12:36 2009 @@ -31,17 +31,24 @@ .. function:: cmpfiles(dir1, dir2, common[, shallow]) - Returns three lists of file names: *match*, *mismatch*, *errors*. *match* - contains the list of files match in both directories, *mismatch* includes the - names of those that don't, and *errros* lists the names of files which could not - be compared. Files may be listed in *errors* because the user may lack - permission to read them or many other reasons, but always that the comparison - could not be done for some reason. + Compare the files in the two directories *dir1* and *dir2* whose names are + given by *common*. - The *common* parameter is a list of file names found in both directories. The - *shallow* parameter has the same meaning and default value as for + Returns three lists of file names: *match*, *mismatch*, + *errors*. *match* contains the list of files that match, *mismatch* contains + the names of those that don't, and *errors* lists the names of files which + could not be compared. Files are listed in *errors* if they don't exist in + one of the directories, the user lacks permission to read them or if the + comparison could not be done for some other reason. + + The *shallow* parameter has the same meaning and default value as for :func:`filecmp.cmp`. + For example, ``cmpfiles('a', 'b', ['c', 'd/e'])`` will compare ``a/c`` with + ``b/c`` and ``a/d/e`` with ``b/d/e``. ``'c'`` and ``'d/e'`` will each be in + one of the three returned lists. + + Example:: >>> import filecmp Modified: python/branches/release30-maint/Doc/library/gzip.rst ============================================================================== --- python/branches/release30-maint/Doc/library/gzip.rst (original) +++ python/branches/release30-maint/Doc/library/gzip.rst Mon Mar 9 22:12:36 2009 @@ -52,6 +52,15 @@ level of compression; ``1`` is fastest and produces the least compression, and ``9`` is slowest and produces the most compression. The default is ``9``. + The *mtime* argument is an optional numeric timestamp to be written to + the stream when compressing. All :program:`gzip` compressed streams are + required to contain a timestamp. If omitted or ``None``, the current + time is used. This module ignores the timestamp when decompressing; + however, some programs, such as :program:`gunzip`\ , make use of it. + The format of the timestamp is the same as that of the return value of + ``time.time()`` and of the ``st_mtime`` member of the object returned + by ``os.stat()``. + Calling a :class:`GzipFile` object's :meth:`close` method does not close *fileobj*, since you might wish to append more material after the compressed data. This also allows you to pass a :class:`StringIO` object opened for Modified: python/branches/release30-maint/Doc/library/mmap.rst ============================================================================== --- python/branches/release30-maint/Doc/library/mmap.rst (original) +++ python/branches/release30-maint/Doc/library/mmap.rst Mon Mar 9 22:12:36 2009 @@ -93,10 +93,10 @@ import mmap # write a simple example file - with open("hello.txt", "w") as f: + with open("hello.txt", "wb") as f: f.write("Hello Python!\n") - with open("hello.txt", "r+") as f: + with open("hello.txt", "r+b") as f: # memory-map the file, size 0 means whole file map = mmap.mmap(f.fileno(), 0) # read content via standard file methods Modified: python/branches/release30-maint/Doc/library/stdtypes.rst ============================================================================== --- python/branches/release30-maint/Doc/library/stdtypes.rst (original) +++ python/branches/release30-maint/Doc/library/stdtypes.rst Mon Mar 9 22:12:36 2009 @@ -1247,7 +1247,7 @@ +------------+-----------------------------------------------------+-------+ | ``'o'`` | Signed octal value. | \(1) | +------------+-----------------------------------------------------+-------+ -| ``'u'`` | Obselete type -- it is identical to ``'d'``. | \(7) | +| ``'u'`` | Obsolete type -- it is identical to ``'d'``. | \(7) | +------------+-----------------------------------------------------+-------+ | ``'x'`` | Signed hexadecimal (lowercase). | \(2) | +------------+-----------------------------------------------------+-------+ Modified: python/branches/release30-maint/Doc/library/struct.rst ============================================================================== --- python/branches/release30-maint/Doc/library/struct.rst (original) +++ python/branches/release30-maint/Doc/library/struct.rst Mon Mar 9 22:12:36 2009 @@ -48,7 +48,7 @@ .. function:: unpack_from(fmt, buffer[,offset=0]) - Unpack the *buffer* according to tthe given format. The result is a tuple even + Unpack the *buffer* according to the given format. The result is a tuple even if it contains exactly one item. The *buffer* must contain at least the amount of data required by the format (``len(buffer[offset:])`` must be at least ``calcsize(fmt)``). Modified: python/branches/release30-maint/Doc/library/symtable.rst ============================================================================== --- python/branches/release30-maint/Doc/library/symtable.rst (original) +++ python/branches/release30-maint/Doc/library/symtable.rst Mon Mar 9 22:12:36 2009 @@ -164,6 +164,12 @@ If the name is used as the target of a function or class statement, this will be true. + For example:: + + >>> table = symtable.symtable("def some_func(): pass", "string", "exec") + >>> table.lookup("some_func").is_namespace() + True + Note that a single name can be bound to multiple objects. If the result is ``True``, the name may also be bound to other objects, like an int or list, that does not introduce a new namespace. Modified: python/branches/release30-maint/Doc/library/time.rst ============================================================================== --- python/branches/release30-maint/Doc/library/time.rst (original) +++ python/branches/release30-maint/Doc/library/time.rst Mon Mar 9 22:12:36 2009 @@ -114,6 +114,25 @@ :class:`struct_time`, or having elements of the wrong type, a :exc:`TypeError` is raised. +* Use the following functions to convert between time representations: + + +-------------------------+-------------------------+-------------------------+ + | From | To | Use | + +=========================+=========================+=========================+ + | seconds since the epoch | :class:`struct_time` in | :func:`gmtime` | + | | UTC | | + +-------------------------+-------------------------+-------------------------+ + | seconds since the epoch | :class:`struct_time` in | :func:`localtime` | + | | local time | | + +-------------------------+-------------------------+-------------------------+ + | :class:`struct_time` in | seconds since the epoch | :func:`calendar.timegm` | + | UTC | | | + +-------------------------+-------------------------+-------------------------+ + | :class:`struct_time` in | seconds since the epoch | :func:`mktime` | + | local time | | | + +-------------------------+-------------------------+-------------------------+ + + The module defines the following functions and data items: Modified: python/branches/release30-maint/Doc/whatsnew/2.6.rst ============================================================================== --- python/branches/release30-maint/Doc/whatsnew/2.6.rst (original) +++ python/branches/release30-maint/Doc/whatsnew/2.6.rst Mon Mar 9 22:12:36 2009 @@ -274,7 +274,7 @@ The expression is evaluated, and it should result in an object that supports the context management protocol (that is, has :meth:`__enter__` and :meth:`__exit__` -methods. +methods). The object's :meth:`__enter__` is called before *with-block* is executed and therefore can run set-up code. It also may return a value that is bound to the Modified: python/branches/release30-maint/Lib/mimetypes.py ============================================================================== --- python/branches/release30-maint/Lib/mimetypes.py (original) +++ python/branches/release30-maint/Lib/mimetypes.py Mon Mar 9 22:12:36 2009 @@ -237,7 +237,8 @@ Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ - init() + if not inited: + init() return guess_type(url, strict) @@ -254,7 +255,8 @@ Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ - init() + if not inited: + init() return guess_all_extensions(type, strict) def guess_extension(type, strict=True): @@ -269,7 +271,8 @@ Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ - init() + if not inited: + init() return guess_extension(type, strict) def add_type(type, ext, strict=True): @@ -284,7 +287,8 @@ list of standard types, else to the list of non-standard types. """ - init() + if not inited: + init() return add_type(type, ext, strict) Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Mon Mar 9 22:12:36 2009 @@ -159,6 +159,9 @@ - Issue #5385: Fixed mmap crash after resize failure on windows. +- Issue #5401: Fixed a performance problem in mimetypes when ``from mimetypes + import guess_extension`` was used. + - Issue #1733986: Fixed mmap crash in accessing elements of second map object with same tagname but larger size than first map. (Windows) Modified: python/branches/release30-maint/Misc/developers.txt ============================================================================== --- python/branches/release30-maint/Misc/developers.txt (original) +++ python/branches/release30-maint/Misc/developers.txt Mon Mar 9 22:12:36 2009 @@ -17,7 +17,10 @@ Permissions History ------------------- -- Tarek Ziad? as given SVN access on Decmeber 21 2008 by NCN, +- Chris Withers was given SVN access on March 8 2009 by MvL, + after recommendation by GvR. + +- Tarek Ziad? was given SVN access on December 21 2008 by NCN, for maintenance of distutils. - Hirokazu Yamamoto was given SVN access on August 12 2008 by MvL, Modified: python/branches/release30-maint/Objects/bytearrayobject.c ============================================================================== --- python/branches/release30-maint/Objects/bytearrayobject.c (original) +++ python/branches/release30-maint/Objects/bytearrayobject.c Mon Mar 9 22:12:36 2009 @@ -249,7 +249,7 @@ size = va.len + vb.len; if (size < 0) { - return PyErr_NoMemory(); + PyErr_NoMemory(); goto done; } @@ -1019,11 +1019,11 @@ static void bytes_dealloc(PyByteArrayObject *self) { - if (self->ob_exports > 0) { - PyErr_SetString(PyExc_SystemError, + if (self->ob_exports > 0) { + PyErr_SetString(PyExc_SystemError, "deallocated bytearray object has exported buffers"); - PyErr_Print(); - } + PyErr_Print(); + } if (self->ob_bytes != 0) { PyMem_Free(self->ob_bytes); } From python-checkins at python.org Mon Mar 9 22:16:41 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 9 Mar 2009 22:16:41 +0100 (CET) Subject: [Python-checkins] r70285 - in python/branches/release30-maint/Lib: io.py test/test_memoryio.py Message-ID: <20090309211641.A8AE21E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 9 22:16:41 2009 New Revision: 70285 Log: fix StringIO newline translation #5456 Modified: python/branches/release30-maint/Lib/io.py python/branches/release30-maint/Lib/test/test_memoryio.py Modified: python/branches/release30-maint/Lib/io.py ============================================================================== --- python/branches/release30-maint/Lib/io.py (original) +++ python/branches/release30-maint/Lib/io.py Mon Mar 9 22:16:41 2009 @@ -1942,13 +1942,12 @@ self._seennl |= (lf and self._LF) | (cr and self._CR) \ | (crlf and self._CRLF) + output = input if self._readtranslate: if crlf: output = input.replace("\r\n", "\n") if cr: output = input.replace("\r", "\n") - else: - output = input return output Modified: python/branches/release30-maint/Lib/test/test_memoryio.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_memoryio.py (original) +++ python/branches/release30-maint/Lib/test/test_memoryio.py Mon Mar 9 22:16:41 2009 @@ -376,6 +376,10 @@ ioclass = io._StringIO EOF = "" + def test_newline_none(self): + memio = self.ioclass('hello\r\nhi\r\n', newline=None) + self.assertEqual(memio.readlines(), ["hello\n", "hi\n"]) + def test_relative_seek(self): memio = self.ioclass() From buildbot at python.org Mon Mar 9 22:23:02 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 09 Mar 2009 21:23:02 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090309212302.351E81E4032@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/405 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,brett.cannon,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From buildbot at python.org Mon Mar 9 23:16:01 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 09 Mar 2009 22:16:01 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090309221601.BBCC21E400C@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/202 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_distutils test_posix ====================================================================== FAIL: test_get_python_inc (distutils.tests.test_sysconfig.SysconfigTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/distutils/tests/test_sysconfig.py", line 45, in test_get_python_inc self.assert_(os.path.isdir(inc_dir), inc_dir) AssertionError: /home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/Include ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From python-checkins at python.org Tue Mar 10 01:06:06 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 01:06:06 +0100 (CET) Subject: [Python-checkins] r70286 - python/trunk/Doc/library/queue.rst Message-ID: <20090310000606.25F6B1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 01:06:05 2009 New Revision: 70286 Log: Fix markup. Modified: python/trunk/Doc/library/queue.rst Modified: python/trunk/Doc/library/queue.rst ============================================================================== --- python/trunk/Doc/library/queue.rst (original) +++ python/trunk/Doc/library/queue.rst Tue Mar 10 01:06:05 2009 @@ -168,7 +168,7 @@ The count of unfinished tasks goes up whenever an item is added to the queue. The count goes down whenever a consumer thread calls :meth:`task_done` to indicate that the item was retrieved and all work on it is complete. When the - count of unfinished tasks drops to zero, join() unblocks. + count of unfinished tasks drops to zero, :meth:`join` unblocks. .. versionadded:: 2.5 From python-checkins at python.org Tue Mar 10 01:07:25 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 01:07:25 +0100 (CET) Subject: [Python-checkins] r70287 - python/branches/py3k/Doc/library/queue.rst Message-ID: <20090310000725.52D4A1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 01:07:25 2009 New Revision: 70287 Log: Fix markup. Modified: python/branches/py3k/Doc/library/queue.rst Modified: python/branches/py3k/Doc/library/queue.rst ============================================================================== --- python/branches/py3k/Doc/library/queue.rst (original) +++ python/branches/py3k/Doc/library/queue.rst Tue Mar 10 01:07:25 2009 @@ -155,7 +155,7 @@ The count of unfinished tasks goes up whenever an item is added to the queue. The count goes down whenever a consumer thread calls :meth:`task_done` to indicate that the item was retrieved and all work on it is complete. When the - count of unfinished tasks drops to zero, join() unblocks. + count of unfinished tasks drops to zero, :meth:`join` unblocks. Example of how to wait for enqueued tasks to be completed:: From python-checkins at python.org Tue Mar 10 01:10:11 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 01:10:11 +0100 (CET) Subject: [Python-checkins] r70288 - python/branches/release30-maint/Doc/library/queue.rst Message-ID: <20090310001011.11F031E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 01:10:10 2009 New Revision: 70288 Log: Fix markup. Modified: python/branches/release30-maint/Doc/library/queue.rst Modified: python/branches/release30-maint/Doc/library/queue.rst ============================================================================== --- python/branches/release30-maint/Doc/library/queue.rst (original) +++ python/branches/release30-maint/Doc/library/queue.rst Tue Mar 10 01:10:10 2009 @@ -155,7 +155,7 @@ The count of unfinished tasks goes up whenever an item is added to the queue. The count goes down whenever a consumer thread calls :meth:`task_done` to indicate that the item was retrieved and all work on it is complete. When the - count of unfinished tasks drops to zero, join() unblocks. + count of unfinished tasks drops to zero, :meth:`join` unblocks. Example of how to wait for enqueued tasks to be completed:: From python-checkins at python.org Tue Mar 10 01:11:32 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 01:11:32 +0100 (CET) Subject: [Python-checkins] r70289 - python/branches/release26-maint/Doc/library/queue.rst Message-ID: <20090310001132.ADCC81E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 01:11:32 2009 New Revision: 70289 Log: Fix markup. Modified: python/branches/release26-maint/Doc/library/queue.rst Modified: python/branches/release26-maint/Doc/library/queue.rst ============================================================================== --- python/branches/release26-maint/Doc/library/queue.rst (original) +++ python/branches/release26-maint/Doc/library/queue.rst Tue Mar 10 01:11:32 2009 @@ -168,7 +168,7 @@ The count of unfinished tasks goes up whenever an item is added to the queue. The count goes down whenever a consumer thread calls :meth:`task_done` to indicate that the item was retrieved and all work on it is complete. When the - count of unfinished tasks drops to zero, join() unblocks. + count of unfinished tasks drops to zero, :meth:`join` unblocks. .. versionadded:: 2.5 From python-checkins at python.org Tue Mar 10 02:07:30 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 02:07:30 +0100 (CET) Subject: [Python-checkins] r70290 - python/trunk/Doc/library/decimal.rst Message-ID: <20090310010730.C85881E400C@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 02:07:30 2009 New Revision: 70290 Log: Update url for the spec. Modified: python/trunk/Doc/library/decimal.rst Modified: python/trunk/Doc/library/decimal.rst ============================================================================== --- python/trunk/Doc/library/decimal.rst (original) +++ python/trunk/Doc/library/decimal.rst Tue Mar 10 02:07:30 2009 @@ -108,7 +108,7 @@ .. seealso:: * IBM's General Decimal Arithmetic Specification, `The General Decimal Arithmetic - Specification `_. + Specification `_. * IEEE standard 854-1987, `Unofficial IEEE 854 Text `_. From python-checkins at python.org Tue Mar 10 04:29:24 2009 From: python-checkins at python.org (brett.cannon) Date: Tue, 10 Mar 2009 04:29:24 +0100 (CET) Subject: [Python-checkins] r70291 - in python/branches/py3k: Doc/library/importlib.rst Lib/importlib/NOTES Lib/importlib/_bootstrap.py Lib/importlib/test/source/test_abc_loader.py Message-ID: <20090310032924.2755F1E4002@bag.python.org> Author: brett.cannon Date: Tue Mar 10 04:29:23 2009 New Revision: 70291 Log: Implement get_source for importlib.abc.PyLoader using source_path and get_data. Modified: python/branches/py3k/Doc/library/importlib.rst python/branches/py3k/Lib/importlib/NOTES python/branches/py3k/Lib/importlib/_bootstrap.py python/branches/py3k/Lib/importlib/test/source/test_abc_loader.py Modified: python/branches/py3k/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k/Doc/library/importlib.rst (original) +++ python/branches/py3k/Doc/library/importlib.rst Tue Mar 10 04:29:23 2009 @@ -226,6 +226,13 @@ :meth:`importlib.abc.InspectLoader.get_code` that creates code objects from Python source code. + .. method:: get_source(fullname) + + A concrete implementation of + :meth:`importlib.abc.InspectLoader.get_source`. Uses + :meth:`importlib.abc.InspectLoader.get_data` and :meth:`source_path` to + get the source code. + .. class:: PyPycLoader Modified: python/branches/py3k/Lib/importlib/NOTES ============================================================================== --- python/branches/py3k/Lib/importlib/NOTES (original) +++ python/branches/py3k/Lib/importlib/NOTES Tue Mar 10 04:29:23 2009 @@ -3,7 +3,6 @@ * Public API left to expose (w/ docs!) - + abc.PyLoader.get_source + util.set_loader * Implement InspectLoader for BuiltinImporter and FrozenImporter. Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Tue Mar 10 04:29:23 2009 @@ -369,6 +369,26 @@ source = source.replace(line_endings, b'\n') return compile(source, source_path, 'exec', dont_inherit=True) + # Never use in implementing import! Imports code within the method. + def get_source(self, fullname): + """Return the source code for a module. + + self.source_path() and self.get_data() are used to implement this + method. + + """ + path = self.source_path(fullname) + if path is None: + return None + try: + source_bytes = self.get_data(path) + except IOError: + return ImportError("source not available through get_data()") + import io + import tokenize + encoding = tokenize.detect_encoding(io.BytesIO(source_bytes).readline) + return source_bytes.decode(encoding[0]) + class PyPycLoader(PyLoader): Modified: python/branches/py3k/Lib/importlib/test/source/test_abc_loader.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/source/test_abc_loader.py (original) +++ python/branches/py3k/Lib/importlib/test/source/test_abc_loader.py Tue Mar 10 04:29:23 2009 @@ -14,8 +14,8 @@ class PyLoaderMock(abc.PyLoader): # Globals that should be defined for all modules. - source = ("_ = '::'.join([__name__, __file__, __package__, " - "repr(__loader__)])") + source = (b"_ = '::'.join([__name__, __file__, __package__, " + b"repr(__loader__)])") def __init__(self, data): """Take a dict of 'module_name: path' pairings. @@ -30,7 +30,7 @@ def get_data(self, path): if path not in self.path_to_module: raise IOError - return self.source.encode('utf-8') + return self.source def is_package(self, name): try: @@ -38,9 +38,6 @@ except KeyError: raise ImportError - def get_source(self, name): # Should not be needed. - raise NotImplementedError - def source_path(self, name): try: return self.module_paths[name] @@ -181,7 +178,7 @@ module = imp.new_module(name) module.blah = None mock = self.mocker({name: 'path/to/mod'}) - mock.source = "1/0" + mock.source = b"1/0" with util.uncache(name): sys.modules[name] = module self.assertRaises(ZeroDivisionError, mock.load_module, name) @@ -192,7 +189,7 @@ def test_unloadable(self): name = "mod" mock = self.mocker({name: 'path/to/mod'}) - mock.source = "1/0" + mock.source = b"1/0" with util.uncache(name): self.assertRaises(ZeroDivisionError, mock.load_module, name) self.assert_(name not in sys.modules) @@ -201,6 +198,8 @@ class PyLoaderInterfaceTests(unittest.TestCase): + """Tests for importlib.abc.PyLoader to make sure that when source_path() + doesn't return a path everything works as expected.""" def test_no_source_path(self): # No source path should lead to ImportError. @@ -216,6 +215,30 @@ self.assertRaises(ImportError, mock.load_module, name) +class PyLoaderGetSourceTests(unittest.TestCase): + + """Tests for importlib.abc.PyLoader.get_source().""" + + def test_default_encoding(self): + # Should have no problems with UTF-8 text. + name = 'mod' + mock = PyLoaderMock({name: 'path/to/mod'}) + source = 'x = "?"' + mock.source = source.encode('utf-8') + returned_source = mock.get_source(name) + self.assertEqual(returned_source, source) + + def test_decoded_source(self): + # Decoding should work. + name = 'mod' + mock = PyLoaderMock({name: 'path/to/mod'}) + source = "# coding: Latin-1\nx='?'" + assert source.encode('latin-1') != source.encode('utf-8') + mock.source = source.encode('latin-1') + returned_source = mock.get_source(name) + self.assertEqual(returned_source, source) + + class PyPycLoaderTests(PyLoaderTests): """Tests for importlib.abc.PyPycLoader.""" @@ -380,7 +403,7 @@ def test_main(): from test.support import run_unittest - run_unittest(PyLoaderTests, PyLoaderInterfaceTests, + run_unittest(PyLoaderTests, PyLoaderInterfaceTests, PyLoaderGetSourceTests, PyPycLoaderTests, SkipWritingBytecodeTests, RegeneratedBytecodeTests, BadBytecodeFailureTests, MissingPathsTests) From buildbot at python.org Tue Mar 10 05:09:17 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 10 Mar 2009 04:09:17 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090310040917.AB93B1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/392 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_pipes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 10 05:33:16 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 10 Mar 2009 04:33:16 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090310043317.145C91E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/407 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_robotparser.py", line 217, in testPasswordProtectedSite parser.read() File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/urllib/robotparser.py", line 56, in read f = urllib.request.urlopen(self.url) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/urllib/request.py", line 122, in urlopen return _opener.open(url, data, timeout) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/urllib/request.py", line 358, in open response = self._open(req, data) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/urllib/request.py", line 376, in _open '_open', req) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/urllib/request.py", line 336, in _call_chain result = func(*args) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/urllib/request.py", line 1082, in http_open return self.do_open(http.client.HTTPConnection, req) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/urllib/request.py", line 1070, in do_open raise URLError(err) urllib.error.URLError: 4 tests failed: test_posix test_robotparser test_smtplib test_urllib2net ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== ERROR: testBasic (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_smtplib.py", line 174, in testBasic smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 345, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") smtplib.SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testHELP (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_smtplib.py", line 214, in testHELP smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 345, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") smtplib.SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testNOOP (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_smtplib.py", line 178, in testNOOP smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 345, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") smtplib.SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testNotImplemented (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_smtplib.py", line 191, in testNotImplemented smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 345, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") smtplib.SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testRSET (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_smtplib.py", line 184, in testRSET smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 345, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") smtplib.SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testSecondHELO (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_smtplib.py", line 207, in testSecondHELO smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 345, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") smtplib.SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testSend (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_smtplib.py", line 221, in testSend smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 345, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") smtplib.SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testVRFY (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_smtplib.py", line 198, in testVRFY smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/smtplib.py", line 345, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") smtplib.SMTPServerDisconnected: Connection unexpectedly closed sincerely, -The Buildbot From python-checkins at python.org Tue Mar 10 05:40:24 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 05:40:24 +0100 (CET) Subject: [Python-checkins] r70292 - python/trunk/Doc/library/decimal.rst Message-ID: <20090310044024.9CC201E400C@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 05:40:24 2009 New Revision: 70292 Log: Clarify the meaning of normal and subnormal. Modified: python/trunk/Doc/library/decimal.rst Modified: python/trunk/Doc/library/decimal.rst ============================================================================== --- python/trunk/Doc/library/decimal.rst (original) +++ python/trunk/Doc/library/decimal.rst Tue Mar 10 05:40:24 2009 @@ -548,8 +548,11 @@ .. method:: is_normal() - Return :const:`True` if the argument is a *normal* finite number. Return - :const:`False` if the argument is zero, subnormal, infinite or a NaN. + Return :const:`True` if the argument is a *normal* finite non-zero + number with an adjusted exponent greater than or equal to *Emin*. + Return :const:`False` if the argument is zero, subnormal, infinite or a + NaN. Note, the term *normal* is used here in a different sense with + the :meth:`normalize` method which is used to create canonical values. .. versionadded:: 2.6 @@ -577,7 +580,8 @@ .. method:: is_subnormal() Return :const:`True` if the argument is subnormal, and :const:`False` - otherwise. + otherwise. A number is subnormal is if it is nonzero, finite, and has an + adjusted exponent less than *Emin*. .. versionadded:: 2.6 From python-checkins at python.org Tue Mar 10 05:49:23 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 05:49:23 +0100 (CET) Subject: [Python-checkins] r70293 - python/trunk/Lib/decimal.py Message-ID: <20090310044923.DA68E1E4023@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 05:49:21 2009 New Revision: 70293 Log: Add a version tag to the decimal module. Modified: python/trunk/Lib/decimal.py Modified: python/trunk/Lib/decimal.py ============================================================================== --- python/trunk/Lib/decimal.py (original) +++ python/trunk/Lib/decimal.py Tue Mar 10 05:49:21 2009 @@ -134,6 +134,8 @@ 'setcontext', 'getcontext', 'localcontext' ] +__version__ = '1.68' # Highest version of the spec this complies with + import copy as _copy import math as _math import numbers as _numbers From python-checkins at python.org Tue Mar 10 06:17:37 2009 From: python-checkins at python.org (brett.cannon) Date: Tue, 10 Mar 2009 06:17:37 +0100 (CET) Subject: [Python-checkins] r70294 - in python/branches/py3k: Doc/library/importlib.rst Lib/importlib/NOTES Lib/importlib/_bootstrap.py Lib/importlib/test/builtin/test_loader.py Lib/importlib/test/extension/test_loader.py Lib/importlib/test/frozen/test_loader.py Lib/importlib/util.py Message-ID: <20090310051737.A925D1E4002@bag.python.org> Author: brett.cannon Date: Tue Mar 10 06:17:37 2009 New Revision: 70294 Log: Implement importlib.util.set_loader: a decorator to automatically set __loader__ on modules. Modified: python/branches/py3k/Doc/library/importlib.rst python/branches/py3k/Lib/importlib/NOTES python/branches/py3k/Lib/importlib/_bootstrap.py python/branches/py3k/Lib/importlib/test/builtin/test_loader.py python/branches/py3k/Lib/importlib/test/extension/test_loader.py python/branches/py3k/Lib/importlib/test/frozen/test_loader.py python/branches/py3k/Lib/importlib/util.py Modified: python/branches/py3k/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k/Doc/library/importlib.rst (original) +++ python/branches/py3k/Doc/library/importlib.rst Tue Mar 10 06:17:37 2009 @@ -348,7 +348,15 @@ loader should initialize as specified by :pep:`302`. -.. function:: set_package(method) +.. function:: set_loader(fxn) + + A :term:`decorator` for a :term:`loader` to set the :attr:`__loader__` + attribute on loaded modules. If the attribute is already set the decorator + does nothing. It is assumed that the first positional argument to the + wrapped method is what :attr:`__loader__` should be set to. + + +.. function:: set_package(fxn) A :term:`decorator` for a :term:`loader` to set the :attr:`__package__` attribute on the module returned by the loader. If :attr:`__package__` is Modified: python/branches/py3k/Lib/importlib/NOTES ============================================================================== --- python/branches/py3k/Lib/importlib/NOTES (original) +++ python/branches/py3k/Lib/importlib/NOTES Tue Mar 10 06:17:37 2009 @@ -1,10 +1,6 @@ to do ///// -* Public API left to expose (w/ docs!) - - + util.set_loader - * Implement InspectLoader for BuiltinImporter and FrozenImporter. + Expose function to see if a frozen module is a package. Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Tue Mar 10 06:17:37 2009 @@ -110,6 +110,17 @@ return wrapper +def set_loader(fxn): + """Set __loader__ on the returned module.""" + def wrapper(self, *args, **kwargs): + module = fxn(self, *args, **kwargs) + if not hasattr(module, '__loader__'): + module.__loader__ = self + return module + wrap(wrapper, fxn) + return wrapper + + class BuiltinImporter: """Meta path loader for built-in modules. @@ -132,6 +143,7 @@ @classmethod @set_package + @set_loader def load_module(cls, fullname): """Load a built-in module.""" if fullname not in sys.builtin_module_names: @@ -161,6 +173,7 @@ @classmethod @set_package + @set_loader def load_module(cls, fullname): """Load a frozen module.""" if cls.find_module(fullname) is None: @@ -249,13 +262,12 @@ @check_name @set_package + @set_loader def load_module(self, fullname): """Load an extension module.""" is_reload = fullname in sys.modules try: - module = imp.load_dynamic(fullname, self._path) - module.__loader__ = self - return module + return imp.load_dynamic(fullname, self._path) except: if not is_reload and fullname in sys.modules: del sys.modules[fullname] Modified: python/branches/py3k/Lib/importlib/test/builtin/test_loader.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/builtin/test_loader.py (original) +++ python/branches/py3k/Lib/importlib/test/builtin/test_loader.py Tue Mar 10 06:17:37 2009 @@ -15,7 +15,8 @@ assert 'errno' in sys.builtin_module_names name = 'errno' - verification = {'__name__': 'errno', '__package__': ''} + verification = {'__name__': 'errno', '__package__': '', + '__loader__': machinery.BuiltinImporter} def verify(self, module): """Verify that the module matches against what it should have.""" Modified: python/branches/py3k/Lib/importlib/test/extension/test_loader.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/extension/test_loader.py (original) +++ python/branches/py3k/Lib/importlib/test/extension/test_loader.py Tue Mar 10 06:17:37 2009 @@ -24,6 +24,8 @@ ('__package__', '')]: self.assertEqual(getattr(module, attr), value) self.assert_(ext_util.NAME in sys.modules) + self.assert_(isinstance(module.__loader__, + importlib._ExtensionFileLoader)) def test_package(self): # Extensions are not found in packages. Modified: python/branches/py3k/Lib/importlib/test/frozen/test_loader.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/frozen/test_loader.py (original) +++ python/branches/py3k/Lib/importlib/test/frozen/test_loader.py Tue Mar 10 06:17:37 2009 @@ -9,7 +9,7 @@ with util.uncache('__hello__'): module = machinery.FrozenImporter.load_module('__hello__') check = {'__name__': '__hello__', '__file__': '', - '__package__': ''} + '__package__': '', '__loader__': machinery.FrozenImporter} for attr, value in check.items(): self.assertEqual(getattr(module, attr), value) @@ -17,7 +17,8 @@ with util.uncache('__phello__'): module = machinery.FrozenImporter.load_module('__phello__') check = {'__name__': '__phello__', '__file__': '', - '__package__': '__phello__', '__path__': ['__phello__']} + '__package__': '__phello__', '__path__': ['__phello__'], + '__loader__': machinery.FrozenImporter} for attr, value in check.items(): attr_value = getattr(module, attr) self.assertEqual(attr_value, value, @@ -28,7 +29,8 @@ with util.uncache('__phello__', '__phello__.spam'): module = machinery.FrozenImporter.load_module('__phello__.spam') check = {'__name__': '__phello__.spam', '__file__': '', - '__package__': '__phello__'} + '__package__': '__phello__', + '__loader__': machinery.FrozenImporter} for attr, value in check.items(): attr_value = getattr(module, attr) self.assertEqual(attr_value, value, Modified: python/branches/py3k/Lib/importlib/util.py ============================================================================== --- python/branches/py3k/Lib/importlib/util.py (original) +++ python/branches/py3k/Lib/importlib/util.py Tue Mar 10 06:17:37 2009 @@ -1,3 +1,4 @@ """Utility code for constructing importers, etc.""" from ._bootstrap import module_for_loader +from ._bootstrap import set_loader from ._bootstrap import set_package From buildbot at python.org Tue Mar 10 06:41:06 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 10 Mar 2009 05:41:06 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090310054107.0D9611E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/717 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson,georg.brandl,martin.v.loewis,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_ftplib.py", line 203, in run asyncore.loop(timeout=0.1, count=1) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 204, in loop poll_fun(timeout, map) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 141, in poll read(obj) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 78, in read obj.handle_error() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 74, in read obj.handle_read_event() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 413, in handle_read_event self.handle_read() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_ssl.py", line 408, in handle_read self.send(data.lower()) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 519, in send self.initiate_send() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 506, in initiate_send num_sent = dispatcher.send(self, self.out_buffer[:512]) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 349, in send result = self.socket.send(data) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/socket.py", line 165, in _dummy raise error(EBADF, 'Bad file descriptor') error: [Errno 9] Bad file descriptor sincerely, -The Buildbot From buildbot at python.org Tue Mar 10 06:56:18 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 10 Mar 2009 05:56:18 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090310055618.8BDCA1E4045@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/497 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Tue Mar 10 06:58:37 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 10 Mar 2009 05:58:37 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc trunk Message-ID: <20090310055838.2356F1E4002@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%20solaris10%20gcc%20trunk/builds/224 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson,georg.brandl,martin.v.loewis,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib ====================================================================== ERROR: testBasic (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_smtplib.py", line 166, in testBasic smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 343, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testHELP (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_smtplib.py", line 206, in testHELP smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 343, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testNOOP (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_smtplib.py", line 170, in testNOOP smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 343, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testNotImplemented (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_smtplib.py", line 183, in testNotImplemented smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 343, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testRSET (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_smtplib.py", line 176, in testRSET smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 343, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testSecondHELO (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_smtplib.py", line 199, in testSecondHELO smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 343, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testSend (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_smtplib.py", line 213, in testSend smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 343, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") SMTPServerDisconnected: Connection unexpectedly closed ====================================================================== ERROR: testVRFY (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_smtplib.py", line 190, in testVRFY smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/smtplib.py", line 343, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") SMTPServerDisconnected: Connection unexpectedly closed sincerely, -The Buildbot From python-checkins at python.org Tue Mar 10 09:16:06 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 09:16:06 +0100 (CET) Subject: [Python-checkins] r70295 - python/trunk/Doc/library/decimal.rst Message-ID: <20090310081606.0167C1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 09:16:05 2009 New Revision: 70295 Log: Update the decimal FAQ for the from_float() classmethod and improve the recipe for remove_exponent() to make it cut and pasteable. Modified: python/trunk/Doc/library/decimal.rst Modified: python/trunk/Doc/library/decimal.rst ============================================================================== --- python/trunk/Doc/library/decimal.rst (original) +++ python/trunk/Doc/library/decimal.rst Tue Mar 10 09:16:05 2009 @@ -1907,47 +1907,28 @@ original's two-place significance. If an application does not care about tracking significance, it is easy to -remove the exponent and trailing zeroes, losing significance, but keeping the -value unchanged: +remove the exponent and trailing zeros, losing significance, but keeping the +value unchanged:: - >>> def remove_exponent(d): - ... return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize() + def remove_exponent(d): + '''Remove exponent and trailing zeros. - >>> remove_exponent(Decimal('5E+3')) - Decimal('5000') + >>> remove_exponent(Decimal('5E+3')) + Decimal('5000') -Q. Is there a way to convert a regular float to a :class:`Decimal`? + ''' + return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize() -A. Yes, all binary floating point numbers can be exactly expressed as a -Decimal. An exact conversion may take more precision than intuition would -suggest, so we trap :const:`Inexact` to signal a need for more precision: +Q. Is there a way to convert a regular float to a Decimal? -.. testcode:: +A. Yes, the classmethod :meth:`from_float` makes an exact conversion. - def float_to_decimal(f): - "Convert a floating point number to a Decimal with no loss of information" - n, d = f.as_integer_ratio() - numerator, denominator = Decimal(n), Decimal(d) - ctx = Context(prec=60) - result = ctx.divide(numerator, denominator) - while ctx.flags[Inexact]: - ctx.flags[Inexact] = False - ctx.prec *= 2 - result = ctx.divide(numerator, denominator) - return result +The regular decimal constructor does not do this by default because there is +some question about whether it is advisable to mix binary and decimal floating +point. Also, its use requires some care to avoid the representation issues +associated with binary floating point: -.. doctest:: - - >>> float_to_decimal(math.pi) - Decimal('3.141592653589793115997963468544185161590576171875') - -Q. Why isn't the :func:`float_to_decimal` routine included in the module? - -A. There is some question about whether it is advisable to mix binary and -decimal floating point. Also, its use requires some care to avoid the -representation issues associated with binary floating point: - - >>> float_to_decimal(1.1) + >>> Decimal.from_float(1.1) Decimal('1.100000000000000088817841970012523233890533447265625') Q. Within a complex calculation, how can I make sure that I haven't gotten a From python-checkins at python.org Tue Mar 10 10:31:49 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 10:31:49 +0100 (CET) Subject: [Python-checkins] r70296 - in python/trunk: Lib/test/test_deque.py Modules/_collectionsmodule.c Message-ID: <20090310093149.5AB011E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 10:31:48 2009 New Revision: 70296 Log: Small optimization for corner case where maxlen==0. Modified: python/trunk/Lib/test/test_deque.py python/trunk/Modules/_collectionsmodule.c Modified: python/trunk/Lib/test/test_deque.py ============================================================================== --- python/trunk/Lib/test/test_deque.py (original) +++ python/trunk/Lib/test/test_deque.py Tue Mar 10 10:31:48 2009 @@ -50,7 +50,9 @@ def test_maxlen(self): self.assertRaises(ValueError, deque, 'abc', -1) self.assertRaises(ValueError, deque, 'abc', -2) - d = deque(range(10), maxlen=3) + it = iter(range(10)) + d = deque(it, maxlen=3) + self.assertEqual(list(it), []) self.assertEqual(repr(d), 'deque([7, 8, 9], maxlen=3)') self.assertEqual(list(d), range(7, 10)) self.assertEqual(d, deque(range(10), 3)) @@ -87,6 +89,21 @@ fo.close() test_support.unlink(test_support.TESTFN) + def test_maxlen_zero(self): + it = iter(range(100)) + deque(it, maxlen=0) + self.assertEqual(list(it), []) + + it = iter(range(100)) + d = deque(maxlen=0) + d.extend(it) + self.assertEqual(list(it), []) + + it = iter(range(100)) + d = deque(maxlen=0) + d.extendleft(it) + self.assertEqual(list(it), []) + def test_comparisons(self): d = deque('xabc'); d.popleft() for e in [d, deque('abc'), deque('ab'), deque(), list(d)]: Modified: python/trunk/Modules/_collectionsmodule.c ============================================================================== --- python/trunk/Modules/_collectionsmodule.c (original) +++ python/trunk/Modules/_collectionsmodule.c Tue Mar 10 10:31:48 2009 @@ -276,6 +276,23 @@ PyDoc_STRVAR(appendleft_doc, "Add an element to the left side of the deque."); + +/* Run an iterator to exhaustion. Shortcut for + the extend/extendleft methods when maxlen == 0. */ +static PyObject* +consume_iterator(PyObject *it) +{ + PyObject *item; + + while ((item = PyIter_Next(it)) != NULL) { + Py_DECREF(item); + } + Py_DECREF(it); + if (PyErr_Occurred()) + return NULL; + Py_RETURN_NONE; +} + static PyObject * deque_extend(dequeobject *deque, PyObject *iterable) { @@ -285,6 +302,9 @@ if (it == NULL) return NULL; + if (deque->maxlen == 0) + return consume_iterator(it); + while ((item = PyIter_Next(it)) != NULL) { deque->state++; if (deque->rightindex == BLOCKLEN-1) { @@ -323,6 +343,9 @@ if (it == NULL) return NULL; + if (deque->maxlen == 0) + return consume_iterator(it); + while ((item = PyIter_Next(it)) != NULL) { deque->state++; if (deque->leftindex == 0) { From python-checkins at python.org Tue Mar 10 10:36:07 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 10:36:07 +0100 (CET) Subject: [Python-checkins] r70297 - in python/branches/py3k: Lib/test/test_deque.py Modules/_collectionsmodule.c Message-ID: <20090310093607.A513D1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 10:36:07 2009 New Revision: 70297 Log: Small optimization for corner case where maxlen==0. Modified: python/branches/py3k/Lib/test/test_deque.py python/branches/py3k/Modules/_collectionsmodule.c Modified: python/branches/py3k/Lib/test/test_deque.py ============================================================================== --- python/branches/py3k/Lib/test/test_deque.py (original) +++ python/branches/py3k/Lib/test/test_deque.py Tue Mar 10 10:36:07 2009 @@ -51,7 +51,9 @@ def test_maxlen(self): self.assertRaises(ValueError, deque, 'abc', -1) self.assertRaises(ValueError, deque, 'abc', -2) - d = deque(range(10), maxlen=3) + it = iter(range(10)) + d = deque(it, maxlen=3) + self.assertEqual(list(it), []) self.assertEqual(repr(d), 'deque([7, 8, 9], maxlen=3)') self.assertEqual(list(d), [7, 8, 9]) self.assertEqual(d, deque(range(10), 3)) @@ -88,6 +90,21 @@ fo.close() support.unlink(support.TESTFN) + def test_maxlen_zero(self): + it = iter(range(100)) + deque(it, maxlen=0) + self.assertEqual(list(it), []) + + it = iter(range(100)) + d = deque(maxlen=0) + d.extend(it) + self.assertEqual(list(it), []) + + it = iter(range(100)) + d = deque(maxlen=0) + d.extendleft(it) + self.assertEqual(list(it), []) + def test_comparisons(self): d = deque('xabc'); d.popleft() for e in [d, deque('abc'), deque('ab'), deque(), list(d)]: Modified: python/branches/py3k/Modules/_collectionsmodule.c ============================================================================== --- python/branches/py3k/Modules/_collectionsmodule.c (original) +++ python/branches/py3k/Modules/_collectionsmodule.c Tue Mar 10 10:36:07 2009 @@ -276,6 +276,23 @@ PyDoc_STRVAR(appendleft_doc, "Add an element to the left side of the deque."); + +/* Run an iterator to exhaustion. Shortcut for + the extend/extendleft methods when maxlen == 0. */ +static PyObject* +consume_iterator(PyObject *it) +{ + PyObject *item; + + while ((item = PyIter_Next(it)) != NULL) { + Py_DECREF(item); + } + Py_DECREF(it); + if (PyErr_Occurred()) + return NULL; + Py_RETURN_NONE; +} + static PyObject * deque_extend(dequeobject *deque, PyObject *iterable) { @@ -285,6 +302,9 @@ if (it == NULL) return NULL; + if (deque->maxlen == 0) + return consume_iterator(it); + while ((item = PyIter_Next(it)) != NULL) { deque->state++; if (deque->rightindex == BLOCKLEN-1) { @@ -323,6 +343,9 @@ if (it == NULL) return NULL; + if (deque->maxlen == 0) + return consume_iterator(it); + while ((item = PyIter_Next(it)) != NULL) { deque->state++; if (deque->leftindex == 0) { From buildbot at python.org Tue Mar 10 11:15:02 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 10 Mar 2009 10:15:02 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090310101502.891751E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/227 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 10 11:21:24 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 10 Mar 2009 10:21:24 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090310102124.DB1E91E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/401 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_robotparser.py", line 217, in testPasswordProtectedSite parser.read() File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/urllib/robotparser.py", line 56, in read f = urllib.request.urlopen(self.url) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/urllib/request.py", line 122, in urlopen return _opener.open(url, data, timeout) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/urllib/request.py", line 358, in open response = self._open(req, data) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/urllib/request.py", line 376, in _open '_open', req) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/urllib/request.py", line 336, in _call_chain result = func(*args) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/urllib/request.py", line 1082, in http_open return self.do_open(http.client.HTTPConnection, req) File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/urllib/request.py", line 1070, in do_open raise URLError(err) urllib.error.URLError: 1 test failed: test_robotparser make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 10 11:58:09 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 10 Mar 2009 10:58:09 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090310105809.7F5511E400C@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/438 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Tue Mar 10 12:15:22 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 10 Mar 2009 11:15:22 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090310111522.C975D1E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/409 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_posix test_subprocess ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_subprocess.py", line 149, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From buildbot at python.org Tue Mar 10 12:31:33 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 10 Mar 2009 11:31:33 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090310113134.47F8C1E404C@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/463 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_multiprocessing sincerely, -The Buildbot From python-checkins at python.org Tue Mar 10 13:51:00 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 13:51:00 +0100 (CET) Subject: [Python-checkins] r70298 - in python/trunk: Doc/library/collections.rst Lib/test/test_deque.py Misc/NEWS Modules/_collectionsmodule.c Message-ID: <20090310125100.4D41E1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 13:50:59 2009 New Revision: 70298 Log: For collections.deque() objects, expose the maxlen parameter as a read-only attribute. Modified: python/trunk/Doc/library/collections.rst python/trunk/Lib/test/test_deque.py python/trunk/Misc/NEWS python/trunk/Modules/_collectionsmodule.c Modified: python/trunk/Doc/library/collections.rst ============================================================================== --- python/trunk/Doc/library/collections.rst (original) +++ python/trunk/Doc/library/collections.rst Tue Mar 10 13:50:59 2009 @@ -382,6 +382,15 @@ ``d.appendleft(d.pop())``. + Deque objects also provide one read-only attribute: + + .. attribute:: maxlen + + Maximum size of a deque or *None* if unbounded. + + .. versionadded:: 2.7 + + In addition to the above, deques support iteration, pickling, ``len(d)``, ``reversed(d)``, ``copy.copy(d)``, ``copy.deepcopy(d)``, membership testing with the :keyword:`in` operator, and subscript references such as ``d[-1]``. Indexed Modified: python/trunk/Lib/test/test_deque.py ============================================================================== --- python/trunk/Lib/test/test_deque.py (original) +++ python/trunk/Lib/test/test_deque.py Tue Mar 10 13:50:59 2009 @@ -104,6 +104,16 @@ d.extendleft(it) self.assertEqual(list(it), []) + def test_maxlen_attribute(self): + self.assertEqual(deque().maxlen, None) + self.assertEqual(deque('abc').maxlen, None) + self.assertEqual(deque('abc', maxlen=4).maxlen, 4) + self.assertEqual(deque('abc', maxlen=2).maxlen, 2) + self.assertEqual(deque('abc', maxlen=0).maxlen, 0) + with self.assertRaises(AttributeError): + d = deque('abc') + d.maxlen = 10 + def test_comparisons(self): d = deque('xabc'); d.popleft() for e in [d, deque('abc'), deque('ab'), deque(), list(d)]: Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 10 13:50:59 2009 @@ -168,6 +168,8 @@ Library ------- +- collections.deque() objects now have a read-only attribute called maxlen. + - Issue #2638: Show a window constructed with tkSimpleDialog.Dialog only after it is has been populated and properly configured in order to prevent window flashing. Modified: python/trunk/Modules/_collectionsmodule.c ============================================================================== --- python/trunk/Modules/_collectionsmodule.c (original) +++ python/trunk/Modules/_collectionsmodule.c Tue Mar 10 13:50:59 2009 @@ -870,6 +870,20 @@ return 0; } +static PyObject * +deque_get_maxlen(dequeobject *deque) +{ + if (deque->maxlen == -1) + Py_RETURN_NONE; + return PyInt_FromSsize_t(deque->maxlen); +} + +static PyGetSetDef deque_getset[] = { + {"maxlen", (getter)deque_get_maxlen, (setter)NULL, + "maximum size of a deque or None if unbounded"}, + {0} +}; + static PySequenceMethods deque_as_sequence = { (lenfunc)deque_len, /* sq_length */ 0, /* sq_concat */ @@ -951,7 +965,7 @@ 0, /* tp_iternext */ deque_methods, /* tp_methods */ 0, /* tp_members */ - 0, /* tp_getset */ + deque_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ From python-checkins at python.org Tue Mar 10 13:56:32 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 13:56:32 +0100 (CET) Subject: [Python-checkins] r70299 - in python/branches/py3k: Doc/library/collections.rst Lib/test/test_deque.py Misc/NEWS Modules/_collectionsmodule.c Message-ID: <20090310125632.693101E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 13:56:32 2009 New Revision: 70299 Log: For collections.deque() objects, expose the maxlen parameter as a read-only attribute. Modified: python/branches/py3k/Doc/library/collections.rst python/branches/py3k/Lib/test/test_deque.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_collectionsmodule.c Modified: python/branches/py3k/Doc/library/collections.rst ============================================================================== --- python/branches/py3k/Doc/library/collections.rst (original) +++ python/branches/py3k/Doc/library/collections.rst Tue Mar 10 13:56:32 2009 @@ -361,6 +361,15 @@ ``d.appendleft(d.pop())``. + Deque objects also provide one read-only attribute: + + .. attribute:: maxlen + + Maximum size of a deque or *None* if unbounded. + + .. versionadded:: 2.7 + + In addition to the above, deques support iteration, pickling, ``len(d)``, ``reversed(d)``, ``copy.copy(d)``, ``copy.deepcopy(d)``, membership testing with the :keyword:`in` operator, and subscript references such as ``d[-1]``. Indexed Modified: python/branches/py3k/Lib/test/test_deque.py ============================================================================== --- python/branches/py3k/Lib/test/test_deque.py (original) +++ python/branches/py3k/Lib/test/test_deque.py Tue Mar 10 13:56:32 2009 @@ -105,6 +105,16 @@ d.extendleft(it) self.assertEqual(list(it), []) + def test_maxlen_attribute(self): + self.assertEqual(deque().maxlen, None) + self.assertEqual(deque('abc').maxlen, None) + self.assertEqual(deque('abc', maxlen=4).maxlen, 4) + self.assertEqual(deque('abc', maxlen=2).maxlen, 2) + self.assertEqual(deque('abc', maxlen=0).maxlen, 0) + with self.assertRaises(AttributeError): + d = deque('abc') + d.maxlen = 10 + def test_comparisons(self): d = deque('xabc'); d.popleft() for e in [d, deque('abc'), deque('ab'), deque(), list(d)]: Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 10 13:56:32 2009 @@ -195,6 +195,8 @@ Library ------- +- collections.deque() objects now have a read-only attribute called maxlen. + - Issue #2638: Show a window constructed with tkSimpleDialog.Dialog only after it is has been populated and properly configured in order to prevent window flashing. Modified: python/branches/py3k/Modules/_collectionsmodule.c ============================================================================== --- python/branches/py3k/Modules/_collectionsmodule.c (original) +++ python/branches/py3k/Modules/_collectionsmodule.c Tue Mar 10 13:56:32 2009 @@ -812,6 +812,20 @@ return 0; } +static PyObject * +deque_get_maxlen(dequeobject *deque) +{ + if (deque->maxlen == -1) + Py_RETURN_NONE; + return PyLong_FromSsize_t(deque->maxlen); +} + +static PyGetSetDef deque_getset[] = { + {"maxlen", (getter)deque_get_maxlen, (setter)NULL, + "maximum size of a deque or None if unbounded"}, + {0} +}; + static PySequenceMethods deque_as_sequence = { (lenfunc)deque_len, /* sq_length */ 0, /* sq_concat */ @@ -893,7 +907,7 @@ 0, /* tp_iternext */ deque_methods, /* tp_methods */ 0, /* tp_members */ - 0, /* tp_getset */ + deque_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ From python-checkins at python.org Tue Mar 10 14:04:31 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 14:04:31 +0100 (CET) Subject: [Python-checkins] r70300 - python/trunk/Doc/library/itertools.rst Message-ID: <20090310130431.2F69A1E400C@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 14:04:30 2009 New Revision: 70300 Log: Fix typo. Modified: python/trunk/Doc/library/itertools.rst Modified: python/trunk/Doc/library/itertools.rst ============================================================================== --- python/trunk/Doc/library/itertools.rst (original) +++ python/trunk/Doc/library/itertools.rst Tue Mar 10 14:04:30 2009 @@ -56,7 +56,7 @@ :func:`ifilterfalse` pred, seq elements of seq where pred(elem) is False :func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] :func:`imap` func, p, q, ... func(p0, q0), func(p1, q1), ... - :func:`starmap` func, seq func(\*seq[0]), fun(\*seq[1]), ... + :func:`starmap` func, seq func(\*seq[0]), func(\*seq[1]), ... :func:`tee` it, n it1, it2 , ... itn splits one iterator into n :func:`takewhile` pred, seq seq[0], seq[1], until pred fails :func:`izip` p, q, ... (p[0], q[0]), (p[1], q[1]), ... From python-checkins at python.org Tue Mar 10 14:05:41 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 14:05:41 +0100 (CET) Subject: [Python-checkins] r70301 - python/branches/release26-maint/Doc/library/itertools.rst Message-ID: <20090310130541.799A81E404F@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 14:05:40 2009 New Revision: 70301 Log: Fix typo. Modified: python/branches/release26-maint/Doc/library/itertools.rst Modified: python/branches/release26-maint/Doc/library/itertools.rst ============================================================================== --- python/branches/release26-maint/Doc/library/itertools.rst (original) +++ python/branches/release26-maint/Doc/library/itertools.rst Tue Mar 10 14:05:40 2009 @@ -55,7 +55,7 @@ :func:`ifilterfalse` pred, seq elements of seq where pred(elem) is False :func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] :func:`imap` func, p, q, ... func(p0, q0), func(p1, q1), ... - :func:`starmap` func, seq func(\*seq[0]), fun(\*seq[1]), ... + :func:`starmap` func, seq func(\*seq[0]), func(\*seq[1]), ... :func:`tee` it, n it1, it2 , ... itn splits one iterator into n :func:`takewhile` pred, seq seq[0], seq[1], until pred fails :func:`izip` p, q, ... (p[0], q[0]), (p[1], q[1]), ... From python-checkins at python.org Tue Mar 10 17:51:19 2009 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 10 Mar 2009 17:51:19 +0100 (CET) Subject: [Python-checkins] r70302 - in python/branches/release26-maint: Doc/library/bsddb.rst Message-ID: <20090310165119.EF1111E4002@bag.python.org> Author: gregory.p.smith Date: Tue Mar 10 17:51:19 2009 New Revision: 70302 Log: Merged revisions 70197 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70197 | jesus.cea | 2009-03-05 11:37:37 -0800 (Thu, 05 Mar 2009) | 1 line Minor bsddb documentation glitch ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/library/bsddb.rst Modified: python/branches/release26-maint/Doc/library/bsddb.rst ============================================================================== --- python/branches/release26-maint/Doc/library/bsddb.rst (original) +++ python/branches/release26-maint/Doc/library/bsddb.rst Tue Mar 10 17:51:19 2009 @@ -17,7 +17,7 @@ objects the user must serialize them somehow, typically using :func:`marshal.dumps` or :func:`pickle.dumps`. -The :mod:`bsddb` module requires a Berkeley DB library version from 3.3 thru +The :mod:`bsddb` module requires a Berkeley DB library version from 4.0 thru 4.7. From python-checkins at python.org Tue Mar 10 23:48:06 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 10 Mar 2009 23:48:06 +0100 (CET) Subject: [Python-checkins] r70303 - python/branches/py3k/Doc/library/collections.rst Message-ID: <20090310224806.ECB581E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 10 23:48:06 2009 New Revision: 70303 Log: Record version added as 3.1. Modified: python/branches/py3k/Doc/library/collections.rst Modified: python/branches/py3k/Doc/library/collections.rst ============================================================================== --- python/branches/py3k/Doc/library/collections.rst (original) +++ python/branches/py3k/Doc/library/collections.rst Tue Mar 10 23:48:06 2009 @@ -367,7 +367,7 @@ Maximum size of a deque or *None* if unbounded. - .. versionadded:: 2.7 + .. versionadded:: 3.1 In addition to the above, deques support iteration, pickling, ``len(d)``, From python-checkins at python.org Wed Mar 11 00:01:49 2009 From: python-checkins at python.org (martin.v.loewis) Date: Wed, 11 Mar 2009 00:01:49 +0100 (CET) Subject: [Python-checkins] r70304 - in tracker/instances/python-dev: detectors/sendmail.py extensions/local_replace.py html/issue.item.html html/page.html Message-ID: <20090310230149.79A3E1E4002@bag.python.org> Author: martin.v.loewis Date: Wed Mar 11 00:01:46 2009 New Revision: 70304 Log: Issue #249: Clear _count attributes out of various places. This is supposed to be a temporary change, to be reverted when something better arrives. Modified: tracker/instances/python-dev/detectors/sendmail.py tracker/instances/python-dev/extensions/local_replace.py tracker/instances/python-dev/html/issue.item.html tracker/instances/python-dev/html/page.html Modified: tracker/instances/python-dev/detectors/sendmail.py ============================================================================== --- tracker/instances/python-dev/detectors/sendmail.py (original) +++ tracker/instances/python-dev/detectors/sendmail.py Wed Mar 11 00:01:46 2009 @@ -73,6 +73,10 @@ changenote = cl.generateChangeNote(nodeid, oldvalues) oldfiles = oldvalues.get('files', []) + # Silence nosy_count/message_count + lines = changenote.splitlines() + changenote = '\n'.join(line for line in lines if '_count' not in line) + newfiles = db.issue.get(nodeid, 'files', []) if oldfiles != newfiles: added = [fid for fid in newfiles if fid not in oldfiles] Modified: tracker/instances/python-dev/extensions/local_replace.py ============================================================================== --- tracker/instances/python-dev/extensions/local_replace.py (original) +++ tracker/instances/python-dev/extensions/local_replace.py Wed Mar 11 00:01:46 2009 @@ -18,12 +18,20 @@ message = cre.sub(replacement, message) return message - - - + +noise_change = re.compile('(nosy_count|message_count)\: \d+\.0 -> \d+\.0') +noise_init = re.compile('(nosy_count|message_count)\: \d+\.0') +br = re.compile('
') + +def clean_count(history): + history = noise_change.sub('', history) + history = noise_init.sub('', history) + history = br.sub('', history) + return history + def init(instance): instance.registerUtil('localReplace', localReplace) - + instance.registerUtil('clean_count', clean_count) if "__main__" == __name__: print " revision 222", localReplace(" revision 222") @@ -31,4 +39,4 @@ print " r222", localReplace(" r222") print " r 222", localReplace(" r 222") print " #555", localReplace(" #555") - + Modified: tracker/instances/python-dev/html/issue.item.html ============================================================================== --- tracker/instances/python-dev/html/issue.item.html (original) +++ tracker/instances/python-dev/html/issue.item.html Wed Mar 11 00:01:46 2009 @@ -257,7 +257,8 @@ - + Modified: tracker/instances/python-dev/html/page.html ============================================================================== --- tracker/instances/python-dev/html/page.html (original) +++ tracker/instances/python-dev/html/page.html Wed Mar 11 00:01:46 2009 @@ -218,8 +218,9 @@

- + clear this message

From python-checkins at python.org Wed Mar 11 05:51:06 2009 From: python-checkins at python.org (brett.cannon) Date: Wed, 11 Mar 2009 05:51:06 +0100 (CET) Subject: [Python-checkins] r70305 - in python/trunk: Doc/library/warnings.rst Lib/test/test_warnings.py Lib/warnings.py Misc/NEWS Python/_warnings.c Message-ID: <20090311045106.80B3C1E4002@bag.python.org> Author: brett.cannon Date: Wed Mar 11 05:51:06 2009 New Revision: 70305 Log: Require implementations for warnings.showwarning() support the 'line' argument. Was a DeprecationWarning for not supporting it since Python 2.6. Closes issue #3652. Modified: python/trunk/Doc/library/warnings.rst python/trunk/Lib/test/test_warnings.py python/trunk/Lib/warnings.py python/trunk/Misc/NEWS python/trunk/Python/_warnings.c Modified: python/trunk/Doc/library/warnings.rst ============================================================================== --- python/trunk/Doc/library/warnings.rst (original) +++ python/trunk/Doc/library/warnings.rst Wed Mar 11 05:51:06 2009 @@ -291,9 +291,8 @@ message; if *line* is not supplied, :func:`showwarning` will try to read the line specified by *filename* and *lineno*. - .. versionchanged:: 2.6 - Added the *line* argument. Implementations that lack the new argument - will trigger a :exc:`DeprecationWarning`. + .. versionchanged:: 2.7 + The *line* argument is required to be supported. .. function:: formatwarning(message, category, filename, lineno[, line]) Modified: python/trunk/Lib/test/test_warnings.py ============================================================================== --- python/trunk/Lib/test/test_warnings.py (original) +++ python/trunk/Lib/test/test_warnings.py Wed Mar 11 05:51:06 2009 @@ -605,41 +605,6 @@ module = py_warnings -class ShowwarningDeprecationTests(BaseTest): - - """Test the deprecation of the old warnings.showwarning() API works.""" - - @staticmethod - def bad_showwarning(message, category, filename, lineno, file=None): - pass - - @staticmethod - def ok_showwarning(*args): - pass - - def test_deprecation(self): - # message, category, filename, lineno[, file[, line]] - args = ("message", UserWarning, "file name", 42) - with original_warnings.catch_warnings(module=self.module): - self.module.filterwarnings("error", category=DeprecationWarning) - self.module.showwarning = self.bad_showwarning - self.assertRaises(DeprecationWarning, self.module.warn_explicit, - *args) - self.module.showwarning = self.ok_showwarning - try: - self.module.warn_explicit(*args) - except DeprecationWarning as exc: - self.fail('showwarning(*args) should not trigger a ' - 'DeprecationWarning') - -class CShowwarningDeprecationTests(ShowwarningDeprecationTests): - module = c_warnings - - -class PyShowwarningDeprecationTests(ShowwarningDeprecationTests): - module = py_warnings - - def test_main(): py_warnings.onceregistry.clear() c_warnings.onceregistry.clear() @@ -649,8 +614,6 @@ _WarningsTests, CWarningsDisplayTests, PyWarningsDisplayTests, CCatchWarningTests, PyCatchWarningTests, - CShowwarningDeprecationTests, - PyShowwarningDeprecationTests, ) Modified: python/trunk/Lib/warnings.py ============================================================================== --- python/trunk/Lib/warnings.py (original) +++ python/trunk/Lib/warnings.py Wed Mar 11 05:51:06 2009 @@ -262,24 +262,6 @@ raise RuntimeError( "Unrecognized action (%r) in warnings.filters:\n %s" % (action, item)) - # Warn if showwarning() does not support the 'line' argument. - # Don't use 'inspect' as it relies on an extension module, which break the - # build thanks to 'warnings' being imported by setup.py. - fxn_code = None - if hasattr(showwarning, 'func_code'): - fxn_code = showwarning.func_code - elif hasattr(showwarning, '__func__'): - fxn_code = showwarning.__func__.func_code - if fxn_code: - args = fxn_code.co_varnames[:fxn_code.co_argcount] - CO_VARARGS = 0x4 - if 'line' not in args and not fxn_code.co_flags & CO_VARARGS: - showwarning_msg = ("functions overriding warnings.showwarning() " - "must support the 'line' argument") - if message == showwarning_msg: - _show_warning(message, category, filename, lineno) - else: - warn(showwarning_msg, DeprecationWarning) # Print message and context showwarning(message, category, filename, lineno) Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Wed Mar 11 05:51:06 2009 @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #3652: Make the 'line' argument for warnings.showwarning() a + requirement. Means the DeprecationWarning from Python 2.6 can go away. + - Issue #5247: Improve error message when unknown format codes are used when using str.format() with str, unicode, long, int, and float arguments. Modified: python/trunk/Python/_warnings.c ============================================================================== --- python/trunk/Python/_warnings.c (original) +++ python/trunk/Python/_warnings.c Wed Mar 11 05:51:06 2009 @@ -1,5 +1,4 @@ #include "Python.h" -#include "code.h" /* For DeprecationWarning about adding 'line'. */ #include "frameobject.h" #define MODULE_NAME "_warnings" @@ -387,54 +386,23 @@ show_warning(filename, lineno, text, category, sourceline); } else { - const char *msg = "functions overriding warnings.showwarning() " - "must support the 'line' argument"; - const char *text_char = PyString_AS_STRING(text); - - if (strcmp(msg, text_char) == 0) { - /* Prevent infinite recursion by using built-in implementation - of showwarning(). */ - show_warning(filename, lineno, text, category, sourceline); - } - else { - PyObject *check_fxn; - PyObject *defaults; - PyObject *res; - - if (PyMethod_Check(show_fxn)) - check_fxn = PyMethod_Function(show_fxn); - else if (PyFunction_Check(show_fxn)) - check_fxn = show_fxn; - else { - PyErr_SetString(PyExc_TypeError, - "warnings.showwarning() must be set to a " - "function or method"); - Py_DECREF(show_fxn); - goto cleanup; - } + PyObject *res; - defaults = PyFunction_GetDefaults(check_fxn); - /* A proper implementation of warnings.showwarning() should - have at least two default arguments. */ - if ((defaults == NULL) || (PyTuple_Size(defaults) < 2)) { - PyCodeObject *code = (PyCodeObject *) - PyFunction_GetCode(check_fxn); - if (!(code->co_flags & CO_VARARGS)) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1) < - 0) { - Py_DECREF(show_fxn); - goto cleanup; - } - } - } - res = PyObject_CallFunctionObjArgs(show_fxn, message, category, - filename, lineno_obj, - NULL); - Py_DECREF(show_fxn); - Py_XDECREF(res); - if (res == NULL) - goto cleanup; - } + if (!PyMethod_Check(show_fxn) && !PyFunction_Check(show_fxn)) { + PyErr_SetString(PyExc_TypeError, + "warnings.showwarning() must be set to a " + "function or method"); + Py_DECREF(show_fxn); + goto cleanup; + } + + res = PyObject_CallFunctionObjArgs(show_fxn, message, category, + filename, lineno_obj, + NULL); + Py_DECREF(show_fxn); + Py_XDECREF(res); + if (res == NULL) + goto cleanup; } } else /* if (rc == -1) */ From python-checkins at python.org Wed Mar 11 06:11:02 2009 From: python-checkins at python.org (brett.cannon) Date: Wed, 11 Mar 2009 06:11:02 +0100 (CET) Subject: [Python-checkins] r70306 - python/branches/py3k Message-ID: <20090311051102.81AD61E4010@bag.python.org> Author: brett.cannon Date: Wed Mar 11 06:11:02 2009 New Revision: 70306 Log: Blocked revisions 70305 via svnmerge ........ r70305 | brett.cannon | 2009-03-10 21:51:06 -0700 (Tue, 10 Mar 2009) | 5 lines Require implementations for warnings.showwarning() support the 'line' argument. Was a DeprecationWarning for not supporting it since Python 2.6. Closes issue #3652. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Wed Mar 11 06:14:27 2009 From: python-checkins at python.org (brett.cannon) Date: Wed, 11 Mar 2009 06:14:27 +0100 (CET) Subject: [Python-checkins] r70307 - python/branches/py3k/Lib/importlib/NOTES Message-ID: <20090311051427.7F0731E4002@bag.python.org> Author: brett.cannon Date: Wed Mar 11 06:14:27 2009 New Revision: 70307 Log: Add a NOTE for importlib to fill in the docstrings for the ABCs. Modified: python/branches/py3k/Lib/importlib/NOTES Modified: python/branches/py3k/Lib/importlib/NOTES ============================================================================== --- python/branches/py3k/Lib/importlib/NOTES (original) +++ python/branches/py3k/Lib/importlib/NOTES Wed Mar 11 06:14:27 2009 @@ -1,6 +1,8 @@ to do ///// +* Fill in docstrings for ABCs. + * Implement InspectLoader for BuiltinImporter and FrozenImporter. + Expose function to see if a frozen module is a package. From buildbot at python.org Wed Mar 11 06:31:45 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Mar 2009 05:31:45 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090311053145.BAF531E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/720 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: brett.cannon,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Wed Mar 11 06:35:27 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Mar 2009 05:35:27 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090311053527.81FCE1E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/229 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: brett.cannon,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_urllib2net make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Wed Mar 11 06:58:42 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Mar 2009 05:58:42 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090311055843.345D11E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/500 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Wed Mar 11 07:39:30 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Mar 2009 06:39:30 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090311063930.96AE71E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/411 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 3 tests failed: test_posix test_robotparser test_subprocess ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_subprocess.py", line 149, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From buildbot at python.org Wed Mar 11 07:40:09 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Mar 2009 06:40:09 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090311064009.4C98B1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/396 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Wed Mar 11 13:48:05 2009 From: python-checkins at python.org (tarek.ziade) Date: Wed, 11 Mar 2009 13:48:05 +0100 (CET) Subject: [Python-checkins] r70308 - in python/trunk: Lib/distutils/tests/test_util.py Misc/NEWS Message-ID: <20090311124805.3524E1E4002@bag.python.org> Author: tarek.ziade Date: Wed Mar 11 13:48:04 2009 New Revision: 70308 Log: Issue #5472: Fixed distutils.test_util tear down Modified: python/trunk/Lib/distutils/tests/test_util.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/distutils/tests/test_util.py ============================================================================== --- python/trunk/Lib/distutils/tests/test_util.py (original) +++ python/trunk/Lib/distutils/tests/test_util.py Wed Mar 11 13:48:04 2009 @@ -53,6 +53,8 @@ os.path.splitdrive = self.splitdrive if self.uname is not None: os.uname = self.uname + else: + del os.uname def _set_uname(self, uname): self._uname = uname Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Wed Mar 11 13:48:04 2009 @@ -171,6 +171,9 @@ Library ------- +- Issue #5472: Fixed distutils.test_util tear down. Original patch by + Tim Golden. + - collections.deque() objects now have a read-only attribute called maxlen. - Issue #2638: Show a window constructed with tkSimpleDialog.Dialog only after From python-checkins at python.org Wed Mar 11 13:50:43 2009 From: python-checkins at python.org (tarek.ziade) Date: Wed, 11 Mar 2009 13:50:43 +0100 (CET) Subject: [Python-checkins] r70309 - python/branches/release26-maint Message-ID: <20090311125043.48F9D1E4002@bag.python.org> Author: tarek.ziade Date: Wed Mar 11 13:50:42 2009 New Revision: 70309 Log: Blocked revisions 70308 via svnmerge ........ r70308 | tarek.ziade | 2009-03-11 13:48:04 +0100 (Wed, 11 Mar 2009) | 1 line Issue #5472: Fixed distutils.test_util tear down ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Wed Mar 11 13:52:01 2009 From: python-checkins at python.org (tarek.ziade) Date: Wed, 11 Mar 2009 13:52:01 +0100 (CET) Subject: [Python-checkins] r70310 - in python/branches/py3k: Lib/distutils/tests/test_util.py Misc/NEWS Message-ID: <20090311125201.558DB1E4002@bag.python.org> Author: tarek.ziade Date: Wed Mar 11 13:52:00 2009 New Revision: 70310 Log: Merged revisions 70308 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70308 | tarek.ziade | 2009-03-11 13:48:04 +0100 (Wed, 11 Mar 2009) | 1 line Issue #5472: Fixed distutils.test_util tear down ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/distutils/tests/test_util.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/distutils/tests/test_util.py ============================================================================== --- python/branches/py3k/Lib/distutils/tests/test_util.py (original) +++ python/branches/py3k/Lib/distutils/tests/test_util.py Wed Mar 11 13:52:00 2009 @@ -53,6 +53,8 @@ os.path.splitdrive = self.splitdrive if self.uname is not None: os.uname = self.uname + else: + del os.uname def _set_uname(self, uname): self._uname = uname Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Mar 11 13:52:00 2009 @@ -195,6 +195,9 @@ Library ------- +- Issue #5472: Fixed distutils.test_util tear down. Original patch by + Tim Golden. + - collections.deque() objects now have a read-only attribute called maxlen. - Issue #2638: Show a window constructed with tkSimpleDialog.Dialog only after From python-checkins at python.org Wed Mar 11 13:55:23 2009 From: python-checkins at python.org (tarek.ziade) Date: Wed, 11 Mar 2009 13:55:23 +0100 (CET) Subject: [Python-checkins] r70311 - python/branches/release30-maint Message-ID: <20090311125523.340B01E402A@bag.python.org> Author: tarek.ziade Date: Wed Mar 11 13:55:22 2009 New Revision: 70311 Log: Blocked revisions 70310 via svnmerge ................ r70310 | tarek.ziade | 2009-03-11 13:52:00 +0100 (Wed, 11 Mar 2009) | 9 lines Merged revisions 70308 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70308 | tarek.ziade | 2009-03-11 13:48:04 +0100 (Wed, 11 Mar 2009) | 1 line Issue #5472: Fixed distutils.test_util tear down ........ ................ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Wed Mar 11 14:47:04 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 11 Mar 2009 13:47:04 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo 2.6 Message-ID: <20090311134705.0ADCB1E4002@bag.python.org> The Buildbot has detected a new failure of x86 gentoo 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20gentoo%202.6/builds/170 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: tarek.ziade BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Wed Mar 11 20:14:30 2009 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 11 Mar 2009 20:14:30 +0100 (CET) Subject: [Python-checkins] r70312 - peps/trunk/pep-3135.txt Message-ID: <20090311191430.AF1761E4002@bag.python.org> Author: guido.van.rossum Date: Wed Mar 11 20:14:30 2009 New Revision: 70312 Log: Finally update the super() PEP. Lie Ryan submitted a draft which I updated a bit more. I think this is good enough now. Modified: peps/trunk/pep-3135.txt Modified: peps/trunk/pep-3135.txt ============================================================================== --- peps/trunk/pep-3135.txt (original) +++ peps/trunk/pep-3135.txt Wed Mar 11 20:14:30 2009 @@ -3,13 +3,14 @@ Version: $Revision$ Last-Modified: $Date$ Author: Calvin Spealman , - Tim Delaney -Status: Draft + Tim Delaney , + Lie Ryan +Status: Accepted Type: Standards Track Content-Type: text/x-rst Created: 28-Apr-2007 Python-Version: 3.0 -Post-History: 28-Apr-2007, 29-Apr-2007 (1), 29-Apr-2007 (2), 14-May-2007 +Post-History: 28-Apr-2007, 29-Apr-2007 (1), 29-Apr-2007 (2), 14-May-2007, 12-Mar-2009 Numbering Note ============== @@ -17,11 +18,6 @@ This PEP started its life as PEP 367. Since it is now targeted for Python 3000, it has been moved into the 3xxx space. -NOTE: This PEP needs to be rewritten to match reality. The actual -implementation is quite different than what is described here; -effectively, super() equals to super(C, self) where C is the current -class and self is the first argument of the current function. - Abstract ======== @@ -32,19 +28,12 @@ The premise of the new super usage suggested is as follows:: - super.foo(1, 2) + super().foo(1, 2) to replace the old:: super(Foo, self).foo(1, 2) -and the current ``__builtin__.super`` be aliased to ``__builtin__.__super__`` -(with ``__builtin__.super`` to be removed in Python 3.0). - -It is further proposed that assignment to ``super`` become a ``SyntaxError``, -similar to the behaviour of ``None``. - - Rationale ========= @@ -58,83 +47,54 @@ ============= Within the specification section, some special terminology will be used to -distinguish similar and closely related concepts. "super type" will refer to -the actual builtin type named "super". A "super instance" is simply an instance -of the super type, which is associated with a class and possibly with an -instance of that class. - -Because the new ``super`` semantics are not backwards compatible with Python -2.5, the new semantics will require a ``__future__`` import:: - - from __future__ import new_super - -The current ``__builtin__.super`` will be aliased to ``__builtin__.__super__``. -This will occur regardless of whether the new ``super`` semantics are active. -It is not possible to simply rename ``__builtin__.super``, as that would affect -modules that do not use the new ``super`` semantics. In Python 3.0 it is -proposed that the name ``__builtin__.super`` will be removed. - -Replacing the old usage of super, calls to the next class in the MRO (method -resolution order) can be made without explicitly creating a ``super`` -instance (although doing so will still be supported via ``__super__``). Every -function will have an implicit local named ``super``. This name behaves -identically to a normal local, including use by inner functions via a cell, -with the following exceptions: +distinguish similar and closely related concepts. "super class" will refer to +the actual builtin class named "super". A "super instance" is simply an +instance of the super class, which is associated with another class and +possibly with an instance of that class. -1. Assigning to the name ``super`` will raise a ``SyntaxError`` at compile time; +The new ``super`` semantics are only available in Python 3.0. -2. Calling a static method or normal function that accesses the name ``super`` - will raise a ``TypeError`` at runtime. - -Every function that uses the name ``super``, or has an inner function that -uses the name ``super``, will include a preamble that performs the equivalent -of:: +Replacing the old usage of super, calls to the next class in the MRO (method +resolution order) can be made without explicitly passing the class object +(although doing so will still be supported). Every function +will have a cell named ``__class__`` that contains the class object that the +function is defined in. - super = __builtin__.__super__(, ) +The new syntax:: -where ```` is the class that the method was defined in, and -```` is the first parameter of the method (normally ``self`` for -instance methods, and ``cls`` for class methods). For static methods and normal -functions, ```` will be ``None``, resulting in a ``TypeError`` being -raised during the preamble. + super() -Note: The relationship between ``super`` and ``__super__`` is similar to that -between ``import`` and ``__import__``. +is equivalent to:: -Much of this was discussed in the thread of the python-dev list, "Fixing super -anyone?" [1]_. + super(__class__, ) +where ``__class__`` is the class that the method was defined in, and +```` is the first parameter of the method (normally ``self`` +for instance methods, and ``cls`` for class methods). For functions +defined outside a class body, ``__class__`` is not defined, and will +result in runtime ``SystemError``. -Open Issues ------------ +While ``super`` is not a reserved word, the parser recognizes the use +of ``super`` in a method definition and only passes in the +``__class__`` cell when this is found. Thus, calling a global alias +of ``super`` without arguments will not necessarily work. +Closed Issues +============= Determining the class object to use -''''''''''''''''''''''''''''''''''' +----------------------------------- -The exact mechanism for associating the method with the defining class is not -specified in this PEP, and should be chosen for maximum performance. For -CPython, it is suggested that the class instance be held in a C-level variable -on the function object which is bound to one of ``NULL`` (not part of a class), -``Py_None`` (static method) or a class object (instance or class method). +The class object is taken from a cell named ``__class__``. Should ``super`` actually become a keyword? -''''''''''''''''''''''''''''''''''''''''''' - -With this proposal, ``super`` would become a keyword to the same extent that -``None`` is a keyword. It is possible that further restricting the ``super`` -name may simplify implementation, however some are against the actual keyword- -ization of super. The simplest solution is often the correct solution and the -simplest solution may well not be adding additional keywords to the language -when they are not needed. Still, it may solve other open issues. +------------------------------------------- - -Closed Issues -------------- +No. It is not necessary for super to become a keyword. super used with __call__ attributes -''''''''''''''''''''''''''''''''''' +----------------------------------- It was considered that it might be a problem that instantiating super instances the classic way, because calling it would lookup the __call__ attribute and @@ -155,315 +115,8 @@ assert a() == '__call__' assert a.__call__() == '__getattribute__' -In any case, with the renaming of ``__builtin__.super`` to -``__builtin__.__super__`` this issue goes away entirely. - - -Reference Implementation -======================== - -It is impossible to implement the above specification entirely in Python. This -reference implementation has the following differences to the specification: - -1. New ``super`` semantics are implemented using bytecode hacking. - -2. Assignment to ``super`` is not a ``SyntaxError``. Also see point #4. - -3. Classes must either use the metaclass ``autosuper_meta`` or inherit from - the base class ``autosuper`` to acquire the new ``super`` semantics. - -4. ``super`` is not an implicit local variable. In particular, for inner - functions to be able to use the super instance, there must be an assignment - of the form ``super = super`` in the method. - -The reference implementation assumes that it is being run on Python 2.5+. - -:: - - #!/usr/bin/env python - # - # autosuper.py - - from array import array - import dis - import new - import types - import __builtin__ - __builtin__.__super__ = __builtin__.super - del __builtin__.super - - # We need these for modifying bytecode - from opcode import opmap, HAVE_ARGUMENT, EXTENDED_ARG - - LOAD_GLOBAL = opmap['LOAD_GLOBAL'] - LOAD_NAME = opmap['LOAD_NAME'] - LOAD_CONST = opmap['LOAD_CONST'] - LOAD_FAST = opmap['LOAD_FAST'] - LOAD_ATTR = opmap['LOAD_ATTR'] - STORE_FAST = opmap['STORE_FAST'] - LOAD_DEREF = opmap['LOAD_DEREF'] - STORE_DEREF = opmap['STORE_DEREF'] - CALL_FUNCTION = opmap['CALL_FUNCTION'] - STORE_GLOBAL = opmap['STORE_GLOBAL'] - DUP_TOP = opmap['DUP_TOP'] - POP_TOP = opmap['POP_TOP'] - NOP = opmap['NOP'] - JUMP_FORWARD = opmap['JUMP_FORWARD'] - ABSOLUTE_TARGET = dis.hasjabs - - def _oparg(code, opcode_pos): - return code[opcode_pos+1] + (code[opcode_pos+2] << 8) - - def _bind_autosuper(func, cls): - co = func.func_code - name = func.func_name - newcode = array('B', co.co_code) - codelen = len(newcode) - newconsts = list(co.co_consts) - newvarnames = list(co.co_varnames) - - # Check if the global 'super' keyword is already present - try: - sn_pos = list(co.co_names).index('super') - except ValueError: - sn_pos = None - - # Check if the varname 'super' keyword is already present - try: - sv_pos = newvarnames.index('super') - except ValueError: - sv_pos = None - - # Check if the callvar 'super' keyword is already present - try: - sc_pos = list(co.co_cellvars).index('super') - except ValueError: - sc_pos = None - - # If 'super' isn't used anywhere in the function, we don't have anything to do - if sn_pos is None and sv_pos is None and sc_pos is None: - return func - - c_pos = None - s_pos = None - n_pos = None - - # Check if the 'cls_name' and 'super' objects are already in the constants - for pos, o in enumerate(newconsts): - if o is cls: - c_pos = pos - - if o is __super__: - s_pos = pos - - if o == name: - n_pos = pos - - # Add in any missing objects to constants and varnames - if c_pos is None: - c_pos = len(newconsts) - newconsts.append(cls) - - if n_pos is None: - n_pos = len(newconsts) - newconsts.append(name) - - if s_pos is None: - s_pos = len(newconsts) - newconsts.append(__super__) - - if sv_pos is None: - sv_pos = len(newvarnames) - newvarnames.append('super') - - # This goes at the start of the function. It is: - # - # super = __super__(cls, self) - # - # If 'super' is a cell variable, we store to both the - # local and cell variables (i.e. STORE_FAST and STORE_DEREF). - # - preamble = [ - LOAD_CONST, s_pos & 0xFF, s_pos >> 8, - LOAD_CONST, c_pos & 0xFF, c_pos >> 8, - LOAD_FAST, 0, 0, - CALL_FUNCTION, 2, 0, - ] - - if sc_pos is None: - # 'super' is not a cell variable - we can just use the local variable - preamble += [ - STORE_FAST, sv_pos & 0xFF, sv_pos >> 8, - ] - else: - # If 'super' is a cell variable, we need to handle LOAD_DEREF. - preamble += [ - DUP_TOP, - STORE_FAST, sv_pos & 0xFF, sv_pos >> 8, - STORE_DEREF, sc_pos & 0xFF, sc_pos >> 8, - ] - - preamble = array('B', preamble) - - # Bytecode for loading the local 'super' variable. - load_super = array('B', [ - LOAD_FAST, sv_pos & 0xFF, sv_pos >> 8, - ]) - - preamble_len = len(preamble) - need_preamble = False - i = 0 - - while i < codelen: - opcode = newcode[i] - need_load = False - remove_store = False - - if opcode == EXTENDED_ARG: - raise TypeError("Cannot use 'super' in function with EXTENDED_ARG opcode") - - # If the opcode is an absolute target it needs to be adjusted - # to take into account the preamble. - elif opcode in ABSOLUTE_TARGET: - oparg = _oparg(newcode, i) + preamble_len - newcode[i+1] = oparg & 0xFF - newcode[i+2] = oparg >> 8 - - # If LOAD_GLOBAL(super) or LOAD_NAME(super) then we want to change it into - # LOAD_FAST(super) - elif (opcode == LOAD_GLOBAL or opcode == LOAD_NAME) and _oparg(newcode, i) == sn_pos: - need_preamble = need_load = True - - # If LOAD_FAST(super) then we just need to add the preamble - elif opcode == LOAD_FAST and _oparg(newcode, i) == sv_pos: - need_preamble = need_load = True - - # If LOAD_DEREF(super) then we change it into LOAD_FAST(super) because - # it's slightly faster. - elif opcode == LOAD_DEREF and _oparg(newcode, i) == sc_pos: - need_preamble = need_load = True - - if need_load: - newcode[i:i+3] = load_super - - i += 1 - - if opcode >= HAVE_ARGUMENT: - i += 2 - - # No changes needed - get out. - if not need_preamble: - return func - - # Our preamble will have 3 things on the stack - co_stacksize = max(3, co.co_stacksize) - - # Conceptually, our preamble is on the `def` line. - co_lnotab = array('B', co.co_lnotab) - - if co_lnotab: - co_lnotab[0] += preamble_len - - co_lnotab = co_lnotab.tostring() - - # Our code consists of the preamble and the modified code. - codestr = (preamble + newcode).tostring() - - codeobj = new.code(co.co_argcount, len(newvarnames), co_stacksize, - co.co_flags, codestr, tuple(newconsts), co.co_names, - tuple(newvarnames), co.co_filename, co.co_name, - co.co_firstlineno, co_lnotab, co.co_freevars, - co.co_cellvars) - - func.func_code = codeobj - func.func_class = cls - return func - - class autosuper_meta(type): - def __init__(cls, name, bases, clsdict): - UnboundMethodType = types.UnboundMethodType - - for v in vars(cls): - o = getattr(cls, v) - if isinstance(o, UnboundMethodType): - _bind_autosuper(o.im_func, cls) - - class autosuper(object): - __metaclass__ = autosuper_meta - - if __name__ == '__main__': - class A(autosuper): - def f(self): - return 'A' - - class B(A): - def f(self): - return 'B' + super.f() - - class C(A): - def f(self): - def inner(): - return 'C' + super.f() - - # Needed to put 'super' into a cell - super = super - return inner() - - class D(B, C): - def f(self, arg=None): - var = None - return 'D' + super.f() - - assert D().f() == 'DBCA' - -Disassembly of B.f and C.f reveals the different preambles used when ``super`` -is simply a local variable compared to when it is used by an inner function. - -:: - - >>> dis.dis(B.f) - - 214 0 LOAD_CONST 4 () - 3 LOAD_CONST 2 () - 6 LOAD_FAST 0 (self) - 9 CALL_FUNCTION 2 - 12 STORE_FAST 1 (super) - - 215 15 LOAD_CONST 1 ('B') - 18 LOAD_FAST 1 (super) - 21 LOAD_ATTR 1 (f) - 24 CALL_FUNCTION 0 - 27 BINARY_ADD - 28 RETURN_VALUE - -:: - - >>> dis.dis(C.f) - - 218 0 LOAD_CONST 4 () - 3 LOAD_CONST 2 () - 6 LOAD_FAST 0 (self) - 9 CALL_FUNCTION 2 - 12 DUP_TOP - 13 STORE_FAST 1 (super) - 16 STORE_DEREF 0 (super) - - 219 19 LOAD_CLOSURE 0 (super) - 22 LOAD_CONST 1 () - 25 MAKE_CLOSURE 0 - 28 STORE_FAST 2 (inner) - - 223 31 LOAD_FAST 1 (super) - 34 STORE_DEREF 0 (super) - - 224 37 LOAD_FAST 2 (inner) - 40 CALL_FUNCTION 0 - 43 RETURN_VALUE - -Note that in the final implementation, the preamble would not be part of the -bytecode of the method, but would occur immediately following unpacking of -parameters. - +In any case, this issue goes away entirely because classic calls to +``super(, )`` are still supported with the same meaning. Alternative Proposals ===================== @@ -491,16 +144,6 @@ This proposal relies on sys._getframe(), which is not appropriate for anything except a prototype implementation. - -super(__this_class__, self) ---------------------------- - -This is nearly an anti-proposal, as it basically relies on the acceptance of -the __this_class__ PEP, which proposes a special name that would always be -bound to the class within which it is used. If that is accepted, __this_class__ -could simply be used instead of the class' name explicitly, solving the name -binding issues [2]_. - self.__super__.foo(\*args) -------------------------- @@ -527,14 +170,6 @@ instance, and if any of the alternatives were pushed into the spotlight, I would want it to be this one. -super or super() ----------------- - -This proposal leaves no room for different names, signatures, or application -to other classes, or instances. A way to allow some similar use alongside the -normal proposal would be favorable, encouraging good design of multiple -inheritance trees and compatible methods. - super(\*p, \*\*kw) ------------------ @@ -561,6 +196,8 @@ History ======= +12-Mar-2009 - Updated to reflect the current state of implementation. + 29-Apr-2007 - Changed title from "Super As A Keyword" to "New Super" - Updated much of the language and added a terminology section for clarification in confusing places. From python-checkins at python.org Wed Mar 11 20:43:05 2009 From: python-checkins at python.org (martin.v.loewis) Date: Wed, 11 Mar 2009 20:43:05 +0100 (CET) Subject: [Python-checkins] r70313 - tracker/instances/python-dev/html/issue.item.html Message-ID: <20090311194305.978561E4002@bag.python.org> Author: martin.v.loewis Date: Wed Mar 11 20:43:05 2009 New Revision: 70313 Log: Sort issues by creation. Modified: tracker/instances/python-dev/html/issue.item.html Modified: tracker/instances/python-dev/html/issue.item.html ============================================================================== --- tracker/instances/python-dev/html/issue.item.html (original) +++ tracker/instances/python-dev/html/issue.item.html Wed Mar 11 20:43:05 2009 @@ -227,7 +227,7 @@ - + From python-checkins at python.org Wed Mar 11 20:43:55 2009 From: python-checkins at python.org (martin.v.loewis) Date: Wed, 11 Mar 2009 20:43:55 +0100 (CET) Subject: [Python-checkins] r70314 - tracker/instances/jython/html/issue.item.html Message-ID: <20090311194355.6186B1E4002@bag.python.org> Author: martin.v.loewis Date: Wed Mar 11 20:43:55 2009 New Revision: 70314 Log: Issue #225: Sort messages by creation. Modified: tracker/instances/jython/html/issue.item.html Modified: tracker/instances/jython/html/issue.item.html ============================================================================== --- tracker/instances/jython/html/issue.item.html (original) +++ tracker/instances/jython/html/issue.item.html Wed Mar 11 20:43:55 2009 @@ -234,7 +234,7 @@
Messages
msg (view)
- + From python-checkins at python.org Thu Mar 12 01:25:05 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 01:25:05 +0100 (CET) Subject: [Python-checkins] r70315 - python/trunk/Doc/reference/datamodel.rst Message-ID: <20090312002505.2AE3D1E4014@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 01:25:03 2009 New Revision: 70315 Log: Add reference to solution for a commonly asked question. Modified: python/trunk/Doc/reference/datamodel.rst Modified: python/trunk/Doc/reference/datamodel.rst ============================================================================== --- python/trunk/Doc/reference/datamodel.rst (original) +++ python/trunk/Doc/reference/datamodel.rst Thu Mar 12 01:25:03 2009 @@ -1346,6 +1346,9 @@ Arguments to rich comparison methods are never coerced. + To automatically generate ordering operations from a single root operation, + see the `Total Ordering recipe in the ASPN cookbook + `_\. .. method:: object.__cmp__(self, other) From python-checkins at python.org Thu Mar 12 01:25:29 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 01:25:29 +0100 (CET) Subject: [Python-checkins] r70316 - python/branches/py3k/Doc/reference/datamodel.rst Message-ID: <20090312002529.B9BA01E400C@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 01:25:29 2009 New Revision: 70316 Log: Add reference to solution for a commonly asked question. Modified: python/branches/py3k/Doc/reference/datamodel.rst Modified: python/branches/py3k/Doc/reference/datamodel.rst ============================================================================== --- python/branches/py3k/Doc/reference/datamodel.rst (original) +++ python/branches/py3k/Doc/reference/datamodel.rst Thu Mar 12 01:25:29 2009 @@ -1198,6 +1198,9 @@ Arguments to rich comparison methods are never coerced. + To automatically generate ordering operations from a single root operation, + see the `Total Ordering recipe in the ASPN cookbook + `_\. .. method:: object.__hash__(self) From python-checkins at python.org Thu Mar 12 01:29:45 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 01:29:45 +0100 (CET) Subject: [Python-checkins] r70317 - python/branches/py3k/Doc/library/itertools.rst Message-ID: <20090312002945.04ACC1E4002@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 01:29:44 2009 New Revision: 70317 Log: Issue 5477: Fix buglet in the itertools documentation. Modified: python/branches/py3k/Doc/library/itertools.rst Modified: python/branches/py3k/Doc/library/itertools.rst ============================================================================== --- python/branches/py3k/Doc/library/itertools.rst (original) +++ python/branches/py3k/Doc/library/itertools.rst Thu Mar 12 01:29:44 2009 @@ -26,9 +26,10 @@ sequence ``f(0), f(1), ...``. But, this effect can be achieved in Python by combining :func:`map` and :func:`count` to form ``map(f, count())``. -The tools also work well with the high-speed functions in the :mod:`operator` -module. For example, the plus-operator can be mapped across two vectors to -form an efficient dot-product: ``sum(map(operator.add, vector1, vector2))``. +These tools and their built-in counterparts also work well with the high-speed +functions in the :mod:`operator` module. For example, the multiplication +operator can be mapped across two vectors to form an efficient dot-product: +``sum(map(operator.mul, vector1, vector2))``. **Infinite Iterators:** From python-checkins at python.org Thu Mar 12 01:31:32 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 01:31:32 +0100 (CET) Subject: [Python-checkins] r70318 - python/branches/release30-maint/Doc/library/itertools.rst Message-ID: <20090312003132.6A4B01E4002@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 01:31:32 2009 New Revision: 70318 Log: Issue 5477: Fix buglet in the itertools documentation. Modified: python/branches/release30-maint/Doc/library/itertools.rst Modified: python/branches/release30-maint/Doc/library/itertools.rst ============================================================================== --- python/branches/release30-maint/Doc/library/itertools.rst (original) +++ python/branches/release30-maint/Doc/library/itertools.rst Thu Mar 12 01:31:32 2009 @@ -26,9 +26,10 @@ sequence ``f(0), f(1), ...``. But, this effect can be achieved in Python by combining :func:`map` and :func:`count` to form ``map(f, count())``. -The tools also work well with the high-speed functions in the :mod:`operator` -module. For example, the plus-operator can be mapped across two vectors to -form an efficient dot-product: ``sum(map(operator.add, vector1, vector2))``. +These tools and their built-in counterparts also work well with the high-speed +functions in the :mod:`operator` module. For example, the multiplication +operator can be mapped across two vectors to form an efficient dot-product: +``sum(map(operator.mul, vector1, vector2))``. **Infinite Iterators:** From python-checkins at python.org Thu Mar 12 01:31:58 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 01:31:58 +0100 (CET) Subject: [Python-checkins] r70319 - python/trunk/Doc/library/itertools.rst Message-ID: <20090312003158.C972C1E4002@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 01:31:58 2009 New Revision: 70319 Log: Issue 5477: Fix buglet in the itertools documentation. Modified: python/trunk/Doc/library/itertools.rst Modified: python/trunk/Doc/library/itertools.rst ============================================================================== --- python/trunk/Doc/library/itertools.rst (original) +++ python/trunk/Doc/library/itertools.rst Thu Mar 12 01:31:58 2009 @@ -28,9 +28,10 @@ :func:`count` which can be combined to form ``imap(f, count())`` to produce an equivalent result. -The tools also work well with the high-speed functions in the :mod:`operator` -module. For example, the plus-operator can be mapped across two vectors to -form an efficient dot-product: ``sum(imap(operator.add, vector1, vector2))``. +These tools and their built-in counterparts also work well with the high-speed +functions in the :mod:`operator` module. For example, the multiplication +operator can be mapped across two vectors to form an efficient dot-product: +``sum(imap(operator.mul, vector1, vector2))``. **Infinite Iterators:** From python-checkins at python.org Thu Mar 12 01:35:05 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 01:35:05 +0100 (CET) Subject: [Python-checkins] r70320 - python/branches/release26-maint/Doc/library/itertools.rst Message-ID: <20090312003505.C51DF1E4002@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 01:35:05 2009 New Revision: 70320 Log: Issue 5477: Fix buglet in the itertools documentation. Modified: python/branches/release26-maint/Doc/library/itertools.rst Modified: python/branches/release26-maint/Doc/library/itertools.rst ============================================================================== --- python/branches/release26-maint/Doc/library/itertools.rst (original) +++ python/branches/release26-maint/Doc/library/itertools.rst Thu Mar 12 01:35:05 2009 @@ -28,9 +28,10 @@ :func:`count` which can be combined to form ``imap(f, count())`` to produce an equivalent result. -The tools also work well with the high-speed functions in the :mod:`operator` -module. For example, the plus-operator can be mapped across two vectors to -form an efficient dot-product: ``sum(imap(operator.add, vector1, vector2))``. +These tools and their built-in counterparts also work well with the high-speed +functions in the :mod:`operator` module. For example, the multiplication +operator can be mapped across two vectors to form an efficient dot-product: +``sum(imap(operator.mul, vector1, vector2))``. **Infinite Iterators:** From buildbot at python.org Thu Mar 12 01:43:27 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 12 Mar 2009 00:43:27 +0000 Subject: [Python-checkins] buildbot failure in x86 OpenBSD 3.x Message-ID: <20090312004328.29DB31E4037@bag.python.org> The Buildbot has detected a new failure of x86 OpenBSD 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20OpenBSD%203.x/builds/308 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: cortesi Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: antoine.pitrou,benjamin.peterson,brett.cannon,guilherme.polo,hirokazu.yamamoto,raymond.hettinger,ronald.oussoren,tarek.ziade BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/home/buildbot/buildarea/3.x.cortesi/build/Lib/test/test_socket.py", line 1107, in testInterruptedTimeout foo = self.serv.accept() test.test_socket.Alarm Traceback (most recent call last): File "/home/buildbot/buildarea/3.x.cortesi/build/Lib/test/test_socket.py", line 1121, in testInterruptedTimeout self.fail("got Alarm in wrong place") AssertionError: got Alarm in wrong place sincerely, -The Buildbot From buildbot at python.org Thu Mar 12 03:08:06 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 12 Mar 2009 02:08:06 +0000 Subject: [Python-checkins] buildbot failure in x86 OpenBSD 3.0 Message-ID: <20090312020807.09B161E4002@bag.python.org> The Buildbot has detected a new failure of x86 OpenBSD 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20OpenBSD%203.0/builds/146 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: cortesi Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: benjamin.peterson,guilherme.polo,hirokazu.yamamoto,raymond.hettinger,ronald.oussoren,tarek.ziade BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Thu Mar 12 13:43:24 2009 From: python-checkins at python.org (david.goodger) Date: Thu, 12 Mar 2009 13:43:24 +0100 (CET) Subject: [Python-checkins] r70321 - peps/trunk/pep-0378.txt Message-ID: <20090312124324.907911E4002@bag.python.org> Author: david.goodger Date: Thu Mar 12 13:43:24 2009 New Revision: 70321 Log: added PEP 378, "Format Specifier for Thousands Separator", by Raymond Hettinger Added: peps/trunk/pep-0378.txt (contents, props changed) Added: peps/trunk/pep-0378.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-0378.txt Thu Mar 12 13:43:24 2009 @@ -0,0 +1,142 @@ +PEP: 378 +Title: Format Specifier for Thousands Separator +Version: $Revision$ +Last-Modified: $Date$ +Author: Raymond Hettinger +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 12-Mar-2009 +Post-History: 12-Mar-2009 + + +Motivation +========== + +Provide a simple, non-locale aware way to format a number +with a thousands separator. + +Adding thousands separators is one of the simplest ways to +improve the professional appearance and readability of output +exposed to end users. + +In the finance world, output with commas is the norm. Finance +users and non-professional programmers find the locale +approach to be frustrating, arcane and non-obvious. + +It is not the goal to replace locale or to accommodate every +possible convention. The goal is to make a common task easier +for many users. + + +Current Version of the Mini-Language +==================================== + +* `Python 2.6 docs`_ + + .. _Python 2.6 docs: http://docs.python.org/library/string.html#formatstrings + +* PEP 3101 Advanced String Formatting + + +Research so far +=============== + +Scanning the web, I've found that thousands separators are +usually one of COMMA, DOT, SPACE, or UNDERSCORE. +When a COMMA is the decimal separator, the thousands separator +is typically a DOT or SPACE (see examples from Denis Spir). + +James Knight observed that Indian/Pakistani numbering systems +group by hundreds. Ben Finney noted that Chinese group by +ten-thousands. Eric Smith pointed-out that these are already +handled by the "n" specifier in the locale module (albiet only +for integers). + +Visual Basic and its brethren (like MS Excel) use a completely +different style and have ultra-flexible custom format +specifiers like: "_($* #,##0_)". + + +Proposal I (from Nick Coghlan) +============================== + +A comma will be added to the format() specifier mini-language: + +[[fill]align][sign][#][0][width][,][.precision][type] + +The ',' option indicates that commas should be included in the +output as a thousands separator. As with locales which do not +use a period as the decimal point, locales which use a +different convention for digit separation will need to use the +locale module to obtain appropriate formatting. + +The proposal works well with floats, ints, and decimals. +It also allows easy substitution for other separators. +For example:: + + format(n, "6,f").replace(",", "_") + +This technique is completely general but it is awkward in the +one case where the commas and periods need to be swapped:: + + format(n, "6,f").replace(",", "X").replace(".", ",").replace("X", ".") + + +Proposal II (to meet Antoine Pitrou's request) +============================================== + +Make both the thousands separator and decimal separator user +specifiable but not locale aware. For simplicity, limit the +choices to a comma, period, space, or underscore. + +[[fill]align][sign][#][0][width][T[tsep]][dsep precision][type] + +Examples:: + + format(1234, "8.1f") --> ' 1234.0' + format(1234, "8,1f") --> ' 1234,0' + format(1234, "8T.,1f") --> ' 1.234,0' + format(1234, "8T .f") --> ' 1 234,0' + format(1234, "8d") --> ' 1234' + format(1234, "8T,d") --> ' 1,234' + +This proposal meets mosts needs (except for people wanting +grouping for hundreds or ten-thousands), but it comes at the +expense of being a little more complicated to learn and +remember. Also, it makes it more challenging to write custom +__format__ methods that follow the format specification +mini-language. + +No change is proposed for the local module. + + +Other Ideas +=========== + +* Lie Ryan suggested a convenience function of the form:: + + create_format(self, type='i', base=16, seppos=4, sep=':', \ + charset='0123456789abcdef', maxwidth=32, \ + minwidth=32, pad='0') + +* Eric Smith would like the C version of the mini-language + parser to be exposed. That would make it easier to write + custom __format__ methods. + + +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 Thu Mar 12 13:48:58 2009 From: python-checkins at python.org (david.goodger) Date: Thu, 12 Mar 2009 13:48:58 +0100 (CET) Subject: [Python-checkins] r70322 - peps/trunk/pep-0378.txt Message-ID: <20090312124858.DCA941E4002@bag.python.org> Author: david.goodger Date: Thu Mar 12 13:48:58 2009 New Revision: 70322 Log: conform to other examples Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Thu Mar 12 13:48:58 2009 @@ -2,7 +2,7 @@ Title: Format Specifier for Thousands Separator Version: $Revision$ Last-Modified: $Date$ -Author: Raymond Hettinger +Author: Raymond Hettinger Status: Draft Type: Standards Track Content-Type: text/x-rst From python-checkins at python.org Thu Mar 12 14:03:14 2009 From: python-checkins at python.org (david.goodger) Date: Thu, 12 Mar 2009 14:03:14 +0100 (CET) Subject: [Python-checkins] r70323 - peps/trunk/pep-0378.txt Message-ID: <20090312130314.6C39D1E4002@bag.python.org> Author: david.goodger Date: Thu Mar 12 14:03:14 2009 New Revision: 70323 Log: backslashes not necessary inside parentheses Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Thu Mar 12 14:03:14 2009 @@ -116,8 +116,8 @@ * Lie Ryan suggested a convenience function of the form:: - create_format(self, type='i', base=16, seppos=4, sep=':', \ - charset='0123456789abcdef', maxwidth=32, \ + create_format(self, type='i', base=16, seppos=4, sep=':', + charset='0123456789abcdef', maxwidth=32, minwidth=32, pad='0') * Eric Smith would like the C version of the mini-language From python-checkins at python.org Thu Mar 12 17:17:07 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 17:17:07 +0100 (CET) Subject: [Python-checkins] r70324 - peps/trunk/pep-0378.txt Message-ID: <20090312161707.52CFC1E4002@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 17:17:07 2009 New Revision: 70324 Log: Fix typo. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Thu Mar 12 17:17:07 2009 @@ -97,7 +97,7 @@ format(1234, "8.1f") --> ' 1234.0' format(1234, "8,1f") --> ' 1234,0' format(1234, "8T.,1f") --> ' 1.234,0' - format(1234, "8T .f") --> ' 1 234,0' + format(1234, "8T ,f") --> ' 1 234,0' format(1234, "8d") --> ' 1234' format(1234, "8T,d") --> ' 1,234' From python-checkins at python.org Thu Mar 12 18:28:58 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 18:28:58 +0100 (CET) Subject: [Python-checkins] r70325 - peps/trunk/pep-0378.txt Message-ID: <20090312172858.04C3D1E402D@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 18:28:57 2009 New Revision: 70325 Log: Add research on the Common Lisp approach. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Thu Mar 12 18:28:57 2009 @@ -57,6 +57,13 @@ different style and have ultra-flexible custom format specifiers like: "_($* #,##0_)". +`Common Lisp`_ uses a COLON before the type specifier to emit a COMMA +as a thousands separator:: + + (format nil "The answer is ~:D." 229345007) + => "The answer is 229,345,007." + +.. _`Common Lisp`: http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node200.html Proposal I (from Nick Coghlan) ============================== From python-checkins at python.org Thu Mar 12 18:46:29 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 18:46:29 +0100 (CET) Subject: [Python-checkins] r70326 - peps/trunk/pep-0378.txt Message-ID: <20090312174629.C229D1E403A@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 18:46:29 2009 New Revision: 70326 Log: More detail on the Common Lisp approach. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Thu Mar 12 18:46:29 2009 @@ -57,11 +57,15 @@ different style and have ultra-flexible custom format specifiers like: "_($* #,##0_)". -`Common Lisp`_ uses a COLON before the type specifier to emit a COMMA -as a thousands separator:: +`Common Lisp`_ uses a COLON before the ``~D`` decimal type specifier to +emit a COMMA as a thousands separator. The general form of ``~D`` is +``~mincol,padchar,commachar,commaintervalD``. The *padchar* defaults +to SPACE. The *commachar* defaults to COLON. The *commainterval* +defaults to three. - (format nil "The answer is ~:D." 229345007) - => "The answer is 229,345,007." +:: + + (format nil "~:D" 229345007) => "229,345,007" .. _`Common Lisp`: http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node200.html From python-checkins at python.org Thu Mar 12 18:50:47 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 18:50:47 +0100 (CET) Subject: [Python-checkins] r70327 - peps/trunk/pep-0378.txt Message-ID: <20090312175047.D620F1E401A@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 18:50:47 2009 New Revision: 70327 Log: Minor typos and formatting. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Thu Mar 12 18:50:47 2009 @@ -55,7 +55,9 @@ Visual Basic and its brethren (like MS Excel) use a completely different style and have ultra-flexible custom format -specifiers like: "_($* #,##0_)". +specifiers like:: + + "_($* #,##0_)". `Common Lisp`_ uses a COLON before the ``~D`` decimal type specifier to emit a COMMA as a thousands separator. The general form of ``~D`` is @@ -119,7 +121,7 @@ __format__ methods that follow the format specification mini-language. -No change is proposed for the local module. +No change is proposed for the locale module. Other Ideas From python-checkins at python.org Thu Mar 12 19:20:21 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 19:20:21 +0100 (CET) Subject: [Python-checkins] r70328 - peps/trunk/pep-0378.txt Message-ID: <20090312182021.7DA341E4002@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 19:20:21 2009 New Revision: 70328 Log: Missing header. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Thu Mar 12 19:20:21 2009 @@ -7,6 +7,7 @@ Type: Standards Track Content-Type: text/x-rst Created: 12-Mar-2009 +Python-Version: 2.7 and 3.1 Post-History: 12-Mar-2009 From python-checkins at python.org Thu Mar 12 20:20:00 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 20:20:00 +0100 (CET) Subject: [Python-checkins] r70329 - peps/trunk/pep-0378.txt Message-ID: <20090312192000.A43261E4002@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 20:20:00 2009 New Revision: 70329 Log: Add research on what COBOL does. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Thu Mar 12 20:20:00 2009 @@ -60,6 +60,10 @@ "_($* #,##0_)". +COBOL uses picture clauses like:: + + PIC $***,**9.99CR + `Common Lisp`_ uses a COLON before the ``~D`` decimal type specifier to emit a COMMA as a thousands separator. The general form of ``~D`` is ``~mincol,padchar,commachar,commaintervalD``. The *padchar* defaults From python-checkins at python.org Thu Mar 12 20:36:28 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 20:36:28 +0100 (CET) Subject: [Python-checkins] r70330 - peps/trunk/pep-0378.txt Message-ID: <20090312193628.6D1731E4013@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 20:36:28 2009 New Revision: 70330 Log: Add research on what C Sharp does. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Thu Mar 12 20:36:28 2009 @@ -60,10 +60,12 @@ "_($* #,##0_)". -COBOL uses picture clauses like:: +`COBOL`_ uses picture clauses like:: PIC $***,**9.99CR +.. _`COBOL`: http://en.wikipedia.org/wiki/Cobol + `Common Lisp`_ uses a COLON before the ``~D`` decimal type specifier to emit a COMMA as a thousands separator. The general form of ``~D`` is ``~mincol,padchar,commachar,commaintervalD``. The *padchar* defaults @@ -76,6 +78,17 @@ .. _`Common Lisp`: http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node200.html +`C-Sharp`_ provides both styles (picture formatting and type specifiers). +The type specifier approach is locale aware. The picture formatting only +offers a COMMA as a thousands separator:: + + String.Format("{0:c}", 12400) ==> "$12,400" + String.Format("{0:n}", 12400) ==> "12,400" + String.Format("{0:0,0}", 12400) ==> "12,400" + +.. _`C-Sharp`: http://blog.stevex.net/index.php/string-formatting-in-csharp/ + + Proposal I (from Nick Coghlan) ============================== From python-checkins at python.org Thu Mar 12 23:01:40 2009 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Mar 2009 23:01:40 +0100 (CET) Subject: [Python-checkins] r70331 - python/branches/py3k/Lib/importlib/__init__.py Message-ID: <20090312220140.513B01E4002@bag.python.org> Author: brett.cannon Date: Thu Mar 12 23:01:40 2009 New Revision: 70331 Log: Define importlib.__init__.__all__. Modified: python/branches/py3k/Lib/importlib/__init__.py Modified: python/branches/py3k/Lib/importlib/__init__.py ============================================================================== --- python/branches/py3k/Lib/importlib/__init__.py (original) +++ python/branches/py3k/Lib/importlib/__init__.py Thu Mar 12 23:01:40 2009 @@ -18,13 +18,15 @@ http://www.python.org/dev/peps/pep-0328 """ +__all__ = ['__import__', 'import_module'] + from . import _bootstrap -# XXX Temporary functions that should eventually be removed. import os import re import tokenize +# XXX Temporary functions that should eventually be removed. def _set__import__(): """Set __import__ to an instance of Import.""" global original__import__ From python-checkins at python.org Thu Mar 12 23:07:17 2009 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Mar 2009 23:07:17 +0100 (CET) Subject: [Python-checkins] r70332 - python/branches/py3k/Lib/importlib/_bootstrap.py Message-ID: <20090312220717.8E5161E400C@bag.python.org> Author: brett.cannon Date: Thu Mar 12 23:07:17 2009 New Revision: 70332 Log: Make utility code in importlib._bootstrap private. Modified: python/branches/py3k/Lib/importlib/_bootstrap.py Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Thu Mar 12 23:07:17 2009 @@ -56,7 +56,7 @@ def _path_without_ext(path, ext_type): """Replacement for os.path.splitext()[0].""" - for suffix in suffix_list(ext_type): + for suffix in _suffix_list(ext_type): if path.endswith(suffix): return path[:-len(suffix)] else: @@ -76,7 +76,7 @@ return _path_join(_os.getcwd(), path) -class closing: +class _closing: """Simple replacement for contextlib.closing.""" @@ -90,7 +90,7 @@ self.obj.close() -def wrap(new, old): +def _wrap(new, old): """Simple substitute for functools.wraps.""" for replace in ['__module__', '__name__', '__doc__']: setattr(new, replace, getattr(old, replace)) @@ -106,7 +106,7 @@ if not hasattr(module, '__path__'): module.__package__ = module.__package__.rpartition('.')[0] return module - wrap(wrapper, fxn) + _wrap(wrapper, fxn) return wrapper @@ -117,7 +117,7 @@ if not hasattr(module, '__loader__'): module.__loader__ = self return module - wrap(wrapper, fxn) + _wrap(wrapper, fxn) return wrapper @@ -187,7 +187,7 @@ raise -def chained_path_hook(*path_hooks): +def _chained_path_hook(*path_hooks): """Create a closure which sequentially checks path hooks to see which ones (if any) can work with a path.""" def path_hook(entry): @@ -203,12 +203,12 @@ if not finders: raise ImportError("no finder found") else: - return ChainedFinder(*finders) + return _ChainedFinder(*finders) return path_hook -class ChainedFinder: +class _ChainedFinder: """Finder that sequentially calls other finders.""" @@ -224,7 +224,7 @@ return None -def check_name(method): +def _check_name(method): """Decorator to verify that the module being requested matches the one the loader can handle. @@ -236,7 +236,7 @@ if self._name != name: raise ImportError("loader cannot handle %s" % name) return method(self, name, *args, **kwargs) - wrap(inner, method) + _wrap(inner, method) return inner @@ -260,7 +260,7 @@ if is_pkg: raise ValueError("extension modules cannot be packages") - @check_name + @_check_name @set_package @set_loader def load_module(self, fullname): @@ -273,23 +273,23 @@ del sys.modules[fullname] raise - @check_name + @_check_name def is_package(self, fullname): """Return False as an extension module can never be a package.""" return False - @check_name + @_check_name def get_code(self, fullname): """Return None as an extension module cannot create a code object.""" return None - @check_name + @_check_name def get_source(self, fullname): """Return None as extension modules have no source code.""" return None -def suffix_list(suffix_type): +def _suffix_list(suffix_type): """Return a list of file suffixes based on the imp file type.""" return [suffix[0] for suffix in imp.get_suffixes() if suffix[2] == suffix_type] @@ -323,7 +323,7 @@ if not is_reload: del sys.modules[fullname] raise - wrap(decorated, fxn) + _wrap(decorated, fxn) return decorated @@ -484,21 +484,21 @@ def _find_path(self, ext_type): """Find a path from the base path and the specified extension type that exists, returning None if one is not found.""" - for suffix in suffix_list(ext_type): + for suffix in _suffix_list(ext_type): path = self._base_path + suffix if _path_exists(path): return path else: return None - @check_name + @_check_name def source_path(self, fullname): """Return the path to an existing source file for the module, or None if one cannot be found.""" # Not a property so that it is easy to override. return self._find_path(imp.PY_SOURCE) - @check_name + @_check_name def get_source(self, fullname): """Return the source for the module as a string. @@ -510,7 +510,7 @@ if source_path is None: return None import tokenize - with closing(_io.FileIO(source_path, 'r')) as file: # Assuming bytes. + with _closing(_io.FileIO(source_path, 'r')) as file: # Assuming bytes. encoding, lines = tokenize.detect_encoding(file.readline) # XXX Will fail when passed to compile() if the encoding is # anything other than UTF-8. @@ -521,7 +521,7 @@ """Return the data from path as raw bytes.""" return _io.FileIO(path, 'r').read() # Assuming bytes. - @check_name + @_check_name def is_package(self, fullname): """Return a boolean based on whether the module is a package. @@ -536,7 +536,7 @@ """Load a module from a source or bytecode file.""" - @check_name + @_check_name def source_mtime(self, name): """Return the modification time of the source for the specified module.""" @@ -545,14 +545,14 @@ return None return int(_os.stat(source_path).st_mtime) - @check_name + @_check_name def bytecode_path(self, fullname): """Return the path to a bytecode file, or None if one does not exist.""" # Not a property for easy overriding. return self._find_path(imp.PY_COMPILED) - @check_name + @_check_name def write_bytecode(self, name, data): """Write out 'data' for the specified module, returning a boolean signifying if the write-out actually occurred. @@ -563,10 +563,10 @@ """ bytecode_path = self.bytecode_path(name) if not bytecode_path: - bytecode_path = self._base_path + suffix_list(imp.PY_COMPILED)[0] + bytecode_path = self._base_path + _suffix_list(imp.PY_COMPILED)[0] file = _io.FileIO(bytecode_path, 'w') # Assuming bytes. try: - with closing(file) as bytecode_file: + with _closing(file) as bytecode_file: bytecode_file.write(data) return True except IOError as exc: @@ -645,7 +645,7 @@ def __init__(self, path_entry): # Assigning to _suffixes here instead of at the class level because # imp is not imported at the time of class creation. - self._suffixes = suffix_list(imp.C_EXTENSION) + self._suffixes = _suffix_list(imp.C_EXTENSION) super().__init__(path_entry) @@ -660,7 +660,7 @@ # Lack of imp during class creation means _suffixes is set here. # Make sure that Python source files are listed first! Needed for an # optimization by the loader. - self._suffixes = suffix_list(imp.PY_SOURCE) + self._suffixes = _suffix_list(imp.PY_SOURCE) super().__init__(path_entry) @@ -672,7 +672,7 @@ def __init__(self, path_entry): super().__init__(path_entry) - self._suffixes += suffix_list(imp.PY_COMPILED) + self._suffixes += _suffix_list(imp.PY_COMPILED) class PathFinder: @@ -738,7 +738,7 @@ return None -_DEFAULT_PATH_HOOK = chained_path_hook(ExtensionFileFinder, PyPycFileFinder) +_DEFAULT_PATH_HOOK = _chained_path_hook(ExtensionFileFinder, PyPycFileFinder) class _DefaultPathFinder(PathFinder): @@ -761,7 +761,7 @@ return super()._path_importer_cache(path, _DEFAULT_PATH_HOOK) -class ImportLockContext: +class _ImportLockContext: """Context manager for the import lock.""" @@ -806,7 +806,7 @@ name = "{0}.{1}".format(package[:dot], name) else: name = package[:dot] - with ImportLockContext(): + with _ImportLockContext(): try: return sys.modules[name] except KeyError: From python-checkins at python.org Thu Mar 12 23:28:55 2009 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Mar 2009 23:28:55 +0100 (CET) Subject: [Python-checkins] r70333 - python/branches/py3k/Lib/importlib/_bootstrap.py Message-ID: <20090312222855.BB9C21E4002@bag.python.org> Author: brett.cannon Date: Thu Mar 12 23:28:55 2009 New Revision: 70333 Log: Do a little bit of reorganization on importlib._bootstrap. Modified: python/branches/py3k/Lib/importlib/_bootstrap.py Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Thu Mar 12 23:28:55 2009 @@ -16,6 +16,8 @@ # anything specified at the class level. +# Bootstrap-related code ###################################################### + # XXX Could also expose Modules/getpath.c:joinpath() def _path_join(*args): """Replacement for os.path.join.""" @@ -97,6 +99,8 @@ new.__dict__.update(old.__dict__) +# Finder/loader utility code ################################################## + def set_package(fxn): """Set __package__ on the returned module.""" def wrapper(*args, **kwargs): @@ -121,6 +125,56 @@ return wrapper +def module_for_loader(fxn): + """Decorator to handle selecting the proper module for loaders. + + Decorated modules are passed the module to use instead of the module name. + The module is either from sys.modules if it already exists (for reloading) + or is a new module which has __name__ set. If any exception is raised by + the decorated method and the decorator added a module to sys.modules, then + the module is deleted from sys.modules. + + The decorator assumes that the decorated method takes self/cls as a first + argument and the module as the second argument. + + """ + def decorated(self, fullname): + module = sys.modules.get(fullname) + is_reload = bool(module) + if not is_reload: + # This must be done before open() is called as the 'io' module + # implicitly imports 'locale' and would otherwise trigger an + # infinite loop. + module = imp.new_module(fullname) + sys.modules[fullname] = module + try: + return fxn(self, module) + except: + if not is_reload: + del sys.modules[fullname] + raise + _wrap(decorated, fxn) + return decorated + + +def _check_name(method): + """Decorator to verify that the module being requested matches the one the + loader can handle. + + The first argument (self) must define _name which the second argument is + comapred against. If the comparison fails then ImportError is raised. + + """ + def inner(self, name, *args, **kwargs): + if self._name != name: + raise ImportError("loader cannot handle %s" % name) + return method(self, name, *args, **kwargs) + _wrap(inner, method) + return inner + + +# Finders/loaders ############################################################# + class BuiltinImporter: """Meta path loader for built-in modules. @@ -224,21 +278,6 @@ return None -def _check_name(method): - """Decorator to verify that the module being requested matches the one the - loader can handle. - - The first argument (self) must define _name which the second argument is - comapred against. If the comparison fails then ImportError is raised. - - """ - def inner(self, name, *args, **kwargs): - if self._name != name: - raise ImportError("loader cannot handle %s" % name) - return method(self, name, *args, **kwargs) - _wrap(inner, method) - return inner - class _ExtensionFileLoader: @@ -295,37 +334,6 @@ if suffix[2] == suffix_type] -def module_for_loader(fxn): - """Decorator to handle selecting the proper module for loaders. - - Decorated modules are passed the module to use instead of the module name. - The module is either from sys.modules if it already exists (for reloading) - or is a new module which has __name__ set. If any exception is raised by - the decorated method and the decorator added a module to sys.modules, then - the module is deleted from sys.modules. - - The decorator assumes that the decorated method takes self/cls as a first - argument and the module as the second argument. - - """ - def decorated(self, fullname): - module = sys.modules.get(fullname) - is_reload = bool(module) - if not is_reload: - # This must be done before open() is called as the 'io' module - # implicitly imports 'locale' and would otherwise trigger an - # infinite loop. - module = imp.new_module(fullname) - sys.modules[fullname] = module - try: - return fxn(self, module) - except: - if not is_reload: - del sys.modules[fullname] - raise - _wrap(decorated, fxn) - return decorated - class PyLoader: @@ -738,6 +746,21 @@ return None +# Import itself ############################################################### + +class _ImportLockContext: + + """Context manager for the import lock.""" + + def __enter__(self): + """Acquire the import lock.""" + imp.acquire_lock() + + def __exit__(self, exc_type, exc_value, exc_traceback): + """Release the import lock regardless of any raised exceptions.""" + imp.release_lock() + + _DEFAULT_PATH_HOOK = _chained_path_hook(ExtensionFileFinder, PyPycFileFinder) class _DefaultPathFinder(PathFinder): @@ -761,18 +784,6 @@ return super()._path_importer_cache(path, _DEFAULT_PATH_HOOK) -class _ImportLockContext: - - """Context manager for the import lock.""" - - def __enter__(self): - """Acquire the import lock.""" - imp.acquire_lock() - - def __exit__(self, exc_type, exc_value, exc_traceback): - """Release the import lock regardless of any raised exceptions.""" - imp.release_lock() - _IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, _DefaultPathFinder] From python-checkins at python.org Thu Mar 12 23:36:04 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 12 Mar 2009 23:36:04 +0100 (CET) Subject: [Python-checkins] r70334 - peps/trunk/pep-0378.txt Message-ID: <20090312223604.1DDDF1E4002@bag.python.org> Author: raymond.hettinger Date: Thu Mar 12 23:36:03 2009 New Revision: 70334 Log: Neaten-up examples. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Thu Mar 12 23:36:03 2009 @@ -82,9 +82,8 @@ The type specifier approach is locale aware. The picture formatting only offers a COMMA as a thousands separator:: - String.Format("{0:c}", 12400) ==> "$12,400" - String.Format("{0:n}", 12400) ==> "12,400" - String.Format("{0:0,0}", 12400) ==> "12,400" + String.Format("{0:n}", 12400) ==> "12,400" + String.Format("{0:0,0}", 12400) ==> "12,400" .. _`C-Sharp`: http://blog.stevex.net/index.php/string-formatting-in-csharp/ @@ -106,7 +105,7 @@ It also allows easy substitution for other separators. For example:: - format(n, "6,f").replace(",", "_") + format(n, "6,d").replace(",", "_") This technique is completely general but it is awkward in the one case where the commas and periods need to be swapped:: From python-checkins at python.org Thu Mar 12 23:37:07 2009 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Mar 2009 23:37:07 +0100 (CET) Subject: [Python-checkins] r70335 - python/branches/py3k/Lib/importlib/_bootstrap.py Message-ID: <20090312223707.3DD7F1E4002@bag.python.org> Author: brett.cannon Date: Thu Mar 12 23:37:06 2009 New Revision: 70335 Log: Last big re-organization of importlib._bootstrap. Should actually be able to find something in the file now. Modified: python/branches/py3k/Lib/importlib/_bootstrap.py Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Thu Mar 12 23:37:06 2009 @@ -173,7 +173,13 @@ return inner -# Finders/loaders ############################################################# +def _suffix_list(suffix_type): + """Return a list of file suffixes based on the imp file type.""" + return [suffix[0] for suffix in imp.get_suffixes() + if suffix[2] == suffix_type] + + +# Loaders ##################################################################### class BuiltinImporter: @@ -241,100 +247,6 @@ raise -def _chained_path_hook(*path_hooks): - """Create a closure which sequentially checks path hooks to see which ones - (if any) can work with a path.""" - def path_hook(entry): - """Check to see if 'entry' matches any of the enclosed path hooks.""" - finders = [] - for hook in path_hooks: - try: - finder = hook(entry) - except ImportError: - continue - else: - finders.append(finder) - if not finders: - raise ImportError("no finder found") - else: - return _ChainedFinder(*finders) - - return path_hook - - -class _ChainedFinder: - - """Finder that sequentially calls other finders.""" - - def __init__(self, *finders): - self._finders = finders - - def find_module(self, fullname, path=None): - for finder in self._finders: - result = finder.find_module(fullname, path) - if result: - return result - else: - return None - - - -class _ExtensionFileLoader: - - """Loader for extension modules. - - The constructor is designed to work with FileFinder. - - """ - - def __init__(self, name, path, is_pkg): - """Initialize the loader. - - If is_pkg is True then an exception is raised as extension modules - cannot be the __init__ module for an extension module. - - """ - self._name = name - self._path = path - if is_pkg: - raise ValueError("extension modules cannot be packages") - - @_check_name - @set_package - @set_loader - def load_module(self, fullname): - """Load an extension module.""" - is_reload = fullname in sys.modules - try: - return imp.load_dynamic(fullname, self._path) - except: - if not is_reload and fullname in sys.modules: - del sys.modules[fullname] - raise - - @_check_name - def is_package(self, fullname): - """Return False as an extension module can never be a package.""" - return False - - @_check_name - def get_code(self, fullname): - """Return None as an extension module cannot create a code object.""" - return None - - @_check_name - def get_source(self, fullname): - """Return None as extension modules have no source code.""" - return None - - -def _suffix_list(suffix_type): - """Return a list of file suffixes based on the imp file type.""" - return [suffix[0] for suffix in imp.get_suffixes() - if suffix[2] == suffix_type] - - - class PyLoader: """Loader base class for Python source. @@ -584,6 +496,136 @@ raise +class _ExtensionFileLoader: + + """Loader for extension modules. + + The constructor is designed to work with FileFinder. + + """ + + def __init__(self, name, path, is_pkg): + """Initialize the loader. + + If is_pkg is True then an exception is raised as extension modules + cannot be the __init__ module for an extension module. + + """ + self._name = name + self._path = path + if is_pkg: + raise ValueError("extension modules cannot be packages") + + @_check_name + @set_package + @set_loader + def load_module(self, fullname): + """Load an extension module.""" + is_reload = fullname in sys.modules + try: + return imp.load_dynamic(fullname, self._path) + except: + if not is_reload and fullname in sys.modules: + del sys.modules[fullname] + raise + + @_check_name + def is_package(self, fullname): + """Return False as an extension module can never be a package.""" + return False + + @_check_name + def get_code(self, fullname): + """Return None as an extension module cannot create a code object.""" + return None + + @_check_name + def get_source(self, fullname): + """Return None as extension modules have no source code.""" + return None + + +# Finders ##################################################################### + +class PathFinder: + + """Meta path finder for sys.(path|path_hooks|path_importer_cache).""" + + @classmethod + def _path_hooks(cls, path, hooks=None): + """Search sequence of hooks for a finder for 'path'. + + If 'hooks' is false then use sys.path_hooks. + + """ + if not hooks: + hooks = sys.path_hooks + for hook in hooks: + try: + return hook(path) + except ImportError: + continue + else: + raise ImportError("no path hook found for {0}".format(path)) + + @classmethod + def _path_importer_cache(cls, path, default=None): + """Get the finder for the path from sys.path_importer_cache. + + If the path is not in the cache, find the appropriate finder and cache + it. If None is cached, get the default finder and cache that + (if applicable). + + Because of NullImporter, some finder should be returned. The only + explicit fail case is if None is cached but the path cannot be used for + the default hook, for which ImportError is raised. + + """ + try: + finder = sys.path_importer_cache[path] + except KeyError: + finder = cls._path_hooks(path) + sys.path_importer_cache[path] = finder + else: + if finder is None and default: + # Raises ImportError on failure. + finder = default(path) + sys.path_importer_cache[path] = finder + return finder + + @classmethod + def find_module(cls, fullname, path=None): + """Find the module on sys.path or 'path'.""" + if not path: + path = sys.path + for entry in path: + try: + finder = cls._path_importer_cache(entry) + except ImportError: + continue + loader = finder.find_module(fullname) + if loader: + return loader + else: + return None + + +class _ChainedFinder: + + """Finder that sequentially calls other finders.""" + + def __init__(self, *finders): + self._finders = finders + + def find_module(self, fullname, path=None): + for finder in self._finders: + result = finder.find_module(fullname, path) + if result: + return result + else: + return None + + class FileFinder: """Base class for file finders. @@ -643,20 +685,6 @@ return None -class ExtensionFileFinder(FileFinder): - - """Importer for extension files.""" - - _possible_package = False - _loader = _ExtensionFileLoader - - def __init__(self, path_entry): - # Assigning to _suffixes here instead of at the class level because - # imp is not imported at the time of class creation. - self._suffixes = _suffix_list(imp.C_EXTENSION) - super().__init__(path_entry) - - class PyFileFinder(FileFinder): """Importer for source/bytecode files.""" @@ -683,82 +711,43 @@ self._suffixes += _suffix_list(imp.PY_COMPILED) -class PathFinder: - """Meta path finder for sys.(path|path_hooks|path_importer_cache).""" - @classmethod - def _path_hooks(cls, path, hooks=None): - """Search sequence of hooks for a finder for 'path'. - - If 'hooks' is false then use sys.path_hooks. +class ExtensionFileFinder(FileFinder): - """ - if not hooks: - hooks = sys.path_hooks - for hook in hooks: - try: - return hook(path) - except ImportError: - continue - else: - raise ImportError("no path hook found for {0}".format(path)) + """Importer for extension files.""" - @classmethod - def _path_importer_cache(cls, path, default=None): - """Get the finder for the path from sys.path_importer_cache. + _possible_package = False + _loader = _ExtensionFileLoader - If the path is not in the cache, find the appropriate finder and cache - it. If None is cached, get the default finder and cache that - (if applicable). + def __init__(self, path_entry): + # Assigning to _suffixes here instead of at the class level because + # imp is not imported at the time of class creation. + self._suffixes = _suffix_list(imp.C_EXTENSION) + super().__init__(path_entry) - Because of NullImporter, some finder should be returned. The only - explicit fail case is if None is cached but the path cannot be used for - the default hook, for which ImportError is raised. - """ - try: - finder = sys.path_importer_cache[path] - except KeyError: - finder = cls._path_hooks(path) - sys.path_importer_cache[path] = finder - else: - if finder is None and default: - # Raises ImportError on failure. - finder = default(path) - sys.path_importer_cache[path] = finder - return finder +# Import itself ############################################################### - @classmethod - def find_module(cls, fullname, path=None): - """Find the module on sys.path or 'path'.""" - if not path: - path = sys.path - for entry in path: +def _chained_path_hook(*path_hooks): + """Create a closure which sequentially checks path hooks to see which ones + (if any) can work with a path.""" + def path_hook(entry): + """Check to see if 'entry' matches any of the enclosed path hooks.""" + finders = [] + for hook in path_hooks: try: - finder = cls._path_importer_cache(entry) + finder = hook(entry) except ImportError: continue - loader = finder.find_module(fullname) - if loader: - return loader + else: + finders.append(finder) + if not finders: + raise ImportError("no finder found") else: - return None - - -# Import itself ############################################################### - -class _ImportLockContext: - - """Context manager for the import lock.""" - - def __enter__(self): - """Acquire the import lock.""" - imp.acquire_lock() + return _ChainedFinder(*finders) - def __exit__(self, exc_type, exc_value, exc_traceback): - """Release the import lock regardless of any raised exceptions.""" - imp.release_lock() + return path_hook _DEFAULT_PATH_HOOK = _chained_path_hook(ExtensionFileFinder, PyPycFileFinder) @@ -784,6 +773,18 @@ return super()._path_importer_cache(path, _DEFAULT_PATH_HOOK) +class _ImportLockContext: + + """Context manager for the import lock.""" + + def __enter__(self): + """Acquire the import lock.""" + imp.acquire_lock() + + def __exit__(self, exc_type, exc_value, exc_traceback): + """Release the import lock regardless of any raised exceptions.""" + imp.release_lock() + _IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, _DefaultPathFinder] From buildbot at python.org Thu Mar 12 23:47:19 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 12 Mar 2009 22:47:19 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090312224719.46DB21E4015@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/413 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From python-checkins at python.org Thu Mar 12 23:47:53 2009 From: python-checkins at python.org (brett.cannon) Date: Thu, 12 Mar 2009 23:47:53 +0100 (CET) Subject: [Python-checkins] r70336 - in python/branches/py3k/Lib/importlib: NOTES __init__.py _bootstrap.py test/extension/test_case_sensitivity.py test/extension/test_finder.py test/extension/test_loader.py test/extension/test_path_hook.py test/source/test_case_sensitivity.py test/source/test_file_loader.py test/source/test_finder.py test/source/test_path_hook.py test/source/test_source_encoding.py Message-ID: <20090312224753.7BAF21E4002@bag.python.org> Author: brett.cannon Date: Thu Mar 12 23:47:53 2009 New Revision: 70336 Log: Finish properly hiding importlib implementation code. Modified: python/branches/py3k/Lib/importlib/NOTES python/branches/py3k/Lib/importlib/__init__.py python/branches/py3k/Lib/importlib/_bootstrap.py python/branches/py3k/Lib/importlib/test/extension/test_case_sensitivity.py python/branches/py3k/Lib/importlib/test/extension/test_finder.py python/branches/py3k/Lib/importlib/test/extension/test_loader.py python/branches/py3k/Lib/importlib/test/extension/test_path_hook.py python/branches/py3k/Lib/importlib/test/source/test_case_sensitivity.py python/branches/py3k/Lib/importlib/test/source/test_file_loader.py python/branches/py3k/Lib/importlib/test/source/test_finder.py python/branches/py3k/Lib/importlib/test/source/test_path_hook.py python/branches/py3k/Lib/importlib/test/source/test_source_encoding.py Modified: python/branches/py3k/Lib/importlib/NOTES ============================================================================== --- python/branches/py3k/Lib/importlib/NOTES (original) +++ python/branches/py3k/Lib/importlib/NOTES Thu Mar 12 23:47:53 2009 @@ -7,15 +7,6 @@ + Expose function to see if a frozen module is a package. -* Remove ``import *`` from importlib.__init__. - -* Remove __all__ from importlib._bootstrap. - -* Add leading underscores to all objects in importlib._bootstrap that are not - publicly exposed. - -* Reorder importlib/_bootstrap.py so definitions are not in inverted order. - * Make sure that there is documentation *somewhere* fully explaining the semantics of import that can be referenced from the package's documentation (even if it is in the package documentation itself, although it might be best Modified: python/branches/py3k/Lib/importlib/__init__.py ============================================================================== --- python/branches/py3k/Lib/importlib/__init__.py (original) +++ python/branches/py3k/Lib/importlib/__init__.py Thu Mar 12 23:47:53 2009 @@ -136,7 +136,3 @@ break level += 1 return _bootstrap._gcd_import(name[level:], package, level) - - -# XXX This should go away once the public API is done. -from ._bootstrap import * Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Thu Mar 12 23:47:53 2009 @@ -387,7 +387,7 @@ return code_object -class PyFileLoader(PyLoader): +class _PyFileLoader(PyLoader): """Load a Python source file.""" @@ -452,7 +452,7 @@ return self._is_pkg -class PyPycFileLoader(PyPycLoader, PyFileLoader): +class _PyPycFileLoader(PyPycLoader, _PyFileLoader): """Load a module from a source or bytecode file.""" @@ -626,7 +626,7 @@ return None -class FileFinder: +class _FileFinder: """Base class for file finders. @@ -685,12 +685,12 @@ return None -class PyFileFinder(FileFinder): +class _PyFileFinder(_FileFinder): """Importer for source/bytecode files.""" _possible_package = True - _loader = PyFileLoader + _loader = _PyFileLoader def __init__(self, path_entry): # Lack of imp during class creation means _suffixes is set here. @@ -700,11 +700,11 @@ super().__init__(path_entry) -class PyPycFileFinder(PyFileFinder): +class _PyPycFileFinder(_PyFileFinder): """Finder for source and bytecode files.""" - _loader = PyPycFileLoader + _loader = _PyPycFileLoader def __init__(self, path_entry): super().__init__(path_entry) @@ -713,7 +713,7 @@ -class ExtensionFileFinder(FileFinder): +class _ExtensionFileFinder(_FileFinder): """Importer for extension files.""" @@ -750,7 +750,7 @@ return path_hook -_DEFAULT_PATH_HOOK = _chained_path_hook(ExtensionFileFinder, PyPycFileFinder) +_DEFAULT_PATH_HOOK = _chained_path_hook(_ExtensionFileFinder, _PyPycFileFinder) class _DefaultPathFinder(PathFinder): @@ -902,8 +902,3 @@ except ImportError: pass return module - - -# XXX Eventually replace with a proper __all__ value (i.e., don't expose os -# replacements but do expose _ExtensionFileLoader, etc. for testing). -__all__ = [obj for obj in globals().keys() if not obj.startswith('__')] Modified: python/branches/py3k/Lib/importlib/test/extension/test_case_sensitivity.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/extension/test_case_sensitivity.py (original) +++ python/branches/py3k/Lib/importlib/test/extension/test_case_sensitivity.py Thu Mar 12 23:47:53 2009 @@ -1,7 +1,7 @@ import sys from test import support import unittest -import importlib +from importlib import _bootstrap from .. import util from . import util as ext_util @@ -13,7 +13,7 @@ good_name = ext_util.NAME bad_name = good_name.upper() assert good_name != bad_name - finder = importlib.ExtensionFileFinder(ext_util.PATH) + finder = _bootstrap._ExtensionFileFinder(ext_util.PATH) return finder.find_module(bad_name) def test_case_sensitive(self): Modified: python/branches/py3k/Lib/importlib/test/extension/test_finder.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/extension/test_finder.py (original) +++ python/branches/py3k/Lib/importlib/test/extension/test_finder.py Thu Mar 12 23:47:53 2009 @@ -1,4 +1,4 @@ -import importlib +from importlib import _bootstrap from .. import abc from . import util @@ -9,7 +9,7 @@ """Test the finder for extension modules.""" def find_module(self, fullname): - importer = importlib.ExtensionFileFinder(util.PATH) + importer = _bootstrap._ExtensionFileFinder(util.PATH) return importer.find_module(fullname) def test_module(self): Modified: python/branches/py3k/Lib/importlib/test/extension/test_loader.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/extension/test_loader.py (original) +++ python/branches/py3k/Lib/importlib/test/extension/test_loader.py Thu Mar 12 23:47:53 2009 @@ -1,4 +1,4 @@ -import importlib +from importlib import _bootstrap from . import util as ext_util from .. import abc from .. import util @@ -12,7 +12,7 @@ """Test load_module() for extension modules.""" def load_module(self, fullname): - loader = importlib._ExtensionFileLoader(ext_util.NAME, + loader = _bootstrap._ExtensionFileLoader(ext_util.NAME, ext_util.FILEPATH, False) return loader.load_module(fullname) @@ -25,7 +25,7 @@ self.assertEqual(getattr(module, attr), value) self.assert_(ext_util.NAME in sys.modules) self.assert_(isinstance(module.__loader__, - importlib._ExtensionFileLoader)) + _bootstrap._ExtensionFileLoader)) def test_package(self): # Extensions are not found in packages. Modified: python/branches/py3k/Lib/importlib/test/extension/test_path_hook.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/extension/test_path_hook.py (original) +++ python/branches/py3k/Lib/importlib/test/extension/test_path_hook.py Thu Mar 12 23:47:53 2009 @@ -1,4 +1,4 @@ -import importlib +from importlib import _bootstrap from . import util import collections @@ -14,7 +14,7 @@ # XXX Should it only work for directories containing an extension module? def hook(self, entry): - return importlib.ExtensionFileFinder(entry) + return _bootstrap._ExtensionFileFinder(entry) def test_success(self): # Path hook should handle a directory where a known extension module Modified: python/branches/py3k/Lib/importlib/test/source/test_case_sensitivity.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/source/test_case_sensitivity.py (original) +++ python/branches/py3k/Lib/importlib/test/source/test_case_sensitivity.py Thu Mar 12 23:47:53 2009 @@ -1,5 +1,5 @@ """Test case-sensitivity (PEP 235).""" -import importlib +from importlib import _bootstrap from .. import util from . import util as source_util import os @@ -19,7 +19,7 @@ assert name != name.lower() def find(self, path): - finder = importlib.PyPycFileFinder(path) + finder = _bootstrap._PyPycFileFinder(path) return finder.find_module(self.name) def sensitivity_test(self): Modified: python/branches/py3k/Lib/importlib/test/source/test_file_loader.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/source/test_file_loader.py (original) +++ python/branches/py3k/Lib/importlib/test/source/test_file_loader.py Thu Mar 12 23:47:53 2009 @@ -1,4 +1,5 @@ import importlib +from importlib import _bootstrap from .. import abc from . import util as source_util @@ -19,7 +20,8 @@ # [basic] def test_module(self): with source_util.create_modules('_temp') as mapping: - loader = importlib.PyPycFileLoader('_temp', mapping['_temp'], False) + loader = _bootstrap._PyPycFileLoader('_temp', mapping['_temp'], + False) module = loader.load_module('_temp') self.assert_('_temp' in sys.modules) check = {'__name__': '_temp', '__file__': mapping['_temp'], @@ -29,8 +31,9 @@ def test_package(self): with source_util.create_modules('_pkg.__init__') as mapping: - loader = importlib.PyPycFileLoader('_pkg', mapping['_pkg.__init__'], - True) + loader = _bootstrap._PyPycFileLoader('_pkg', + mapping['_pkg.__init__'], + True) module = loader.load_module('_pkg') self.assert_('_pkg' in sys.modules) check = {'__name__': '_pkg', '__file__': mapping['_pkg.__init__'], @@ -42,8 +45,8 @@ def test_lacking_parent(self): with source_util.create_modules('_pkg.__init__', '_pkg.mod')as mapping: - loader = importlib.PyPycFileLoader('_pkg.mod', mapping['_pkg.mod'], - False) + loader = _bootstrap._PyPycFileLoader('_pkg.mod', + mapping['_pkg.mod'], False) module = loader.load_module('_pkg.mod') self.assert_('_pkg.mod' in sys.modules) check = {'__name__': '_pkg.mod', '__file__': mapping['_pkg.mod'], @@ -57,7 +60,8 @@ def test_module_reuse(self): with source_util.create_modules('_temp') as mapping: - loader = importlib.PyPycFileLoader('_temp', mapping['_temp'], False) + loader = _bootstrap._PyPycFileLoader('_temp', mapping['_temp'], + False) module = loader.load_module('_temp') module_id = id(module) module_dict_id = id(module.__dict__) @@ -87,7 +91,8 @@ setattr(orig_module, attr, value) with open(mapping[name], 'w') as file: file.write('+++ bad syntax +++') - loader = importlib.PyPycFileLoader('_temp', mapping['_temp'], False) + loader = _bootstrap._PyPycFileLoader('_temp', mapping['_temp'], + False) self.assertRaises(SyntaxError, loader.load_module, name) for attr in attributes: self.assertEqual(getattr(orig_module, attr), value) @@ -97,7 +102,8 @@ with source_util.create_modules('_temp') as mapping: with open(mapping['_temp'], 'w') as file: file.write('=') - loader = importlib.PyPycFileLoader('_temp', mapping['_temp'], False) + loader = _bootstrap._PyPycFileLoader('_temp', mapping['_temp'], + False) self.assertRaises(SyntaxError, loader.load_module, '_temp') self.assert_('_temp' not in sys.modules) @@ -116,7 +122,7 @@ """ def import_(self, file, module_name): - loader = importlib.PyPycFileLoader(module_name, file, False) + loader = _bootstrap._PyPycFileLoader(module_name, file, False) module = loader.load_module(module_name) self.assert_(module_name in sys.modules) Modified: python/branches/py3k/Lib/importlib/test/source/test_finder.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/source/test_finder.py (original) +++ python/branches/py3k/Lib/importlib/test/source/test_finder.py Thu Mar 12 23:47:53 2009 @@ -1,4 +1,4 @@ -import importlib +from importlib import _bootstrap from .. import abc from . import util as source_util import os @@ -32,7 +32,7 @@ """ def import_(self, root, module): - finder = importlib.PyPycFileFinder(root) + finder = _bootstrap._PyPycFileFinder(root) return finder.find_module(module) def run_test(self, test, create=None, *, compile_=None, unlink=None): Modified: python/branches/py3k/Lib/importlib/test/source/test_path_hook.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/source/test_path_hook.py (original) +++ python/branches/py3k/Lib/importlib/test/source/test_path_hook.py Thu Mar 12 23:47:53 2009 @@ -1,4 +1,4 @@ -import importlib +from importlib import _bootstrap from . import util as source_util import unittest @@ -10,7 +10,7 @@ def test_success(self): # XXX Only work on existing directories? with source_util.create_modules('dummy') as mapping: - self.assert_(hasattr(importlib.FileFinder(mapping['.root']), + self.assert_(hasattr(_bootstrap._FileFinder(mapping['.root']), 'find_module')) Modified: python/branches/py3k/Lib/importlib/test/source/test_source_encoding.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/source/test_source_encoding.py (original) +++ python/branches/py3k/Lib/importlib/test/source/test_source_encoding.py Thu Mar 12 23:47:53 2009 @@ -1,4 +1,4 @@ -import importlib +from importlib import _bootstrap from . import util as source_util import codecs @@ -35,7 +35,7 @@ with source_util.create_modules(self.module_name) as mapping: with open(mapping[self.module_name], 'wb')as file: file.write(source) - loader = importlib.PyPycFileLoader(self.module_name, + loader = _bootstrap._PyPycFileLoader(self.module_name, mapping[self.module_name], False) return loader.load_module(self.module_name) @@ -96,8 +96,8 @@ with source_util.create_modules(module_name) as mapping: with open(mapping[module_name], 'wb') as file: file.write(source) - loader = importlib.PyPycFileLoader(module_name, mapping[module_name], - False) + loader = _bootstrap._PyPycFileLoader(module_name, + mapping[module_name], False) return loader.load_module(module_name) # [cr] From buildbot at python.org Thu Mar 12 23:54:36 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 12 Mar 2009 22:54:36 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090312225438.CC8161E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/502 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Thu Mar 12 23:55:46 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 12 Mar 2009 22:55:46 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090312225546.B36971E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/468 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_multiprocessing make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Fri Mar 13 00:33:12 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 13 Mar 2009 00:33:12 +0100 (CET) Subject: [Python-checkins] r70337 - peps/trunk/pep-0378.txt Message-ID: <20090312233312.6934C1E4002@bag.python.org> Author: raymond.hettinger Date: Fri Mar 13 00:33:12 2009 New Revision: 70337 Log: Clarify what width means when thousands separators are present. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Fri Mar 13 00:33:12 2009 @@ -112,6 +112,12 @@ format(n, "6,f").replace(",", "X").replace(".", ",").replace("X", ".") +The *width* argument means the total length including the commas +and decimal point:: + + format(1234, "08,d") --> '0001,234' + format(1234.5, "08,.1f") --> '01,234.5' + Proposal II (to meet Antoine Pitrou's request) ============================================== @@ -138,6 +144,9 @@ __format__ methods that follow the format specification mini-language. +As shown in the examples, the *width* argument means the total +length including the thousands separators and decimal separators. + No change is proposed for the locale module. From buildbot at python.org Fri Mar 13 00:58:29 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 12 Mar 2009 23:58:29 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090312235829.C71C31E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/444 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Fri Mar 13 01:15:39 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 13 Mar 2009 00:15:39 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090313001539.46D6D1E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/415 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_posix test_subprocess ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_subprocess.py", line 149, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From python-checkins at python.org Fri Mar 13 03:20:21 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 13 Mar 2009 03:20:21 +0100 (CET) Subject: [Python-checkins] r70338 - peps/trunk/pep-0378.txt Message-ID: <20090313022021.999971E4002@bag.python.org> Author: raymond.hettinger Date: Fri Mar 13 03:20:21 2009 New Revision: 70338 Log: Add Eric Smith's variant Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Fri Mar 13 03:20:21 2009 @@ -150,6 +150,34 @@ No change is proposed for the locale module. +Proposal III (from Eric Smith: like II but without the T) +========================================================= + +In the second proposal, the *T* isn't strictly necessary. +In the context of an integer, an optional single specifier means +a thousands separator. In the context of a float, a single +specifier is a decimal separator while two specifiers are taken +as a thousands separator and a decimal separator:: + +[[fill]align][sign][#][0][width][tsep][dsep precision][type] + +Examples:: + + format(1234, "8.1f") --> ' 1234.0' + format(1234, "8,1f") --> ' 1234,0' + format(1234, "8.,1f") --> ' 1.234,0' + format(1234, "8 ,f") --> ' 1 234,0' + format(1234, "8d") --> ' 1234' + format(1234, "8,d") --> ' 1,234' + +This is a cleaner looking syntax but has the minor disadvantage of +using context to direct the translation. Whenever the separator +is followed by a precision, it decimal separator and a separator +preceding it is a thousands separator. When the precision is +absent, the context is integral and a lone specifier means +a thousands separator. + + Other Ideas =========== @@ -160,8 +188,9 @@ minwidth=32, pad='0') * Eric Smith would like the C version of the mini-language - parser to be exposed. That would make it easier to write - custom __format__ methods. + parser to be exposed with hooks that would make it easier + to write custom __format__ methods. That way + Decimal.__format__ would not have to be written from scratch. Copyright From python-checkins at python.org Fri Mar 13 03:23:58 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 13 Mar 2009 03:23:58 +0100 (CET) Subject: [Python-checkins] r70339 - peps/trunk/pep-0378.txt Message-ID: <20090313022358.200B51E4002@bag.python.org> Author: raymond.hettinger Date: Fri Mar 13 03:23:57 2009 New Revision: 70339 Log: Fix typo. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Fri Mar 13 03:23:57 2009 @@ -172,7 +172,7 @@ This is a cleaner looking syntax but has the minor disadvantage of using context to direct the translation. Whenever the separator -is followed by a precision, it decimal separator and a separator +is followed by a precision, it is a decimal separator and the separator preceding it is a thousands separator. When the precision is absent, the context is integral and a lone specifier means a thousands separator. From python-checkins at python.org Fri Mar 13 03:55:14 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 13 Mar 2009 03:55:14 +0100 (CET) Subject: [Python-checkins] r70340 - peps/trunk/pep-0378.txt Message-ID: <20090313025514.4BE921E4010@bag.python.org> Author: raymond.hettinger Date: Fri Mar 13 03:55:13 2009 New Revision: 70340 Log: Merge Eric's proposal into proposal II. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Fri Mar 13 03:55:13 2009 @@ -119,23 +119,29 @@ format(1234.5, "08,.1f") --> '01,234.5' -Proposal II (to meet Antoine Pitrou's request) -============================================== +Proposal II (from Eric Smith) +============================= Make both the thousands separator and decimal separator user specifiable but not locale aware. For simplicity, limit the -choices to a comma, period, space, or underscore. +choices to a COMMA, DOT, SPACE, or UNDERSCORE. -[[fill]align][sign][#][0][width][T[tsep]][dsep precision][type] +Whenever the separator is followed by a precision, it is a +decimal separator and the optional separator preceding it is a +thousands separator. When the precision is absent, the +context is integral and a lone specifier means a thousands +separator:: + +[[fill]align][sign][#][0][width][tsep|([tsep] dsep precision)][type] Examples:: - format(1234, "8.1f") --> ' 1234.0' - format(1234, "8,1f") --> ' 1234,0' - format(1234, "8T.,1f") --> ' 1.234,0' - format(1234, "8T ,f") --> ' 1 234,0' - format(1234, "8d") --> ' 1234' - format(1234, "8T,d") --> ' 1,234' + format(1234, "8.1f") --> ' 1234.0' + format(1234, "8,1f") --> ' 1234,0' + format(1234, "8.,1f") --> ' 1.234,0' + format(1234, "8 ,f") --> ' 1 234,0' + format(1234, "8d") --> ' 1234' + format(1234, "8,d") --> ' 1,234' This proposal meets mosts needs (except for people wanting grouping for hundreds or ten-thousands), but it comes at the @@ -150,34 +156,6 @@ No change is proposed for the locale module. -Proposal III (from Eric Smith: like II but without the T) -========================================================= - -In the second proposal, the *T* isn't strictly necessary. -In the context of an integer, an optional single specifier means -a thousands separator. In the context of a float, a single -specifier is a decimal separator while two specifiers are taken -as a thousands separator and a decimal separator:: - -[[fill]align][sign][#][0][width][tsep][dsep precision][type] - -Examples:: - - format(1234, "8.1f") --> ' 1234.0' - format(1234, "8,1f") --> ' 1234,0' - format(1234, "8.,1f") --> ' 1.234,0' - format(1234, "8 ,f") --> ' 1 234,0' - format(1234, "8d") --> ' 1234' - format(1234, "8,d") --> ' 1,234' - -This is a cleaner looking syntax but has the minor disadvantage of -using context to direct the translation. Whenever the separator -is followed by a precision, it is a decimal separator and the separator -preceding it is a thousands separator. When the precision is -absent, the context is integral and a lone specifier means -a thousands separator. - - Other Ideas =========== From python-checkins at python.org Fri Mar 13 04:01:42 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 13 Mar 2009 04:01:42 +0100 (CET) Subject: [Python-checkins] r70341 - peps/trunk/pep-0378.txt Message-ID: <20090313030142.5F8441E4002@bag.python.org> Author: raymond.hettinger Date: Fri Mar 13 04:01:42 2009 New Revision: 70341 Log: Clarify the difference between the two proposals. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Fri Mar 13 04:01:42 2009 @@ -156,6 +156,15 @@ No change is proposed for the locale module. +Comparision +=========== + +The difference between the two proposals is that the first is hard-wired +to a COMMA for a thousands separator and a DOT as a decimal separator. +The second allows either separator to be one of four possibilities. + + + Other Ideas =========== From python-checkins at python.org Fri Mar 13 20:03:59 2009 From: python-checkins at python.org (georg.brandl) Date: Fri, 13 Mar 2009 20:03:59 +0100 (CET) Subject: [Python-checkins] r70342 - in python/trunk/Doc: c-api/init.rst distutils/packageindex.rst library/2to3.rst library/exceptions.rst library/turtle.rst Message-ID: <20090313190359.0BD5B1E4002@bag.python.org> Author: georg.brandl Date: Fri Mar 13 20:03:58 2009 New Revision: 70342 Log: #5486: typos. Modified: python/trunk/Doc/c-api/init.rst python/trunk/Doc/distutils/packageindex.rst python/trunk/Doc/library/2to3.rst python/trunk/Doc/library/exceptions.rst python/trunk/Doc/library/turtle.rst Modified: python/trunk/Doc/c-api/init.rst ============================================================================== --- python/trunk/Doc/c-api/init.rst (original) +++ python/trunk/Doc/c-api/init.rst Fri Mar 13 20:03:58 2009 @@ -835,7 +835,7 @@ it returns -1 without setting any exception. This function can be called on any thread, be it a Python thread or - some other system thread. If it is a Python thread, it doesen't matter if + some other system thread. If it is a Python thread, it doesn't matter if it holds the global interpreter lock or not. .. versionadded:: 2.7 Modified: python/trunk/Doc/distutils/packageindex.rst ============================================================================== --- python/trunk/Doc/distutils/packageindex.rst (original) +++ python/trunk/Doc/distutils/packageindex.rst Fri Mar 13 20:03:58 2009 @@ -98,7 +98,7 @@ python setup.py register -r http://example.com/pypi -The name of the section that describes the repository may also be used -for conveniency:: +For convenience, the name of the section that describes the repository +may also be used:: python setup.py register -r other Modified: python/trunk/Doc/library/2to3.rst ============================================================================== --- python/trunk/Doc/library/2to3.rst (original) +++ python/trunk/Doc/library/2to3.rst Fri Mar 13 20:03:58 2009 @@ -99,7 +99,7 @@ Fixers ------ -Each step of tranforming code is encapsulated in a fixer. The command ``2to3 +Each step of transforming code is encapsulated in a fixer. The command ``2to3 -l`` lists them. As :ref:`documented above <2to3-using>`, each can be turned on and off individually. They are described here in more detail. @@ -167,11 +167,11 @@ .. 2to3fixer:: idioms - This optional fixer preforms several transformations that make Python code - more idiomatic. Type comparisions like ``type(x) is SomeClass`` and + This optional fixer performs several transformations that make Python code + more idiomatic. Type comparisons like ``type(x) is SomeClass`` and ``type(x) == SomeClass`` are converted to ``isinstance(x, SomeClass)``. ``while 1`` becomes ``while True``. This fixer also tries to make use of - :func:`sorted` in appropiate places. For example, this block :: + :func:`sorted` in appropriate places. For example, this block :: L = list(some_iterable) L.sort() Modified: python/trunk/Doc/library/exceptions.rst ============================================================================== --- python/trunk/Doc/library/exceptions.rst (original) +++ python/trunk/Doc/library/exceptions.rst Fri Mar 13 20:03:58 2009 @@ -52,7 +52,7 @@ The base class for all built-in exceptions. It is not meant to be directly inherited by user-defined classes (for that use :exc:`Exception`). If :func:`str` or :func:`unicode` is called on an instance of this class, the - representation of the argument(s) to the instance are returned or the emptry + representation of the argument(s) to the instance are returned or the empty string when there were no arguments. All arguments are stored in :attr:`args` as a tuple. Modified: python/trunk/Doc/library/turtle.rst ============================================================================== --- python/trunk/Doc/library/turtle.rst (original) +++ python/trunk/Doc/library/turtle.rst Fri Mar 13 20:03:58 2009 @@ -61,7 +61,7 @@ The procedural interface provides functions which are derived from the methods of the classes :class:`Screen` and :class:`Turtle`. They have the same names as -the corresponding methods. A screen object is automativally created whenever a +the corresponding methods. A screen object is automatically created whenever a function derived from a Screen method is called. An (unnamed) turtle object is automatically created whenever any of the functions derived from a Turtle method is called. @@ -1608,7 +1608,7 @@ =========== =========== "polygon" a polygon-tuple, i.e. a tuple of pairs of coordinates "image" an image (in this form only used internally!) - "compound" ``None`` (a compund shape has to be constructed using the + "compound" ``None`` (a compound shape has to be constructed using the :meth:`addcomponent` method) =========== =========== @@ -1830,7 +1830,7 @@ It contains: -- a set of 15 demo scripts demonstrating differet features of the new module +- a set of 15 demo scripts demonstrating different features of the new module :mod:`turtle` - a demo viewer :file:`turtleDemo.py` which can be used to view the sourcecode of the scripts and run them at the same time. 14 of the examples can be From python-checkins at python.org Fri Mar 13 20:04:40 2009 From: python-checkins at python.org (georg.brandl) Date: Fri, 13 Mar 2009 20:04:40 +0100 (CET) Subject: [Python-checkins] r70343 - in python/branches/py3k/Doc: c-api/buffer.rst c-api/init.rst c-api/typeobj.rst distutils/packageindex.rst library/2to3.rst library/cgi.rst library/exceptions.rst library/importlib.rst library/pickle.rst library/re.rst library/tkinter.ttk.rst library/tokenize.rst library/turtle.rst reference/datamodel.rst reference/expressions.rst Message-ID: <20090313190440.DBE431E4002@bag.python.org> Author: georg.brandl Date: Fri Mar 13 20:04:40 2009 New Revision: 70343 Log: #5486: typos. Modified: python/branches/py3k/Doc/c-api/buffer.rst python/branches/py3k/Doc/c-api/init.rst python/branches/py3k/Doc/c-api/typeobj.rst python/branches/py3k/Doc/distutils/packageindex.rst python/branches/py3k/Doc/library/2to3.rst python/branches/py3k/Doc/library/cgi.rst python/branches/py3k/Doc/library/exceptions.rst python/branches/py3k/Doc/library/importlib.rst python/branches/py3k/Doc/library/pickle.rst python/branches/py3k/Doc/library/re.rst python/branches/py3k/Doc/library/tkinter.ttk.rst python/branches/py3k/Doc/library/tokenize.rst python/branches/py3k/Doc/library/turtle.rst python/branches/py3k/Doc/reference/datamodel.rst python/branches/py3k/Doc/reference/expressions.rst Modified: python/branches/py3k/Doc/c-api/buffer.rst ============================================================================== --- python/branches/py3k/Doc/c-api/buffer.rst (original) +++ python/branches/py3k/Doc/c-api/buffer.rst Fri Mar 13 20:04:40 2009 @@ -93,7 +93,7 @@ occur (striding in a contiguous memory block). 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 + pointed to by an N-dimensional index when there are both non-NULL strides and suboffsets:: void *get_item_pointer(int ndim, void *buf, Py_ssize_t *strides, Modified: python/branches/py3k/Doc/c-api/init.rst ============================================================================== --- python/branches/py3k/Doc/c-api/init.rst (original) +++ python/branches/py3k/Doc/c-api/init.rst Fri Mar 13 20:04:40 2009 @@ -820,7 +820,7 @@ it returns -1 without setting any exception. This function can be called on any thread, be it a Python thread or - some other system thread. If it is a Python thread, it doesen't matter if + some other system thread. If it is a Python thread, it doesn't matter if it holds the global interpreter lock or not. .. versionadded:: 2.7 Modified: python/branches/py3k/Doc/c-api/typeobj.rst ============================================================================== --- python/branches/py3k/Doc/c-api/typeobj.rst (original) +++ python/branches/py3k/Doc/c-api/typeobj.rst Fri Mar 13 20:04:40 2009 @@ -1214,7 +1214,7 @@ export, *view* is the :ctype:`Py_buffer` struct to fill, and *flags* gives the conditions the caller wants the memory under. (See :cfunc:`PyObject_GetBuffer` for all flags.) :cmember:`bf_getbuffer` is - responsible for filling *view* with the approiate information. + responsible for filling *view* with the appropriate information. (:cfunc:`PyBuffer_FillView` can be used in simple cases.) See :ctype:`Py_buffer`\s docs for what needs to be filled in. Modified: python/branches/py3k/Doc/distutils/packageindex.rst ============================================================================== --- python/branches/py3k/Doc/distutils/packageindex.rst (original) +++ python/branches/py3k/Doc/distutils/packageindex.rst Fri Mar 13 20:04:40 2009 @@ -98,7 +98,7 @@ python setup.py register -r http://example.com/pypi -The name of the section that describes the repository may also be used -for conveniency:: +For convenience, the name of the section that describes the repository +may also be used:: python setup.py register -r other Modified: python/branches/py3k/Doc/library/2to3.rst ============================================================================== --- python/branches/py3k/Doc/library/2to3.rst (original) +++ python/branches/py3k/Doc/library/2to3.rst Fri Mar 13 20:04:40 2009 @@ -99,7 +99,7 @@ Fixers ------ -Each step of tranforming code is encapsulated in a fixer. The command ``2to3 +Each step of transforming code is encapsulated in a fixer. The command ``2to3 -l`` lists them. As :ref:`documented above <2to3-using>`, each can be turned on and off individually. They are described here in more detail. @@ -167,11 +167,11 @@ .. 2to3fixer:: idioms - This optional fixer preforms several transformations that make Python code - more idiomatic. Type comparisions like ``type(x) is SomeClass`` and + This optional fixer performs several transformations that make Python code + more idiomatic. Type comparisons like ``type(x) is SomeClass`` and ``type(x) == SomeClass`` are converted to ``isinstance(x, SomeClass)``. ``while 1`` becomes ``while True``. This fixer also tries to make use of - :func:`sorted` in appropiate places. For example, this block :: + :func:`sorted` in appropriate places. For example, this block :: L = list(some_iterable) L.sort() Modified: python/branches/py3k/Doc/library/cgi.rst ============================================================================== --- python/branches/py3k/Doc/library/cgi.rst (original) +++ python/branches/py3k/Doc/library/cgi.rst Fri Mar 13 20:04:40 2009 @@ -265,12 +265,12 @@ .. function:: parse_qs(qs[, keep_blank_values[, strict_parsing]]) This function is deprecated in this module. Use :func:`urllib.parse.parse_qs` - instead. It is maintained here only for backward compatiblity. + instead. It is maintained here only for backward compatibility. .. function:: parse_qsl(qs[, keep_blank_values[, strict_parsing]]) This function is deprecated in this module. Use :func:`urllib.parse.parse_qs` - instead. It is maintained here only for backward compatiblity. + instead. It is maintained here only for backward compatibility. .. function:: parse_multipart(fp, pdict) Modified: python/branches/py3k/Doc/library/exceptions.rst ============================================================================== --- python/branches/py3k/Doc/library/exceptions.rst (original) +++ python/branches/py3k/Doc/library/exceptions.rst Fri Mar 13 20:04:40 2009 @@ -53,7 +53,7 @@ The base class for all built-in exceptions. It is not meant to be directly inherited by user-defined classes (for that use :exc:`Exception`). If :func:`str` or :func:`unicode` is called on an instance of this class, the - representation of the argument(s) to the instance are returned or the emptry + representation of the argument(s) to the instance are returned or the empty string when there were no arguments. All arguments are stored in :attr:`args` as a tuple. Modified: python/branches/py3k/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k/Doc/library/importlib.rst (original) +++ python/branches/py3k/Doc/library/importlib.rst Fri Mar 13 20:04:40 2009 @@ -78,9 +78,9 @@ The :func:`import_module` function acts as a simplifying wrapper around :func:`__import__`. This means all semantics of the function are derived - from :func:`__import__`, including requiring the package where an import is - occuring from to already be imported (i.e., *package* must already be - imported). + from :func:`__import__`, including requiring the package from which an + import is occurring to have been previously imported (i.e., *package* + must already be imported). :mod:`importlib.abc` -- Abstract base classes related to import --------------------------------------------------------------- Modified: python/branches/py3k/Doc/library/pickle.rst ============================================================================== --- python/branches/py3k/Doc/library/pickle.rst (original) +++ python/branches/py3k/Doc/library/pickle.rst Fri Mar 13 20:04:40 2009 @@ -473,13 +473,13 @@ Although powerful, implementing :meth:`__reduce__` directly in your classes is error prone. For this reason, class designers should use the high-level interface (i.e., :meth:`__getnewargs__`, :meth:`__getstate__` and -:meth:`__setstate__`) whenever possible. We will show however cases where using +:meth:`__setstate__`) whenever possible. We will show, however, cases where using :meth:`__reduce__` is the only option or leads to more efficient pickling or both. -The interface is currently defined as follow. The :meth:`__reduce__` method +The interface is currently defined as follows. The :meth:`__reduce__` method takes no argument and shall return either a string or preferably a tuple (the -returned object is often refered as the "reduce value"). +returned object is often referred to as the "reduce value"). If a string is returned, the string should be interpreted as the name of a global variable. It should be the object's local name relative to its module; Modified: python/branches/py3k/Doc/library/re.rst ============================================================================== --- python/branches/py3k/Doc/library/re.rst (original) +++ python/branches/py3k/Doc/library/re.rst Fri Mar 13 20:04:40 2009 @@ -16,7 +16,7 @@ Both patterns and strings to be searched can be Unicode strings as well as 8-bit strings. However, Unicode strings and 8-bit strings cannot be mixed: that is, you cannot match an Unicode string with a byte pattern or -vice-versa; similarly, when asking for a substition, the replacement +vice-versa; similarly, when asking for a substitution, the replacement string must be of the same type as both the pattern and the search string. Regular expressions use the backslash character (``'\'``) to indicate Modified: python/branches/py3k/Doc/library/tkinter.ttk.rst ============================================================================== --- python/branches/py3k/Doc/library/tkinter.ttk.rst (original) +++ python/branches/py3k/Doc/library/tkinter.ttk.rst Fri Mar 13 20:04:40 2009 @@ -139,7 +139,7 @@ +----------------+---------------------------------------------------------+ | option | description | +================+=========================================================+ - | xscrollcommand | Used to comunicate with horizontal scrollbars. | + | xscrollcommand | Used to communicate with horizontal scrollbars. | | | | | | When the view in the widget's window change, the widget | | | will generate a Tcl command based on the scrollcommand. | @@ -149,7 +149,7 @@ | | the scrollbar to be updated whenever the view in the | | | window changes. | +----------------+---------------------------------------------------------+ - | yscrollcommand | Used to comunicate with vertical scrollbars. | + | yscrollcommand | Used to communicate with vertical scrollbars. | | | For some more information, see above. | +----------------+---------------------------------------------------------+ Modified: python/branches/py3k/Doc/library/tokenize.rst ============================================================================== --- python/branches/py3k/Doc/library/tokenize.rst (original) +++ python/branches/py3k/Doc/library/tokenize.rst Fri Mar 13 20:04:40 2009 @@ -82,7 +82,7 @@ .. function:: detect_encoding(readline) The :func:`detect_encoding` function is used to detect the encoding that - should be used to decode a Python source file. It requires one argment, + should be used to decode a Python source file. It requires one argument, readline, in the same way as the :func:`tokenize` generator. It will call readline a maximum of twice, and return the encoding used Modified: python/branches/py3k/Doc/library/turtle.rst ============================================================================== --- python/branches/py3k/Doc/library/turtle.rst (original) +++ python/branches/py3k/Doc/library/turtle.rst Fri Mar 13 20:04:40 2009 @@ -61,7 +61,7 @@ The procedural interface provides functions which are derived from the methods of the classes :class:`Screen` and :class:`Turtle`. They have the same names as -the corresponding methods. A screen object is automativally created whenever a +the corresponding methods. A screen object is automatically created whenever a function derived from a Screen method is called. An (unnamed) turtle object is automatically created whenever any of the functions derived from a Turtle method is called. @@ -1584,7 +1584,7 @@ =========== =========== "polygon" a polygon-tuple, i.e. a tuple of pairs of coordinates "image" an image (in this form only used internally!) - "compound" ``None`` (a compund shape has to be constructed using the + "compound" ``None`` (a compound shape has to be constructed using the :meth:`addcomponent` method) =========== =========== @@ -1806,7 +1806,7 @@ It contains: -- a set of 15 demo scripts demonstrating differet features of the new module +- a set of 15 demo scripts demonstrating different features of the new module :mod:`turtle` - a demo viewer :file:`turtleDemo.py` which can be used to view the sourcecode of the scripts and run them at the same time. 14 of the examples can be Modified: python/branches/py3k/Doc/reference/datamodel.rst ============================================================================== --- python/branches/py3k/Doc/reference/datamodel.rst (original) +++ python/branches/py3k/Doc/reference/datamodel.rst Fri Mar 13 20:04:40 2009 @@ -1240,7 +1240,7 @@ ``isinstance(obj, collections.Hashable)`` (unlike classes which define their own :meth:`__hash__` to explicitly raise :exc:`TypeError`). - If a class that overrrides :meth:`__eq__` needs to retain the implementation + If a class that overrides :meth:`__eq__` needs to retain the implementation of :meth:`__hash__` from a parent class, the interpreter must be told this explicitly by setting ``__hash__ = .__hash__``. Otherwise the inheritance of :meth:`__hash__` will be blocked, just as if :attr:`__hash__` Modified: python/branches/py3k/Doc/reference/expressions.rst ============================================================================== --- python/branches/py3k/Doc/reference/expressions.rst (original) +++ python/branches/py3k/Doc/reference/expressions.rst Fri Mar 13 20:04:40 2009 @@ -1300,7 +1300,7 @@ .. [#] While comparisons between strings make sense at the byte level, they may be counter-intuitive to users. For example, the strings ``"\u00C7"`` and ``"\u0327\u0043"`` compare differently, even though they both represent the - same unicode character (LATIN CAPTITAL LETTER C WITH CEDILLA). To compare + same unicode character (LATIN CAPITAL LETTER C WITH CEDILLA). To compare strings in a human recognizable way, compare using :func:`unicodedata.normalize`. From python-checkins at python.org Fri Mar 13 20:25:21 2009 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 13 Mar 2009 20:25:21 +0100 (CET) Subject: [Python-checkins] r70344 - in python/branches/py3k: Include/ceval.h Lib/test/test_sys.py Misc/NEWS Message-ID: <20090313192521.3ED9E1E4002@bag.python.org> Author: antoine.pitrou Date: Fri Mar 13 20:25:20 2009 New Revision: 70344 Log: Issue #5392: when a very low recursion limit was set, the interpreter would abort with a fatal error after the recursion limit was hit twice. Modified: python/branches/py3k/Include/ceval.h python/branches/py3k/Lib/test/test_sys.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Include/ceval.h ============================================================================== --- python/branches/py3k/Include/ceval.h (original) +++ python/branches/py3k/Include/ceval.h Fri Mar 13 20:25:20 2009 @@ -92,11 +92,10 @@ # define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit) #endif -#ifdef USE_STACKCHECK -# define _Py_MakeEndRecCheck(x) (--(x) < _Py_CheckRecursionLimit - 50) -#else -# define _Py_MakeEndRecCheck(x) (--(x) < _Py_CheckRecursionLimit - 50) -#endif +#define _Py_MakeEndRecCheck(x) \ + (--(x) < ((_Py_CheckRecursionLimit > 100) \ + ? (_Py_CheckRecursionLimit - 50) \ + : (3 * (_Py_CheckRecursionLimit >> 2)))) #define Py_ALLOW_RECURSION \ do { unsigned char _old = PyThreadState_GET()->recursion_critical;\ Modified: python/branches/py3k/Lib/test/test_sys.py ============================================================================== --- python/branches/py3k/Lib/test/test_sys.py (original) +++ python/branches/py3k/Lib/test/test_sys.py Fri Mar 13 20:25:20 2009 @@ -2,6 +2,8 @@ import unittest, test.support import sys, io, os import struct +import subprocess +import textwrap class SysModuleTest(unittest.TestCase): @@ -155,6 +157,46 @@ self.assertEqual(sys.getrecursionlimit(), 10000) sys.setrecursionlimit(oldlimit) + def test_recursionlimit_recovery(self): + # NOTE: this test is slightly fragile in that it depends on the current + # recursion count when executing the test being low enough so as to + # trigger the recursion recovery detection in the _Py_MakeEndRecCheck + # macro (see ceval.h). + oldlimit = sys.getrecursionlimit() + def f(): + f() + try: + for i in (50, 1000): + # Issue #5392: stack overflow after hitting recursion limit twice + sys.setrecursionlimit(i) + self.assertRaises(RuntimeError, f) + self.assertRaises(RuntimeError, f) + finally: + sys.setrecursionlimit(oldlimit) + + def test_recursionlimit_fatalerror(self): + # A fatal error occurs if a second recursion limit is hit when recovering + # from a first one. + code = textwrap.dedent(""" + import sys + + def f(): + try: + f() + except RuntimeError: + f() + + sys.setrecursionlimit(%d) + f()""") + for i in (50, 1000): + sub = subprocess.Popen([sys.executable, '-c', code % i], + stderr=subprocess.PIPE) + err = sub.communicate()[1] + self.assertTrue(sub.returncode, sub.returncode) + self.assertTrue( + b"Fatal Python error: Cannot recover from stack overflow" in err, + err) + def test_getwindowsversion(self): if hasattr(sys, "getwindowsversion"): v = sys.getwindowsversion() Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Mar 13 20:25:20 2009 @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #5392: when a very low recursion limit was set, the interpreter would + abort with a fatal error after the recursion limit was hit twice. + Library ------- @@ -24,8 +27,6 @@ Core and Builtins ----------------- -======= - - The io module has been reimplemented in C for speed. - Give dict views an informative __repr__. From python-checkins at python.org Fri Mar 13 21:35:06 2009 From: python-checkins at python.org (georg.brandl) Date: Fri, 13 Mar 2009 21:35:06 +0100 (CET) Subject: [Python-checkins] r70345 - peps/trunk/pep-0378.txt Message-ID: <20090313203506.14DD51E4002@bag.python.org> Author: georg.brandl Date: Fri Mar 13 21:35:04 2009 New Revision: 70345 Log: Typos. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Fri Mar 13 21:35:04 2009 @@ -51,7 +51,7 @@ James Knight observed that Indian/Pakistani numbering systems group by hundreds. Ben Finney noted that Chinese group by ten-thousands. Eric Smith pointed-out that these are already -handled by the "n" specifier in the locale module (albiet only +handled by the "n" specifier in the locale module (albeit only for integers). Visual Basic and its brethren (like MS Excel) use a completely @@ -156,8 +156,8 @@ No change is proposed for the locale module. -Comparision -=========== +Comparison +========== The difference between the two proposals is that the first is hard-wired to a COMMA for a thousands separator and a DOT as a decimal separator. From python-checkins at python.org Fri Mar 13 21:37:02 2009 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 13 Mar 2009 21:37:02 +0100 (CET) Subject: [Python-checkins] r70346 - python/branches/release26-maint Message-ID: <20090313203702.407F81E4002@bag.python.org> Author: benjamin.peterson Date: Fri Mar 13 21:37:01 2009 New Revision: 70346 Log: Unblocked revisions 68737 via svnmerge ........ r68737 | jesse.noller | 2009-01-18 15:04:36 -0600 (Sun, 18 Jan 2009) | 1 line issue 4301: patch logging to add processName, remove the old _check_logger_class code ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Fri Mar 13 21:38:57 2009 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 13 Mar 2009 21:38:57 +0100 (CET) Subject: [Python-checkins] r70347 - in python/branches/release30-maint: Include/ceval.h Lib/test/test_sys.py Misc/NEWS Message-ID: <20090313203857.032BB1E4002@bag.python.org> Author: antoine.pitrou Date: Fri Mar 13 21:38:56 2009 New Revision: 70347 Log: Merged revisions 70344 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70344 | antoine.pitrou | 2009-03-13 20:25:20 +0100 (ven., 13 mars 2009) | 4 lines Issue #5392: when a very low recursion limit was set, the interpreter would abort with a fatal error after the recursion limit was hit twice. ........ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Include/ceval.h python/branches/release30-maint/Lib/test/test_sys.py python/branches/release30-maint/Misc/NEWS Modified: python/branches/release30-maint/Include/ceval.h ============================================================================== --- python/branches/release30-maint/Include/ceval.h (original) +++ python/branches/release30-maint/Include/ceval.h Fri Mar 13 21:38:56 2009 @@ -92,11 +92,10 @@ # define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit) #endif -#ifdef USE_STACKCHECK -# define _Py_MakeEndRecCheck(x) (--(x) < _Py_CheckRecursionLimit - 50) -#else -# define _Py_MakeEndRecCheck(x) (--(x) < _Py_CheckRecursionLimit - 50) -#endif +#define _Py_MakeEndRecCheck(x) \ + (--(x) < ((_Py_CheckRecursionLimit > 100) \ + ? (_Py_CheckRecursionLimit - 50) \ + : (3 * (_Py_CheckRecursionLimit >> 2)))) #define Py_ALLOW_RECURSION \ do { unsigned char _old = PyThreadState_GET()->recursion_critical;\ Modified: python/branches/release30-maint/Lib/test/test_sys.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_sys.py (original) +++ python/branches/release30-maint/Lib/test/test_sys.py Fri Mar 13 21:38:56 2009 @@ -2,6 +2,8 @@ import unittest, test.support import sys, io, os import struct +import subprocess +import textwrap class SysModuleTest(unittest.TestCase): @@ -155,6 +157,46 @@ self.assertEqual(sys.getrecursionlimit(), 10000) sys.setrecursionlimit(oldlimit) + def test_recursionlimit_recovery(self): + # NOTE: this test is slightly fragile in that it depends on the current + # recursion count when executing the test being low enough so as to + # trigger the recursion recovery detection in the _Py_MakeEndRecCheck + # macro (see ceval.h). + oldlimit = sys.getrecursionlimit() + def f(): + f() + try: + for i in (50, 1000): + # Issue #5392: stack overflow after hitting recursion limit twice + sys.setrecursionlimit(i) + self.assertRaises(RuntimeError, f) + self.assertRaises(RuntimeError, f) + finally: + sys.setrecursionlimit(oldlimit) + + def test_recursionlimit_fatalerror(self): + # A fatal error occurs if a second recursion limit is hit when recovering + # from a first one. + code = textwrap.dedent(""" + import sys + + def f(): + try: + f() + except RuntimeError: + f() + + sys.setrecursionlimit(%d) + f()""") + for i in (50, 1000): + sub = subprocess.Popen([sys.executable, '-c', code % i], + stderr=subprocess.PIPE) + err = sub.communicate()[1] + self.assertTrue(sub.returncode, sub.returncode) + self.assertTrue( + b"Fatal Python error: Cannot recover from stack overflow" in err, + err) + def test_getwindowsversion(self): if hasattr(sys, "getwindowsversion"): v = sys.getwindowsversion() Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Fri Mar 13 21:38:56 2009 @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #5392: when a very low recursion limit was set, the interpreter would + abort with a fatal error after the recursion limit was hit twice. + - Issue #5247: Improve error message when unknown format codes are used when using str.format() with str, int, and float arguments. From python-checkins at python.org Fri Mar 13 21:48:11 2009 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 13 Mar 2009 21:48:11 +0100 (CET) Subject: [Python-checkins] r70348 - in python/branches/release26-maint: Lib/logging/__init__.py Lib/multiprocessing/util.py Misc/NEWS Message-ID: <20090313204811.0C2261E4002@bag.python.org> Author: benjamin.peterson Date: Fri Mar 13 21:48:10 2009 New Revision: 70348 Log: Merged revisions 68737 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r68737 | jesse.noller | 2009-01-18 15:04:36 -0600 (Sun, 18 Jan 2009) | 1 line issue 4301: patch logging to add processName, remove the old _check_logger_class code ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/logging/__init__.py python/branches/release26-maint/Lib/multiprocessing/util.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/logging/__init__.py ============================================================================== --- python/branches/release26-maint/Lib/logging/__init__.py (original) +++ python/branches/release26-maint/Lib/logging/__init__.py Fri Mar 13 21:48:10 2009 @@ -97,6 +97,11 @@ logThreads = 1 # +# If you don't want multiprocessing information in the log, set this to zero +# +logMultiprocessing = 1 + +# # If you don't want process information in the log, set this to zero # logProcesses = 1 @@ -263,6 +268,11 @@ else: self.thread = None self.threadName = None + if logMultiprocessing: + from multiprocessing import current_process + self.processName = current_process().name + else: + self.processName = None if logProcesses and hasattr(os, 'getpid'): self.process = os.getpid() else: Modified: python/branches/release26-maint/Lib/multiprocessing/util.py ============================================================================== --- python/branches/release26-maint/Lib/multiprocessing/util.py (original) +++ python/branches/release26-maint/Lib/multiprocessing/util.py Fri Mar 13 21:48:10 2009 @@ -69,34 +69,10 @@ atexit._exithandlers.remove((_exit_function, (), {})) atexit._exithandlers.append((_exit_function, (), {})) - _check_logger_class() _logger = logging.getLogger(LOGGER_NAME) return _logger -def _check_logger_class(): - ''' - Make sure process name is recorded when loggers are used - ''' - # XXX This function is unnecessary once logging is patched - import logging - if hasattr(logging, 'multiprocessing'): - return - - logging._acquireLock() - try: - OldLoggerClass = logging.getLoggerClass() - if not getattr(OldLoggerClass, '_process_aware', False): - class ProcessAwareLogger(OldLoggerClass): - _process_aware = True - def makeRecord(self, *args, **kwds): - record = OldLoggerClass.makeRecord(self, *args, **kwds) - record.processName = current_process()._name - return record - logging.setLoggerClass(ProcessAwareLogger) - finally: - logging._releaseLock() - def log_to_stderr(level=None): ''' Turn on logging and add a handler which prints to stderr Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Fri Mar 13 21:48:10 2009 @@ -658,6 +658,9 @@ Extension Modules ----------------- +- Issue #4301: Patch the logging module to add processName support, remove + _check_logger_class from multiprocessing. + - Issue #2975: When compiling several extension modules with Visual Studio 2008 from the same python interpreter, some environment variables would grow without limit. From buildbot at python.org Fri Mar 13 22:29:33 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 13 Mar 2009 21:29:33 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.0 Message-ID: <20090313212933.DBB8D1E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.0/builds/178 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: antoine.pitrou,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Fri Mar 13 22:29:58 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 13 Mar 2009 21:29:58 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090313212959.07C6F1E400C@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/168 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Fri Mar 13 23:22:40 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 13 Mar 2009 22:22:40 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090313222241.578901E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/204 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: antoine.pitrou,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From python-checkins at python.org Fri Mar 13 23:33:17 2009 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 13 Mar 2009 23:33:17 +0100 (CET) Subject: [Python-checkins] r70349 - in python/branches/py3k: Lib/test/test_fileio.py Misc/NEWS Modules/_fileio.c Message-ID: <20090313223317.E54831E4002@bag.python.org> Author: antoine.pitrou Date: Fri Mar 13 23:33:17 2009 New Revision: 70349 Log: The error detection code in FileIO.close() could fail to reflect the `errno` value, and report it as -1 instead. Modified: python/branches/py3k/Lib/test/test_fileio.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_fileio.c Modified: python/branches/py3k/Lib/test/test_fileio.py ============================================================================== --- python/branches/py3k/Lib/test/test_fileio.py (original) +++ python/branches/py3k/Lib/test/test_fileio.py Fri Mar 13 23:33:17 2009 @@ -2,6 +2,7 @@ import sys import os +import errno import unittest from array import array from weakref import proxy @@ -113,6 +114,20 @@ else: self.fail("Should have raised IOError") + def testErrnoOnClose(self): + # Test that the IOError's `errno` attribute is correctly set when + # close() fails. Here we first close the file descriptor ourselves so + # that close() fails with EBADF ('Bad file descriptor'). + f = self.f + os.close(f.fileno()) + self.f = None + try: + f.close() + except IOError as e: + self.assertEqual(e.errno, errno.EBADF) + else: + self.fail("Should have raised IOError") + class OtherFileTests(unittest.TestCase): Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Mar 13 23:33:17 2009 @@ -18,6 +18,9 @@ Library ------- +- The error detection code in FileIO.close() could fail to reflect the `errno` + value, and report it as -1 instead. + What's New in Python 3.1 alpha 1 ================================ Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Fri Mar 13 23:33:17 2009 @@ -97,10 +97,8 @@ Py_RETURN_NONE; } errno = internal_close(self); - if (errno < 0) { - PyErr_SetFromErrno(PyExc_IOError); + if (errno < 0) return NULL; - } return PyObject_CallMethod((PyObject*)&PyRawIOBase_Type, "close", "O", self); From python-checkins at python.org Fri Mar 13 23:38:28 2009 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 13 Mar 2009 23:38:28 +0100 (CET) Subject: [Python-checkins] r70350 - python/branches/release30-maint Message-ID: <20090313223828.8ED6D1E4002@bag.python.org> Author: antoine.pitrou Date: Fri Mar 13 23:38:28 2009 New Revision: 70350 Log: Blocked revisions 70349 via svnmerge ........ r70349 | antoine.pitrou | 2009-03-13 23:33:17 +0100 (ven., 13 mars 2009) | 4 lines The error detection code in FileIO.close() could fail to reflect the `errno` value, and report it as -1 instead. ........ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Sat Mar 14 00:11:22 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 13 Mar 2009 23:11:22 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090313231122.BBF2C1E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/446 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_pipes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sat Mar 14 00:28:44 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 14 Mar 2009 00:28:44 +0100 (CET) Subject: [Python-checkins] r70351 - peps/trunk/pep-0378.txt Message-ID: <20090313232844.AFA011E4002@bag.python.org> Author: raymond.hettinger Date: Sat Mar 14 00:28:44 2009 New Revision: 70351 Log: Update PEP: * Summarize commentary to date. * Add APOSTROPHE and non-breaking SPACE to the list of separators. * Add more links to external references. * Detail issues with the locale module. * Clarify how proposal II is parsed. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Sat Mar 14 00:28:44 2009 @@ -25,6 +25,16 @@ users and non-professional programmers find the locale approach to be frustrating, arcane and non-obvious. +The locale module presents two other challenges. First, it is +a global setting and not suitable for multi-threaded apps that +need to serve-up requests in multiple locales. Second, the +name of a relevant locale (perhaps "de_DE") can vary from +platform to platform or may not be defined at all. The docs +for the locale module describe these and `other challenges`_ +in detail. + +.. _`other challenges`: http://docs.python.org/library/locale.html#background-details-hints-tips-and-caveats + It is not the goal to replace locale or to accommodate every possible convention. The goal is to make a common task easier for many users. @@ -54,17 +64,19 @@ handled by the "n" specifier in the locale module (albeit only for integers). -Visual Basic and its brethren (like MS Excel) use a completely +Visual Basic and its brethren (like `MS Excel`_) use a completely different style and have ultra-flexible custom format specifiers like:: "_($* #,##0_)". +.. _`MS Excel`: http://www.brainbell.com/tutorials/ms-office/excel/Create_Custom_Number_Formats.htm + `COBOL`_ uses picture clauses like:: - PIC $***,**9.99CR + PICTURE $***,**9.99CR -.. _`COBOL`: http://en.wikipedia.org/wiki/Cobol +.. _`COBOL`: http://en.wikipedia.org/wiki/Cobol#Syntactic_features `Common Lisp`_ uses a COLON before the ``~D`` decimal type specifier to emit a COMMA as a thousands separator. The general form of ``~D`` is @@ -91,7 +103,7 @@ Proposal I (from Nick Coghlan) ============================== -A comma will be added to the format() specifier mini-language: +A comma will be added to the format() specifier mini-language:: [[fill]align][sign][#][0][width][,][.precision][type] @@ -124,15 +136,15 @@ Make both the thousands separator and decimal separator user specifiable but not locale aware. For simplicity, limit the -choices to a COMMA, DOT, SPACE, or UNDERSCORE. +choices to a COMMA, DOT, SPACE, APOSTROPHE or UNDERSCORE. +The SPACE can be eitherU +0020 or U+00A0. Whenever the separator is followed by a precision, it is a -decimal separator and the optional separator preceding it is a -thousands separator. When the precision is absent, the -context is integral and a lone specifier means a thousands -separator:: +decimal separator and an optional separator preceding it is a +thousands separator. When the precision is absent, a lone +specifier means a thousands separator:: -[[fill]align][sign][#][0][width][tsep|([tsep] dsep precision)][type] +[[fill]align][sign][#][0][width][tsep][dsep precision]][type] Examples:: @@ -142,13 +154,12 @@ format(1234, "8 ,f") --> ' 1 234,0' format(1234, "8d") --> ' 1234' format(1234, "8,d") --> ' 1,234' + format(1234, "8_d") --> ' 1_234' This proposal meets mosts needs (except for people wanting grouping for hundreds or ten-thousands), but it comes at the expense of being a little more complicated to learn and -remember. Also, it makes it more challenging to write custom -__format__ methods that follow the format specification -mini-language. +remember. As shown in the examples, the *width* argument means the total length including the thousands separators and decimal separators. @@ -179,6 +190,32 @@ to write custom __format__ methods. That way Decimal.__format__ would not have to be written from scratch. +* Antoine Pitrou noted that the provision for a SPACE separator + should also allow a non-breaking space (U+00A0). + +* A poster on the newgroup, Wolfgang Rohdewald, noted that a + convention in Switzerland is use an APOSTROPHE as a + thousands separator, ``12`000.99``. + + +Commentary +========== + +* Some commenters do not like the idea of format strings at all + and find them to be unreadable. Suggested alternatives include + the COBOL style PICTURE approach or a convenience function with + keyword arguments for every possible combination. + +* Some newsgroup respondants think there is no place for any + scripts that are not internationalized and that it is a step + backwards to provide a simple way to hardwire a given convention. + +* Another thought is that embedding some particular convention in + individual format strings makes it hard to change that convention + later. No workable alternative was suggested but the general idea + is to set the convention once and have it apply everywhere (others + commented that locale already does this). + Copyright ========= From python-checkins at python.org Sat Mar 14 00:42:56 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 14 Mar 2009 00:42:56 +0100 (CET) Subject: [Python-checkins] r70352 - in python/branches/py3k: Lib/test/test_largefile.py Misc/NEWS Modules/_fileio.c Message-ID: <20090313234256.5E2481E4002@bag.python.org> Author: antoine.pitrou Date: Sat Mar 14 00:42:55 2009 New Revision: 70352 Log: Issue #5016: FileIO.seekable() could return False if the file position was negative when truncated to a C int. Patch by Victor Stinner. Modified: python/branches/py3k/Lib/test/test_largefile.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_fileio.c Modified: python/branches/py3k/Lib/test/test_largefile.py ============================================================================== --- python/branches/py3k/Lib/test/test_largefile.py (original) +++ python/branches/py3k/Lib/test/test_largefile.py Sat Mar 14 00:42:55 2009 @@ -133,6 +133,15 @@ f.seek(0) self.assertEqual(len(f.read()), 1) # else wasn't truncated + def test_seekable(self): + # Issue #5016; seekable() can return False when the current position + # is negative when truncated to an int. + for pos in (2**31-1, 2**31, 2**31+1): + with self.open(TESTFN, 'rb') as f: + f.seek(pos) + self.assert_(f.seekable()) + + def test_main(): # On Windows and Mac OSX this test comsumes large resources; It # takes a long time to build the >2GB file and takes >2GB of disk @@ -172,6 +181,7 @@ with _open(TESTFN, 'wb') as f: if hasattr(f, 'truncate'): suite.addTest(TestCase('test_truncate')) + suite.addTest(TestCase('test_seekable')) unlink(TESTFN) try: run_unittest(suite) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Mar 14 00:42:55 2009 @@ -21,6 +21,9 @@ - The error detection code in FileIO.close() could fail to reflect the `errno` value, and report it as -1 instead. +- Issue #5016: FileIO.seekable() could return False if the file position + was negative when truncated to a C int. Patch by Victor Stinner. + What's New in Python 3.1 alpha 1 ================================ Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Sat Mar 14 00:42:55 2009 @@ -66,6 +66,8 @@ static PyObject * portable_lseek(int fd, PyObject *posobj, int whence); +static PyObject *portable_lseek(int fd, PyObject *posobj, int whence); + /* Returns 0 on success, -1 with exception set on failure. */ static int internal_close(PyFileIOObject *self) @@ -441,14 +443,14 @@ if (self->fd < 0) return err_closed(); if (self->seekable < 0) { - int ret; - Py_BEGIN_ALLOW_THREADS - ret = lseek(self->fd, 0, SEEK_CUR); - Py_END_ALLOW_THREADS - if (ret < 0) + PyObject *pos = portable_lseek(self->fd, NULL, SEEK_CUR); + if (pos == NULL) { + PyErr_Clear(); self->seekable = 0; - else + } else { + Py_DECREF(pos); self->seekable = 1; + } } return PyBool_FromLong((long) self->seekable); } From python-checkins at python.org Sat Mar 14 00:46:18 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 14 Mar 2009 00:46:18 +0100 (CET) Subject: [Python-checkins] r70353 - in python/branches/release30-maint: Lib/test/test_largefile.py Misc/NEWS Modules/_fileio.c Message-ID: <20090313234618.74F241E4002@bag.python.org> Author: antoine.pitrou Date: Sat Mar 14 00:46:17 2009 New Revision: 70353 Log: Merged revisions 70352 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70352 | antoine.pitrou | 2009-03-14 00:42:55 +0100 (sam., 14 mars 2009) | 4 lines Issue #5016: FileIO.seekable() could return False if the file position was negative when truncated to a C int. Patch by Victor Stinner. ........ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/test/test_largefile.py python/branches/release30-maint/Misc/NEWS python/branches/release30-maint/Modules/_fileio.c Modified: python/branches/release30-maint/Lib/test/test_largefile.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_largefile.py (original) +++ python/branches/release30-maint/Lib/test/test_largefile.py Sat Mar 14 00:46:17 2009 @@ -131,6 +131,15 @@ f.seek(0) self.assertEqual(len(f.read()), 1) # else wasn't truncated + def test_seekable(self): + # Issue #5016; seekable() can return False when the current position + # is negative when truncated to an int. + for pos in (2**31-1, 2**31, 2**31+1): + with open(TESTFN, 'rb') as f: + f.seek(pos) + self.assert_(f.seekable()) + + def test_main(): # On Windows and Mac OSX this test comsumes large resources; It # takes a long time to build the >2GB file and takes >2GB of disk @@ -165,6 +174,7 @@ with open(TESTFN, 'w') as f: if hasattr(f, 'truncate'): suite.addTest(TestCase('test_truncate')) + suite.addTest(TestCase('test_seekable')) unlink(TESTFN) try: run_unittest(suite) Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Sat Mar 14 00:46:17 2009 @@ -24,6 +24,9 @@ Library ------- +- Issue #5016: FileIO.seekable() could return False if the file position + was negative when truncated to a C int. Patch by Victor Stinner. + - Issue #5179: Fixed subprocess handle leak on failure on windows. - Issue #5282: Fixed mmap resize on 32bit windows and unix. When offset > 0, Modified: python/branches/release30-maint/Modules/_fileio.c ============================================================================== --- python/branches/release30-maint/Modules/_fileio.c (original) +++ python/branches/release30-maint/Modules/_fileio.c Sat Mar 14 00:46:17 2009 @@ -58,6 +58,8 @@ static PyObject * portable_lseek(int fd, PyObject *posobj, int whence); +static PyObject *portable_lseek(int fd, PyObject *posobj, int whence); + /* Returns 0 on success, -1 with exception set on failure. */ static int internal_close(PyFileIOObject *self) @@ -396,14 +398,14 @@ if (self->fd < 0) return err_closed(); if (self->seekable < 0) { - int ret; - Py_BEGIN_ALLOW_THREADS - ret = lseek(self->fd, 0, SEEK_CUR); - Py_END_ALLOW_THREADS - if (ret < 0) + PyObject *pos = portable_lseek(self->fd, NULL, SEEK_CUR); + if (pos == NULL) { + PyErr_Clear(); self->seekable = 0; - else + } else { + Py_DECREF(pos); self->seekable = 1; + } } return PyBool_FromLong((long) self->seekable); } From python-checkins at python.org Sat Mar 14 00:52:27 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 14 Mar 2009 00:52:27 +0100 (CET) Subject: [Python-checkins] r70354 - peps/trunk/pep-0378.txt Message-ID: <20090313235227.20FBF1E4002@bag.python.org> Author: raymond.hettinger Date: Sat Mar 14 00:52:26 2009 New Revision: 70354 Log: * Minor edits/typos. * Link to Babel project. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Sat Mar 14 00:52:26 2009 @@ -18,8 +18,7 @@ with a thousands separator. Adding thousands separators is one of the simplest ways to -improve the professional appearance and readability of output -exposed to end users. +improve the professional appearance and readability of output. In the finance world, output with commas is the norm. Finance users and non-professional programmers find the locale @@ -30,14 +29,17 @@ need to serve-up requests in multiple locales. Second, the name of a relevant locale (perhaps "de_DE") can vary from platform to platform or may not be defined at all. The docs -for the locale module describe these and `other challenges`_ +for the locale module describe these and `many other challenges`_ in detail. -.. _`other challenges`: http://docs.python.org/library/locale.html#background-details-hints-tips-and-caveats +.. _`many other challenges`: http://docs.python.org/library/locale.html#background-details-hints-tips-and-caveats -It is not the goal to replace locale or to accommodate every -possible convention. The goal is to make a common task easier -for many users. +It is not the goal to replace the locale module or to +accommodate every possible convention. Such tasks are better +suited to robust tools like `Babel`_ . Instead, our goal is to +make a common, everyday task easier for many users. + +.. _`Babel`: http://babel.edgewall.org/ Current Version of the Mini-Language @@ -81,7 +83,7 @@ `Common Lisp`_ uses a COLON before the ``~D`` decimal type specifier to emit a COMMA as a thousands separator. The general form of ``~D`` is ``~mincol,padchar,commachar,commaintervalD``. The *padchar* defaults -to SPACE. The *commachar* defaults to COLON. The *commainterval* +to SPACE. The *commachar* defaults to COMMA. The *commainterval* defaults to three. :: @@ -137,9 +139,9 @@ Make both the thousands separator and decimal separator user specifiable but not locale aware. For simplicity, limit the choices to a COMMA, DOT, SPACE, APOSTROPHE or UNDERSCORE. -The SPACE can be eitherU +0020 or U+00A0. +The SPACE can be either U+0020 or U+00A0. -Whenever the separator is followed by a precision, it is a +Whenever a separator is followed by a precision, it is a decimal separator and an optional separator preceding it is a thousands separator. When the precision is absent, a lone specifier means a thousands separator:: @@ -156,10 +158,8 @@ format(1234, "8,d") --> ' 1,234' format(1234, "8_d") --> ' 1_234' -This proposal meets mosts needs (except for people wanting -grouping for hundreds or ten-thousands), but it comes at the -expense of being a little more complicated to learn and -remember. +This proposal meets mosts needs , but it comes at the expense +of being a little more complicated to learn and remember. As shown in the examples, the *width* argument means the total length including the thousands separators and decimal separators. @@ -172,7 +172,7 @@ The difference between the two proposals is that the first is hard-wired to a COMMA for a thousands separator and a DOT as a decimal separator. -The second allows either separator to be one of four possibilities. +The second allows either separator to be one of several possibilities. @@ -187,8 +187,8 @@ * Eric Smith would like the C version of the mini-language parser to be exposed with hooks that would make it easier - to write custom __format__ methods. That way - Decimal.__format__ would not have to be written from scratch. + to write custom *__format__* methods. That way, methods like + *Decimal.__format__* would not have to be written from scratch. * Antoine Pitrou noted that the provision for a SPACE separator should also allow a non-breaking space (U+00A0). @@ -214,7 +214,7 @@ individual format strings makes it hard to change that convention later. No workable alternative was suggested but the general idea is to set the convention once and have it apply everywhere (others - commented that locale already does this). + commented that locale already provides a way to do this). Copyright From buildbot at python.org Sat Mar 14 00:54:11 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 13 Mar 2009 23:54:11 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090313235411.C5B2F1E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/417 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From python-checkins at python.org Sat Mar 14 00:58:26 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 14 Mar 2009 00:58:26 +0100 (CET) Subject: [Python-checkins] r70355 - peps/trunk/pep-0378.txt Message-ID: <20090313235826.10C241E4002@bag.python.org> Author: raymond.hettinger Date: Sat Mar 14 00:58:25 2009 New Revision: 70355 Log: Typo Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Sat Mar 14 00:58:25 2009 @@ -194,7 +194,7 @@ should also allow a non-breaking space (U+00A0). * A poster on the newgroup, Wolfgang Rohdewald, noted that a - convention in Switzerland is use an APOSTROPHE as a + convention in Switzerland is to use an APOSTROPHE as a thousands separator, ``12`000.99``. From python-checkins at python.org Sat Mar 14 01:07:22 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 14 Mar 2009 01:07:22 +0100 (CET) Subject: [Python-checkins] r70356 - in python/trunk: Lib/locale.py Lib/test/test_locale.py Misc/NEWS Message-ID: <20090314000722.516AE1E4002@bag.python.org> Author: antoine.pitrou Date: Sat Mar 14 01:07:21 2009 New Revision: 70356 Log: Issue #1222: locale.format() bug when the thousands separator is a space character. Modified: python/trunk/Lib/locale.py python/trunk/Lib/test/test_locale.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/locale.py ============================================================================== --- python/trunk/Lib/locale.py (original) +++ python/trunk/Lib/locale.py Sat Mar 14 01:07:21 2009 @@ -108,6 +108,19 @@ # Author: Martin von Loewis # improved by Georg Brandl +# Iterate over grouping intervals +def _grouping_intervals(grouping): + for interval in grouping: + # if grouping is -1, we are done + if interval == CHAR_MAX: + return + # 0: re-use last group ad infinitum + if interval == 0: + while True: + yield last_interval + yield interval + last_interval = interval + #perform the grouping from right to left def _group(s, monetary=False): conv = localeconv() @@ -117,35 +130,41 @@ return (s, 0) result = "" seps = 0 - spaces = "" if s[-1] == ' ': - sp = s.find(' ') - spaces = s[sp:] - s = s[:sp] - while s and grouping: - # if grouping is -1, we are done - if grouping[0] == CHAR_MAX: + stripped = s.rstrip() + right_spaces = s[len(stripped):] + s = stripped + else: + right_spaces = '' + left_spaces = '' + groups = [] + for interval in _grouping_intervals(grouping): + if not s or s[-1] not in "0123456789": + # only non-digit characters remain (sign, spaces) + left_spaces = s + s = '' break - # 0: re-use last group ad infinitum - elif grouping[0] != 0: - #process last group - group = grouping[0] - grouping = grouping[1:] - if result: - result = s[-group:] + thousands_sep + result - seps += 1 - else: - result = s[-group:] - s = s[:-group] - if s and s[-1] not in "0123456789": - # the leading string is only spaces and signs - return s + result + spaces, seps - if not result: - return s + spaces, seps + groups.append(s[-interval:]) + s = s[:-interval] if s: - result = s + thousands_sep + result - seps += 1 - return result + spaces, seps + groups.append(s) + groups.reverse() + return ( + left_spaces + thousands_sep.join(groups) + right_spaces, + len(groups) - 1 + ) + +# Strip a given amount of excess padding from the given string +def _strip_padding(s, amount): + lpos = 0 + while amount and s[lpos] == ' ': + lpos += 1 + amount -= 1 + rpos = len(s) - 1 + while amount and s[rpos] == ' ': + rpos -= 1 + amount -= 1 + return s[lpos:rpos+1] def format(percent, value, grouping=False, monetary=False, *additional): """Returns the locale-aware substitution of a %? specifier @@ -170,14 +189,14 @@ decimal_point = localeconv()[monetary and 'mon_decimal_point' or 'decimal_point'] formatted = decimal_point.join(parts) - while seps: - sp = formatted.find(' ') - if sp == -1: break - formatted = formatted[:sp] + formatted[sp+1:] - seps -= 1 + if seps: + formatted = _strip_padding(formatted, seps) elif percent[-1] in 'diu': + seps = 0 if grouping: - formatted = _group(formatted, monetary=monetary)[0] + formatted, seps = _group(formatted, monetary=monetary) + if seps: + formatted = _strip_padding(formatted, seps) return formatted import re, operator Modified: python/trunk/Lib/test/test_locale.py ============================================================================== --- python/trunk/Lib/test/test_locale.py (original) +++ python/trunk/Lib/test/test_locale.py Sat Mar 14 01:07:21 2009 @@ -105,6 +105,32 @@ } +class FrFRCookedTest(BaseCookedTest): + # A cooked "fr_FR" locale with a space character as decimal separator + # and a non-ASCII currency symbol. + + cooked_values = { + 'currency_symbol': '\xe2\x82\xac', + 'decimal_point': ',', + 'frac_digits': 2, + 'grouping': [3, 3, 0], + 'int_curr_symbol': 'EUR ', + 'int_frac_digits': 2, + 'mon_decimal_point': ',', + 'mon_grouping': [3, 3, 0], + 'mon_thousands_sep': ' ', + 'n_cs_precedes': 0, + 'n_sep_by_space': 1, + 'n_sign_posn': 1, + 'negative_sign': '-', + 'p_cs_precedes': 0, + 'p_sep_by_space': 1, + 'p_sign_posn': 1, + 'positive_sign': '', + 'thousands_sep': ' ' + } + + class BaseFormattingTest(object): # # Utility functions for formatting tests @@ -152,6 +178,12 @@ self._test_format("%+d", 4200, grouping=True, out='+4%s200' % self.sep) self._test_format("%+d", -4200, grouping=True, out='-4%s200' % self.sep) + def test_integer_grouping_and_padding(self): + self._test_format("%10d", 4200, grouping=True, + out=('4%s200' % self.sep).rjust(10)) + self._test_format("%-10d", -4200, grouping=True, + out=('-4%s200' % self.sep).ljust(10)) + def test_simple(self): self._test_format("%f", 1024, grouping=0, out='1024.000000') self._test_format("%f", 102, grouping=0, out='102.000000') @@ -223,6 +255,49 @@ self._test_format("%9.2f", 12345.67, grouping=True, out=' 12345.67') +class TestFrFRNumberFormatting(FrFRCookedTest, BaseFormattingTest): + # Test number formatting with a cooked "fr_FR" locale. + + def test_decimal_point(self): + self._test_format("%.2f", 12345.67, out='12345,67') + + def test_grouping(self): + self._test_format("%.2f", 345.67, grouping=True, out='345,67') + self._test_format("%.2f", 12345.67, grouping=True, out='12 345,67') + + def test_grouping_and_padding(self): + self._test_format("%6.2f", 345.67, grouping=True, out='345,67') + self._test_format("%7.2f", 345.67, grouping=True, out=' 345,67') + self._test_format("%8.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%9.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%10.2f", 12345.67, grouping=True, out=' 12 345,67') + self._test_format("%-6.2f", 345.67, grouping=True, out='345,67') + self._test_format("%-7.2f", 345.67, grouping=True, out='345,67 ') + self._test_format("%-8.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%-9.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%-10.2f", 12345.67, grouping=True, out='12 345,67 ') + + def test_integer_grouping(self): + self._test_format("%d", 200, grouping=True, out='200') + self._test_format("%d", 4200, grouping=True, out='4 200') + + def test_integer_grouping_and_padding(self): + self._test_format("%4d", 4200, grouping=True, out='4 200') + self._test_format("%5d", 4200, grouping=True, out='4 200') + self._test_format("%10d", 4200, grouping=True, out='4 200'.rjust(10)) + self._test_format("%-4d", 4200, grouping=True, out='4 200') + self._test_format("%-5d", 4200, grouping=True, out='4 200') + self._test_format("%-10d", 4200, grouping=True, out='4 200'.ljust(10)) + + def test_currency(self): + euro = u'\u20ac'.encode('utf-8') + self._test_currency(50000, "50000,00 " + euro) + self._test_currency(50000, "50 000,00 " + euro, grouping=True) + # XXX is the trailing space a bug? + self._test_currency(50000, "50 000,00 EUR ", + grouping=True, international=True) + + class TestStringMethods(BaseLocalizedTest): locale_type = locale.LC_CTYPE @@ -277,7 +352,8 @@ tests = [ TestMiscellaneous, TestEnUSNumberFormatting, - TestCNumberFormatting + TestCNumberFormatting, + TestFrFRNumberFormatting, ] # TestSkipped can't be raised inside unittests, handle it manually instead try: Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sat Mar 14 01:07:21 2009 @@ -171,6 +171,9 @@ Library ------- +- Issue #1222: locale.format() bug when the thousands separator is a space + character. + - Issue #5472: Fixed distutils.test_util tear down. Original patch by Tim Golden. From python-checkins at python.org Sat Mar 14 01:13:14 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 14 Mar 2009 01:13:14 +0100 (CET) Subject: [Python-checkins] r70357 - in python/branches/py3k: Lib/locale.py Lib/test/test_locale.py Misc/NEWS Message-ID: <20090314001314.351BD1E4002@bag.python.org> Author: antoine.pitrou Date: Sat Mar 14 01:13:13 2009 New Revision: 70357 Log: Merged revisions 70356 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70356 | antoine.pitrou | 2009-03-14 01:07:21 +0100 (sam., 14 mars 2009) | 3 lines Issue #1222: locale.format() bug when the thousands separator is a space character. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/locale.py python/branches/py3k/Lib/test/test_locale.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/locale.py ============================================================================== --- python/branches/py3k/Lib/locale.py (original) +++ python/branches/py3k/Lib/locale.py Sat Mar 14 01:13:13 2009 @@ -115,6 +115,19 @@ # Author: Martin von Loewis # improved by Georg Brandl +# Iterate over grouping intervals +def _grouping_intervals(grouping): + for interval in grouping: + # if grouping is -1, we are done + if interval == CHAR_MAX: + return + # 0: re-use last group ad infinitum + if interval == 0: + while True: + yield last_interval + yield interval + last_interval = interval + #perform the grouping from right to left def _group(s, monetary=False): conv = localeconv() @@ -124,35 +137,41 @@ return (s, 0) result = "" seps = 0 - spaces = "" if s[-1] == ' ': - sp = s.find(' ') - spaces = s[sp:] - s = s[:sp] - while s and grouping: - # if grouping is -1, we are done - if grouping[0] == CHAR_MAX: + stripped = s.rstrip() + right_spaces = s[len(stripped):] + s = stripped + else: + right_spaces = '' + left_spaces = '' + groups = [] + for interval in _grouping_intervals(grouping): + if not s or s[-1] not in "0123456789": + # only non-digit characters remain (sign, spaces) + left_spaces = s + s = '' break - # 0: re-use last group ad infinitum - elif grouping[0] != 0: - #process last group - group = grouping[0] - grouping = grouping[1:] - if result: - result = s[-group:] + thousands_sep + result - seps += 1 - else: - result = s[-group:] - s = s[:-group] - if s and s[-1] not in "0123456789": - # the leading string is only spaces and signs - return s + result + spaces, seps - if not result: - return s + spaces, seps + groups.append(s[-interval:]) + s = s[:-interval] if s: - result = s + thousands_sep + result - seps += 1 - return result + spaces, seps + groups.append(s) + groups.reverse() + return ( + left_spaces + thousands_sep.join(groups) + right_spaces, + len(groups) - 1 + ) + +# Strip a given amount of excess padding from the given string +def _strip_padding(s, amount): + lpos = 0 + while amount and s[lpos] == ' ': + lpos += 1 + amount -= 1 + rpos = len(s) - 1 + while amount and s[rpos] == ' ': + rpos -= 1 + amount -= 1 + return s[lpos:rpos+1] def format(percent, value, grouping=False, monetary=False, *additional): """Returns the locale-aware substitution of a %? specifier @@ -177,14 +196,14 @@ decimal_point = localeconv()[monetary and 'mon_decimal_point' or 'decimal_point'] formatted = decimal_point.join(parts) - while seps: - sp = formatted.find(' ') - if sp == -1: break - formatted = formatted[:sp] + formatted[sp+1:] - seps -= 1 + if seps: + formatted = _strip_padding(formatted, seps) elif percent[-1] in 'diu': + seps = 0 if grouping: - formatted = _group(formatted, monetary=monetary)[0] + formatted, seps = _group(formatted, monetary=monetary) + if seps: + formatted = _strip_padding(formatted, seps) return formatted import re, collections Modified: python/branches/py3k/Lib/test/test_locale.py ============================================================================== --- python/branches/py3k/Lib/test/test_locale.py (original) +++ python/branches/py3k/Lib/test/test_locale.py Sat Mar 14 01:13:13 2009 @@ -103,6 +103,32 @@ } +class FrFRCookedTest(BaseCookedTest): + # A cooked "fr_FR" locale with a space character as decimal separator + # and a non-ASCII currency symbol. + + cooked_values = { + 'currency_symbol': '\u20ac', + 'decimal_point': ',', + 'frac_digits': 2, + 'grouping': [3, 3, 0], + 'int_curr_symbol': 'EUR ', + 'int_frac_digits': 2, + 'mon_decimal_point': ',', + 'mon_grouping': [3, 3, 0], + 'mon_thousands_sep': ' ', + 'n_cs_precedes': 0, + 'n_sep_by_space': 1, + 'n_sign_posn': 1, + 'negative_sign': '-', + 'p_cs_precedes': 0, + 'p_sep_by_space': 1, + 'p_sign_posn': 1, + 'positive_sign': '', + 'thousands_sep': ' ' + } + + class BaseFormattingTest(object): # # Utility functions for formatting tests @@ -150,6 +176,12 @@ self._test_format("%+d", 4200, grouping=True, out='+4%s200' % self.sep) self._test_format("%+d", -4200, grouping=True, out='-4%s200' % self.sep) + def test_integer_grouping_and_padding(self): + self._test_format("%10d", 4200, grouping=True, + out=('4%s200' % self.sep).rjust(10)) + self._test_format("%-10d", -4200, grouping=True, + out=('-4%s200' % self.sep).ljust(10)) + def test_simple(self): self._test_format("%f", 1024, grouping=0, out='1024.000000') self._test_format("%f", 102, grouping=0, out='102.000000') @@ -221,6 +253,49 @@ self._test_format("%9.2f", 12345.67, grouping=True, out=' 12345.67') +class TestFrFRNumberFormatting(FrFRCookedTest, BaseFormattingTest): + # Test number formatting with a cooked "fr_FR" locale. + + def test_decimal_point(self): + self._test_format("%.2f", 12345.67, out='12345,67') + + def test_grouping(self): + self._test_format("%.2f", 345.67, grouping=True, out='345,67') + self._test_format("%.2f", 12345.67, grouping=True, out='12 345,67') + + def test_grouping_and_padding(self): + self._test_format("%6.2f", 345.67, grouping=True, out='345,67') + self._test_format("%7.2f", 345.67, grouping=True, out=' 345,67') + self._test_format("%8.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%9.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%10.2f", 12345.67, grouping=True, out=' 12 345,67') + self._test_format("%-6.2f", 345.67, grouping=True, out='345,67') + self._test_format("%-7.2f", 345.67, grouping=True, out='345,67 ') + self._test_format("%-8.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%-9.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%-10.2f", 12345.67, grouping=True, out='12 345,67 ') + + def test_integer_grouping(self): + self._test_format("%d", 200, grouping=True, out='200') + self._test_format("%d", 4200, grouping=True, out='4 200') + + def test_integer_grouping_and_padding(self): + self._test_format("%4d", 4200, grouping=True, out='4 200') + self._test_format("%5d", 4200, grouping=True, out='4 200') + self._test_format("%10d", 4200, grouping=True, out='4 200'.rjust(10)) + self._test_format("%-4d", 4200, grouping=True, out='4 200') + self._test_format("%-5d", 4200, grouping=True, out='4 200') + self._test_format("%-10d", 4200, grouping=True, out='4 200'.ljust(10)) + + def test_currency(self): + euro = '\u20ac' + self._test_currency(50000, "50000,00 " + euro) + self._test_currency(50000, "50 000,00 " + euro, grouping=True) + # XXX is the trailing space a bug? + self._test_currency(50000, "50 000,00 EUR ", + grouping=True, international=True) + + class TestMiscellaneous(unittest.TestCase): def test_getpreferredencoding(self): # Invoke getpreferredencoding to make sure it does not cause exceptions. @@ -240,7 +315,8 @@ tests = [ TestMiscellaneous, TestEnUSNumberFormatting, - TestCNumberFormatting + TestCNumberFormatting, + TestFrFRNumberFormatting, ] # TestSkipped can't be raised inside unittests, handle it manually instead try: Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Mar 14 01:13:13 2009 @@ -202,6 +202,9 @@ Library ------- +- Issue #1222: locale.format() bug when the thousands separator is a space + character. + - Issue #5472: Fixed distutils.test_util tear down. Original patch by Tim Golden. From python-checkins at python.org Sat Mar 14 01:13:36 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 14 Mar 2009 01:13:36 +0100 (CET) Subject: [Python-checkins] r70358 - in python/branches/release26-maint: Lib/locale.py Lib/test/test_locale.py Misc/NEWS Message-ID: <20090314001336.C99281E4002@bag.python.org> Author: antoine.pitrou Date: Sat Mar 14 01:13:36 2009 New Revision: 70358 Log: Merged revisions 70356 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70356 | antoine.pitrou | 2009-03-14 01:07:21 +0100 (sam., 14 mars 2009) | 3 lines Issue #1222: locale.format() bug when the thousands separator is a space character. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/locale.py python/branches/release26-maint/Lib/test/test_locale.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/locale.py ============================================================================== --- python/branches/release26-maint/Lib/locale.py (original) +++ python/branches/release26-maint/Lib/locale.py Sat Mar 14 01:13:36 2009 @@ -108,6 +108,19 @@ # Author: Martin von Loewis # improved by Georg Brandl +# Iterate over grouping intervals +def _grouping_intervals(grouping): + for interval in grouping: + # if grouping is -1, we are done + if interval == CHAR_MAX: + return + # 0: re-use last group ad infinitum + if interval == 0: + while True: + yield last_interval + yield interval + last_interval = interval + #perform the grouping from right to left def _group(s, monetary=False): conv = localeconv() @@ -117,35 +130,41 @@ return (s, 0) result = "" seps = 0 - spaces = "" if s[-1] == ' ': - sp = s.find(' ') - spaces = s[sp:] - s = s[:sp] - while s and grouping: - # if grouping is -1, we are done - if grouping[0] == CHAR_MAX: + stripped = s.rstrip() + right_spaces = s[len(stripped):] + s = stripped + else: + right_spaces = '' + left_spaces = '' + groups = [] + for interval in _grouping_intervals(grouping): + if not s or s[-1] not in "0123456789": + # only non-digit characters remain (sign, spaces) + left_spaces = s + s = '' break - # 0: re-use last group ad infinitum - elif grouping[0] != 0: - #process last group - group = grouping[0] - grouping = grouping[1:] - if result: - result = s[-group:] + thousands_sep + result - seps += 1 - else: - result = s[-group:] - s = s[:-group] - if s and s[-1] not in "0123456789": - # the leading string is only spaces and signs - return s + result + spaces, seps - if not result: - return s + spaces, seps + groups.append(s[-interval:]) + s = s[:-interval] if s: - result = s + thousands_sep + result - seps += 1 - return result + spaces, seps + groups.append(s) + groups.reverse() + return ( + left_spaces + thousands_sep.join(groups) + right_spaces, + len(groups) - 1 + ) + +# Strip a given amount of excess padding from the given string +def _strip_padding(s, amount): + lpos = 0 + while amount and s[lpos] == ' ': + lpos += 1 + amount -= 1 + rpos = len(s) - 1 + while amount and s[rpos] == ' ': + rpos -= 1 + amount -= 1 + return s[lpos:rpos+1] def format(percent, value, grouping=False, monetary=False, *additional): """Returns the locale-aware substitution of a %? specifier @@ -170,14 +189,14 @@ decimal_point = localeconv()[monetary and 'mon_decimal_point' or 'decimal_point'] formatted = decimal_point.join(parts) - while seps: - sp = formatted.find(' ') - if sp == -1: break - formatted = formatted[:sp] + formatted[sp+1:] - seps -= 1 + if seps: + formatted = _strip_padding(formatted, seps) elif percent[-1] in 'diu': + seps = 0 if grouping: - formatted = _group(formatted, monetary=monetary)[0] + formatted, seps = _group(formatted, monetary=monetary) + if seps: + formatted = _strip_padding(formatted, seps) return formatted import re, operator Modified: python/branches/release26-maint/Lib/test/test_locale.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_locale.py (original) +++ python/branches/release26-maint/Lib/test/test_locale.py Sat Mar 14 01:13:36 2009 @@ -105,6 +105,32 @@ } +class FrFRCookedTest(BaseCookedTest): + # A cooked "fr_FR" locale with a space character as decimal separator + # and a non-ASCII currency symbol. + + cooked_values = { + 'currency_symbol': '\xe2\x82\xac', + 'decimal_point': ',', + 'frac_digits': 2, + 'grouping': [3, 3, 0], + 'int_curr_symbol': 'EUR ', + 'int_frac_digits': 2, + 'mon_decimal_point': ',', + 'mon_grouping': [3, 3, 0], + 'mon_thousands_sep': ' ', + 'n_cs_precedes': 0, + 'n_sep_by_space': 1, + 'n_sign_posn': 1, + 'negative_sign': '-', + 'p_cs_precedes': 0, + 'p_sep_by_space': 1, + 'p_sign_posn': 1, + 'positive_sign': '', + 'thousands_sep': ' ' + } + + class BaseFormattingTest(object): # # Utility functions for formatting tests @@ -152,6 +178,12 @@ self._test_format("%+d", 4200, grouping=True, out='+4%s200' % self.sep) self._test_format("%+d", -4200, grouping=True, out='-4%s200' % self.sep) + def test_integer_grouping_and_padding(self): + self._test_format("%10d", 4200, grouping=True, + out=('4%s200' % self.sep).rjust(10)) + self._test_format("%-10d", -4200, grouping=True, + out=('-4%s200' % self.sep).ljust(10)) + def test_simple(self): self._test_format("%f", 1024, grouping=0, out='1024.000000') self._test_format("%f", 102, grouping=0, out='102.000000') @@ -223,6 +255,49 @@ self._test_format("%9.2f", 12345.67, grouping=True, out=' 12345.67') +class TestFrFRNumberFormatting(FrFRCookedTest, BaseFormattingTest): + # Test number formatting with a cooked "fr_FR" locale. + + def test_decimal_point(self): + self._test_format("%.2f", 12345.67, out='12345,67') + + def test_grouping(self): + self._test_format("%.2f", 345.67, grouping=True, out='345,67') + self._test_format("%.2f", 12345.67, grouping=True, out='12 345,67') + + def test_grouping_and_padding(self): + self._test_format("%6.2f", 345.67, grouping=True, out='345,67') + self._test_format("%7.2f", 345.67, grouping=True, out=' 345,67') + self._test_format("%8.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%9.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%10.2f", 12345.67, grouping=True, out=' 12 345,67') + self._test_format("%-6.2f", 345.67, grouping=True, out='345,67') + self._test_format("%-7.2f", 345.67, grouping=True, out='345,67 ') + self._test_format("%-8.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%-9.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%-10.2f", 12345.67, grouping=True, out='12 345,67 ') + + def test_integer_grouping(self): + self._test_format("%d", 200, grouping=True, out='200') + self._test_format("%d", 4200, grouping=True, out='4 200') + + def test_integer_grouping_and_padding(self): + self._test_format("%4d", 4200, grouping=True, out='4 200') + self._test_format("%5d", 4200, grouping=True, out='4 200') + self._test_format("%10d", 4200, grouping=True, out='4 200'.rjust(10)) + self._test_format("%-4d", 4200, grouping=True, out='4 200') + self._test_format("%-5d", 4200, grouping=True, out='4 200') + self._test_format("%-10d", 4200, grouping=True, out='4 200'.ljust(10)) + + def test_currency(self): + euro = u'\u20ac'.encode('utf-8') + self._test_currency(50000, "50000,00 " + euro) + self._test_currency(50000, "50 000,00 " + euro, grouping=True) + # XXX is the trailing space a bug? + self._test_currency(50000, "50 000,00 EUR ", + grouping=True, international=True) + + class TestStringMethods(BaseLocalizedTest): locale_type = locale.LC_CTYPE @@ -277,7 +352,8 @@ tests = [ TestMiscellaneous, TestEnUSNumberFormatting, - TestCNumberFormatting + TestCNumberFormatting, + TestFrFRNumberFormatting, ] # TestSkipped can't be raised inside unittests, handle it manually instead try: Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Sat Mar 14 01:13:36 2009 @@ -89,6 +89,9 @@ Library ------- +- Issue #1222: locale.format() bug when the thousands separator is a space + character. + - Issue #4792: Prevent a segfault in _tkinter by using the guaranteed to be safe interp argument given to the PythonCmd in place of the Tcl interpreter taken from a PythonCmd_ClientData. From python-checkins at python.org Sat Mar 14 01:15:12 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 14 Mar 2009 01:15:12 +0100 (CET) Subject: [Python-checkins] r70359 - in python/branches/release30-maint: Lib/locale.py Lib/test/test_locale.py Misc/NEWS Message-ID: <20090314001512.1C04D1E4002@bag.python.org> Author: antoine.pitrou Date: Sat Mar 14 01:15:11 2009 New Revision: 70359 Log: Merged revisions 70357 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70357 | antoine.pitrou | 2009-03-14 01:13:13 +0100 (sam., 14 mars 2009) | 9 lines Merged revisions 70356 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70356 | antoine.pitrou | 2009-03-14 01:07:21 +0100 (sam., 14 mars 2009) | 3 lines Issue #1222: locale.format() bug when the thousands separator is a space character. ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/locale.py python/branches/release30-maint/Lib/test/test_locale.py python/branches/release30-maint/Misc/NEWS Modified: python/branches/release30-maint/Lib/locale.py ============================================================================== --- python/branches/release30-maint/Lib/locale.py (original) +++ python/branches/release30-maint/Lib/locale.py Sat Mar 14 01:15:11 2009 @@ -115,6 +115,19 @@ # Author: Martin von Loewis # improved by Georg Brandl +# Iterate over grouping intervals +def _grouping_intervals(grouping): + for interval in grouping: + # if grouping is -1, we are done + if interval == CHAR_MAX: + return + # 0: re-use last group ad infinitum + if interval == 0: + while True: + yield last_interval + yield interval + last_interval = interval + #perform the grouping from right to left def _group(s, monetary=False): conv = localeconv() @@ -124,35 +137,41 @@ return (s, 0) result = "" seps = 0 - spaces = "" if s[-1] == ' ': - sp = s.find(' ') - spaces = s[sp:] - s = s[:sp] - while s and grouping: - # if grouping is -1, we are done - if grouping[0] == CHAR_MAX: + stripped = s.rstrip() + right_spaces = s[len(stripped):] + s = stripped + else: + right_spaces = '' + left_spaces = '' + groups = [] + for interval in _grouping_intervals(grouping): + if not s or s[-1] not in "0123456789": + # only non-digit characters remain (sign, spaces) + left_spaces = s + s = '' break - # 0: re-use last group ad infinitum - elif grouping[0] != 0: - #process last group - group = grouping[0] - grouping = grouping[1:] - if result: - result = s[-group:] + thousands_sep + result - seps += 1 - else: - result = s[-group:] - s = s[:-group] - if s and s[-1] not in "0123456789": - # the leading string is only spaces and signs - return s + result + spaces, seps - if not result: - return s + spaces, seps + groups.append(s[-interval:]) + s = s[:-interval] if s: - result = s + thousands_sep + result - seps += 1 - return result + spaces, seps + groups.append(s) + groups.reverse() + return ( + left_spaces + thousands_sep.join(groups) + right_spaces, + len(groups) - 1 + ) + +# Strip a given amount of excess padding from the given string +def _strip_padding(s, amount): + lpos = 0 + while amount and s[lpos] == ' ': + lpos += 1 + amount -= 1 + rpos = len(s) - 1 + while amount and s[rpos] == ' ': + rpos -= 1 + amount -= 1 + return s[lpos:rpos+1] def format(percent, value, grouping=False, monetary=False, *additional): """Returns the locale-aware substitution of a %? specifier @@ -177,14 +196,14 @@ decimal_point = localeconv()[monetary and 'mon_decimal_point' or 'decimal_point'] formatted = decimal_point.join(parts) - while seps: - sp = formatted.find(' ') - if sp == -1: break - formatted = formatted[:sp] + formatted[sp+1:] - seps -= 1 + if seps: + formatted = _strip_padding(formatted, seps) elif percent[-1] in 'diu': + seps = 0 if grouping: - formatted = _group(formatted, monetary=monetary)[0] + formatted, seps = _group(formatted, monetary=monetary) + if seps: + formatted = _strip_padding(formatted, seps) return formatted import re, collections Modified: python/branches/release30-maint/Lib/test/test_locale.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_locale.py (original) +++ python/branches/release30-maint/Lib/test/test_locale.py Sat Mar 14 01:15:11 2009 @@ -103,6 +103,32 @@ } +class FrFRCookedTest(BaseCookedTest): + # A cooked "fr_FR" locale with a space character as decimal separator + # and a non-ASCII currency symbol. + + cooked_values = { + 'currency_symbol': '\u20ac', + 'decimal_point': ',', + 'frac_digits': 2, + 'grouping': [3, 3, 0], + 'int_curr_symbol': 'EUR ', + 'int_frac_digits': 2, + 'mon_decimal_point': ',', + 'mon_grouping': [3, 3, 0], + 'mon_thousands_sep': ' ', + 'n_cs_precedes': 0, + 'n_sep_by_space': 1, + 'n_sign_posn': 1, + 'negative_sign': '-', + 'p_cs_precedes': 0, + 'p_sep_by_space': 1, + 'p_sign_posn': 1, + 'positive_sign': '', + 'thousands_sep': ' ' + } + + class BaseFormattingTest(object): # # Utility functions for formatting tests @@ -150,6 +176,12 @@ self._test_format("%+d", 4200, grouping=True, out='+4%s200' % self.sep) self._test_format("%+d", -4200, grouping=True, out='-4%s200' % self.sep) + def test_integer_grouping_and_padding(self): + self._test_format("%10d", 4200, grouping=True, + out=('4%s200' % self.sep).rjust(10)) + self._test_format("%-10d", -4200, grouping=True, + out=('-4%s200' % self.sep).ljust(10)) + def test_simple(self): self._test_format("%f", 1024, grouping=0, out='1024.000000') self._test_format("%f", 102, grouping=0, out='102.000000') @@ -221,6 +253,49 @@ self._test_format("%9.2f", 12345.67, grouping=True, out=' 12345.67') +class TestFrFRNumberFormatting(FrFRCookedTest, BaseFormattingTest): + # Test number formatting with a cooked "fr_FR" locale. + + def test_decimal_point(self): + self._test_format("%.2f", 12345.67, out='12345,67') + + def test_grouping(self): + self._test_format("%.2f", 345.67, grouping=True, out='345,67') + self._test_format("%.2f", 12345.67, grouping=True, out='12 345,67') + + def test_grouping_and_padding(self): + self._test_format("%6.2f", 345.67, grouping=True, out='345,67') + self._test_format("%7.2f", 345.67, grouping=True, out=' 345,67') + self._test_format("%8.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%9.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%10.2f", 12345.67, grouping=True, out=' 12 345,67') + self._test_format("%-6.2f", 345.67, grouping=True, out='345,67') + self._test_format("%-7.2f", 345.67, grouping=True, out='345,67 ') + self._test_format("%-8.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%-9.2f", 12345.67, grouping=True, out='12 345,67') + self._test_format("%-10.2f", 12345.67, grouping=True, out='12 345,67 ') + + def test_integer_grouping(self): + self._test_format("%d", 200, grouping=True, out='200') + self._test_format("%d", 4200, grouping=True, out='4 200') + + def test_integer_grouping_and_padding(self): + self._test_format("%4d", 4200, grouping=True, out='4 200') + self._test_format("%5d", 4200, grouping=True, out='4 200') + self._test_format("%10d", 4200, grouping=True, out='4 200'.rjust(10)) + self._test_format("%-4d", 4200, grouping=True, out='4 200') + self._test_format("%-5d", 4200, grouping=True, out='4 200') + self._test_format("%-10d", 4200, grouping=True, out='4 200'.ljust(10)) + + def test_currency(self): + euro = '\u20ac' + self._test_currency(50000, "50000,00 " + euro) + self._test_currency(50000, "50 000,00 " + euro, grouping=True) + # XXX is the trailing space a bug? + self._test_currency(50000, "50 000,00 EUR ", + grouping=True, international=True) + + class TestMiscellaneous(unittest.TestCase): def test_getpreferredencoding(self): # Invoke getpreferredencoding to make sure it does not cause exceptions. @@ -240,7 +315,8 @@ tests = [ TestMiscellaneous, TestEnUSNumberFormatting, - TestCNumberFormatting + TestCNumberFormatting, + TestFrFRNumberFormatting, ] # TestSkipped can't be raised inside unittests, handle it manually instead try: Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Sat Mar 14 01:15:11 2009 @@ -24,6 +24,9 @@ Library ------- +- Issue #1222: locale.format() bug when the thousands separator is a space + character. + - Issue #5016: FileIO.seekable() could return False if the file position was negative when truncated to a C int. Patch by Victor Stinner. From buildbot at python.org Sat Mar 14 01:29:06 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 14 Mar 2009 00:29:06 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.0 Message-ID: <20090314002906.521171E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.0/builds/180 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sat Mar 14 01:48:29 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 14 Mar 2009 01:48:29 +0100 (CET) Subject: [Python-checkins] r70360 - peps/trunk/pep-0378.txt Message-ID: <20090314004829.D1E191E4002@bag.python.org> Author: raymond.hettinger Date: Sat Mar 14 01:48:29 2009 New Revision: 70360 Log: Link to ADA docs. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Sat Mar 14 01:48:29 2009 @@ -27,7 +27,7 @@ The locale module presents two other challenges. First, it is a global setting and not suitable for multi-threaded apps that need to serve-up requests in multiple locales. Second, the -name of a relevant locale (perhaps "de_DE") can vary from +name of a relevant locale (such as "de_DE") can vary from platform to platform or may not be defined at all. The docs for the locale module describe these and `many other challenges`_ in detail. @@ -56,7 +56,7 @@ =============== Scanning the web, I've found that thousands separators are -usually one of COMMA, DOT, SPACE, or UNDERSCORE. +usually one of COMMA, DOT, SPACE, APOSTROPHE or UNDERSCORE. When a COMMA is the decimal separator, the thousands separator is typically a DOT or SPACE (see examples from Denis Spir). @@ -197,6 +197,10 @@ convention in Switzerland is to use an APOSTROPHE as a thousands separator, ``12`000.99``. +* The `ADA language`_ allows UNDERSCORES in its numeric literals. + +.. _`ADA language`: http://archive.adaic.com/standards/83lrm/html/lrm-02-04.html + Commentary ========== From python-checkins at python.org Sat Mar 14 02:11:05 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 14 Mar 2009 02:11:05 +0100 (CET) Subject: [Python-checkins] r70361 - peps/trunk/pep-0378.txt Message-ID: <20090314011105.448FD1E404F@bag.python.org> Author: raymond.hettinger Date: Sat Mar 14 02:11:05 2009 New Revision: 70361 Log: Don't restate the obvious. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Sat Mar 14 02:11:05 2009 @@ -57,8 +57,6 @@ Scanning the web, I've found that thousands separators are usually one of COMMA, DOT, SPACE, APOSTROPHE or UNDERSCORE. -When a COMMA is the decimal separator, the thousands separator -is typically a DOT or SPACE (see examples from Denis Spir). James Knight observed that Indian/Pakistani numbering systems group by hundreds. Ben Finney noted that Chinese group by From buildbot at python.org Sat Mar 14 02:23:51 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 14 Mar 2009 01:23:51 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.0 Message-ID: <20090314012351.8FB161E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.0/builds/201 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Sat Mar 14 03:19:37 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 14 Mar 2009 02:19:37 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090314021937.7D1D21E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/722 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: antoine.pitrou,georg.brandl,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_poplib.py", line 131, in run asyncore.loop(timeout=0.1, count=1) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 204, in loop poll_fun(timeout, map) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 141, in poll read(obj) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 78, in read obj.handle_error() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 74, in read obj.handle_read_event() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 413, in handle_read_event self.handle_read() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_ssl.py", line 408, in handle_read self.send(data.lower()) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 519, in send self.initiate_send() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 506, in initiate_send num_sent = dispatcher.send(self, self.out_buffer[:512]) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 349, in send result = self.socket.send(data) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/socket.py", line 165, in _dummy raise error(EBADF, 'Bad file descriptor') error: [Errno 9] Bad file descriptor sincerely, -The Buildbot From buildbot at python.org Sat Mar 14 04:04:15 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 14 Mar 2009 03:04:15 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090314030415.552C01E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/206 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_locale test_posix ====================================================================== FAIL: test_integer_grouping_and_padding (test.test_locale.TestNumberFormatting) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_locale.py", line 181, in test_integer_grouping_and_padding out=('4%s200' % self.sep).rjust(10)) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_locale.py", line 143, in _test_format func=locale.format, **format_opts) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_locale.py", line 139, in _test_formatfunc func(format, value, **format_opts), out) AssertionError: ' 4200' != ' 4200' ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From python-checkins at python.org Sat Mar 14 04:08:00 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 14 Mar 2009 04:08:00 +0100 (CET) Subject: [Python-checkins] r70362 - peps/trunk/pep-0378.txt Message-ID: <20090314030800.9191E1E4002@bag.python.org> Author: raymond.hettinger Date: Sat Mar 14 04:08:00 2009 New Revision: 70362 Log: Wording tweaks. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Sat Mar 14 04:08:00 2009 @@ -18,10 +18,11 @@ with a thousands separator. Adding thousands separators is one of the simplest ways to -improve the professional appearance and readability of output. +humanize a program's output, improving its professional appearance +and readability. -In the finance world, output with commas is the norm. Finance -users and non-professional programmers find the locale +In the finance world, output with thousands separators is the norm. +Finance users and non-professional programmers find the locale approach to be frustrating, arcane and non-obvious. The locale module presents two other challenges. First, it is @@ -210,7 +211,8 @@ * Some newsgroup respondants think there is no place for any scripts that are not internationalized and that it is a step - backwards to provide a simple way to hardwire a given convention. + backwards to provide a simple way to hardwire a particular choice + (thus reducing incentive to use a locale sensitive approach). * Another thought is that embedding some particular convention in individual format strings makes it hard to change that convention From buildbot at python.org Sat Mar 14 04:43:01 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 14 Mar 2009 03:43:01 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090314034301.7AF5B1E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/419 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_locale test_posix ====================================================================== FAIL: test_integer_grouping_and_padding (test.test_locale.TestNumberFormatting) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_locale.py", line 181, in test_integer_grouping_and_padding out=('4%s200' % self.sep).rjust(10)) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_locale.py", line 143, in _test_format func=locale.format, **format_opts) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_locale.py", line 139, in _test_formatfunc func(format, value, **format_opts), out) AssertionError: ' 4200' != ' 4200' ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From python-checkins at python.org Sat Mar 14 08:28:36 2009 From: python-checkins at python.org (nick.coghlan) Date: Sat, 14 Mar 2009 08:28:36 +0100 (CET) Subject: [Python-checkins] r70363 - peps/trunk/pep-0377.txt Message-ID: <20090314072836.3D27A1E4002@bag.python.org> Author: nick.coghlan Date: Sat Mar 14 08:28:35 2009 New Revision: 70363 Log: Add some more to the rationale section in PEP 377 Modified: peps/trunk/pep-0377.txt Modified: peps/trunk/pep-0377.txt ============================================================================== --- peps/trunk/pep-0377.txt (original) +++ peps/trunk/pep-0377.txt Sat Mar 14 08:28:35 2009 @@ -129,40 +129,95 @@ # instead of as classes!) class CM(object): def __init__(self): - self.cmA = None - self.cmB = None + self.cmA = None + self.cmB = None def __enter__(self): - if self.cmA is not None: - raise RuntimeError("Can't re-use this CM") - self.cmA = cmA() - self.cmA.__enter__() - try: - self.cmB = cmB() - self.cmB.__enter__() - except: - self.cmA.__exit__(*sys.exc_info()) - # Can't suppress in __enter__(), so must raise + if self.cmA is not None: + raise RuntimeError("Can't re-use this CM") + self.cmA = cmA() + self.cmA.__enter__() + try: + self.cmB = cmB() + self.cmB.__enter__() + except: + self.cmA.__exit__(*sys.exc_info()) + # Can't suppress in __enter__(), so must raise + raise + + def __exit__(self, *args): + suppress = False + try: + if self.cmB is not None: + suppress = self.cmB.__exit__(*args) + except: + suppress = self.cmA.__exit__(*sys.exc_info()): + if not suppress: + # Exception has changed, so reraise explicitly raise + else: + if suppress: + # cmB already suppressed the exception, + # so don't pass it to cmA + suppress = self.cmA.__exit__(None, None, None): + else: + suppress = self.cmA.__exit__(*args): + return suppress + +With the proposed semantic change in place, the contextlib based examples +above would then "just work", but the class based version would need +adjustment to take advantage of the new semantics:: + + class CM(object): + def __init__(self): + self.cmA = None + self.cmB = None + + def __enter__(self): + if self.cmA is not None: + raise RuntimeError("Can't re-use this CM") + self.cmA = cmA() + self.cmA.__enter__() + try: + self.cmB = cmB() + self.cmB.__enter__() + except: + if self.cmA.__exit__(*sys.exc_info()): + # Suppress the exception, but don't run + # the body of the with statement either + raise SkipStatement + raise def __exit__(self, *args): - suppress = False - try: - if self.cmB is not None: - suppress = self.cmB.__exit__(*args) - except: - suppress = self.cmA.__exit__(*sys.exc_info()): - if not suppress: - # Exception has changed, so reraise explicitly - raise + suppress = False + try: + if self.cmB is not None: + suppress = self.cmB.__exit__(*args) + except: + suppress = self.cmA.__exit__(*sys.exc_info()): + if not suppress: + # Exception has changed, so reraise explicitly + raise + else: + if suppress: + # cmB already suppressed the exception, + # so don't pass it to cmA + suppress = self.cmA.__exit__(None, None, None): else: - if suppress: - # cmB already suppressed the exception, - # so don't pass it to cmA - suppress = self.cmA.__exit__(None, None, None): - else: - suppress = self.cmA.__exit__(*args): - return suppress + suppress = self.cmA.__exit__(*args): + return suppress + +There is currently a tentative suggestion [3] to add import-style syntax to +the ``with`` statement to allow multiple context managers to be included in +a single ``with`` statement without needing to use ``contextlib.nested``. In +that case the compiler has the option of simply emitting multiple ``with`` +statements at the AST level, thus allowing the semantics of actual nested +``with`` statements to be reproduced accurately. However, such a change +would highlight rather than alleviate the problem the current PEP aims to +address: it would not be possible to use ``contextlib.contextmanager``to +reliably factor out such ``with`` statements, as they would exhibit exactly +the same semantic differences as are seen with the ``combined()`` context +manager in the above example. Reference Implementation @@ -186,6 +241,9 @@ .. [2] PEP 343: The "with" Statement (http://www.python.org/dev/peps/pep-0343/) +.. [3] Import-style syntax to reduce indentation of nested with statements + (http://mail.python.org/pipermail/python-ideas/2009-March/003188.html) + Copyright ========= From python-checkins at python.org Sat Mar 14 12:57:26 2009 From: python-checkins at python.org (eric.smith) Date: Sat, 14 Mar 2009 12:57:26 +0100 (CET) Subject: [Python-checkins] r70364 - in python/trunk: Lib/test/test_str.py Lib/test/test_unicode.py Misc/NEWS Objects/stringlib/string_format.h Message-ID: <20090314115726.7ADAA1E4002@bag.python.org> Author: eric.smith Date: Sat Mar 14 12:57:26 2009 New Revision: 70364 Log: Issue 5237, Allow auto-numbered replacement fields in str.format() strings. For simple uses for str.format(), this makes the typing easier. Hopfully this will help in the adoption of str.format(). For example: 'The {} is {}'.format('sky', 'blue') You can mix and matcth auto-numbering and named replacement fields: 'The {} is {color}'.format('sky', color='blue') But you can't mix and match auto-numbering and specified numbering: 'The {0} is {}'.format('sky', 'blue') ValueError: cannot switch from manual field specification to automatic field numbering Will port to 3.1. Modified: python/trunk/Lib/test/test_str.py python/trunk/Lib/test/test_unicode.py python/trunk/Misc/NEWS python/trunk/Objects/stringlib/string_format.h Modified: python/trunk/Lib/test/test_str.py ============================================================================== --- python/trunk/Lib/test/test_str.py (original) +++ python/trunk/Lib/test/test_str.py Sat Mar 14 12:57:26 2009 @@ -347,9 +347,9 @@ self.assertRaises(ValueError, "{0!}".format, 0) self.assertRaises(ValueError, "{0!rs}".format, 0) self.assertRaises(ValueError, "{!}".format) - self.assertRaises(ValueError, "{:}".format) - self.assertRaises(ValueError, "{:s}".format) - self.assertRaises(ValueError, "{}".format) + self.assertRaises(IndexError, "{:}".format) + self.assertRaises(IndexError, "{:s}".format) + self.assertRaises(IndexError, "{}".format) # can't have a replacement on the field name portion self.assertRaises(TypeError, '{0[{1}]}'.format, 'abcdefg', 4) @@ -364,6 +364,36 @@ self.assertRaises(ValueError, format, "", "-") self.assertRaises(ValueError, "{0:=s}".format, '') + def test_format_auto_numbering(self): + class C: + def __init__(self, x=100): + self._x = x + def __format__(self, spec): + return spec + + self.assertEqual('{}'.format(10), '10') + self.assertEqual('{:5}'.format('s'), 's ') + self.assertEqual('{!r}'.format('s'), "'s'") + self.assertEqual('{._x}'.format(C(10)), '10') + self.assertEqual('{[1]}'.format([1, 2]), '2') + self.assertEqual('{[a]}'.format({'a':4, 'b':2}), '4') + self.assertEqual('a{}b{}c'.format(0, 1), 'a0b1c') + + self.assertEqual('a{:{}}b'.format('x', '^10'), 'a x b') + self.assertEqual('a{:{}x}b'.format(20, '#'), 'a0x14b') + + # can't mix and match numbering and auto-numbering + self.assertRaises(ValueError, '{}{1}'.format, 1, 2) + self.assertRaises(ValueError, '{1}{}'.format, 1, 2) + self.assertRaises(ValueError, '{:{1}}'.format, 1, 2) + self.assertRaises(ValueError, '{0:{}}'.format, 1, 2) + + # can mix and match auto-numbering and named + self.assertEqual('{f}{}'.format(4, f='test'), 'test4') + self.assertEqual('{}{f}'.format(4, f='test'), '4test') + self.assertEqual('{:{f}}{g}{}'.format(1, 3, g='g', f=2), ' 1g3') + self.assertEqual('{f:{}}{}{g}'.format(2, 4, f=1, g='g'), ' 14g') + def test_buffer_is_readonly(self): self.assertRaises(TypeError, sys.stdin.readinto, b"") Modified: python/trunk/Lib/test/test_unicode.py ============================================================================== --- python/trunk/Lib/test/test_unicode.py (original) +++ python/trunk/Lib/test/test_unicode.py Sat Mar 14 12:57:26 2009 @@ -1087,9 +1087,9 @@ self.assertRaises(ValueError, "{0!}".format, 0) self.assertRaises(ValueError, "{0!rs}".format, 0) self.assertRaises(ValueError, "{!}".format) - self.assertRaises(ValueError, "{:}".format) - self.assertRaises(ValueError, "{:s}".format) - self.assertRaises(ValueError, "{}".format) + self.assertRaises(IndexError, "{:}".format) + self.assertRaises(IndexError, "{:s}".format) + self.assertRaises(IndexError, "{}".format) # can't have a replacement on the field name portion self.assertRaises(TypeError, '{0[{1}]}'.format, 'abcdefg', 4) @@ -1113,6 +1113,36 @@ # will fail self.assertRaises(UnicodeEncodeError, "foo{0}".format, u'\u1000bar') + def test_format_auto_numbering(self): + class C: + def __init__(self, x=100): + self._x = x + def __format__(self, spec): + return spec + + self.assertEqual(u'{}'.format(10), u'10') + self.assertEqual(u'{:5}'.format('s'), u's ') + self.assertEqual(u'{!r}'.format('s'), u"'s'") + self.assertEqual(u'{._x}'.format(C(10)), u'10') + self.assertEqual(u'{[1]}'.format([1, 2]), u'2') + self.assertEqual(u'{[a]}'.format({'a':4, 'b':2}), u'4') + self.assertEqual(u'a{}b{}c'.format(0, 1), u'a0b1c') + + self.assertEqual(u'a{:{}}b'.format('x', '^10'), u'a x b') + self.assertEqual(u'a{:{}x}b'.format(20, '#'), u'a0x14b') + + # can't mix and match numbering and auto-numbering + self.assertRaises(ValueError, u'{}{1}'.format, 1, 2) + self.assertRaises(ValueError, u'{1}{}'.format, 1, 2) + self.assertRaises(ValueError, u'{:{1}}'.format, 1, 2) + self.assertRaises(ValueError, u'{0:{}}'.format, 1, 2) + + # can mix and match auto-numbering and named + self.assertEqual(u'{f}{}'.format(4, f='test'), u'test4') + self.assertEqual(u'{}{f}'.format(4, f='test'), u'4test') + self.assertEqual(u'{:{f}}{g}{}'.format(1, 3, g='g', f=2), u' 1g3') + self.assertEqual(u'{f:{}}{}{g}'.format(2, 4, f=1, g='g'), u' 14g') + def test_raiseMemError(self): # Ensure that the freelist contains a consistent object, even # when a string allocation fails with a MemoryError. Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sat Mar 14 12:57:26 2009 @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #5237: Allow auto-numbered fields in str.format(). For + example: '{} {}'.format(1, 2) == '1 2'. + - Issue #3652: Make the 'line' argument for warnings.showwarning() a requirement. Means the DeprecationWarning from Python 2.6 can go away. Modified: python/trunk/Objects/stringlib/string_format.h ============================================================================== --- python/trunk/Objects/stringlib/string_format.h (original) +++ python/trunk/Objects/stringlib/string_format.h Sat Mar 14 12:57:26 2009 @@ -31,10 +31,23 @@ } SubString; +typedef enum { + ANS_INIT, + ANS_AUTO, + ANS_MANUAL, +} AutoNumberState; /* Keep track if we're auto-numbering fields */ + +/* Keeps track of our auto-numbering state, and which number field we're on */ +typedef struct { + AutoNumberState an_state; + int an_field_number; +} AutoNumber; + + /* forward declaration for recursion */ static PyObject * build_string(SubString *input, PyObject *args, PyObject *kwargs, - int recursion_depth); + int recursion_depth, AutoNumber *auto_number); @@ -42,6 +55,13 @@ /************************** Utility functions ************************/ /************************************************************************/ +static void +AutoNumber_Init(AutoNumber *auto_number) +{ + auto_number->an_state = ANS_INIT; + auto_number->an_field_number = 0; +} + /* fill in a SubString from a pointer and length */ Py_LOCAL_INLINE(void) SubString_init(SubString *str, STRINGLIB_CHAR *p, Py_ssize_t len) @@ -74,6 +94,32 @@ return STRINGLIB_NEW(str->ptr, str->end - str->ptr); } +/* Return 1 if an error has been detected switching between automatic + field numbering and manual field specification, else return 0. Set + ValueError on error. */ +static int +autonumber_state_error(AutoNumberState state, int field_name_is_empty) +{ + if (state == ANS_MANUAL) { + if (field_name_is_empty) { + PyErr_SetString(PyExc_ValueError, "cannot switch from " + "manual field specification to " + "automatic field numbering"); + return 1; + } + } + else { + if (!field_name_is_empty) { + PyErr_SetString(PyExc_ValueError, "cannot switch from " + "automatic field numbering to " + "manual field specification"); + return 1; + } + } + return 0; +} + + /************************************************************************/ /*********** Output string management functions ****************/ /************************************************************************/ @@ -352,11 +398,14 @@ */ static int field_name_split(STRINGLIB_CHAR *ptr, Py_ssize_t len, SubString *first, - Py_ssize_t *first_idx, FieldNameIterator *rest) + Py_ssize_t *first_idx, FieldNameIterator *rest, + AutoNumber *auto_number) { STRINGLIB_CHAR c; STRINGLIB_CHAR *p = ptr; STRINGLIB_CHAR *end = ptr + len; + int field_name_is_empty; + int using_numeric_index; /* find the part up until the first '.' or '[' */ while (p < end) { @@ -380,15 +429,41 @@ /* see if "first" is an integer, in which case it's used as an index */ *first_idx = get_integer(first); - /* zero length string is an error */ - if (first->ptr >= first->end) { - PyErr_SetString(PyExc_ValueError, "empty field name"); - goto error; + field_name_is_empty = first->ptr >= first->end; + + /* If the field name is omitted or if we have a numeric index + specified, then we're doing numeric indexing into args. */ + using_numeric_index = field_name_is_empty || *first_idx != -1; + + /* We always get here exactly one time for each field we're + processing. And we get here in field order (counting by left + braces). So this is the perfect place to handle automatic field + numbering if the field name is omitted. */ + + /* Check if we need to do the auto-numbering. It's not needed if + we're called from string.Format routines, because it's handled + in that class by itself. */ + if (auto_number) { + /* Initialize our auto numbering state if this is the first + time we're either auto-numbering or manually numbering. */ + if (auto_number->an_state == ANS_INIT && using_numeric_index) + auto_number->an_state = field_name_is_empty ? + ANS_AUTO : ANS_MANUAL; + + /* Make sure our state is consistent with what we're doing + this time through. Only check if we're using a numeric + index. */ + if (using_numeric_index) + if (autonumber_state_error(auto_number->an_state, + field_name_is_empty)) + return 0; + /* Zero length field means we want to do auto-numbering of the + fields. */ + if (field_name_is_empty) + *first_idx = (auto_number->an_field_number)++; } return 1; -error: - return 0; } @@ -398,7 +473,8 @@ the entire input string. */ static PyObject * -get_field_object(SubString *input, PyObject *args, PyObject *kwargs) +get_field_object(SubString *input, PyObject *args, PyObject *kwargs, + AutoNumber *auto_number) { PyObject *obj = NULL; int ok; @@ -409,7 +485,7 @@ FieldNameIterator rest; if (!field_name_split(input->ptr, input->end - input->ptr, &first, - &index, &rest)) { + &index, &rest, auto_number)) { goto error; } @@ -557,14 +633,18 @@ parse_field(SubString *str, SubString *field_name, SubString *format_spec, STRINGLIB_CHAR *conversion) { + /* Note this function works if the field name is zero length, + which is good. Zero length field names are handled later, in + field_name_split. */ + STRINGLIB_CHAR c = 0; /* initialize these, as they may be empty */ *conversion = '\0'; SubString_init(format_spec, NULL, 0); - /* search for the field name. it's terminated by the end of the - string, or a ':' or '!' */ + /* Search for the field name. it's terminated by the end of + the string, or a ':' or '!' */ field_name->ptr = str->ptr; while (str->ptr < str->end) { switch (c = *(str->ptr++)) { @@ -607,15 +687,12 @@ } } } - - return 1; - } - else { + else /* end of string, there's no format_spec or conversion */ field_name->end = str->ptr; - return 1; - } + + return 1; } /************************************************************************/ @@ -642,8 +719,8 @@ string (or something to be expanded) */ static int MarkupIterator_next(MarkupIterator *self, SubString *literal, - SubString *field_name, SubString *format_spec, - STRINGLIB_CHAR *conversion, + int *field_present, SubString *field_name, + SubString *format_spec, STRINGLIB_CHAR *conversion, int *format_spec_needs_expanding) { int at_end; @@ -659,6 +736,7 @@ SubString_init(format_spec, NULL, 0); *conversion = '\0'; *format_spec_needs_expanding = 0; + *field_present = 0; /* No more input, end of iterator. This is the normal exit path. */ @@ -720,6 +798,7 @@ /* this is markup, find the end of the string by counting nested braces. note that this prohibits escaped braces, so that format_specs cannot have braces in them. */ + *field_present = 1; count = 1; start = self->str.ptr; @@ -744,13 +823,6 @@ if (parse_field(&s, field_name, format_spec, conversion) == 0) return 0; - /* a zero length field_name is an error */ - if (field_name->ptr == field_name->end) { - PyErr_SetString(PyExc_ValueError, "zero length field name " - "in format"); - return 0; - } - /* success */ return 2; } @@ -798,13 +870,17 @@ compute the result and write it to output. format_spec_needs_expanding is an optimization. if it's false, just output the string directly, otherwise recursively expand the - format_spec string. */ + format_spec string. + + field_name is allowed to be zero length, in which case we + are doing auto field numbering. +*/ static int output_markup(SubString *field_name, SubString *format_spec, int format_spec_needs_expanding, STRINGLIB_CHAR conversion, OutputString *output, PyObject *args, PyObject *kwargs, - int recursion_depth) + int recursion_depth, AutoNumber *auto_number) { PyObject *tmp = NULL; PyObject *fieldobj = NULL; @@ -813,7 +889,7 @@ int result = 0; /* convert field_name to an object */ - fieldobj = get_field_object(field_name, args, kwargs); + fieldobj = get_field_object(field_name, args, kwargs, auto_number); if (fieldobj == NULL) goto done; @@ -830,7 +906,8 @@ /* if needed, recurively compute the format_spec */ if (format_spec_needs_expanding) { - tmp = build_string(format_spec, args, kwargs, recursion_depth-1); + tmp = build_string(format_spec, args, kwargs, recursion_depth-1, + auto_number); if (tmp == NULL) goto done; @@ -864,26 +941,28 @@ */ static int do_markup(SubString *input, PyObject *args, PyObject *kwargs, - OutputString *output, int recursion_depth) + OutputString *output, int recursion_depth, AutoNumber *auto_number) { MarkupIterator iter; int format_spec_needs_expanding; int result; + int field_present; SubString literal; SubString field_name; SubString format_spec; STRINGLIB_CHAR conversion; MarkupIterator_init(&iter, input->ptr, input->end - input->ptr); - while ((result = MarkupIterator_next(&iter, &literal, &field_name, - &format_spec, &conversion, + while ((result = MarkupIterator_next(&iter, &literal, &field_present, + &field_name, &format_spec, + &conversion, &format_spec_needs_expanding)) == 2) { if (!output_data(output, literal.ptr, literal.end - literal.ptr)) return 0; - if (field_name.ptr != field_name.end) + if (field_present) if (!output_markup(&field_name, &format_spec, format_spec_needs_expanding, conversion, output, - args, kwargs, recursion_depth)) + args, kwargs, recursion_depth, auto_number)) return 0; } return result; @@ -896,7 +975,7 @@ */ static PyObject * build_string(SubString *input, PyObject *args, PyObject *kwargs, - int recursion_depth) + int recursion_depth, AutoNumber *auto_number) { OutputString output; PyObject *result = NULL; @@ -918,7 +997,8 @@ INITIAL_SIZE_INCREMENT)) goto done; - if (!do_markup(input, args, kwargs, &output, recursion_depth)) { + if (!do_markup(input, args, kwargs, &output, recursion_depth, + auto_number)) { goto done; } @@ -952,8 +1032,11 @@ */ int recursion_depth = 2; + AutoNumber auto_number; + + AutoNumber_Init(&auto_number); SubString_init(&input, STRINGLIB_STR(self), STRINGLIB_LEN(self)); - return build_string(&input, args, kwargs, recursion_depth); + return build_string(&input, args, kwargs, recursion_depth, &auto_number); } @@ -998,8 +1081,9 @@ SubString format_spec; STRINGLIB_CHAR conversion; int format_spec_needs_expanding; - int result = MarkupIterator_next(&it->it_markup, &literal, &field_name, - &format_spec, &conversion, + int field_present; + int result = MarkupIterator_next(&it->it_markup, &literal, &field_present, + &field_name, &format_spec, &conversion, &format_spec_needs_expanding); /* all of the SubString objects point into it->str, so no @@ -1014,7 +1098,6 @@ PyObject *format_spec_str = NULL; PyObject *conversion_str = NULL; PyObject *tuple = NULL; - int has_field = field_name.ptr != field_name.end; literal_str = SubString_new_object(&literal); if (literal_str == NULL) @@ -1026,7 +1109,7 @@ /* if field_name is non-zero length, return a string for format_spec (even if zero length), else return None */ - format_spec_str = (has_field ? + format_spec_str = (field_present ? SubString_new_object_or_empty : SubString_new_object)(&format_spec); if (format_spec_str == NULL) @@ -1250,9 +1333,11 @@ Py_INCREF(self); it->str = self; + /* Pass in auto_number = NULL. We'll return an empty string for + first_obj in that case. */ if (!field_name_split(STRINGLIB_STR(self), STRINGLIB_LEN(self), - &first, &first_idx, &it->it_field)) + &first, &first_idx, &it->it_field, NULL)) goto done; /* first becomes an integer, if possible; else a string */ From python-checkins at python.org Sat Mar 14 12:59:19 2009 From: python-checkins at python.org (eric.smith) Date: Sat, 14 Mar 2009 12:59:19 +0100 (CET) Subject: [Python-checkins] r70365 - python/branches/release26-maint Message-ID: <20090314115919.132A61E4002@bag.python.org> Author: eric.smith Date: Sat Mar 14 12:59:18 2009 New Revision: 70365 Log: Blocked revisions 70364 via svnmerge ........ r70364 | eric.smith | 2009-03-14 07:57:26 -0400 (Sat, 14 Mar 2009) | 17 lines Issue 5237, Allow auto-numbered replacement fields in str.format() strings. For simple uses for str.format(), this makes the typing easier. Hopfully this will help in the adoption of str.format(). For example: 'The {} is {}'.format('sky', 'blue') You can mix and matcth auto-numbering and named replacement fields: 'The {} is {color}'.format('sky', color='blue') But you can't mix and match auto-numbering and specified numbering: 'The {0} is {}'.format('sky', 'blue') ValueError: cannot switch from manual field specification to automatic field numbering Will port to 3.1. ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Sat Mar 14 13:29:34 2009 From: python-checkins at python.org (eric.smith) Date: Sat, 14 Mar 2009 13:29:34 +0100 (CET) Subject: [Python-checkins] r70366 - in python/branches/py3k: Lib/test/test_unicode.py Misc/NEWS Objects/stringlib/string_format.h Message-ID: <20090314122934.B51721E4002@bag.python.org> Author: eric.smith Date: Sat Mar 14 13:29:34 2009 New Revision: 70366 Log: Merged revisions 70364 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70364 | eric.smith | 2009-03-14 07:57:26 -0400 (Sat, 14 Mar 2009) | 17 lines Issue 5237, Allow auto-numbered replacement fields in str.format() strings. For simple uses for str.format(), this makes the typing easier. Hopfully this will help in the adoption of str.format(). For example: 'The {} is {}'.format('sky', 'blue') You can mix and matcth auto-numbering and named replacement fields: 'The {} is {color}'.format('sky', color='blue') But you can't mix and match auto-numbering and specified numbering: 'The {0} is {}'.format('sky', 'blue') ValueError: cannot switch from manual field specification to automatic field numbering Will port to 3.1. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_unicode.py python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/stringlib/string_format.h Modified: python/branches/py3k/Lib/test/test_unicode.py ============================================================================== --- python/branches/py3k/Lib/test/test_unicode.py (original) +++ python/branches/py3k/Lib/test/test_unicode.py Sat Mar 14 13:29:34 2009 @@ -683,9 +683,9 @@ self.assertRaises(ValueError, "{0!}".format, 0) self.assertRaises(ValueError, "{0!rs}".format, 0) self.assertRaises(ValueError, "{!}".format) - self.assertRaises(ValueError, "{:}".format) - self.assertRaises(ValueError, "{:s}".format) - self.assertRaises(ValueError, "{}".format) + self.assertRaises(IndexError, "{:}".format) + self.assertRaises(IndexError, "{:s}".format) + self.assertRaises(IndexError, "{}".format) # can't have a replacement on the field name portion self.assertRaises(TypeError, '{0[{1}]}'.format, 'abcdefg', 4) @@ -704,6 +704,36 @@ self.assertRaises(ValueError, format, '', '#') self.assertRaises(ValueError, format, '', '#20') + def test_format_auto_numbering(self): + class C: + def __init__(self, x=100): + self._x = x + def __format__(self, spec): + return spec + + self.assertEqual('{}'.format(10), '10') + self.assertEqual('{:5}'.format('s'), 's ') + self.assertEqual('{!r}'.format('s'), "'s'") + self.assertEqual('{._x}'.format(C(10)), '10') + self.assertEqual('{[1]}'.format([1, 2]), '2') + self.assertEqual('{[a]}'.format({'a':4, 'b':2}), '4') + self.assertEqual('a{}b{}c'.format(0, 1), 'a0b1c') + + self.assertEqual('a{:{}}b'.format('x', '^10'), 'a x b') + self.assertEqual('a{:{}x}b'.format(20, '#'), 'a0x14b') + + # can't mix and match numbering and auto-numbering + self.assertRaises(ValueError, '{}{1}'.format, 1, 2) + self.assertRaises(ValueError, '{1}{}'.format, 1, 2) + self.assertRaises(ValueError, '{:{1}}'.format, 1, 2) + self.assertRaises(ValueError, '{0:{}}'.format, 1, 2) + + # can mix and match auto-numbering and named + self.assertEqual('{f}{}'.format(4, f='test'), 'test4') + self.assertEqual('{}{f}'.format(4, f='test'), '4test') + self.assertEqual('{:{f}}{g}{}'.format(1, 3, g='g', f=2), ' 1g3') + self.assertEqual('{f:{}}{}{g}'.format(2, 4, f=1, g='g'), ' 14g') + def test_formatting(self): string_tests.MixinStrUnicodeUserStringTest.test_formatting(self) # Testing Unicode formatting strings... Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Mar 14 13:29:34 2009 @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #5237: Allow auto-numbered fields in str.format(). For + example: '{} {}'.format(1, 2) == '1 2'. + - Issue #5392: when a very low recursion limit was set, the interpreter would abort with a fatal error after the recursion limit was hit twice. @@ -33,6 +36,7 @@ Core and Builtins ----------------- +======= - The io module has been reimplemented in C for speed. - Give dict views an informative __repr__. Modified: python/branches/py3k/Objects/stringlib/string_format.h ============================================================================== --- python/branches/py3k/Objects/stringlib/string_format.h (original) +++ python/branches/py3k/Objects/stringlib/string_format.h Sat Mar 14 13:29:34 2009 @@ -31,10 +31,23 @@ } SubString; +typedef enum { + ANS_INIT, + ANS_AUTO, + ANS_MANUAL, +} AutoNumberState; /* Keep track if we're auto-numbering fields */ + +/* Keeps track of our auto-numbering state, and which number field we're on */ +typedef struct { + AutoNumberState an_state; + int an_field_number; +} AutoNumber; + + /* forward declaration for recursion */ static PyObject * build_string(SubString *input, PyObject *args, PyObject *kwargs, - int recursion_depth); + int recursion_depth, AutoNumber *auto_number); @@ -42,6 +55,13 @@ /************************** Utility functions ************************/ /************************************************************************/ +static void +AutoNumber_Init(AutoNumber *auto_number) +{ + auto_number->an_state = ANS_INIT; + auto_number->an_field_number = 0; +} + /* fill in a SubString from a pointer and length */ Py_LOCAL_INLINE(void) SubString_init(SubString *str, STRINGLIB_CHAR *p, Py_ssize_t len) @@ -74,6 +94,32 @@ return STRINGLIB_NEW(str->ptr, str->end - str->ptr); } +/* Return 1 if an error has been detected switching between automatic + field numbering and manual field specification, else return 0. Set + ValueError on error. */ +static int +autonumber_state_error(AutoNumberState state, int field_name_is_empty) +{ + if (state == ANS_MANUAL) { + if (field_name_is_empty) { + PyErr_SetString(PyExc_ValueError, "cannot switch from " + "manual field specification to " + "automatic field numbering"); + return 1; + } + } + else { + if (!field_name_is_empty) { + PyErr_SetString(PyExc_ValueError, "cannot switch from " + "automatic field numbering to " + "manual field specification"); + return 1; + } + } + return 0; +} + + /************************************************************************/ /*********** Output string management functions ****************/ /************************************************************************/ @@ -352,11 +398,14 @@ */ static int field_name_split(STRINGLIB_CHAR *ptr, Py_ssize_t len, SubString *first, - Py_ssize_t *first_idx, FieldNameIterator *rest) + Py_ssize_t *first_idx, FieldNameIterator *rest, + AutoNumber *auto_number) { STRINGLIB_CHAR c; STRINGLIB_CHAR *p = ptr; STRINGLIB_CHAR *end = ptr + len; + int field_name_is_empty; + int using_numeric_index; /* find the part up until the first '.' or '[' */ while (p < end) { @@ -380,15 +429,41 @@ /* see if "first" is an integer, in which case it's used as an index */ *first_idx = get_integer(first); - /* zero length string is an error */ - if (first->ptr >= first->end) { - PyErr_SetString(PyExc_ValueError, "empty field name"); - goto error; + field_name_is_empty = first->ptr >= first->end; + + /* If the field name is omitted or if we have a numeric index + specified, then we're doing numeric indexing into args. */ + using_numeric_index = field_name_is_empty || *first_idx != -1; + + /* We always get here exactly one time for each field we're + processing. And we get here in field order (counting by left + braces). So this is the perfect place to handle automatic field + numbering if the field name is omitted. */ + + /* Check if we need to do the auto-numbering. It's not needed if + we're called from string.Format routines, because it's handled + in that class by itself. */ + if (auto_number) { + /* Initialize our auto numbering state if this is the first + time we're either auto-numbering or manually numbering. */ + if (auto_number->an_state == ANS_INIT && using_numeric_index) + auto_number->an_state = field_name_is_empty ? + ANS_AUTO : ANS_MANUAL; + + /* Make sure our state is consistent with what we're doing + this time through. Only check if we're using a numeric + index. */ + if (using_numeric_index) + if (autonumber_state_error(auto_number->an_state, + field_name_is_empty)) + return 0; + /* Zero length field means we want to do auto-numbering of the + fields. */ + if (field_name_is_empty) + *first_idx = (auto_number->an_field_number)++; } return 1; -error: - return 0; } @@ -398,7 +473,8 @@ the entire input string. */ static PyObject * -get_field_object(SubString *input, PyObject *args, PyObject *kwargs) +get_field_object(SubString *input, PyObject *args, PyObject *kwargs, + AutoNumber *auto_number) { PyObject *obj = NULL; int ok; @@ -409,7 +485,7 @@ FieldNameIterator rest; if (!field_name_split(input->ptr, input->end - input->ptr, &first, - &index, &rest)) { + &index, &rest, auto_number)) { goto error; } @@ -548,14 +624,18 @@ parse_field(SubString *str, SubString *field_name, SubString *format_spec, STRINGLIB_CHAR *conversion) { + /* Note this function works if the field name is zero length, + which is good. Zero length field names are handled later, in + field_name_split. */ + STRINGLIB_CHAR c = 0; /* initialize these, as they may be empty */ *conversion = '\0'; SubString_init(format_spec, NULL, 0); - /* search for the field name. it's terminated by the end of the - string, or a ':' or '!' */ + /* Search for the field name. it's terminated by the end of + the string, or a ':' or '!' */ field_name->ptr = str->ptr; while (str->ptr < str->end) { switch (c = *(str->ptr++)) { @@ -598,15 +678,12 @@ } } } - - return 1; - } - else { + else /* end of string, there's no format_spec or conversion */ field_name->end = str->ptr; - return 1; - } + + return 1; } /************************************************************************/ @@ -633,8 +710,8 @@ string (or something to be expanded) */ static int MarkupIterator_next(MarkupIterator *self, SubString *literal, - SubString *field_name, SubString *format_spec, - STRINGLIB_CHAR *conversion, + int *field_present, SubString *field_name, + SubString *format_spec, STRINGLIB_CHAR *conversion, int *format_spec_needs_expanding) { int at_end; @@ -650,6 +727,7 @@ SubString_init(format_spec, NULL, 0); *conversion = '\0'; *format_spec_needs_expanding = 0; + *field_present = 0; /* No more input, end of iterator. This is the normal exit path. */ @@ -711,6 +789,7 @@ /* this is markup, find the end of the string by counting nested braces. note that this prohibits escaped braces, so that format_specs cannot have braces in them. */ + *field_present = 1; count = 1; start = self->str.ptr; @@ -735,13 +814,6 @@ if (parse_field(&s, field_name, format_spec, conversion) == 0) return 0; - /* a zero length field_name is an error */ - if (field_name->ptr == field_name->end) { - PyErr_SetString(PyExc_ValueError, "zero length field name " - "in format"); - return 0; - } - /* success */ return 2; } @@ -793,13 +865,17 @@ compute the result and write it to output. format_spec_needs_expanding is an optimization. if it's false, just output the string directly, otherwise recursively expand the - format_spec string. */ + format_spec string. + + field_name is allowed to be zero length, in which case we + are doing auto field numbering. +*/ static int output_markup(SubString *field_name, SubString *format_spec, int format_spec_needs_expanding, STRINGLIB_CHAR conversion, OutputString *output, PyObject *args, PyObject *kwargs, - int recursion_depth) + int recursion_depth, AutoNumber *auto_number) { PyObject *tmp = NULL; PyObject *fieldobj = NULL; @@ -808,7 +884,7 @@ int result = 0; /* convert field_name to an object */ - fieldobj = get_field_object(field_name, args, kwargs); + fieldobj = get_field_object(field_name, args, kwargs, auto_number); if (fieldobj == NULL) goto done; @@ -825,7 +901,8 @@ /* if needed, recurively compute the format_spec */ if (format_spec_needs_expanding) { - tmp = build_string(format_spec, args, kwargs, recursion_depth-1); + tmp = build_string(format_spec, args, kwargs, recursion_depth-1, + auto_number); if (tmp == NULL) goto done; @@ -859,26 +936,28 @@ */ static int do_markup(SubString *input, PyObject *args, PyObject *kwargs, - OutputString *output, int recursion_depth) + OutputString *output, int recursion_depth, AutoNumber *auto_number) { MarkupIterator iter; int format_spec_needs_expanding; int result; + int field_present; SubString literal; SubString field_name; SubString format_spec; STRINGLIB_CHAR conversion; MarkupIterator_init(&iter, input->ptr, input->end - input->ptr); - while ((result = MarkupIterator_next(&iter, &literal, &field_name, - &format_spec, &conversion, + while ((result = MarkupIterator_next(&iter, &literal, &field_present, + &field_name, &format_spec, + &conversion, &format_spec_needs_expanding)) == 2) { if (!output_data(output, literal.ptr, literal.end - literal.ptr)) return 0; - if (field_name.ptr != field_name.end) + if (field_present) if (!output_markup(&field_name, &format_spec, format_spec_needs_expanding, conversion, output, - args, kwargs, recursion_depth)) + args, kwargs, recursion_depth, auto_number)) return 0; } return result; @@ -891,7 +970,7 @@ */ static PyObject * build_string(SubString *input, PyObject *args, PyObject *kwargs, - int recursion_depth) + int recursion_depth, AutoNumber *auto_number) { OutputString output; PyObject *result = NULL; @@ -913,7 +992,8 @@ INITIAL_SIZE_INCREMENT)) goto done; - if (!do_markup(input, args, kwargs, &output, recursion_depth)) { + if (!do_markup(input, args, kwargs, &output, recursion_depth, + auto_number)) { goto done; } @@ -947,8 +1027,11 @@ */ int recursion_depth = 2; + AutoNumber auto_number; + + AutoNumber_Init(&auto_number); SubString_init(&input, STRINGLIB_STR(self), STRINGLIB_LEN(self)); - return build_string(&input, args, kwargs, recursion_depth); + return build_string(&input, args, kwargs, recursion_depth, &auto_number); } @@ -993,8 +1076,9 @@ SubString format_spec; STRINGLIB_CHAR conversion; int format_spec_needs_expanding; - int result = MarkupIterator_next(&it->it_markup, &literal, &field_name, - &format_spec, &conversion, + int field_present; + int result = MarkupIterator_next(&it->it_markup, &literal, &field_present, + &field_name, &format_spec, &conversion, &format_spec_needs_expanding); /* all of the SubString objects point into it->str, so no @@ -1009,7 +1093,6 @@ PyObject *format_spec_str = NULL; PyObject *conversion_str = NULL; PyObject *tuple = NULL; - int has_field = field_name.ptr != field_name.end; literal_str = SubString_new_object(&literal); if (literal_str == NULL) @@ -1021,7 +1104,7 @@ /* if field_name is non-zero length, return a string for format_spec (even if zero length), else return None */ - format_spec_str = (has_field ? + format_spec_str = (field_present ? SubString_new_object_or_empty : SubString_new_object)(&format_spec); if (format_spec_str == NULL) @@ -1245,9 +1328,11 @@ Py_INCREF(self); it->str = self; + /* Pass in auto_number = NULL. We'll return an empty string for + first_obj in that case. */ if (!field_name_split(STRINGLIB_STR(self), STRINGLIB_LEN(self), - &first, &first_idx, &it->it_field)) + &first, &first_idx, &it->it_field, NULL)) goto done; /* first becomes an integer, if possible; else a string */ From python-checkins at python.org Sat Mar 14 13:30:26 2009 From: python-checkins at python.org (eric.smith) Date: Sat, 14 Mar 2009 13:30:26 +0100 (CET) Subject: [Python-checkins] r70367 - python/branches/release30-maint Message-ID: <20090314123026.1C5EF1E4002@bag.python.org> Author: eric.smith Date: Sat Mar 14 13:30:25 2009 New Revision: 70367 Log: Blocked revisions 70366 via svnmerge ................ r70366 | eric.smith | 2009-03-14 08:29:34 -0400 (Sat, 14 Mar 2009) | 24 lines Merged revisions 70364 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70364 | eric.smith | 2009-03-14 07:57:26 -0400 (Sat, 14 Mar 2009) | 17 lines Issue 5237, Allow auto-numbered replacement fields in str.format() strings. For simple uses for str.format(), this makes the typing easier. Hopfully this will help in the adoption of str.format(). For example: 'The {} is {}'.format('sky', 'blue') You can mix and matcth auto-numbering and named replacement fields: 'The {} is {color}'.format('sky', color='blue') But you can't mix and match auto-numbering and specified numbering: 'The {0} is {}'.format('sky', 'blue') ValueError: cannot switch from manual field specification to automatic field numbering Will port to 3.1. ........ ................ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Sat Mar 14 13:44:09 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 14 Mar 2009 12:44:09 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090314124409.9D3EF1E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/232 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: eric.smith BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sat Mar 14 15:37:38 2009 From: python-checkins at python.org (eric.smith) Date: Sat, 14 Mar 2009 15:37:38 +0100 (CET) Subject: [Python-checkins] r70368 - python/trunk/Lib/test/test_unicode.py Message-ID: <20090314143738.E00781E4039@bag.python.org> Author: eric.smith Date: Sat Mar 14 15:37:38 2009 New Revision: 70368 Log: Unicode format tests weren't actually testing unicode. This was probably due to the original backport from py3k. Modified: python/trunk/Lib/test/test_unicode.py Modified: python/trunk/Lib/test/test_unicode.py ============================================================================== --- python/trunk/Lib/test/test_unicode.py (original) +++ python/trunk/Lib/test/test_unicode.py Sat Mar 14 15:37:38 2009 @@ -1036,73 +1036,73 @@ self.assertEqual(u'{0:>15s}'.format(G(u'data')), u' string is data') self.assertEqual(u'{0!s}'.format(G(u'data')), u'string is data') - self.assertEqual("{0:date: %Y-%m-%d}".format(I(year=2007, - month=8, - day=27)), - "date: 2007-08-27") + self.assertEqual(u"{0:date: %Y-%m-%d}".format(I(year=2007, + month=8, + day=27)), + u"date: 2007-08-27") # test deriving from a builtin type and overriding __format__ - self.assertEqual("{0}".format(J(10)), "20") + self.assertEqual(u"{0}".format(J(10)), u"20") # string format specifiers - self.assertEqual('{0:}'.format('a'), 'a') + self.assertEqual(u'{0:}'.format('a'), u'a') # computed format specifiers - self.assertEqual("{0:.{1}}".format('hello world', 5), 'hello') - self.assertEqual("{0:.{1}s}".format('hello world', 5), 'hello') - self.assertEqual("{0:.{precision}s}".format('hello world', precision=5), 'hello') - self.assertEqual("{0:{width}.{precision}s}".format('hello world', width=10, precision=5), 'hello ') - self.assertEqual("{0:{width}.{precision}s}".format('hello world', width='10', precision='5'), 'hello ') + self.assertEqual(u"{0:.{1}}".format(u'hello world', 5), u'hello') + self.assertEqual(u"{0:.{1}s}".format(u'hello world', 5), u'hello') + self.assertEqual(u"{0:.{precision}s}".format('hello world', precision=5), u'hello') + self.assertEqual(u"{0:{width}.{precision}s}".format('hello world', width=10, precision=5), u'hello ') + self.assertEqual(u"{0:{width}.{precision}s}".format('hello world', width='10', precision='5'), u'hello ') # test various errors - self.assertRaises(ValueError, '{'.format) - self.assertRaises(ValueError, '}'.format) - self.assertRaises(ValueError, 'a{'.format) - self.assertRaises(ValueError, 'a}'.format) - self.assertRaises(ValueError, '{a'.format) - self.assertRaises(ValueError, '}a'.format) - self.assertRaises(IndexError, '{0}'.format) - self.assertRaises(IndexError, '{1}'.format, 'abc') - self.assertRaises(KeyError, '{x}'.format) - self.assertRaises(ValueError, "}{".format) - self.assertRaises(ValueError, "{".format) - self.assertRaises(ValueError, "}".format) - self.assertRaises(ValueError, "abc{0:{}".format) - self.assertRaises(ValueError, "{0".format) - self.assertRaises(IndexError, "{0.}".format) - self.assertRaises(ValueError, "{0.}".format, 0) - self.assertRaises(IndexError, "{0[}".format) - self.assertRaises(ValueError, "{0[}".format, []) - self.assertRaises(KeyError, "{0]}".format) - self.assertRaises(ValueError, "{0.[]}".format, 0) - self.assertRaises(ValueError, "{0..foo}".format, 0) - self.assertRaises(ValueError, "{0[0}".format, 0) - self.assertRaises(ValueError, "{0[0:foo}".format, 0) - self.assertRaises(KeyError, "{c]}".format) - self.assertRaises(ValueError, "{{ {{{0}}".format, 0) - self.assertRaises(ValueError, "{0}}".format, 0) - self.assertRaises(KeyError, "{foo}".format, bar=3) - self.assertRaises(ValueError, "{0!x}".format, 3) - self.assertRaises(ValueError, "{0!}".format, 0) - self.assertRaises(ValueError, "{0!rs}".format, 0) - self.assertRaises(ValueError, "{!}".format) - self.assertRaises(IndexError, "{:}".format) - self.assertRaises(IndexError, "{:s}".format) - self.assertRaises(IndexError, "{}".format) + self.assertRaises(ValueError, u'{'.format) + self.assertRaises(ValueError, u'}'.format) + self.assertRaises(ValueError, u'a{'.format) + self.assertRaises(ValueError, u'a}'.format) + self.assertRaises(ValueError, u'{a'.format) + self.assertRaises(ValueError, u'}a'.format) + self.assertRaises(IndexError, u'{0}'.format) + self.assertRaises(IndexError, u'{1}'.format, u'abc') + self.assertRaises(KeyError, u'{x}'.format) + self.assertRaises(ValueError, u"}{".format) + self.assertRaises(ValueError, u"{".format) + self.assertRaises(ValueError, u"}".format) + self.assertRaises(ValueError, u"abc{0:{}".format) + self.assertRaises(ValueError, u"{0".format) + self.assertRaises(IndexError, u"{0.}".format) + self.assertRaises(ValueError, u"{0.}".format, 0) + self.assertRaises(IndexError, u"{0[}".format) + self.assertRaises(ValueError, u"{0[}".format, []) + self.assertRaises(KeyError, u"{0]}".format) + self.assertRaises(ValueError, u"{0.[]}".format, 0) + self.assertRaises(ValueError, u"{0..foo}".format, 0) + self.assertRaises(ValueError, u"{0[0}".format, 0) + self.assertRaises(ValueError, u"{0[0:foo}".format, 0) + self.assertRaises(KeyError, u"{c]}".format) + self.assertRaises(ValueError, u"{{ {{{0}}".format, 0) + self.assertRaises(ValueError, u"{0}}".format, 0) + self.assertRaises(KeyError, u"{foo}".format, bar=3) + self.assertRaises(ValueError, u"{0!x}".format, 3) + self.assertRaises(ValueError, u"{0!}".format, 0) + self.assertRaises(ValueError, u"{0!rs}".format, 0) + self.assertRaises(ValueError, u"{!}".format) + self.assertRaises(IndexError, u"{:}".format) + self.assertRaises(IndexError, u"{:s}".format) + self.assertRaises(IndexError, u"{}".format) # can't have a replacement on the field name portion - self.assertRaises(TypeError, '{0[{1}]}'.format, 'abcdefg', 4) + self.assertRaises(TypeError, u'{0[{1}]}'.format, u'abcdefg', 4) # exceed maximum recursion depth - self.assertRaises(ValueError, "{0:{1:{2}}}".format, 'abc', 's', '') - self.assertRaises(ValueError, "{0:{1:{2:{3:{4:{5:{6}}}}}}}".format, + self.assertRaises(ValueError, u"{0:{1:{2}}}".format, u'abc', u's', u'') + self.assertRaises(ValueError, u"{0:{1:{2:{3:{4:{5:{6}}}}}}}".format, 0, 1, 2, 3, 4, 5, 6, 7) # string format spec errors - self.assertRaises(ValueError, "{0:-s}".format, '') - self.assertRaises(ValueError, format, "", "-") - self.assertRaises(ValueError, "{0:=s}".format, '') + self.assertRaises(ValueError, u"{0:-s}".format, u'') + self.assertRaises(ValueError, format, u"", u"-") + self.assertRaises(ValueError, u"{0:=s}".format, u'') # test combining string and unicode self.assertEqual(u"foo{0}".format('bar'), u'foobar') From python-checkins at python.org Sat Mar 14 15:43:28 2009 From: python-checkins at python.org (eric.smith) Date: Sat, 14 Mar 2009 15:43:28 +0100 (CET) Subject: [Python-checkins] r70369 - in python/branches/release26-maint: Lib/test/test_unicode.py Message-ID: <20090314144328.1ABE61E4002@bag.python.org> Author: eric.smith Date: Sat Mar 14 15:43:27 2009 New Revision: 70369 Log: Merged revisions 70368 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70368 | eric.smith | 2009-03-14 10:37:38 -0400 (Sat, 14 Mar 2009) | 1 line Unicode format tests weren't actually testing unicode. This was probably due to the original backport from py3k. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_unicode.py Modified: python/branches/release26-maint/Lib/test/test_unicode.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_unicode.py (original) +++ python/branches/release26-maint/Lib/test/test_unicode.py Sat Mar 14 15:43:27 2009 @@ -1036,73 +1036,73 @@ self.assertEqual(u'{0:>15s}'.format(G(u'data')), u' string is data') self.assertEqual(u'{0!s}'.format(G(u'data')), u'string is data') - self.assertEqual("{0:date: %Y-%m-%d}".format(I(year=2007, - month=8, - day=27)), - "date: 2007-08-27") + self.assertEqual(u"{0:date: %Y-%m-%d}".format(I(year=2007, + month=8, + day=27)), + u"date: 2007-08-27") # test deriving from a builtin type and overriding __format__ - self.assertEqual("{0}".format(J(10)), "20") + self.assertEqual(u"{0}".format(J(10)), u"20") # string format specifiers - self.assertEqual('{0:}'.format('a'), 'a') + self.assertEqual(u'{0:}'.format('a'), u'a') # computed format specifiers - self.assertEqual("{0:.{1}}".format('hello world', 5), 'hello') - self.assertEqual("{0:.{1}s}".format('hello world', 5), 'hello') - self.assertEqual("{0:.{precision}s}".format('hello world', precision=5), 'hello') - self.assertEqual("{0:{width}.{precision}s}".format('hello world', width=10, precision=5), 'hello ') - self.assertEqual("{0:{width}.{precision}s}".format('hello world', width='10', precision='5'), 'hello ') + self.assertEqual(u"{0:.{1}}".format(u'hello world', 5), u'hello') + self.assertEqual(u"{0:.{1}s}".format(u'hello world', 5), u'hello') + self.assertEqual(u"{0:.{precision}s}".format('hello world', precision=5), u'hello') + self.assertEqual(u"{0:{width}.{precision}s}".format('hello world', width=10, precision=5), u'hello ') + self.assertEqual(u"{0:{width}.{precision}s}".format('hello world', width='10', precision='5'), u'hello ') # test various errors - self.assertRaises(ValueError, '{'.format) - self.assertRaises(ValueError, '}'.format) - self.assertRaises(ValueError, 'a{'.format) - self.assertRaises(ValueError, 'a}'.format) - self.assertRaises(ValueError, '{a'.format) - self.assertRaises(ValueError, '}a'.format) - self.assertRaises(IndexError, '{0}'.format) - self.assertRaises(IndexError, '{1}'.format, 'abc') - self.assertRaises(KeyError, '{x}'.format) - self.assertRaises(ValueError, "}{".format) - self.assertRaises(ValueError, "{".format) - self.assertRaises(ValueError, "}".format) - self.assertRaises(ValueError, "abc{0:{}".format) - self.assertRaises(ValueError, "{0".format) - self.assertRaises(IndexError, "{0.}".format) - self.assertRaises(ValueError, "{0.}".format, 0) - self.assertRaises(IndexError, "{0[}".format) - self.assertRaises(ValueError, "{0[}".format, []) - self.assertRaises(KeyError, "{0]}".format) - self.assertRaises(ValueError, "{0.[]}".format, 0) - self.assertRaises(ValueError, "{0..foo}".format, 0) - self.assertRaises(ValueError, "{0[0}".format, 0) - self.assertRaises(ValueError, "{0[0:foo}".format, 0) - self.assertRaises(KeyError, "{c]}".format) - self.assertRaises(ValueError, "{{ {{{0}}".format, 0) - self.assertRaises(ValueError, "{0}}".format, 0) - self.assertRaises(KeyError, "{foo}".format, bar=3) - self.assertRaises(ValueError, "{0!x}".format, 3) - self.assertRaises(ValueError, "{0!}".format, 0) - self.assertRaises(ValueError, "{0!rs}".format, 0) - self.assertRaises(ValueError, "{!}".format) - self.assertRaises(ValueError, "{:}".format) - self.assertRaises(ValueError, "{:s}".format) - self.assertRaises(ValueError, "{}".format) + self.assertRaises(ValueError, u'{'.format) + self.assertRaises(ValueError, u'}'.format) + self.assertRaises(ValueError, u'a{'.format) + self.assertRaises(ValueError, u'a}'.format) + self.assertRaises(ValueError, u'{a'.format) + self.assertRaises(ValueError, u'}a'.format) + self.assertRaises(IndexError, u'{0}'.format) + self.assertRaises(IndexError, u'{1}'.format, u'abc') + self.assertRaises(KeyError, u'{x}'.format) + self.assertRaises(ValueError, u"}{".format) + self.assertRaises(ValueError, u"{".format) + self.assertRaises(ValueError, u"}".format) + self.assertRaises(ValueError, u"abc{0:{}".format) + self.assertRaises(ValueError, u"{0".format) + self.assertRaises(IndexError, u"{0.}".format) + self.assertRaises(ValueError, u"{0.}".format, 0) + self.assertRaises(IndexError, u"{0[}".format) + self.assertRaises(ValueError, u"{0[}".format, []) + self.assertRaises(KeyError, u"{0]}".format) + self.assertRaises(ValueError, u"{0.[]}".format, 0) + self.assertRaises(ValueError, u"{0..foo}".format, 0) + self.assertRaises(ValueError, u"{0[0}".format, 0) + self.assertRaises(ValueError, u"{0[0:foo}".format, 0) + self.assertRaises(KeyError, u"{c]}".format) + self.assertRaises(ValueError, u"{{ {{{0}}".format, 0) + self.assertRaises(ValueError, u"{0}}".format, 0) + self.assertRaises(KeyError, u"{foo}".format, bar=3) + self.assertRaises(ValueError, u"{0!x}".format, 3) + self.assertRaises(ValueError, u"{0!}".format, 0) + self.assertRaises(ValueError, u"{0!rs}".format, 0) + self.assertRaises(ValueError, u"{!}".format) + self.assertRaises(ValueError, u"{:}".format) + self.assertRaises(ValueError, u"{:s}".format) + self.assertRaises(ValueError, u"{}".format) # can't have a replacement on the field name portion - self.assertRaises(TypeError, '{0[{1}]}'.format, 'abcdefg', 4) + self.assertRaises(TypeError, u'{0[{1}]}'.format, u'abcdefg', 4) # exceed maximum recursion depth - self.assertRaises(ValueError, "{0:{1:{2}}}".format, 'abc', 's', '') - self.assertRaises(ValueError, "{0:{1:{2:{3:{4:{5:{6}}}}}}}".format, + self.assertRaises(ValueError, u"{0:{1:{2}}}".format, u'abc', u's', u'') + self.assertRaises(ValueError, u"{0:{1:{2:{3:{4:{5:{6}}}}}}}".format, 0, 1, 2, 3, 4, 5, 6, 7) # string format spec errors - self.assertRaises(ValueError, "{0:-s}".format, '') - self.assertRaises(ValueError, format, "", "-") - self.assertRaises(ValueError, "{0:=s}".format, '') + self.assertRaises(ValueError, u"{0:-s}".format, u'') + self.assertRaises(ValueError, format, u"", u"-") + self.assertRaises(ValueError, u"{0:=s}".format, u'') # test combining string and unicode self.assertEqual(u"foo{0}".format('bar'), u'foobar') From python-checkins at python.org Sat Mar 14 15:44:03 2009 From: python-checkins at python.org (eric.smith) Date: Sat, 14 Mar 2009 15:44:03 +0100 (CET) Subject: [Python-checkins] r70370 - python/branches/py3k Message-ID: <20090314144403.6DF571E4002@bag.python.org> Author: eric.smith Date: Sat Mar 14 15:44:03 2009 New Revision: 70370 Log: Blocked revisions 70368 via svnmerge ........ r70368 | eric.smith | 2009-03-14 10:37:38 -0400 (Sat, 14 Mar 2009) | 1 line Unicode format tests weren't actually testing unicode. This was probably due to the original backport from py3k. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Sat Mar 14 16:50:10 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 14 Mar 2009 16:50:10 +0100 (CET) Subject: [Python-checkins] r70371 - peps/trunk/pep-0375.txt Message-ID: <20090314155010.A08231E4002@bag.python.org> Author: benjamin.peterson Date: Sat Mar 14 16:50:10 2009 New Revision: 70371 Log: add etree upgrade Modified: peps/trunk/pep-0375.txt Modified: peps/trunk/pep-0375.txt ============================================================================== --- peps/trunk/pep-0375.txt (original) +++ peps/trunk/pep-0375.txt Sat Mar 14 16:50:10 2009 @@ -53,6 +53,7 @@ - Ordered dictionary for collections [#ordered]_. - Fixing contextlib.nested() [#contextlib]_. - auto-numbered replacement fields in str.format() strings [#strformat]_ +- Upgrading xml.etree to the latest external version [#etree]_ Footnotes @@ -73,6 +74,9 @@ .. [#strformat] http://bugs.python.org/issue5237 +.. [#etree] + http://bugs.python.org/issue1143 + Copyright From buildbot at python.org Sat Mar 14 17:24:08 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 14 Mar 2009 16:24:08 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090314162408.ACAEB1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/475 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: eric.smith BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sun Mar 15 01:00:19 2009 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Mar 2009 01:00:19 +0100 (CET) Subject: [Python-checkins] r70372 - python/branches/py3k/Lib/importlib/_bootstrap.py Message-ID: <20090315000019.547B61E4002@bag.python.org> Author: brett.cannon Date: Sun Mar 15 01:00:19 2009 New Revision: 70372 Log: Clean up docstring from importlib.util.module_for_loader. Modified: python/branches/py3k/Lib/importlib/_bootstrap.py Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Sun Mar 15 01:00:19 2009 @@ -128,14 +128,14 @@ def module_for_loader(fxn): """Decorator to handle selecting the proper module for loaders. - Decorated modules are passed the module to use instead of the module name. - The module is either from sys.modules if it already exists (for reloading) - or is a new module which has __name__ set. If any exception is raised by - the decorated method and the decorator added a module to sys.modules, then - the module is deleted from sys.modules. + The decorated function is passed the module to use instead of the module + name. The module passed in to the function is either from sys.modules if + it already exists or is a new module which has __name__ set and is inserted + into sys.modules. If an exception is raised and the decorator created the + module it is subsequently removed from sys.modules. - The decorator assumes that the decorated method takes self/cls as a first - argument and the module as the second argument. + The decorator assumes that the decorated function takes the module name as + the second argument. """ def decorated(self, fullname): From python-checkins at python.org Sun Mar 15 01:53:05 2009 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Mar 2009 01:53:05 +0100 (CET) Subject: [Python-checkins] r70373 - in python/branches/py3k/Lib/importlib: __init__.py _bootstrap.py abc.py test/import_/util.py Message-ID: <20090315005305.9D3811E4002@bag.python.org> Author: brett.cannon Date: Sun Mar 15 01:53:05 2009 New Revision: 70373 Log: A few more docstring/API cleanups for importlib. Modified: python/branches/py3k/Lib/importlib/__init__.py python/branches/py3k/Lib/importlib/_bootstrap.py python/branches/py3k/Lib/importlib/abc.py python/branches/py3k/Lib/importlib/test/import_/util.py Modified: python/branches/py3k/Lib/importlib/__init__.py ============================================================================== --- python/branches/py3k/Lib/importlib/__init__.py (original) +++ python/branches/py3k/Lib/importlib/__init__.py Sun Mar 15 01:53:05 2009 @@ -26,20 +26,6 @@ import re import tokenize -# XXX Temporary functions that should eventually be removed. -def _set__import__(): - """Set __import__ to an instance of Import.""" - global original__import__ - original__import__ = __import__ - __builtins__['__import__'] = _bootstrap._import - - -def _reset__import__(): - """Set __import__ back to the original implementation (assumes - _set__import__ was called previously).""" - __builtins__['__import__'] = original__import__ - - # Bootstrap help ##################################################### def _case_ok(directory, check): @@ -116,7 +102,7 @@ # Public API ######################################################### -__import__ = _bootstrap._import +from ._bootstrap import __import__ def import_module(name, package=None): Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Sun Mar 15 01:53:05 2009 @@ -183,16 +183,16 @@ class BuiltinImporter: - """Meta path loader for built-in modules. + """Meta path import for built-in modules. - All methods are either class or static methods, allowing direct use of the - class. + All methods are either class or static methods to avoid the need to + instantiate the class. """ @classmethod def find_module(cls, fullname, path=None): - """Try to find the built-in module. + """Find the built-in module. If 'path' is ever specified then the search is considered a failure. @@ -219,10 +219,10 @@ class FrozenImporter: - """Meta path class for importing frozen modules. + """Meta path import for frozen modules. - All methods are either class or static method to allow direct use of the - class. + All methods are either class or static methods to avoid the need to + instantiate the class. """ @@ -249,10 +249,13 @@ class PyLoader: - """Loader base class for Python source. + """Loader base class for Python source code. - Requires implementing the optional PEP 302 protocols as well as - source_path. + Subclasses need to implement the methods: + + - source_path + - get_data + - is_package """ @@ -595,7 +598,8 @@ @classmethod def find_module(cls, fullname, path=None): - """Find the module on sys.path or 'path'.""" + """Find the module on sys.path or 'path' based on sys.path_hooks and + sys.path_importer_cache.""" if not path: path = sys.path for entry in path: @@ -857,7 +861,7 @@ return module -def _import(name, globals={}, locals={}, fromlist=[], level=0): +def __import__(name, globals={}, locals={}, fromlist=[], level=0): """Import a module. The 'globals' argument is used to infer where the import is occuring from Modified: python/branches/py3k/Lib/importlib/abc.py ============================================================================== --- python/branches/py3k/Lib/importlib/abc.py (original) +++ python/branches/py3k/Lib/importlib/abc.py Sun Mar 15 01:53:05 2009 @@ -7,13 +7,11 @@ class Loader(metaclass=abc.ABCMeta): - """Abstract base class for import loaders. - - See PEP 302 for details. - - """ + """Abstract base class for import loaders.""" + @abc.abstractmethod def load_module(self, fullname:str) -> types.ModuleType: + """Abstract method which when implemented should load a module.""" raise NotImplementedError Loader.register(machinery.BuiltinImporter) @@ -22,14 +20,11 @@ class Finder(metaclass=abc.ABCMeta): - """Abstract base class for import finders. - - See PEP 302 for details. - - """ + """Abstract base class for import finders.""" @abc.abstractmethod def find_module(self, fullname:str, path:[str]=None) -> Loader: + """Abstract method which when implemented should find a module.""" raise NotImplementedError Finder.register(machinery.BuiltinImporter) @@ -37,16 +32,10 @@ Finder.register(machinery.PathFinder) -class Importer(Finder, Loader): - - """Abstract base class for importers.""" - - - class ResourceLoader(Loader): - """Abstract base class for loaders which can return data from the back-end - storage. + """Abstract base class for loaders which can return data from their + back-end storage. This ABC represents one of the optional protocols specified by PEP 302. @@ -54,12 +43,15 @@ @abc.abstractmethod def get_data(self, path:str) -> bytes: + """Abstract method which when implemented should return the bytes for + the specified path.""" raise NotImplementedError class InspectLoader(Loader): - """Abstract base class for loaders which supports introspection. + """Abstract base class for loaders which support inspection about the + modules they can load. This ABC represents one of the optional protocols specified by PEP 302. @@ -67,44 +59,64 @@ @abc.abstractmethod def is_package(self, fullname:str) -> bool: + """Abstract method which when implemented should return whether the + module is a package.""" return NotImplementedError @abc.abstractmethod def get_code(self, fullname:str) -> types.CodeType: + """Abstract method which when implemented should return the code object + for the module""" return NotImplementedError @abc.abstractmethod def get_source(self, fullname:str) -> str: + """Abstract method which should return the source code for the + module.""" return NotImplementedError class PyLoader(_bootstrap.PyLoader, InspectLoader): - """Abstract base class that implements the core parts needed to load Python - source code.""" + """Abstract base class to assist in loading source code by requiring only + back-end storage methods to be implemented. - # load_module and get_code are implemented. + The methods get_code, get_source, and load_module are implemented for the + user. + + """ @abc.abstractmethod def source_path(self, fullname:str) -> object: + """Abstract method which when implemented should return the path to the + sourced code for the module.""" raise NotImplementedError class PyPycLoader(_bootstrap.PyPycLoader, PyLoader): - """Abstract base class that implements the core parts needed to load Python - source and bytecode.""" + """Abstract base class to assist in loading source and bytecode by + requiring only back-end storage methods to be implemented. + + The methods get_code, get_source, and load_module are implemented for the + user. - # Implements load_module and get_code. + """ @abc.abstractmethod def source_mtime(self, fullname:str) -> int: + """Abstract method which when implemented should return the + modification time for the source of the module.""" raise NotImplementedError @abc.abstractmethod def bytecode_path(self, fullname:str) -> object: + """Abstract method which when implemented should return the path to the + bytecode for the module.""" raise NotImplementedError @abc.abstractmethod def write_bytecode(self, fullname:str, bytecode:bytes): + """Abstract method which when implemented should attempt to write the + bytecode for the module.""" raise NotImplementedError Modified: python/branches/py3k/Lib/importlib/test/import_/util.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/import_/util.py (original) +++ python/branches/py3k/Lib/importlib/test/import_/util.py Sun Mar 15 01:53:05 2009 @@ -10,7 +10,7 @@ if using___import__: return __import__(*args, **kwargs) else: - return importlib._bootstrap._import(*args, **kwargs) + return importlib._bootstrap.__import__(*args, **kwargs) def importlib_only(fxn): From buildbot at python.org Sun Mar 15 02:17:11 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 15 Mar 2009 01:17:11 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090315011711.568701E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/416 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_pipes test_threading_local make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sun Mar 15 02:28:54 2009 From: python-checkins at python.org (nick.coghlan) Date: Sun, 15 Mar 2009 02:28:54 +0100 (CET) Subject: [Python-checkins] r70374 - peps/trunk/pep-0377.txt Message-ID: <20090315012854.E23E01E4002@bag.python.org> Author: nick.coghlan Date: Sun Mar 15 02:28:54 2009 New Revision: 70374 Log: Formatting fix Modified: peps/trunk/pep-0377.txt Modified: peps/trunk/pep-0377.txt ============================================================================== --- peps/trunk/pep-0377.txt (original) +++ peps/trunk/pep-0377.txt Sun Mar 15 02:28:54 2009 @@ -214,7 +214,7 @@ statements at the AST level, thus allowing the semantics of actual nested ``with`` statements to be reproduced accurately. However, such a change would highlight rather than alleviate the problem the current PEP aims to -address: it would not be possible to use ``contextlib.contextmanager``to +address: it would not be possible to use ``contextlib.contextmanager`` to reliably factor out such ``with`` statements, as they would exhibit exactly the same semantic differences as are seen with the ``combined()`` context manager in the above example. From python-checkins at python.org Sun Mar 15 02:41:34 2009 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Mar 2009 02:41:34 +0100 (CET) Subject: [Python-checkins] r70375 - in python/branches/py3k: Doc/library/importlib.rst Lib/importlib/NOTES Lib/importlib/_bootstrap.py Lib/importlib/abc.py Lib/importlib/test/builtin/test_finder.py Lib/importlib/test/builtin/test_loader.py Lib/importlib/test/builtin/util.py Message-ID: <20090315014134.06E1D1E4002@bag.python.org> Author: brett.cannon Date: Sun Mar 15 02:41:33 2009 New Revision: 70375 Log: Implement InspectLoader for BuiltinImporter. Added: python/branches/py3k/Lib/importlib/test/builtin/util.py Modified: python/branches/py3k/Doc/library/importlib.rst python/branches/py3k/Lib/importlib/NOTES python/branches/py3k/Lib/importlib/_bootstrap.py python/branches/py3k/Lib/importlib/abc.py python/branches/py3k/Lib/importlib/test/builtin/test_finder.py python/branches/py3k/Lib/importlib/test/builtin/test_loader.py Modified: python/branches/py3k/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k/Doc/library/importlib.rst (original) +++ python/branches/py3k/Doc/library/importlib.rst Sun Mar 15 02:41:33 2009 @@ -175,11 +175,12 @@ An abstract base class for a :term:`loader` which implements the optional :pep:`302` protocol for loaders which inspect modules. - .. method:: is_package(fullname) + .. method:: get_code(fullname) - An abstract method to return a true value if the module is a package, a - false value otherwise. :exc:`ImportError` is raised if the - :term:`loader` cannot find the module. + An abstract method to return the :class:`code` object for a module. + :keyword:`None` is returned if the module does not have a code object + (e.g. built-in module). :exc:`ImportError` is raised if loader cannot + find the requested module. .. method:: get_source(fullname) @@ -188,12 +189,11 @@ source is available (e.g. a built-in module). Raises :exc:`ImportError` if the loader cannot find the module specified. - .. method:: get_code(fullname) + .. method:: is_package(fullname) - An abstract method to return the :class:`code` object for a module. - :keyword:`None` is returned if the module does not have a code object - (e.g. built-in module). :exc:`ImportError` is raised if loader cannot - find the requested module. + An abstract method to return a true value if the module is a package, a + false value otherwise. :exc:`ImportError` is raised if the + :term:`loader` cannot find the module. .. class:: PyLoader @@ -274,7 +274,8 @@ An :term:`importer` for built-in modules. All known built-in modules are listed in :data:`sys.builtin_module_names`. This class implements the - :class:`importlib.abc.Finder` and :class:`importlib.abc.Loader` ABCs. + :class:`importlib.abc.Finder` and :class:`importlib.abc.InspectLoader` + ABCs. Only class methods are defined by this class to alleviate the need for instantiation. Modified: python/branches/py3k/Lib/importlib/NOTES ============================================================================== --- python/branches/py3k/Lib/importlib/NOTES (original) +++ python/branches/py3k/Lib/importlib/NOTES Sun Mar 15 02:41:33 2009 @@ -1,9 +1,7 @@ to do ///// -* Fill in docstrings for ABCs. - -* Implement InspectLoader for BuiltinImporter and FrozenImporter. +* Implement InspectLoader for FrozenImporter. + Expose function to see if a frozen module is a package. Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Sun Mar 15 02:41:33 2009 @@ -173,6 +173,16 @@ return inner +def _requires_builtin(fxn): + """Decorator to verify the named module is built-in.""" + def wrapper(self, fullname): + if fullname not in sys.builtin_module_names: + raise ImportError("{0} is not a built-in module".format(fullname)) + return fxn(self, fullname) + _wrap(wrapper, fxn) + return wrapper + + def _suffix_list(suffix_type): """Return a list of file suffixes based on the imp file type.""" return [suffix[0] for suffix in imp.get_suffixes() @@ -204,10 +214,9 @@ @classmethod @set_package @set_loader + @_requires_builtin def load_module(cls, fullname): """Load a built-in module.""" - if fullname not in sys.builtin_module_names: - raise ImportError("{0} is not a built-in module".format(fullname)) is_reload = fullname in sys.modules try: return imp.init_builtin(fullname) @@ -216,6 +225,24 @@ del sys.modules[fullname] raise + @classmethod + @_requires_builtin + def get_code(cls, fullname): + """Return None as built-in modules do not have code objects.""" + return None + + @classmethod + @_requires_builtin + def get_source(cls, fullname): + """Return None as built-in modules do not have source code.""" + return None + + @classmethod + @_requires_builtin + def is_package(cls, fullname): + """Return None as built-in module are never packages.""" + return False + class FrozenImporter: Modified: python/branches/py3k/Lib/importlib/abc.py ============================================================================== --- python/branches/py3k/Lib/importlib/abc.py (original) +++ python/branches/py3k/Lib/importlib/abc.py Sun Mar 15 02:41:33 2009 @@ -14,7 +14,6 @@ """Abstract method which when implemented should load a module.""" raise NotImplementedError -Loader.register(machinery.BuiltinImporter) Loader.register(machinery.FrozenImporter) @@ -75,6 +74,8 @@ module.""" return NotImplementedError +InspectLoader.register(machinery.BuiltinImporter) + class PyLoader(_bootstrap.PyLoader, InspectLoader): Modified: python/branches/py3k/Lib/importlib/test/builtin/test_finder.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/builtin/test_finder.py (original) +++ python/branches/py3k/Lib/importlib/test/builtin/test_finder.py Sun Mar 15 02:41:33 2009 @@ -1,6 +1,7 @@ from importlib import machinery from .. import abc from .. import util +from . import util as builtin_util import sys import unittest @@ -9,13 +10,11 @@ """Test find_module() for built-in modules.""" - assert 'errno' in sys.builtin_module_names - name = 'errno' - def test_module(self): # Common case. - with util.uncache(self.name): - self.assert_(machinery.BuiltinImporter.find_module(self.name)) + with util.uncache(builtin_util.NAME): + found = machinery.BuiltinImporter.find_module(builtin_util.NAME) + self.assert_(found) def test_package(self): # Built-in modules cannot be a package. @@ -40,8 +39,9 @@ def test_ignore_path(self): # The value for 'path' should always trigger a failed import. - with util.uncache(self.name): - loader = machinery.BuiltinImporter.find_module(self.name, ['pkg']) + with util.uncache(builtin_util.NAME): + loader = machinery.BuiltinImporter.find_module(builtin_util.NAME, + ['pkg']) self.assert_(loader is None) Modified: python/branches/py3k/Lib/importlib/test/builtin/test_loader.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/builtin/test_loader.py (original) +++ python/branches/py3k/Lib/importlib/test/builtin/test_loader.py Sun Mar 15 02:41:33 2009 @@ -2,6 +2,7 @@ from importlib import machinery from .. import abc from .. import util +from . import util as builtin_util import sys import types @@ -12,9 +13,6 @@ """Test load_module() for built-in modules.""" - assert 'errno' in sys.builtin_module_names - name = 'errno' - verification = {'__name__': 'errno', '__package__': '', '__loader__': machinery.BuiltinImporter} @@ -30,8 +28,8 @@ def test_module(self): # Common case. - with util.uncache(self.name): - module = self.load_module(self.name) + with util.uncache(builtin_util.NAME): + module = self.load_module(builtin_util.NAME) self.verify(module) def test_package(self): @@ -48,9 +46,9 @@ def test_module_reuse(self): # Test that the same module is used in a reload. - with util.uncache(self.name): - module1 = self.load_module(self.name) - module2 = self.load_module(self.name) + with util.uncache(builtin_util.NAME): + module1 = self.load_module(builtin_util.NAME) + module2 = self.load_module(builtin_util.NAME) self.assert_(module1 is module2) def test_unloadable(self): @@ -65,9 +63,36 @@ self.assertRaises(ImportError, self.load_module, 'importlib') +class InspectLoaderTests(unittest.TestCase): + + """Tests for InspectLoader methods for BuiltinImporter.""" + + def test_get_code(self): + # There is no code object. + result = machinery.BuiltinImporter.get_code(builtin_util.NAME) + self.assert_(result is None) + + def test_get_source(self): + # There is no source. + result = machinery.BuiltinImporter.get_source(builtin_util.NAME) + self.assert_(result is None) + + def test_is_package(self): + # Cannot be a package. + result = machinery.BuiltinImporter.is_package(builtin_util.NAME) + self.assert_(not result) + + def test_not_builtin(self): + # Modules not built-in should raise ImportError. + for meth_name in ('get_code', 'get_source', 'is_package'): + method = getattr(machinery.BuiltinImporter, meth_name) + self.assertRaises(ImportError, method, builtin_util.BAD_NAME) + + + def test_main(): from test.support import run_unittest - run_unittest(LoaderTests) + run_unittest(LoaderTests, InspectLoaderTests) if __name__ == '__main__': Added: python/branches/py3k/Lib/importlib/test/builtin/util.py ============================================================================== --- (empty file) +++ python/branches/py3k/Lib/importlib/test/builtin/util.py Sun Mar 15 02:41:33 2009 @@ -0,0 +1,7 @@ +import sys + +assert 'errno' in sys.builtin_module_names +NAME = 'errno' + +assert 'importlib' not in sys.builtin_module_names +BAD_NAME = 'importlib' From python-checkins at python.org Sun Mar 15 03:18:42 2009 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Mar 2009 03:18:42 +0100 (CET) Subject: [Python-checkins] r70376 - python/branches/py3k/Doc/library/functions.rst Message-ID: <20090315021842.280C91E4002@bag.python.org> Author: brett.cannon Date: Sun Mar 15 03:18:41 2009 New Revision: 70376 Log: Fix docs for __import__ that say the default for 'level' is -1; it's actually 0. Modified: python/branches/py3k/Doc/library/functions.rst Modified: python/branches/py3k/Doc/library/functions.rst ============================================================================== --- python/branches/py3k/Doc/library/functions.rst (original) +++ python/branches/py3k/Doc/library/functions.rst Sun Mar 15 03:18:41 2009 @@ -1207,9 +1207,8 @@ not use its *locals* argument at all, and uses its *globals* only to determine the package context of the :keyword:`import` statement. - *level* specifies whether to use absolute or relative imports. The default - is ``-1`` which indicates both absolute and relative imports will be - attempted. ``0`` means only perform absolute imports. Positive values for + *level* specifies whether to use absolute or relative imports. ``0`` (the + default) means only perform absolute imports. Positive values for *level* indicate the number of parent directories to search relative to the directory of the module calling :func:`__import__`. @@ -1221,11 +1220,11 @@ For example, the statement ``import spam`` results in bytecode resembling the following code:: - spam = __import__('spam', globals(), locals(), [], -1) + spam = __import__('spam', globals(), locals(), [], 0) The statement ``import spam.ham`` results in this call:: - spam = __import__('spam.ham', globals(), locals(), [], -1) + spam = __import__('spam.ham', globals(), locals(), [], 0) Note how :func:`__import__` returns the toplevel module here because this is the object that is bound to a name by the :keyword:`import` statement. @@ -1233,7 +1232,7 @@ On the other hand, the statement ``from spam.ham import eggs, sausage as saus`` results in :: - _temp = __import__('spam.ham', globals(), locals(), ['eggs', 'sausage'], -1) + _temp = __import__('spam.ham', globals(), locals(), ['eggs', 'sausage'], 0) eggs = _temp.eggs saus = _temp.sausage From python-checkins at python.org Sun Mar 15 03:20:16 2009 From: python-checkins at python.org (brett.cannon) Date: Sun, 15 Mar 2009 03:20:16 +0100 (CET) Subject: [Python-checkins] r70377 - in python/branches/py3k: Doc/library/importlib.rst Lib/importlib/NOTES Lib/importlib/_bootstrap.py Lib/importlib/abc.py Lib/importlib/test/frozen/test_loader.py Python/import.c Message-ID: <20090315022016.4ADA21E4002@bag.python.org> Author: brett.cannon Date: Sun Mar 15 03:20:16 2009 New Revision: 70377 Log: Implement InspectLoader for FrozenImporter. Modified: python/branches/py3k/Doc/library/importlib.rst python/branches/py3k/Lib/importlib/NOTES python/branches/py3k/Lib/importlib/_bootstrap.py python/branches/py3k/Lib/importlib/abc.py python/branches/py3k/Lib/importlib/test/frozen/test_loader.py python/branches/py3k/Python/import.c Modified: python/branches/py3k/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k/Doc/library/importlib.rst (original) +++ python/branches/py3k/Doc/library/importlib.rst Sun Mar 15 03:20:16 2009 @@ -284,7 +284,8 @@ .. class:: FrozenImporter An :term:`importer` for frozen modules. This class implements the - :class:`importlib.abc.Finder` and :class:`importlib.abc.Loader` ABCs. + :class:`importlib.abc.Finder` and :class:`importlib.abc.InspectLoader` + ABCs. Only class methods are defined by this class to alleviate the need for instantiation. Modified: python/branches/py3k/Lib/importlib/NOTES ============================================================================== --- python/branches/py3k/Lib/importlib/NOTES (original) +++ python/branches/py3k/Lib/importlib/NOTES Sun Mar 15 03:20:16 2009 @@ -1,10 +1,6 @@ to do ///// -* Implement InspectLoader for FrozenImporter. - - + Expose function to see if a frozen module is a package. - * Make sure that there is documentation *somewhere* fully explaining the semantics of import that can be referenced from the package's documentation (even if it is in the package documentation itself, although it might be best Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Sun Mar 15 03:20:16 2009 @@ -183,6 +183,16 @@ return wrapper +def _requires_frozen(fxn): + """Decorator to verify the named module is frozen.""" + def wrapper(self, fullname): + if not imp.is_frozen(fullname): + raise ImportError("{0} is not a frozen module".format(fullname)) + return fxn(self, fullname) + _wrap(wrapper, fxn) + return wrapper + + def _suffix_list(suffix_type): """Return a list of file suffixes based on the imp file type.""" return [suffix[0] for suffix in imp.get_suffixes() @@ -261,10 +271,9 @@ @classmethod @set_package @set_loader + @_requires_frozen def load_module(cls, fullname): """Load a frozen module.""" - if cls.find_module(fullname) is None: - raise ImportError("{0} is not a frozen module".format(fullname)) is_reload = fullname in sys.modules try: return imp.init_frozen(fullname) @@ -273,6 +282,24 @@ del sys.modules[fullname] raise + @classmethod + @_requires_frozen + def get_code(cls, fullname): + """Return the code object for the frozen module.""" + return imp.get_frozen_object(fullname) + + @classmethod + @_requires_frozen + def get_source(cls, fullname): + """Return None as frozen modules do not have source code.""" + return None + + @classmethod + @_requires_frozen + def is_package(cls, fullname): + """Return if the frozen module is a package.""" + return imp.is_frozen_package(fullname) + class PyLoader: Modified: python/branches/py3k/Lib/importlib/abc.py ============================================================================== --- python/branches/py3k/Lib/importlib/abc.py (original) +++ python/branches/py3k/Lib/importlib/abc.py Sun Mar 15 03:20:16 2009 @@ -14,8 +14,6 @@ """Abstract method which when implemented should load a module.""" raise NotImplementedError -Loader.register(machinery.FrozenImporter) - class Finder(metaclass=abc.ABCMeta): @@ -75,6 +73,7 @@ return NotImplementedError InspectLoader.register(machinery.BuiltinImporter) +InspectLoader.register(machinery.FrozenImporter) class PyLoader(_bootstrap.PyLoader, InspectLoader): Modified: python/branches/py3k/Lib/importlib/test/frozen/test_loader.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/frozen/test_loader.py (original) +++ python/branches/py3k/Lib/importlib/test/frozen/test_loader.py Sun Mar 15 03:20:16 2009 @@ -1,4 +1,6 @@ from importlib import machinery +import imp +import unittest from .. import abc from .. import util @@ -53,9 +55,41 @@ '_not_real') +class InspectLoaderTests(unittest.TestCase): + + """Tests for the InspectLoader methods for FrozenImporter.""" + + def test_get_code(self): + # Make sure that the code object is good. + name = '__hello__' + code = machinery.FrozenImporter.get_code(name) + mod = imp.new_module(name) + exec(code, mod.__dict__) + self.assert_(hasattr(mod, 'initialized')) + + def test_get_source(self): + # Should always return None. + result = machinery.FrozenImporter.get_source('__hello__') + self.assert_(result is None) + + def test_is_package(self): + # Should be able to tell what is a package. + test_for = (('__hello__', False), ('__phello__', True), + ('__phello__.spam', False)) + for name, is_package in test_for: + result = machinery.FrozenImporter.is_package(name) + self.assert_(bool(result) == is_package) + + def test_failure(self): + # Raise ImportError for modules that are not frozen. + for meth_name in ('get_code', 'get_source', 'is_package'): + method = getattr(machinery.FrozenImporter, meth_name) + self.assertRaises(ImportError, method, 'importlib') + + def test_main(): from test.support import run_unittest - run_unittest(LoaderTests) + run_unittest(LoaderTests, InspectLoaderTests) if __name__ == '__main__': Modified: python/branches/py3k/Python/import.c ============================================================================== --- python/branches/py3k/Python/import.c (original) +++ python/branches/py3k/Python/import.c Sun Mar 15 03:20:16 2009 @@ -1951,6 +1951,28 @@ return PyMarshal_ReadObjectFromString((char *)p->code, size); } +static PyObject * +is_frozen_package(char *name) +{ + struct _frozen *p = find_frozen(name); + int size; + + if (p == NULL) { + PyErr_Format(PyExc_ImportError, + "No such frozen object named %.200s", + name); + return NULL; + } + + size = p->size; + + if (size < 0) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + + /* Initialize a frozen module. Return 1 for success, 0 if the module is not found, and -1 with an exception set if the initialization failed. @@ -2959,6 +2981,16 @@ } static PyObject * +imp_is_frozen_package(PyObject *self, PyObject *args) +{ + char *name; + + if (!PyArg_ParseTuple(args, "s:is_frozen_package", &name)) + return NULL; + return is_frozen_package(name); +} + +static PyObject * imp_is_builtin(PyObject *self, PyObject *args) { char *name; @@ -3191,6 +3223,7 @@ {"reload", imp_reload, METH_O, doc_reload}, /* The rest are obsolete */ {"get_frozen_object", imp_get_frozen_object, METH_VARARGS}, + {"is_frozen_package", imp_is_frozen_package, METH_VARARGS}, {"init_builtin", imp_init_builtin, METH_VARARGS}, {"init_frozen", imp_init_frozen, METH_VARARGS}, {"is_builtin", imp_is_builtin, METH_VARARGS}, From buildbot at python.org Sun Mar 15 03:23:21 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 15 Mar 2009 02:23:21 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090315022322.24B741E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/453 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sun Mar 15 04:24:46 2009 From: python-checkins at python.org (nick.coghlan) Date: Sun, 15 Mar 2009 04:24:46 +0100 (CET) Subject: [Python-checkins] r70378 - python/trunk/Python/marshal.c Message-ID: <20090315032447.0075D1E4002@bag.python.org> Author: nick.coghlan Date: Sun Mar 15 04:24:46 2009 New Revision: 70378 Log: Make marshalling errors a little more informative as to what went wrong Modified: python/trunk/Python/marshal.c Modified: python/trunk/Python/marshal.c ============================================================================== --- python/trunk/Python/marshal.c (original) +++ python/trunk/Python/marshal.c Sun Mar 15 04:24:46 2009 @@ -576,7 +576,7 @@ n = r_long(p); if (n < -INT_MAX || n > INT_MAX) { PyErr_SetString(PyExc_ValueError, - "bad marshal data"); + "bad marshal data (long size out of range)"); retval = NULL; break; } @@ -592,7 +592,7 @@ if (digit < 0) { Py_DECREF(ob); PyErr_SetString(PyExc_ValueError, - "bad marshal data"); + "bad marshal data (negative digit in long)"); ob = NULL; break; } @@ -709,7 +709,7 @@ case TYPE_STRING: n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (string size out of range)"); retval = NULL; break; } @@ -738,7 +738,7 @@ case TYPE_STRINGREF: n = r_long(p); if (n < 0 || n >= PyList_GET_SIZE(p->strings)) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (string ref out of range)"); retval = NULL; break; } @@ -754,7 +754,7 @@ n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (unicode size out of range)"); retval = NULL; break; } @@ -780,7 +780,7 @@ case TYPE_TUPLE: n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (tuple size out of range)"); retval = NULL; break; } @@ -794,7 +794,7 @@ if ( v2 == NULL ) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_TypeError, - "NULL object in marshal data"); + "NULL object in marshal data for tuple"); Py_DECREF(v); v = NULL; break; @@ -807,7 +807,7 @@ case TYPE_LIST: n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (list size out of range)"); retval = NULL; break; } @@ -821,7 +821,7 @@ if ( v2 == NULL ) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_TypeError, - "NULL object in marshal data"); + "NULL object in marshal data for list"); Py_DECREF(v); v = NULL; break; @@ -859,7 +859,7 @@ case TYPE_FROZENSET: n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (set size out of range)"); retval = NULL; break; } @@ -873,7 +873,7 @@ if ( v2 == NULL ) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_TypeError, - "NULL object in marshal data"); + "NULL object in marshal data for set"); Py_DECREF(v); v = NULL; break; @@ -973,7 +973,7 @@ default: /* Bogus data got written, which isn't ideal. This will let you keep working and recover. */ - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (unknown type code)"); retval = NULL; break; @@ -992,7 +992,7 @@ } v = r_object(p); if (v == NULL && !PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, "NULL object in marshal data"); + PyErr_SetString(PyExc_TypeError, "NULL object in marshal data for object"); return v; } From python-checkins at python.org Sun Mar 15 04:41:37 2009 From: python-checkins at python.org (nick.coghlan) Date: Sun, 15 Mar 2009 04:41:37 +0100 (CET) Subject: [Python-checkins] r70379 - python/branches/release26-maint Message-ID: <20090315034137.CBA781E4002@bag.python.org> Author: nick.coghlan Date: Sun Mar 15 04:41:37 2009 New Revision: 70379 Log: Blocked revisions 70378 via svnmerge ........ r70378 | nick.coghlan | 2009-03-15 13:24:46 +1000 (Sun, 15 Mar 2009) | 1 line Make marshalling errors a little more informative as to what went wrong ........ Modified: python/branches/release26-maint/ (props changed) From buildbot at python.org Sun Mar 15 05:05:06 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 15 Mar 2009 04:05:06 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo trunk Message-ID: <20090315040506.38FC91E4002@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%20gentoo%20trunk/builds/4725 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: nick.coghlan BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Sun Mar 15 05:05:52 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 15 Mar 2009 04:05:52 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu trunk Message-ID: <20090315040552.52DEC1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%20trunk/builds/960 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: nick.coghlan BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Sun Mar 15 05:22:03 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 15 Mar 2009 04:22:03 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090315042203.D11F41E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/173 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: nick.coghlan BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/test/test_ftplib.py", line 203, in run asyncore.loop(timeout=0.1, count=1) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 204, in loop poll_fun(timeout, map) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 141, in poll read(obj) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 78, in read obj.handle_error() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 74, in read obj.handle_read_event() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 413, in handle_read_event self.handle_read() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/test/test_ssl.py", line 408, in handle_read self.send(data.lower()) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 519, in send self.initiate_send() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 506, in initiate_send num_sent = dispatcher.send(self, self.out_buffer[:512]) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 349, in send result = self.socket.send(data) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/socket.py", line 165, in _dummy raise error(EBADF, 'Bad file descriptor') error: [Errno 9] Bad file descriptor 1 test failed: test_ftplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sun Mar 15 05:47:46 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 15 Mar 2009 04:47:46 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 2.6 Message-ID: <20090315044746.BF28A1E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%202.6/builds/169 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: nick.coghlan BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sun Mar 15 06:07:57 2009 From: python-checkins at python.org (nick.coghlan) Date: Sun, 15 Mar 2009 06:07:57 +0100 (CET) Subject: [Python-checkins] r70380 - in python/branches/py3k: Python/marshal.c Message-ID: <20090315050757.155481E4002@bag.python.org> Author: nick.coghlan Date: Sun Mar 15 06:07:56 2009 New Revision: 70380 Log: Merged revisions 70378 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70378 | nick.coghlan | 2009-03-15 13:24:46 +1000 (Sun, 15 Mar 2009) | 1 line Make marshalling errors a little more informative as to what went wrong ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Python/marshal.c Modified: python/branches/py3k/Python/marshal.c ============================================================================== --- python/branches/py3k/Python/marshal.c (original) +++ python/branches/py3k/Python/marshal.c Sun Mar 15 06:07:56 2009 @@ -550,7 +550,7 @@ n = r_long(p); if (n < -INT_MAX || n > INT_MAX) { PyErr_SetString(PyExc_ValueError, - "bad marshal data"); + "bad marshal data (long size out of range)"); retval = NULL; break; } @@ -566,7 +566,7 @@ if (digit < 0) { Py_DECREF(ob); PyErr_SetString(PyExc_ValueError, - "bad marshal data"); + "bad marshal data (negative digit in long)"); ob = NULL; break; } @@ -682,7 +682,7 @@ case TYPE_STRING: n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (string size out of range)"); retval = NULL; break; } @@ -707,7 +707,7 @@ n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (unicode size out of range)"); retval = NULL; break; } @@ -732,7 +732,7 @@ case TYPE_TUPLE: n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (tuple size out of range)"); retval = NULL; break; } @@ -746,7 +746,7 @@ if ( v2 == NULL ) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_TypeError, - "NULL object in marshal data"); + "NULL object in marshal data for tuple"); Py_DECREF(v); v = NULL; break; @@ -759,7 +759,7 @@ case TYPE_LIST: n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (list size out of range)"); retval = NULL; break; } @@ -773,7 +773,7 @@ if ( v2 == NULL ) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_TypeError, - "NULL object in marshal data"); + "NULL object in marshal data for list"); Py_DECREF(v); v = NULL; break; @@ -811,7 +811,7 @@ case TYPE_FROZENSET: n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (set size out of range)"); retval = NULL; break; } @@ -825,7 +825,7 @@ if ( v2 == NULL ) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_TypeError, - "NULL object in marshal data"); + "NULL object in marshal data for set"); Py_DECREF(v); v = NULL; break; @@ -920,7 +920,7 @@ default: /* Bogus data got written, which isn't ideal. This will let you keep working and recover. */ - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (unknown type code)"); retval = NULL; break; @@ -939,7 +939,7 @@ } v = r_object(p); if (v == NULL && !PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, "NULL object in marshal data"); + PyErr_SetString(PyExc_TypeError, "NULL object in marshal data for object"); return v; } From python-checkins at python.org Sun Mar 15 06:10:35 2009 From: python-checkins at python.org (nick.coghlan) Date: Sun, 15 Mar 2009 06:10:35 +0100 (CET) Subject: [Python-checkins] r70381 - python/branches/release30-maint Message-ID: <20090315051035.683D91E4002@bag.python.org> Author: nick.coghlan Date: Sun Mar 15 06:10:35 2009 New Revision: 70381 Log: Blocked revisions 70380 via svnmerge ................ r70380 | nick.coghlan | 2009-03-15 15:07:56 +1000 (Sun, 15 Mar 2009) | 9 lines Merged revisions 70378 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70378 | nick.coghlan | 2009-03-15 13:24:46 +1000 (Sun, 15 Mar 2009) | 1 line Make marshalling errors a little more informative as to what went wrong ........ ................ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Sun Mar 15 06:38:01 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 15 Mar 2009 05:38:01 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090315053801.C55AF1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/480 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: nick.coghlan BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_ssl make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sun Mar 15 06:53:51 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 15 Mar 2009 05:53:51 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 2.6 Message-ID: <20090315055351.C372B1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%202.6/builds/167 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: nick.coghlan BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sun Mar 15 13:41:43 2009 From: python-checkins at python.org (nick.coghlan) Date: Sun, 15 Mar 2009 13:41:43 +0100 (CET) Subject: [Python-checkins] r70382 - peps/trunk/pep-0377.txt Message-ID: <20090315124143.587C11E4002@bag.python.org> Author: nick.coghlan Date: Sun Mar 15 13:41:42 2009 New Revision: 70382 Log: Tweak comments on performance impact based on current implementation Modified: peps/trunk/pep-0377.txt Modified: peps/trunk/pep-0377.txt ============================================================================== --- peps/trunk/pep-0377.txt (original) +++ peps/trunk/pep-0377.txt Sun Mar 15 13:41:42 2009 @@ -166,7 +166,7 @@ With the proposed semantic change in place, the contextlib based examples above would then "just work", but the class based version would need -adjustment to take advantage of the new semantics:: +a small adjustment to take advantage of the new semantics:: class CM(object): def __init__(self): @@ -220,17 +220,31 @@ manager in the above example. +Performance Impact +================== + +Implementing the new semantics makes it necessary to store the references +to the ``__enter__`` and ``__exit__`` methods in temporary variables instead +of on the stack. This results in a slight regression in ``with`` statement +speed relative to Python 2.6/3.1. However, implementing a custom +``SETUP_WITH`` opcode would negate any differences between the two +approaches (as well as dramatically improving speed by eliminating more +than a dozen unnecessary trips around the eval loop). + + Reference Implementation ======================== -In work. +Patch attached to Issue 5251 [1]. That patch uses only existing opcodes +(i.e. no ``SETUP_WITH``). Acknowledgements ================ -James William Pye both raised the issue and suggested the solution -described in this PEP. +James William Pye both raised the issue and suggested the basic outline of +the solution described in this PEP. + References ========== @@ -244,6 +258,7 @@ .. [3] Import-style syntax to reduce indentation of nested with statements (http://mail.python.org/pipermail/python-ideas/2009-March/003188.html) + Copyright ========= From python-checkins at python.org Sun Mar 15 13:47:03 2009 From: python-checkins at python.org (nick.coghlan) Date: Sun, 15 Mar 2009 13:47:03 +0100 (CET) Subject: [Python-checkins] r70383 - peps/trunk/pep-0377.txt Message-ID: <20090315124703.B7D691E4002@bag.python.org> Author: nick.coghlan Date: Sun Mar 15 13:47:03 2009 New Revision: 70383 Log: Change abstract to avoid the implication that the problem is specific to contextlib.nested Modified: peps/trunk/pep-0377.txt Modified: peps/trunk/pep-0377.txt ============================================================================== --- peps/trunk/pep-0377.txt (original) +++ peps/trunk/pep-0377.txt Sun Mar 15 13:47:03 2009 @@ -16,9 +16,13 @@ This PEP proposes a backwards compatible mechanism that allows ``__enter__()`` methods to skip the body of the associated ``with`` statment. The lack of -this ability currently means the ``contextlib.nested`` context manager -is unable to fulfil its specification of being equivalent to writing out -multiple nested ``with`` statements [1]. +this ability currently means the ``contextlib.contextmanager`` decorator +is unable to fulfil its specification of being able to turn arbitrary +code into a context manager by moving it into a generator function +with a yield in the appropriate location. One symptom of this is that +``contextlib.nested`` will currently raise ``RuntimeError`` in +situations where writing out the corresponding nested ``with`` +statements would not [1]. The proposed change is to introduce a new flow control exception ``SkipStatement``, and skip the execution of the ``with`` From python-checkins at python.org Sun Mar 15 13:48:49 2009 From: python-checkins at python.org (nick.coghlan) Date: Sun, 15 Mar 2009 13:48:49 +0100 (CET) Subject: [Python-checkins] r70384 - peps/trunk/pep-0377.txt Message-ID: <20090315124849.B420A1E4002@bag.python.org> Author: nick.coghlan Date: Sun Mar 15 13:48:49 2009 New Revision: 70384 Log: Fix typo Modified: peps/trunk/pep-0377.txt Modified: peps/trunk/pep-0377.txt ============================================================================== --- peps/trunk/pep-0377.txt (original) +++ peps/trunk/pep-0377.txt Sun Mar 15 13:48:49 2009 @@ -15,7 +15,7 @@ ======== This PEP proposes a backwards compatible mechanism that allows ``__enter__()`` -methods to skip the body of the associated ``with`` statment. The lack of +methods to skip the body of the associated ``with`` statement. The lack of this ability currently means the ``contextlib.contextmanager`` decorator is unable to fulfil its specification of being able to turn arbitrary code into a context manager by moving it into a generator function From python-checkins at python.org Sun Mar 15 15:38:55 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 15 Mar 2009 15:38:55 +0100 (CET) Subject: [Python-checkins] r70385 - python/trunk/Objects/tupleobject.c Message-ID: <20090315143855.E73771E4043@bag.python.org> Author: benjamin.peterson Date: Sun Mar 15 15:38:55 2009 New Revision: 70385 Log: fix tuple.index() error message #5495 Modified: python/trunk/Objects/tupleobject.c Modified: python/trunk/Objects/tupleobject.c ============================================================================== --- python/trunk/Objects/tupleobject.c (original) +++ python/trunk/Objects/tupleobject.c Sun Mar 15 15:38:55 2009 @@ -483,7 +483,7 @@ else if (cmp < 0) return NULL; } - PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in list"); + PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in tuple"); return NULL; } From buildbot at python.org Sun Mar 15 16:36:54 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 15 Mar 2009 15:36:54 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090315153654.9ACCE1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/726 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_poplib.py", line 131, in run asyncore.loop(timeout=0.1, count=1) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 204, in loop poll_fun(timeout, map) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 141, in poll read(obj) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 78, in read obj.handle_error() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 74, in read obj.handle_read_event() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 413, in handle_read_event self.handle_read() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_ssl.py", line 408, in handle_read self.send(data.lower()) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 519, in send self.initiate_send() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 506, in initiate_send num_sent = dispatcher.send(self, self.out_buffer[:512]) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 349, in send result = self.socket.send(data) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/socket.py", line 165, in _dummy raise error(EBADF, 'Bad file descriptor') error: [Errno 9] Bad file descriptor sincerely, -The Buildbot From python-checkins at python.org Sun Mar 15 22:32:07 2009 From: python-checkins at python.org (georg.brandl) Date: Sun, 15 Mar 2009 22:32:07 +0100 (CET) Subject: [Python-checkins] r70386 - python/trunk/Modules/_codecsmodule.c Message-ID: <20090315213207.045A21E404D@bag.python.org> Author: georg.brandl Date: Sun Mar 15 22:32:06 2009 New Revision: 70386 Log: #5496: fix docstring of lookup(). Modified: python/trunk/Modules/_codecsmodule.c Modified: python/trunk/Modules/_codecsmodule.c ============================================================================== --- python/trunk/Modules/_codecsmodule.c (original) +++ python/trunk/Modules/_codecsmodule.c Sun Mar 15 22:32:06 2009 @@ -61,7 +61,7 @@ "lookup(encoding) -> CodecInfo\n\ \n\ Looks up a codec tuple in the Python codec registry and returns\n\ -a tuple of function (or a CodecInfo object)."); +a CodecInfo object."); static PyObject *codec_lookup(PyObject *self, PyObject *args) From python-checkins at python.org Sun Mar 15 22:37:16 2009 From: python-checkins at python.org (georg.brandl) Date: Sun, 15 Mar 2009 22:37:16 +0100 (CET) Subject: [Python-checkins] r70387 - python/trunk/Doc/reference/datamodel.rst Message-ID: <20090315213716.9D2291E4002@bag.python.org> Author: georg.brandl Date: Sun Mar 15 22:37:16 2009 New Revision: 70387 Log: #5493: clarify __nonzero__ docs. Modified: python/trunk/Doc/reference/datamodel.rst Modified: python/trunk/Doc/reference/datamodel.rst ============================================================================== --- python/trunk/Doc/reference/datamodel.rst (original) +++ python/trunk/Doc/reference/datamodel.rst Sun Mar 15 22:37:16 2009 @@ -1424,11 +1424,12 @@ .. index:: single: __len__() (mapping object method) - Called to implement truth value testing, and the built-in operation ``bool()``; + Called to implement truth value testing and the built-in operation ``bool()``; should return ``False`` or ``True``, or their integer equivalents ``0`` or - ``1``. When this method is not defined, :meth:`__len__` is called, if it is - defined (see below). If a class defines neither :meth:`__len__` nor - :meth:`__nonzero__`, all its instances are considered true. + ``1``. When this method is not defined, :meth:`__len__` is called, if it is + defined, and the object is considered true if its result is nonzero. + If a class defines neither :meth:`__len__` nor :meth:`__nonzero__`, all its + instances are considered true. .. method:: object.__unicode__(self) From python-checkins at python.org Sun Mar 15 22:43:34 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 15 Mar 2009 22:43:34 +0100 (CET) Subject: [Python-checkins] r70388 - in tracker/roundup-src: CHANGES.txt COPYING.txt ChangeLog MANIFEST.in README.txt demo.py detectors/creator_resolution.py doc/FAQ.txt doc/_static doc/_static/style.css doc/_templates doc/_templates/layout.html doc/acknowledgements.txt doc/admin_guide.txt doc/announcement.txt doc/contact.txt doc/customizing.txt doc/default.css doc/design.txt doc/developers.txt doc/index.txt doc/installation.txt doc/license.txt doc/roundup-admin.1 doc/roundup-demo.1 doc/roundup-mailgw.1 doc/roundup-server.1 doc/upgrading.txt doc/user_guide.txt doc/xmlrpc.txt frontends/ZRoundup/ZRoundup.py frontends/ZRoundup/__init__.py frontends/roundup.cgi locale/de.po locale/en.po locale/fr.po locale/it.po locale/lt.po locale/roundup.pot locale/ru.po locale/zh_CN.po locale/zh_TW.po roundup/__init__.py roundup/actions.py roundup/admin.py roundup/anypy roundup/anypy/README.txt roundup/anypy/TODO.txt roundup/anypy/__init__.py roundup/anypy/hashlib_.py roundup/anypy/sets_.py roundup/backends/__init__.py roundup/backends/back_anydbm.py roundup/backends/back_metakit.py roundup/backends/back_mysql.py roundup/backends/back_postgresql.py roundup/backends/back_sqlite.py roundup/backends/back_tsearch2.py roundup/backends/blobfiles.py roundup/backends/indexer_common.py roundup/backends/indexer_dbm.py roundup/backends/indexer_rdbms.py roundup/backends/indexer_xapian.py roundup/backends/locking.py roundup/backends/portalocker.py roundup/backends/rdbms_common.py roundup/backends/sessions_dbm.py roundup/backends/sessions_rdbms.py roundup/backends/tsearch2_setup.py roundup/cgi/PageTemplates/GlobalTranslationService.py roundup/cgi/PageTemplates/__init__.py roundup/cgi/TAL/TranslationContext.py roundup/cgi/TranslationService.py roundup/cgi/ZTUtils/Batch.py roundup/cgi/ZTUtils/Iterator.py roundup/cgi/ZTUtils/__init__.py roundup/cgi/actions.py roundup/cgi/apache.py roundup/cgi/cgitb.py roundup/cgi/client.py roundup/cgi/exceptions.py roundup/cgi/form_parser.py roundup/cgi/templating.py roundup/cgi/wsgi_handler.py roundup/configuration.py roundup/date.py roundup/dist roundup/dist/__init__.py roundup/dist/command roundup/dist/command/__init__.py roundup/dist/command/bdist_rpm.py roundup/dist/command/build.py roundup/dist/command/build_doc.py roundup/dist/command/build_py.py roundup/dist/command/build_scripts.py roundup/exceptions.py roundup/hyperdb.py roundup/i18n.py roundup/init.py roundup/install_util.py roundup/instance.py roundup/mailer.py roundup/mailgw.py roundup/password.py roundup/roundupdb.py roundup/scripts/__init__.py roundup/scripts/roundup_admin.py roundup/scripts/roundup_demo.py roundup/scripts/roundup_gettext.py roundup/scripts/roundup_mailgw.py roundup/scripts/roundup_server.py roundup/security.py roundup/token.py roundup/version_check.py roundup/xmlrpc.py run_tests.py scripts/add-issue scripts/copy-user.py scripts/import_sf.py scripts/roundup-reminder scripts/roundup.rc-debian scripts/weekly-report setup.py share share/man share/man/man1 share/man/man1/roundup-admin.1 share/man/man1/roundup-demo.1 share/man/man1/roundup-mailgw.1 share/man/man1/roundup-server.1 sha Message-ID: <20090315214334.F0D2F1E400C@bag.python.org> Author: martin.v.loewis Date: Sun Mar 15 22:43:30 2009 New Revision: 70388 Log: Import roundup 1.4.7 as-is; local changes will be re-applied. Added: tracker/roundup-src/doc/_static/ tracker/roundup-src/doc/_static/style.css (contents, props changed) tracker/roundup-src/doc/_templates/ tracker/roundup-src/doc/_templates/layout.html (contents, props changed) tracker/roundup-src/doc/acknowledgements.txt (contents, props changed) tracker/roundup-src/doc/contact.txt (contents, props changed) tracker/roundup-src/doc/license.txt (contents, props changed) tracker/roundup-src/doc/xmlrpc.txt (contents, props changed) tracker/roundup-src/locale/it.po (contents, props changed) tracker/roundup-src/roundup/actions.py (contents, props changed) tracker/roundup-src/roundup/anypy/ tracker/roundup-src/roundup/anypy/README.txt (contents, props changed) tracker/roundup-src/roundup/anypy/TODO.txt (contents, props changed) tracker/roundup-src/roundup/anypy/__init__.py (contents, props changed) tracker/roundup-src/roundup/anypy/hashlib_.py (contents, props changed) tracker/roundup-src/roundup/anypy/sets_.py (contents, props changed) tracker/roundup-src/roundup/dist/ tracker/roundup-src/roundup/dist/__init__.py (contents, props changed) tracker/roundup-src/roundup/dist/command/ tracker/roundup-src/roundup/dist/command/__init__.py (contents, props changed) tracker/roundup-src/roundup/dist/command/bdist_rpm.py (contents, props changed) tracker/roundup-src/roundup/dist/command/build.py (contents, props changed) tracker/roundup-src/roundup/dist/command/build_doc.py (contents, props changed) tracker/roundup-src/roundup/dist/command/build_py.py (contents, props changed) tracker/roundup-src/roundup/dist/command/build_scripts.py (contents, props changed) tracker/roundup-src/roundup/xmlrpc.py (contents, props changed) tracker/roundup-src/share/ tracker/roundup-src/share/man/ tracker/roundup-src/share/man/man1/ tracker/roundup-src/share/man/man1/roundup-admin.1 (contents, props changed) tracker/roundup-src/share/man/man1/roundup-demo.1 (contents, props changed) tracker/roundup-src/share/man/man1/roundup-mailgw.1 (contents, props changed) tracker/roundup-src/share/man/man1/roundup-server.1 (contents, props changed) tracker/roundup-src/share/roundup/ tracker/roundup-src/share/roundup/templates/ tracker/roundup-src/share/roundup/templates/classic/ tracker/roundup-src/share/roundup/templates/classic/TEMPLATE-INFO.txt (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/detectors/ tracker/roundup-src/share/roundup/templates/classic/detectors/messagesummary.py (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/detectors/nosyreaction.py (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/detectors/statusauditor.py (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/detectors/userauditor.py (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/extensions/ tracker/roundup-src/share/roundup/templates/classic/extensions/README.txt (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/ tracker/roundup-src/share/roundup/templates/classic/html/_generic.404.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/_generic.calendar.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/_generic.collision.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/_generic.help-empty.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/_generic.help-list.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/_generic.help-search.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/_generic.help-submit.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/_generic.help.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/_generic.index.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/_generic.item.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/file.index.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/file.item.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/help.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/help_controls.js (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/home.classlist.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/home.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/issue.index.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/issue.item.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/issue.search.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/keyword.item.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/msg.index.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/msg.item.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/page.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/query.edit.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/query.item.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/style.css (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/user.forgotten.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/user.help-search.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/user.help.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/user.index.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/user.item.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/user.register.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/user.rego_progress.html (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/html/user_utils.js (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/initial_data.py (contents, props changed) tracker/roundup-src/share/roundup/templates/classic/schema.py (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/ tracker/roundup-src/share/roundup/templates/minimal/TEMPLATE-INFO.txt (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/detectors/ tracker/roundup-src/share/roundup/templates/minimal/detectors/userauditor.py (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/extensions/ tracker/roundup-src/share/roundup/templates/minimal/extensions/README.txt (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/ tracker/roundup-src/share/roundup/templates/minimal/html/_generic.404.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/_generic.calendar.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/_generic.collision.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/_generic.help.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/_generic.index.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/_generic.item.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/help_controls.js (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/home.classlist.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/home.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/page.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/style.css (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/user.index.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/user.item.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/user.register.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/html/user.rego_progress.html (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/initial_data.py (contents, props changed) tracker/roundup-src/share/roundup/templates/minimal/schema.py (contents, props changed) tracker/roundup-src/test/test_anypy_hashlib.py (contents, props changed) tracker/roundup-src/test/test_userauditor.py (contents, props changed) tracker/roundup-src/test/test_xmlrpc.py (contents, props changed) Removed: tracker/roundup-src/ChangeLog tracker/roundup-src/doc/roundup-admin.1 tracker/roundup-src/doc/roundup-demo.1 tracker/roundup-src/doc/roundup-mailgw.1 tracker/roundup-src/doc/roundup-server.1 tracker/roundup-src/roundup/backends/back_metakit.py tracker/roundup-src/templates/ tracker/roundup-src/test/test_metakit.py Modified: tracker/roundup-src/CHANGES.txt tracker/roundup-src/COPYING.txt tracker/roundup-src/MANIFEST.in tracker/roundup-src/README.txt tracker/roundup-src/demo.py tracker/roundup-src/detectors/creator_resolution.py tracker/roundup-src/doc/FAQ.txt tracker/roundup-src/doc/admin_guide.txt tracker/roundup-src/doc/announcement.txt tracker/roundup-src/doc/customizing.txt tracker/roundup-src/doc/default.css tracker/roundup-src/doc/design.txt tracker/roundup-src/doc/developers.txt tracker/roundup-src/doc/index.txt tracker/roundup-src/doc/installation.txt tracker/roundup-src/doc/upgrading.txt tracker/roundup-src/doc/user_guide.txt tracker/roundup-src/frontends/ZRoundup/ZRoundup.py tracker/roundup-src/frontends/ZRoundup/__init__.py tracker/roundup-src/frontends/roundup.cgi tracker/roundup-src/locale/de.po tracker/roundup-src/locale/en.po tracker/roundup-src/locale/fr.po tracker/roundup-src/locale/lt.po tracker/roundup-src/locale/roundup.pot tracker/roundup-src/locale/ru.po tracker/roundup-src/locale/zh_CN.po tracker/roundup-src/locale/zh_TW.po tracker/roundup-src/roundup/__init__.py tracker/roundup-src/roundup/admin.py tracker/roundup-src/roundup/backends/__init__.py tracker/roundup-src/roundup/backends/back_anydbm.py tracker/roundup-src/roundup/backends/back_mysql.py tracker/roundup-src/roundup/backends/back_postgresql.py tracker/roundup-src/roundup/backends/back_sqlite.py tracker/roundup-src/roundup/backends/back_tsearch2.py tracker/roundup-src/roundup/backends/blobfiles.py tracker/roundup-src/roundup/backends/indexer_common.py tracker/roundup-src/roundup/backends/indexer_dbm.py tracker/roundup-src/roundup/backends/indexer_rdbms.py tracker/roundup-src/roundup/backends/indexer_xapian.py tracker/roundup-src/roundup/backends/locking.py tracker/roundup-src/roundup/backends/portalocker.py tracker/roundup-src/roundup/backends/rdbms_common.py tracker/roundup-src/roundup/backends/sessions_dbm.py tracker/roundup-src/roundup/backends/sessions_rdbms.py tracker/roundup-src/roundup/backends/tsearch2_setup.py tracker/roundup-src/roundup/cgi/PageTemplates/GlobalTranslationService.py tracker/roundup-src/roundup/cgi/PageTemplates/__init__.py tracker/roundup-src/roundup/cgi/TAL/TranslationContext.py tracker/roundup-src/roundup/cgi/TranslationService.py tracker/roundup-src/roundup/cgi/ZTUtils/Batch.py tracker/roundup-src/roundup/cgi/ZTUtils/Iterator.py tracker/roundup-src/roundup/cgi/ZTUtils/__init__.py tracker/roundup-src/roundup/cgi/actions.py tracker/roundup-src/roundup/cgi/apache.py tracker/roundup-src/roundup/cgi/cgitb.py tracker/roundup-src/roundup/cgi/client.py tracker/roundup-src/roundup/cgi/exceptions.py tracker/roundup-src/roundup/cgi/form_parser.py tracker/roundup-src/roundup/cgi/templating.py tracker/roundup-src/roundup/cgi/wsgi_handler.py tracker/roundup-src/roundup/configuration.py tracker/roundup-src/roundup/date.py tracker/roundup-src/roundup/exceptions.py tracker/roundup-src/roundup/hyperdb.py tracker/roundup-src/roundup/i18n.py tracker/roundup-src/roundup/init.py tracker/roundup-src/roundup/install_util.py tracker/roundup-src/roundup/instance.py tracker/roundup-src/roundup/mailer.py tracker/roundup-src/roundup/mailgw.py tracker/roundup-src/roundup/password.py tracker/roundup-src/roundup/roundupdb.py tracker/roundup-src/roundup/scripts/__init__.py tracker/roundup-src/roundup/scripts/roundup_admin.py tracker/roundup-src/roundup/scripts/roundup_demo.py tracker/roundup-src/roundup/scripts/roundup_gettext.py tracker/roundup-src/roundup/scripts/roundup_mailgw.py tracker/roundup-src/roundup/scripts/roundup_server.py tracker/roundup-src/roundup/security.py tracker/roundup-src/roundup/token.py tracker/roundup-src/roundup/version_check.py tracker/roundup-src/run_tests.py tracker/roundup-src/scripts/add-issue tracker/roundup-src/scripts/copy-user.py tracker/roundup-src/scripts/import_sf.py tracker/roundup-src/scripts/roundup-reminder tracker/roundup-src/scripts/roundup.rc-debian tracker/roundup-src/scripts/weekly-report tracker/roundup-src/setup.py tracker/roundup-src/test/README.txt tracker/roundup-src/test/db_test_base.py tracker/roundup-src/test/test_anydbm.py tracker/roundup-src/test/test_cgi.py tracker/roundup-src/test/test_dates.py tracker/roundup-src/test/test_hyperdbvals.py tracker/roundup-src/test/test_indexer.py tracker/roundup-src/test/test_locking.py tracker/roundup-src/test/test_mailgw.py tracker/roundup-src/test/test_mailsplit.py tracker/roundup-src/test/test_multipart.py tracker/roundup-src/test/test_mysql.py tracker/roundup-src/test/test_postgresql.py tracker/roundup-src/test/test_schema.py tracker/roundup-src/test/test_security.py tracker/roundup-src/test/test_sqlite.py tracker/roundup-src/test/test_templating.py tracker/roundup-src/test/test_token.py tracker/roundup-src/test/test_tsearch2.py tracker/roundup-src/tools/load_tracker.py tracker/roundup-src/tools/pygettext.py Modified: tracker/roundup-src/CHANGES.txt ============================================================================== --- tracker/roundup-src/CHANGES.txt (original) +++ tracker/roundup-src/CHANGES.txt Sun Mar 15 22:43:30 2009 @@ -1,7 +1,78 @@ This file contains the changes to the Roundup system over time. The entries are given with the most recent entry first. -2008-02-07 1.4.2 +2009-03-13 1.4.7 (r4202) + +Features: +- Provide a "no selection" option in web interface selection widgets +- Debug logging now uses the logging module rather than print +- Allow CGI frontend to serve XMLRPC requests. +- Added XMLRPC actions, as well as bridging CGI actions to XMLRPC actions. +- Optimized large file serving via mod_python / sendfile(). +- Support resuming downloads for (large) files. + +Fixes: +- a number of security issues were discovered by Daniel Diniz +- EditCSV and ExportCSV altered to include permission checks +- HTTP POST required on actions which alter data +- HTML file uploads served as application/octet-stream +- Handle Unauthorised in file serving correctly +- New item action reject creation of new users +- Item retirement was not being controlled +- Roundup is now compatible with Python 2.6 +- Improved French and German translations +- Improve consistency of item sorting in HTML interface +- Various other small bug fixes, robustification and optimisation + + +2008-09-01 1.4.6 +Fixed: +- Fix bug introduced in 1.4.5 in RDBMS full-text indexing +- Make URL matching code less matchy +- Try to clarify mail_domain config setting + + +2008-08-19 1.4.5 +Feature: +- Add use of username/password stored in ~/.netrc in mailgw (sf patch + #1912105) + +Fixed: +- 'Make a Copy' failed with more than one person in nosy list (sf #1906147) +- xml-rpc security checks and tests across all backends (sf #1907211) +- Send a Precedence header in email so (well-written) autoresponders don't +- Fix mailgw total failure bounce message generation (thanks Bradley Dean) +- Fix for postgres 8.3 compatibility (and bug) (sf patch #2030479 and bug + #1959261) +- Fix for translations (sf patch #2032526) +- Fire reactors after file storage is all done (sf patch #2001243) +- Allow negative ids other than -1 for item generation (sf patch #1982481) +- Better German translation for retiring users (sf #1998701) +- More improvements to German translation (sf #1919446) +- Add filter() to XML-RPC interface (sf patch #1966456) +- Fix IndexError when there are no messages to an issue (sf patch #1894249) +- Prevent broken pipe errors in csv export (sf patch #1911449) +- New session API and cleanup thanks anatoly t. +- Make WSGI handler threadsafe (sf #1968027) +- Improved URL matching RE (sf #2038858) +- Allow binary file content submission via XML-RPC (sf #1995623) +- Don't run old code on newer database (sf #1979556) +- Fix HTML injection into page title +- Fix indexer handling of indexed Link properties (sf #1936876) + + +2008-03-01 1.4.4 +Fixed: +- Security fixes (thanks Roland Meister) + + +2008-02-27 1.4.3 +Fixed: +- MySQL backend bug introduced in 1.4.2 (TEXT columns need a size when + being indexed) + + +2008-02-08 1.4.2 Feature: - New config option in mail section: ignore_alternatives allows to ignore alternatives besides the text/plain part used for the content Modified: tracker/roundup-src/COPYING.txt ============================================================================== --- tracker/roundup-src/COPYING.txt (original) +++ tracker/roundup-src/COPYING.txt Sun Mar 15 22:43:30 2009 @@ -1,7 +1,7 @@ Roundup Licensing ----------------- -Copyright (c) 2003 Richard Jones (richard at mechanicalcat.net) +Copyright (c) 2003-2009 Richard Jones (richard at mechanicalcat.net) Copyright (c) 2002 eKit.com Inc (http://www.ekit.com/) Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/) Deleted: tracker/roundup-src/ChangeLog ============================================================================== --- tracker/roundup-src/ChangeLog Sun Mar 15 22:43:30 2009 +++ (empty file) @@ -1,926 +0,0 @@ -2006-11-22 Stefan Seefeld - - * roundup/cgi/form_parser.py: Allow required fields to be ommitted - if user doesn't have edit permission and the value is already set. - -2001-08-03 11:54 richard - - * BUILD.txt, CHANGES.txt, README.txt, setup.py, - roundup/templates/classic/htmlbase.py: Started stuff off for the - 0.2.5 release - -2001-08-03 11:28 richard - - * roundup-admin, roundup-mailgw, roundup-server, - cgi-bin/roundup.cgi, roundup/init.py: Used the much nicer - load_package, pointed out by Steve Majewski. - -2001-08-03 11:19 richard - - * roundup/templates/classic/: htmlbase.py, html/issue.item, - html/style.css: finished of colourising the classic template - -2001-08-03 10:59 richard - - * CHANGES.txt: chnages - -2001-08-03 10:59 richard - - * roundup-admin, roundup-mailgw, roundup-server, - cgi-bin/roundup.cgi, roundup/init.py: Instance import now imports - the instance using imp.load_module so that we can have instance - homes of "roundup" or other existing python package names. - -2001-08-02 20:26 richard - - * README.txt: changes - -2001-08-02 16:38 richard - - * roundup/: cgi_client.py, hyperdb.py, roundupdb.py, - templates/classic/dbinit.py, templates/classic/instance_config.py, - templates/extended/dbinit.py, - templates/extended/instance_config.py: Roundupdb now appends - "mailing list" information to its messages which include the e-mail - address and web interface address. Templates may override this in - their db classes to include specific information (support - instructions, etc). - -2001-08-02 16:00 richard - - * CHANGES.txt: anges - -2001-08-02 15:55 richard - - * roundup/cgi_client.py: Web edit messages aren't sent to the - person who did the edit any more. No message is generated if they - are the only person on the nosy list. - -2001-08-02 11:01 richard - - * CHANGES.txt: changes - -2001-08-02 11:00 richard - - * BUILD.txt: Added the 'clean' command to the instructions - - distutils doesn't seem to always detect when it needs to rebuild - when it should. - -2001-08-02 10:43 richard - - * roundup/templates/extended/interfaces.py: Even better (more - useful) headings - -2001-08-02 10:36 richard - - * roundup/templates/extended/interfaces.py: Made all the - user-specific link names the same (My Foo) - -2001-08-02 10:34 richard - - * roundup/cgi_client.py: bleah syntax error - -2001-08-02 10:27 richard - - * CHANGES.txt, roundup/templates/extended/htmlbase.py: changes - -2001-08-02 10:27 richard - - * roundup/date.py: Extended the range of intervals that are - pretty-printed before actual dates are displayed. - -2001-08-02 10:26 richard - - * roundup/cgi_client.py: Changed the order of the information in - the message generated by web edits. - -2001-08-01 15:15 richard - - * CHANGES.txt: changes - -2001-08-01 15:15 richard - - * README.txt, roundup/templates/extended/htmlbase.py, - roundup/templates/extended/interfaces.py, - roundup/templates/extended/html/issue.index, - roundup/templates/extended/html/support.index: Added "My Issues" - and "My Support" to extended template. - -2001-08-01 15:06 richard - - * CHANGES.txt: changes - -2001-08-01 15:06 richard - - * roundup/: templatebuilder.py, templates/classic/htmlbase.py, - templates/extended/htmlbase.py: htmlbase doesn't have extraneous - $Foo$ in it any more - -2001-08-01 14:24 richard - - * roundup/: hyperdb.py, mailgw.py: mailgw was assuming certain - properties existed on the issues being created. - -2001-08-01 13:52 richard - - * CHANGES.txt, roundup/htmltemplate.py: Checklist was using wrong - name. - -2001-08-01 13:48 richard - - * README.txt: Just a new idea... - -2001-07-31 19:58 richard - - * CHANGES.txt: changes - -2001-07-31 19:54 richard - - * roundup/date.py: Fixed the 2.1-specific gmtime() (no arg) call in - roundup.date. (Paul Wright) - -2001-07-30 18:12 richard - - * CHANGES.txt, roundup-admin, roundup/cgi_client.py, - roundup/htmltemplate.py, roundup/templatebuilder.py, - roundup/templates/classic/htmlbase.py, - roundup/templates/classic/html/file.newitem, - roundup/templates/classic/html/issue.item, - roundup/templates/extended/htmlbase.py, - roundup/templates/extended/interfaces.py: Added time logging and - file uploading to the templates. - -2001-07-30 18:04 richard - - * roundup/templates/extended/html/: file.newitem, timelog.index, - timelog.item: oops - -2001-07-30 18:03 richard - - * roundup/templates/extended/html/: issue.item, support.item: Fixes - to the uploading stuff (I forgot to put the code in the issue class - ;) - -2001-07-30 17:17 richard - - * setup.py: Just making sure we've got the right version in there - for development. - -2001-07-30 16:26 richard - - * roundup/cgi_client.py: Added some documentation on how the - newblah works. - -2001-07-30 16:17 richard - - * roundup/: cgi_client.py, htmltemplate.py: Features: . Added - ability for cgi newblah forms to indicate that the new node - should be linked somewhere. Fixed: . Fixed the agument handling - for the roundup-admin find command. . Fixed handling of summary - when no note supplied for newblah. Again. . Fixed detection of no - form in htmltemplate Field display. - -2001-07-30 13:53 richard - - * CHANGES.txt: chanegs - -2001-07-30 13:52 richard - - * roundup-admin: init help now lists templates and backends - -2001-07-30 13:52 richard - - * roundup/backends/__init__.py: Checks for ability to import the - specific back-end module. - -2001-07-30 13:45 richard - - * test/test_db.py: Added more DB to test_db. Can skip tests where - imports fail. - -2001-07-30 12:38 richard - - * roundup/templates/: classic/htmlbase.py, extended/htmlbase.py: - updated htmlbases - -2001-07-30 12:38 richard - - * roundup/: hyperdb.py, roundupdb.py: get() now has a default arg - - for migration only. - -2001-07-30 12:37 richard - - * roundup/htmltemplate.py: Temporary measure until we have decent - schema migration. - -2001-07-30 12:37 richard - - * roundup/cgi_client.py: Temporary measure until we have decent - schema migration... - -2001-07-30 12:37 richard - - * roundup-admin: Freshen is really broken. Commented out. - -2001-07-30 12:36 richard - - * roundup/backends/: back_bsddb.py, back_bsddb3.py: Handle - non-existence of db files in the other backends (code from anydbm). - -2001-07-30 12:35 richard - - * roundup/templates/extended/html/issue.item: Should've been - supportcall - -2001-07-30 11:47 richard - - * roundup/templates/extended/html/issue.item: Forgot to add the - support call property to the item page. - -2001-07-30 11:41 richard - - * roundup/backends/: back_anydbm.py, back_bsddb.py, back_bsddb3.py: - Makes schema changes mucho easier. - -2001-07-30 11:32 richard - - * CHANGES.txt, README.txt: noted changes - -2001-07-30 11:28 richard - - * roundup-admin: Bugfixes - -2001-07-30 11:28 richard - - * roundup/templates/__init__.py: Support for determining the - installed tempaltes - -2001-07-30 11:27 richard - - * roundup/templates/extended/html/: support.filter, support.index, - support.item: Oops - these are the HTML displays for the support - class. - -2001-07-30 11:26 richard - - * roundup/templates/extended/: dbinit.py, htmlbase.py, - interfaces.py, html/issue.filter, html/issue.index, - html/issue.item: Big changes: . split off the support priority - into its own class . added "new support, new user" to the page - head . fixed the display options for the heading links - -2001-07-30 11:25 richard - - * roundup/templates/classic/: htmlbase.py, interfaces.py: Changes - to reflect cgi_client now implementing this template by default, - and not "extended". - -2001-07-30 11:25 richard - - * roundup/cgi_client.py: Default implementation is now "classic" - rather than "extended" as one would expect. - -2001-07-30 11:24 richard - - * roundup/htmltemplate.py: Handles new node display now. - -2001-07-30 10:57 richard - - * roundup-admin: Now uses getopt, much improved command-line - parsing. Much fuller help. Much better internal structure. It's - just BETTER. :) - -2001-07-30 10:06 richard - - * roundup/templatebuilder.py: Hrm - had IOError instead of OSError. - Not sure why there's two. Ho hum. - -2001-07-30 10:05 richard - - * roundup/roundupdb.py: Fixed IssueClass so that superseders links - to its classname rather than hard-coded to "issue". - -2001-07-30 10:04 richard - - * roundup-admin: Made the "init" prompting more friendly. - -2001-07-30 09:34 richard - - * CHANGES.txt, roundup/templates/classic/htmlbase.py, - roundup/templates/extended/htmlbase.py: changes - -2001-07-30 09:34 richard - - * setup.py: Added unit tests so they're run whenever we - package/install/whatever. - -2001-07-30 09:32 richard - - * test/test_dates.py: Fixed bug in unit test ;) - -2001-07-29 19:43 richard - - * setup.py: Make sure that the htmlbase is up-to-date when we build - a source dist. - -2001-07-29 19:33 richard - - * CHANGES.txt: changes - -2001-07-29 19:31 richard - - * roundup/htmltemplate.py: oops - -2001-07-29 19:28 richard - - * roundup/: htmltemplate.py, hyperdb.py: Fixed sorting by clicking - on column headings. - -2001-07-29 18:37 richard - - * CHANGES.txt, README.txt, setup.py: changes - -2001-07-29 18:27 richard - - * roundup/: cgi_client.py, htmltemplate.py, hyperdb.py: Fixed - handling of passed-in values in form elements (ie. during a - drill-down) - -2001-07-29 17:01 richard - - * README.txt, roundup-admin, roundup-mailgw, roundup-server, - setup.py, cgi-bin/roundup.cgi, roundup/__init__.py, - roundup/cgi_client.py, roundup/cgitb.py, roundup/date.py, - roundup/htmltemplate.py, roundup/hyperdb.py, roundup/init.py, - roundup/mailgw.py, roundup/roundupdb.py, - roundup/templatebuilder.py, roundup/templates/classic/__init__.py, - roundup/templates/classic/dbinit.py, - roundup/templates/classic/instance_config.py, - roundup/templates/classic/interfaces.py, - roundup/templates/extended/__init__.py, - roundup/templates/extended/dbinit.py, - roundup/templates/extended/instance_config.py, - roundup/templates/extended/interfaces.py, test/README.txt, - test/__init__.py, test/test_dates.py, test/test_db.py, - test/test_multipart.py, test/test_schema.py: Added vim command to - all source so that we don't get no steenkin' tabs :) - -2001-07-29 16:42 richard - - * test/test_dates.py: Added Interval tests. - -2001-07-29 15:41 richard - - * CHANGES.txt: changes - -2001-07-29 15:36 richard - - * roundup/: htmltemplate.py, hyperdb.py: Cleanup of the link label - generation. - -2001-07-29 14:11 richard - - * CHANGES.txt: Reverse the entries so most recent is first. - -2001-07-29 14:09 richard - - * test/test_db.py: Added the fabricated property "id" to all - hyperdb classes. - -2001-07-29 14:07 richard - - * roundup/templates/classic/: interfaces.py, html/file.index, - html/issue.filter, html/issue.index, html/issue.item, - html/msg.index, html/msg.item, html/style.css, html/user.index, - html/user.item: Fixed the classic template so it's more like the - "advertised" Roundup template. - -2001-07-29 14:06 richard - - * roundup/htmltemplate.py: Fixed problem in link display when Link - value is None. - -2001-07-29 14:05 richard - - * roundup/: hyperdb.py, roundupdb.py: Added the fabricated property - "id". - -2001-07-29 14:04 richard - - * roundup/cgi_client.py: Moved some code around allowing for - subclassing to change behaviour. - -2001-07-28 18:17 richard - - * roundup/htmltemplate.py: fixed use of stylesheet - -2001-07-28 18:16 richard - - * roundup/cgi_client.py: New issue form handles lack of note better - now. - -2001-07-28 18:02 richard - - * roundup/templatebuilder.py: commented out print - -2001-07-28 17:59 richard - - * roundup/: htmltemplate.py, init.py, templatebuilder.py: Replaced - errno integers with their module values. De-tabbed - templatebuilder.py - -2001-07-28 17:35 richard - - * README.txt: todo refinement ;) - -2001-07-28 16:44 richard - - * CHANGES.txt, README.txt, doc/implementation.txt: Split off - implementation notes into separate file in doc directory. Added - some todo items to the README - -2001-07-28 16:43 richard - - * roundup/mailgw.py, test/__init__.py, test/test_multipart.py: - Multipart message class has the getPart method now. Added some - tests for it. - -2001-07-28 11:56 richard - - * CHANGES.txt, MANIFEST.in: changes - -2001-07-28 11:45 richard - - * doc/: overview.html, spec.html, images/edit.gif, images/edit.png, - images/hyperdb.gif, images/hyperdb.png, images/logo-acl-medium.gif, - images/logo-acl-medium.png, images/logo-codesourcery-medium.gif, - images/logo-codesourcery-medium.png, - images/logo-software-carpentry-standard.gif, - images/logo-software-carpentry-standard.png, images/roundup-1.gif, - images/roundup-1.png, images/roundup.gif, images/roundup.png: GIF - -> PNG, saving about 100k - -2001-07-28 11:40 richard - - * doc/: overview.html, images/edit.gif, images/hyperdb.gif, - images/roundup-1.gif, images/roundup.gif: added more documentation - -2001-07-28 11:39 richard - - * roundup/__init__.py: Added some documentation to the roundup - package. - -2001-07-28 10:39 richard - - * CHANGES.txt, setup.py: changes for the 0.2.1 distribution build. - -2001-07-28 10:34 richard - - * CHANGES.txt: changes - -2001-07-28 10:34 richard - - * roundup/: cgi_client.py, mailgw.py: Fixed some non-string node - ids. - -2001-07-28 10:31 richard - - * INSTALL.txt, roundup/templatebuilder.py: Fixed some problems with - installation. - -2001-07-27 17:33 richard - - * INSTALL.txt: more notes for installation - -2001-07-27 17:30 richard - - * BUILD.txt: minor notes - -2001-07-27 17:27 richard - - * BUILD.txt, README.txt: Added build instructions, changed my - e-mail address in the docs to the sourceforge address. - -2001-07-27 17:20 richard - - * Makefile, setup.cfg, setup.py: Makefile is now obsolete - setup - does what it used to do. - -2001-07-27 17:18 richard - - * MANIFEST.in: Added the distutils manifest template (for - "documentation", see distutils.filelist). Has no facility for - comments, so no ID or LOG for this baby. - -2001-07-27 17:16 richard - - * test/: README.TXT, README.txt: rename for consistency - -2001-07-27 17:04 richard - - * INSTALL.TXT, CHANGES.txt, INSTALL.txt, README.TXT, README.txt: - name changes to make distutils happy - -2001-07-27 16:56 richard - - * setup.cfg, setup.py: Added scripts to the setup and added the - config so the default script install dir is /usr/local/bin. - -2001-07-27 16:55 richard - - * test/: README.TXT, __init__.py, test_dates.py, test_db.py, - test_schema.py: moving tests -> test - -2001-07-27 16:25 richard - - * roundup/hyperdb.py: Fixed some of the exceptions so they're the - right type. Removed the str()-ification of node ids so we don't - mask oopsy errors any more. - -2001-07-27 15:17 richard - - * roundup/hyperdb.py: just some comments - -2001-07-26 17:14 richard - - * setup.py: Made setup.py executable, added id and log. - -2001-07-26 16:47 richard - - * INSTALL.TXT: Updated for new installation procedure - -2001-07-25 14:19 anthonybaxter - - * setup.py: first cut at setup.py - installs the package, but not - the bin/cgi-bin yet - -2001-07-25 14:09 richard - - * roundup/date.py: Fixed offset handling (shoulda read the spec a - little better) - -2001-07-25 13:40 richard - - * README.TXT: added note about the spec - -2001-07-25 13:39 richard - - * roundup/htmltemplate.py: Hrm - displaying links to classes that - don't specify a key property. I've got it defaulting to 'name', - then 'title' and then a "random" property (first one returned by - getprops().keys(). Needs to be moved onto the Class I think... - -2001-07-25 11:23 richard - - * doc/spec.html, doc/images/logo-acl-medium.gif, - doc/images/logo-codesourcery-medium.gif, - doc/images/logo-software-carpentry-standard.gif, - roundup/backends/back_anydbm.py, - roundup/templates/extended/dbinit.py: Added the Roundup spec to the - new documentation directory. - -2001-07-24 21:18 anthonybaxter - - * roundup/init.py: oops. left a print in - -2001-07-24 20:54 anthonybaxter - - * roundup/: init.py, templatebuilder.py: oops. Html. - -2001-07-24 20:46 anthonybaxter - - * roundup/: init.py, templatebuilder.py, templates/__init__.py, - templates/classic/__init__.py, templates/classic/dbinit.py, - templates/classic/htmlbase.py, templates/extended/__init__.py, - templates/extended/htmlbase.py: Added templatebuilder module. two - functions - one to pack up the html base, one to unpack it. Packed - up the two standard templates into htmlbases. Modified __init__ to - install them. - - __init__.py magic was needed for the rather high levels of wierd - import magic. Reducing level of import magic == (good, future) - -2001-07-24 14:26 anthonybaxter - - * roundup/backends/back_bsddb3.py: bsddb3 implementation. For now, - it's the bsddb implementation with a "3" added in crayon. - -2001-07-24 11:07 richard - - * roundup-server: Added command-line arg handling to roundup-server - so it's more useful out-of-the-box. - -2001-07-24 11:06 richard - - * roundup/templates/classic/dbinit.py: Oops - accidentally duped - the keywords class - -2001-07-24 09:32 richard - - * INSTALL.TXT: minor edit - -2001-07-24 09:28 richard - - * roundup/templates/: README.txt, classic/__init__.py, - classic/dbinit.py, classic/instance_config.py, - classic/interfaces.py, classic/detectors/__init__.py, - classic/detectors/nosyreaction.py, classic/html/file.index, - classic/html/issue.filter, classic/html/issue.index, - classic/html/issue.item, classic/html/msg.index, - classic/html/msg.item, classic/html/style.css, - classic/html/user.index, classic/html/user.item: Adding the classic - template - -2001-07-24 09:20 richard - - * roundup/templates/extended/dbinit.py: forgot to remove the - interfaces from the dbinit module ;) - -2001-07-24 09:16 richard - - * roundup/templates/extended/: __init__.py, interfaces.py: Split - off the interfaces (CGI, mailgw) into a separate file from the DB - stuff. - -2001-07-23 20:31 richard - - * roundup-server: disabled the reloading until it can be done - properly - -2001-07-23 18:55 richard - - * CHANGES, INSTALL.TXT, README, README.TXT: renamed the text files - so that they're recognised as text files on windows added - INSTALL.TXT - -2001-07-23 18:53 richard - - * README, roundup-server: Fixed the ROUNDUPS decl in roundup-server - Move the installation notes to INSTALL - -2001-07-23 18:45 richard - - * roundup-admin, roundup/init.py, - roundup/templates/extended/dbinit.py: ok, so now "./roundup-admin - init" will ask questions in an attempt to get a workable - instance_home set up :) _and_ anydbm has had its first test :) - -2001-07-23 18:25 richard - - * roundup/backends/back_bsddb.py: more handling of bad journals - -2001-07-23 18:20 richard - - * roundup-admin, roundup/backends/back_anydbm.py, - roundup/backends/back_bsddb.py: Moved over to using marshal in the - bsddb and anydbm backends. roundup-admin now has a "freshen" - command that'll load/save all nodes (not retired - mod - hyperdb.Class.list() so it lists retired nodes) - -2001-07-23 17:56 richard - - * roundup/: date.py, backends/back_bsddb.py: Storing only - marshallable data in the db - no nasty pickled class references. - -2001-07-23 17:22 richard - - * roundup/backends/: __init__.py, _anydbm.py, _bsddb.py, - back_anydbm.py, back_bsddb.py: *sigh* some databases have _foo.so - as their underlying implementation. This time for sure, Rocky. - -2001-07-23 17:15 richard - - * roundup/backends/: _anydbm.py, _bsddb.py, bsddb.py: Moved the - backends into the backends package. Anydbm hasn't been tested at - all. - -2001-07-23 17:14 richard - - * roundup/: roundupdb.py, backends/__init__.py, - templates/extended/dbinit.py: Moved the database backends off into - backends. - -2001-07-23 16:25 richard - - * roundup/templates/extended/dbinit.py: relfected the move to - roundup/backends - -2001-07-23 16:24 richard - - * roundup/backends/__init__.py: made backends a package - -2001-07-23 16:23 richard - - * roundup/: hyper_bsddb.py, backends/bsddb.py: moved hyper_bsddb.py - to the new backends package as bsddb.py - -2001-07-23 14:49 anthonybaxter - - * README: changed the 'snip' lines so they don't look like CVS - conflict markers. - -2001-07-23 14:47 anthonybaxter - - * cgi-bin/roundup.cgi: renamed ROUNDUPS to ROUNDUP_INSTANCE_HOMES - sys.exit(0) if python version wrong. - -2001-07-23 14:33 richard - - * cgi-bin/roundup.cgi: brought the CGI instance config dict in line - with roundup-server - -2001-07-23 14:33 anthonybaxter - - * roundup/templates/extended/: __init__.py, dbinit.py, - instance_config.py: split __init__.py into 2. dbinit and - instance_config. - -2001-07-23 14:31 richard - - * CHANGES, cgi-bin/roundup.cgi: Fixed the roundup CGI script for - updates to cgi_client.py - -2001-07-23 14:21 richard - - * roundup/templates/extended/: html/file.index, html/issue.filter, - html/issue.index, html/issue.item, html/msg.index, html/msg.item, - html/style.css, html/user.index, html/user.item, issue.filter, - issue.item, msg.item, style.css, user.item: moving HTML templates - to their own dir - -2001-07-23 14:19 richard - - * roundup/templates/extended/: file.index, issue.index, msg.index, - user.index: moving the HTML templates into their own dir - -2001-07-23 14:05 anthonybaxter - - * roundup-server: actually quit if python version wrong - -2001-07-23 13:56 richard - - * roundup/cgi_client.py: oops, missed a config removal - -2001-07-23 13:50 anthonybaxter - - * roundup/templates/extended/: __init__.py, file.index, - issue.filter, issue.index, issue.item, msg.index, msg.item, - style.css, user.index, user.item, detectors/__init__.py, - detectors/nosyreaction.py: moved templates to proper location - -2001-07-23 13:46 richard - - * roundup-admin, roundup-mailgw, roundup-server: moving the bin - files to facilitate out-of-the-boxness - -2001-07-22 22:09 richard - - * roundup/: __init__.py, cgi_client.py, cgitb.py, date.py, - htmltemplate.py, hyper_bsddb.py, hyperdb.py, init.py, mailgw.py, - roundupdb.py: Final commit of Grande Splite - -2001-07-22 21:58 richard - - * roundup/: __init__.py, cgi_client.py, cgitb.py, date.py, - htmltemplate.py, hyper_bsddb.py, hyperdb.py, init.py, mailgw.py, - roundupdb.py: More Grande Splite - -2001-07-22 21:47 richard - - * cgi-bin/roundup.cgi: More Grande Splite - -2001-07-22 21:11 richard - - * CHANGES, README, cgitb.py, config.py, date.py, hyperdb.py, - hyperdb_bsddb.py, roundup-mailgw.py, roundup.cgi, roundup.py, - roundup_cgi.py, roundupdb.py, server.py, style.css, template.py, - test.py: Initial commit of the Grande Splite - -2001-07-20 22:33 richard - - * server.py: oops ;) - -2001-07-20 18:20 richard - - * CHANGES: update for recent chagnes - -2001-07-20 18:20 richard - - * README, hyperdb.py: Fixed a bug in the filter - wrong variable - names in the error message. Recognised that the filter has an - outstanding bug. Hrm. we need a bug tracker for this project :) - -2001-07-20 17:35 richard - - * CHANGES, hyperdb.py, hyperdb_bsddb.py, roundup_cgi.py, - roundupdb.py, test.py: largish changes as a start of splitting off - bits and pieces to allow more flexible installation / database - back-ends - -2001-07-20 17:34 richard - - * template.py: Quote the value put in the text input value - attribute. - -2001-07-20 11:37 richard - - * README: Just registering a new TODO - -2001-07-20 10:53 richard - - * roundup_cgi.py: Default index now filters out the resolved issues - ;) - -2001-07-20 10:23 richard - - * CHANGES: update for latest changes - -2001-07-20 10:22 richard - - * roundupdb.py: Priority list changes - removed the redundant TODO - and added support. See roundup-devel for details. - -2001-07-20 10:17 richard - - * roundup_cgi.py: Fixed adding a new issue when there is no __note - -2001-07-19 20:43 anthonybaxter - - * config.py, server.py: HTTP_HOST and HTTP_PORT config options. - -2001-07-19 16:37 anthonybaxter - - * README: added more todo items - -2001-07-19 16:27 anthonybaxter - - * cgitb.py, config.py, date.py, hyperdb.py, roundup-mailgw.py, - roundup.py, roundup_cgi.py, roundupdb.py, server.py, template.py: - fixing (manually) the (dollarsign)Log(dollarsign) entries caused by - my using the magic (dollarsign)Id(dollarsign) and - (dollarsign)Log(dollarsign) strings in a commit message. I'm a - twonk. - - Also broke the help string in two. - -2001-07-19 16:14 richard - - * Makefile, README, dummy_config.py: minor changes to test the cvs - mailout system - -2001-07-19 16:08 anthonybaxter - - * roundup.py: fixed typo in usage string because it was bugging me - each time I saw it. - -2001-07-19 15:52 anthonybaxter - - * cgitb.py, config.py, date.py, hyperdb.py, roundup-mailgw.py, - roundup.py, roundup_cgi.py, roundupdb.py, server.py, template.py: - Added CVS keywords $Id: ChangeLog,v 1.8 2006/11/23 00:44:48 stefan Exp $ and $Log: ChangeLog,v $ - Added CVS keywords $Id: ChangeLog,v 1.7 2001/08/03 02:12:07 anthonybaxter Exp $ and Revision 1.8 2006/11/23 00:44:48 stefan - Added CVS keywords $Id: ChangeLog,v 1.7 2001/08/03 02:12:07 anthonybaxter Exp $ and Fix sf bug 1599740 - Added CVS keywords $Id: ChangeLog,v 1.7 2001/08/03 02:12:07 anthonybaxter Exp $ and - Added CVS keywords $Id: ChangeLog,v 1.8 2006/11/23 00:44:48 stefan Exp $ and Revision 1.7 2001/08/03 02:12:07 anthonybaxter - Added CVS keywords $Id: ChangeLog,v 1.8 2006/11/23 00:44:48 stefan Exp $ and regenerated on Fri Aug 3 12:12:00 EST 2001 - Added CVS keywords $Id: ChangeLog,v 1.8 2006/11/23 00:44:48 stefan Exp $ and to all python files. - -2001-07-19 15:46 anthonybaxter - - * config.py: modified to use localconfig.py (if it exists) and to - make the various options (e.g. paths) based on ROUNDUP_HOME &c. - -2001-07-19 15:23 richard - - * CHANGES, Makefile, config.py, hyperdb.py, roundup_cgi.py, - roundupdb.py, template.py: . Fixed bug in re generation in the - filter (I hadn't finished the code ;) - . Added TODO as a priority (between bug and usability) - . Fixed handling of None String property in grouped list headings - -2001-07-19 13:12 richard - - * README: mention config.py in the install instructions, removed a - bug - -2001-07-19 13:11 richard - - * Makefile, dummy_config.py: Added stuff to help with release - generation. . Makefile has the release tgz builder in it . - dummy_config.py is an empty config file that replaces the config.py - in the release - -2001-07-19 12:16 richard - - * README, date.py, hyperdb.py, roundup.cgi, roundup_cgi.py, - roundupdb.py, CHANGES, cgitb.py, config.py, roundup-mailgw.py, - roundup.py, server.py, style.css, template.py: Initial revision - -2001-07-19 12:16 richard - - * README, date.py, hyperdb.py, roundup.cgi, roundup_cgi.py, - roundupdb.py, CHANGES, cgitb.py, config.py, roundup-mailgw.py, - roundup.py, server.py, style.css, template.py: Initial import of - code - currently version 1.0.2 but with the 1.0.3 changes as given - in the CHANGES file. Is about ready for a 1.0.3 release. - Modified: tracker/roundup-src/MANIFEST.in ============================================================================== --- tracker/roundup-src/MANIFEST.in (original) +++ tracker/roundup-src/MANIFEST.in Sun Mar 15 22:43:30 2009 @@ -1,3 +1,4 @@ +recursive-include share * recursive-include roundup *.* recursive-include frontends *.* recursive-include scripts *.* *-* @@ -6,7 +7,7 @@ recursive-include doc *.html *.png *.txt *.css *.1 *.example recursive-include detectors *.py recursive-include templates *.* home* page* -global-exclude .cvsignore *.pyc *.pyo .DS_Store +global-exclude .svn .cvsignore *.pyc *.pyo .DS_Store include run_tests.py *.txt demo.py MANIFEST.in MANIFEST exclude BUILD.txt I18N_PROGRESS.txt TODO.txt exclude doc/security.txt doc/templating.txt Modified: tracker/roundup-src/README.txt ============================================================================== --- tracker/roundup-src/README.txt (original) +++ tracker/roundup-src/README.txt Sun Mar 15 22:43:30 2009 @@ -2,7 +2,7 @@ Roundup: an Issue-Tracking System for Knowledge Workers ======================================================= -Copyright (c) 2003 Richard Jones (richard at mechanicalcat.net) +Copyright (c) 2003-2009 Richard Jones (richard at mechanicalcat.net) Copyright (c) 2002 eKit.com Inc (http://www.ekit.com/) Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/) @@ -31,7 +31,7 @@ Upgrading ========= For upgrading instructions, please see upgrading.txt in the "doc" directory. - + Usage and Other Information =========================== Modified: tracker/roundup-src/demo.py ============================================================================== --- tracker/roundup-src/demo.py (original) +++ tracker/roundup-src/demo.py Sun Mar 15 22:43:30 2009 @@ -2,7 +2,7 @@ # # Copyright (c) 2003 Richard Jones (richard at mechanicalcat.net) # -# $Id: demo.py,v 1.26 2007/08/28 22:37:45 jpend Exp $ +# $Id: demo.py,v 1.26 2007-08-28 22:37:45 jpend Exp $ import errno import os @@ -127,7 +127,7 @@ backend = sys.argv[-2] else: backend = 'anydbm' - install_demo(home, backend, os.path.join('templates', 'classic')) + install_demo(home, backend, os.path.join('share', 'roundup', 'templates', 'classic')) run_demo(home) if __name__ == '__main__': Modified: tracker/roundup-src/detectors/creator_resolution.py ============================================================================== --- tracker/roundup-src/detectors/creator_resolution.py (original) +++ tracker/roundup-src/detectors/creator_resolution.py Sun Mar 15 22:43:30 2009 @@ -1,7 +1,7 @@ # This detector was written by richard at mechanicalcat.net and it's been # placed in the Public Domain. Copy and modify to your heart's content. -#$Id: creator_resolution.py,v 1.2 2004/04/07 06:32:54 richard Exp $ +#$Id: creator_resolution.py,v 1.2 2004-04-07 06:32:54 richard Exp $ from roundup.exceptions import Reject Modified: tracker/roundup-src/doc/FAQ.txt ============================================================================== --- tracker/roundup-src/doc/FAQ.txt (original) +++ tracker/roundup-src/doc/FAQ.txt Sun Mar 15 22:43:30 2009 @@ -2,8 +2,6 @@ Roundup FAQ =========== -:Version: $Revision: 1.23 $ - .. contents:: @@ -204,10 +202,5 @@ sorting, all items of that Class *must* have a value against the "order" property, or sorting will result in random ordering. ------------------ - -Back to `Table of Contents`_ - -.. _`Table of Contents`: index.html .. _`customisation`: customizing.html Added: tracker/roundup-src/doc/_static/style.css ============================================================================== --- (empty file) +++ tracker/roundup-src/doc/_static/style.css Sun Mar 15 22:43:30 2009 @@ -0,0 +1,109 @@ +/* layout*/ +body +{ + font-family: sans-serif, Arial, Helvetica; + background-color: white; + color: #333; + margin:0; + padding: 0 3em 0 14em; +} +body > .header { margin: 0 0 0 -14em;} +body > .footer { margin: 0 0 0 -14em; clear:both;} +body > .navigation +{ + margin-left: -14em; + width: 14em; + float: left; +} +body > .content +{ + width: 100%; + margin: 0; +} +body > .header > #searchbox { position: absolute; right: 1em; top: 1em;} + +/* style */ + +:link { color: #bb0000; text-decoration: none;} +:visited { color: #770000; text-decoration: none;} +a.toc-backref { color: #000000; } + +.header h1 { margin-left: 1em; } + +body +{ + font-family: sans-serif, Arial, Helvetica; + background-color: #f5f5f5; + color: #333; +} + +.menu +{ + margin-right: 1em; + padding: 2pt; + border: solid thin #dadada; + background-color:#ffffff; +} +.menu ul { list-style-type:none; padding: 0;} +.menu ul ul { padding-left: 1em;} +.menu li { border-top: solid thin #dadada;} +.menu li:first-child { border-top: none;} + +/* related */ + +div.related +{ + width: 100%; + font-size: 90%; +} +div.related-top { border-bottom: solid thin #dadada;} +div.related-bottom { border-top: solid thin #dadada;} + +div.related ul +{ + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { display: inline;} + +div.related li.right +{ + float: right; + margin-right: 5px; +} + +.footer +{ + font-size: small; + text-align: center; + color: lightgrey; +} + +.content +{ + padding: 1em; + border: solid thin #dadada; + background-color: #ffffff; +} + +/* This is a little hack to inject a 'news' block into the title + page without having to set up a custom directive. */ +#roundup-issue-tracker .note +{ + float: right; + width: auto; + border: solid thin #dadada; + background-color:#f5f5f5; + padding: 1em; + margin: 1em; +} +#roundup-issue-tracker .note .admonition-title { display: none; } + +table +{ + border-collapse: collapse; + border-spacing: 1px; + background-color: #fafafa; +} Added: tracker/roundup-src/doc/_templates/layout.html ============================================================================== --- (empty file) +++ tracker/roundup-src/doc/_templates/layout.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,166 @@ + + +{%- macro relbar(class) %} + +{%- endmacro %} +{%- macro sidebar() %} + {%- block sidebartoc %} + {%- if display_toc %} +

{{ _('Table Of Contents') }}

+ {{ toc }} + {%- endif %} + {%- endblock %} + {%- block sidebarrel %} + {%- if prev %} +

{{ _('Previous topic') }}

+

{{ prev.title }}

+ {%- endif %} + {%- if next %} +

{{ _('Next topic') }}

+

{{ next.title }}

+ {%- endif %} + {%- endblock %} + {%- block sidebarsourcelink %} + {%- if show_source and has_source and sourcename %} +

{{ _('This Page') }}

+ + {%- endif %} + {%- endblock %} + {%- block sidebarsearch %} + {%- if pagename != "search" %} + + + {%- endif %} + {%- endblock %} +{%- endmacro %} + + + + + {{ metatags }} + {%- if builder != 'htmlhelp' %} + {%- set titlesuffix = " — " + docstitle|e %} + {%- endif %} + {{ title|striptags }}{{ titlesuffix }} + {%- if builder == 'web' %} + + {%- for link, type, title in page_links %} + + {%- endfor %} + {%- else %} + + + {%- endif %} + {%- if builder != 'htmlhelp' %} + + {%- for scriptfile in script_files %} + + {%- endfor %} + {%- if use_opensearch %} + + {%- endif %} + {%- if favicon %} + + {%- endif %} + {%- endif %} +{%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + + + {%- if hasdoc('copyright') %} + + {%- endif %} + + {%- if parents %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} +{%- endblock %} +{%- block extrahead %} {% endblock %} + + +

Roundup

+ {%- if pagename != "search" %} + + + {%- endif %} +
+ +
+ {{ relbar('related-top') }} + {{ body }} + {{ relbar('related-bottom') }} +
+{%- block footer %} + +{%- endblock %} + + Added: tracker/roundup-src/doc/acknowledgements.txt ============================================================================== --- (empty file) +++ tracker/roundup-src/doc/acknowledgements.txt Sun Mar 15 22:43:30 2009 @@ -0,0 +1,132 @@ +Acknowledgements +================ + +Go Ping, you rock! Also, go Common Ground, ekit.com and Bizar Software for +letting me implement this system on their time. + +Thanks also to the many people on the mailing list, in the sourceforge +project and those who just report bugs: +Thomas Arendsen Hein, +Nerijus Baliunas, +Anthony Baxter, +Marlon van den Berg, +Bo Berglund, +St??phane Bidoul, +Cameron Blackwood, +Jeff Blaine, +Duncan Booth, +Seb Brezel, +J Alan Brogan, +Titus Brown, +Steve Byan, +Brett Cannon, +Godefroid Chapelle, +Roch'e Compaan, +Wil Cooley, +Joe Cooper, +Kelley Dagley, +Bruno Damour, +Bradley Dean, +Toby Dickenson, +Paul F. Dubois, +Eric Earnst, +Peter Eisentraut, +Andrew Eland, +Jeff Epler, +Tom Epperly, +Tamer Fahmy, +Vickenty Fesunov, +Hernan Martinez Foffani, +Stuart D. Gathman, +Martin Geisler, +Ajit George, +Frank Gibbons, +Johannes Gijsbers, +Gus Gollings, +Philipp Gortan, +Dan Grassi, +Robin Green, +Jason Grout, +Charles Groves, +Engelbert Gruber, +Bruce Guenter, +Tam??s Gul??csi, +Thomas Arendsen Hein, +Juergen Hermann, +Tobias Herp, +Uwe Hoffmann, +Alex Holkner, +Tobias Hunger, +Simon Hyde, +Paul Jimenez, +Christophe Kalt, +Timo Kankare, +Brian Kelley, +James Kew, +Sheila King, +Michael Klatt, +Bastian Kleineidam, +Axel Kollmorgen, +Cedric Krier, +Detlef Lannert, +Andrey Lebedev, +Henrik Levkowetz, +David Linke, +Martin v. L??wis, +Fredrik Lundh, +Will Maier, +Ksenia Marasanova, +Georges Martin, +Gordon McMillan, +John F Meinel Jr, +Roland Meister, +Ulrik Mikaelsson, +John Mitchell, +Ramiro Morales, +Toni Mueller, +Stefan Niederhauser, +Truls E. N??ss, +Patrick Ohly, +Luke Opperman, +Eddie Parker, +Will Partain, +Ewout Prangsma, +Marcus Priesch, +Bernhard Reiter, +Roy Rapoport, +John P. Rouillard, +Luke Ross, +Ollie Rutherfurd, +Toby Sargeant, +Giuseppe Scelsi, +Ralf Schlatterbeck, +Gregor Schmid, +Florian Schulze, +Klamer Schutte, +Dougal Scott, +Stefan Seefeld, +Jouni K Sepp??nen, +Jeffrey P Shell, +Dan Shidlovsky, +Joel Shprentz, +Terrel Shumway, +Emil Sit, +Alexander Smishlajev, +Nathaniel Smith, +Leonardo Soto, +Maciej Starzyk, +Mitchell Surface, +Anatoly T., +Jon C. Thomason +Mike Thompson, +Michael Twomey, +Karl Ulbrich, +Martin Uzak, +Darryl VanDorp, +J Vickroy, +Timothy J. Warren, +William (Wilk), +Tue Wennerberg, +Matt Wilbert, +Chris Withers, +Milan Zamazal. Modified: tracker/roundup-src/doc/admin_guide.txt ============================================================================== --- tracker/roundup-src/doc/admin_guide.txt (original) +++ tracker/roundup-src/doc/admin_guide.txt Sun Mar 15 22:43:30 2009 @@ -2,8 +2,6 @@ Administration Guide ==================== -:Version: $Revision: 1.27 $ - .. contents:: What does Roundup install? @@ -207,7 +205,11 @@ 2. If you're using an RDBMS backend, make a backup of its contents now. 3. Make a backup of the tracker home itself. 4. Stop the tracker web and email frontends. -5. Follow the steps in the `upgrading documentation`_ for the new version of +5. Install the new version of the software:: + + python setup.py install + +6. Follow the steps in the `upgrading documentation`_ for the new version of the software in the copied. Usually you will be asked to run `roundup_admin migrate` on your tracker @@ -215,25 +217,7 @@ It's safe to run this even if it's not required, so just get into the habit. -6. You may test each of the admin tool, web interface and mail gateway using - the new version of the software. To do this, invoke the scripts directly - in the source directory with:: - - PYTHONPATH=. python roundup/scripts/roundup_server.py - PYTHONPATH=. python roundup/scripts/roundup_admin.py - PYTHONPATH=. python roundup/scripts/roundup_mailgw.py - - Note that on Windows, this would read:: - - C:\sources\roundup-0.7.4> SET PYTHONPATH=. - C:\sources\roundup-0.7.4> python roundup/scripts/roundup_server.py - -7. Once you're comfortable that the upgrade will work using that copy, you - should install the new version of the software:: - - python setup.py install - -8. Restart your tracker web and email frontends. +7. Restart your tracker web and email frontends. If something bad happens, you may reinstate your backup of the tracker and reinstall the older version of the sofware using the same install command:: @@ -384,10 +368,5 @@ of your normal login -------------------- - -Back to `Table of Contents`_ - -.. _`Table of Contents`: index.html .. _`customisation documentation`: customizing.html .. _`upgrading documentation`: upgrading.html Modified: tracker/roundup-src/doc/announcement.txt ============================================================================== --- tracker/roundup-src/doc/announcement.txt (original) +++ tracker/roundup-src/doc/announcement.txt Sun Mar 15 22:43:30 2009 @@ -1,24 +1,28 @@ -I'm proud to release version 1.4.2 of Roundup. +I'm proud to release version 1.4.7 of Roundup. -New Features in 1.4.2: -- New config option in mail section: ignore_alternatives allows to - ignore alternatives besides the text/plain part used for the content - of a message in multipart/alternative attachments. -- Admin copy of error email from mailgw includes traceback (thanks Ulrik - Mikaelsson) -- Messages created through the web are now given an in-reply-to header - when email out to nosy (thanks Martin v. L??wis) -- Nosy messages now include more information about issues (all link - properties with a "name" attribute) (thanks Martin v. L??wis) - -And things fixed: -- Searching date range by supplying just a date as the filter spec -- Handle no time.tzset under Windows (sf #1825643) -- Fix race condition in file storage transaction commit (sf #1883580) -- Make user utils JS work with firstname/lastname again (sf #1868323) -- Fix ZRoundup to work with Zope 2.8.5 (sf #1806125) -- Fix race condition for key properties in rdbms backends (sf #1876683) -- Handle Reject in mailgw final set/create (sf #1826425) +1.4.7 is primarily a bugfix release which contains important security +fixes: + +- a number of security issues were discovered by Daniel Diniz +- EditCSV and ExportCSV altered to include permission checks +- HTTP POST required on actions which alter data +- HTML file uploads served as application/octet-stream +- Handle Unauthorised in file serving correctly +- New item action reject creation of new users +- Item retirement was not being controlled +- Roundup is now compatible with Python 2.6 +- Improved French and German translations +- Improve consistency of item sorting in HTML interface +- Various other small bug fixes, robustification and optimisation + +Though some new features made it in also: + +- Provide a "no selection" option in web interface selection widgets +- Debug logging now uses the logging module rather than print +- Allow CGI frontend to serve XMLRPC requests. +- Added XMLRPC actions, as well as bridging CGI actions to XMLRPC actions. +- Optimized large file serving via mod_python / sendfile(). +- Support resuming downloads for (large) files. If you're upgrading from an older version of Roundup you *must* follow the "Software Upgrade" guidelines given in the maintenance documentation. Added: tracker/roundup-src/doc/contact.txt ============================================================================== --- (empty file) +++ tracker/roundup-src/doc/contact.txt Sun Mar 15 22:43:30 2009 @@ -0,0 +1,22 @@ +Contact +======= + +For general support enquiries about usage, a mailing list is available: + + roundup-users at sourceforge.net + +If you've got a great idea for roundup, or have found a bug, please +submit an issue to the tracker at: + + http://sourceforge.net/tracker/?group_id=31577 + +For discussions about developing or enhancing roundup: + + roundup-devel at sourceforge.net + +The admin for this project is Richard Jones: + + richard at users.sourceforge.net + +but he should only be contacted directly when none of the +above avenues of contact are suitable. Modified: tracker/roundup-src/doc/customizing.txt ============================================================================== --- tracker/roundup-src/doc/customizing.txt (original) +++ tracker/roundup-src/doc/customizing.txt Sun Mar 15 22:43:30 2009 @@ -1,9 +1,9 @@ +:tocdepth: 2 + =================== Customising Roundup =================== -:Version: $Revision: 1.222 $ - .. This document borrows from the ZopeBook section on ZPT. The original is at: http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx @@ -181,6 +181,12 @@ LC_MESSAGES, or LANG, in that order of preference. Section **web** + allow_html_file -- ``no`` + Setting this option enables Roundup to serve uploaded HTML + file content *as HTML*. This is a potential security risk + and is therefore disabled by default. Set to 'yes' if you + trust *all* users uploading content to your tracker. + http_auth -- ``yes`` Whether to use HTTP Basic Authentication, if present. Roundup will use either the REMOTE_USER or HTTP_AUTHORIZATION @@ -1875,10 +1881,15 @@ - the current index information (``filterspec``, ``filter`` args, ``properties``, etc) parsed out of the form. - methods for easy filterspec link generation - - *user*, the current user item as an HTMLItem instance - - *form* + - "form" The current CGI form information as a mapping of form argument name - to value + to value (specifically a cgi.FieldStorage) + - "env" the CGI environment variables + - "base" the base URL for this instance + - "user" a HTMLItem instance for the current user + - "language" as determined by the browser or config + - "classname" the current classname (possibly None) + - "template" the current template (suffix, also possibly None) **config** This variable holds all the values defined in the tracker config.ini file (eg. TRACKER_NAME, etc.) @@ -4850,11 +4861,4 @@ rather than requiring a web server restart. -------------------- - -Back to `Table of Contents`_ - -.. _`Table of Contents`: index.html .. _`design documentation`: design.html -.. _`admin guide`: admin_guide.html - Modified: tracker/roundup-src/doc/default.css ============================================================================== --- tracker/roundup-src/doc/default.css (original) +++ tracker/roundup-src/doc/default.css Sun Mar 15 22:43:30 2009 @@ -1,7 +1,7 @@ /* :Author: David Goodger :Contact: goodger at users.sourceforge.net -:date: $Date: 2004/06/09 00:25:32 $ +:date: $Date: 2004-06-09 00:25:32 $ :version: $Revision: 1.13 $ :copyright: This stylesheet has been placed in the public domain. Modified: tracker/roundup-src/doc/design.txt ============================================================================== --- tracker/roundup-src/doc/design.txt (original) +++ tracker/roundup-src/doc/design.txt Sun Mar 15 22:43:30 2009 @@ -475,6 +475,8 @@ match the 'filter' spec, sorted by the group spec and then the sort spec. + "search_matches" is a container type + "filterspec" is {propname: value(s)} "sort" and "group" are [(dir, prop), ...] where dir is '+', '-' @@ -482,8 +484,6 @@ backward-compatibility reasons a single (dir, prop) tuple is also allowed. - "search_matches" is {nodeid: marker} - The filter must match all properties specificed. If the property value to match is a list: @@ -599,7 +599,7 @@ 4 >>> db.issue.create(title="abuse", status=1) 5 - >>> hyperdb.Class(db, "user", username=hyperdb.Key(), + >>> hyperdb.Class(db, "user", username=hyperdb.String(), ... password=hyperdb.String()) >>> db.issue.addprop(fixer=hyperdb.Link("user")) @@ -1652,10 +1652,5 @@ - Access Controls - Added "actor" property ------------------- - -Back to `Table of Contents`_ - -.. _`Table of Contents`: index.html .. _customisation: customizing.html Modified: tracker/roundup-src/doc/developers.txt ============================================================================== --- tracker/roundup-src/doc/developers.txt (original) +++ tracker/roundup-src/doc/developers.txt Sun Mar 15 22:43:30 2009 @@ -2,8 +2,6 @@ Developing Roundup ================== -:Version: $Revision: 1.16 $ - .. note:: The intended audience of this document is the developers of the core Roundup code. If you just wish to alter some behaviour of your Roundup @@ -429,11 +427,6 @@ At run time, Roundup automatically compiles message catalogs whenever `PO`_ file is changed. ------------------ - -Back to `Table of Contents`_ - -.. _`Table of Contents`: index.html .. _`Customising Roundup`: customizing.html .. _`Roundup's Design Document`: spec.html .. _`implementation notes`: implementation.html Modified: tracker/roundup-src/doc/index.txt ============================================================================== --- tracker/roundup-src/doc/index.txt (original) +++ tracker/roundup-src/doc/index.txt Sun Mar 15 22:43:30 2009 @@ -5,185 +5,20 @@ Contents ======== -- Features__ -- Installation__ and Upgrading__ existing installs -- `Frequently Asked Questions`__ -- `User Guide`__ -- `Configuring and Customising Roundup`__ -- `Administering Roundup Trackers`__ -- `Roundup's Design`__ (original__) -- `Developing Roundup`__ -- `Roundup Tracker Templates`__ -- Contact_ -- Acknowledgements_ -- License_ - -__ features.html -__ installation.html -__ upgrading.html -__ FAQ.html -__ user_guide.html -__ customizing.html -__ admin_guide.html -__ design.html -__ spec.html -__ developers.html -__ tracker_templates.html - -Contact -======= - -For general support enquiries about usage, a mailing list is available: - - roundup-users at sourceforge.net - -If you've got a great idea for roundup, or have found a bug, please -submit an issue to the tracker at: - - http://sourceforge.net/tracker/?group_id=31577 - -For discussions about developing or enhancing roundup: - - roundup-devel at sourceforge.net - -The admin for this project is Richard Jones: - - richard at users.sourceforge.net - -but he should only be contacted directly when none of the -above avenues of contact are suitable. - - -Acknowledgements -================ - -Go Ping, you rock! Also, go Common Ground, ekit.com and Bizar Software for -letting me implement this system on their time. - -Thanks also to the many people on the mailing list, in the sourceforge -project and those who just report bugs: -Thomas Arendsen Hein, -Nerijus Baliunas, -Anthony Baxter, -Marlon van den Berg, -Bo Berglund, -St?phane Bidoul, -Cameron Blackwood, -Jeff Blaine, -Duncan Booth, -Seb Brezel, -J Alan Brogan, -Titus Brown, -Steve Byan, -Brett Cannon, -Godefroid Chapelle, -Roch'e Compaan, -Wil Cooley, -Joe Cooper, -Kelley Dagley, -Bruno Damour, -Toby Dickenson, -Paul F. Dubois, -Eric Earnst, -Andrew Eland, -Jeff Epler, -Tom Epperly, -Tamer Fahmy, -Vickenty Fesunov, -Hernan Martinez Foffani, -Stuart D. Gathman, -Ajit George, -Frank Gibbons, -Johannes Gijsbers, -Gus Gollings, -Philipp Gortan, -Dan Grassi, -Robin Green, -Jason Grout, -Charles Groves, -Engelbert Gruber, -Bruce Guenter, -Tam?s Gul?csi, -Thomas Arendsen Hein, -Juergen Hermann, -Tobias Herp, -Uwe Hoffmann, -Alex Holkner, -Tobias Hunger, -Simon Hyde, -Paul Jimenez, -Christophe Kalt, -Timo Kankare, -Brian Kelley, -James Kew, -Sheila King, -Michael Klatt, -Bastian Kleineidam, -Axel Kollmorgen, -Detlef Lannert, -Andrey Lebedev, -Henrik Levkowetz, -David Linke, -Martin v. L?wis, -Fredrik Lundh, -Will Maier, -Georges Martin, -Gordon McMillan, -John F Meinel Jr, -Ulrik Mikaelsson, -John Mitchell, -Ramiro Morales, -Toni Mueller, -Stefan Niederhauser, -Truls E. N?ss, -Patrick Ohly, -Luke Opperman, -Eddie Parker, -Will Partain, -Ewout Prangsma, -Marcus Priesch, -Bernhard Reiter, -Roy Rapoport, -John P. Rouillard, -Luke Ross, -Ollie Rutherfurd, -Toby Sargeant, -Giuseppe Scelsi, -Ralf Schlatterbeck, -Gregor Schmid, -Florian Schulze, -Klamer Schutte, -Dougal Scott, -Stefan Seefeld, -Jouni K Sepp?nen, -Jeffrey P Shell, -Dan Shidlovsky, -Joel Shprentz, -Terrel Shumway, -Emil Sit, -Alexander Smishlajev, -Nathaniel Smith, -Leonardo Soto, -Maciej Starzyk, -Mitchell Surface, -Jon C. Thomason -Mike Thompson, -Michael Twomey, -Karl Ulbrich, -Martin Uzak, -Darryl VanDorp, -J Vickroy, -Timothy J. Warren, -William (Wilk), -Tue Wennerberg, -Matt Wilbert, -Chris Withers, -Milan Zamazal. - - - -License -======= - -See COPYING.txt in the software distribution for the licensing terms. +.. toctree:: + :maxdepth: 2 + features + installation + upgrading + FAQ + user_guide + customizing + admin_guide + spec + original design + developers + tracker_templates + contact + acknowledgements + license Modified: tracker/roundup-src/doc/installation.txt ============================================================================== --- tracker/roundup-src/doc/installation.txt (original) +++ tracker/roundup-src/doc/installation.txt Sun Mar 15 22:43:30 2009 @@ -2,8 +2,6 @@ Installing Roundup ================== -:Version: $Revision: 1.130 $ - .. contents:: :depth: 2 @@ -1010,12 +1008,6 @@ Roundup -- from installation and scripts. -------------------------------------------------------------------------------- - -Back to `Table of Contents`_ - -Next: `User Guide`_ - .. _`table of contents`: index.html .. _`user guide`: user_guide.html .. _`roundup specification`: spec.html Added: tracker/roundup-src/doc/license.txt ============================================================================== --- (empty file) +++ tracker/roundup-src/doc/license.txt Sun Mar 15 22:43:30 2009 @@ -0,0 +1,5 @@ +License +======= + +See COPYING.txt in the software distribution for the licensing terms. + Deleted: tracker/roundup-src/doc/roundup-admin.1 ============================================================================== --- tracker/roundup-src/doc/roundup-admin.1 Sun Mar 15 22:43:30 2009 +++ (empty file) @@ -1,26 +0,0 @@ -.TH ROUNDUP-ADMIN 1 "24 January 2003" -.SH NAME -roundup-admin \- administrate roundup trackers -.SH SYNOPSIS -\fBroundup-admin\fP [\fIoptions\fP] \fI\fP \fI\fP -.SH OPTIONS -.TP -\fB-i\fP \fIinstance home\fP -specify the issue tracker "home directory" to administer -.TP -\fB-u\fP -the user[:password] to use for commands -.TP -\fB-c\fP -when outputting lists of data, just comma-separate them -.SH FURTHER HELP - roundup-admin -h - roundup-admin help -- this help - roundup-admin help -- command-specific help - roundup-admin help all -- all available help -.SH AUTHOR -This manpage was written by Bastian Kleineidam - for the Debian distribution of roundup. - -The main author of roundup is Richard Jones -. Deleted: tracker/roundup-src/doc/roundup-demo.1 ============================================================================== --- tracker/roundup-src/doc/roundup-demo.1 Sun Mar 15 22:43:30 2009 +++ (empty file) @@ -1,30 +0,0 @@ -.TH ROUNDUP-SERVER 1 "27 July 2004" -.SH NAME -roundup-demo \- create a roundup "demo" tracker and launch its web interface -.SH SYNOPSIS -\fBroundup-demo\fP [\fIbackend\fP [\fBnuke\fP]] -.SH OPTIONS -.TP -\fBnuke\fP -Create a fresh demo tracker (deleting the existing one if any). If the -additional \fIbackend\fP argument is specified, the new demo tracker will -use the backend named (one of "anydbm", "sqlite", "metakit", "mysql" or -"postgresql"; subject to availability on your system). -.TH DESCRIPTION -This command creates a fresh demo tracker for you to experiment with. The -email features of Roundup will be turned off (so the nosy feature won't -send email). It does this by removing the \fInosyreaction.py\fP module -from the demo tracker's \fIdetectors\fP directory. - -If you wish, you may modify the demo tracker by editing its configuration -files and HTML templates. See the \fIcustomisation\fP manual for -information about how to do that. - -Once you've fiddled with the demo tracker, you may use it as a template for -creating your real, live tracker. Simply run the \fIroundup-admin\fP -command to install the tracker from inside the demo tracker home directory, -and it will be listed as an available template for installation. No data -will be copied over. -.SH AUTHOR -This manpage was written by Richard Jones -. Deleted: tracker/roundup-src/doc/roundup-mailgw.1 ============================================================================== --- tracker/roundup-src/doc/roundup-mailgw.1 Sun Mar 15 22:43:30 2009 +++ (empty file) @@ -1,59 +0,0 @@ -.TH ROUNDUP-MAILGW 1 "24 January 2003" -.SH NAME -roundup-mailgw \- mail gateway for roundup -.SH SYNOPSIS -\fBroundup-mailgw\fP \fI\fP [\fImethod\fP] -.SH OPTIONS -.TP -\fB-C\fP \fIhyperdb class\fP -specify a tracker class - one of msg (the default), issue, file, user - to -manipulate with -S options -.TP -\fB-S\fP \fIproperty=value[;property=value] pairs\fP -specify the values to set on the class specified by -C using the same -format as the Subject line property manipulations -.SH DESCRIPTION -The roundup mail gateway may be called in one of three ways: -.IP \(bu -with an instance home as the only argument, -.IP \(bu -with both an instance home and a mail spool file, or -.IP \(bu -with both an instance home and a pop server account. -.PP -\fBPIPE\fP -.br -In the first case, the mail gateway reads a single message from the -standard input and submits the message to the roundup.mailgw module. - -\fBUNIX mailbox\fP -.br -In the second case, the gateway reads all messages from the mail spool -file and submits each in turn to the roundup.mailgw module. The file is -emptied once all messages have been successfully handled. The file is -specified as: - \fImailbox /path/to/mailbox\fP - -\fBPOP\fP -.br -In the third case, the gateway reads all messages from the POP server -specified and submits each in turn to the roundup.mailgw module. The -server is specified as: - \fIpop username:password at server\fP -.br -The username and password may be omitted: - \fIpop username at server\fP - \fIpop server\fP -.br -are both valid. The username and/or password will be prompted for if -not supplied on the command-line. - -\fBAPOP\fP -Same as POP, but using Authenticated POP: - \fIapop username:password at server\fP -.SH AUTHOR -This manpage was written by Bastian Kleineidam - for the Debian distribution of roundup. - -The main author of roundup is Richard Jones -. Deleted: tracker/roundup-src/doc/roundup-server.1 ============================================================================== --- tracker/roundup-src/doc/roundup-server.1 Sun Mar 15 22:43:30 2009 +++ (empty file) @@ -1,61 +0,0 @@ -.TH ROUNDUP-SERVER 1 "27 July 2004" -.SH NAME -roundup-server \- start roundup web server -.SH SYNOPSIS -\fBroundup-server\fP [\fIoptions\fP] [\fBname=\fP\fItracker home\fP]* -.SH OPTIONS -.TP -\fB-C\fP \fIfile\fP -Use options read from the configuration file (see below). -.TP -\fB-n\fP \fIhostname\fP -Sets the host name. -.TP -\fB-p\fP \fIport\fP -Sets the port to listen on. -.TP -\fB-d\fP \fIfile\fP -Daemonize, and write the server's PID to the nominated file. -.TP -\fB-l\fP \fIfile\fP -Sets a filename to log to (instead of stdout). This is required if the -d -option is used. -.TP -\fB-i\fP \fIfile\fP -Sets a filename to use as a template for generating the tracker index page. -The variable "trackers" is available to the template and is a dict of all -configured trackers. -.TP -\fB-s\fP -Enables to use of SSL. -.TP -\fB-e\fP \fIfile\fP -Sets a filename containing the PEM file to use for SSL. If left blank, a -temporary self-signed certificate will be used. -.TP -\fB-h\fP -print help -.TP -\fBname=\fP\fItracker home\fP -Sets the tracker home(s) to use. The \fBname\fP variable is how the tracker is -identified in the URL (it's the first part of the URL path). The \fItracker -home\fP variable is the directory that was identified when you did -"roundup-admin init". You may specify any number of these name=home pairs on -the command-line. For convenience, you may edit the TRACKER_HOMES variable in -the roundup-server file instead. Make sure the name part doesn't include any -url-unsafe characters like spaces, as these confuse the cookie handling in -browsers like IE. -.SH EXAMPLES -.TP -.B roundup-server -p 9000 bugs=/var/tracker reqs=/home/roundup/group1 -Start the server on port \fB9000\fP serving two trackers; one under -\fB/bugs\fP and one under \fB/reqs\fP. - -.SH CONFIGURATION FILE -See the "admin_guide" in the Roundup "doc" directory. -.SH AUTHOR -This manpage was written by Bastian Kleineidam - for the Debian distribution of roundup. - -The main author of roundup is Richard Jones -. Modified: tracker/roundup-src/doc/upgrading.txt ============================================================================== --- tracker/roundup-src/doc/upgrading.txt (original) +++ tracker/roundup-src/doc/upgrading.txt Sun Mar 15 22:43:30 2009 @@ -13,6 +13,99 @@ .. contents:: + +Migrating from 1.4.x to 1.4.7 +============================= + +Several security issues were addressed in this release. Some aspects of your +trackers may no longer function depending on your local customisations. Core +functionality that will need to be modified: + +Grant the "retire" permission to users for their queries +-------------------------------------------------------- + +Users will no longer be able to retire their own queries. To remedy this you +will need to add the following to your tracker's ``schema.py`` just under the +line that grants them permission to edit their own queries:: + + p = db.security.addPermission(name='Edit', klass='query', check=edit_query, + description="User is allowed to edit their queries") + db.security.addPermissionToRole('User', p) + + p = db.security.addPermission(name='Retire', klass='query', check=edit_query, + + description="User is allowed to retire their queries") + + db.security.addPermissionToRole('User', p) + p = db.security.addPermission(name='Create', klass='query', + description="User is allowed to create queries") + db.security.addPermissionToRole('User', p) + +The lines marked "+" should be added, minus the "+" sign. + + +Fix the "retire" link in the users list for admin users +------------------------------------------------------- + +The "retire" link found in the file ``html/users.index.html``:: + +
Messages
msg (view) + retire + +Should be replaced with:: + + +
+ + + +
+ + +Fix for Python 2.6+ users +------------------------- + +If you use Python 2.6 you should edit your tracker's +``detectors/nosyreaction.py`` file to change:: + + import sets + +at the top to:: + + from roundup.anypy.sets_ import set + +and then all instances of ``sets.Set()`` to ``set()`` in the later code. + + + +Trackers currently allowing HTML file uploading +----------------------------------------------- + +Trackers which wish to continue to allow uploading of HTML content against issues +will need to set a new configuration variable in the ``[web]`` section of the +tracker's ``config.ini`` file: + + # Setting this option enables Roundup to serve uploaded HTML + # file content *as HTML*. This is a potential security risk + # and is therefore disabled by default. Set to 'yes' if you + # trust *all* users uploading content to your tracker. + # Allowed values: yes, no + # Default: no + allow_html_file = no + + + +Migrating from 1.4.2 to 1.4.3 +============================= + +If you are using the MySQL backend you will need to replace some indexes +that may have been created by version 1.4.2. + +You should to access your MySQL database directly and remove any indexes +with a name ending in "_key_retired_idx". You should then re-add them with +the same spec except the key column name needs a size. So an index on +"_user (__retired, _name)" should become "_user (__retired, _name(255))". + + Migrating from 1.4.x to 1.4.2 ============================= Modified: tracker/roundup-src/doc/user_guide.txt ============================================================================== --- tracker/roundup-src/doc/user_guide.txt (original) +++ tracker/roundup-src/doc/user_guide.txt Sun Mar 15 22:43:30 2009 @@ -2,8 +2,6 @@ User Guide ========== -:Version: $Revision: 1.37 $ - .. contents:: .. hint:: @@ -479,8 +477,13 @@ If the sender of an e-mail is unknown to Roundup (looking up both user primary e-mail addresses and their alternate addresses) then a new user -will be created. The new user will have their username set to the "user" -part of "user at domain" in their e-mail address. Their password will be +may be created, depending on tracker configuration (see the `Admin +Guide`_ section "Users and Security" for configuration details.) + +.. _`Admin Guide`: admin_guide.html + +The new user will have their username set to the "user" part of +"user at domain" in their e-mail address. Their password will be completely randomised, and they'll have to visit the web interface to have it changed. Some sites don't allow web access by users who register via e-mail like this. @@ -799,9 +802,3 @@ Remember the roundup commands that accept multiple designators accept them ',' separated so using '-dc' is almost always required. ------------------ - -Back to `Table of Contents`_ - -.. _`Table of Contents`: index.html -.. _`customisation documentation`: customizing.html Added: tracker/roundup-src/doc/xmlrpc.txt ============================================================================== --- (empty file) +++ tracker/roundup-src/doc/xmlrpc.txt Sun Mar 15 22:43:30 2009 @@ -0,0 +1,88 @@ +========================= +XML-RPC access to Roundup +========================= + +.. contents:: + +Introduction +------------ +Version 1.4 of Roundup includes an XML-RPC frontend. Some installations find +that roundup-admins requirement of local access to the tracker instance +limiting. The XML-RPC frontend provides the ability to execute a limited subset +of commands similar to those found in roundup-admin from remote machines. + +roundup-xmlrpc-server +--------------------- +The Roundup XML-RPC server must be started before remote clients can access the +tracker via XML-RPC. ``roundup-xmlrpc-server`` is installed in the scripts +directory alongside ``roundup-server`` and roundup-admin``. When invoked, the +location of the tracker instance must be specified. + + roundup-xmlrpc-server -i ``/path/to/tracker`` + +The default port is ``8000``. An alternative port can be specified with the +``--port`` switch. + +security consideration +====================== +Note that the current ``roundup-xmlrpc-server`` implementation does not +support SSL. This means that usernames and passwords will be passed in +cleartext unless the server is being proxied behind another server (such as +Apache or lighttpd) that provide SSL. + +client API +---------- +The server currently implements four methods. Each method requires that the +user provide a username and password in the HTTP authorization header in order +to authenticate the request against the tracker. + +======= ==================================================================== +Command Description +======= ==================================================================== +list arguments: *classname, [property_name]* + + List all elements of a given ``classname``. If ``property_name`` is + specified, that is the property that will be displayed for each + element. If ``property_name`` is not specified the default label + property will be used. + +display arguments: *designator, [property_1, ..., property_N]* + + Display a single item in the tracker as specified by ``designator`` + (e.g. issue20 or user5). The default is to display all properties + for the item. Alternatively, a list of properties to display can be + specified. + +create arguments: *classname, arg_1 ... arg_N* + + Create a new instance of ``classname`` with ``arg_1`` through + ``arg_N`` as the values of the new instance. The arguments are + name=value pairs (e.g. ``status='3'``). + +set arguments: *designator, arg_1 ... arg_N* + + Set the values of an existing item in the tracker as specified by + ``designator``. The new values are specified in ``arg_1`` through + ``arg_N``. The arguments are name=value pairs (e.g. ``status='3'``). +======= ==================================================================== + +sample python client +==================== +:: + + >>> import xmlrpclib + >>> roundup_server = xmlrpclib.ServerProxy('http://username:password at localhost:8000') + >>> roundup_server.list('user') + ['admin', 'anonymous', 'demo'] + >>> roundup_server.list('issue', 'id') + ['1'] + >>> roundup_server.display('issue1') + {'assignedto' : None, 'files' : [], 'title' = 'yes, ..... } + >>> roundup_server.display('issue1', 'priority', 'status') + {'priority' : '1', 'status' : '2'} + >>> roundup_server.set('issue1', 'status=3') + >>> roundup_server.display('issue1', 'status') + {'status' : '3' } + >>> roundup_server.create('issue', "title='another bug'", "status=2") + '2' + Modified: tracker/roundup-src/frontends/ZRoundup/ZRoundup.py ============================================================================== --- tracker/roundup-src/frontends/ZRoundup/ZRoundup.py (original) +++ tracker/roundup-src/frontends/ZRoundup/ZRoundup.py Sun Mar 15 22:43:30 2009 @@ -14,7 +14,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: ZRoundup.py,v 1.23 2008/02/07 01:03:39 richard Exp $ +# $Id: ZRoundup.py,v 1.23 2008-02-07 01:03:39 richard Exp $ # ''' ZRoundup module - exposes the roundup web interface to Zope Modified: tracker/roundup-src/frontends/ZRoundup/__init__.py ============================================================================== --- tracker/roundup-src/frontends/ZRoundup/__init__.py (original) +++ tracker/roundup-src/frontends/ZRoundup/__init__.py Sun Mar 15 22:43:30 2009 @@ -14,7 +14,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: __init__.py,v 1.5 2006/08/11 00:04:29 richard Exp $ +# $Id: __init__.py,v 1.5 2006-08-11 00:04:29 richard Exp $ # __version__='1.1' Modified: tracker/roundup-src/frontends/roundup.cgi ============================================================================== --- tracker/roundup-src/frontends/roundup.cgi (original) +++ tracker/roundup-src/frontends/roundup.cgi Sun Mar 15 22:43:30 2009 @@ -16,7 +16,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: roundup.cgi,v 1.2 2006/12/11 23:36:15 richard Exp $ +# $Id: roundup.cgi,v 1.2 2006-12-11 23:36:15 richard Exp $ # python version check from roundup import version_check Modified: tracker/roundup-src/locale/de.po ============================================================================== --- tracker/roundup-src/locale/de.po (original) +++ tracker/roundup-src/locale/de.po Sun Mar 15 22:43:30 2009 @@ -1,40 +1,54 @@ # German message file for Roundup Issue Tracker -# Tobias Herp , 2006 # Initial work by Stefan Niederhauser , 2004. # updated by Toni Mueller +# updated by Tobias Herp # -# $Id: de.po,v 1.5 2006/12/18 03:51:44 richard Exp $ -# -# roundup.pot revision 1.8 +# $Id: de.po,v 1.9 2008-08-19 01:51:10 richard Exp $ # msgid "" msgstr "" -"Project-Id-Version: Roundup 1.2.1\n" +"Project-Id-Version: Roundup 1.4.6\n" "Report-Msgid-Bugs-To: roundup-devel at lists.sourceforge.net\n" -"POT-Creation-Date: 2004-12-08 10:25+0200\n" -"PO-Revision-Date: 2006-10-07 22:45Westeurop?ische Normalzeit\n" -"Last-Translator: Toni Mueller \n" +"POT-Creation-Date: 2009-03-12 11:58+0200\n" +"PO-Revision-Date: 2009-03-12 18:05Westeurop?ische Normalzeit\n" +"Last-Translator: Tobias Herp \n" "Language-Team: German Translators \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Poedit-Bookmarks: 75,-1,-1,-1,-1,-1,-1,-1,-1,-1\n" + +#: ../roundup/actions.py:53 +#: ../roundup/cgi/actions.py:120 +msgid "You may not retire the admin or anonymous user" +msgstr "Sie k??nnen den Administrator oder den Gast-Benutzer nicht l??schen" + +#: ../roundup/actions.py:66 +#: ../roundup/cgi/actions.py:57 +#, python-format +msgid "You do not have permission to %(action)s the %(classname)s class." +msgstr "Sie sind nicht berechtigt, die Aktion(en) %(action)s auf die Klasse %(classname)s anzuwenden." -# ../roundup/admin.py:83 :949 :998 :1020 -#: ../roundup/admin.py:84 ../roundup/admin.py:954 ../roundup/admin.py:1003 -#: ../roundup/admin.py:1025 +#: ../roundup/admin.py:83 +#: ../roundup/admin.py:986 +#: ../roundup/admin.py:1037 +#: ../roundup/admin.py:1060 +#: ../roundup/admin.py:83:986 +#: :1037:1060 #, python-format msgid "no such class \"%(classname)s\"" msgstr "Die Klasse \"%(classname)s\" existiert nicht" # ../roundup/admin.py:93 :97 -#: ../roundup/admin.py:94 ../roundup/admin.py:98 +#: ../roundup/admin.py:93 +#: ../roundup/admin.py:97 +#: ../roundup/admin.py:93:97 #, python-format msgid "argument \"%(arg)s\" not propname=value" -msgstr "" -"Der Parameter \"%(arg)s\" entspricht nicht dem Format Eigenschaft=Wert" +msgstr "Der Parameter \"%(arg)s\" entspricht nicht dem Format Eigenschaft=Wert" -#: ../roundup/admin.py:111 +#: ../roundup/admin.py:110 #, python-format msgid "" "Problem: %(message)s\n" @@ -43,14 +57,13 @@ "Problem: %(message)s\n" "\n" -#: ../roundup/admin.py:113 +#: ../roundup/admin.py:111 #, python-format msgid "" "%(message)sUsage: roundup-admin [options] [ ]\n" "\n" "Options:\n" -" -i instance home -- specify the issue tracker \"home directory\" to " -"administer\n" +" -i instance home -- specify the issue tracker \"home directory\" to administer\n" " -u -- the user[:password] to use for commands\n" " -d -- print full designators not just class id numbers\n" " -c -- when outputting lists of data, comma-separate them.\n" @@ -72,38 +85,38 @@ "%(message)sVerwendung: roundup-admin [Optionen] [ ]\n" "\n" "Optionen:\n" -" -i -- Tracker-Instanz zur Administration ausw?hlen\n" -" -u -- Benutzer[:Pa?wort] f?r das Ausf?hren von Befehlen\n" +" -i -- Tracker-Instanz zur Administration ausw??hlen\n" +" -u -- Benutzer[:Passwort] f??r das Ausf??hren von Befehlen\n" " -d -- lange Bezeichner statt Klassen-Ids anzeigen\n" " -c -- Komma-getrennte Listenausgabe (CSV).\n" " Analog zu '-S \",\"'.\n" " -S -- Trennzeichen bei der Listenausgabe.\n" " -s -- Leerzeichen als Trennzeichen verwenden.\n" " Analog zu '-S \" \"'.\n" -" -V -- ausf?hrliche Ausgaben (\"verbose\") beim Import\n" +" -V -- ausf??hrliche Ausgaben (\"verbose\") beim Import\n" " -v -- Roundup- und Python-Version ausgeben (und beenden)\n" "\n" -" Nur eine der Optionen -s, -c or -S kann gew?hlt werden.\n" +" Nur eine der Optionen -s, -c or -S kann gew??hlt werden.\n" "\n" "Hilfe:\n" " roundup-admin -h\n" " roundup-admin help -- diese Kurzhilfe anzeigen\n" " roundup-admin help -- Hilfe zu einem Befehl anzeigen\n" -" roundup-admin help all -- s?mtliche Hilfen anzeigen\n" +" roundup-admin help all -- s??mtliche Hilfen anzeigen\n" -#: ../roundup/admin.py:137 +#: ../roundup/admin.py:138 msgid "Commands:" msgstr "Befehle:" -#: ../roundup/admin.py:144 +#: ../roundup/admin.py:145 msgid "" "Commands may be abbreviated as long as the abbreviation\n" "matches only one command, e.g. l == li == lis == list." msgstr "" -"Befehle k?nnen abgek?rzt werden, solange sie eindeutig bleiben, \n" +"Befehle k??nnen abgek??rzt werden, solange sie eindeutig bleiben, \n" "z.B. l == li == lis == list." -#: ../roundup/admin.py:174 +#: ../roundup/admin.py:175 msgid "" "\n" "All commands (except help) require a tracker specifier. This is just\n" @@ -138,8 +151,8 @@ " Roch\\'e Compaan (2 tokens: Roch'e Compaan)\n" " address=\"1 2 3\" (1 token: address=1 2 3)\n" " \\\\ (1 token: \\)\n" -" \\n\\r\\t (1 token: a newline, carriage-return and " -"tab)\n" +" \\n" +"\\r\\t (1 token: a newline, carriage-return and tab)\n" "\n" "When multiple nodes are specified to the roundup get or roundup set\n" "commands, the specified properties are retrieved or set on all the listed\n" @@ -169,30 +182,30 @@ "Command help:\n" msgstr "" "\n" -"Sie m?ssen f?r s?mtliche Befehle - au?er f?r die Hilfe - das Verzeichnis\n" +"Sie m??ssen f??r s??mtliche Befehle - au??er f??r die Hilfe - das Verzeichnis\n" "einer Tracker-Instanz angeben. Dort wird die Konfiguration gespeichert und\n" -" - je nach Datenbank - auch die Daten. Das Tracker-Verzeichnis kann ?ber\n" +" - je nach Datenbank - auch die Daten. Das Tracker-Verzeichnis kann ??ber\n" "die Umgebungsvariable TRACKER_HOME oder die Option \"-i Verzeichnis\"\n" "angegeben werden.\n" "\n" "Ein Bezeichner besteht aus einem Klassennamen und einer ID, zum Beispiel\n" "\"issue12\"\n" "\n" -"Eigenschaften werden als Zeichenketten ?bergeben und angezeigt.\n" +"Eigenschaften werden als Zeichenketten ??bergeben und angezeigt.\n" " . Eine Zeichenkette (\"String\") wird direkt ausgegeben.\n" -" . Datumswerte werden als vollst?ndiges Datum in der lokalen Zeitzone\n" -" ausgegeben und k?nnen im vollst?ndigen Format oder in einem Teilformat\n" +" . Datumswerte werden als vollst??ndiges Datum in der lokalen Zeitzone\n" +" ausgegeben und k??nnen im vollst??ndigen Format oder in einem Teilformat\n" " eingeben werden (siehe unten).\n" -" . Links zu anderen Eintr?gen werden mit dem Bezeichner dargestellt.\n" -" Bei der Eingabe wird entweder der Bezeichner oder nur der Schl?ssel\n" +" . Links zu anderen Eintr??gen werden mit dem Bezeichner dargestellt.\n" +" Bei der Eingabe wird entweder der Bezeichner oder nur der Schl??ssel\n" " angegeben.\n" " . Bei Mehrfach-Links werden die verlinkten Bezeichner mit Kommata getrennt\n" -" ausgegeben. Bei der Eingabe k?nnen Bezeichner oder Schl?ssel\n" +" ausgegeben. Bei der Eingabe k??nnen Bezeichner oder Schl??ssel\n" " mit Kommata getrennt eingegeben werden.\n" "\n" -"Falls Eigenschaften Leerzeichen enthalten, m?ssen die Werte in\n" -"\"Anf?hrungszeichen\" eingeschlossen werden. Leerzeichen k?nnen auch mit\n" -"einem \\Backslash gesch?tzt werden. Ebenso m?ssen Anf?hrungszeichen im Wert\n" +"Falls Eigenschaften Leerzeichen enthalten, m??ssen die Werte in\n" +"\"Anf??hrungszeichen\" eingeschlossen werden. Leerzeichen k??nnen auch mit\n" +"einem \\Backslash gesch??tzt werden. Ebenso m??ssen Anf??hrungszeichen im Wert\n" "mit einem Backslash versehen werden, einfache ' wie doppelte \".\n" "Beispiele:\n" " Hallo Welt (2 Werte: Hallo, Welt)\n" @@ -201,22 +214,23 @@ " Alfons\\' Welt (2 Werte: Alfons', Welt)\n" " Adresse=\"1 2 3\" (1 Wert: Address=1 2 3)\n" " \\\\ (1 Wert: \\)\n" -" \\n\\r\\t (1 Wert: Zeilenumbruch + CR + Tab)\n" +" \\n" +"\\r\\t (1 Wert: Zeilenumbruch + CR + Tab)\n" "\n" -"Wenn bei einer Abfrage oder einer ?nderung mehrere Eintr?ge angegeben\n" -"werden, so werden die gew?nschten Eigenschaften aller Eintr?ge angezeigt\n" -"bzw. ge?ndert.\n" +"Wenn bei einer Abfrage oder einer ??nderung mehrere Eintr??ge angegeben\n" +"werden, so werden die gew??nschten Eigenschaften aller Eintr??ge angezeigt\n" +"bzw. ge??ndert.\n" "\n" -"Wenn ein Befehl \"get\" oder \"find\" mehrere Eintr?ge zur?ckgibt, so \n" -"werden diese Zeile f?r Zeile oder (mit der Option -c) kommagetrennt\n" +"Wenn ein Befehl \"get\" oder \"find\" mehrere Eintr??ge zur??ckgibt, so \n" +"werden diese Zeile f??r Zeile oder (mit der Option -c) kommagetrennt\n" "ausgegeben.\n" "\n" -"Bei ?nderungen wird ein Benutzername und ein Pa?wort ben?tigt.\n" -"Diese Angaben k?nnen in der Umgebungsvariable ROUNDUP_LOGIN oder mit der\n" +"Bei ??nderungen wird ein Benutzername und ein Passwort ben??tigt.\n" +"Diese Angaben k??nnen in der Umgebungsvariable ROUNDUP_LOGIN oder mit der\n" "Option -u gemacht werden, entweder als \"Benutzername\" oder als\n" -"\"benutzername:pa?wort\".\n" +"\"benutzername:passwort\".\n" "\n" -"Beispiele f?r Datumsformate:\n" +"Beispiele f??r Datumsformate:\n" " \"2000-04-17.03:45\" ergibt \n" " \"2000-04-17\" ergibt \n" " \"01-25\" ergibt \n" @@ -228,12 +242,12 @@ "\n" "Befehlshilfe:\n" -#: ../roundup/admin.py:237 +#: ../roundup/admin.py:238 #, python-format msgid "%s:" msgstr "%s:" -#: ../roundup/admin.py:242 +#: ../roundup/admin.py:243 msgid "" "Usage: help topic\n" " Give help about topic.\n" @@ -245,41 +259,45 @@ " " msgstr "" "Verwendung: help Thema\n" -" Zeigt die Hilfe f?r ein Thema ein.\n" +" Zeigt die Hilfe f??r ein Thema ein.\n" "\n" " commands -- Befehle auflisten\n" " -- Hilfe zu einem bestimmten Befehl\n" " initopts -- Optionen zur Initialisierung\n" -" all -- s?mtlichen Hilfetext anzeigen\n" +" all -- s??mtlichen Hilfetext anzeigen\n" " " -#: ../roundup/admin.py:265 +#: ../roundup/admin.py:266 #, python-format msgid "Sorry, no help for \"%(topic)s\"" msgstr "Zum Thema \"%(topic)s\" existiert leider kein Hilfetext" # ../roundup/admin.py:336 :382 -#: ../roundup/admin.py:337 ../roundup/admin.py:386 +#: ../roundup/admin.py:343 +#: ../roundup/admin.py:399 +#: ../roundup/admin.py:343:399 msgid "Templates:" msgstr "Vorlagen:" # ../roundup/admin.py:339 :393 -#: ../roundup/admin.py:340 ../roundup/admin.py:397 +#: ../roundup/admin.py:346 +#: ../roundup/admin.py:410 +#: ../roundup/admin.py:346:410 msgid "Back ends:" msgstr "Datenbanken:" -#: ../roundup/admin.py:343 +#: ../roundup/admin.py:349 msgid "" -"Usage: install [template [backend [admin password [key=val[,key=val]]]]]\n" +"Usage: install [template [backend [key=val[,key=val]]]]\n" " Install a new Roundup tracker.\n" "\n" " The command will prompt for the tracker home directory\n" " (if not supplied through TRACKER_HOME or the -i option).\n" -" The template, backend and admin password may be specified\n" -" on the command-line as arguments, in that order.\n" +" The template and backend may be specified on the command-line\n" +" as arguments, in that order.\n" "\n" -" The last command line argument allows to pass initial values\n" -" for config options. For example, passing\n" +" Command line arguments following the backend allows you to\n" +" pass initial values for config options. For example, passing\n" " \"web_http_auth=no,rdbms_user=dinsdale\" will override defaults\n" " for options http_auth in section [web] and user in section [rdbms].\n" " Please be careful to not use spaces in this argument! (Enclose\n" @@ -293,26 +311,26 @@ " See also initopts help.\n" " " msgstr "" -"Verwendung: install [Vorlage [Datenbanktyp [Administratorpasswort]]]\n" +"Verwendung: install [Vorlage [Datenbanktyp [Admin-Pa??wort [opt=wert[,...]]]]]\n" " Installiert einen neuen Roundup-Tracker.\n" "\n" -" Sie werden aufgefordert, ein Tracker-Verzeichnis zu w?hlen\n" +" Sie werden aufgefordert, ein Tracker-Verzeichnis zu w??hlen\n" " (falls Sie keines mit TRACKER_HOME oder -i angegeben haben),\n" " sowie eine Vorlage, den Datenbanktyp und das Administrations-\n" -" pa?wort anzugeben.\n" -" Sie k?nnen auch die Vorlage, den Datenbanktyp und das Pa?wort\n" +" passwort anzugeben.\n" +" Sie k??nnen auch die Vorlage, den Datenbanktyp und das Passwort\n" " in dieser Reihenfolge auf der Kommandozeile angegen.\n" "\n" " Das letzte Argument erlaubt die Angabe von Konfigurations-Optionen.\n" " So wird zum Beispiel durch Angabe von\n" " \"web_http_auth=no,rdbms_user=dinsdale\"\n" " die Option http_auth in der Sektion [web] ausgeschaltet und der\n" -" Name des Datenbank-Benutzers in der Sektion [rdbms] ge?ndert.\n" -" Vorsicht bitte mit Leerzeichen! Wenn sie Leerzeichen angeben m?ssen,\n" -" schlie?en Sie das ganze Argument in G?nsef??chen ein.\n" +" Name des Datenbank-Benutzers in der Sektion [rdbms] ge??ndert.\n" +" Vorsicht bitte mit Leerzeichen! Wenn sie Leerzeichen angeben m??ssen,\n" +" schlie??en Sie das ganze Argument in G??nsef????chen ein.\n" "\n" -" Nach der Installation m?ssen Sie die Datenbank mit dem Befehl \n" -" \"initialise\" einrichten. Zuvor k?nnen Sie in der Datei\n" +" Nach der Installation m??ssen Sie die Datenbank mit dem Befehl \n" +" \"initialise\" einrichten. Zuvor k??nnen Sie in der Datei\n" " \"dbinit.py\" die Funktion \"init()\" einen Anfangsbestand an\n" " Daten programmieren.\n" "\n" @@ -321,21 +339,40 @@ # ../roundup/admin.py:358 :483 :562 :612 :682 :703 :731 :802 :869 :940 :988 # :1010 :1037 :1098 :1156 -#: ../roundup/admin.py:359 ../roundup/admin.py:441 ../roundup/admin.py:502 -#: ../roundup/admin.py:581 ../roundup/admin.py:631 ../roundup/admin.py:687 -#: ../roundup/admin.py:708 ../roundup/admin.py:736 ../roundup/admin.py:807 -#: ../roundup/admin.py:874 ../roundup/admin.py:945 ../roundup/admin.py:993 -#: ../roundup/admin.py:1015 ../roundup/admin.py:1042 ../roundup/admin.py:1104 -#: ../roundup/admin.py:1170 +#: ../roundup/admin.py:372 +#: ../roundup/admin.py:469 +#: ../roundup/admin.py:530 +#: ../roundup/admin.py:609 +#: ../roundup/admin.py:660 +#: ../roundup/admin.py:718 +#: ../roundup/admin.py:739 +#: ../roundup/admin.py:767 +#: ../roundup/admin.py:839 +#: ../roundup/admin.py:906 +#: ../roundup/admin.py:977 +#: ../roundup/admin.py:1027 +#: ../roundup/admin.py:1050 +#: ../roundup/admin.py:1081 +#: ../roundup/admin.py:1177 +#: ../roundup/admin.py:1250 +#: ../roundup/admin.py:372:469 +#: :1027:1050 +#: :1081:1177 +#: :1250 +#: :530:609 +#: :660:718 +#: :739:767 +#: :839:906 +#: :977 msgid "Not enough arguments supplied" -msgstr "Zu wenig Parameter ?bergeben" +msgstr "Zu wenig Parameter ??bergeben" -#: ../roundup/admin.py:365 +#: ../roundup/admin.py:378 #, python-format msgid "Instance home parent directory \"%(parent)s\" does not exist" msgstr "Das angegebene Tracker-Verzeichnis \"%(parent)s\" existiert nicht" -#: ../roundup/admin.py:373 +#: ../roundup/admin.py:386 #, python-format msgid "" "WARNING: There appears to be a tracker in \"%(tracker_home)s\"!\n" @@ -343,27 +380,27 @@ "Erase it? Y/N: " msgstr "" "WARNUNG: Im Verzeichnis \"%(tracker_home)s\" scheint bereits ein Tracker\n" -"installiert zu sein! Eine erneute Installation l?scht s?mtliche Daten!\n" -"Wirklich l?schen? Y/N: " +"installiert zu sein! Eine erneute Installation l??scht s??mtliche Daten!\n" +"Wirklich l??schen? Y/N: " -#: ../roundup/admin.py:388 +#: ../roundup/admin.py:401 msgid "Select template [classic]: " -msgstr "Template ausw?hlen [classic]:" +msgstr "Template ausw??hlen [classic]:" -#: ../roundup/admin.py:399 +#: ../roundup/admin.py:412 msgid "Select backend [anydbm]: " -msgstr "Datenbank ausw?hlen [anydbm]" +msgstr "Datenbank ausw??hlen [anydbm]" -#: ../roundup/admin.py:419 +#: ../roundup/admin.py:422 #, python-format msgid "Error in configuration settings: \"%s\"" -msgstr "" -"Fehler in der Konfiguration: \"%s\"" +msgstr "Fehler in der Konfiguration: \"%s\"" -#: ../roundup/admin.py:408 -#, python-format +#: ../roundup/admin.py:431 +#, fuzzy, python-format msgid "" "\n" +"---------------------------------------------------------------------------\n" " You should now edit the tracker configuration file:\n" " %(config_file)s" msgstr "" @@ -371,11 +408,11 @@ " Sie sollten nun die Konfigurationsdatei des Trackers bearbeiten:\n" " %(config_file)s" -#: ../roundup/admin.py:417 +#: ../roundup/admin.py:441 msgid " ... at a minimum, you must set following options:" msgstr " ... passen sie zumindest folgende Optionen an:" -#: ../roundup/admin.py:422 +#: ../roundup/admin.py:446 #, python-format msgid "" "\n" @@ -393,14 +430,14 @@ "\n" " Um das Datenbank-Schema anzupassen, bearbeiten Sie die Datei:\n" " %(database_config_file)s\n" -" Sie k?nnen zudem auch den anf?nglichen Datenbestand ?ndern:\n" +" Sie k??nnen zudem auch den anf??nglichen Datenbestand ??ndern:\n" " %(database_init_file)s\n" -" ... die Online-Dokumentation enth?lt ein eigenes Kapitel ?ber Anpassungen.\n" +" ... die Online-Dokumentation enth??lt ein eigenes Kapitel ??ber Anpassungen.\n" "\n" -" Anschlie?end M?SSEN Sie \"roundup-admin initialise\" ausf?hren.\n" +" Anschlie??end M??SSEN Sie \"roundup-admin initialise\" ausf??hren.\n" "---------------------------------------------------------------------------\n" -#: ../roundup/admin.py:436 +#: ../roundup/admin.py:464 msgid "" "Usage: genconfig \n" " Generate a new tracker config file (ini style) with default values\n" @@ -413,7 +450,7 @@ " " #. password -#: ../roundup/admin.py:446 +#: ../roundup/admin.py:474 msgid "" "Usage: initialise [adminpw]\n" " Initialise a new Roundup tracker.\n" @@ -423,7 +460,7 @@ " Execute the tracker's initialisation function dbinit.init()\n" " " msgstr "" -"Verwendung: initialise [Administrationspasswort]\n" +"Verwendung: initialise [Admin-Pa??wort]\n" " Initialisieren eines neuen Roundup-Trackers.\n" "\n" " Der Administrator-Benutzer wird eingerichtet.\n" @@ -431,33 +468,33 @@ " Die Funktion dbinit.init() wird aufgerufen\n" " " -#: ../roundup/admin.py:460 +#: ../roundup/admin.py:488 msgid "Admin Password: " -msgstr "Administrator-Pa?wort: " +msgstr "Administratorpasswort: " -#: ../roundup/admin.py:461 +#: ../roundup/admin.py:489 msgid " Confirm: " msgstr " Wiederholen: " -#: ../roundup/admin.py:465 +#: ../roundup/admin.py:493 msgid "Instance home does not exist" msgstr "Tracker-Verzeichnis existiert nicht" -#: ../roundup/admin.py:469 +#: ../roundup/admin.py:497 msgid "Instance has not been installed" msgstr "Tracker-Instanz wurde nicht installiert" -#: ../roundup/admin.py:474 +#: ../roundup/admin.py:502 msgid "" "WARNING: The database is already initialised!\n" "If you re-initialise it, you will lose all the data!\n" "Erase it? Y/N: " msgstr "" "WARNUNG: Die Datenbank ist schon initialisiert!\n" -"Eine erneute Initialisierung l?scht s?mtliche Daten!\n" -"Wirklich l?schen? Y/N: " +"Eine erneute Initialisierung l??scht s??mtliche Daten!\n" +"Wirklich l??schen? Y/N: " -#: ../roundup/admin.py:495 +#: ../roundup/admin.py:523 msgid "" "Usage: get property designator[,designator]*\n" " Get the given property of one or more designator(s).\n" @@ -467,36 +504,37 @@ " " msgstr "" "Verwendung: get Eigenschaft Bezeichner[,Bezeichner]*\n" -" Gibt die Eigenschaft eines oder mehrerer Eintr?ge zur?ck.\n" +" Gibt die Eigenschaft eines oder mehrerer Eintr??ge zur??ck.\n" "\n" " Diese Funktion zeigt Ihnen die Werte einer bestimmten\n" -" Eigenschaft der gew?nschten Eintr?ge an.\n" +" Eigenschaft der gew??nschten Eintr??ge an.\n" " " # ../roundup/admin.py:516 :531 -#: ../roundup/admin.py:535 ../roundup/admin.py:550 +#: ../roundup/admin.py:563 +#: ../roundup/admin.py:578 +#: ../roundup/admin.py:563:578 #, python-format msgid "property %s is not of type Multilink or Link so -d flag does not apply." -msgstr "" -"Die Eigenschaft %s ist kein Multilink oder Link; die Option -d wird " -"deshalb hier nicht ausgewertet." +msgstr "Die Eigenschaft %s ist kein Multilink oder Link; die Option -d wird deshalb hier nicht ausgewertet." # ../roundup/admin.py:539 :951 :1000 :1022 -#: ../roundup/admin.py:558 ../roundup/admin.py:956 ../roundup/admin.py:1005 -#: ../roundup/admin.py:1027 +#: ../roundup/admin.py:586 +#: ../roundup/admin.py:988 +#: ../roundup/admin.py:1039 +#: ../roundup/admin.py:1062 +#: ../roundup/admin.py:586:988 +#: :1039:1062 #, python-format msgid "no such %(classname)s node \"%(nodeid)s\"" -msgstr "" -"Es existiert kein Eintrag der Klasse %(classname)s mit der ID \"%(nodeid)s\"" +msgstr "Es existiert kein Eintrag der Klasse %(classname)s mit der ID \"%(nodeid)s\"" -#: ../roundup/admin.py:560 +#: ../roundup/admin.py:588 #, python-format msgid "no such %(classname)s property \"%(propname)s\"" -msgstr "" -"Die Eigenschaft \"%(propname)s\" ist f?r die Klasse \"%" -"(classname)s\" nicht definiert" +msgstr "Die Eigenschaft \"%(propname)s\" ist f??r die Klasse \"%(classname)s\" nicht definiert" -#: ../roundup/admin.py:569 +#: ../roundup/admin.py:597 msgid "" "Usage: set items property=value property=value ...\n" " Set the given properties of one or more items(s).\n" @@ -505,26 +543,25 @@ " list of item designators (ie \"designator[,designator,...]\").\n" "\n" " This command sets the properties to the values for all designators\n" -" given. If the value is missing (ie. \"property=\") then the " -"property\n" +" given. If the value is missing (ie. \"property=\") then the property\n" " is un-set. If the property is a multilink, you specify the linked\n" " ids for the multilink as comma-separated numbers (ie \"1,2,3\").\n" " " msgstr "" -"Verwendung: set Eintr?ge Eigenschaft=Wert Eigenschaft=Wert ...\n" -" Bearbeitet den Eigenschaftswert eines oder mehrerer Eintr?ge.\n" +"Verwendung: set Eintr??ge Eigenschaft=Wert Eigenschaft=Wert ...\n" +" Bearbeitet den Eigenschaftswert eines oder mehrerer Eintr??ge.\n" "\n" -" F?r \"Eintr?ge\" k?nnen Sie eine Klasse angeben oder eine Liste\n" -" von einem oder mehreren mit Kommata getrennten Bezeichnern auff?hren\n" +" F??r \"Eintr??ge\" k??nnen Sie eine Klasse angeben oder eine Liste\n" +" von einem oder mehreren mit Kommata getrennten Bezeichnern auff??hren\n" " (\"Bezeichner[,Bezeichner]*\").\n" "\n" -" Der Wert der Eigenschaft wird f?r alle angegebenen Eintr?ge gesetzt.\n" -" Wenn der Wert fehlt (Eigenschaft=), wird die Eigenschaft gel?scht.\n" +" Der Wert der Eigenschaft wird f??r alle angegebenen Eintr??ge gesetzt.\n" +" Wenn der Wert fehlt (Eigenschaft=), wird die Eigenschaft gel??scht.\n" " Wenn die Eigenschaft ein Link/Multilink ist, werden die verlinkten\n" -" Eintr?ge als mit Kommata getrennte ID-Nummern angegeben (\"1,2,3\").\n" +" Eintr??ge als mit Kommata getrennte ID-Nummern angegeben (\"1,2,3\").\n" " " -#: ../roundup/admin.py:623 +#: ../roundup/admin.py:652 msgid "" "Usage: find classname propname=value ...\n" " Find the nodes of the given class with a given link property value.\n" @@ -535,21 +572,25 @@ " " msgstr "" "Verwendung: find Klassenname Eigenschaft=Wert ...\n" -" Findet Eintr?ge, welche die angegebene Verlinkung aufweisen.\n" +" Findet Eintr??ge, welche die angegebene Verlinkung aufweisen.\n" "\n" -" Findet s?mtliche Eintr?ge einer Klasse, bei welchen die Link-\n" -" Eigenschaft den angegebenen Wert enth?lt. Der Wert kann entweder\n" +" Findet s??mtliche Eintr??ge einer Klasse, bei welchen die Link-\n" +" Eigenschaft den angegebenen Wert enth??lt. Der Wert kann entweder\n" " als ID oder als Bezeichner (\"msg23\") spezifiziert werden.\n" " " # ../roundup/admin.py:631 :669 :822 :834 :888 -#: ../roundup/admin.py:674 ../roundup/admin.py:827 ../roundup/admin.py:839 -#: ../roundup/admin.py:893 +#: ../roundup/admin.py:705 +#: ../roundup/admin.py:859 +#: ../roundup/admin.py:871 +#: ../roundup/admin.py:925 +#: ../roundup/admin.py:705:859 +#: :871:925 #, python-format msgid "%(classname)s has no property \"%(propname)s\"" msgstr "Die Klasse \"%(classname)s\" hat keine Eigenschaft \"%(propname)s\"" -#: ../roundup/admin.py:681 +#: ../roundup/admin.py:712 msgid "" "Usage: specification classname\n" " Show the properties for a classname.\n" @@ -560,20 +601,22 @@ "Verwendung: specification Klassenname\n" " Gibt die Attribute der Klasse aus.\n" "\n" -" Zeigt s?mtliche Eigenschaften der Klasse auf.\n" +" Zeigt s??mtliche Eigenschaften der Klasse auf.\n" " " -#: ../roundup/admin.py:696 +#: ../roundup/admin.py:727 #, python-format msgid "%(key)s: %(value)s (key property)" -msgstr "%(key)s: %(value)s (Schl?sseleigenschaft)" +msgstr "%(key)s: %(value)s (Schl??sseleigenschaft)" -#: ../roundup/admin.py:698 +#: ../roundup/admin.py:729 +#: ../roundup/admin.py:756 +#: ../roundup/admin.py:729:756 #, python-format msgid "%(key)s: %(value)s" msgstr "%(key)s: %(value)s" -#: ../roundup/admin.py:701 +#: ../roundup/admin.py:732 msgid "" "Usage: display designator[,designator]*\n" " Show the property values for the given node(s).\n" @@ -585,23 +628,17 @@ "Verwendung: display Bezeichner[,Bezeichner]*\n" " Zeigt alle Eigenschaften eines oder mehrerer Eintrage an.\n" "\n" -" Der Befehl zeigt die Eigenschaften und Ihre Werte des\n" -" gew?hlten Eintrags an.\n" +" Der Befehl zeigt die Eigenschaften und ihre Werte des\n" +" gew??hlten Eintrags an.\n" " " -#: ../roundup/admin.py:725 -#, python-format -msgid "%(key)s: %(value)r" -msgstr "%(key)s: %(value)r" - -#: ../roundup/admin.py:728 +#: ../roundup/admin.py:759 msgid "" "Usage: create classname property=value ...\n" " Create a new entry of a given class.\n" "\n" " This creates a new entry of the given class using the property\n" -" name=value arguments provided on the command line after the \"create" -"\"\n" +" name=value arguments provided on the command line after the \"create\"\n" " command.\n" " " msgstr "" @@ -612,31 +649,31 @@ " werden mit den Werten initialisiert\n" " " -#: ../roundup/admin.py:755 +#: ../roundup/admin.py:786 #, python-format msgid "%(propname)s (Password): " -msgstr "%(propname)s (Pa?wort):" +msgstr "%(propname)s (Passwort):" -#: ../roundup/admin.py:757 +#: ../roundup/admin.py:788 #, python-format msgid " %(propname)s (Again): " msgstr " %(propname)s (Wiederholen):" -#: ../roundup/admin.py:759 +#: ../roundup/admin.py:790 msgid "Sorry, try again..." msgstr "Bitte erneut versuchen..." -#: ../roundup/admin.py:763 +#: ../roundup/admin.py:794 #, python-format msgid "%(propname)s (%(proptype)s): " msgstr "%(propname)s (%(proptype)s): " -#: ../roundup/admin.py:781 +#: ../roundup/admin.py:812 #, python-format msgid "you must provide the \"%(propname)s\" property." -msgstr "Sie m?ssen einen Wert f?r \"%(propname)s\" angeben." +msgstr "Sie m??ssen einen Wert f??r \"%(propname)s\" angeben." -#: ../roundup/admin.py:792 +#: ../roundup/admin.py:824 msgid "" "Usage: list classname [property]\n" " List the instances of a class.\n" @@ -652,31 +689,30 @@ " " msgstr "" "Usage: list Klassenname [Eigenschaft]\n" -" Listet s?mtliche Eintr?ge einer Klasse auf.\n" +" Listet s??mtliche Eintr??ge einer Klasse auf.\n" "\n" -" Es werden s?mtliche Eintr?ge der Klasse ausgegeben. Wird keine\n" +" Es werden s??mtliche Eintr??ge der Klasse ausgegeben. Wird keine\n" " Eigenschaft angegeben, so wird ein Bezeichner aus der folgenden\n" -" Liste generiert, mit absteigender Priorit?t:\n" -" Schl?sselfeld, ein Feld namens \"name\" oder \"title\". Falls\n" +" Liste generiert, mit absteigender Priorit??t:\n" +" Schl??sselfeld, ein Feld namens \"name\" oder \"title\". Falls\n" " auch diese Felder nicht existieren, wird das \n" " erste Feld alphabetisch sortiert angezeigt.\n" "\n" " Mit den Optionen -c, -S or -s wird eine Liste von IDs ausgegeben,\n" " falls keine Eigenschaft angegeben wird. Sonst werden die Werte\n" -" dieser Eigenschaften s?mtlicher Instanzen dieser Klasse " -"aufgelistet.\n" +" dieser Eigenschaften s??mtlicher Instanzen dieser Klasse aufgelistet.\n" " " -#: ../roundup/admin.py:805 +#: ../roundup/admin.py:837 msgid "Too many arguments supplied" -msgstr "Sie haben zuviele Argumente ?bergeben" +msgstr "Sie haben zuviele Argumente ??bergeben" -#: ../roundup/admin.py:841 +#: ../roundup/admin.py:873 #, python-format msgid "%(nodeid)4s: %(value)s" msgstr "%(nodeid)4s: %(value)s" -#: ../roundup/admin.py:845 +#: ../roundup/admin.py:877 msgid "" "Usage: table classname [property[,property]*]\n" " List the instances of a class in tabular form.\n" @@ -708,12 +744,12 @@ " " msgstr "" "Verwendung: table Klassenname [Eigenschaft[,Eigenschaft]*]\n" -" Listet die Eintr?ge einer Klasse in tabellarischer Form.\n" +" Listet die Eintr??ge einer Klasse in tabellarischer Form.\n" "\n" -" Dieser Befehl gibt eine Liste s?mtlicher Instanzen einer Klasse aus.\n" +" Dieser Befehl gibt eine Liste s??mtlicher Instanzen einer Klasse aus.\n" " Werden die Eigenschaften nicht explizit angegeben, so werden\n" " alle angezeigt. Die Spaltenbreite wird automatisch nach dem \n" -" gr?ssten Wert jeder Spalte berechnet, oder sie kann explizit\n" +" gr??ssten Wert jeder Spalte berechnet, oder sie kann explizit\n" " als \"Eigenschaft:Breite\" angegeben werden.\n" " Beispiel:\n" "\n" @@ -724,7 +760,7 @@ " 3 usability\n" " 4 feature\n" "\n" -" Um die Spaltenbreite auf die Gr?sse des Spaltentitels zu bechr?nken,\n" +" Um die Spaltenbreite auf die Gr??sse des Spaltentitels zu bechr??nken,\n" " lassen Sie die Breitenangabe hinter dem Doppelpunkt weg.\n" " Beispiel:\n" "\n" @@ -737,18 +773,17 @@ "\n" " " -#: ../roundup/admin.py:889 +#: ../roundup/admin.py:921 #, python-format msgid "\"%(spec)s\" not name:width" msgstr "\"%(spec)s\" entspricht nicht dem Format Eigenschaft:Breite" -#: ../roundup/admin.py:939 +#: ../roundup/admin.py:971 msgid "" "Usage: history designator\n" " Show the history entries of a designator.\n" "\n" -" Lists the journal entries for the node identified by the " -"designator.\n" +" Lists the journal entries for the node identified by the designator.\n" " " msgstr "" "Verwendung: history Bezeichner\n" @@ -758,7 +793,7 @@ " Bezeichner auf.\n" " " -#: ../roundup/admin.py:960 +#: ../roundup/admin.py:992 msgid "" "Usage: commit\n" " Commit changes made to the database during an interactive session.\n" @@ -772,17 +807,17 @@ " " msgstr "" "Verwendung: commit\n" -" Speichern der Datenbank-?nderungen.\n" +" Speichern der Datenbank-??nderungen.\n" "\n" -" Falls die Datenbank Transaktionen unterst?tzt, werden ?nderungen\n" -" w?hrend einer Bearbeitungs-Session erst nach einem \"commit\" an die\n" -" Datenbank ?bermittelt.\n" +" Falls die Datenbank Transaktionen unterst??tzt, werden ??nderungen\n" +" w??hrend einer Bearbeitungs-Session erst nach einem \"commit\" an die\n" +" Datenbank ??bermittelt.\n" "\n" -" Einzelbefehle ?ber die Kommandozeile werden sofort in die Datenbank\n" +" Einzelbefehle ??ber die Kommandozeile werden sofort in die Datenbank\n" " geschrieben.\n" " " -#: ../roundup/admin.py:974 +#: ../roundup/admin.py:1007 msgid "" "Usage: rollback\n" " Undo all changes that are pending commit to the database.\n" @@ -794,14 +829,14 @@ " " msgstr "" "Verwendung: rollback\n" -" S?mtliche nicht gespeicherte ?nderungen werden verworfen.\n" +" S??mtliche nicht gespeicherte ??nderungen werden verworfen.\n" "\n" -" Falls die Datenbank Transaktionen unterst?tzt, werden dadurch\n" -" s?mtliche noch nicht gespeicherte ?nderungen (siehe \"commit\")\n" +" Falls die Datenbank Transaktionen unterst??tzt, werden dadurch\n" +" s??mtliche noch nicht gespeicherte ??nderungen (siehe \"commit\")\n" " verworfen.\n" " " -#: ../roundup/admin.py:986 +#: ../roundup/admin.py:1020 msgid "" "Usage: retire designator[,designator]*\n" " Retire the node specified by designator.\n" @@ -811,14 +846,14 @@ " " msgstr "" "Verwendung: retire Bezeichner[,Bezeichner]*\n" -" Verbirgt einen oder mehrere Eintr?ge.\n" +" Verbirgt einen oder mehrere Eintr??ge.\n" "\n" -" Das Verbergen eines Eintrags bewirkt, da? dieser bei einer Suche\n" -" nicht mehr angezeigt wird. Der Schl?ssel des verborgenen Eintrags\n" +" Das Verbergen eines Eintrags bewirkt, dass dieser bei einer Suche\n" +" nicht mehr angezeigt wird. Der Schl??ssel des verborgenen Eintrags\n" " kann zudem wiederverwendet werden.\n" " " -#: ../roundup/admin.py:1009 +#: ../roundup/admin.py:1044 msgid "" "Usage: restore designator[,designator]*\n" " Restore the retired node specified by designator.\n" @@ -827,19 +862,22 @@ " " msgstr "" "Verwendung: restore Bezeichner[,Bezeichner]*\n" -" Ein oder mehrere verborgene Eintr?ge werden wiederhergestellt.\n" +" Ein oder mehrere verborgene Eintr??ge werden wiederhergestellt.\n" "\n" " Ein verborgener Eintrag wird wiederhergestellt und ist danach\n" -" f?r die Benutzer wieder sichtbar.\n" +" f??r die Benutzer wieder sichtbar.\n" " " #. grab the directory to export to -#: ../roundup/admin.py:1031 +#: ../roundup/admin.py:1067 msgid "" -"Usage: export [class[,class]] export_dir\n" +"Usage: export [[-]class[,class]] export_dir\n" " Export the database to colon-separated-value files.\n" +" To exclude the files (e.g. for the msg or file class),\n" +" use the exporttables command.\n" "\n" -" Optionally limit the export to just the names classes.\n" +" Optionally limit the export to just the named classes\n" +" or exclude the named classes, if the 1st argument starts with '-'.\n" "\n" " This action exports the current data from the database into\n" " colon-separated-value files that are placed in the nominated\n" @@ -848,14 +886,44 @@ msgstr "" "Verwendung: export [Klasse[,Klasse]] Exportverzeichnis\n" " Exportiert die Datenbank in ein Verzeichnis mit CSV-Dateien.\n" +" Um die im Dateisystem abgelegten Daten fortzulassen (z. B.\n" +" die Klassen msg und file), verwenden Sie \"exporttables\".\n" "\n" -" Optional kann der Export auf gewisse Klassen beschr?nkt werden.\n" +" Wenn Sie Klassennamen ??bergeben, wird der Export auf diese beschr??nkt\n" +" bzw. (wenn der ersten Klasse ein '-' vorgestellt wird) diese fortgelassen.\n" "\n" " Die Daten werden als kommagetrennte Dateien in das angegebene\n" " Exportverzeichnis geschrieben.\n" " " -#: ../roundup/admin.py:1084 +#: ../roundup/admin.py:1142 +msgid "" +"Usage: exporttables [[-]class[,class]] export_dir\n" +" Export the database to colon-separated-value files, excluding the\n" +" files below $TRACKER_HOME/db/files/ (which can be archived separately).\n" +" To include the files, use the export command.\n" +"\n" +" Optionally limit the export to just the named classes\n" +" or exclude the named classes, if the 1st argument starts with '-'.\n" +"\n" +" This action exports the current data from the database into\n" +" colon-separated-value files that are placed in the nominated\n" +" destination directory.\n" +" " +msgstr "" +"Verwendung: exporttables [Klasse[,Klasse]] Exportverzeichnis\n" +" Exportiert die Datenbank in ein Verzeichnis mit CSV-Dateien,\n" +" unter Fortlassung der im Dateisystem unter $TRACKER_HOME/db/files\n" +" abgelegten Daten; um diese mitzuexportieren, verwenden Sie \"export\".\n" +"\n" +" Wenn Sie Klassennamen ??bergeben, wird der Export auf diese beschr??nkt\n" +" bzw. (wenn der ersten Klasse ein '-' vorgestellt wird) diese fortgelassen.\n" +"\n" +" Die Daten werden als kommagetrennte Dateien in das angegebene\n" +" Exportverzeichnis geschrieben.\n" +" " + +#: ../roundup/admin.py:1157 msgid "" "Usage: import import_dir\n" " Import a database from the directory containing CSV files,\n" @@ -878,36 +946,35 @@ " " msgstr "" "Verwendung: import Importverzeichnis\n" -" Importiert Datens?tze aus einem Verzeichnis mit CSV-Dateien\n" +" Importiert Datens??tze aus einem Verzeichnis mit CSV-Dateien\n" "\n" " Folgende Dateien werden beim Import verwendet:\n" "\n" " .csv\n" -" In dieser Datei sind die Daten zu den Eintr?gen einer Klasse.\n" -" F?r s?mtliche Eigenschaften der Klasse mu? eine Spalte \n" +" In dieser Datei sind die Daten zu den Eintr??gen einer Klasse.\n" +" F??r s??mtliche Eigenschaften der Klasse muss eine Spalte \n" " exisitieren. In der ersten Zeile stehen die Eigenschaftsnamen.\n" " -journals.csv\n" -" In dieser Datei wird der Bearbeitungs-Verlauf der Eintr?ge\n" +" In dieser Datei wird der Bearbeitungs-Verlauf der Eintr??ge\n" " beschrieben.\n" "\n" -" Importierte Eintr?ge ?bernehmen die IDs, welche in den Dateien\n" -" definiert sind. Existierende Eintr?ge mit denselben IDs werden\n" -" ?berschrieben.\n" -" Die Eintr?ge werden in die existierende Datenbank geschrieben.\n" -" Falls eine neue, leere Datenbank verwendet werden soll, so m?ssen\n" -" Sie diese zuerst erstellen (oder s?mtliche bestehenden Inhalte \n" +" Importierte Eintr??ge ??bernehmen die IDs, welche in den Dateien\n" +" definiert sind. Existierende Eintr??ge mit denselben IDs werden\n" +" ??berschrieben.\n" +" Die Eintr??ge werden in die existierende Datenbank geschrieben.\n" +" Falls eine neue, leere Datenbank verwendet werden soll, so m??ssen\n" +" Sie diese zuerst erstellen (oder s??mtliche bestehenden Inhalte \n" " verbergen).\n" " " -#: ../roundup/admin.py:1152 +#: ../roundup/admin.py:1232 msgid "" "Usage: pack period | date\n" "\n" " Remove journal entries older than a period of time specified or\n" " before a certain date.\n" "\n" -" A period is specified using the suffixes \"y\", \"m\", and \"d\". " -"The\n" +" A period is specified using the suffixes \"y\", \"m\", and \"d\". The\n" " suffix \"w\" (for \"week\") means 7 days.\n" "\n" " \"3y\" means three years\n" @@ -923,26 +990,25 @@ "Verwendung: pack Periode | Datum\n" " Entfernt den Bearbeitungsverlauf ab einem gewissen Datum.\n" "\n" -" Das Datum kann als r?ckl?ufige Periode spezifiziert werden:\n" -" \"y\", \"m\", and \"d\". wobei \"w\" (Woche) f?r 7 Tage " -"steht.\n" +" Das Datum kann als r??ckl??ufige Periode spezifiziert werden:\n" +" \"y\", \"m\", and \"d\". wobei \"w\" (Woche) f??r 7 Tage steht.\n" "\n" " Beispiele:\n" -" \"3y\" steht f?r 3 Jahre\n" -" \"2y 1m\" steht f?r 2 Jahre und ein Monat\n" -" \"1m 25d\" steht f?r 1 Monat und 25 Tage\n" -" \"2w 3d\" steht f?r 2 Wochen und 3 Tage\n" +" \"3y\" steht f??r 3 Jahre\n" +" \"2y 1m\" steht f??r 2 Jahre und ein Monat\n" +" \"1m 25d\" steht f??r 1 Monat und 25 Tage\n" +" \"2w 3d\" steht f??r 2 Wochen und 3 Tage\n" "\n" " Das Datumsformat lautet \"JJJJ-MM-TT\", z.B:\n" " 2001-06-27\n" "\n" " " -#: ../roundup/admin.py:1180 +#: ../roundup/admin.py:1260 msgid "Invalid format" -msgstr "Ung?ltiges Format" +msgstr "Ung??ltiges Format" -#: ../roundup/admin.py:1190 +#: ../roundup/admin.py:1271 msgid "" "Usage: reindex [classname|designator]*\n" " Re-generate a tracker's search indexes.\n" @@ -958,12 +1024,12 @@ " normalerweise automatisch.\n" " " -#: ../roundup/admin.py:1204 +#: ../roundup/admin.py:1285 #, python-format msgid "no such item \"%(designator)s\"" msgstr "Der Eintrag \"%(designator)s\" existiert nicht" -#: ../roundup/admin.py:1214 +#: ../roundup/admin.py:1295 msgid "" "Usage: security [Role name]\n" " Display the Permissions available to one or all Roles.\n" @@ -973,77 +1039,129 @@ " Zeigt die Berechtigungen einer oder aller Rollen an.\n" " " -#: ../roundup/admin.py:1222 +#: ../roundup/admin.py:1303 #, python-format msgid "No such Role \"%(role)s\"" msgstr "Die Rolle \"%(role)s\" existiert nicht " -#: ../roundup/admin.py:1228 +#: ../roundup/admin.py:1309 #, python-format msgid "New Web users get the Roles \"%(role)s\"" msgstr "Neue Web-Benutzer erhalten die Rollen \"%(role)s\"" -#: ../roundup/admin.py:1230 +#: ../roundup/admin.py:1311 #, python-format msgid "New Web users get the Role \"%(role)s\"" msgstr "Neue Web-Benutzer erhalten die Rolle \"%(role)s\"" -#: ../roundup/admin.py:1233 +#: ../roundup/admin.py:1314 #, python-format msgid "New Email users get the Roles \"%(role)s\"" -msgstr "Neue Email-Benutzer erhalten die Rollen \"%(role)s\"" +msgstr "Neue E-Mail-Benutzer erhalten die Rollen \"%(role)s\"" -#: ../roundup/admin.py:1235 +#: ../roundup/admin.py:1316 #, python-format msgid "New Email users get the Role \"%(role)s\"" -msgstr "Neue Email-Benutzer erhalten die Rolle \"%(role)s\"" +msgstr "Neue E-Mail-Benutzer erhalten die Rolle \"%(role)s\"" -#: ../roundup/admin.py:1238 +#: ../roundup/admin.py:1319 #, python-format msgid "Role \"%(name)s\":" msgstr "Rolle \"%(name)s\":" -#: ../roundup/admin.py:1280 +#: ../roundup/admin.py:1324 #, python-format msgid " %(description)s (%(name)s for \"%(klass)s\": %(properties)s only)" -msgstr " %(description)s (%(name)s f?r \"%(klass)s\": ausschlie?lich %(properties)s)" +msgstr " %(description)s (%(name)s f??r \"%(klass)s\": ausschlie??lich %(properties)s)" -#: ../roundup/admin.py:1241 +#: ../roundup/admin.py:1327 #, python-format msgid " %(description)s (%(name)s for \"%(klass)s\" only)" -msgstr "%(description)s (%(name)s einzig f?r \"%(klass)s\")" +msgstr "%(description)s (%(name)s einzig f??r \"%(klass)s\")" -#: ../roundup/admin.py:1244 +#: ../roundup/admin.py:1330 #, python-format msgid " %(description)s (%(name)s)" msgstr " %(description)s (%(name)s)" -#: ../roundup/admin.py:1273 +#: ../roundup/admin.py:1335 +msgid "" +"Usage: migrate\n" +" Update a tracker's database to be compatible with the Roundup\n" +" codebase.\n" +"\n" +" You should run the \"migrate\" command for your tracker once you've\n" +" installed the latest codebase. \n" +"\n" +" Do this before you use the web, command-line or mail interface and\n" +" before any users access the tracker.\n" +"\n" +" This command will respond with either \"Tracker updated\" (if you've\n" +" not previously run it on an RDBMS backend) or \"No migration action\n" +" required\" (if you have run it, or have used another interface to the\n" +" tracker, or possibly because you are using anydbm).\n" +"\n" +" It's safe to run this even if it's not required, so just get into\n" +" the habit.\n" +" " +msgstr "" +"Verwendung: migrate\n" +" Aktualisiert die Datenbank eines Trackers, um sie mit dem aktuellen\n" +" Roundup-Code kompatibel zu machen\n" +"\n" +" Sie sollten \"migrate\" einmalig ausf??hren, wenn Sie auf die neueste Roundup-Version aktualisiert haben.\n" +"\n" +" Tun Sie das, bevor Sie per Web (Internet-Browser), Kommandozeile\n" +" oder Mail auf den Tracker zugreifen.\n" +"\n" +" Das Kommando wird anschlie??end \"Tracker aktualisiert\" antworten\n" +" (sofern Sie es nicht schon vorher ausgef??hrt haben) oder\n" +" \"Keine Migration notwendig\" (wenn Sie es schon ausgef??hrt hatten,\n" +" oder ein anderes Datenbank-Backend verwendet haben, oder\n" +" vielleicht weil Sie anydbm verwenden.\n" +"\n" +" Es kann nicht schaden, dieses Kommando auszuf??hren, selbst wenn\n" +" es nicht n??tig ist; also gew??hnen Sie es sich einfach an.\n" +" " + +#: ../roundup/admin.py:1354 +msgid "Tracker updated" +msgstr "Tracker aktualisiert" + +#: ../roundup/admin.py:1357 +msgid "No migration action required" +msgstr "Keine Migration notwendig" + +#: ../roundup/admin.py:1386 #, python-format msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)" msgstr "Der Befehl \"%(command)s\" existiert nicht (siehe \"help commands\")" -#: ../roundup/admin.py:1279 +#: ../roundup/admin.py:1392 #, python-format msgid "Multiple commands match \"%(command)s\": %(list)s" -msgstr "Zur Abk?rzung \"%(command)s\" passen mehrere Befehle: %(list)s" +msgstr "Zur Abk??rzung \"%(command)s\" passen mehrere Befehle: %(list)s" -#: ../roundup/admin.py:1286 +#: ../roundup/admin.py:1399 msgid "Enter tracker home: " msgstr "Tracker-Verzeichnis: " # ../roundup/admin.py:1263 :1269 :1289 -#: ../roundup/admin.py:1293 ../roundup/admin.py:1299 ../roundup/admin.py:1319 +#: ../roundup/admin.py:1406 +#: ../roundup/admin.py:1412 +#: ../roundup/admin.py:1432 +#: ../roundup/admin.py:1406:1412 +#: :1432 #, python-format msgid "Error: %(message)s" msgstr "Fehler: %(message)s" -#: ../roundup/admin.py:1307 +#: ../roundup/admin.py:1420 #, python-format msgid "Error: Couldn't open tracker: %(message)s" -msgstr "Fehler: Die Tracker-Instanz konnte nicht ge?ffnet werden: %(message)s" +msgstr "Fehler: Die Tracker-Instanz konnte nicht ge??ffnet werden: %(message)s" -#: ../roundup/admin.py:1332 +#: ../roundup/admin.py:1445 #, python-format msgid "" "Roundup %s ready for input.\n" @@ -1052,209 +1170,253 @@ "Roundup %s ist bereit.\n" "Schreiben Sie \"help\", um zur Hilfe zu gelangen." -#: ../roundup/admin.py:1337 +#: ../roundup/admin.py:1450 msgid "Note: command history and editing not available" -msgstr "Bemerkung: Befehlsverlauf/-bearbeitung nicht verf?gbar" +msgstr "Bemerkung: Befehlsverlauf/-bearbeitung m??glicherweise nicht verf??gbar" -#: ../roundup/admin.py:1341 +#: ../roundup/admin.py:1454 msgid "roundup> " msgstr "roundup> " -#: ../roundup/admin.py:1343 +#: ../roundup/admin.py:1456 msgid "exit..." msgstr "beenden..." -#: ../roundup/admin.py:1353 +#: ../roundup/admin.py:1466 msgid "There are unsaved changes. Commit them (y/N)? " -msgstr "Es gibt noch ungespeicherte ?nderungen. ?nderungen speichern (y/N)?" +msgstr "Es gibt noch ungespeicherte ??nderungen. ??nderungen speichern (y/N)?" + +#: ../roundup/backends/back_anydbm.py:218 +#: ../roundup/backends/sessions_dbm.py:50 +msgid "Couldn't identify database type" +msgstr "Konnte den Datenbanktyp nicht ermitteln" + +#: ../roundup/backends/back_anydbm.py:244 +#, python-format +msgid "Couldn't open database - the required module '%s' is not available" +msgstr "Konnte die Datenbank nicht ??ffnen - das erforderliche Modul '%s' ist nicht verf??gbar" + +#: ../roundup/backends/back_anydbm.py:799 +#: ../roundup/backends/back_anydbm.py:1074 +#: ../roundup/backends/back_anydbm.py:1271 +#: ../roundup/backends/back_anydbm.py:1289 +#: ../roundup/backends/back_anydbm.py:1335 +#: ../roundup/backends/back_anydbm.py:1905 +#: ../roundup/backends/back_anydbm.py:799:1074 +#: ../roundup/backends/rdbms_common.py:1396 +#: ../roundup/backends/rdbms_common.py:1625 +#: ../roundup/backends/rdbms_common.py:1831 +#: ../roundup/backends/rdbms_common.py:1851 +#: ../roundup/backends/rdbms_common.py:1904 +#: ../roundup/backends/rdbms_common.py:2512 +#: ../roundup/backends/rdbms_common.py:1396:1625 +#: :1271:1289 +#: :1335:1905 +#: :1831:1851 +#: :1904:2512 +msgid "Database open read-only" +msgstr "Datenbank nur zum Lesen ge??ffnet" -#: ../roundup/backends/back_anydbm.py:2054 +#: ../roundup/backends/back_anydbm.py:2007 #, python-format msgid "WARNING: invalid date tuple %r" -msgstr "WARNUNG: ung?ltiges Datums-Tupel %r" +msgstr "WARNUNG: ung??ltiges Datums-Tupel %r" -#: ../roundup/backends/rdbms_common.py:1425 +#: ../roundup/backends/rdbms_common.py:1525 msgid "create" msgstr "erstellt" -#: ../roundup/backends/rdbms_common.py:1588 +#: ../roundup/backends/rdbms_common.py:1691 msgid "unlink" -msgstr "Link gel?scht" +msgstr "Link gel??scht" -#: ../roundup/backends/rdbms_common.py:1592 +#: ../roundup/backends/rdbms_common.py:1695 msgid "link" msgstr "verlinkt" -#: ../roundup/backends/rdbms_common.py:1702 +#: ../roundup/backends/rdbms_common.py:1817 msgid "set" -msgstr "ge?ndert" +msgstr "ge??ndert" -#: ../roundup/backends/rdbms_common.py:1726 +#: ../roundup/backends/rdbms_common.py:1841 msgid "retired" msgstr "verborgen" -#: ../roundup/backends/rdbms_common.py:1756 +#: ../roundup/backends/rdbms_common.py:1871 msgid "restored" msgstr "wiederhergestellt" -#: ../roundup/cgi/actions.py:58 -#, python-format -msgid "You do not have permission to %(action)s the %(classname)s class." -msgstr "" -"Sie sind nicht berechtigt, die Aktion(en) %(action)s auf die Klasse" -" %(classname)s anzuwenden." - -#: ../roundup/cgi/actions.py:89 +#: ../roundup/cgi/actions.py:88 msgid "No type specified" msgstr "Typ nicht spezifiziert" -#: ../roundup/cgi/actions.py:91 +#: ../roundup/cgi/actions.py:90 msgid "No ID entered" msgstr "keine ID spezifiziert" -#: ../roundup/cgi/actions.py:97 +#: ../roundup/cgi/actions.py:96 #, python-format msgid "\"%(input)s\" is not an ID (%(classname)s ID required)" msgstr "\"%(input)s\" ist keine ID (%(classname)s ID wird erwartet)" -#: ../roundup/cgi/actions.py:117 -msgid "You may not retire the admin or anonymous user" -msgstr "Sie k?nnen den Administrator oder den Gast-Benutzer nicht l?schen" +#: ../roundup/cgi/actions.py:108 +#: ../roundup/cgi/actions.py:287 +#: ../roundup/cgi/actions.py:590 +#: ../roundup/cgi/actions.py:636 +#: ../roundup/cgi/actions.py:822 +#: ../roundup/cgi/actions.py:940 +#: ../roundup/cgi/actions.py:108:287 +#: :590:636 +#: :822:940 +msgid "Invalid request" +msgstr "Ung??ltige Anforderung" + +#: ../roundup/cgi/actions.py:126 +#: ../roundup/cgi/actions.py:382 +#: ../roundup/cgi/actions.py:126:382 +#, python-format +msgid "You do not have permission to retire %(class)s" +msgstr "Sie sind nicht berechtigt, Eintr??ge der Klasse \"%(class)s\" zu l??schen" -#: ../roundup/cgi/actions.py:124 +#: ../roundup/cgi/actions.py:134 #, python-format msgid "%(classname)s %(itemid)s has been retired" -msgstr "%(classname)s %(itemid)s wurde gel?scht" +msgstr "%(classname)s %(itemid)s wurde gel??scht" # ../roundup/cgi/actions.py:174 :202 -#: ../roundup/cgi/actions.py:174 ../roundup/cgi/actions.py:202 +#: ../roundup/cgi/actions.py:175 +#: ../roundup/cgi/actions.py:203 +#: ../roundup/cgi/actions.py:175:203 msgid "You do not have permission to edit queries" msgstr "Sie haben keine Berechtigung, Abfragen zu bearbeiten." # ../roundup/cgi/actions.py:180 :209 -#: ../roundup/cgi/actions.py:180 ../roundup/cgi/actions.py:209 +#: ../roundup/cgi/actions.py:181 +#: ../roundup/cgi/actions.py:210 +#: ../roundup/cgi/actions.py:181:210 msgid "You do not have permission to store queries" msgstr "Sie haben keine Berechtigung, Abfragen zu speichern." -#: ../roundup/cgi/actions.py:279 +#: ../roundup/cgi/actions.py:321 +#: ../roundup/cgi/actions.py:507 +#: ../roundup/cgi/actions.py:321:507 +#, python-format +msgid "You do not have permission to create %(class)s" +msgstr "Sie sind nicht berechtigt, Eintr??ge der Klasse \"%(class)s\" zu erstellen" + +#: ../roundup/cgi/actions.py:329 #, python-format msgid "Not enough values on line %(line)s" -msgstr "Nicht gen?gend Werte in Zeile %(line)s" +msgstr "Nicht gen??gend Werte in Zeile %(line)s" -#: ../roundup/cgi/actions.py:326 +#: ../roundup/cgi/actions.py:339 +#: ../roundup/cgi/actions.py:495 +#: ../roundup/cgi/actions.py:339:495 +#, python-format +msgid "You do not have permission to edit %(class)s" +msgstr "Sie sind nicht berechtigt, Eintr??ge der Klasse \"%(class)s\" zu bearbeiten" + +#: ../roundup/cgi/actions.py:389 msgid "Items edited OK" -msgstr "Die Eintr?ge wurden aktualisiert" +msgstr "Die Eintr??ge wurden aktualisiert" -#: ../roundup/cgi/actions.py:386 +#: ../roundup/cgi/actions.py:448 #, python-format msgid "%(class)s %(id)s %(properties)s edited ok" msgstr "Eigenschaft \"%(properties)s\" bei \"%(class)s %(id)s\" bearbeitet" -#: ../roundup/cgi/actions.py:389 +#: ../roundup/cgi/actions.py:451 #, python-format msgid "%(class)s %(id)s - nothing changed" -msgstr "%(class)s %(id)s - keine ?nderungen" +msgstr "%(class)s %(id)s - keine ??nderungen" -#: ../roundup/cgi/actions.py:401 +#: ../roundup/cgi/actions.py:463 #, python-format msgid "%(class)s %(id)s created" msgstr "Der Eintrag \"%(class)s%(id)s\" wurde erstellt" -#: ../roundup/cgi/actions.py:433 -#, python-format -msgid "You do not have permission to edit %(class)s" -msgstr "" -"Sie sind nicht berechtigt, Eintr?ge der Klasse \"%(class)s\" zu " -"bearbeiten" - -#: ../roundup/cgi/actions.py:445 +#: ../roundup/cgi/actions.py:575 #, python-format -msgid "You do not have permission to create %(class)s" -msgstr "" -"Sie sind nicht berechtigt, Eintr?ge der Klasse \"%(class)s\" zu " -"erstellen" - -#: ../roundup/cgi/actions.py:468 -msgid "You do not have permission to edit user roles" -msgstr "Sie sind nicht berechtigt, Benutzer-Rollen zu ?ndern" - -#: ../roundup/cgi/actions.py:537 -#, python-format -msgid "" -"Edit Error: someone else has edited this %s (%s). View their changes in a new window." -msgstr "" -"Fehler: Jemand anders hat dieses %s bearbeitet (%s). Sehen Sie " -"dessen ?nderungen in einem neuen Fenster." +msgid "Edit Error: someone else has edited this %s (%s). View their changes in a new window." +msgstr "Fehler: Jemand anders hat dieses %s bearbeitet (%s). Sehen Sie dessen ??nderungen in einem neuen Fenster." -#: ../roundup/cgi/actions.py:530 +#: ../roundup/cgi/actions.py:607 #, python-format msgid "Edit Error: %s" msgstr "Fehler bei der Bearbeitung: %s" # ../roundup/cgi/actions.py:546 :556 -#: ../roundup/cgi/actions.py:561 ../roundup/cgi/actions.py:572 -#: ../roundup/cgi/actions.py:743 ../roundup/cgi/actions.py:762 +#: ../roundup/cgi/actions.py:642 +#: ../roundup/cgi/actions.py:658 +#: ../roundup/cgi/actions.py:828 +#: ../roundup/cgi/actions.py:847 +#: ../roundup/cgi/actions.py:642:658 +#: :828:847 #, python-format msgid "Error: %s" msgstr "Fehler: %s" -#: ../roundup/cgi/actions.py:598 +#: ../roundup/cgi/actions.py:684 msgid "" "Invalid One Time Key!\n" -"(a Mozilla bug may cause this message to show up erroneously, please check " -"your email)" +"(a Mozilla bug may cause this message to show up erroneously, please check your email)" msgstr "" -"Ung?ltiger Authentifizierungscode!\n" -"(Ein Fehler in Mozilla kann diese Meldung hervorrufen, bitte pr?fen Sie Ihr " -"Email-Konto)" +"Ung??ltiger Authentifizierungscode!\n" +"(Ein Fehler in Mozilla kann diese Meldung hervorrufen, bitte pr??fen Sie Ihr E-Mail-Konto)" -#: ../roundup/cgi/actions.py:640 +#: ../roundup/cgi/actions.py:726 #, python-format msgid "Password reset and email sent to %s" -msgstr "Ihr Pa?wort wurde zur?ckgesetzt und per Email an %s versandt" +msgstr "Ihr Passwort wurde zur??ckgesetzt und per E-Mail an %s versandt" -#: ../roundup/cgi/actions.py:649 +#: ../roundup/cgi/actions.py:735 msgid "Unknown username" msgstr "Benutzername unbekannt" -#: ../roundup/cgi/actions.py:657 +#: ../roundup/cgi/actions.py:743 msgid "Unknown email address" -msgstr "Email-Adresse unbekannt" +msgstr "E-Mail-Adresse unbekannt" -#: ../roundup/cgi/actions.py:662 +#: ../roundup/cgi/actions.py:748 msgid "You need to specify a username or address" -msgstr "Sie m?ssen einen Benutzernamen oder eine Email-Adresse angeben" +msgstr "Sie m??ssen einen Benutzernamen oder eine E-Mail-Adresse angeben" -#: ../roundup/cgi/actions.py:687 +#: ../roundup/cgi/actions.py:773 #, python-format msgid "Email sent to %s" -msgstr "Eine Email wurde an %s versandt" +msgstr "Eine E-Mail wurde an %s versandt" -#: ../roundup/cgi/actions.py:706 +#: ../roundup/cgi/actions.py:787 msgid "You are now registered, welcome!" msgstr "Sie sind nun registriert. Willkommen!" -#: ../roundup/cgi/actions.py:751 +#: ../roundup/cgi/actions.py:836 msgid "It is not permitted to supply roles at registration." -msgstr "Bei der Registrierung d?rfen keine Rollen angegeben werden" +msgstr "Bei der Registrierung d??rfen keine Rollen angegeben werden" -#: ../roundup/cgi/actions.py:834 +#: ../roundup/cgi/actions.py:923 msgid "You are logged out" msgstr "Sie wurden vom System abgemeldet" -#: ../roundup/cgi/actions.py:845 +#: ../roundup/cgi/actions.py:944 msgid "Username required" msgstr "Benutzername notwendig" -#: ../roundup/cgi/actions.py:873 ../roundup/cgi/actions.py:877 +#: ../roundup/cgi/actions.py:978 +#: ../roundup/cgi/actions.py:982 +#: ../roundup/cgi/actions.py:978:982 msgid "Invalid login" -msgstr "Ung?ltiger Benutzername" +msgstr "Ung??ltiger Benutzername" -#: ../roundup/cgi/actions.py:883 +#: ../roundup/cgi/actions.py:988 msgid "You do not have permission to login" msgstr "Sie sind nicht berechtigt, sich anzumelden" +#: ../roundup/cgi/actions.py:1047 +#, python-format +msgid "You do not have permission to view %(class)s" +msgstr "Sie sind nicht berechtigt, Eintr??ge der Klasse \"%(class)s\" zu lesen" + #: ../roundup/cgi/cgitb.py:49 #, python-format msgid "" @@ -1298,7 +1460,7 @@ "
\n" msgstr "" "\n" -"
  • Beim Ausf?hren von %(info)r auf Zeile %(line)d\n" +"
  • Beim Ausf??hren von %(info)r auf Zeile %(line)d\n" "\n" " \n" " %(globals)s\n" @@ -1307,7 +1469,7 @@ #: ../roundup/cgi/cgitb.py:103 msgid "Full traceback:" -msgstr "Vollst?ndiger Traceback:" +msgstr "Vollst??ndiger Traceback:" #: ../roundup/cgi/cgitb.py:116 #, python-format @@ -1315,19 +1477,12 @@ msgstr "%(exc_type)s: %(exc_value)s" #: ../roundup/cgi/cgitb.py:120 -msgid "" -"

    A problem occurred while running a Python script. Here is the sequence of " -"function calls leading up to the error, with the most recent (innermost) " -"call first. The exception attributes are:" -msgstr "" -"

    Ein Problem trat auf, als ein Python-Script ausgef?hrt wurde. Hier sehen " -"Sie die Aufrufe, welche zu dem Fehler f?hrten. Der letzte (innerste) Aufruf erscheint " -"dabei zuoberst. Der Fehler hat folgende Attribute: " +msgid "

    A problem occurred while running a Python script. Here is the sequence of function calls leading up to the error, with the most recent (innermost) call first. The exception attributes are:" +msgstr "

    Ein Problem trat auf, als ein Python-Script ausgef??hrt wurde. Hier sehen Sie die Aufrufe, welche zu dem Fehler f??hrten. Der letzte (innerste) Aufruf erscheint dabei zuoberst. Der Fehler hat folgende Attribute: " #: ../roundup/cgi/cgitb.py:129 msgid "<file is None - probably inside eval or exec>" -msgstr "<file ist None - Wahrscheinlich in einem eval oder einem " -"exec>" +msgstr "<file ist None - Wahrscheinlich in einem eval oder einem exec>" #: ../roundup/cgi/cgitb.py:138 #, python-format @@ -1335,361 +1490,460 @@ msgstr "in %s" # ../roundup/cgi/cgitb.py:145 :151 -#: ../roundup/cgi/cgitb.py:172 ../roundup/cgi/cgitb.py:178 +#: ../roundup/cgi/cgitb.py:172 +#: ../roundup/cgi/cgitb.py:178 +#: ../roundup/cgi/cgitb.py:172:178 msgid "undefined" msgstr "nicht definiert" -#: ../roundup/cgi/client.py:49 -msgid "" -"Ein Fehler ist aufgetreten\n" -"

    Ein Fehler ist aufgetreten

    \n" -"

    Bei der Bearbeitung Ihrer Daten ist ein Fehler aufgetreten. " -"Die Admistratoren wurden benachrichtigt.

    \n" -"" -msgstr "" - -#: ../roundup/cgi/client.py:291 +#: ../roundup/cgi/client.py:517 msgid "Form Error: " msgstr "Formular-Fehler: " -#: ../roundup/cgi/client.py:344 +#: ../roundup/cgi/client.py:575 #, python-format msgid "Unrecognized charset: %r" msgstr "Zeichensatz nicht erkannt: %r" -#: ../roundup/cgi/client.py:446 +#: ../roundup/cgi/client.py:696 msgid "Anonymous users are not allowed to use the web interface" -msgstr "" -"Gast-Benutzer sind nicht berechtigt, das Web-Interface zu benutzen." +msgstr "Gast-Benutzer sind nicht berechtigt, das Web-Interface zu benutzen." -#: ../roundup/cgi/client.py:597 +#: ../roundup/cgi/client.py:851 msgid "You are not allowed to view this file." msgstr "Sie sind nicht berechtigt, diese Seite anzuzeigen." -#: ../roundup/cgi/client.py:689 +#: ../roundup/cgi/client.py:968 #, python-format msgid "%(starttag)sTime elapsed: %(seconds)fs%(endtag)s\n" -msgstr "%(starttag)sBen?tigte Zeit: %(seconds)fs%(endtag)s\n" +msgstr "%(starttag)sBen??tigte Zeit: %(seconds)fs%(endtag)s\n" -#: ../roundup/cgi/client.py:693 +#: ../roundup/cgi/client.py:972 #, python-format -msgid "" -"%(starttag)sCache hits: %(cache_hits)d, misses %(cache_misses)d. Loading " -"items: %(get_items)f secs. Filtering: %(filtering)f secs.%(endtag)s\n" -msgstr "" -"%(starttag)sCache benutzt: %(cache_hits)d, verfehlt: %(cache_misses)d. " -"Eintr?ge laden: %(get_items)fs; filtern: %(filtering)fs.%(endtag)s\n" +msgid "%(starttag)sCache hits: %(cache_hits)d, misses %(cache_misses)d. Loading items: %(get_items)f secs. Filtering: %(filtering)f secs.%(endtag)s\n" +msgstr "%(starttag)sCache benutzt: %(cache_hits)d, verfehlt: %(cache_misses)d. Eintr??ge laden: %(get_items)fs; filtern: %(filtering)fs.%(endtag)s\n" #: ../roundup/cgi/form_parser.py:283 #, python-format -msgid "link \"%(key)s\" value \"%(value)s\" not a designator" -msgstr "" -"Der Wert \"%(value)s\" ist kein g?ltiger Bezeichner f?r die Verkn?pfung \"%" -"(key)s\"" +msgid "link \"%(key)s\" value \"%(entry)s\" not a designator" +msgstr "Der Wert \"%(entry)s\" ist kein g??ltiger Bezeichner f??r die Verkn??pfung \"%(key)s\"" -#: ../roundup/cgi/form_parser.py:290 +#: ../roundup/cgi/form_parser.py:301 #, python-format msgid "%(class)s %(property)s is not a link or multilink property" msgstr "%(class)s %(property)s ist weder ein Link noch ein Mehrfachlink" -#: ../roundup/cgi/form_parser.py:312 +#: ../roundup/cgi/form_parser.py:313 #, python-format -msgid "" -"You have submitted a %(action)s action for the property \"%(property)s\" " -"which doesn't exist" -msgstr "Die Aktion %(action)s gilt nicht f?r die Eigenschaft \"%(property)s\" " +msgid "The form action claims to require property \"%(property)s\" which doesn't exist" +msgstr "Die Aktion erfordert die fehlende Angabe \"%(property)s\"" + +#: ../roundup/cgi/form_parser.py:335 +#, python-format +msgid "You have submitted a %(action)s action for the property \"%(property)s\" which doesn't exist" +msgstr "Die Aktion %(action)s gilt nicht f??r die Eigenschaft \"%(property)s\" " # ../roundup/cgi/form_parser.py:331 :357 -#: ../roundup/cgi/form_parser.py:331 ../roundup/cgi/form_parser.py:357 +#: ../roundup/cgi/form_parser.py:354 +#: ../roundup/cgi/form_parser.py:380 +#: ../roundup/cgi/form_parser.py:354:380 #, python-format msgid "You have submitted more than one value for the %s property" -msgstr "Sie haben mehr als einen Wert f?r die Eigenschaft \"%s\" ?bermittelt" +msgstr "Sie haben mehr als einen Wert f??r die Eigenschaft \"%s\" ??bermittelt" # ../roundup/cgi/form_parser.py:354 :360 -#: ../roundup/cgi/form_parser.py:354 ../roundup/cgi/form_parser.py:360 +#: ../roundup/cgi/form_parser.py:377 +#: ../roundup/cgi/form_parser.py:383 +#: ../roundup/cgi/form_parser.py:377:383 msgid "Password and confirmation text do not match" -msgstr "Die beiden Pa?wort-Felder stimmen nicht ?berein" +msgstr "Die beiden Passwortfelder stimmen nicht ??berein" -#: ../roundup/cgi/form_parser.py:395 +#: ../roundup/cgi/form_parser.py:418 #, python-format msgid "property \"%(propname)s\": \"%(value)s\" not currently in list" -msgstr "Der Wert \"%(value)s\" ist nicht in der Liste f?r \"%(propname)s\"" +msgstr "Der Wert \"%(value)s\" ist nicht in der Liste f??r \"%(propname)s\"" -#: ../roundup/cgi/form_parser.py:509 +#: ../roundup/cgi/form_parser.py:557 #, python-format msgid "Required %(class)s property %(property)s not supplied" msgid_plural "Required %(class)s properties %(property)s not supplied" -msgstr[0] "" -"Die Eigenschaft \"%(property)s\" mu? f?r die Klasse \"%(class)s\" angegeben " -"werden" -msgstr[1] "" -"Die Eigenschaften \"%(property)\" m?ssen f?r die Klasse \"%(class)s\" " -"angegeben werden" +msgstr[0] "Die Eigenschaft \"%(property)s\" muss f??r die Klasse \"%(class)s\" angegeben werden" +msgstr[1] "Die Eigenschaften \"%(property)s\" m??ssen f??r die Klasse \"%(class)s\" angegeben werden" -#: ../roundup/cgi/form_parser.py:529 +#: ../roundup/cgi/form_parser.py:580 msgid "File is empty" -msgstr "Die ausgew?hlte Datei ist leer" +msgstr "Die ausgew??hlte Datei ist leer" -#: ../roundup/cgi/templating.py:68 +#: ../roundup/cgi/templating.py:77 #, python-format msgid "You are not allowed to %(action)s items of class %(class)s" -msgstr "" -"Sie sind nicht berechtigt, die Aktion \"%(action)s\" auf Eintr?ge der " -"Klasse \"%(class)s\" anzuwenden" +msgstr "Sie sind nicht berechtigt, die Aktion \"%(action)s\" auf Eintr??ge der Klasse \"%(class)s\" anzuwenden" -#: ../roundup/cgi/templating.py:612 +#: ../roundup/cgi/templating.py:664 msgid "(list)" msgstr "(Liste)" -#: ../roundup/cgi/templating.py:646 +#: ../roundup/cgi/templating.py:733 msgid "Submit New Entry" msgstr "Eintrag speichern" -#: ../roundup/cgi/templating.py:656 +#: ../roundup/cgi/templating.py:747 +#: ../roundup/cgi/templating.py:886 +#: ../roundup/cgi/templating.py:1358 +#: ../roundup/cgi/templating.py:1387 +#: ../roundup/cgi/templating.py:1407 +#: ../roundup/cgi/templating.py:1420 +#: ../roundup/cgi/templating.py:1471 +#: ../roundup/cgi/templating.py:1494 +#: ../roundup/cgi/templating.py:1530 +#: ../roundup/cgi/templating.py:1567 +#: ../roundup/cgi/templating.py:1620 +#: ../roundup/cgi/templating.py:1637 +#: ../roundup/cgi/templating.py:1721 +#: ../roundup/cgi/templating.py:1741 +#: ../roundup/cgi/templating.py:1759 +#: ../roundup/cgi/templating.py:1791 +#: ../roundup/cgi/templating.py:1801 +#: ../roundup/cgi/templating.py:1853 +#: ../roundup/cgi/templating.py:2069 +#: ../roundup/cgi/templating.py:747:886 +#: :1358:1387 +#: :1407:1420 +#: :1471:1494 +#: :1530:1567 +#: :1620:1637 +#: :1721:1741 +#: :1759:1791 +#: :1801:1853 +#: :2069 +msgid "[hidden]" +msgstr "[verborgen]" + +#: ../roundup/cgi/templating.py:748 msgid "New node - no history" msgstr "Neuer Eintrag - Noch kein Verlauf" -#: ../roundup/cgi/templating.py:756 +#: ../roundup/cgi/templating.py:868 msgid "Submit Changes" msgstr "Speichern" -#: ../roundup/cgi/templating.py:837 +#: ../roundup/cgi/templating.py:950 msgid "The indicated property no longer exists" -msgstr "Die gew?hlte Eigenschaft existiert nicht mehr" +msgstr "Die gew??hlte Eigenschaft existiert nicht mehr" -#: ../roundup/cgi/templating.py:838 +#: ../roundup/cgi/templating.py:951 #, python-format msgid "%s: %s\n" msgstr "%s: %s\n" -#: ../roundup/cgi/templating.py:851 +#: ../roundup/cgi/templating.py:964 #, python-format msgid "The linked class %(classname)s no longer exists" msgstr "Die verlinkte Klasse \"%(classname)s\" existiert nicht mehr" # ../roundup/cgi/templating.py:905 :926 -#: ../roundup/cgi/templating.py:884 ../roundup/cgi/templating.py:905 +#: ../roundup/cgi/templating.py:998 +#: ../roundup/cgi/templating.py:1023 +#: ../roundup/cgi/templating.py:998:1023 msgid "The linked node no longer exists" -msgstr "Der verkn?pfte Eintrag existiert nicht mehr" +msgstr "Der verkn??pfte Eintrag existiert nicht mehr" -#: ../roundup/cgi/templating.py:944 -msgid "No" -msgstr "Nein" - -#: ../roundup/cgi/templating.py:944 -msgid "Yes" -msgstr "Ja" - -#: ../roundup/cgi/templating.py:955 +#: ../roundup/cgi/templating.py:1077 #, python-format msgid "%s: (no value)" msgstr "%s: (kein Wert)" -#: ../roundup/cgi/templating.py:967 -msgid "" -"This event is not handled by the history display!" -msgstr "" -"Dieses Ereignis kann nicht im Verlauf angezeigt werden!" +#: ../roundup/cgi/templating.py:1089 +msgid "This event is not handled by the history display!" +msgstr "Dieses Ereignis kann nicht im Verlauf angezeigt werden!" -#: ../roundup/cgi/templating.py:979 +#: ../roundup/cgi/templating.py:1101 msgid "" -msgstr "" +msgstr "" -#: ../roundup/cgi/templating.py:988 +#: ../roundup/cgi/templating.py:1110 msgid "History" msgstr "Verlauf" -#: ../roundup/cgi/templating.py:990 +#: ../roundup/cgi/templating.py:1112 msgid "" msgstr "" -#: ../roundup/cgi/templating.py:991 +#: ../roundup/cgi/templating.py:1113 msgid "" msgstr "" -#: ../roundup/cgi/templating.py:992 +#: ../roundup/cgi/templating.py:1114 msgid "" msgstr "" -#: ../roundup/cgi/templating.py:993 +#: ../roundup/cgi/templating.py:1115 msgid "" msgstr "" -#: ../roundup/cgi/templating.py:1097 +#: ../roundup/cgi/templating.py:1160 #, python-format msgid "Copy of %(class)s %(id)s" -msgstr "" -"Kopie von %(class)s %(id)s" +msgstr "Kopie von %(class)s %(id)s" -#: ../roundup/cgi/templating.py:1234 +#: ../roundup/cgi/templating.py:1498 msgid "*encrypted*" -msgstr "*verschl?sselt*" +msgstr "*verschl??sselt*" -#: ../roundup/cgi/templating.py:1412 -msgid "" -"default value for DateHTMLProperty must be either DateHTMLProperty or string " -"date representation." +#: ../roundup/cgi/templating.py:1571 +#: ../roundup/cgi/templating.py:1592 +#: ../roundup/cgi/templating.py:1598 +#: ../roundup/cgi/templating.py:1066:1571 +#: :1592:1598 +msgid "No" +msgstr "Nein" + +#: ../roundup/cgi/templating.py:1571 +#: ../roundup/cgi/templating.py:1590 +#: ../roundup/cgi/templating.py:1595 +#: ../roundup/cgi/templating.py:1066:1571 +#: :1590:1595 +msgid "Yes" +msgstr "Ja" + +#: ../roundup/cgi/templating.py:1684 +msgid "default value for DateHTMLProperty must be either DateHTMLProperty or string date representation." msgstr "" -"Der voreingestellte Wert einer DateHTML-Eigenschaft mu? entweder ein\n" -"DateHTML-Objekt sein oder ein Datum repr?sentieren." +"Der voreingestellte Wert einer DateHTML-Eigenschaft muss entweder ein\n" +"DateHTML-Objekt sein oder ein Datum repr??sentieren." -#: ../roundup/cgi/templating.py:1674 +#: ../roundup/cgi/templating.py:1844 #, python-format msgid "Attempt to look up %(attr)s on a missing value" -msgstr "" -"Versuch, das Attribut %(attr)s eines nicht vorhandenen Werts abzufragen" +msgstr "Versuch, das Attribut %(attr)s eines nicht vorhandenen Werts abzufragen" -#: ../roundup/cgi/templating.py:1750 -#: ../roundup/cgi/templating.py:1600 +#: ../roundup/cgi/templating.py:1929 #, python-format msgid "" -msgstr "" +msgstr "" -#: ../roundup/date.py:180 -#, python-format -msgid "Not a date spec: %s" -msgstr "Kein g?ltiges Datum: %s" +#: ../roundup/date.py:292 +msgid "Not a date spec: \"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", \"HH:MM:SS\" or \"yyyy-mm-dd.HH:MM:SS.SSS\"" +msgstr "Kein g??ltiges Datum: \"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", \"HH:MM:SS\" oder \"yyyy-mm-dd.HH:MM:SS.SSS\"" -#: ../roundup/date.py:186 -msgid "" -"Kein g?ltiges Datum: \"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", \"HH:MM:SS\" oder \"yyyy-" -"mm-dd.HH:MM:SS.SSS\"" -msgstr "" +#: ../roundup/date.py:315 +msgid "Could not determine granularity" +msgstr "Konnte K??rnigkeit nicht ermitteln" -#: ../roundup/date.py:231 +#: ../roundup/date.py:365 #, python-format -msgid "%r not a date spec (%s)" -msgstr "%r ist kein g?ltiges Datum (%s)" +msgid "%r not a date / time spec \"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", \"HH:MM:SS\" or \"yyyy-mm-dd.HH:MM:SS.SSS\"" +msgstr "%r ist keine Datums- oder Zeitangabe (\"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", \"HH:MM:SS\" oder \"yyyy-mm-dd.HH:MM:SS.SSS\")" -#: ../roundup/date.py:522 -msgid "" -"Not an interval spec:" -" [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS] [date spec]" -msgstr "" -"Keine g?ltige Intervall-Angabe:" -" [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS] [Datum]" +#: ../roundup/date.py:677 +msgid "Not an interval spec: [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS] [date spec]" +msgstr "Keine g??ltige Intervall-Angabe: [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS] [Datum]" -#: ../roundup/date.py:541 -msgid "Not an interval spec:" -" [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS]" -msgstr "" -"Keine g?ltige Intervall-Angabe:" -" [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS]" +#: ../roundup/date.py:699 +msgid "Not an interval spec: [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS]" +msgstr "Keine g??ltige Intervall-Angabe: [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS]" -#: ../roundup/date.py:678 +#: ../roundup/date.py:836 #, python-format msgid "%(number)s year" msgid_plural "%(number)s years" msgstr[0] "%(number)s Jahr" msgstr[1] "%(number)s Jahren" -#: ../roundup/date.py:682 +#: ../roundup/date.py:840 #, python-format msgid "%(number)s month" msgid_plural "%(number)s months" msgstr[0] "%(number)s Monat" msgstr[1] "%(number)s Monaten" -#: ../roundup/date.py:686 +#: ../roundup/date.py:844 #, python-format msgid "%(number)s week" msgid_plural "%(number)s weeks" msgstr[0] "%(number)s Woche" msgstr[1] "%(number)s Wochen" -#: ../roundup/date.py:690 +#: ../roundup/date.py:848 #, python-format msgid "%(number)s day" msgid_plural "%(number)s days" msgstr[0] "%(number)s Tag" msgstr[1] "%(number)s Tagen" -#: ../roundup/date.py:694 +#: ../roundup/date.py:852 msgid "tomorrow" msgstr "morgen" -#: ../roundup/date.py:696 +#: ../roundup/date.py:854 msgid "yesterday" msgstr "gestern" -#: ../roundup/date.py:699 +#: ../roundup/date.py:857 #, python-format msgid "%(number)s hour" msgid_plural "%(number)s hours" msgstr[0] "%(number)s Stunde" msgstr[1] "%(number)s Stunden" -#: ../roundup/date.py:703 +#: ../roundup/date.py:861 msgid "an hour" msgstr "eine Stunde" -#: ../roundup/date.py:705 +#: ../roundup/date.py:863 msgid "1 1/2 hours" msgstr "1 1/2 Stunden" -#: ../roundup/date.py:707 +#: ../roundup/date.py:865 #, python-format msgid "1 %(number)s/4 hours" msgid_plural "1 %(number)s/4 hours" -msgstr[0] "1 %(number)s/4 Stunden" +msgstr[0] "1 %(number)s/4 Stunde" msgstr[1] "1 %(number)s/4 Stunden" -#: ../roundup/date.py:711 +#: ../roundup/date.py:869 msgid "in a moment" -msgstr "in K?rze" +msgstr "in K??rze" -#: ../roundup/date.py:713 +#: ../roundup/date.py:871 msgid "just now" msgstr "soeben" -#: ../roundup/date.py:716 +#: ../roundup/date.py:874 msgid "1 minute" msgstr "1 Minute" -#: ../roundup/date.py:719 +#: ../roundup/date.py:877 #, python-format msgid "%(number)s minute" msgid_plural "%(number)s minutes" msgstr[0] "%(number)s Minute" msgstr[1] "%(number)s Minuten" -#: ../roundup/date.py:722 +#: ../roundup/date.py:880 msgid "1/2 an hour" msgstr "1/2 Stunde" -#: ../roundup/date.py:724 +#: ../roundup/date.py:882 #, python-format msgid "%(number)s/4 hour" msgid_plural "%(number)s/4 hours" -msgstr[0] "%(number)s/4 Stunden" +msgstr[0] "%(number)s/4 Stunde" msgstr[1] "%(number)s/4 Stunden" -#: ../roundup/date.py:728 +#: ../roundup/date.py:886 #, python-format msgid "%s ago" msgstr "vor %s" -#: ../roundup/date.py:730 +#: ../roundup/date.py:888 #, python-format msgid "in %s" msgstr "in %s" -#: ../roundup/init.py:132 +#: ../roundup/hyperdb.py:91 +#, python-format +msgid "property %s: %s" +msgstr "Eigenschaft %s: %s" + +#: ../roundup/hyperdb.py:111 +#, python-format +msgid "property %s: %r is an invalid date (%s)" +msgstr "Eigenschaft %s: %r ist kein g??ltiges Datum (%s)" + +#: ../roundup/hyperdb.py:128 +#, python-format +msgid "property %s: %r is an invalid date interval (%s)" +msgstr "Eigenschaft %s: %r ist kein g??ltiges Datumsintervall (%s)" + +#: ../roundup/hyperdb.py:223 +#, python-format +msgid "property %s: %r is not currently an element" +msgstr "Eigenschaft %s: %r ist derzeit kein Element" + +#: ../roundup/hyperdb.py:267 +#, python-format +msgid "property %s: %r is not a number" +msgstr "Eigenschaft %s: %r ist keine Zahl" + +#: ../roundup/hyperdb.py:280 +#, python-format +msgid "\"%s\" not a node designator" +msgstr "\"%s\" ist kein g??ltiger Bezeichner" + +#: ../roundup/hyperdb.py:953 +#: ../roundup/hyperdb.py:961 +#: ../roundup/hyperdb.py:953:961 +#, python-format +msgid "Not a property name: %s" +msgstr "Keine Eigenschaft: %s" + +#: ../roundup/hyperdb.py:1244 +#, python-format +msgid "property %s: %r is not a %s." +msgstr "Eigenschaft %s: %r ist kein %s." + +#: ../roundup/hyperdb.py:1247 +#, python-format +msgid "you may only enter ID values for property %s" +msgstr "Sie k??nnen f??r die Eigenschaft %s nur IDs eingeben" + +#: ../roundup/hyperdb.py:1277 +#, python-format +msgid "%r is not a property of %s" +msgstr "%r ist keine Eigenschaft von %s" + +#: ../roundup/init.py:136 #, python-format msgid "" "WARNING: directory '%s'\n" "\tcontains old-style template - ignored" msgstr "" "WARNUNG: Das Verzeichnis '%s'\n" -"\tenth?lt Templates im alten Format, die ignoriert werden." +"\tenth??lt Templates im alten Format, die ignoriert werden." + +#: ../roundup/mailgw.py:201 +#: ../roundup/mailgw.py:213 +#: ../roundup/mailgw.py:201:213 +#, python-format +msgid "Message signed with unknown key: %s" +msgstr "Nachricht signiert mit unbekanntem Schl??ssel: %s" + +#: ../roundup/mailgw.py:204 +#, python-format +msgid "Message signed with an expired key: %s" +msgstr "Nachricht signiert mit abgelaufenem Schl??ssel: %s" + +#: ../roundup/mailgw.py:207 +#, python-format +msgid "Message signed with a revoked key: %s" +msgstr "Nachricht signiert mit zur??ckgezogenem Schl??ssel: %s" -#: ../roundup/mailgw.py:586 +#: ../roundup/mailgw.py:210 +msgid "Invalid PGP signature detected." +msgstr "Ung??ltige PGP-Signatur festgestellt." + +#: ../roundup/mailgw.py:464 +msgid "Unknown multipart/encrypted version." +msgstr "Unbekannte Version von multipart/encrypted." + +#: ../roundup/mailgw.py:473 +msgid "Unable to decrypt your message." +msgstr "Kann Ihre Nachricht nicht entschl??sseln" + +#: ../roundup/mailgw.py:502 +msgid "No PGP signature found in message." +msgstr "Keine PGP-Signatur in Nachricht gefunden" + +#: ../roundup/mailgw.py:812 msgid "" "\n" "Emails to Roundup trackers must include a Subject: line!\n" msgstr "" +"\n" +"Mails an Roundup m??ssen eine Subject-Zeile haben (Betreff)!\n" -#: ../roundup/mailgw.py:674 +#: ../roundup/mailgw.py:936 #, python-format msgid "" "\n" @@ -1705,31 +1959,83 @@ "\n" "Subject was: '%(subject)s'\n" msgstr "" +"\n" +"Ihre Nachricht an Roundup enthielt keine g??ltige Betreffzeile (subject).\n" +"Der Betreff mu?? einen Klassennamen oder Bezeichner enthalten, um\n" +"anzuzeigen, worum es geht. Zum Beispiel:\n" +" Betreff: [issue] Ein neues Thema\n" +" - dadurch wird ein neuer issue-Eintrag mit dem Titel\n" +" 'Ein neues Thema' angelegt\n" +" Betreff: [issue1234] Vorhandenes Thema 1234\n" +" - dadurch wird dem vorhandenen 'issue' mit der Nummer 1234\n" +" eine neue Nachricht hinzugef??gt\n" +"\n" +"Der Betreff war: '%(subject)s'\n" -#: ../roundup/mailgw.py:705 +#: ../roundup/mailgw.py:974 #, python-format msgid "" "\n" -"The class name you identified in the subject line (\"%(classname)s\") does " -"not exist in the\n" -"database.\n" +"The class name you identified in the subject line (\"%(classname)s\") does\n" +"not exist in the database.\n" "\n" "Valid class names are: %(validname)s\n" "Subject was: \"%(subject)s\"\n" msgstr "" +"\n" +"Der von Ihnen in der Betreffzeile angegebene Klassenname (\"%(classname)s\")existiert in der Datenbank nicht.\n" +"G??ltige Klassen sind: %(validname)s\n" +"Die Betreffzeile war: \"%(subject)s\"\n" + +#: ../roundup/mailgw.py:982 +#, python-format +msgid "" +"\n" +"You did not identify a class name in the subject line and there is no\n" +"default set for this tracker. The subject must contain a class name or\n" +"designator to indicate the 'topic' of the message. For example:\n" +" Subject: [issue] This is a new issue\n" +" - this will create a new issue in the tracker with the title 'This is\n" +" a new issue'.\n" +" Subject: [issue1234] This is a followup to issue 1234\n" +" - this will append the message's contents to the existing issue 1234\n" +" in the tracker.\n" +"\n" +"Subject was: '%(subject)s'\n" +msgstr "" +"\n" +"Sie haben in der Betreffzeile keinen Klassennamen angegeben, und es ist f??r\n" +"diesen Tracker kein Standardwert gesetzt. Die Betreffzeile mu?? eine Klasse\n" +"oder einen Bezeichner des Gegenstands Ihrer Nachricht enthalten;\n" +"zum Beispiel:\n" +" Subject: [issue] Dies ist ein neues Issue\n" +" - dies erzeugt ein neues Issue im Tracker mit dem Titel 'Dies\n" +" ist ein neues Issue'.\n" +" Subject: [issue1234] Dies bezieht sich auf Issue 1234\n" +" - f??gt den Inhalt der Nachricht dem existierenden Issue 1234 hinzu\n" +"\n" +"Die Betreffzeile (Subject) war:\n" +" '%(subject)s'\n" -#: ../roundup/mailgw.py:733 +#: ../roundup/mailgw.py:1023 #, python-format msgid "" "\n" "I cannot match your message to a node in the database - you need to either\n" -"supply a full designator (with number, eg \"[issue123]\" or keep the\n" +"supply a full designator (with number, eg \"[issue123]\") or keep the\n" "previous subject title intact so I can match that.\n" "\n" "Subject was: \"%(subject)s\"\n" msgstr "" +"\n" +"Ich kann Ihre Nachricht keinem Eintrag in der Datenbank zuordnen - Sie m??ssen\n" +"entweder einen vollen Bezeichner angeben (mit Nummer, z. B. \"[issue123]\")\n" +"oder die Betreffzeile intakt lassen, so da?? ich diese zuordnen kann.\n" +"\n" +"Die Betreffzeile (Subject) war:\n" +" '%(subject)s'\n" -#: ../roundup/mailgw.py:766 +#: ../roundup/mailgw.py:1056 #, python-format msgid "" "\n" @@ -1738,8 +2044,14 @@ "\n" "Subject was: \"%(subject)s\"\n" msgstr "" +"\n" +"Der in der Betreffzeile Ihre Nachricht bezeichnete Eintrag\n" +"(\"%(nodeid)s\") existiert nicht.\n" +"\n" +"Die Betreffzeile (Subject) war:\n" +" '%(subject)s'\n" -#: ../roundup/mailgw.py:794 +#: ../roundup/mailgw.py:1084 #, python-format msgid "" "\n" @@ -1747,8 +2059,12 @@ "%(mailadmin)s and have them fix the incorrect class specified as:\n" " %(current_class)s\n" msgstr "" +"\n" +"Das Mail-Gateway ist nicht korrekt eingerichtet. Bitte wenden\n" +"Sie sich an %(mailadmin)s und bitten Sie um Korrektur der\n" +"fehlerhaften Klasse: %(current_class)s\n" -#: ../roundup/mailgw.py:817 +#: ../roundup/mailgw.py:1107 #, python-format msgid "" "\n" @@ -1756,31 +2072,39 @@ "%(mailadmin)s and have them fix the incorrect properties:\n" " %(errors)s\n" msgstr "" +"\n" +"Das Mail-Gateway ist nicht korrekt eingerichtet. Bitte wenden\n" +"Sie sich an %(mailadmin)s und bitten Sie um Korrektur der\n" +"fehlerhaften Eigenschaften: %(errors)s\n" -#: ../roundup/mailgw.py:847 +#: ../roundup/mailgw.py:1147 #, python-format msgid "" "\n" -"You are not a registered user.\n" +"You are not a registered user.%(registration_info)s\n" "\n" "Unknown address: %(from_address)s\n" msgstr "" +"\n" +"Sie sind kein registrierter Anwender.%(registration_info)s\n" +"\n" +"Unbekannte Adresse: %(from_address)s\n" -#: ../roundup/mailgw.py:855 +#: ../roundup/mailgw.py:1155 msgid "You are not permitted to access this tracker." -msgstr "" +msgstr "Sie haben keinen Zugriff auf diesen Tracker." -#: ../roundup/mailgw.py:862 +#: ../roundup/mailgw.py:1162 #, python-format msgid "You are not permitted to edit %(classname)s." -msgstr "" +msgstr "Sie sind nicht berechtigt, die Klasse \"%(classname)s\" zu bearbeiten" -#: ../roundup/mailgw.py:866 +#: ../roundup/mailgw.py:1166 #, python-format msgid "You are not permitted to create %(classname)s." -msgstr "" +msgstr "Sie sind nicht berechtigt, ein \"%(classname)s\" zu erzeugen" -#: ../roundup/mailgw.py:913 +#: ../roundup/mailgw.py:1213 #, python-format msgid "" "\n" @@ -1789,135 +2113,183 @@ "\n" "Subject was: \"%(subject)s\"\n" msgstr "" +"\n" +"Es sind Probleme aufgetreten bei der Verarbeitung Ihrer Betreffzeile:\n" +"- %(errors)s\n" +"\n" +"Die Betreffzeile war: \"%(subject)s\"\n" -#: ../roundup/mailgw.py:942 +#: ../roundup/mailgw.py:1266 +msgid "" +"\n" +"This tracker has been configured to require all email be PGP signed or\n" +"encrypted." +msgstr "" +"\n" +"Dieser Tracker wurde konfiguriert, Email-Nachrichten nur PGP-signiert oder\n" +"verschl??sselt entgegenzunehmen." + +#: ../roundup/mailgw.py:1273 msgid "" "\n" "Roundup requires the submission to be plain text. The message parser could\n" "not find a text/plain part to use.\n" msgstr "" +"\n" +"Dieser Tracker akzeptiert nur einfache Textnachrichten. Der Mail-Parser konnte\n" +"keinen entsprechenden Teil (\"text/plain\") finden.\n" -#: ../roundup/mailgw.py:964 +#: ../roundup/mailgw.py:1290 msgid "You are not permitted to create files." -msgstr "" +msgstr "Sie sind nicht berechtigt, Dateien zu erzeugen." -#: ../roundup/mailgw.py:978 +#: ../roundup/mailgw.py:1304 #, python-format msgid "You are not permitted to add files to %(classname)s." -msgstr "" +msgstr "Sie sind nicht berechtigt, Dateien zu %(classname)s hinzuzuf??gen." -#: ../roundup/mailgw.py:996 +#: ../roundup/mailgw.py:1322 msgid "You are not permitted to create messages." -msgstr "" +msgstr "Sie sind nicht berechtigt, Nachrichten zu erzeugen" -#: ../roundup/mailgw.py:1004 +#: ../roundup/mailgw.py:1330 #, python-format msgid "" "\n" "Mail message was rejected by a detector.\n" "%(error)s\n" msgstr "" +"\n" +"Die Mail-Nachricht wurde von einem Detektor zur??ckgewiesen.\n" +"%(error)s\n" -#: ../roundup/mailgw.py:1012 +#: ../roundup/mailgw.py:1338 #, python-format msgid "You are not permitted to add messages to %(classname)s." -msgstr "" +msgstr "Sie sind nicht berechtigt, Kommentare zu %(classname)s hinzuzuf??gen." -#: ../roundup/mailgw.py:1039 +#: ../roundup/mailgw.py:1365 #, python-format msgid "You are not permitted to edit property %(prop)s of class %(classname)s." msgstr "" +"Sie sind nicht berechtigt, die Eigenschaft %(prop)s der Klasse %(classname)s\n" +"zu bearbeiten." -#: ../roundup/mailgw.py:1047 +#: ../roundup/mailgw.py:1374 #, python-format msgid "" "\n" "There was a problem with the message you sent:\n" " %(message)s\n" msgstr "" +"\n" +"Es gab ein Problem mit Ihrer Nachricht:\n" +" %(message)s\n" -#: ../roundup/mailgw.py:1069 +#: ../roundup/mailgw.py:1396 msgid "not of form [arg=value,value,...;arg=value,value,...]" -msgstr "" +msgstr "entspricht nicht der Form [arg=wert,wert,...;arg=wert,wert,...]" -#: ../roundup/roundupdb.py:142 +#: ../roundup/roundupdb.py:174 msgid "files" msgstr "Dateien" -#: ../roundup/roundupdb.py:141 +#: ../roundup/roundupdb.py:174 msgid "messages" msgstr "Kommentare" -#: ../roundup/roundupdb.py:141 +#: ../roundup/roundupdb.py:174 msgid "nosy" msgstr "Interessenten" -#: ../roundup/roundupdb.py:141 +#: ../roundup/roundupdb.py:174 msgid "superseder" msgstr "ersetzt durch" -#: ../roundup/roundupdb.py:141 +#: ../roundup/roundupdb.py:174 msgid "title" msgstr "Titel" -#: ../roundup/roundupdb.py:142 +#: ../roundup/roundupdb.py:175 msgid "assignedto" msgstr "zugewiesen" -#: ../roundup/roundupdb.py:142 +#: ../roundup/roundupdb.py:175 +msgid "keyword" +msgstr "Schlagwort" + +#: ../roundup/roundupdb.py:175 msgid "priority" -msgstr "Priori?t" +msgstr "Priori??t" -#: ../roundup/roundupdb.py:142 +#: ../roundup/roundupdb.py:175 msgid "status" msgstr "Status" -#: ../roundup/roundupdb.py:142 -msgid "topic" -msgstr "Schlagwort" -# siehe die Anmerkung zu "Schlagwort" - -#: ../roundup/roundupdb.py:145 +#: ../roundup/roundupdb.py:178 msgid "activity" -msgstr "Aktivit?t" +msgstr "Aktivit??t" #. following properties are common for all hyperdb classes #. they are listed here to keep things in one place -#: ../roundup/roundupdb.py:145 +#: ../roundup/roundupdb.py:178 msgid "actor" msgstr "Akteur" -#: ../roundup/roundupdb.py:145 +#: ../roundup/roundupdb.py:178 msgid "creation" msgstr "Erstellungsdatum" -#: ../roundup/roundupdb.py:145 +#: ../roundup/roundupdb.py:178 msgid "creator" msgstr "Ersteller" -#: ../roundup/roundupdb.py:304 +#: ../roundup/roundupdb.py:335 #, python-format msgid "New submission from %(authname)s%(authaddr)s:" -msgstr "" +msgstr "Neue Nachricht von %(authname)s%(authaddr)s:" -#: ../roundup/roundupdb.py:307 +#: ../roundup/roundupdb.py:338 #, python-format msgid "%(authname)s%(authaddr)s added the comment:" msgstr "%(authname)s%(authaddr)s merkte an:" -#: ../roundup/roundupdb.py:310 -msgid "System message:" -msgstr "System-Nachricht:" +#: ../roundup/roundupdb.py:341 +#, python-format +msgid "Change by %(authname)s%(authaddr)s:" +msgstr "??nderung von %(authname)s%(authaddr)s:" + +#: ../roundup/roundupdb.py:361 +#, python-format +msgid "File '%(filename)s' not attached - you can download it from %(link)s." +msgstr "" +"Die Datei '%(filename)s' ist nicht beigef??gt - Sie k??nnen Sie unter\n" +"%(link)s herunterladen." + +#: ../roundup/roundupdb.py:661 +#, python-format +msgid "" +"\n" +"Now:\n" +"%(new)s\n" +"Was:\n" +"%(old)s" +msgstr "" +"\n" +"Jetzt:\n" +"%(new)s\n" +"Vorher:\n" +"%(old)s" #: ../roundup/scripts/roundup_demo.py:32 #, python-format msgid "Enter directory path to create demo tracker [%s]: " -msgstr "Verzeichnis f?r Tracker-Demo eingeben [%s]: " +msgstr "Verzeichnis f??r Tracker-Demo eingeben [%s]: " #: ../roundup/scripts/roundup_gettext.py:22 #, python-format msgid "Usage: %(program)s " -msgstr "Verwendung: %(program)s " +msgstr "Verwendung: %(program)s " #: ../roundup/scripts/roundup_gettext.py:37 #, python-format @@ -1927,8 +2299,7 @@ #: ../roundup/scripts/roundup_mailgw.py:36 #, python-format msgid "" -"Usage: %(program)s [-v] [-c] [[-C class] -S field=value]* " -"[method]\n" +"Usage: %(program)s [-v] [-c class] [[-C class] -S field=value]* [method]\n" "\n" "Options:\n" " -v: print version and exit\n" @@ -1962,16 +2333,26 @@ " specified as:\n" " mailbox /path/to/mailbox\n" "\n" +"In all of the following the username and password can be stored in a\n" +"~/.netrc file. In this case only the server name need be specified on\n" +"the command-line.\n" +"\n" +"The username and/or password will be prompted for if not supplied on\n" +"the command-line or in ~/.netrc.\n" +"\n" "POP:\n" " In the third case, the gateway reads all messages from the POP server\n" " specified and submits each in turn to the roundup.mailgw module. The\n" " server is specified as:\n" " pop username:password at server\n" -" The username and password may be omitted:\n" +" Alternatively, one can omit one or both of username and password:\n" " pop username at server\n" " pop server\n" -" are both valid. The username and/or password will be prompted for if\n" -" not supplied on the command-line.\n" +" are both valid.\n" +"\n" +"POPS:\n" +" Connect to a POP server over ssl. This requires python 2.4 or later.\n" +" This supports the same notation as POP.\n" "\n" "APOP:\n" " Same as POP, but using Authenticated POP:\n" @@ -1991,8 +2372,7 @@ " imaps username:password at server [mailbox]\n" "\n" msgstr "" -"Verwendung: %(program)s [-v] [[-C Klasse] -S Eigenschaft=Wert]* [Methode]\n" +"Verwendung: %(program)s [-v] [[-C Klasse] -S Eigenschaft=Wert]* [Methode]\n" "\n" "Optionen:\n" " -v: Versionsnummer ausgeben und beenden\n" @@ -2006,74 +2386,78 @@ " . mit einem Tracker-Verzeichnis und einem IMAP/IMAPS-Konto.\n" "\n" "Optional kann mit -C die Klasse des zu erstellenden Eintrags spezifiziert \n" -"werden. Zudem k?nnen Sie mit -S oder --set Eigenschaften der Eintr?ge\n" +"werden. Zudem k??nnen Sie mit -S oder --set Eigenschaften der Eintr??ge\n" "als Eigenschaft=Wert[;Eigenschaft=Wert]* setzen, analog zum Roundup-\n" -"Kommandozeilen Programm, resp. zur Syntax in der Betreffszeile einer Email.\n" +"Kommandozeilen Programm, resp. zur Syntax in der Betreffszeile einer E-Mail.\n" "Voreingestellt ist die Klasse \"msg\", aber auch Klassen wie \"issue\",\n" -"\"user\" oder \"file\" k?nnen verwendet werden.\n" +"\"user\" oder \"file\" k??nnen verwendet werden.\n" "\n" -"Sie k?nnen dadurch mehrere Email-Konten f?r einen Tracker verwenden und\n" +"Sie k??nnen dadurch mehrere E-Mail-Konten f??r einen Tracker verwenden und\n" "unterschiedliche Eintragstypen aus den Nachrichten erstellen.\n" "\n" "PIPE:\n" " Das Mail-Gateway liest eine Nachricht von der Standardeingabe und\n" -" ?bergibt sie an das Modul roundup.mailgw.\n" +" ??bergibt sie an das Modul roundup.mailgw.\n" "\n" -"UNIX Mailbox:\n" +"UNIX-Mailbox:\n" " Die angegebene Mailbox-Datei wird ausgelesen, und alle Nachrichten werden\n" -" an das Modul roundup.mailgw ?bergeben. Nach erfolgreicher Verarbeitung \n" +" an das Modul roundup.mailgw ??bergeben. Nach erfolgreicher Verarbeitung \n" " wird die Mail-Spooldatei geleert.\n" -" Die Mailbox-Datei wird folgenderma?en angegeben: mailbox /pfad/zur/" -"mailbox\n" +" Die Mailbox-Datei wird folgenderma??en angegeben: mailbox /pfad/zur/mailbox\n" "\n" "POP:\n" " Das Gateway liest alle Nachrichten vom POP3-Konto und leitet sie weiter an \n" " das Modul roundup.mailgw. \n" -" Das Konto wird folgenderma?en angegeben:\n" -" pop benutzername:pa?wort at server\n" -" Benutzername und Pa?wort k?nnen weggelassen werden:\n" +" Das Konto wird folgenderma??en angegeben:\n" +" pop benutzername:passwort at server\n" +" Benutzername und Passwort k??nnen weggelassen werden:\n" " pop benutzername at server\n" " pop server\n" " In diesem Fall werden die Anmeldungs-Daten zur Laufzeit erfragt.\n" "\n" +"POPS:\n" +" Mit einem POP3-Server ??ber SSL verbinden; dies erfordert Python 2.4 oder\n" +" neuer. Argumente wie bei POP.\n" +"\n" "APOP:\n" " Wie POP, aber unter Verwendung von authentifiziertem POP:\n" -" apop benutzername:pa?wort at server\n" +" apop benutzername:passwort at server\n" "\n" "IMAP:\n" " Verbindung mit einem IMAP-Server. Die Syntax entspricht der POP-\n" " Spezifikation:\n" -" imap benutzername:pa?wort at server\n" +" imap benutzername:passwort at server\n" " Um eine andere Mailbox anstelle von \"INBOX\" zu verwenden, benutzen Sie:\n" -" imap benutzername:pa?wort at server mailbox\n" +" imap benutzername:passwort at server mailbox\n" "\n" "IMAPS:\n" -" Verbindung zu einem IMAP-Server ?ber eine sichere SSL-Verbindung.\n" +" Verbindung zu einem IMAP-Server ??ber eine sichere SSL-Verbindung.\n" " Die Syntax entspricht der IMAP-Spezifikation:\n" -" imaps benutzername:pa?wort at server [mailbox]\n" +" imaps benutzername:passwort at server [mailbox]\n" "\n" -#: ../roundup/scripts/roundup_mailgw.py:147 +#: ../roundup/scripts/roundup_mailgw.py:157 msgid "Error: not enough source specification information" -msgstr "Sie haben nicht gen?gend Angaben zur Mail-Quelle gemacht" +msgstr "Sie haben nicht gen??gend Angaben zur E-Mail-Quelle gemacht" -#: ../roundup/scripts/roundup_mailgw.py:157 -msgid "Error: pop specification not valid" -msgstr "Fehler: pop Optionen ung?ltig" +#: ../roundup/scripts/roundup_mailgw.py:186 +#, python-format +msgid "Error: %s specification not valid" +msgstr "Fehler: %s-Optionen ung??ltig" -#: ../roundup/scripts/roundup_mailgw.py:164 -msgid "Error: apop specification not valid" -msgstr "Fehler: apop Optionen ung?ltig" +#: ../roundup/scripts/roundup_mailgw.py:192 +msgid "Error: a later version of python is required" +msgstr "Fehler: eine neuere Python-Version wird ben??tigt" -#: ../roundup/scripts/roundup_mailgw.py:178 -msgid "" -"Error: The source must be either \"mailbox\", \"pop\", \"apop\", \"imap\" or " -"\"imaps\"" -msgstr "" -"Fehler: Als Mail-Quelle mu? \"mailbox\", \"pop\", \"apop\", \"imap\" oder " -"\"imaps\" gew?hlt werden" +#: ../roundup/scripts/roundup_mailgw.py:203 +msgid "Error: The source must be either \"mailbox\", \"pop\", \"pops\", \"apop\", \"imap\" or \"imaps\"" +msgstr "Fehler: Als E-Mail-Quelle muss \"mailbox\", \"pop\", \"pops\", \"apop\", \"imap\" oder \"imaps\" gew??hlt werden" -#: ../roundup/scripts/roundup_server.py:140 +#: ../roundup/scripts/roundup_server.py:76 +msgid "WARNING: generating temporary SSL certificate" +msgstr "WARNUNG: erzeuge tempor??res SSL-Zertifikat" + +#: ../roundup/scripts/roundup_server.py:253 msgid "" "Roundup trackers index\n" "

    Roundup trackers index

      \n" @@ -2081,55 +2465,52 @@ "Roundup Tracker-Liste\n" "

      Roundup Tracker-Liste

        \n" -#: ../roundup/scripts/roundup_server.py:242 +#: ../roundup/scripts/roundup_server.py:389 #, python-format msgid "Error: %s: %s" msgstr "Fehler: %s: %s" -#: ../roundup/scripts/roundup_server.py:252 +#: ../roundup/scripts/roundup_server.py:399 msgid "WARNING: ignoring \"-g\" argument, not root" -msgstr "" -"WARNUNG: die Option \"-g\" wird ignoriert, da Sie nicht Administrator sind" +msgstr "WARNUNG: die Option \"-g\" wird ignoriert, da Sie nicht Administrator sind" -#: ../roundup/scripts/roundup_server.py:258 +#: ../roundup/scripts/roundup_server.py:405 msgid "Can't change groups - no grp module" msgstr "Die Gruppe kann nicht gewechselt werden - das Modul grp fehlt" -#: ../roundup/scripts/roundup_server.py:267 +#: ../roundup/scripts/roundup_server.py:414 #, python-format msgid "Group %(group)s doesn't exist" msgstr "Die Gruppe %(group)s existiert nicht" -#: ../roundup/scripts/roundup_server.py:278 +#: ../roundup/scripts/roundup_server.py:425 msgid "Can't run as root!" -msgstr "Dieser Proze? kann nicht unter dem Administrator-Konto (\"root\") laufen!" +msgstr "Dieser Prozess kann nicht unter dem Administrator-Konto (\"root\") laufen!" -#: ../roundup/scripts/roundup_server.py:281 +#: ../roundup/scripts/roundup_server.py:428 msgid "WARNING: ignoring \"-u\" argument, not root" -msgstr "" -"WARNUNG: die Option \"-u\" wird ignoriert, da Sie nicht Administrator sind" +msgstr "WARNUNG: die Option \"-u\" wird ignoriert, da Sie nicht Administrator sind" -#: ../roundup/scripts/roundup_server.py:286 +#: ../roundup/scripts/roundup_server.py:434 msgid "Can't change users - no pwd module" msgstr "Der Benutzer kann nicht gewechselt werden - das Modul pwd fehlt" -#: ../roundup/scripts/roundup_server.py:295 +#: ../roundup/scripts/roundup_server.py:443 #, python-format msgid "User %(user)s doesn't exist" msgstr "Der Benutzer %(user)s existiert nicht" -#: ../roundup/scripts/roundup_server.py:417 +#: ../roundup/scripts/roundup_server.py:592 #, python-format msgid "Multiprocess mode \"%s\" is not available, switching to single-process" -msgstr "Der Multiproze?-Modus \"%s\" ist nicht verf?gbar, Einproze?-Modus" -"aktiviert" +msgstr "Der Multiprozessmodus \"%s\" ist nicht verf??gbar, Einprozessmodus aktiviert" -#: ../roundup/scripts/roundup_server.py:440 +#: ../roundup/scripts/roundup_server.py:620 #, python-format msgid "Unable to bind to port %s, port already in use." msgstr "Start des Servers auf Port %s schlug fehl. Port bereits verwendet." -#: ../roundup/scripts/roundup_server.py:507 +#: ../roundup/scripts/roundup_server.py:688 msgid "" " -c Windows Service options.\n" " If you want to run the server as a Windows Service, you\n" @@ -2142,10 +2523,10 @@ " Um den Roundup-Server als Windows Service zu starten,\n" " benutzen Sie eine Server-Konfiguration, in der die Tracker-\n" " Instanzen angegeben werden.\n" -" Zudem m?ssen Sie die Logfile-Option aktivieren.\n" +" Zudem m??ssen Sie die Logfile-Option aktivieren.\n" " \"roundup-server -c help\" zeigt eine weitere Hilfe zum Thema." -#: ../roundup/scripts/roundup_server.py:514 +#: ../roundup/scripts/roundup_server.py:695 msgid "" " -u runs the Roundup web server as this UID\n" " -g runs the Roundup web server as this GID\n" @@ -2153,13 +2534,13 @@ " to the file indicated by PIDfile. The -l option *must* be\n" " specified if -d is used." msgstr "" -" -u Startet den Roundup-Server mit dieser Benutzer-Nummer\n" -" -g Startet den Roundup-Server mit dieser Gruppen-Nummer\n" -" -d Startet den Server als Hintergrundproze? und schreibt\n" -" die Proze?-ID in die Datei PIDDatei.\n" -" Die Option -l mu? dann auch angegeben werden." +" -u Startet den Roundup-Server mit dieser Benutzernummer\n" +" -g Startet den Roundup-Server mit dieser Gruppennummer\n" +" -d Startet den Server als Hintergrundprozess und schreibt\n" +" die Prozess-ID in die Datei PIDDatei.\n" +" Die Option -l muss dann auch angegeben werden." -#: ../roundup/scripts/roundup_server.py:521 +#: ../roundup/scripts/roundup_server.py:702 #, python-format msgid "" "%(message)sUsage: roundup-server [options] [name=tracker home]*\n" @@ -2172,8 +2553,10 @@ " -n set the host name of the Roundup web server instance\n" " -p set the port to listen on (default: %(port)s)\n" " -l log to the file indicated by fname instead of stderr/stdout\n" -" -N log client machine names instead of IP addresses (much " -"slower)\n" +" -N log client machine names instead of IP addresses (much slower)\n" +" -i set tracker index template\n" +" -s enable SSL\n" +" -e PEM file containing SSL key and certificate\n" " -t multiprocess mode (default: %(mp_def)s).\n" " Allowed values: %(mp_types)s.\n" "%(os_part)s\n" @@ -2213,8 +2596,7 @@ " pairs on the command-line. Make sure the name part doesn't include\n" " any url-unsafe characters like spaces, as these confuse IE.\n" msgstr "" -"%(message)s" -"Benutzung: roundup-server [Optionen] [Tracker-Name=Tracker-Verzeichnis]*\n" +"%(message)sBenutzung: roundup-server [Optionen] [Tracker-Name=Tracker-Verzeichnis]*\n" "\n" "Optionen:\n" " -v Versionsnummer ausgeben und beenden\n" @@ -2224,9 +2606,9 @@ " -n Hostnamen des Serverprozesses bestimmen\n" " -p Port bestimmen (Voreinstellung: %(port)s)\n" " -l Logdatei bestimmen (anstelle \"stderr\" / \"stdout\")\n" -" -N Domainnamen in der Logdatei aufl?sen (viel langsamer)\n" -" -t Multiproze?-Modus (Voreinstellung: %(mp_def)s).\n" -" Verf?gbare Modi: %(mp_types)s.\n" +" -N Domainnamen in der Logdatei aufl??sen (viel langsamer)\n" +" -t Multiprozessmodus (Voreinstellung: %(mp_def)s).\n" +" Verf??gbare Modi: %(mp_types)s.\n" "%(os_part)s\n" "\n" "Lange Optionen:\n" @@ -2234,7 +2616,7 @@ " --help Diese Hilfe ausgeben und beenden\n" " --save-config Konfiguration erstellen oder aktualiseren und beenden\n" " --config Konfiguration verwenden\n" -" Die Einstellungen in der Sektion [main] der Konfigurationsdatei k?nnen Sie\n" +" Die Einstellungen in der Sektion [main] der Konfigurationsdatei k??nnen Sie\n" " auch in der Form --= angegeben.\n" "\n" "Beispiele:\n" @@ -2253,51 +2635,50 @@ "Konfigurations-Format:\n" " Roundup Server benutzt das standardisierte .ini Format.\n" " Konfigurationen, welche mit 'roundup-server -S' erstellt werden, \n" -" enthalten detaillierte Erkl?rungen zu jeder Option. Bitte konsultieren\n" -" Sie diese Datei f?r weitere Angaben.\n" +" enthalten detaillierte Erkl??rungen zu jeder Option. Bitte konsultieren\n" +" Sie diese Datei f??r weitere Angaben.\n" "\n" "Tracker-Name=Tracker-Verzeichnis:\n" " Gibt an, welche Tracker-Instanz(en) verwendet werden. Der Tracker-Name\n" " bestimmt den URL-Pfad im Web. Das Tracker-Verzeichnis gibt an, in \n" " welchem Verzeichnis die Tracker-Konfiguration gespeichert wurde.\n" -" Sie k?nnen mehrere Tracker-Instanzen auf der Kommandozeile angeben oder\n" +" Sie k??nnen mehrere Tracker-Instanzen auf der Kommandozeile angeben oder\n" " alternativ die Variable TRACKER_HOME in der roundup-server Datei \n" " anpassen. \n" " ACHTUNG: Der Tracker-Name darf keine Sonderzeichen enthalten, welche in \n" -" URLs Probleme bereiten k?nnten. Am besten verwenden Sie nur Buchstaben, \n" +" URLs Probleme bereiten k??nnten. Am besten verwenden Sie nur Buchstaben, \n" " Zahlen und \"-_\".\n" -#: ../roundup/scripts/roundup_server.py:669 +#: ../roundup/scripts/roundup_server.py:860 msgid "Instances must be name=home" -msgstr "Instanzen m?ssen als Tracker-Name=Tracker-Verzeichnis angegeben werden" +msgstr "Instanzen m??ssen als Tracker-Name=Tracker-Verzeichnis angegeben werden" -#: ../roundup/scripts/roundup_server.py:683 +#: ../roundup/scripts/roundup_server.py:874 #, python-format msgid "Configuration saved to %s" msgstr "Konfiguration in der Datei %s gespeichert" -#: ../roundup/scripts/roundup_server.py:694 +#: ../roundup/scripts/roundup_server.py:892 msgid "Sorry, you can't run the server as a daemon on this Operating System" -msgstr "" -"Auf diesem Betriebssystem kann der Server nicht als Hintergrundproze? laufen" +msgstr "Auf diesem Betriebssystem kann der Server nicht als Hintergrundprozess laufen" -#: ../roundup/scripts/roundup_server.py:706 +#: ../roundup/scripts/roundup_server.py:907 #, python-format msgid "Roundup server started on %(HOST)s:%(PORT)s" msgstr "Der Roundup-Server wurde unter %(HOST)s:%(PORT)s gestartet" -#: ../templates/classic/html/_generic.collision.html:4 -#: ../templates/minimal/html/_generic.collision.html:4 +#: ../share/roundup/templates/classic/html/_generic.collision.html:4 +#: ../share/roundup/templates/minimal/html/_generic.collision.html:4 msgid "${class} Edit Collision - ${tracker}" msgstr "Kollision bei der Bearbeitung - ${tracker}" -#: ../templates/classic/html/_generic.collision.html:7 -#: ../templates/minimal/html/_generic.collision.html:7 +#: ../share/roundup/templates/classic/html/_generic.collision.html:7 +#: ../share/roundup/templates/minimal/html/_generic.collision.html:7 msgid "${class} Edit Collision" msgstr "Kollision bei der Bearbeitung" -#: ../templates/classic/html/_generic.collision.html:14 -#: ../templates/minimal/html/_generic.collision.html:14 +#: ../share/roundup/templates/classic/html/_generic.collision.html:14 +#: ../share/roundup/templates/minimal/html/_generic.collision.html:14 msgid "" "\n" " There has been a collision. Another user updated this node\n" @@ -2305,1107 +2686,1114 @@ " the node and review your edits.\n" msgstr "" "\n" -" Eine Kollision wurde festgestellt. W?hrend Ihrer Bearbeitung\n" -" hat ein anderer Benutzer diesen Eintrag aktualisiert. Bitte laden Sie diese Seite neu \n" -" und f?gen Sie Ihre ?nderungen erneut ein.\n" - -#: ../templates/classic/html/_generic.help.html:9 -#: ../templates/minimal/html/_generic.help.html:9 -msgid "${property} help - ${tracker}" -msgstr "Hilfe zu \"${property}\" - ${tracker}" +" Eine Kollision wurde festgestellt. W??hrend Ihrer Bearbeitung\n" +" hat ein anderer Benutzer diesen Eintrag aktualisiert. Bitte laden Sie diese Seite neu \n" +" und f??gen Sie Ihre ??nderungen erneut ein.\n" + +#: ../share/roundup/templates/classic/html/_generic.help-empty.html:6 +msgid "Please specify your search parameters!" +msgstr "Bitte geben Sie Ihre Suchparameter an!" + +#: ../share/roundup/templates/classic/html/_generic.help-list.html:20 +#: ../share/roundup/templates/classic/html/_generic.index.html:14 +#: ../share/roundup/templates/classic/html/_generic.item.html:12 +#: ../share/roundup/templates/classic/html/file.item.html:9 +#: ../share/roundup/templates/classic/html/issue.index.html:16 +#: ../share/roundup/templates/classic/html/issue.item.html:28 +#: ../share/roundup/templates/classic/html/msg.item.html:26 +#: ../share/roundup/templates/classic/html/user.index.html:9 +#: ../share/roundup/templates/classic/html/user.item.html:35 +#: ../share/roundup/templates/minimal/html/_generic.index.html:14 +#: ../share/roundup/templates/minimal/html/_generic.item.html:12 +#: ../share/roundup/templates/minimal/html/user.index.html:9 +#: ../share/roundup/templates/minimal/html/user.item.html:35 +#: ../share/roundup/templates/minimal/html/user.register.html:14 +msgid "You are not allowed to view this page." +msgstr "Sie sind nicht berechtigt, diese Seite anzuzeigen." -#: ../templates/classic/html/_generic.help.html:30 -#: ../templates/minimal/html/_generic.help.html:30 +#: ../share/roundup/templates/classic/html/_generic.help-list.html:34 +msgid "1..25 out of 50" +msgstr "1..25 von 50" + +#: ../share/roundup/templates/classic/html/_generic.help-search.html:9 +msgid "Generic template ${template} or version for class ${classname} is not yet implemented" +msgstr "Die generische Vorlage ${template} bzw. die Version f??r die Klasse ${classname} ist noch nicht implementiert" + +#: ../share/roundup/templates/classic/html/_generic.help-submit.html:57 +#: ../share/roundup/templates/classic/html/_generic.help.html:31 +#: ../share/roundup/templates/minimal/html/_generic.help.html:31 msgid " Cancel " msgstr " Abbrechen " -#: ../templates/classic/html/_generic.help.html:33 -#: ../templates/minimal/html/_generic.help.html:33 +#: ../share/roundup/templates/classic/html/_generic.help-submit.html:63 +#: ../share/roundup/templates/classic/html/_generic.help.html:34 +#: ../share/roundup/templates/minimal/html/_generic.help.html:34 msgid " Apply " msgstr " Anwenden " -#: ../templates/classic/html/_generic.help.html:40 -#: ../templates/classic/html/issue.index.html:67 -#: ../templates/minimal/html/_generic.help.html:40 +#: ../share/roundup/templates/classic/html/_generic.help.html:9 +#: ../share/roundup/templates/classic/html/user.help.html:13 +#: ../share/roundup/templates/minimal/html/_generic.help.html:9 +msgid "${property} help - ${tracker}" +msgstr "Hilfe zu \"${property}\" - ${tracker}" + +#: ../share/roundup/templates/classic/html/_generic.help.html:41 +#: ../share/roundup/templates/classic/html/help.html:21 +#: ../share/roundup/templates/classic/html/issue.index.html:81 +#: ../share/roundup/templates/minimal/html/_generic.help.html:41 msgid "<< previous" -msgstr "<< zur?ck" +msgstr "<< zur??ck" -#: ../templates/classic/html/_generic.help.html:50 -#: ../templates/classic/html/issue.index.html:75 -#: ../templates/minimal/html/_generic.help.html:50 +#: ../share/roundup/templates/classic/html/_generic.help.html:53 +#: ../share/roundup/templates/classic/html/help.html:28 +#: ../share/roundup/templates/classic/html/issue.index.html:89 +#: ../share/roundup/templates/minimal/html/_generic.help.html:53 msgid "${start}..${end} out of ${total}" msgstr "${start}..${end} von ${total}" -#: ../templates/classic/html/_generic.help.html:54 -#: ../templates/classic/html/issue.index.html:78 -#: ../templates/minimal/html/_generic.help.html:54 +#: ../share/roundup/templates/classic/html/_generic.help.html:57 +#: ../share/roundup/templates/classic/html/help.html:32 +#: ../share/roundup/templates/classic/html/issue.index.html:92 +#: ../share/roundup/templates/minimal/html/_generic.help.html:57 msgid "next >>" msgstr "weiter >>" -#: ../templates/classic/html/_generic.index.html:6 -#: ../templates/classic/html/_generic.item.html:4 -#: ../templates/minimal/html/_generic.index.html:6 -#: ../templates/minimal/html/_generic.item.html:4 +#: ../share/roundup/templates/classic/html/_generic.index.html:6 +#: ../share/roundup/templates/classic/html/_generic.item.html:4 +#: ../share/roundup/templates/minimal/html/_generic.index.html:6 +#: ../share/roundup/templates/minimal/html/_generic.item.html:4 msgid "${class} editing - ${tracker}" msgstr "Klasse bearbeiten - ${tracker}" -#: ../templates/classic/html/_generic.index.html:9 -#: ../templates/classic/html/_generic.item.html:7 -#: ../templates/minimal/html/_generic.index.html:9 -#: ../templates/minimal/html/_generic.item.html:7 +#: ../share/roundup/templates/classic/html/_generic.index.html:9 +#: ../share/roundup/templates/classic/html/_generic.item.html:7 +#: ../share/roundup/templates/minimal/html/_generic.index.html:9 +#: ../share/roundup/templates/minimal/html/_generic.item.html:7 msgid "${class} editing" msgstr "\"${class}\" bearbeiten" -#: ../templates/classic/html/_generic.index.html:14 -#: ../templates/classic/html/_generic.item.html:12 -#: ../templates/classic/html/file.item.html:9 -#: ../templates/classic/html/issue.index.html:16 -#: ../templates/classic/html/issue.item.html:28 -#: ../templates/classic/html/msg.item.html:26 -#: ../templates/classic/html/user.index.html:9 -#: ../templates/classic/html/user.item.html:28 -#: ../templates/minimal/html/_generic.index.html:14 -#: ../templates/minimal/html/_generic.item.html:12 -#: ../templates/minimal/html/user.index.html:9 -#: ../templates/minimal/html/user.item.html:18 -#: ../templates/minimal/html/user.register.html:14 -msgid "You are not allowed to view this page." -msgstr "Sie sind nicht berechtigt, diese Seite anzuzeigen." - -#: ../templates/classic/html/_generic.index.html:22 -#: ../templates/minimal/html/_generic.index.html:22 -msgid "" -"

        You may edit the contents of the ${classname} class " -"using this form. Commas, newlines and double quotes (\") must be handled " -"delicately. You may include commas and newlines by enclosing the values in " -"double-quotes (\"). Double quotes themselves must be quoted by doubling " -"(\"\").

        Multilink properties have their " -"multiple values colon (\":\") separated (... ,\"one:two:three\", ...)

        " -"

        Remove entries by deleting their line. Add new " -"entries by appending them to the table - put an X in the id column.

        " -msgstr "" -"

        Sie k?nnen hier die Eintr?ge der Klasse \"${classname}\" " -"bearbeiten. Hinweise:

        " -"
          " -"
        • Kommata, Zeilenumbr?che und " -"Anf?hrungszeichen (\") mit Vorsicht verwenden:" -"
          • Kommata und Zeilenumbr?che " -"d?rfen nur in Anf?hrungszeichen (\") verwendet werden." -"
          • Um Anf?hrungszeichen in " -"Werten zu verwenden, m?ssen sie verdoppelt werden (\"\")
          " -"
        • Mehrfachlinks werden durch Doppelpunkt (:) getrennt " -"(... ,\"eins:zwei:drei\", ...)" -"
        • Eintr?ge k?nnen " -"gel?scht werden, indem Sie Zeilen entfernen." -"
        • F?r neue Eintr?ge f?gen Sie Zeilen ein; " -"geben Sie bei der ID-Spalte ein gro?es X an.

        " +#: ../share/roundup/templates/classic/html/_generic.index.html:19 +#: ../share/roundup/templates/classic/html/_generic.item.html:16 +#: ../share/roundup/templates/classic/html/file.item.html:13 +#: ../share/roundup/templates/classic/html/issue.index.html:20 +#: ../share/roundup/templates/classic/html/issue.item.html:32 +#: ../share/roundup/templates/classic/html/msg.item.html:30 +#: ../share/roundup/templates/classic/html/user.index.html:13 +#: ../share/roundup/templates/classic/html/user.item.html:39 +#: ../share/roundup/templates/minimal/html/_generic.index.html:19 +#: ../share/roundup/templates/minimal/html/_generic.item.html:17 +#: ../share/roundup/templates/minimal/html/user.index.html:13 +#: ../share/roundup/templates/minimal/html/user.item.html:39 +#: ../share/roundup/templates/minimal/html/user.register.html:17 +msgid "Please login with your username and password." +msgstr "Bitte melden Sie sich an mit Ihrem Benutzernamen und Pa??wort" + +#: ../share/roundup/templates/classic/html/_generic.index.html:28 +#: ../share/roundup/templates/minimal/html/_generic.index.html:28 +msgid "

        You may edit the contents of the ${classname} class using this form. Commas, newlines and double quotes (\") must be handled delicately. You may include commas and newlines by enclosing the values in double-quotes (\"). Double quotes themselves must be quoted by doubling (\"\").

        Multilink properties have their multiple values colon (\":\") separated (... ,\"one:two:three\", ...)

        Remove entries by deleting their line. Add new entries by appending them to the table - put an X in the id column.

        " +msgstr "

        Sie k??nnen hier die Eintr??ge der Klasse \"${classname}\" bearbeiten. Hinweise:

        • Kommata, Zeilenumbr??che und Anf??hrungszeichen (\") mit Vorsicht verwenden:
          • Kommata und Zeilenumbr??che d??rfen nur in Anf??hrungszeichen (\") verwendet werden.
          • Um Anf??hrungszeichen in Werten zu verwenden, m??ssen sie verdoppelt werden (\"\")
        • Mehrfachlinks werden durch Doppelpunkt (:) getrennt (... ,\"eins:zwei:drei\", ...)
        • Eintr??ge k??nnen gel??scht werden, indem Sie Zeilen entfernen.
        • F??r neue Eintr??ge f??gen Sie Zeilen ein; geben Sie bei der ID-Spalte ein gro??es X an.

        " -#: ../templates/classic/html/_generic.index.html:44 -#: ../templates/minimal/html/_generic.index.html:44 +#: ../share/roundup/templates/classic/html/_generic.index.html:50 +#: ../share/roundup/templates/minimal/html/_generic.index.html:50 msgid "Edit Items" -msgstr "Eintr?ge bearbeiten" +msgstr "Eintr??ge bearbeiten" -#: ../templates/classic/html/file.index.html:4 +#: ../share/roundup/templates/classic/html/file.index.html:4 msgid "List of files - ${tracker}" msgstr "Dateiliste - ${tracker}" -#: ../templates/classic/html/file.index.html:5 +#: ../share/roundup/templates/classic/html/file.index.html:5 msgid "List of files" msgstr "Dateiliste" -#: ../templates/classic/html/file.index.html:10 +#: ../share/roundup/templates/classic/html/file.index.html:10 msgid "Download" msgstr "Herunterladen" -#: ../templates/classic/html/file.index.html:11 -#: ../templates/classic/html/file.item.html:23 -#: ../templates/classic/html/file.item.html:51 +#: ../share/roundup/templates/classic/html/file.index.html:11 +#: ../share/roundup/templates/classic/html/file.item.html:27 msgid "Content Type" msgstr "Inhaltstyp" -#: ../templates/classic/html/file.index.html:12 +#: ../share/roundup/templates/classic/html/file.index.html:12 msgid "Uploaded By" msgstr "Hochgeladen von" -#: ../templates/classic/html/file.index.html:13 -#: ../templates/classic/html/msg.item.html:38 +#: ../share/roundup/templates/classic/html/file.index.html:13 +#: ../share/roundup/templates/classic/html/msg.item.html:48 msgid "Date" msgstr "Datum" -#: ../templates/classic/html/file.item.html:2 +#: ../share/roundup/templates/classic/html/file.item.html:2 msgid "File display - ${tracker}" msgstr "Datei anzeigen - ${tracker}" -#: ../templates/classic/html/file.item.html:4 +#: ../share/roundup/templates/classic/html/file.item.html:4 msgid "File display" msgstr "Datei anzeigen" -#: ../templates/classic/html/file.item.html:18 -#: ../templates/classic/html/user.item.html:39 -#: ../templates/classic/html/user.register.html:17 +#: ../share/roundup/templates/classic/html/file.item.html:23 +#: ../share/roundup/templates/classic/html/user.register.html:17 msgid "Name" msgstr "Name" -#: ../templates/classic/html/file.item.html:41 +#: ../share/roundup/templates/classic/html/file.item.html:45 msgid "download" msgstr "herunterladen" -#: ../templates/classic/html/home.classlist.html:2 -#: ../templates/minimal/html/home.classlist.html:2 +#: ../share/roundup/templates/classic/html/home.classlist.html:2 +#: ../share/roundup/templates/minimal/html/home.classlist.html:2 msgid "List of classes - ${tracker}" msgstr "Klassenliste - ${tracker}" -#: ../templates/classic/html/home.classlist.html:4 -#: ../templates/minimal/html/home.classlist.html:4 +#: ../share/roundup/templates/classic/html/home.classlist.html:4 +#: ../share/roundup/templates/minimal/html/home.classlist.html:4 msgid "List of classes" msgstr "Klassenliste" -#: ../templates/classic/html/issue.index.html:4 -msgid "List of issues - ${tracker}" -msgstr "Aufgabenliste - ${tracker}" - -#: ../templates/classic/html/issue.index.html:6 +#: ../share/roundup/templates/classic/html/issue.index.html:4 +#: ../share/roundup/templates/classic/html/issue.index.html:10 msgid "List of issues" msgstr "Aufgabenliste" -#: ../templates/classic/html/issue.index.html:6 -msgid "List of issues - ${query} - ${tracker}" -msgstr "Aufgabenliste - ${query} - ${tracker}" - -#: ../templates/classic/html/issue.index.html:6 -msgid "List of issues - ${query}" -msgstr "Aufgabenliste - ${query}" - -#: ../templates/classic/html/issue.index.html:17 -#: ../templates/classic/html/issue.item.html:38 +#: ../share/roundup/templates/classic/html/issue.index.html:27 +#: ../share/roundup/templates/classic/html/issue.item.html:49 msgid "Priority" -msgstr "Priorit?t" +msgstr "Priorit??t" -#: ../templates/classic/html/issue.index.html:18 +#: ../share/roundup/templates/classic/html/issue.index.html:28 msgid "ID" msgstr "ID" -#: ../templates/classic/html/issue.index.html:19 +#: ../share/roundup/templates/classic/html/issue.index.html:29 msgid "Creation" msgstr "Erstellungsdatum" -#: ../templates/classic/html/issue.index.html:20 +#: ../share/roundup/templates/classic/html/issue.index.html:30 msgid "Activity" -msgstr "Aktivit?t" +msgstr "Aktivit??t" -#: ../templates/classic/html/issue.index.html:21 +#: ../share/roundup/templates/classic/html/issue.index.html:31 msgid "Actor" msgstr "Akteur" -#: ../templates/classic/html/issue.index.html:22 -msgid "Topic" +#: ../share/roundup/templates/classic/html/issue.index.html:32 +#: ../share/roundup/templates/classic/html/keyword.item.html:37 +msgid "Keyword" msgstr "Schlagwort" -# Schlagwort <-> verschlagworten. Fachbegriff; besser als Stichwort oder Thema! -#: ../templates/classic/html/issue.index.html:23 -#: ../templates/classic/html/issue.item.html:33 +#: ../share/roundup/templates/classic/html/issue.index.html:33 +#: ../share/roundup/templates/classic/html/issue.item.html:44 msgid "Title" msgstr "Titel" -#: ../templates/classic/html/issue.index.html:24 -#: ../templates/classic/html/issue.item.html:40 +#: ../share/roundup/templates/classic/html/issue.index.html:34 +#: ../share/roundup/templates/classic/html/issue.item.html:51 msgid "Status" msgstr "Status" -#: ../templates/classic/html/issue.index.html:25 +#: ../share/roundup/templates/classic/html/issue.index.html:35 msgid "Creator" msgstr "Ersteller" -#: ../templates/classic/html/issue.index.html:26 +#: ../share/roundup/templates/classic/html/issue.index.html:36 msgid "Assigned To" msgstr "Zugewiesen" -#: ../templates/classic/html/issue.index.html:90 +#: ../share/roundup/templates/classic/html/issue.index.html:105 msgid "Download as CSV" msgstr "Als CSV-Datei herunterladen" -#: ../templates/classic/html/issue.index.html:98 +#: ../share/roundup/templates/classic/html/issue.index.html:115 msgid "Sort on:" msgstr "Sortieren:" -#: ../templates/classic/html/issue.index.html:101 -#: ../templates/classic/html/issue.index.html:118 +#: ../share/roundup/templates/classic/html/issue.index.html:119 +#: ../share/roundup/templates/classic/html/issue.index.html:140 msgid "- nothing -" msgstr "- nichts -" -#: ../templates/classic/html/issue.index.html:109 -#: ../templates/classic/html/issue.index.html:126 +#: ../share/roundup/templates/classic/html/issue.index.html:127 +#: ../share/roundup/templates/classic/html/issue.index.html:148 msgid "Descending:" msgstr "Absteigend:" -#: ../templates/classic/html/issue.index.html:115 +#: ../share/roundup/templates/classic/html/issue.index.html:136 msgid "Group on:" msgstr "Gruppieren:" -#: ../templates/classic/html/issue.index.html:132 +#: ../share/roundup/templates/classic/html/issue.index.html:155 msgid "Redisplay" msgstr "Aktualisieren" -#: ../templates/classic/html/issue.item.html:7 +#: ../share/roundup/templates/classic/html/issue.item.html:7 msgid "Issue ${id}: ${title} - ${tracker}" msgstr "Aufgabe ${id}: ${title} - ${tracker}" -#: ../templates/classic/html/issue.item.html:10 +#: ../share/roundup/templates/classic/html/issue.item.html:10 msgid "New Issue - ${tracker}" msgstr "Neue Aufgabe - ${tracker}" -#: ../templates/classic/html/issue.item.html:14 +#: ../share/roundup/templates/classic/html/issue.item.html:14 msgid "New Issue" msgstr "Neue Aufgabe" -#: ../templates/classic/html/issue.item.html:16 +#: ../share/roundup/templates/classic/html/issue.item.html:16 msgid "New Issue Editing" msgstr "Neue Aufgabe bearbeiten" -#: ../templates/classic/html/issue.item.html:19 +#: ../share/roundup/templates/classic/html/issue.item.html:19 msgid "Issue${id}" msgstr "Aufgabe${id}" -#: ../templates/classic/html/issue.item.html:22 +#: ../share/roundup/templates/classic/html/issue.item.html:22 msgid "Issue${id} Editing" msgstr "Aufgabe ${id} bearbeiten" -#: ../templates/classic/html/issue.item.html:45 +#: ../share/roundup/templates/classic/html/issue.item.html:56 msgid "Superseder" msgstr "Ersetzt durch" -#: ../templates/classic/html/issue.item.html:50 -msgid "View: ${link}" -msgstr "Anzeigen: ${link}" +#: ../share/roundup/templates/classic/html/issue.item.html:61 +msgid "View:" +msgstr "Anzeigen:" -#: ../templates/classic/html/issue.item.html:54 +#: ../share/roundup/templates/classic/html/issue.item.html:67 msgid "Nosy List" msgstr "Interessenten" -#: ../templates/classic/html/issue.item.html:63 +#: ../share/roundup/templates/classic/html/issue.item.html:76 msgid "Assigned To" msgstr "Zugewiesen" -#: ../templates/classic/html/issue.item.html:65 -msgid "Topics" -msgstr "Schlagw?rter" -# siehe die Anmerkung zu "Schlagwort" +#: ../share/roundup/templates/classic/html/issue.item.html:78 +#: ../share/roundup/templates/classic/html/page.html:103 +#: ../share/roundup/templates/minimal/html/page.html:102 +msgid "Keywords" +msgstr "Schlagw??rter" -#: ../templates/classic/html/issue.item.html:73 +#: ../share/roundup/templates/classic/html/issue.item.html:86 msgid "Change Note" -msgstr "?nderungsnotiz" +msgstr "??nderungsnotiz" -#: ../templates/classic/html/issue.item.html:81 +#: ../share/roundup/templates/classic/html/issue.item.html:94 msgid "File" msgstr "Datei" -#: ../templates/classic/html/issue.item.html:99 +#: ../share/roundup/templates/classic/html/issue.item.html:106 msgid "Make a copy" msgstr "kopieren" -#: ../templates/classic/html/issue.item.html:100 -msgid "" -"

    Aktuelle Variablen:
    Note:
    Notiz:
    Bitte beachten:
    DateDatumUserBenutzerActionAktionArgsArgumente
    Note:  highlighted  fields are required.
    " -msgstr "" -" " -"
    Achtung:  Fett markierte  Felder sind immer auszuf?llen.
    " - -#: ../templates/classic/html/issue.item.html:114 -msgid "" -"Created on ${creation} by ${creator}, last changed " -"${activity} by ${actor}." -msgstr "" -"Erstellt am ${creation} durch ${creator}, ge?ndert am " -"${activity} durch ${actor}." +#: ../share/roundup/templates/classic/html/issue.item.html:114 +#: ../share/roundup/templates/classic/html/user.item.html:153 +#: ../share/roundup/templates/classic/html/user.register.html:69 +#: ../share/roundup/templates/minimal/html/user.item.html:153 +msgid "
    Note:  highlighted  fields are required.
    " +msgstr "
    Achtung:  Fett markierte  Felder sind immer auszuf??llen.
    " + +#: ../share/roundup/templates/classic/html/issue.item.html:128 +#, fuzzy +msgid "Created on ${creation} by ${creator}, last changed ${activity} by ${actor}." +msgstr "Erstellt am ${creation} durch ${creator}, ge??ndert am ${activity} durch ${actor}." -#: ../templates/classic/html/issue.item.html:118 -#: ../templates/classic/html/msg.item.html:51 +#: ../share/roundup/templates/classic/html/issue.item.html:132 +#: ../share/roundup/templates/classic/html/msg.item.html:61 msgid "Files" msgstr "Dateien" -#: ../templates/classic/html/issue.item.html:120 -#: ../templates/classic/html/msg.item.html:53 +#: ../share/roundup/templates/classic/html/issue.item.html:134 +#: ../share/roundup/templates/classic/html/msg.item.html:63 msgid "File name" msgstr "Dateiname" -#: ../templates/classic/html/issue.item.html:121 -#: ../templates/classic/html/msg.item.html:54 +#: ../share/roundup/templates/classic/html/issue.item.html:135 +#: ../share/roundup/templates/classic/html/msg.item.html:64 msgid "Uploaded" msgstr "Hochgeladen" -#: ../templates/classic/html/issue.item.html:122 +#: ../share/roundup/templates/classic/html/issue.item.html:136 msgid "Type" msgstr "Typ" -#: ../templates/classic/html/issue.item.html:123 -#: ../templates/classic/html/query.edit.html:30 +#: ../share/roundup/templates/classic/html/issue.item.html:137 +#: ../share/roundup/templates/classic/html/query.edit.html:30 msgid "Edit" msgstr "bearbeiten" -#: ../templates/classic/html/issue.item.html:124 +#: ../share/roundup/templates/classic/html/issue.item.html:138 msgid "Remove" msgstr "verbergen" -#: ../templates/classic/html/issue.item.html:144 -#: ../templates/classic/html/issue.item.html:165 -#: ../templates/classic/html/query.edit.html:50 +#: ../share/roundup/templates/classic/html/issue.item.html:158 +#: ../share/roundup/templates/classic/html/issue.item.html:179 +#: ../share/roundup/templates/classic/html/query.edit.html:50 msgid "remove" msgstr "verbergen" -#: ../templates/classic/html/issue.item.html:151 -#: ../templates/classic/html/msg.index.html:9 +#: ../share/roundup/templates/classic/html/issue.item.html:165 +#: ../share/roundup/templates/classic/html/msg.index.html:9 msgid "Messages" msgstr "Kommentare" -#: ../templates/classic/html/issue.item.html:155 +#: ../share/roundup/templates/classic/html/issue.item.html:169 msgid "msg${id} (view)" msgstr "Kommentar msg${id} (betrachten)" -#: ../templates/classic/html/issue.item.html:156 +#: ../share/roundup/templates/classic/html/issue.item.html:170 msgid "Author: ${author}" msgstr "Autor: ${author}" -#: ../templates/classic/html/issue.item.html:158 +#: ../share/roundup/templates/classic/html/issue.item.html:172 msgid "Date: ${date}" msgstr "Datum: ${date}" -#: ../templates/classic/html/issue.search.html:2 +#: ../share/roundup/templates/classic/html/issue.search.html:2 msgid "Issue searching - ${tracker}" msgstr "Aufgaben suchen - ${tracker}" -#: ../templates/classic/html/issue.search.html:4 +#: ../share/roundup/templates/classic/html/issue.search.html:4 msgid "Issue searching" msgstr "Aufgaben suchen" -#: ../templates/classic/html/issue.search.html:25 +#: ../share/roundup/templates/classic/html/issue.search.html:31 msgid "Filter on" msgstr "Filtern" -#: ../templates/classic/html/issue.search.html:26 +#: ../share/roundup/templates/classic/html/issue.search.html:32 msgid "Display" msgstr "anzeigen" -#: ../templates/classic/html/issue.search.html:27 +#: ../share/roundup/templates/classic/html/issue.search.html:33 msgid "Sort on" msgstr "sortieren" -#: ../templates/classic/html/issue.search.html:28 +#: ../share/roundup/templates/classic/html/issue.search.html:34 msgid "Group on" msgstr "gruppieren" -#: ../templates/classic/html/issue.search.html:32 +#: ../share/roundup/templates/classic/html/issue.search.html:38 msgid "All text*:" msgstr "Volltext*:" -#: ../templates/classic/html/issue.search.html:40 +#: ../share/roundup/templates/classic/html/issue.search.html:46 msgid "Title:" msgstr "Titel:" -#: ../templates/classic/html/issue.search.html:50 -msgid "Topic:" +#: ../share/roundup/templates/classic/html/issue.search.html:56 +msgid "Keyword:" msgstr "Schlagwort:" -# siehe die Anmerkung zu "Schlagwort" -#: ../templates/classic/html/issue.search.html:58 +#: ../share/roundup/templates/classic/html/issue.search.html:58 +#: ../share/roundup/templates/classic/html/issue.search.html:123 +#: ../share/roundup/templates/classic/html/issue.search.html:139 +msgid "not selected" +msgstr "nicht ausgew??hlt" + +#: ../share/roundup/templates/classic/html/issue.search.html:67 msgid "ID:" msgstr "ID:" -#: ../templates/classic/html/issue.search.html:66 +#: ../share/roundup/templates/classic/html/issue.search.html:75 msgid "Creation Date:" msgstr "Erstellungsdatum:" -#: ../templates/classic/html/issue.search.html:77 +#: ../share/roundup/templates/classic/html/issue.search.html:86 msgid "Creator:" msgstr "Ersteller:" -#: ../templates/classic/html/issue.search.html:79 +#: ../share/roundup/templates/classic/html/issue.search.html:88 msgid "created by me" msgstr "von mir erstellt" -#: ../templates/classic/html/issue.search.html:88 +#: ../share/roundup/templates/classic/html/issue.search.html:97 msgid "Activity:" -msgstr "Aktivit?t:" +msgstr "Aktivit??t:" -#: ../templates/classic/html/issue.search.html:99 +#: ../share/roundup/templates/classic/html/issue.search.html:108 msgid "Actor:" msgstr "Akteur:" -#: ../templates/classic/html/issue.search.html:101 +#: ../share/roundup/templates/classic/html/issue.search.html:110 msgid "done by me" -msgstr "von mir zuletzt ge?ndert" +msgstr "von mir zuletzt ge??ndert" -#: ../templates/classic/html/issue.search.html:112 +#: ../share/roundup/templates/classic/html/issue.search.html:121 msgid "Priority:" -msgstr "Priorit?t:" +msgstr "Priorit??t:" -#: ../templates/classic/html/issue.search.html:114 -#: ../templates/classic/html/issue.search.html:130 -msgid "not selected" -msgstr "nicht gesetzt" - -#: ../templates/classic/html/issue.search.html:125 +#: ../share/roundup/templates/classic/html/issue.search.html:134 msgid "Status:" msgstr "Status:" -#: ../templates/classic/html/issue.search.html:128 +#: ../share/roundup/templates/classic/html/issue.search.html:137 msgid "not resolved" -msgstr "ungel?st" +msgstr "ungel??st" -#: ../templates/classic/html/issue.search.html:143 +#: ../share/roundup/templates/classic/html/issue.search.html:152 msgid "Assigned to:" msgstr "Zugewiesen:" -#: ../templates/classic/html/issue.search.html:146 +#: ../share/roundup/templates/classic/html/issue.search.html:155 msgid "assigned to me" msgstr "mir zugewiesen" -#: ../templates/classic/html/issue.search.html:148 +#: ../share/roundup/templates/classic/html/issue.search.html:157 msgid "unassigned" msgstr "nicht zugewiesen" -#: ../templates/classic/html/issue.search.html:158 +#: ../share/roundup/templates/classic/html/issue.search.html:167 msgid "No Sort or group:" -msgstr "" -"Nicht sortieren/gruppieren:" +msgstr "Nicht sortieren/gruppieren:" -#: ../templates/classic/html/issue.search.html:166 +#: ../share/roundup/templates/classic/html/issue.search.html:175 msgid "Pagesize:" -msgstr "Eintr?ge/Seite:" +msgstr "Eintr??ge/Seite:" -#: ../templates/classic/html/issue.search.html:164 +#: ../share/roundup/templates/classic/html/issue.search.html:181 msgid "Start With:" msgstr "Starten bei:" -#: ../templates/classic/html/issue.search.html:170 +#: ../share/roundup/templates/classic/html/issue.search.html:187 msgid "Sort Descending:" msgstr "Absteigend sortieren:" -#: ../templates/classic/html/issue.search.html:177 +#: ../share/roundup/templates/classic/html/issue.search.html:194 msgid "Group Descending:" msgstr "Absteigend gruppieren:" -#: ../templates/classic/html/issue.search.html:184 +#: ../share/roundup/templates/classic/html/issue.search.html:201 msgid "Query name**:" msgstr "Speichern unter**:" -#: ../templates/classic/html/issue.search.html:204 -#: ../templates/classic/html/page.html:31 -#: ../templates/classic/html/page.html:60 -#: ../templates/minimal/html/page.html:31 +#: ../share/roundup/templates/classic/html/issue.search.html:213 +#: ../share/roundup/templates/classic/html/page.html:43 +#: ../share/roundup/templates/classic/html/page.html:92 +#: ../share/roundup/templates/classic/html/user.help-search.html:69 +#: ../share/roundup/templates/minimal/html/page.html:43 +#: ../share/roundup/templates/minimal/html/page.html:91 msgid "Search" msgstr "Suchen" -#: ../templates/classic/html/issue.search.html:209 +#: ../share/roundup/templates/classic/html/issue.search.html:218 msgid "*: The \"all text\" field will look in message bodies and issue titles" -msgstr "" -"*: Das Feld \"Volltext\" durchsucht Titel von Aufgaben und Kommentartexte" +msgstr "*: Das Feld \"Volltext\" durchsucht Titel von Aufgaben und Kommentartexte" -#: ../templates/classic/html/issue.search.html:212 -msgid "" -"**: If you supply a name, the query will be saved off and available as a link " -"in the sidebar" -msgstr "" -"**: Geben Sie einen Namen f?r diese Abfrage ein, um sie in der Seitenleiste " -"zu speichern. " +#: ../share/roundup/templates/classic/html/issue.search.html:221 +msgid "**: If you supply a name, the query will be saved off and available as a link in the sidebar" +msgstr "**: Geben Sie einen Namen f??r diese Abfrage ein, um sie in der Seitenleiste zu speichern. " -#: ../templates/classic/html/keyword.item.html:3 +#: ../share/roundup/templates/classic/html/keyword.item.html:3 msgid "Keyword editing - ${tracker}" msgstr "Schlagwort bearbeiten - ${tracker}" -#: ../templates/classic/html/keyword.item.html:5 +#: ../share/roundup/templates/classic/html/keyword.item.html:5 msgid "Keyword editing" -msgstr "Schlagw?rter bearbeiten" -# siehe die Anmerkung zu "Schlagwort" +msgstr "Schlagw??rter bearbeiten" -#: ../templates/classic/html/keyword.item.html:11 +#: ../share/roundup/templates/classic/html/keyword.item.html:11 msgid "Existing Keywords" -msgstr "Vorhandene Schlagw?rter" -# siehe die Anmerkung zu "Schlagwort" +msgstr "Vorhandene Schlagw??rter" -#: ../templates/classic/html/keyword.item.html:20 -msgid "" -"To edit an existing keyword (for spelling or typing errors), click on its " -"entry above." +#: ../share/roundup/templates/classic/html/keyword.item.html:20 +msgid "To edit an existing keyword (for spelling or typing errors), click on its entry above." msgstr "Um ein bestehendes Schlagwort zu bearbeiten, klicken Sie darauf." -# siehe die Anmerkung zu "Schlagwort" -#: ../templates/classic/html/keyword.item.html:27 +#: ../share/roundup/templates/classic/html/keyword.item.html:27 msgid "To create a new keyword, enter it below and click \"Submit New Entry\"." -msgstr "" -"Um ein neues Schlagwort hinzuf?gen, tragen Sie es hier ein und klicken Sie " -"auf \"Eintrag speichern\"." -# siehe die Anmerkung zu "Schlagwort" +msgstr "Um ein neues Schlagwort hinzuf??gen, tragen Sie es hier ein und klicken Sie auf \"Eintrag speichern\"." -#: ../templates/classic/html/keyword.item.html:37 -msgid "Keyword" -msgstr "Schlagwort" -# siehe die Anmerkung zu "Schlagwort" ("Topic") - -#: ../templates/classic/html/msg.index.html:3 +#: ../share/roundup/templates/classic/html/msg.index.html:3 msgid "List of messages - ${tracker}" msgstr "Kommentare - ${tracker}" -#: ../templates/classic/html/msg.index.html:5 +#: ../share/roundup/templates/classic/html/msg.index.html:5 msgid "Message listing" msgstr "Kommentare" -#: ../templates/classic/html/msg.item.html:6 +#: ../share/roundup/templates/classic/html/msg.item.html:6 msgid "Message ${id} - ${tracker}" msgstr "Kommentar ${id} - ${tracker}" -#: ../templates/classic/html/msg.item.html:9 +#: ../share/roundup/templates/classic/html/msg.item.html:9 msgid "New Message - ${tracker}" msgstr "Neuer Kommentar - ${tracker}" -#: ../templates/classic/html/msg.item.html:13 +#: ../share/roundup/templates/classic/html/msg.item.html:13 msgid "New Message" msgstr "Neuer Kommentar" -#: ../templates/classic/html/msg.item.html:15 +#: ../share/roundup/templates/classic/html/msg.item.html:15 msgid "New Message Editing" msgstr "Neuen Kommentar bearbeiten" -#: ../templates/classic/html/msg.item.html:18 +#: ../share/roundup/templates/classic/html/msg.item.html:18 msgid "Message${id}" msgstr "Kommentar ${id}" -#: ../templates/classic/html/msg.item.html:21 +#: ../share/roundup/templates/classic/html/msg.item.html:21 msgid "Message${id} Editing" msgstr "Kommentar ${id} bearbeiten" -#: ../templates/classic/html/msg.item.html:28 +#: ../share/roundup/templates/classic/html/msg.item.html:38 msgid "Author" msgstr "Autor" -#: ../templates/classic/html/msg.item.html:33 +#: ../share/roundup/templates/classic/html/msg.item.html:43 msgid "Recipients" -msgstr "Empf?nger" +msgstr "Empf??nger" -#: ../templates/classic/html/msg.item.html:44 +#: ../share/roundup/templates/classic/html/msg.item.html:54 msgid "Content" msgstr "Inhalt" -#: ../templates/classic/html/page.html:28 +#: ../share/roundup/templates/classic/html/page.html:54 +#: ../share/roundup/templates/minimal/html/page.html:53 msgid "Your Queries (edit)" msgstr "Abfragen (bearbeiten)" -#: ../templates/classic/html/page.html:39 +#: ../share/roundup/templates/classic/html/page.html:65 +#: ../share/roundup/templates/minimal/html/page.html:64 msgid "Issues" msgstr "Aufgaben" -#: ../templates/classic/html/page.html:41 -#: ../templates/classic/html/page.html:60 +#: ../share/roundup/templates/classic/html/page.html:67 +#: ../share/roundup/templates/classic/html/page.html:105 +#: ../share/roundup/templates/minimal/html/page.html:66 +#: ../share/roundup/templates/minimal/html/page.html:104 msgid "Create New" msgstr "neuer Eintrag" -#: ../templates/classic/html/page.html:43 +#: ../share/roundup/templates/classic/html/page.html:69 +#: ../share/roundup/templates/minimal/html/page.html:68 msgid "Show Unassigned" msgstr "nicht zugewiesen" -#: ../templates/classic/html/page.html:45 +#: ../share/roundup/templates/classic/html/page.html:81 +#: ../share/roundup/templates/minimal/html/page.html:80 msgid "Show All" msgstr "alle anzeigen" -#: ../templates/classic/html/page.html:48 +#: ../share/roundup/templates/classic/html/page.html:93 +#: ../share/roundup/templates/minimal/html/page.html:92 msgid "Show issue:" msgstr "Aufgabe anzeigen:" -#: ../templates/classic/html/page.html:58 -msgid "Keywords" -msgstr "Schlagw?rter" -# siehe die Anmerkung zu "Schlagwort" - -#: ../templates/classic/html/page.html:64 +#: ../share/roundup/templates/classic/html/page.html:108 +#: ../share/roundup/templates/minimal/html/page.html:107 msgid "Edit Existing" msgstr "bearbeiten" -#: ../templates/classic/html/page.html:70 -#: ../templates/minimal/html/page.html:48 +#: ../share/roundup/templates/classic/html/page.html:114 +#: ../share/roundup/templates/minimal/html/page.html:113 msgid "Administration" msgstr "Administration" -#: ../templates/classic/html/page.html:72 -#: ../templates/minimal/html/page.html:49 +#: ../share/roundup/templates/classic/html/page.html:116 +#: ../share/roundup/templates/minimal/html/page.html:115 msgid "Class List" msgstr "Klassenliste" -#: ../templates/classic/html/page.html:76 -#: ../templates/minimal/html/page.html:51 +#: ../share/roundup/templates/classic/html/page.html:120 +#: ../share/roundup/templates/minimal/html/page.html:119 msgid "User List" msgstr "Benutzerliste" -#: ../templates/classic/html/page.html:78 -#: ../templates/minimal/html/page.html:54 +#: ../share/roundup/templates/classic/html/page.html:122 +#: ../share/roundup/templates/minimal/html/page.html:121 msgid "Add User" -msgstr "Benutzer hinzuf?gen" +msgstr "Benutzer hinzuf??gen" -#: ../templates/classic/html/page.html:85 -#: ../templates/classic/html/page.html:89 -#: ../templates/minimal/html/page.html:30 +#: ../share/roundup/templates/classic/html/page.html:129 +#: ../share/roundup/templates/classic/html/page.html:135 +#: ../share/roundup/templates/minimal/html/page.html:128 +#: ../share/roundup/templates/minimal/html/page.html:134 msgid "Login" msgstr "anmelden" -#: ../templates/classic/html/page.html:104 -#: ../templates/minimal/html/page.html:45 +#: ../share/roundup/templates/classic/html/page.html:134 +#: ../share/roundup/templates/minimal/html/page.html:133 msgid "Remember me?" msgstr "dauerhaft anmelden?" -#: ../templates/classic/html/page.html:108 -#: ../templates/classic/html/user.register.html:63 -#: ../templates/minimal/html/page.html:50 -#: ../templates/minimal/html/user.register.html:58 +#: ../share/roundup/templates/classic/html/page.html:138 +#: ../share/roundup/templates/classic/html/user.register.html:63 +#: ../share/roundup/templates/minimal/html/page.html:137 +#: ../share/roundup/templates/minimal/html/user.register.html:61 msgid "Register" msgstr "registrieren" -#: ../templates/classic/html/page.html:94 +#: ../share/roundup/templates/classic/html/page.html:141 +#: ../share/roundup/templates/minimal/html/page.html:140 msgid "Lost your login?" -msgstr "Pa?wort vergessen?" +msgstr "Passwort vergessen?" -#: ../templates/classic/html/page.html:99 +#: ../share/roundup/templates/classic/html/page.html:146 +#: ../share/roundup/templates/minimal/html/page.html:145 msgid "Hello, ${user}" msgstr "Hallo, ${user}" -#: ../templates/classic/html/page.html:101 +#: ../share/roundup/templates/classic/html/page.html:148 msgid "Your Issues" msgstr "Ihre Aufgaben" -#: ../templates/classic/html/page.html:102 -#: ../templates/minimal/html/page.html:40 +#: ../share/roundup/templates/classic/html/page.html:160 +#: ../share/roundup/templates/minimal/html/page.html:147 msgid "Your Details" msgstr "Ihr Konto" -#: ../templates/classic/html/page.html:104 -#: ../templates/minimal/html/page.html:42 +#: ../share/roundup/templates/classic/html/page.html:162 +#: ../share/roundup/templates/minimal/html/page.html:149 msgid "Logout" msgstr "abmelden" -#: ../templates/classic/html/page.html:108 +#: ../share/roundup/templates/classic/html/page.html:166 +#: ../share/roundup/templates/minimal/html/page.html:153 msgid "Help" msgstr "Hilfe" -#: ../templates/classic/html/page.html:109 +#: ../share/roundup/templates/classic/html/page.html:167 +#: ../share/roundup/templates/minimal/html/page.html:154 msgid "Roundup docs" msgstr "Roundup-Handbuch" -#: ../templates/classic/html/page.html:160 -#: ../templates/classic/html/page.html:136 -#: ../templates/minimal/html/page.html:81 -msgid "diese Nachricht l?schen" -msgstr "" - +#: ../share/roundup/templates/classic/html/page.html:177 +#: ../share/roundup/templates/minimal/html/page.html:164 +msgid "clear this message" +msgstr "diese Nachricht l??schen" + +#: ../share/roundup/templates/classic/html/page.html:241 +#: ../share/roundup/templates/classic/html/page.html:256 +#: ../share/roundup/templates/classic/html/page.html:270 +#: ../share/roundup/templates/minimal/html/page.html:228 +#: ../share/roundup/templates/minimal/html/page.html:243 +#: ../share/roundup/templates/minimal/html/page.html:257 msgid "don't care" msgstr "egal" -#: ../templates/classic/html/page.html:162 +#: ../share/roundup/templates/classic/html/page.html:243 +#: ../share/roundup/templates/classic/html/page.html:258 +#: ../share/roundup/templates/classic/html/page.html:271 +#: ../share/roundup/templates/minimal/html/page.html:230 +#: ../share/roundup/templates/minimal/html/page.html:245 +#: ../share/roundup/templates/minimal/html/page.html:258 msgid "------------" msgstr "------------" -#: ../templates/classic/html/page.html:188 +#: ../share/roundup/templates/classic/html/page.html:299 +#: ../share/roundup/templates/minimal/html/page.html:286 msgid "no value" msgstr "kein Wert" -#: ../templates/classic/html/query.edit.html:4 +#: ../share/roundup/templates/classic/html/query.edit.html:4 msgid "\"Your Queries\" Editing - ${tracker}" msgstr "Abfragen bearbeiten - ${tracker}" -#: ../templates/classic/html/query.edit.html:6 +#: ../share/roundup/templates/classic/html/query.edit.html:6 msgid "\"Your Queries\" Editing" msgstr "Abfragen bearbeiten" -#: ../templates/classic/html/query.edit.html:11 +#: ../share/roundup/templates/classic/html/query.edit.html:11 msgid "You are not allowed to edit queries." msgstr "Sie sind nicht berechtigt, Abfragen zu bearbeiten." -#: ../templates/classic/html/query.edit.html:28 +#: ../share/roundup/templates/classic/html/query.edit.html:28 msgid "Query" msgstr "Abfrage" -#: ../templates/classic/html/query.edit.html:29 +#: ../share/roundup/templates/classic/html/query.edit.html:29 msgid "Include in \"Your Queries\"" -msgstr "Unter \"Abfragen\" auff?hren" +msgstr "Unter \"Abfragen\" auff??hren" -#: ../templates/classic/html/query.edit.html:31 +#: ../share/roundup/templates/classic/html/query.edit.html:31 msgid "Private to you?" -msgstr "Nur f?r Sie?" +msgstr "Nur f??r Sie?" -#: ../templates/classic/html/query.edit.html:44 +#: ../share/roundup/templates/classic/html/query.edit.html:44 msgid "leave out" msgstr "weglassen" -#: ../templates/classic/html/query.edit.html:45 +#: ../share/roundup/templates/classic/html/query.edit.html:45 msgid "include" -msgstr "anf?gen" +msgstr "anf??gen" -#: ../templates/classic/html/query.edit.html:49 +#: ../share/roundup/templates/classic/html/query.edit.html:49 msgid "leave in" msgstr "belassen" -#: ../templates/classic/html/query.edit.html:54 +#: ../share/roundup/templates/classic/html/query.edit.html:54 msgid "[query is retired]" msgstr "[Abfrage ist verborgen]" -#: ../templates/classic/html/query.edit.html:67 -#: ../templates/classic/html/query.edit.html:92 +#: ../share/roundup/templates/classic/html/query.edit.html:67 +#: ../share/roundup/templates/classic/html/query.edit.html:94 msgid "edit" msgstr "bearbeiten" -#: ../templates/classic/html/query.edit.html:71 +#: ../share/roundup/templates/classic/html/query.edit.html:71 msgid "yes" msgstr "ja" -#: ../templates/classic/html/query.edit.html:73 +#: ../share/roundup/templates/classic/html/query.edit.html:73 msgid "no" msgstr "nein" -#: ../templates/classic/html/query.edit.html:79 +#: ../share/roundup/templates/classic/html/query.edit.html:79 msgid "Delete" -msgstr "L?schen" +msgstr "L??schen" -#: ../templates/classic/html/query.edit.html:90 +#: ../share/roundup/templates/classic/html/query.edit.html:96 msgid "[not yours to edit]" msgstr "[nicht Ihr Eintrag]" -#: ../templates/classic/html/query.edit.html:96 +#: ../share/roundup/templates/classic/html/query.edit.html:104 msgid "Save Selection" msgstr "Auswahl speichern" -#: ../templates/classic/html/user.forgotten.html:3 +#: ../share/roundup/templates/classic/html/user.forgotten.html:3 msgid "Password reset request - ${tracker}" -msgstr "Pa?wort zur?cksetzen - ${tracker}" +msgstr "Passwort zur??cksetzen - ${tracker}" -#: ../templates/classic/html/user.forgotten.html:5 +#: ../share/roundup/templates/classic/html/user.forgotten.html:5 msgid "Password reset request" -msgstr "Pa?wort zur?cksetzen" +msgstr "Passwort zur??cksetzen" -#: ../templates/classic/html/user.forgotten.html:9 -msgid "" -"You have two options if you have forgotten your password. If you know the " -"email address you registered with, enter it below." -msgstr "" -"Um Ihr Pa?wort zur?ckzusetzen, geben Sie entweder die Email-Adresse an, mit " -"der Sie sich registriert haben..." +#: ../share/roundup/templates/classic/html/user.forgotten.html:9 +msgid "You have two options if you have forgotten your password. If you know the email address you registered with, enter it below." +msgstr "Um Ihr Passwort zur??ckzusetzen, geben Sie entweder die E-Mail-Adresse an, mit der Sie sich registriert haben..." -#: ../templates/classic/html/user.forgotten.html:16 +#: ../share/roundup/templates/classic/html/user.forgotten.html:16 msgid "Email Address:" -msgstr "Email-Adresse" +msgstr "E-Mail-Adresse" -#: ../templates/classic/html/user.forgotten.html:24 -#: ../templates/classic/html/user.forgotten.html:34 +#: ../share/roundup/templates/classic/html/user.forgotten.html:24 +#: ../share/roundup/templates/classic/html/user.forgotten.html:34 msgid "Request password reset" -msgstr "Pa?wort zur?cksetzen" +msgstr "Passwort zur??cksetzen" -#: ../templates/classic/html/user.forgotten.html:30 +#: ../share/roundup/templates/classic/html/user.forgotten.html:30 msgid "Or, if you know your username, then enter it below." msgstr "... oder Ihren Benutzernamen." -#: ../templates/classic/html/user.forgotten.html:33 +#: ../share/roundup/templates/classic/html/user.forgotten.html:33 msgid "Username:" msgstr "Benutzername:" -#: ../templates/classic/html/user.forgotten.html:39 -msgid "" -"A confirmation email will be sent to you - please follow the instructions " -"within it to complete the reset process." -msgstr "" -"Danach wird eine Best?tigungs-Mail verschickt. Bitte folgen Sie den " -"Anweisungen darin, um ihr Pa?wort zur?ckzusetzen." +#: ../share/roundup/templates/classic/html/user.forgotten.html:39 +msgid "A confirmation email will be sent to you - please follow the instructions within it to complete the reset process." +msgstr "Danach wird eine Best??tigungs-E-Mail verschickt. Bitte folgen Sie den Anweisungen darin, um ihr Passwort zur??ckzusetzen." -#: ../templates/classic/html/user.index.html:3 -#: ../templates/minimal/html/user.index.html:3 +#: ../share/roundup/templates/classic/html/user.help-search.html:73 +msgid "Pagesize" +msgstr "Eintr??ge/Seite" + +#: ../share/roundup/templates/classic/html/user.help.html:43 +msgid "Your browser is not capable of using frames; you should be redirected immediately, or visit ${link}." +msgstr "Ihr Browser unterst??tzt keine Frames; Sie sollten gleich weitergeleitetwerden, oder besuchen Sie ${link}." + +#: ../share/roundup/templates/classic/html/user.index.html:3 +#: ../share/roundup/templates/minimal/html/user.index.html:3 msgid "User listing - ${tracker}" msgstr "Benutzerliste - ${tracker}" -#: ../templates/classic/html/user.index.html:5 -#: ../templates/minimal/html/user.index.html:5 +#: ../share/roundup/templates/classic/html/user.index.html:5 +#: ../share/roundup/templates/minimal/html/user.index.html:5 msgid "User listing" msgstr "Benutzerliste" -#: ../templates/classic/html/user.index.html:14 -#: ../templates/minimal/html/user.index.html:14 +#: ../share/roundup/templates/classic/html/user.index.html:19 +#: ../share/roundup/templates/minimal/html/user.index.html:19 msgid "Username" msgstr "Benutzername" -#: ../templates/classic/html/user.index.html:15 +#: ../share/roundup/templates/classic/html/user.index.html:20 msgid "Real name" msgstr "Name" -#: ../templates/classic/html/user.index.html:16 -#: ../templates/classic/html/user.item.html:65 -#: ../templates/classic/html/user.register.html:45 +#: ../share/roundup/templates/classic/html/user.index.html:21 +#: ../share/roundup/templates/classic/html/user.register.html:45 msgid "Organisation" msgstr "Organisation" -#: ../templates/classic/html/user.index.html:17 -#: ../templates/minimal/html/user.index.html:15 +#: ../share/roundup/templates/classic/html/user.index.html:22 +#: ../share/roundup/templates/minimal/html/user.index.html:20 msgid "Email address" -msgstr "Email-Adresse" +msgstr "E-Mail-Adresse" -#: ../templates/classic/html/user.index.html:18 +#: ../share/roundup/templates/classic/html/user.index.html:23 msgid "Phone number" msgstr "Telefonnummer" -#: ../templates/classic/html/user.index.html:19 +#: ../share/roundup/templates/classic/html/user.index.html:24 msgid "Retire" -msgstr "Verbergen" +msgstr "Entfernen" -#: ../templates/classic/html/user.index.html:32 +#: ../share/roundup/templates/classic/html/user.index.html:41 msgid "retire" -msgstr "verbergen" +msgstr "entfernen" -#: ../templates/classic/html/user.item.html:7 -#: ../templates/minimal/html/user.item.html:7 +#: ../share/roundup/templates/classic/html/user.item.html:9 +#: ../share/roundup/templates/minimal/html/user.item.html:9 msgid "User ${id}: ${title} - ${tracker}" msgstr "Benutzer ${id}: ${title} - ${tracker}" -#: ../templates/classic/html/user.item.html:10 -#: ../templates/minimal/html/user.item.html:10 +#: ../share/roundup/templates/classic/html/user.item.html:12 +#: ../share/roundup/templates/minimal/html/user.item.html:12 msgid "New User - ${tracker}" msgstr "Neuer Benutzer - ${tracker}" -#: ../templates/classic/html/user.item.html:14 -#: ../templates/minimal/html/user.item.html:6 +#: ../share/roundup/templates/classic/html/user.item.html:21 +#: ../share/roundup/templates/minimal/html/user.item.html:21 msgid "New User" msgstr "Neuer Benutzer" -#: ../templates/classic/html/user.item.html:16 -#: ../templates/minimal/html/user.item.html:8 +#: ../share/roundup/templates/classic/html/user.item.html:23 +#: ../share/roundup/templates/minimal/html/user.item.html:23 msgid "New User Editing" msgstr "Neuen Benutzer bearbeiten" -#: ../templates/classic/html/user.item.html:19 -#: ../templates/minimal/html/user.item.html:11 +#: ../share/roundup/templates/classic/html/user.item.html:26 +#: ../share/roundup/templates/minimal/html/user.item.html:26 msgid "User${id}" msgstr "Benutzer${id}" -#: ../templates/classic/html/user.item.html:22 -#: ../templates/minimal/html/user.item.html:14 +#: ../share/roundup/templates/classic/html/user.item.html:29 +#: ../share/roundup/templates/minimal/html/user.item.html:29 msgid "User${id} Editing" msgstr "Benutzer ${id} bearbeiten" -#: ../templates/classic/html/user.item.html:43 -#: ../templates/classic/html/user.register.html:21 -#: ../templates/minimal/html/user.item.html:40 -#: ../templates/minimal/html/user.register.html:26 -msgid "Login Name" -msgstr "Benutzername" - -#: ../templates/classic/html/user.item.html:42 -#: ../templates/classic/html/user.register.html:25 -#: ../templates/minimal/html/user.item.html:31 -#: ../templates/minimal/html/user.register.html:30 -msgid "Login Password" -msgstr "Pa?wort" - -#: ../templates/classic/html/user.item.html:46 -#: ../templates/classic/html/user.register.html:29 -#: ../templates/minimal/html/user.item.html:35 -#: ../templates/minimal/html/user.register.html:34 -msgid "Confirm Password" -msgstr "Pa?wort best?tigen" - -#: ../templates/classic/html/user.item.html:50 -#: ../templates/classic/html/user.register.html:33 -#: ../templates/minimal/html/user.item.html:39 -#: ../templates/minimal/html/user.register.html:38 +#: ../share/roundup/templates/classic/html/user.item.html:80 +#: ../share/roundup/templates/classic/html/user.register.html:33 +#: ../share/roundup/templates/minimal/html/user.item.html:80 +#: ../share/roundup/templates/minimal/html/user.register.html:41 msgid "Roles" msgstr "Rollen" -#: ../templates/classic/html/user.item.html:61 -#: ../templates/minimal/html/user.item.html:58 +#: ../share/roundup/templates/classic/html/user.item.html:88 +#: ../share/roundup/templates/minimal/html/user.item.html:88 msgid "(to give the user more than one role, enter a comma,separated,list)" -msgstr "" -"Verwenden,Sie,Kommata, um einem Benutzer mehrere Rollen zuzuteilen" - -#: ../templates/classic/html/user.item.html:61 -#: ../templates/classic/html/user.register.html:41 -msgid "Phone" -msgstr "Telefon" - -#: ../templates/classic/html/user.item.html:69 -msgid "Timezone" -msgstr "Zeitzone" +msgstr "Verwenden,Sie,Kommata, um einem Benutzer mehrere Rollen zuzuteilen" -#: ../templates/classic/html/user.item.html:73 +#: ../share/roundup/templates/classic/html/user.item.html:109 +#: ../share/roundup/templates/minimal/html/user.item.html:109 msgid "(this is a numeric hour offset, the default is ${zone})" msgstr "(als Differenz zu GMT/UTC in Stunden - Voreinstellung: ${zone})" -#: ../templates/classic/html/user.item.html:83 -#: ../templates/classic/html/user.register.html:49 -#: ../templates/minimal/html/user.item.html:63 -#: ../templates/minimal/html/user.register.html:46 -msgid "E-mail address" -msgstr "Email-Adresse" - -#: ../templates/classic/html/user.item.html:82 -#: ../templates/classic/html/user.register.html:53 -#: ../templates/minimal/html/user.item.html:51 -#: ../templates/minimal/html/user.register.html:50 +#: ../share/roundup/templates/classic/html/user.item.html:130 +#: ../share/roundup/templates/classic/html/user.register.html:53 +#: ../share/roundup/templates/minimal/html/user.item.html:130 +#: ../share/roundup/templates/minimal/html/user.register.html:53 msgid "Alternate E-mail addresses
    One address per line" -msgstr "
    Alternative Email-Adressen
    (eine pro Zeile)" +msgstr "
    Alternative E-Mail-Adressen
    (eine pro Zeile)" -#: ../templates/classic/html/user.register.html:4 -#: ../templates/classic/html/user.register.html:7 -#: ../templates/minimal/html/user.register.html:4 -#: ../templates/minimal/html/user.register.html:7 +#: ../share/roundup/templates/classic/html/user.register.html:4 +#: ../share/roundup/templates/classic/html/user.register.html:7 +#: ../share/roundup/templates/minimal/html/user.register.html:4 +#: ../share/roundup/templates/minimal/html/user.register.html:7 msgid "Registering with ${tracker}" -msgstr "Registrieren f?r ${tracker}" - -#: ../templates/classic/html/user.rego_progress.html:4 -#: ../templates/minimal/html/user.rego_progress.html:4 -msgid "Registration in progress - ${tracker}" -msgstr "Die Registrierung ist im Gange - ${tracker}" - -#: ../templates/classic/html/user.rego_progress.html:6 -#: ../templates/minimal/html/user.rego_progress.html:6 -msgid "Registration in progress..." -msgstr "Die Registrierung ist im Gange..." - -#: ../templates/classic/html/user.rego_progress.html:10 -#: ../templates/minimal/html/user.rego_progress.html:10 -msgid "" -"You will shortly receive an email to confirm your registration. To complete " -"the registration process, visit the link indicated in the email." -msgstr "" -"Sie werden in K?rze eine Best?tigungs-Mail erhalten. Um die Registrierung " -"abzuschlie?en, klicken Sie auf den enthaltenen Link." - -#: ../templates/minimal/html/home.html:2 -msgid "Tracker home - ${tracker}" -msgstr "Tracker-Start - ${tracker}" - -#: ../templates/minimal/html/home.html:4 -msgid "Tracker home" -msgstr "Tracker-Start" +msgstr "Registrieren f??r ${tracker}" -#: ../templates/minimal/html/home.html:16 -msgid "Please select from one of the menu options on the left." -msgstr "Bitte w?hlen Sie links eine Menu-Option." - -#: ../templates/minimal/html/home.html:19 -msgid "Please log in or register." -msgstr "Bitte anmelden oder registrieren" - -#: ../templates/minimal/html/page.html:38 -msgid "Hello,
    ${user}" -msgstr "Hallo,
    ${user}" - -#: ../templates/minimal/html/user.item.html:3 -msgid "User editing - ${tracker}" -msgstr "Benutzer bearbeiten - ${tracker}" - -#: ../templates/classic/html/issue.item.html:120; -msgid "Copy item" -msgstr "kopieren" - -#: ../templating.py:1099; -msgid "Copy of %(class)s %(id)s" -msgstr "Kopie von %(class)s%(id)s" - -#: ../templates/classic/html/...:123 -msgid "No Sort or group" -msgstr "nicht sortieren/gruppieren" - -#: ../templates/classic/html/issue.search.html:170 -msgid "sort descending" -msgstr "absteigend sortieren" - -#: ../templates/classic/html/issue.search.html:177 -msgid "group descending" -msgstr "absteigend gruppieren" - -#: ../templates/classic/html/issue.search.html:170 -msgid "don't sort" -msgstr "nicht sortieren" +#: ../share/roundup/templates/classic/html/user.register.html:21 +#: ../share/roundup/templates/minimal/html/user.register.html:29 +msgid "Login Name" +msgstr "Benutzername" -#: ../templates/classic/html/issue.search.html:177 -msgid "don't group" -msgstr "nicht gruppieren" +#: ../share/roundup/templates/classic/html/user.register.html:25 +#: ../share/roundup/templates/minimal/html/user.register.html:33 +msgid "Login Password" +msgstr "Pa??wort" -#: ../templates/classic(th)/html/issue.search.html:XXX -msgid "Sort/Group Descending:" -msgstr "absteigend sortieren/gruppieren:" +#: ../share/roundup/templates/classic/html/user.register.html:29 +#: ../share/roundup/templates/minimal/html/user.register.html:37 +msgid "Confirm Password" +msgstr "Pa??wort best??tigen" -#: ../templates/classic(th)/html/issue.search.html:XXX -msgid "Paged Output:" -msgstr "seitenweise ausgeben:" +#: ../share/roundup/templates/classic/html/user.register.html:41 +msgid "Phone" +msgstr "Telefon" -#: ../templates/classic(th)/html/issue.search.html:XXX -msgid "Pagesize" -msgstr "Eintr?ge/Seite" +#: ../share/roundup/templates/classic/html/user.register.html:49 +#: ../share/roundup/templates/minimal/html/user.register.html:49 +msgid "E-mail address" +msgstr "Email-Adresse" -#: ../templates/classic/html/user.item.html:XXX -msgid "username" -msgstr "Benutzername" +#: ../share/roundup/templates/classic/html/user.rego_progress.html:4 +#: ../share/roundup/templates/minimal/html/user.rego_progress.html:4 +msgid "Registration in progress - ${tracker}" +msgstr "Die Registrierung ist im Gange - ${tracker}" -#: ../templates/classic/html/user.item.html:XXX -msgid "realname" -msgstr "Name" +#: ../share/roundup/templates/classic/html/user.rego_progress.html:6 +#: ../share/roundup/templates/minimal/html/user.rego_progress.html:6 +msgid "Registration in progress..." +msgstr "Die Registrierung ist im Gange..." -#: ../templates/classic/html/user.item.html:XXX -msgid "address" -msgstr "Mail-Adresse" +#: ../share/roundup/templates/classic/html/user.rego_progress.html:10 +#: ../share/roundup/templates/minimal/html/user.rego_progress.html:10 +msgid "You will shortly receive an email to confirm your registration. To complete the registration process, visit the link indicated in the email." +msgstr "Sie werden in K??rze eine Best??tigungs-E-Mail erhalten. Um die Registrierung abzuschlie??en, klicken Sie auf den enthaltenen Link." # priority translations: -#: ../templates/classic/initial_data.py:5 +#: ../share/roundup/templates/classic/initial_data.py:5 msgid "critical" msgstr "Fehler (KRITISCH)" -#: ../templates/classic/initial_data.py:6 +#: ../share/roundup/templates/classic/initial_data.py:6 msgid "urgent" msgstr "Fehler (dringend)" -#: ../templates/classic/initial_data.py:7 +#: ../share/roundup/templates/classic/initial_data.py:7 msgid "bug" msgstr "Fehler" -#: ../templates/classic/initial_data.py:8 +#: ../share/roundup/templates/classic/initial_data.py:8 msgid "feature" msgstr "Anforderung" -#: ../templates/classic/initial_data.py:9 +#: ../share/roundup/templates/classic/initial_data.py:9 msgid "wish" msgstr "Wunsch" -#: status translations: -#: ../templates/classic/initial_data.py:12 +#: ../share/roundup/templates/classic/initial_data.py:12 msgid "unread" msgstr "ungelesen" -#: ../templates/classic/initial_data.py:13 +#: ../share/roundup/templates/classic/initial_data.py:13 msgid "deferred" -msgstr "zur?ckgestellt" +msgstr "zur??ckgestellt" -#: ../templates/classic/initial_data.py:14 +#: ../share/roundup/templates/classic/initial_data.py:14 msgid "chatting" msgstr "in Diskussion" -#: ../templates/classic/initial_data.py:15 -msgid "in-progress" -msgstr "in Arbeit" - -#: ../templates/classic/initial_data.py:16 +#: ../share/roundup/templates/classic/initial_data.py:15 msgid "need-eg" msgstr "Beispiel erbeten" -#: ../templates/classic/initial_data.py:17 +#: ../share/roundup/templates/classic/initial_data.py:16 +msgid "in-progress" +msgstr "in Arbeit" + +#: ../share/roundup/templates/classic/initial_data.py:17 msgid "testing" msgstr "im Test" -#: ../templates/classic/initial_data.py:18 +#: ../share/roundup/templates/classic/initial_data.py:18 msgid "done-cbb" msgstr "erledigt (provisorisch)" -#: ../templates/classic/initial_data.py:19 +#: ../share/roundup/templates/classic/initial_data.py:19 msgid "resolved" msgstr "erledigt" -#: ../scripts/roundup_mailgw.py:36 -msgid "try %(prog)s --help for usage info" -msgstr "%(prog)s --help gibt eine Hilfe aus" - -#: ../templates/classic(th)/html/issue.item.html -msgid "(cal)" -msgstr "(Kal.)" +#: ../share/roundup/templates/minimal/html/home.html:2 +msgid "Tracker home - ${tracker}" +msgstr "Tracker-Startseite - ${tracker}" + +#: ../share/roundup/templates/minimal/html/home.html:4 +msgid "Tracker home" +msgstr "Tracker-Startseite" + +#: ../share/roundup/templates/minimal/html/home.html:16 +msgid "Please select from one of the menu options on the left." +msgstr "Bitte w??hlen Sie links eine Menu-Option." + +#: ../share/roundup/templates/minimal/html/home.html:19 +msgid "Please log in or register." +msgstr "Bitte anmelden oder registrieren" + +#~ msgid "%(key)s: %(value)r" +#~ msgstr "%(key)s: %(value)r" +#~ msgid "You do not have permission to edit user roles" +#~ msgstr "Sie sind nicht berechtigt, Benutzer-Rollen zu ??ndern" +#~ msgid "" +#~ "An error has occurred\n" +#~ "

    An error has occurred

    \n" +#~ "

    A problem was encountered processing your request.\n" +#~ "The tracker maintainers have been notified of the problem.

    \n" +#~ "" +#~ msgstr "" +#~ "Ein Fehler ist aufgetreten\n" +#~ "

    Ein Fehler ist aufgetreten

    \n" +#~ "

    Bei der Bearbeitung Ihrer Daten ist ein Fehler aufgetreten. Die " +#~ "Admistratoren wurden benachrichtigt.

    \n" +#~ "" +#~ msgid "Not a date spec: %s" +#~ msgstr "Kein g??ltiges Datum: %s" +#~ msgid "" +#~ "\n" +#~ "I cannot match your message to a node in the database - you need to " +#~ "either\n" +#~ "supply a full designator (with number, eg \"[issue123]\" or keep the\n" +#~ "previous subject title intact so I can match that.\n" +#~ "\n" +#~ "Subject was: \"%(subject)s\"\n" +#~ msgstr "" +#~ "\n" +#~ "Ich kann Ihre Nachricht keinem Eintrag in der Datenbank zuordnen - Sie " +#~ "m??ssen\n" +#~ "entweder einen vollen Bezeichner angeben (mit Nummer, z. B. \"[issue123]" +#~ "\")\n" +#~ "oder die Betreffzeile intakt lassen, so da?? ich diese zuordnen kann.\n" +#~ "\n" +#~ "Die Betreffzeile (Subject) war:\n" +#~ " '%(subject)s'\n" +#~ msgid "" +#~ "\n" +#~ "You are not a registered user.\n" +#~ "\n" +#~ "Unknown address: %(from_address)s\n" +#~ msgstr "" +#~ "\n" +#~ "Sie sind kein registrierter Anwender.\n" +#~ "\n" +#~ "Unbekannte Adresse: %(from_address)s\n" +#~ msgid "topic" +#~ msgstr "Schlagwort" +#~ msgid "Error: apop specification not valid" +#~ msgstr "Fehler: apop Optionen ung??ltig" +#~ msgid "List of issues - ${tracker}" +#~ msgstr "Aufgabenliste - ${tracker}" +#~ msgid "List of issues - ${query} - ${tracker}" +#~ msgstr "Aufgabenliste - ${query} - ${tracker}" +#~ msgid "List of issues - ${query}" +#~ msgstr "Aufgabenliste - ${query}" +#~ msgid "Topic" +#~ msgstr "Schlagwort" +#~ msgid "View: ${link}" +#~ msgstr "Anzeigen: ${link}" +#~ msgid "Topics" +#~ msgstr "Schlagw??rter" +#~ msgid "Topic:" +#~ msgstr "Schlagwort:" +#~ msgid "Timezone" +#~ msgstr "Zeitzone" +#~ msgid "Hello,
    ${user}" +#~ msgstr "Hallo,
    ${user}" +#~ msgid "User editing - ${tracker}" +#~ msgstr "Benutzer bearbeiten - ${tracker}" +#~ msgid "Copy item" +#~ msgstr "kopieren" +#~ msgid "sort descending" +#~ msgstr "absteigend sortieren" +#~ msgid "group descending" +#~ msgstr "absteigend gruppieren" +#~ msgid "don't sort" +#~ msgstr "nicht sortieren" +#~ msgid "don't group" +#~ msgstr "nicht gruppieren" +#~ msgid "Sort/Group Descending:" +#~ msgstr "absteigend sortieren/gruppieren:" +#~ msgid "Paged Output:" +#~ msgstr "seitenweise ausgeben:" +#~ msgid "username" +#~ msgstr "Benutzername" +#~ msgid "realname" +#~ msgstr "Name" +#~ msgid "firstname" +#~ msgstr "Vorname" +#~ msgid "lastname" +#~ msgstr "Nachname" +#~ msgid "address" +#~ msgstr "Mail-Adresse" +#~ msgid "(cal)" +#~ msgstr "(Kal.)" + Modified: tracker/roundup-src/locale/en.po ============================================================================== --- tracker/roundup-src/locale/en.po (original) +++ tracker/roundup-src/locale/en.po Sun Mar 15 22:43:30 2009 @@ -1,6 +1,6 @@ # English message file for Roundup Issue Tracker # -# $Id: en.po,v 1.2 2004/11/20 11:54:32 a1s Exp $ +# $Id: en.po,v 1.2 2004-11-20 11:54:32 a1s Exp $ # # roundup.pot revision 1.9 # Modified: tracker/roundup-src/locale/fr.po ============================================================================== --- tracker/roundup-src/locale/fr.po (original) +++ tracker/roundup-src/locale/fr.po Sun Mar 15 22:43:30 2009 @@ -1,22 +1,24 @@ # French message file for Roundup Issue Tracker # Georges Martin , 2004. +# Patrick Decat , 2008. +# St?phane Raimbault , 2008. # This file is distributed under the same license as the Roundup package. # -# $Id: fr.po,v 1.5 2006/05/13 09:42:49 a1s Exp $ +# $Id: fr.po,v 1.6 2009-02-05 14:18:27 stefan Exp $ # roundup.pot revision 1.18 # msgid "" msgstr "" -"Project-Id-Version: Roundup 1.1.1\n" +"Project-Id-Version: Roundup 1.4.6\n" "Report-Msgid-Bugs-To: roundup-devel at lists.sourceforge.net\n" "POT-Creation-Date: 2006-04-27 09:02+0300\n" -"PO-Revision-Date: 2006-05-09 12:08+0300\n" -"Last-Translator: Patrick Decat \n" -"Language-Team: French Translators \n" +"PO-Revision-Date: 2008-10-14 10:15+0200\n" +"Last-Translator: St?phane Raimbault \n" +"Language-Team: GNOME French Team \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n !=1;\n" +"Plural-Forms: nplurals=2; plural=n>1;\n" # ../roundup/admin.py:85 :979 :1028 :1050 # ../roundup/admin.py:1052 ../roundup/admin.py:85:981 :1030:1052 @@ -24,26 +26,24 @@ #: ../roundup/admin.py:1052 #, python-format msgid "no such class \"%(classname)s\"" -msgstr "la classe \"%(classname)s\" n'existe pas" +msgstr "aucune classe nomm?e ??%(classname)s??" # ../roundup/admin.py:95 :99 # ../roundup/admin.py:95 ../roundup/admin.py:99 ../roundup/admin.py:95:99 #: ../roundup/admin.py:95 ../roundup/admin.py:99 #, python-format msgid "argument \"%(arg)s\" not propname=value" -msgstr "l'argument \"%(arg)s\" n'est pas au format nom-de-propri?t?=valeur" +msgstr "l'argument ??%(arg)s?? n'est pas au format nom-de-propri?t?=valeur" #: ../roundup/admin.py:112 #, python-format msgid "" "Problem: %(message)s\n" "\n" -msgstr "" -"Probl?me: %(message)s\n" -"\n" +msgstr "Probl?me?: %(message)s\n\n" #: ../roundup/admin.py:113 -#, fuzzy, python-format +#, python-format msgid "" "%(message)sUsage: roundup-admin [options] [ ]\n" "\n" @@ -68,10 +68,10 @@ " roundup-admin help -- command-specific help\n" " roundup-admin help all -- all available help\n" msgstr "" -"%(message)sUsage: roundup-admin [options] [ ]\n" +"%(message)sUtilisation?: roundup-admin [options] [ ]\n" "\n" -"Options:\n" -" -i base-du-pisteur -- sp?cifie le r?pertoire de base du pisteur ?\n" +"Options?:\n" +" -i racine pisteur -- indique le r?pertoire racine du pisteur ?\n" " administrer.\n" " -u -- le nom-d'utilisateur[:mot-de-passe] ? utiliser\n" " pour les commandes.\n" @@ -79,16 +79,18 @@ " les num?ros d'identification de classe.\n" " -c -- imprime les listes de donn?es en les s?parant par\n" " des virgules.\n" -" Identique ? '-S \",\"'.\n" +" Identique ? ??-S \",\"??.\n" " -S -- imprime les listes de donn?es en les s?parant par\n" " la cha?ne sp?cifi?e.\n" " -s -- imprime les listes de donn?es en les s?parant par\n" " des espaces.\n" -" Identique ? '-S \" \"'.\n" +" Identique ? ??-S \" \"??.\n" +" -V -- est verbeux ? l'importation\n" +" -v -- affiche les versions de Roundup et Python (et quitte).\n" "\n" -" Une seule des options -s, -c ou -S peut ?tre sp?cifi?e.\n" +" Seulement une des options parmi -s, -c ou -S peut ?tre utilis?e ? la fois.\n" "\n" -"Aide:\n" +"Aide?:\n" " roundup-admin -h\n" " roundup-admin help -- cette aide\n" " roundup-admin help -- l'aide sur une commande\n" @@ -96,16 +98,16 @@ #: ../roundup/admin.py:140 msgid "Commands:" -msgstr "Commandes:" +msgstr "Commandes?:" #: ../roundup/admin.py:147 msgid "" "Commands may be abbreviated as long as the abbreviation\n" "matches only one command, e.g. l == li == lis == list." msgstr "" -"Les commandes peuvent ?tre abr?g?es, pour autant\n" -"que l'abr?viation ne corresponde qu'? une seule commande,\n" -"par ex.: l == li == lis == list." +"Les commandes peuvent ?tre abr?g?es, dans le cas\n" +"o? l'abr?viation ne correspond qu'? une seule commande,\n" +"par ex.?: l == li == lis == list." #: ../roundup/admin.py:177 msgid "" @@ -174,68 +176,66 @@ "Command help:\n" msgstr "" "\n" -"Toutes les commandes (? l'exception de \"help\") n?cessitent\n" -"un sp?cificateur de pisteur. Il s'agit juste du chemin vers le pisteur\n" -"roundup sur lequel vous d?sirez travailler. Un pisteur roundup est " -"l'endroit\n" -"o? roundup garde la base de donn?es et les fichiers de configuration qui\n" -"d?finissent un pisteur de probl?mes.Il peut ?tre sp?cifi? dans la variable " -"d'environnement \"TRACKER_HOME\" ou\n" -"dans la ligne de commande comme \"-i base-du-pisteur\".\n" +"Toutes les commandes (? l'exception de ??help??) n?cessitent\n" +"d'indiquer un pisteur. Il s'agit juste du chemin vers le pisteur\n" +"Roundup sur lequel vous d?sirez travailler. Un pisteur Roundup est\n" +"l'endroit o? Roundup conserver la base de donn?es et les fichiers de\n" +"configuration qui d?finissent un pisteur de probl?mes. Il peut ?tre\n" +"indiqu? dans la variable d'environnement ??TRACKER_HOME?? ou en ligne\n" +"de commande comme ??-i racine-du-pisteur??.\n" "\n" "Un indicateur est la concat?nation d'un nom de classe et d'un\n" -"identificateur de noeud, par ex: bug1, user10,...\n" +"identificateur de noeud, p. ex.?: bug1, user10, ...\n" "\n" -"Les valeurs de propri?t? sont repr?sent?s comme des cha?nes de caract?res\n" -"dans les arguments de commande et dans les r?sultats imprim?s:\n" -" . les cha?nes de caract?res sont repr?sent?es telles quelles.\n" -" . les dates sont imprim?es dans le format de date complet avec le fuseau\n" -" horaire local et accept?es dans le format complet ou l'un des formats\n" -" partiels expliqu?s ci-dessous. . les valeurs de lien sont imprim?es comme " -"indicateurs de noeuds.\n" +"Les valeurs de propri?t? sont repr?sent?es comme des cha?nes de\n" +"caract?res dans les arguments de commande et dans les r?sultats\n" +"imprim?s?:\n" +" . Les cha?nes de caract?res sont repr?sent?es telles quelles.\n" +" . Les dates sont imprim?es dans le format de date complet avec le\n" +" fuseau horaire local et accept?es dans le format complet ou l'un\n" +" des formats partiels expliqu?s ci-dessous.\n" +" . Les valeurs de liens sont imprim?es comme indicateurs de noeuds.\n" " Lorsqu'ils sont donn?s comme arguments, les indicateurs de noeuds\n" -" et les cha?nes de cl?s sont tout deux accept?s.\n" -" . les valeurs des liens multiples sont imprim?es comme listes de\n" +" et les cha?nes de cl?s sont tous deux accept?s.\n" +" . Les valeurs des liens multiples sont imprim?es comme listes de\n" " d?signateurs de noeuds, s?par?s par des virgules. Lorsqu'ils sont\n" -" donn?s comme arguments, des d?signateurs de noeuds ou des cl?s\n" -" sous forme de cha?ne de caract?res sont accept?s; une cha?ne de " -"caract?res\n" -" vide, un noeud seul ou une liste de noeuds s?par?s par des virgules \n" -" sont accept?s.\n" -"\n" -"Lorsque des valeurs de propri?t?s doivent contenir des espaces, entourez\n" -"simplement la valeur avec des guillements simples ('') ou doubles (\"\").\n" -"Un espace seul peut ?galement ?tre \"backslash-quoted\". Si une valeur doit\n" -"contenir une caract?re de \"quoting\", il doit ?tre \"backslash-quoted\" ou " -"?tre\n" -"plac? entre guillemets. Par ex.:\n" -" hello world (2 ?l?ments: hello, world)\n" -" \"hello world\" (1 ?l?ment: hello world)\n" -" \"Roch'e\" Compaan (2 ?l?ments: Roch'e Compaan)\n" -" Roch\\'e Compaan (2 ?l?ments: Roch'e Compaan)\n" -" address=\"1 2 3\" (1 ?l?ment: address=1 2 3)\n" -" \\\\ (1 ?l?ment: \\)\n" -" \\n\\r\\t (1 ?l?ment: un passage ? la ligne, un\n" -" retour-chariot et une tabulation)\n" -"\n" -"Lorsque plusieurs noeuds sont sp?cifi?s aux commandes roundup \"get\"\n" -"ou \"set\", les propri?t?s sp?cifi?es sont extraites ou assign?es ?\n" -"tout ces noeuds.\n" -"\n" -"Lorsque plusieurs r?sultats sont renvoy?s par les commandes roundup \"get\"\n" -"ou \"set\", ils sont, par d?faut, imprim?s un par ligne ou, avec \n" -"l'option -c, s?par?s par des virgules.\n" -"\n" -"Lorsqu'une commande change des donn?es, une authentification par nom et mot " -"de\n" -"passe est requise. L'authentification peut ?tre donn?e soit comme \"nom\",\n" -"soit comme \"nom:mot-de-passe.\n" +" donn?s comme arguments, des d?signateurs de noeuds ou des cl?s sous\n" +" forme de cha?ne de caract?res sont accept?s?; une cha?ne de\n" +" caract?res vide, un noeud seul ou une liste de noeuds s?par?s par\n" +" des virgules sont accept?s.\n" +"\n" +"Lorsque des valeurs de propri?t?s doivent contenir des espaces,\n" +"entourez simplement la valeur avec des guillements simples ??'?? ou\n" +"doubles ??\"??. Une espace seule peut ?galement ?tre prot?g?e par un\n" +"anti-slash. Si une valeur doit contenir un guillemet, il doit ?tre\n" +"prot?g? par un anti-slash ou ?tre plac? entre guillemets. Par\n" +"exemple?:\n" +" hello world (2 ?l?ments?: hello, world)\n" +" \"hello world\" (1 ?l?ment?: hello world)\n" +" \"Roch'e\" Compaan (2 ?l?ments?: Roch'e Compaan)\n" +" Roch\\'e Compaan (2 ?l?ments?: Roch'e Compaan)\n" +" address=\"1 2 3\" (1 ?l?ment?: address=1 2 3)\n" +" \\\\ (1 ?l?ment?: \\)\n" +" \\n\\r\\t (1 ?l?ment?: un passage ? la ligne, un\n" +" retour-chariot et une tabulation)\n" +"\n" +"Lorsque plusieurs noeuds sont indiqu?s aux commandes roundup ??get??\n" +"ou ??set??, les propri?t?s sont extraites ou assign?es ? tous ces\n" +"noeuds.\n" +"\n" +"Lorsque plusieurs r?sultats sont renvoy?s par les commandes roundup\n" +"??get?? ou ??set??, ils sont, par d?faut, imprim?s un par ligne ou,\n" +"avec l'option -c, s?par?s par des virgules.\n" +"\n" +"Lorsqu'une commande modifie des donn?es, une authentification par nom\n" +"et mot de passe est requise. L'authentification peut ?tre donn?e soit\n" +"comme ??nom??, soit comme ??nom:mot-de-passe??.\n" " . comme variable d'environnement ROUNDUP_LOGIN\n" " . comme option -u dans la ligne de commande\n" -"Si le nom ou le mot de passe ne sont pas fournis, ils sont demand?s ? la\n" -"ligne de commande\n" +"Si le nom ou le mot de passe ne sont pas fournis, ils sont demand?s ?\n" +"la ligne de commande.\n" "\n" -"Quelques exemples de dates:\n" +"Quelques exemples de dates?:\n" " \"2000-04-17.03:45\" donne \n" " \"2000-04-17\" donne \n" " \"01-25\" donne \n" @@ -245,12 +245,12 @@ " \"8:47:11\" donne \n" " \".\" donne \"maintenant\"\n" "\n" -"Aide sur les commandes:\n" +"Aide sur les commandes?:\n" #: ../roundup/admin.py:240 #, python-format msgid "%s:" -msgstr "%s:" +msgstr "%s?:" #: ../roundup/admin.py:245 msgid "" @@ -263,8 +263,8 @@ " all -- all available help\n" " " msgstr "" -"Usage: help sujet\n" -" Donne de l'aide sur un sujet.\n" +"Utilisation?: help sujet\n" +" Affiche de l'aide sur un sujet.\n" "\n" " commands -- liste les commandes\n" " -- aide sp?cifique ? une commande\n" @@ -275,19 +275,19 @@ #: ../roundup/admin.py:268 #, python-format msgid "Sorry, no help for \"%(topic)s\"" -msgstr "D?sol?, aucune aide n'est disponible ? propos de \"%(topic)s\"" +msgstr "D?sol?, aucune aide n'est disponible au sujet de ??%(topic)s??" # ../roundup/admin.py:338 :394 # ../roundup/admin.py:340 ../roundup/admin.py:396 ../roundup/admin.py:340:396 #: ../roundup/admin.py:340 ../roundup/admin.py:396 msgid "Templates:" -msgstr "Mod?les:" +msgstr "Mod?les?:" # ../roundup/admin.py:341 :405 # ../roundup/admin.py:343 ../roundup/admin.py:407 ../roundup/admin.py:343:407 #: ../roundup/admin.py:343 ../roundup/admin.py:407 msgid "Back ends:" -msgstr "Moteurs de stockage:" +msgstr "Moteurs de stockage?:" #: ../roundup/admin.py:346 msgid "" @@ -314,33 +314,32 @@ " See also initopts help.\n" " " msgstr "" -"Usage: install [template [backend [admin password [key=val[,key=val]]]]]\n" +"Utilisation?: install [template [backend [admin password [key=val[,key=val]]]]]\n" " Installe un nouveau pisteur Roundup.\n" "\n" -" Cette commande demandera le r?pertoire de base du pisteur (s'il\n" -" n'est pas fourni par la variable d'environnement TRACKER_HOME\n" -" ou l'option -i).\n" -" Le mod?le, le moteur de stockage et le mot de passe\n" -" d'administration peuvent ?tre sp?cifi?s dans cet ordre comme\n" -" arguments dans la ligne de commande.\n" -"\n" -" Le dernier argument de la ligne de commande permet de pr?ciser des\n" -" valeurs initiales pour les options de configuration. Par exemple,\n" -" \"web_http_auth=no,rdbms_user=dinsdale\" remplacera les valeurs par\n" -" d?faut pour les options http_auth dans la section [web] and user\n" -" dans la in section [rdbms]. Soyez attentifs ? ne pas mettre " -"d'espace\n" -" dans cet argument! (Entourez-le de quotes si vous devez pr?ciser " -"des\n" -" valeurs contenant des espaces).\n" -"\n" -" La commande \"initialise\" do?t ?tre appel?e apr?s cette commande,\n" -" pour initialiser la base de donn?es du pisteur. Vous pouvez ?diter\n" -" le contenu initial de la base de donn?es avant d'ex?cuter cette\n" -" commande en modifiant la fonction init() du module dbinit.py du\n" -" pisteur.\n" +" Cette commande demandera le r?pertoire de base du pisteur\n" +" (s'il n'est pas fourni par la variable d'environnement\n" +" TRACKER_HOME ou l'option -i). Le mod?le, le moteur de\n" +" stockage et le mot de passe d'administration peuvent ?tre\n" +" renseign?s dans cet ordre comme arguments dans la ligne de\n" +" commande.\n" +"\n" +" Le dernier argument de la ligne de commande permet de pr?ciser\n" +" des valeurs initiales pour les options de configuration. Par\n" +" exemple, ??web_http_auth=no,rdbms_user=dinsdale?? remplacera\n" +" les valeurs par d?faut pour les options http_auth dans la\n" +" section [web] and user dans la in section [rdbms]. Soyez\n" +" attentifs ? ne pas mettre d'espace dans cet argument (prot?ger\n" +" les arguments avec des guillemets si vous devez pr?ciser des\n" +" contenant des espaces).\n" +"\n" +" La commande ??initialise?? do?t ?tre appel?e apr?s cette\n" +" commande, pour initialiser la base de donn?es du pisteur. Vous\n" +" pouvez modifier le contenu initial de la base de donn?es avant\n" +" d'ex?cuter cette commande en modifiant la fonction init() du\n" +" module dbinit.py du pisteur.\n" "\n" -" Voyez ?galement l'aide sur \"initopts\".\n" +" Consultez ?galement l'aide sur ??initopts??.\n" " " # ../roundup/admin.py:367 :464 :525 :604 :654 :712 :733 :761 :832 :899 :970 @@ -354,12 +353,12 @@ #: ../roundup/admin.py:1042 ../roundup/admin.py:1069 ../roundup/admin.py:1136 #: ../roundup/admin.py:1207 msgid "Not enough arguments supplied" -msgstr "Pas assez d'arguments fournis" +msgstr "Pas suffisamment d'arguments fournis" #: ../roundup/admin.py:375 #, python-format msgid "Instance home parent directory \"%(parent)s\" does not exist" -msgstr "Le r?pertoire parent \"%(parent)s\" de l'instance de base n'existe pas" +msgstr "Le r?pertoire parent ??%(parent)s?? de l'instance de base n'existe pas" #: ../roundup/admin.py:383 #, python-format @@ -368,22 +367,22 @@ "If you re-install it, you will lose all the data!\n" "Erase it? Y/N: " msgstr "" -"ATTENTION: Il semble qu'il y ait d?j? un pisteur dans \"%(tracker_home)s\"!\n" -"Si vous le r?installez, vous perdrez toutes les donn?es !\n" -"Effacer le pisteur ? Y/N: " +"ATTENTION?: il semble qu'il y ait d?j? un pisteur dans ??%(tracker_home)s???!\n" +"Si vous le r?installez, vous perdrez toutes les donn?es?!\n" +"Supprimer le pisteur (Y/N)?? " #: ../roundup/admin.py:398 msgid "Select template [classic]: " -msgstr "S?lectionnez un mod?le [classic]: " +msgstr "S?lection du mod?le [classic]?: " #: ../roundup/admin.py:409 msgid "Select backend [anydbm]: " -msgstr "S?lectionnez un moteur de stockage [anydbm]: " +msgstr "S?lection du moteur de stockage [anydbm]: " #: ../roundup/admin.py:419 #, python-format msgid "Error in configuration settings: \"%s\"" -msgstr "Erreur dans les param?tres de la configuration : \"%s\"" +msgstr "Erreur dans les param?tres de la configuration?: ??%s??" #: ../roundup/admin.py:428 #, python-format @@ -393,10 +392,14 @@ " You should now edit the tracker configuration file:\n" " %(config_file)s" msgstr "" +"\n" +"---------------------------------------------------------------------------\n" +" Vous devez maintenant modifier le fichier de configuration du pisteur?:\n" +" %(config_file)s" #: ../roundup/admin.py:438 msgid " ... at a minimum, you must set following options:" -msgstr "" +msgstr " ou au minimum, vous devez d?finir les options suivantes?:" #: ../roundup/admin.py:443 #, python-format @@ -414,6 +417,21 @@ " the above steps.\n" "---------------------------------------------------------------------------\n" msgstr "" +"\n" +" Si vous souhaitez modifier le sch?ma de la base de donn?es, vous\n" +" devez aussi modifier la sch?ma du fichier?:\n" +" %(database_config_file)s\n" +"\n" +" Vous pouvez aussi modifier le fichier d'initialisation de la base de\n" +" donn?es?:\n" +" %(database_init_file)s\n" +"\n" +" Consultez la documentation sur la personnalisation pour plus\n" +" d'informations.\n" +"\n" +" Vous DEVEZ ex?cuter la commande ??roundup-admin initialise?? une fois\n" +" que vous avez r?alis? les ?tapes pr?c?dentes.\n" +"---------------------------------------------------------------------------\n" #: ../roundup/admin.py:461 msgid "" @@ -422,6 +440,10 @@ " in .\n" " " msgstr "" +"Utilisation?: genconfig \n" +" G?n?re un nouveau fichier de configuration du pisteur\n" +" (au format ini) avec des valeurs par d?faut dans\n" +" " #. password #: ../roundup/admin.py:471 @@ -434,26 +456,26 @@ " Execute the tracker's initialisation function dbinit.init()\n" " " msgstr "" -"Usage: initialise [adminpw]\n" +"Utilisation?: initialise [adminpw]\n" " Initialise un nouveau pisteur Roundup.\n" "\n" -" Les d?tails sur l'administrateur sont r?gl?s au cours de cette\n" -" ?tape.\n" +" Les d?tails au sujet de l'administrateur sont d?finis au cours\n" +" de cette ?tape.\n" "\n" -" Ex?cute la fonction d'initialisation dbinit.init() du pisteur\n" +" Ex?cute la fonction d'initialisation dbinit.init() du pisteur.\n" " " #: ../roundup/admin.py:485 msgid "Admin Password: " -msgstr "Mot de passe d'administrateur: " +msgstr "Mot de passe administrateur?: " #: ../roundup/admin.py:486 msgid " Confirm: " -msgstr " Confirmez: " +msgstr " Confirmez?: " #: ../roundup/admin.py:490 msgid "Instance home does not exist" -msgstr "Le r?pertoire de base de l'instance n'existe pas" +msgstr "Le r?pertoire racine de l'instance n'existe pas" #: ../roundup/admin.py:494 msgid "Instance has not been installed" @@ -465,9 +487,9 @@ "If you re-initialise it, you will lose all the data!\n" "Erase it? Y/N: " msgstr "" -"ATTENTION: La base de donn?es est d?j? initialis?e !\n" -"Si vous la r?initialisez, vous perdrez toutes les donn?es !\n" -"Effacer la base de donn?es ? Y/N: " +"ATTENTION?: la base de donn?es est d?j? initialis?e?!\n" +"Si vous la r?initialisez, vous perdrez toutes les donn?es?!\n" +"Supprimez la base de donn?es (Y/N)?? " #: ../roundup/admin.py:520 msgid "" @@ -478,10 +500,10 @@ " by the designators.\n" " " msgstr "" -"Usage: get property indicateur[,indicateur]*\n" -" Donne la propri?t? sp?cifi?e d'un ou plusieurs indicateurs.\n" +"Utilisation?: get property indicateur[,indicateur]*\n" +" Retourne la propri?t? demand?e d'un ou plusieurs indicateurs.\n" "\n" -" Donne la valeur de la propri?t? des noeuds sp?cifi?s par\n" +" Retourne la valeur de la propri?t? des noeuds sp?cifi?s par\n" " les indicateurs.\n" " " @@ -490,9 +512,7 @@ #: ../roundup/admin.py:560 ../roundup/admin.py:575 #, python-format msgid "property %s is not of type Multilink or Link so -d flag does not apply." -msgstr "" -"la propri?t? %s n'est pas de type Multilien ou Lien et donc l'option -d " -"nes'applique pas." +msgstr "la propri?t? %s n'est pas de type Multilien ou Lien et donc l'option -d ne s'applique pas." # ../roundup/admin.py:581 :981 :1030 :1052 # ../roundup/admin.py:1054 ../roundup/admin.py:583:983 :1032:1054 @@ -500,13 +520,12 @@ #: ../roundup/admin.py:1054 #, python-format msgid "no such %(classname)s node \"%(nodeid)s\"" -msgstr "le noeud \"%(nodeid)s\" de classe \"%(classname)s\" n'existe pas" +msgstr "le noeud ??%(nodeid)s?? de classe ??%(classname)s?? n'existe pas" #: ../roundup/admin.py:585 #, python-format msgid "no such %(classname)s property \"%(propname)s\"" -msgstr "" -"la propri?t? \"%(propname)s\" n'existe pas pour la classe \"%(classname)s\"" +msgstr "la propri?t? ??%(propname)s?? n'existe pas pour la classe ??%(classname)s??" #: ../roundup/admin.py:594 msgid "" @@ -523,20 +542,19 @@ " ids for the multilink as comma-separated numbers (ie \"1,2,3\").\n" " " msgstr "" -"Usage: set ?l?ments propri?t?=valeur propri?t?=valeur ...\n" +"Utilisation?: set ?l?ments propri?t?=valeur propri?t?=valeur ...\n" " Assigne les propri?t?s donn?es ? un ou plusieurs ?l?ments.\n" "\n" -" Les ?l?ments sont sp?cifi?s par une classe ou par une liste\n" -" d'indicateurs s?par?s par des virgules (par ex.:\n" -" \"indicateur[,indicateur,...]\").\n" -"\n" -" Cette commande assigne les valeurs donn?es aux propri?t?s de tout\n" -" les indicateurs sp?cifi?s. Si la valeur est absente (par ex.:\n" -" \"propri?t?=\") alors la propri?t? est #effac?e. Si la propri?t?\n" -" est un lien multiple, les identificateurs attach?s ? ce lien sont\n" -" sp?cifi?s comme des nombres s?par?s par des virgules (par ex.: \n" -" \"1,2,3\").\n" -" " +" Les ?l?ments sont indiqu?s par une classe ou par une liste\n" +" d'indicateurs s?par?s par des virgules (par\n" +" ex. ??indicateur[,indicateur,...]??).\n" +"\n" +" Cette commande assigne les valeurs donn?es aux propri?t?s de\n" +" tous les indicateurs indiqu?s. Si la valeur est absente (par\n" +" ex. ??propri?t?=??) alors la propri?t? est effac?e. Si la\n" +" propri?t? est un lien multiple, les identificateurs attach?s ?\n" +" ce lien sont indiqu?s comme des nombres s?par?s par des\n" +" virgules (par ex. ??1,2,3??)." #: ../roundup/admin.py:648 msgid "" @@ -548,11 +566,11 @@ " value.\n" " " msgstr "" -"Usage: find nom-de-classe propri?t?=valeur ...\n" -" Recherche les noeuds de la classe sp?cifi?e, ayant une propri?t? de\n" +"Utilisation?: find nom-de-classe propri?t?=valeur ...\n" +" Recherche les noeuds de la classe indiqu?e, ayant une propri?t? de\n" " lien donn?e.\n" "\n" -" Recherche les noeuds de la classe sp?cifi?e, ayant une propri?t? de\n" +" Recherche les noeuds de la classe indiqu?e, ayant une propri?t? de\n" " lien donn?e. La valeur peut ?tre soit l'identificateur de noeud du\n" " noeud li?, ou sa valeur de cl?.\n" " " @@ -563,7 +581,7 @@ #: ../roundup/admin.py:920 #, python-format msgid "%(classname)s has no property \"%(propname)s\"" -msgstr "%(classname)s n'a pas de propri?t? \"%(propname)s\"" +msgstr "%(classname)s n'a pas de propri?t? ??%(propname)s??" #: ../roundup/admin.py:708 msgid "" @@ -573,21 +591,21 @@ " This lists the properties for a given class.\n" " " msgstr "" -"Usage: specification nom-de-classe\n" -" Donne les propri?t?s pour un nom de classe donn?.\n" +"Utilisation?: specification nom-de-classe\n" +" Affiche les propri?t?s de la classe nomm?e.\n" "\n" -" Cette commande ?num?re les propri?t?s d'une classe donn?e.\n" +" Cette commande ?num?re les propri?t?s de la classe nomm?e.\n" " " #: ../roundup/admin.py:723 #, python-format msgid "%(key)s: %(value)s (key property)" -msgstr "%(key)s: %(value)s (propri?t? cl?)" +msgstr "%(key)s?: %(value)s (propri?t? cl?)" #: ../roundup/admin.py:725 #, python-format msgid "%(key)s: %(value)s" -msgstr "%(key)s: %(value)s" +msgstr "%(key)s?: %(value)s" #: ../roundup/admin.py:728 msgid "" @@ -598,11 +616,11 @@ " node.\n" " " msgstr "" -"Usage: display indicateur[,indicateur]*\n" -" Donne les valeurs des propri?t?s pour les noeuds sp?cifi?s.\n" +"Utilisation?: display indicateur[,indicateur]*\n" +" Affiche les valeurs des propri?t?s des noeuds indiqu?s.\n" "\n" " Cette commande ?num?re les propri?t?s et leurs valeurs du ou\n" -" des noeuds sp?cifi?s.\n" +" des noeuds indiqu?s.\n" " " #: ../roundup/admin.py:752 @@ -621,37 +639,38 @@ " command.\n" " " msgstr "" -"Usage: create nom-de-classe propri?t?=valeur ...\n" +"Utilisation?: create nom-de-classe propri?t?=valeur ...\n" " Cr?e une nouvelle entr?e d'une classe donn?e.\n" "\n" -" Cette commande cr?e une nouvelle entr?e d'une classe sp?cifi?e en\n" -" utilisant les propri?t?s \"nom=valeur\" donn?es en arguments dans\n" -" la ligne de commande, apr?s la commande \"create\".\n" +" Cette commande cr?e une nouvelle entr?e d'une classe indiqu?e\n" +" en utilisant les propri?t?s ??nom=valeur?? donn?es en\n" +" arguments de la ligne de commande, apr?s la commande\n" +" ??create??.\n" " " #: ../roundup/admin.py:782 #, python-format msgid "%(propname)s (Password): " -msgstr "%(propname)s (Mot de passe): " +msgstr "%(propname)s (mot de passe)?: " #: ../roundup/admin.py:784 #, python-format msgid " %(propname)s (Again): " -msgstr " %(propname)s (? nouveau): " +msgstr " %(propname)s (? nouveau)?: " #: ../roundup/admin.py:786 msgid "Sorry, try again..." -msgstr "D?sol?, essayez encore..." +msgstr "D?sol?, essayez ? nouveau..." #: ../roundup/admin.py:790 #, python-format msgid "%(propname)s (%(proptype)s): " -msgstr "%(propname)s (%(proptype)s): " +msgstr "%(propname)s (%(proptype)s)?: " #: ../roundup/admin.py:808 #, python-format msgid "you must provide the \"%(propname)s\" property." -msgstr "Vous devez fournir la propri?t? \"%(propname)s\"." +msgstr "vous devez renseigner la propri?t? ??%(propname)s??." #: ../roundup/admin.py:819 msgid "" @@ -668,20 +687,19 @@ " for every class instance.\n" " " msgstr "" -"Usage: list nom-de-classe [propri?t?]\n" -" Donne toutes les instances d'une classe.\n" +"Utilisation: list nom-de-classe [propri?t?]\n" +" Liste toutes les instances d'une classe.\n" "\n" -" ?num?re toutes les instances d'une classe donn?e. Si la propri?t?\n" -" n'est pas sp?cifi?e, la propri?t? \"label\" est utilis?e. Cette\n" -" propri?t? ?tiquette est d?termin?e selon l'ordre suivant: la cl?,\n" -" les propri?t?s \"name\", \"title\" et la premi?re propri?t? par\n" -" ordre alphab?tique.\n" +" ?num?re toutes les instances d'une classe donn?e. Si la\n" +" propri?t? n'est pas indiqu?e, la propri?t? ??label?? est\n" +" utilis?e. Cette propri?t? ?tiquette est d?termin?e selon\n" +" l'ordre suivant?: la cl?, les propri?t?s ??name??, ??title??\n" +" et la premi?re propri?t? par ordre alphab?tique.\n" "\n" " Avec les options -c, -S ou -s, affiche une liste des\n" -" identificateurs d'?l?ments si aucune propri?t? n'est sp?cifi?e.\n" -" Si une propri?t? est sp?cifi?e, affiche une liste de cette " -"propri?t?\n" -" pour chaque instance de cette classe.\n" +" identificateurs d'?l?ments si aucune propri?t? n'est indiqu?e.\n" +" Si une propri?t? est indiqu?e, affiche une liste de cette\n" +" propri?t? pour chaque instance de cette classe.\n" " " #: ../roundup/admin.py:832 @@ -691,7 +709,7 @@ #: ../roundup/admin.py:868 #, python-format msgid "%(nodeid)4s: %(value)s" -msgstr "%(nodeid)4s: %(value)s" +msgstr "%(nodeid)4s?: %(value)s" #: ../roundup/admin.py:872 msgid "" @@ -724,15 +742,15 @@ " will result in a the 4 character wide \"Name\" column.\n" " " msgstr "" -"Usage: table nom-de-classe [propri?t?[,propri?t?]*]\n" +"Utilisation?: table nom-de-classe [propri?t?[,propri?t?]*]\n" " Liste les instances d'une classe, sous forme de tableau.\n" "\n" " Liste toutes les instances d'une classe. Si aucune propri?t? n'est\n" -" sp?cifi?e, toutes les propri?t?s sont affich?es. Par d?faut,\n" +" indiqu?e, toutes les propri?t?s sont affich?es. Par d?faut,\n" " les largeurs de colonnes sont de la largeur de la colonne la plus\n" -" large. La largeur peut ?tre sp?cifi?e explicitement en d?finissant\n" -" la propri?t? comme \"nom-de-propri?t?:largeur\".\n" -" Par ex.:\n" +" large. La largeur peut ?tre indiqu?e explicitement en d?finissant\n" +" la propri?t? comme ??nom-de-propri?t?:largeur??.\n" +" Par exemple?:\n" "\n" " roundup> table priority id,name:10\n" " Id Name\n" @@ -742,8 +760,8 @@ " 4 feature\n" "\n" " De m?me, pour fixer la largeur de la colonne sur la largeur de\n" -" l'?tiquette, laissez le \":\" final sans donner de largeur pour \n" -" la propri?t?. Par ex.::\n" +" l'?tiquette, laissez le ??:?? final sans donner de largeur pour \n" +" la propri?t?. Par exemple?:\n" "\n" " roundup> table priority id,name:\n" " Id Name\n" @@ -752,13 +770,13 @@ " 3 usab\n" " 4 feat\n" "\n" -" donnera une colonne \"Name\" large de 4 caract?res.\n" +" donnera une colonne ??Name?? large de 4 caract?res.\n" " " #: ../roundup/admin.py:916 #, python-format msgid "\"%(spec)s\" not name:width" -msgstr "\"%(spec)s\" ne correspond pas au format \"nom:largeur\"" +msgstr "??%(spec)s?? ne correspond pas au format ??nom:largeur??" #: ../roundup/admin.py:966 msgid "" @@ -769,8 +787,8 @@ "designator.\n" " " msgstr "" -"Usage: history indicateur\n" -" Donne l'historique pour un indicateur.\n" +"Utilisation?: history indicateur\n" +" Affiche le journal des entr?es d'un indicateur.\n" "\n" " Liste les entr?es de journal pour le noeud identifi? par\n" " l'indicateur.\n" @@ -789,16 +807,16 @@ " they are successful.\n" " " msgstr "" -"Usage: commit\n" +"Utilisation?: commit\n" " Valide les changements apport?s ? la base de donn?es lors d'une\n" " session interactive.\n" "\n" -" Les changements effectu?s lors d'une session interactive ne sont\n" -" pas automatiquement enregistr?s dans la base de donn?es - Ils\n" -" doivent ?tre valid?s par cette commande.\n" +" Les changements effectu?s lors d'une session interactive ne\n" +" sont pas automatiquement enregistr?s dans la base de donn?es -\n" +" ils doivent ?tre valid?s par cette commande.\n" "\n" -" Les commandes \"one-off\" donn?es en ligne de commande sont\n" -" automatiquement valid?es si elles r?ussissent\n" +" Les commandes ??one-off?? en ligne de commande sont\n" +" automatiquement valid?es si elles r?ussissent.\n" " " #: ../roundup/admin.py:1001 @@ -812,15 +830,16 @@ " immediately after would make no changes to the database.\n" " " msgstr "" -"Usage: rollback\n" -" Annule tout les changements en attente de validation pour la base\n" +"Utlisation?: rollback\n" +" Annule tous les changements en attente de validation pour la base\n" " de donn?es.\n" "\n" -" Les changements effectu?s lors d'une session interactive ne sont\n" -" pas automatiquement enregistr?s dans la base de donn?es - Ils\n" -" doivent ?tre valid?s manuellement. Cette commande annule tout ces\n" -" changements, de telle mani?re qu'une validation effectu?e\n" -" imm?diatement n'apporterait aucun changement ? la base de donn?es.\n" +" Les changements effectu?s lors d'une session interactive ne\n" +" sont pas automatiquement enregistr?s dans la base de donn?es -\n" +" ils doivent ?tre valid?s manuellement. Cette commande annule\n" +" tout ces changements, de telle mani?re qu'une validation\n" +" effectu?e imm?diatement n'apporterait aucun changement ? la\n" +" base de donn?es.\n" " " #: ../roundup/admin.py:1013 @@ -832,12 +851,12 @@ " by the list or find commands, and its key value may be re-used.\n" " " msgstr "" -"Usage: retire indicateur[,indicateur]*\n" -" Abandonne le noeud sp?cifi? par l'indicateur.\n" +"Utilisation?: retire indicateur[,indicateur]*\n" +" Retire le noeud indiqu? par l'indicateur.\n" "\n" " Cette action indique qu'un noeud particulier ne doit plus ?tre\n" -" trouv? par les commandes \"list\" ou \"find\", et que sa valeur\n" -" de cl? peut ?tre r?-utilis?e.\n" +" trouv? par les commandes ??list?? ou ??find??, et que sa\n" +" valeur de cl? peut ?tre r?-utilis?e.\n" " " #: ../roundup/admin.py:1036 @@ -848,11 +867,12 @@ " The given nodes will become available for users again.\n" " " msgstr "" -"Usage: restore indicateur[,indicateur]*\n" -" Restaure le ou les noeuds abandonn?s, sp?cifi?s par le ou les\n" +"Utilisaiton?: restore indicateur[,indicateur]*\n" +" Restaure le ou les noeuds retir?s, indiqu?s par le ou les\n" " indicateurs.\n" "\n" -" Les noeuds sp?cifi?s seront ? nouveau acessibles aux utilisateurs.\n" +" Les noeuds indiqu?s seront ? nouveau acessibles aux\n" +" utilisateurs.\n" " " #. grab the directory to export to @@ -868,11 +888,11 @@ " destination directory.\n" " " msgstr "" -"Usage: export [classe[,classe]] r?pertoire-d'exportation\n" +"Utilisation?: export [classe[,classe]] r?pertoire-d'exportation\n" " Exporte la base de donn?es vers des fichiers dans un format\n" " aux valeurs s?par?es par des double-points.\n" "\n" -" Limite ?ventuellement l'exportation aux classes sp?cifi?es.\n" +" Limite ?ventuellement l'exportation aux classes indiqu?es.\n" "\n" " Cette action exporte les donn?es actuelles de la base de donn?es,\n" " vers des fichiers plac?s dans le r?pertoire d?sign?, et dans un \n" @@ -901,7 +921,7 @@ " database (or, tediously, retire all the old data.)\n" " " msgstr "" -"Usage: import r?pertoire-d'importation\n" +"Utilisation: import r?pertoire-d'importation\n" " Importe une base de donn?es ? partir d'un r?pertoire contenant des\n" " fichiers, d'un format aux valeurs s?par?es par des doubles points,\n" " deux par classe ? importer.\n" @@ -910,18 +930,18 @@ "\n" " .csv\n" " Celui-ci d?finit les m?mes propri?t?s que la classe (avec\n" -" une ligne \"header\" donnant ces noms de propri?t?s).\n" +" une ligne ??header?? donnant ces noms de propri?t?s).\n" " -journals.csv\n" " Celui-ci d?finit les journaux pour les ?l?ments import?s.\n" "\n" " Les noeuds import?s auront les m?mes identificateurs de noeuds\n" -" (\"nodeid\") que ceux d?finis dans le fichier d'importation,\n" +" (??nodeid??) que ceux d?finis dans le fichier d'importation,\n" " rempla?ant d?s lors tout contenu existant.\n" "\n" " Les nouveaux noeuds sont ajout?s ? la base de donn?es - si, en\n" " fait, vous d?sirez cr?er une nouvelle base de donn?es avec les\n" " donn?es import?es, cr?ez plut?t une nouvelle base de donn?es (ou,\n" -" plus p?niblement, \"abandonnez\" toutes les anciennes donn?es).\n" +" plus p?niblement, ??abandonnez?? toutes les anciennes donn?es).\n" " " #: ../roundup/admin.py:1189 @@ -945,30 +965,30 @@ "\n" " " msgstr "" -"Usage: pack p?riode | date\n" +"Utilisation: pack p?riode | date\n" "\n" -" Efface les entr?es de journaux ant?rieures ? une p?riode\n" -" ou ? une date donn?e.\n" +" Efface les entr?es de journaux ant?rieures ? une p?riode ou ?\n" +" une date donn?e.\n" "\n" -" Une p?riode est sp?cifi?e en utilisant les suffixes \"y\" (pour\n" -" \"year\" - ann?e), \"m\" (pour \"month\" - mois), et \"d\" (pour\n" -" \"day\" - jour).\n" +" Une p?riode est indiqu?e en utilisant les suffixes ??y?? (pour\n" +" ??year?? - ann?e), ??m?? (pour ??month?? - mois), et ??d??\n" +" (pour ??day?? - jour).\n" "\n" -" Le suffixe \"w\" (pour \"week\" - semaine) signifie 7 jours.\n" +" Le suffixe ??w?? (pour ??week?? - semaine) signifie 7 jours.\n" "\n" -" \"3y\" signifie 3 ans\n" -" \"2y 1m\" signifie 2 ans et un mois\n" -" \"1m 25d\" signifie un an et 25 jours\n" -" \"2w 3d\" signifie 2 semaines et 3 jours\n" +" ??3y?? signifie 3 ans\n" +" ??2y 1m?? signifie 2 ans et un mois\n" +" ??1m 25d?? signifie un an et 25 jours\n" +" ??2w 3d?? signifie 2 semaines et 3 jours\n" "\n" -" Le format de date est \"AAAA-MM-JJ\", par ex.:\n" +" Le format de date est ??AAAA-MM-JJ??, par exemple?:\n" " 2001-01-01\n" "\n" " " #: ../roundup/admin.py:1217 msgid "Invalid format" -msgstr "Format invalide" +msgstr "Format non valide" #: ../roundup/admin.py:1227 msgid "" @@ -979,17 +999,17 @@ " This will typically happen automatically.\n" " " msgstr "" -"Usage: reindex [classname|designator]*\n" +"Utilisation: reindex [classname|designator]*\n" " Reg?n?re les index de recherche d'un pisteur.\n" "\n" " Cette commande reg?n?rera les index de recherche d'un pisteur.\n" -" Cette manoeuvre doit normalement s'effectuer automatiquement.\n" +" Cette op?ration est normalement effectuer automatiquement.\n" " " #: ../roundup/admin.py:1241 #, python-format msgid "no such item \"%(designator)s\"" -msgstr "" +msgstr "pas d'?l?ment ??%(designator)s??" #: ../roundup/admin.py:1251 msgid "" @@ -997,49 +1017,49 @@ " Display the Permissions available to one or all Roles.\n" " " msgstr "" -"Usage: security [nom-de-r?le]\n" +"Utilisation?: security [nom-de-r?le]\n" " Affiche les permissions disponible pour un ou plusieurs r?les.\n" " " #: ../roundup/admin.py:1259 #, python-format msgid "No such Role \"%(role)s\"" -msgstr "Ce r?le \"%(role)s\" n'existe pas" +msgstr "Ce r?le ??%(role)s?? n'existe pas" #: ../roundup/admin.py:1265 #, python-format msgid "New Web users get the Roles \"%(role)s\"" -msgstr "Les nouveaux utilisateurs Web ont les r?les \"%(role)s\"" +msgstr "Les nouveaux utilisateurs Web ont les r?les ??%(role)s??" #: ../roundup/admin.py:1267 #, python-format msgid "New Web users get the Role \"%(role)s\"" -msgstr "Les nouveaux utilisateurs Web ont le r?le \"%(role)s\"" +msgstr "Les nouveaux utilisateurs Web ont le r?le ??%(role)s??" #: ../roundup/admin.py:1270 #, python-format msgid "New Email users get the Roles \"%(role)s\"" -msgstr "Les nouveaux utilisateurs Email ont les r?les \"%(role)s\"" +msgstr "Les nouveaux utilisateurs Courriel ont les r?les ??%(role)s??" #: ../roundup/admin.py:1272 #, python-format msgid "New Email users get the Role \"%(role)s\"" -msgstr "Les nouveaux utilisateurs Email ont le r?le \"%(role)s\"" +msgstr "Les nouveaux utilisateurs Courriel ont le r?le ??%(role)s??" #: ../roundup/admin.py:1275 #, python-format msgid "Role \"%(name)s\":" -msgstr "R?le \"%(name)s\":" +msgstr "R?le ??%(name)s???:" #: ../roundup/admin.py:1280 #, python-format msgid " %(description)s (%(name)s for \"%(klass)s\": %(properties)s only)" -msgstr "" +msgstr " %(description)s (%(name)s pour ??%(klass)s???: %(properties)s uniquement)" #: ../roundup/admin.py:1283 #, python-format msgid " %(description)s (%(name)s for \"%(klass)s\" only)" -msgstr " %(description)s (%(name)s pour \"%(klass)s\" uniquement)" +msgstr " %(description)s (%(name)s pour ??%(klass)s?? uniquement)" #: ../roundup/admin.py:1286 #, python-format @@ -1049,28 +1069,28 @@ #: ../roundup/admin.py:1315 #, python-format msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)" -msgstr "Commande inconnue \"%(command)s\" (\"help commands\" pour la liste)" +msgstr "Commande inconnue ??%(command)s?? (??help commands?? pour la liste)" #: ../roundup/admin.py:1321 #, python-format msgid "Multiple commands match \"%(command)s\": %(list)s" -msgstr "Plusieurs commandes correspondent ? \"%(command)s\": %(list)s" +msgstr "Plusieurs commandes correspondent ? ??%(command)s???: %(list)s" #: ../roundup/admin.py:1328 msgid "Enter tracker home: " -msgstr "Entrez le r?pertoire de base du pisteur: " +msgstr "Saisissez le r?pertoire racine du pisteur?: " # ../roundup/admin.py:1332 :1338 :1358 # ../roundup/admin.py:1335:1341:1361 #: ../roundup/admin.py:1335 ../roundup/admin.py:1341 ../roundup/admin.py:1361 #, python-format msgid "Error: %(message)s" -msgstr "Erreur: %(message)s" +msgstr "Erreur?: %(message)s" #: ../roundup/admin.py:1349 #, python-format msgid "Error: Couldn't open tracker: %(message)s" -msgstr "Erreur: impossible d'ouvrir le pisteur: %(message)s" +msgstr "Erreur?: impossible d'ouvrir le pisteur, %(message)s" #: ../roundup/admin.py:1374 #, python-format @@ -1078,12 +1098,12 @@ "Roundup %s ready for input.\n" "Type \"help\" for help." msgstr "" -"Roundup %s pr?t pour l'entr?e.\n" -"Entrez \"help\" pour l'aide." +"Roundup %s est pr?t pour la saisie.\n" +"Saisissez ??help?? pour l'aide." #: ../roundup/admin.py:1379 msgid "Note: command history and editing not available" -msgstr "Note: l'historique et l'?dition des commandes n'est pas disponible" +msgstr "Note?: l'historique et l'?dition des commandes n'est pas disponible" #: ../roundup/admin.py:1383 msgid "roundup> " @@ -1095,12 +1115,12 @@ #: ../roundup/admin.py:1395 msgid "There are unsaved changes. Commit them (y/N)? " -msgstr "Des changements n'ont pas ?t? enregistr?s. ? valider ? (y/N)? " +msgstr "Des changements n'ont pas ?t? enregistr?s, les valider (y/N)??" #: ../roundup/backends/back_anydbm.py:2001 #, python-format msgid "WARNING: invalid date tuple %r" -msgstr "" +msgstr "ATTENTION?: tuple de date non valide %r" #: ../roundup/backends/rdbms_common.py:1434 msgid "create" @@ -1120,7 +1140,7 @@ #: ../roundup/backends/rdbms_common.py:1748 msgid "retired" -msgstr "abandonn?" +msgstr "retir?" #: ../roundup/backends/rdbms_common.py:1778 msgid "restored" @@ -1138,14 +1158,12 @@ #: ../roundup/cgi/actions.py:91 msgid "No ID entered" -msgstr "Aucun identifiant entr?" +msgstr "Aucun identifiant saisi" #: ../roundup/cgi/actions.py:97 #, python-format msgid "\"%(input)s\" is not an ID (%(classname)s ID required)" -msgstr "" -"\"%(input)s\" n'est pas un identifiant (l'identifiant de %(classname)s est " -"requis)" +msgstr "??%(input)s?? n'est pas un identifiant (l'identifiant de %(classname)s est requis)" #: ../roundup/cgi/actions.py:117 msgid "You may not retire the admin or anonymous user" @@ -1154,7 +1172,7 @@ #: ../roundup/cgi/actions.py:124 #, python-format msgid "%(classname)s %(itemid)s has been retired" -msgstr "%(classname)s %(itemid)s a ?t? abandonn?" +msgstr "%(classname)s %(itemid)s a ?t? retir?" # ../roundup/cgi/actions.py:174 :202 # ../roundup/cgi/actions.py:174:202 @@ -1166,21 +1184,21 @@ # ../roundup/cgi/actions.py:180:209 #: ../roundup/cgi/actions.py:180 ../roundup/cgi/actions.py:209 msgid "You do not have permission to store queries" -msgstr "Vous n'avez pas la permission de sauvegarder des requ?tes" +msgstr "Vous n'avez pas la permission d'enregistrer des requ?tes" #: ../roundup/cgi/actions.py:297 #, python-format msgid "Not enough values on line %(line)s" -msgstr "Pas assez de valeurs sur la ligne %(line)s" +msgstr "Pas suffisament de valeurs sur la ligne %(line)s" #: ../roundup/cgi/actions.py:344 msgid "Items edited OK" -msgstr "Les ?l?ments ont bien ?t? modifi?s" +msgstr "Les ?l?ments ont ?t? modifi?s avec succ?s" #: ../roundup/cgi/actions.py:404 #, python-format msgid "%(class)s %(id)s %(properties)s edited ok" -msgstr "%(class)s %(id)s %(properties)s modifi?(s)" +msgstr "%(class)s %(id)s %(properties)s modifi?(s) avec succ?s" #: ../roundup/cgi/actions.py:407 #, python-format @@ -1211,14 +1229,12 @@ msgid "" "Edit Error: someone else has edited this %s (%s). View their changes in a new window." -msgstr "" -"Erreur de modification: quelqu'un d'autre a ?dit? ce %s (%s). Voir ses modifications dans une nouvelle fen?tre." +msgstr "Erreur de modification?: quelqu'un d'autre a modifi? ce %s (%s). Consultez ses modifications dans une nouvelle fen?tre." #: ../roundup/cgi/actions.py:565 #, python-format msgid "Edit Error: %s" -msgstr "Erreur de modification: %s" +msgstr "Erreur de modification?: %s" # ../roundup/cgi/actions.py:596 :607 :778 :797 # ../roundup/cgi/actions.py:596:607 :778:797 @@ -1226,7 +1242,7 @@ #: ../roundup/cgi/actions.py:778 ../roundup/cgi/actions.py:797 #, python-format msgid "Error: %s" -msgstr "Erreur: %s" +msgstr "Erreur?: %s" #: ../roundup/cgi/actions.py:633 msgid "" @@ -1234,9 +1250,8 @@ "(a Mozilla bug may cause this message to show up erroneously, please check " "your email)" msgstr "" -"La cl? ? usage unique est invalide !\n" -"(un bug dans Mozilla peut provoquer une apparition erron?e de ce message, " -"veuillez v?rifier votre courriel)" +"La cl? ? usage unique n'est pas valide.\n" +"Un bug dans Mozilla peut provoquer une apparition erron?e de ce message, v?rifiez votre courriel." #: ../roundup/cgi/actions.py:675 #, python-format @@ -1249,11 +1264,11 @@ #: ../roundup/cgi/actions.py:692 msgid "Unknown email address" -msgstr "Adresse courriel inconnue" +msgstr "Adresse ?lectronique inconnue" #: ../roundup/cgi/actions.py:697 msgid "You need to specify a username or address" -msgstr "Vous devez sp?cifier un nom d'utilisateur ou une adresse courriel" +msgstr "Vous devez indiquer un nom d'utilisateur ou une adresse ?lectronique" #: ../roundup/cgi/actions.py:722 #, python-format @@ -1262,11 +1277,11 @@ #: ../roundup/cgi/actions.py:741 msgid "You are now registered, welcome!" -msgstr "Vous ?tes d?sormais inscrit, bienvenue !" +msgstr "Vous ?tes d?sormais inscrit, bienvenue?!" #: ../roundup/cgi/actions.py:786 msgid "It is not permitted to supply roles at registration." -msgstr "" +msgstr "Impossible de renseigner les r?les ? l'inscription." #: ../roundup/cgi/actions.py:878 msgid "You are logged out" @@ -1280,7 +1295,7 @@ # ../roundup/cgi/actions.py:930:934 #: ../roundup/cgi/actions.py:930 ../roundup/cgi/actions.py:934 msgid "Invalid login" -msgstr "Tentative de connexion invalide" +msgstr "Tentative de connexion non valide" #: ../roundup/cgi/actions.py:940 msgid "You do not have permission to login" @@ -1294,18 +1309,18 @@ "

    Debugging information follows

    " msgstr "" "

    Erreur de mod?le

    \n" -"

    %(exc_type)s: %(exc_value)s

    \n" +"

    %(exc_type)s?: %(exc_value)s

    \n" "

    Les informations de d?boguage suivent

    " #: ../roundup/cgi/cgitb.py:64 #, python-format msgid "
  • \"%(name)s\" (%(info)s)
  • " -msgstr "
  • \"%(name)s\" (%(info)s)
  • " +msgstr "
  • ??%(name)s?? (%(info)s)
  • " #: ../roundup/cgi/cgitb.py:67 #, python-format msgid "
  • Looking for \"%(name)s\", current path:
      %(path)s
  • " -msgstr "
  • Recherche de \"%(name)s\", chemin actuel:
      %(path)s
  • " +msgstr "
  • Recherche de ??%(name)s??, chemin actuel?:
      %(path)s
  • " #: ../roundup/cgi/cgitb.py:71 #, python-format @@ -1315,7 +1330,7 @@ #: ../roundup/cgi/cgitb.py:76 #, python-format msgid "A problem occurred in your template \"%s\"." -msgstr "Un probl?me est apparu dans votre mod?le \"%s\"." +msgstr "Un probl?me est apparu dans votre mod?le ??%s??." #: ../roundup/cgi/cgitb.py:84 #, python-format @@ -1331,35 +1346,30 @@ "\n" "
  • Lors de l'?valuation de l'expression %(info)r ? la ligne %(line)d\n" "\n" -" \n" +" \n" " %(globals)s\n" " %(locals)s\n" "
    Variables courantes:
    Variables actuelles?:
  • \n" #: ../roundup/cgi/cgitb.py:103 msgid "Full traceback:" -msgstr "Historique complet:" +msgstr "Historique complet?:" #: ../roundup/cgi/cgitb.py:116 #, python-format msgid "%(exc_type)s: %(exc_value)s" -msgstr "%(exc_type)s: %(exc_value)s" +msgstr "%(exc_type)s?: %(exc_value)s" #: ../roundup/cgi/cgitb.py:120 msgid "" "

    A problem occurred while running a Python script. Here is the sequence of " "function calls leading up to the error, with the most recent (innermost) " "call first. The exception attributes are:" -msgstr "" -"

    Un probl?me est apparu lors de l'ex?cution d'un script Python. Voici la " -"suite d'appels de fonction menant ? l'erreur, avec l'appel le plus r?cent " -"(le plus imbriqu?) d'abord. Les attributs de l'exception sont:" +msgstr "

    Un probl?me est apparu lors de l'ex?cution d'un script Python. Voici la suite d'appels de fonction menant ? l'erreur, avec l'appel le plus r?cent (le plus imbriqu?) d'abord. Les attributs de l'exception sont?:" #: ../roundup/cgi/cgitb.py:129 msgid "<file is None - probably inside eval or exec>" -msgstr "" -"<\"file\" est ? \"None\" - probablement dans un eval ou un " -"exec>" +msgstr "<??file?? est ? ??None?? - probablement dans un eval ou un exec>" #: ../roundup/cgi/cgitb.py:138 #, python-format @@ -1370,7 +1380,7 @@ # ../roundup/cgi/cgitb.py:172:178 #: ../roundup/cgi/cgitb.py:172 ../roundup/cgi/cgitb.py:178 msgid "undefined" -msgstr "non d?fini" +msgstr "ind?fini" #: ../roundup/cgi/client.py:49 msgid "" @@ -1388,12 +1398,12 @@ #: ../roundup/cgi/client.py:308 msgid "Form Error: " -msgstr "Erreur de formulaire: " +msgstr "Erreur de formulaire?: " #: ../roundup/cgi/client.py:363 #, python-format msgid "Unrecognized charset: %r" -msgstr "Table de caract?res non reconnue: %r" +msgstr "Jeu de caract?res non reconnu?: %r" #: ../roundup/cgi/client.py:491 msgid "Anonymous users are not allowed to use the web interface" @@ -1414,15 +1424,12 @@ msgid "" "%(starttag)sCache hits: %(cache_hits)d, misses %(cache_misses)d. Loading " "items: %(get_items)f secs. Filtering: %(filtering)f secs.%(endtag)s\n" -msgstr "" -"%(starttag)sAcc?s au cache: %(cache_hits)d, rat?s %(cache_misses)d. " -"Chargement d'?l?ments: %(get_items)f secondes. Filtrage: %(filtering)f " -"secondes.%(endtag)s\n" +msgstr "%(starttag)sAcc?s au cache?: %(cache_hits)d, manqu?s %(cache_misses)d. Chargement d'?l?ments?: %(get_items)f secondes. Filtrage?: %(filtering)f secondes.%(endtag)s\n" #: ../roundup/cgi/form_parser.py:283 #, python-format msgid "link \"%(key)s\" value \"%(value)s\" not a designator" -msgstr "la valeur \"%(value)s\" du lien \"%(key)s\" n'est pas un indicateur" +msgstr "la valeur ??%(value)s?? du lien ??%(key)s?? n'est pas un indicateur" #: ../roundup/cgi/form_parser.py:290 #, python-format @@ -1434,9 +1441,7 @@ msgid "" "You have submitted a %(action)s action for the property \"%(property)s\" " "which doesn't exist" -msgstr "" -"Vous avez demand? une action \"%(action)s\" sur une propri?t? \"%(property)s" -"\" qui n'existe pas" +msgstr "Vous avez demand? une action ??%(action)s?? sur une propri?t? ??%(property)s?? qui n'existe pas" # ../roundup/cgi/form_parser.py:331 :357 # ../roundup/cgi/form_parser.py:331:357 @@ -1454,9 +1459,7 @@ #: ../roundup/cgi/form_parser.py:395 #, python-format msgid "property \"%(propname)s\": \"%(value)s\" not currently in list" -msgstr "" -"propri?t? \"%(propname)s\": \"%(value)s\" n'est pas actuellement dans la " -"liste" +msgstr "propri?t? ??%(propname)s???: ??%(value)s?? n'est pas actuellement dans la liste" #: ../roundup/cgi/form_parser.py:512 #, python-format @@ -1502,7 +1505,7 @@ #: ../roundup/cgi/templating.py:711 msgid "New node - no history" -msgstr "Nouveau noeud - pas d'historique" +msgstr "Nouveau n~ud - pas d'historique" #: ../roundup/cgi/templating.py:811 msgid "Submit Changes" @@ -1515,7 +1518,7 @@ #: ../roundup/cgi/templating.py:894 #, python-format msgid "%s: %s\n" -msgstr "%s: %s\n" +msgstr "%s?: %s\n" #: ../roundup/cgi/templating.py:907 #, python-format @@ -1547,18 +1550,16 @@ #: ../roundup/cgi/templating.py:1017 #, python-format msgid "%s: (no value)" -msgstr "%s: (pas de valeur)" +msgstr "%s?: (pas de valeur)" #: ../roundup/cgi/templating.py:1029 msgid "" "This event is not handled by the history display!" -msgstr "" -"Cet ?v?nement n'est pas g?r? par l'affichage de l'historique !" +msgstr "Cet ?v?nement n'est pas g?r? par l'affichage de l'historique." #: ../roundup/cgi/templating.py:1041 msgid "Note:" -msgstr "Note:" +msgstr "Note?:" #: ../roundup/cgi/templating.py:1050 msgid "History" @@ -1587,7 +1588,7 @@ #: ../roundup/cgi/templating.py:1331 msgid "*encrypted*" -msgstr "*encrypt?*" +msgstr "*crypt?*" #: ../roundup/cgi/templating.py:1514 msgid "" @@ -1611,31 +1612,23 @@ msgid "" "Not a date spec: \"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", \"HH:MM:SS\" or " "\"yyyy-mm-dd.HH:MM:SS.SSS\"" -msgstr "" -"Ceci n'est pas une repr?sentation de date: \"aaaa-mm-jj\", \"mm-jj\", \"HH:MM" -"\", \"HH:MM:SS\" or \"aaaa-mm-jj.HH:MM:SS.SSS\"" +msgstr "Ceci n'est pas une repr?sentation de date?: ??aaaa-mm-jj??, ??mm-jj??, ??HH:MM??, ??HH:MM:SS?? or ??aaaa-mm-jj.HH:MM:SS.SSS??" #: ../roundup/date.py:240 #, python-format msgid "" "%r not a date / time spec \"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", \"HH:MM:SS\" " "or \"yyyy-mm-dd.HH:MM:SS.SSS\"" -msgstr "" -"%r n'est pas une repr?sentation de date ou d'heure \"aaaa-mm-jj\", \"mm-jj" -"\", \"HH:MM\", \"HH:MM:SS\" or \"aaaa-mm-jj.HH:MM:SS.SSS\"" +msgstr "%r n'est pas une repr?sentation de date ou d'heure ??aaaa-mm-jj??, ??mm-jj??, ??HH:MM??, ??HH:MM:SS?? or ??aaaa-mm-jj.HH:MM:SS.SSS??" #: ../roundup/date.py:538 msgid "" "Not an interval spec: [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS] [date spec]" -msgstr "" -"Ceci n'est pas une repr?sentation d'intervalle: [+-] [#a] [#m] [#s] [#j] " -"[[[H]H:MM]:SS] [repr?sentation de date]" +msgstr "Ceci n'est pas une repr?sentation d'intervalle?: [+-] [#a] [#m] [#s] [#j] [[[H]H:MM]:SS] [repr?sentation de date]" #: ../roundup/date.py:557 msgid "Not an interval spec: [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS]" -msgstr "" -"Ceci n'est pas une repr?sentation d'intervalle: [+-] [#a] [#m] [#s] [#j] " -"[[[H]H:MM]:SS]" +msgstr "Ceci n'est pas une repr?sentation d'intervalle?: [+-] [#a] [#m] [#s] [#j] [[[H]H:MM]:SS]" #: ../roundup/date.py:694 #, python-format @@ -1693,7 +1686,7 @@ msgid "1 %(number)s/4 hours" msgid_plural "1 %(number)s/4 hours" msgstr[0] "1 heure et quart" -msgstr[1] "1 heure trois-quart" +msgstr[1] "1 heure %(number)s/4" #: ../roundup/date.py:727 msgid "in a moment" @@ -1723,12 +1716,12 @@ msgid "%(number)s/4 hour" msgid_plural "%(number)s/4 hours" msgstr[0] "un quart d'heure" -msgstr[1] "trois quarts d'heure" +msgstr[1] "%(number)s/4 d'heures" #: ../roundup/date.py:744 #, python-format msgid "%s ago" -msgstr "il y a %s" +msgstr "Il y a %s" #: ../roundup/date.py:746 #, python-format @@ -1741,16 +1734,14 @@ "WARNING: directory '%s'\n" "\tcontains old-style template - ignored" msgstr "" -"ATTENTION: le r?pertoire '%s'\n" +"ATTENTION?: le r?pertoire '%s'\n" "\tcontient des mod?les obsol?tes - ignor?" #: ../roundup/mailgw.py:586 msgid "" "\n" "Emails to Roundup trackers must include a Subject: line!\n" -msgstr "" -"\n" -"Les emails envoy?s au gestionnaire de ticket doivent comporter un sujet !\n" +msgstr "\nLes courriels envoy?s au gestionnaire de ticket doivent comporter un sujet?!\n" #: ../roundup/mailgw.py:674 #, python-format @@ -1771,15 +1762,16 @@ "\n" "Le sujet du message que vous avez envoy? au gestionnaire de ticket n'?tait\n" "pas correct. Le sujet doit contenir le nom d'une classe ou d'un objet. Par\n" -"exemple : \n" -" Subject: [issue] un nouveau ticket\n" -" - Cela cr?era dans le gestionnaire un nouveau ticket dont le titre \n" -" sera 'un nouveau ticket'.\n" -" Subject: [issue1234] r?ponse au ticket 1234\n" -" - Cela ajoutera le corps du message au ticket 1234 d?j? pr?sent dans \n" +"exemple?: \n" +" Sujet: [issue] Un nouveau ticket\n" +" - cr?era dans le gestionnaire un nouveau ticket dont le titre\n" +" sera ??Un nouveau ticket??.\n" +"\n" +" Sujet: [issue1234] R?ponse au ticket 1234\n" +" - ajoutera le corps du message au ticket 1234 d?j? pr?sent dans \n" " le gestionnaire.\n" "\n" -"Sujet original : '%(subject)s'\n" +"Sujet original?: '%(subject)s'\n" #: ../roundup/mailgw.py:705 #, python-format @@ -1793,11 +1785,11 @@ "Subject was: \"%(subject)s\"\n" msgstr "" "\n" -"Le nom de la classe identifi?e par dans le sujet (\"%(classname)s\")\n" +"Le nom de la classe identifi?e dans le sujet (??%(classname)s??)\n" "n'existe pas dans la base de donn?es.\n" "\n" -"Les noms de classes valides sont : %(validname)s\n" -"Sujet original : '%(subject)s'\n" +"Les noms de classes valides sont?: %(validname)s\n" +"Sujet original?: ??%(subject)s??\n" #: ../roundup/mailgw.py:733 #, python-format @@ -1811,11 +1803,11 @@ msgstr "" "\n" "Impossible d'associer votre message ? un objet de la base de donn?es.\n" -"Vous devez soit fournir un le nom d'une classe avec un num?ro (par exemple\n" -"\"[issue123]\"), soit garder le sujet du pr?c?dent message tel quel pour\n" -"pouvoir effectuer la correspondance.\n" +"Vous devez soit fournir soit le nom d'une classe avec un num?ro (par\n" +"exemple \"[issue123]\"), soit garder le sujet du pr?c?dent message tel\n" +"quel pour pouvoir effectuer la correspondance.\n" "\n" -"Sujet original : '%(subject)s'\n" +"Sujet original?: ??%(subject)s??\n" #: ../roundup/mailgw.py:766 #, python-format @@ -1827,10 +1819,10 @@ "Subject was: \"%(subject)s\"\n" msgstr "" "\n" -"L'objet sp?cifi? dans le sujet de votre message (\"%nodeid)s\")\n" +"L'objet indiqu? dans le sujet de votre message (??%(nodeid)s??)\n" " n'existe pas.\n" "\n" -"Sujet original : '%(subject)s'\n" +"Sujet original?: ??%(subject)s??\n" #: ../roundup/mailgw.py:794 #, python-format @@ -1840,10 +1832,11 @@ "%(mailadmin)s and have them fix the incorrect class specified as:\n" " %(current_class)s\n" msgstr "" -"La passerelle mail ne fonctionne pas correctement. Veuillez contacter\n" -"%(mailadmin)s pour r?gler ce probl?me.\n" "\n" -"classe incorrecte : %(current_class)s\n" +"La passerelle courriel ne fonctionne pas correctement. Contactez\n" +"%(mailadmin)s afin qu'il corrige la classe incorrecte qui a ?t?\n" +"indiqu?e comme?: \n" +" %(current_class)s\n" #: ../roundup/mailgw.py:817 #, python-format @@ -1853,10 +1846,11 @@ "%(mailadmin)s and have them fix the incorrect properties:\n" " %(errors)s\n" msgstr "" -"La passerelle mail ne fonctionne pas correctement. Veuillez contacter\n" -"%(mailadmin)s pour r?gler ce probl?me.\n" "\n" -"propri?t?s incorrectes : %(errors)s\n" +"La passerelle courriel ne fonctionne pas correctement. Contactez\n" +"%(mailadmin)s afin que les propri?t?s incorrectes suivantes soient\n" +"corrig?s?:\n" +" %(errors)s\n" #: ../roundup/mailgw.py:847 #, python-format @@ -1867,14 +1861,13 @@ "Unknown address: %(from_address)s\n" msgstr "" "\n" -"Vous n'?tes pas enregistr?s.\n" +"Vous n'?tes pas un utilisateur inscrit.\n" "\n" -"addresse inconnue : %(from_address)s\n" +"Addresse inconnue?: %(from_address)s\n" #: ../roundup/mailgw.py:855 -#, fuzzy msgid "You are not permitted to access this tracker." -msgstr "Vous n'êtes pas autorisé à voir cette page." +msgstr "Vous n'?tes pas autoris? ? acc?der ? ce pisteur." #: ../roundup/mailgw.py:862 #, python-format @@ -1895,9 +1888,11 @@ "\n" "Subject was: \"%(subject)s\"\n" msgstr "" -"Une erreur s'est produite lors du traitement du sujet :- %(errors)s\n" "\n" -"Sujet original : '%(subject)s'\n" +"Une erreur s'est produite lors du traitement de la liste de sujets?:\n" +"- %(errors)s\n" +"\n" +"Le sujet ?tait ??%(subject)s??\n" #: ../roundup/mailgw.py:942 msgid "" @@ -1905,13 +1900,13 @@ "Roundup requires the submission to be plain text. The message parser could\n" "not find a text/plain part to use.\n" msgstr "" -"Le message soumis doit ?tre en texte brut. L'analyse du message n'a pas " -"trouv?\n" -"trouv? de partie en text/plain.\n" +"\n" +"Le message soumis doit ?tre en texte brut. L'analyse du message n'a pas trouv?\n" +"de partie text/plain ? utiliser.\n" #: ../roundup/mailgw.py:964 msgid "You are not permitted to create files." -msgstr "Vous n'?tes pas autoris? ? cr?er des fichier" +msgstr "Vous n'?tes pas autoris? ? cr?er des fichiers." #: ../roundup/mailgw.py:978 #, python-format @@ -1955,7 +1950,7 @@ " %(message)s\n" msgstr "" "\n" -"Il y a eu un probl?me lors de la r?ception de votre email :\n" +"Un probl?me a eu lieu ? l'envoi de votre message?:\n" " %(message)s\n" #: ../roundup/mailgw.py:1069 @@ -1984,7 +1979,7 @@ #: ../roundup/roundupdb.py:143 msgid "assignedto" -msgstr "assign?_?" +msgstr "affect?_?" #: ../roundup/roundupdb.py:143 msgid "priority" @@ -2019,29 +2014,26 @@ #: ../roundup/roundupdb.py:304 #, python-format msgid "New submission from %(authname)s%(authaddr)s:" -msgstr "Nouvelle soumission de %(authname)s%(authaddr)s:" +msgstr "Nouvel envoi de %(authname)s%(authaddr)s?:" #: ../roundup/roundupdb.py:307 #, python-format msgid "%(authname)s%(authaddr)s added the comment:" -msgstr "%(authname)s%(authaddr)s a ajout? le commentaire:" +msgstr "%(authname)s%(authaddr)s a ajout? le commentaire?:" #: ../roundup/roundupdb.py:310 -#, fuzzy msgid "System message:" -msgstr "Nouveau message" +msgstr "Message syst?me?:" #: ../roundup/scripts/roundup_demo.py:32 #, python-format msgid "Enter directory path to create demo tracker [%s]: " -msgstr "" -"Saisissez le chemin du r?pertoire dans lequel cr?er le pisteur de " -"d?monstration [%s]: " +msgstr "Saisissez le chemin du r?pertoire o? cr?er le pisteur de d?monstration [%s]?: " #: ../roundup/scripts/roundup_gettext.py:22 #, python-format msgid "Usage: %(program)s " -msgstr "Usage: %(program)s " +msgstr "Utilisation?: %(program)s " #: ../roundup/scripts/roundup_gettext.py:37 #, python-format @@ -2116,98 +2108,89 @@ " imaps username:password at server [mailbox]\n" "\n" msgstr "" -"Usage: %(program)s [-v] [[-C classe] -S champ=valeur]* " -"[m?thode]\n" +"Utilisation?: %(program)s [-v] [[-C classe] -S champ=valeur]* [m?thode]\n" "\n" -"Options:\n" -" -v: imprime la version et quitte\n" -" -c: classe de l'?lement ? cr?er (par d?faut, la classe MAIL_DEFAULT_CLASS)\n" -" -C / -S: voir ci-apr?s\n" +"Options?:\n" +" -v?: imprime la version et quitte.\n" +" -c?: classe de l'?lement ? cr?er (par d?faut, la classe MAIL_DEFAULT_CLASS).\n" +" -C / -S?: voir ci-dessous.\n" "\n" -"La passerelle de messagerie de Roundup peut ?tre appel?e de quatre " -"mani?res:\n" +"La passerelle de messagerie de Roundup peut ?tre appel?e de quatre fa?ons?:\n" " . avec le r?pertoire de base d'une instance comme seul argument,\n" -" . avec ? la fois un r?pertoire de base et un fichier d'attente de " -"messagerie,\n" -" . avec ? la fois un r?pertoire de base et un compte de serveur POP/APOP, " -"ou\n" +" . avec ? la fois un r?pertoire de base et un fichier d'attente de messagerie,\n" +" . avec ? la fois un r?pertoire de base et un compte de serveur POP/APOP, ou\n" " . avec ? la fois un r?pertoire de base et un compte de serveur IMAP/IMAPS.\n" "\n" -"Elle accepte ?galement les options -C et -S qui vous permettent d'assigner\n" -"des champs pour une classe cr??e par roundup-mailgw. La classe par d?faut, " -"si\n" -"elle n'est pas sp?cifi?e, est \"msg\", mais les autres classes: \"issue\",\n" -"\"file\", \"user\" peuvent ?galement ?tre utilis?es. Les options -S ou --" -"set \n" -"utilisent la m?me notation propri?t?=valeur[;propri?t?=valeur] accept?e par " -"la\n" -"ligne de commande de Roundup ou par les commandes qui peuvent ?tre donn?es\n" -"dans l'objet d'un courriel.\n" -"\n" -"Elle vous permet ?galement de sp?cifier le type de message pour chaque " -"adresse\n" -"de messagerie.\n" +"Elle accepte ?galement les options -C et -S qui vous permettent\n" +"d'assigner des champs pour une classe cr??e par roundup-mailgw. La\n" +"classe par d?faut, si elle n'est pas sp?cifi?e, est ??msg??, mais les\n" +"autres classes?: ??issue?? (anomalie), ??file?? (fichier), ??user??\n" +"(utilisateur) peuvent ?galement ?tre utilis?es. Les options -S ou\n" +"--set utilisent la m?me notation propri?t?=valeur[;propri?t?=valeur]\n" +"accept?e par la ligne de commande de Roundup ou par les commandes qui\n" +"peuvent ?tre donn?es dans l'objet d'un courriel.\n" "\n" -"PIPE:\n" -" Dans le premier cas, la passerelle de messagerie lit un seul message " -"venant\n" +"Elle vous permet ?galement de sp?cifier le type de message pour chaque\n" +"adresse de messagerie.\n" +"\n" +"PIPE?:\n" +" Dans le premier cas, la passerelle de messagerie lit un seul message venant\n" " de l'entr?e standard et le soumet au module roundup.mailgw.\n" "\n" -"UNIX mailbox:\n" +"UNIX mailbox?:\n" " Dans le second cas, la passerelle lit tout les messages venant du fichier\n" " d'attente de messagerie et les soumet chacun ? leur tour au module\n" -" roundup.mailgw. Le fichier est vid? une fois que tout les messages ont ?t?\n" -" trait?s avec succ?s. Le fichier est sp?cifi? comme:\n" +" roundup.mailgw. Le fichier est vid? une fois que tous les messages ont ?t?\n" +" trait?s avec succ?s. Le fichier est indiqu? comme:\n" " mailbox /chemin/vers/mailbox\n" "\n" -"POP:\n" +"POP?:\n" " Dans le troisi?me cas, la passerelle lit tout les messages du serveur POP\n" -" sp?cifi? et les soumet chacun ? leur tour au module roundup.mailgw. Le\n" -" serveur est sp?cifi? comme suit:\n" +" indiqu? et les soumet chacun ? leur tour au module roundup.mailgw. Le\n" +" serveur est renseign? comme suit?:\n" " pop nom-d'utilisateur:mot-de-passe at serveur\n" -" Le nom d'utilisateur et le mot de passe peuvent ?tre omis:\n" +" Le nom d'utilisateur et le mot de passe peuvent ?tre omis?:\n" " pop nom-d'utilisateur at serveur\n" " pop server\n" " sont tous deux valides. Le nom d'utilisateur et/ou le mot de passe seront\n" " demand?s s'ils ne sont pas fournis dans la ligne de commande.\n" "\n" -"APOP:\n" -" Identique ? POP, mais utilisant le POP authentifi?:\n" +"APOP?:\n" +" Identique ? POP, mais utilisant le POP authentifi??:\n" " apop nom-d'utilisateur:mot-de-passe at serveur\n" "\n" -"IMAP:\n" -" Se connecte ? un serveur IMAP. Supporte la m?me notation que pour la\n" -" messagerie POP\n" +"IMAP?:\n" +" Se connecte ? un serveur IMAP. Il prend en charge la m?me notation\n" +" que pour la messagerie POP\n" +"\n" " imap nom-d'utilisateur:mot-de-passe at serveur\n" -" Vous permet ?galement de sp?cifier une bo?te aux lettres sp?cifique, autre\n" -" que INBOX, en utilisant ce format:\n" +" Il permet ?galement d'indiquer une bo?te aux lettres sp?cifique, autre\n" +" que INBOX, en utilisant ce format?:\n" " imap nom-d'utilisateur:mot-de-passe at serveur bo?te-aux-lettres\n" "\n" -"IMAPS:\n" +"IMAPS?:\n" " Se connecte avec SSL ? un serveur IMAP.\n" -" Supporte la m?me notation que IMAP.\n" +" Prend en charge la m?me notation que IMAP.\n" " imaps nom-d'utilisateur:mot-de-passe at serveur [bo?te-aux-lettres]\n" "\n" #: ../roundup/scripts/roundup_mailgw.py:147 msgid "Error: not enough source specification information" -msgstr "Erreur: pas assez d'informations dans la sp?cification de la source" +msgstr "Erreur?: pas suffisament d'informations dans la sp?cification de la source" #: ../roundup/scripts/roundup_mailgw.py:163 msgid "Error: pop specification not valid" -msgstr "Erreur: la sp?cification pop n'est pas valide" +msgstr "Erreur?: la sp?cification pop n'est pas valide" #: ../roundup/scripts/roundup_mailgw.py:170 msgid "Error: apop specification not valid" -msgstr "Erreur: la sp?cification apop n'est pas valide" +msgstr "Erreur?: la sp?cification apop n'est pas valide" #: ../roundup/scripts/roundup_mailgw.py:184 msgid "" "Error: The source must be either \"mailbox\", \"pop\", \"apop\", \"imap\" or " "\"imaps\"" -msgstr "" -"Erreur: la source doit ?tre \"mailbox\", \"pop\", \"apop\", \"imap\" ou " -"\"imaps\"" +msgstr "Erreur?: la source doit ?tre ??mailbox??, ??pop??, ??apop??, ??imap?? ou ??imaps??" #: ../roundup/scripts/roundup_server.py:157 msgid "" @@ -2220,13 +2203,11 @@ #: ../roundup/scripts/roundup_server.py:287 #, python-format msgid "Error: %s: %s" -msgstr "Erreur: %s: %s" +msgstr "Erreur?: %s: %s" #: ../roundup/scripts/roundup_server.py:297 msgid "WARNING: ignoring \"-g\" argument, not root" -msgstr "" -"ATTENTION: le param?tre \"-g\" est ignor?, vous n'?tes pas superutilisateur " -"(\"root\")" +msgstr "ATTENTION?: le param?tre ??-g?? est ignor?, vous n'?tes pas superutilisateur (??root??)" #: ../roundup/scripts/roundup_server.py:303 msgid "Can't change groups - no grp module" @@ -2284,7 +2265,7 @@ " pr?ciser les r?pertoires des pisteurs.\n" " L'option Logfile est requise pour ex?cuter le service\n" " RoundUp Tracker.\n" -" La commande \"roundup-server -c help\" donne les\n" +" La commande ??roundup-server -c help?? donne les\n" " sp?cificit?s du service Windows." #: ../roundup/scripts/roundup_server.py:569 @@ -2360,6 +2341,59 @@ " pairs on the command-line. Make sure the name part doesn't include\n" " any url-unsafe characters like spaces, as these confuse IE.\n" msgstr "" +"%(message)sUtilisation?: roundup-server [options] [name=tracker home]*\n" +"\n" +"Options?:\n" +" -v affiche le num?ro de version Roundup et quitte\n" +" -h affiche ce texte et quitte\n" +" -S cr?e ou met ? jour le fichier de configuration et quitte\n" +" -C utilise le fichier de configuration \n" +" -n d?finit le nom d'h?te de l'instance Web Roundup\n" +" -p d?finit le port d'?coute (par d?faut %(port)s)\n" +" -l historise dans le fichier indiqu? par au lieu de \n" +" stderr/stdout\n" +" -N historise le nom d'h?te client au lieu des adresses IP \n" +" (beaucoup plus lent)\n" +" -t mode multi-processus (par d?faut %(mp_def)s). Valeurs\n" +" utilis?es?: %(mp_types)s.\n" +"\n" +"%(os_part)s\n" +"\n" +"Options longues?:\n" +" --version affiche le num?ro de version Roundup et quitte\n" +" --help affiche ce texte et quitte\n" +" --save-config cr?e ou met ? jour le fichier de configuration et quitte\n" +" --config utilise le fichier de configuration \n" +"\n" +"Exemples?:\n" +" roundup-server -S -C /opt/roundup/etc/roundup-server.ini\n" +" -n localhost -p 8917 -l /var/log/roundup.log\n" +" support=/var/spool/roundup-trackers/support\n" +"\n" +" roundup-server -C /opt/roundup/etc/roundup-server.ini\n" +"\n" +" roundup-server support=/var/spool/roundup-trackers/support\n" +"\n" +" roundup-server -d /var/run/roundup.pid -l /var/log/roundup.log\n" +" support=/var/spool/roundup-trackers/support\n" +"\n" +"Format du fichier de configuration?:\n" +"\n" +" Le fichier de configuration du serveur Roundup utilise le format de\n" +" fichier commun .ini. Le fichier de configuration cr?? par\n" +" ??roundup-server -S?? contient les explications d?taill?es de\n" +" chaque option. Consultez ce fichier pour la description des\n" +" options.\n" +"\n" +"Utilisation de ??name=racine du pisteur???:\n" +" \n" +" Ces arguments d?finissent la racine du pisteur ? utiliser. Le nom\n" +" est celui utilis? pour identifier le pisteur dans l'URL (premi?re\n" +" partie du chemin de l'URL). La racine du pisteur est le r?pertoire\n" +" qui a ?t? identifi? quand vous ex?cutez ??roundup-admin list??. Il\n" +" est possible de fournir autant de paires ??name=racine?? que\n" +" souhait?. Assurez-vous que ??name?? ne contienne pas de caract?res\n" +" inappropri?s pour une URL, comme les espaces qui perturbe IE.\n" #: ../roundup/scripts/roundup_server.py:723 msgid "Instances must be name=home" @@ -2384,12 +2418,12 @@ #: ../templates/classic/html/_generic.collision.html:4 #: ../templates/minimal/html/_generic.collision.html:4 msgid "${class} Edit Collision - ${tracker}" -msgstr "Édition des collisions pour ${class} - ${tracker}" +msgstr "Modification des collisions pour ${class} - ${tracker}" #: ../templates/classic/html/_generic.collision.html:7 #: ../templates/minimal/html/_generic.collision.html:7 msgid "${class} Edit Collision" -msgstr "Édition des collisions pour ${class}" +msgstr "Modification des collisions pour ${class}" #: ../templates/classic/html/_generic.collision.html:14 #: ../templates/minimal/html/_generic.collision.html:14 @@ -2400,15 +2434,15 @@ " the node and review your edits.\n" msgstr "" "\n" -" Une collision s'est produite. Un autre utilisateur a mis à jour ce\n" -" noeud pendant que vous l'éditiez. Veuillez recharger\n" -" ce noeud et vérifier vos modifications.\n" +" Une collision s'est produite. Un autre utilisateur a mis à\n" +" jour ce noeud pendant que vous ?tiez en train de la\n" +" modifier. Veuillez actualiser ce noeud et\n" +" vérifier vos modifications.\n" #: ../templates/classic/html/_generic.help.html:9 #: ../templates/minimal/html/_generic.help.html:9 msgid "${property} help - ${tracker}" -msgstr "Aide concernant ${property} - ${tracker}" +msgstr "Aide ? propos de ??${property}?? - ${tracker}" #: ../templates/classic/html/_generic.help.html:31 #: ../templates/minimal/html/_generic.help.html:31 @@ -2443,14 +2477,14 @@ #: ../templates/minimal/html/_generic.index.html:6 #: ../templates/minimal/html/_generic.item.html:4 msgid "${class} editing - ${tracker}" -msgstr "Édition de ${class} - ${tracker}" +msgstr "Modification de ${class} - ${tracker}" #: ../templates/classic/html/_generic.index.html:9 #: ../templates/classic/html/_generic.item.html:7 #: ../templates/minimal/html/_generic.index.html:9 #: ../templates/minimal/html/_generic.item.html:7 msgid "${class} editing" -msgstr "Édition de ${class}" +msgstr "Modification de ${class}" #: ../templates/classic/html/_generic.index.html:14 #: ../templates/classic/html/_generic.item.html:12 @@ -2479,20 +2513,7 @@ "multiple values colon (\":\") separated (... ,\"one:two:three\", ...)

    " "

    Remove entries by deleting their line. Add new " "entries by appending them to the table - put an X in the id column.

    " -msgstr "" -"

    Vous pouvez éditer le contenu de la classe " -"${classname} en utilisant ce formulaire. Les virgules, passages à la " -"ligne guillemets doubles (\") doivent être gérés " -"soigneusement. Vous pouvez insérer des virgules et des passage " -"à la ligne en insérant les valeurs dans des guillemets doubles " -"(\"). Les guillemets doubles elles-mêmes doivent être insé" -"rées en les doublant (\"\").

    Les " -"propriétés des liens multiples doivent séparerleurs " -"valeurs multiples par des double-points (\":\") (... ,\"un:deux:trois" -"\", ...)

    Enlevez des entrées en " -"effaçant leur ligne. Ajoutez de nouvelles entrées en les " -"ajoutant à la fin de la table - mettez un \"X\" dans la colonne \"id" -"\".

    " +msgstr "

    Vous pouvez modifier le contenu de la classe ${classname} en utilisant ce formulaire. Les virgules, passages à la ligne guillemets doubles (\") doivent être gérés soigneusement. Vous pouvez insérer des virgules et des passage à la ligne en insérant les valeurs dans des guillemets doubles (\"). Les guillemets doubles eux-mêmes doivent être insérés en les doublant (\"\").

    Les propriétés des liens multiples doivent séparer leurs valeurs multiples par des double-points ??:?? (... , \"un:deux:trois\", ...)

    Enlevez des entrées en effaçant leur ligne. Ajoutez de nouvelles entrées en les ajoutant à la fin de la table - mettez un ??X?? dans la colonne ??id??.

    " #: ../templates/classic/html/_generic.index.html:44 #: ../templates/minimal/html/_generic.index.html:44 @@ -2555,11 +2576,11 @@ #: ../templates/classic/html/issue.index.html:7 msgid "List of issues - ${tracker}" -msgstr "Liste des demandes - ${tracker}" +msgstr "Liste des anomalies - ${tracker}" #: ../templates/classic/html/issue.index.html:11 msgid "List of issues" -msgstr "Liste des demandes" +msgstr "Liste des anomalies" #: ../templates/classic/html/issue.index.html:22 #: ../templates/classic/html/issue.item.html:44 @@ -2602,7 +2623,7 @@ #: ../templates/classic/html/issue.index.html:31 msgid "Assigned To" -msgstr "Assigné à" +msgstr "Affecté à" #: ../templates/classic/html/issue.index.html:97 msgid "Download as CSV" @@ -2610,7 +2631,8 @@ #: ../templates/classic/html/issue.index.html:105 msgid "Sort on:" -msgstr "Trier par:" +msgstr "Trier par?:" + #: ../templates/classic/html/issue.index.html:108 #: ../templates/classic/html/issue.index.html:125 @@ -2624,35 +2646,35 @@ #: ../templates/classic/html/issue.index.html:122 msgid "Group on:" -msgstr "Grouper par:" +msgstr "Regrouper par?:" #: ../templates/classic/html/issue.index.html:139 msgid "Redisplay" -msgstr "R?-afficher" +msgstr "Actualiser" #: ../templates/classic/html/issue.item.html:7 msgid "Issue ${id}: ${title} - ${tracker}" -msgstr "Demande ${id}: ${title} - ${tracker}" +msgstr "Anomalie ${id}?: ${title} - ${tracker}" #: ../templates/classic/html/issue.item.html:10 msgid "New Issue - ${tracker}" -msgstr "Nouvelle demande - ${tracker}" +msgstr "Nouvelle anomalie - ${tracker}" #: ../templates/classic/html/issue.item.html:14 msgid "New Issue" -msgstr "Nouvelle demande" +msgstr "Nouvelle anomalie" #: ../templates/classic/html/issue.item.html:16 msgid "New Issue Editing" -msgstr "?dition d'une nouvelle demande" +msgstr "Cr?ation d'une nouvelle anomalie" #: ../templates/classic/html/issue.item.html:19 msgid "Issue${id}" -msgstr "Issue${id}" +msgstr "Anomalie?${id}" #: ../templates/classic/html/issue.item.html:22 msgid "Issue${id} Editing" -msgstr "Édition de la demande Issue${id}" +msgstr "Modification de l'anomalie?${id}" #: ../templates/classic/html/issue.item.html:51 msgid "Superseder" @@ -2660,7 +2682,7 @@ #: ../templates/classic/html/issue.item.html:56 msgid "View: ${link}" -msgstr "Voir: ${link}" +msgstr "Voir?: ${link}" #: ../templates/classic/html/issue.item.html:60 msgid "Nosy List" @@ -2668,7 +2690,7 @@ #: ../templates/classic/html/issue.item.html:69 msgid "Assigned To" -msgstr "Assigné à" +msgstr "Affecté à" #: ../templates/classic/html/issue.item.html:71 msgid "Topics" @@ -2732,13 +2754,13 @@ #: ../templates/classic/html/issue.item.html:131 msgid "Remove" -msgstr "Effacer" +msgstr "Supprimer" #: ../templates/classic/html/issue.item.html:151 #: ../templates/classic/html/issue.item.html:172 #: ../templates/classic/html/query.edit.html:50 msgid "remove" -msgstr "enlever" +msgstr "supprimer" #: ../templates/classic/html/issue.item.html:158 #: ../templates/classic/html/msg.index.html:9 @@ -2751,19 +2773,19 @@ #: ../templates/classic/html/issue.item.html:163 msgid "Author: ${author}" -msgstr "Auteur: ${author}" +msgstr "Auteur?: ${author}" #: ../templates/classic/html/issue.item.html:165 msgid "Date: ${date}" -msgstr "Date: ${date}" +msgstr "Date?: ${date}" #: ../templates/classic/html/issue.search.html:2 msgid "Issue searching - ${tracker}" -msgstr "Recherche de demande - ${tracker}" +msgstr "Recherche de l'anomalie - ${tracker}" #: ../templates/classic/html/issue.search.html:4 msgid "Issue searching" -msgstr "Recherche de demande" +msgstr "Recherche de l'anomalie" #: ../templates/classic/html/issue.search.html:25 msgid "Filter on" @@ -2783,7 +2805,7 @@ #: ../templates/classic/html/issue.search.html:32 msgid "All text*:" -msgstr "Tout le texte*:" +msgstr "Tout le texte*?:" #: ../templates/classic/html/issue.search.html:40 msgid "Title:" @@ -2799,7 +2821,7 @@ #: ../templates/classic/html/issue.search.html:66 msgid "Creation Date:" -msgstr "Date de création:" +msgstr "Date de création?:" #: ../templates/classic/html/issue.search.html:77 msgid "Creator:" @@ -2811,7 +2833,7 @@ #: ../templates/classic/html/issue.search.html:88 msgid "Activity:" -msgstr "Activité:" +msgstr "Activité?:" #: ../templates/classic/html/issue.search.html:99 msgid "Actor:" @@ -2823,7 +2845,7 @@ #: ../templates/classic/html/issue.search.html:112 msgid "Priority:" -msgstr "Priorité:" +msgstr "Priorité?:" #: ../templates/classic/html/issue.search.html:114 #: ../templates/classic/html/issue.search.html:130 @@ -2832,7 +2854,7 @@ #: ../templates/classic/html/issue.search.html:125 msgid "Status:" -msgstr "État:" +msgstr "État?:" #: ../templates/classic/html/issue.search.html:128 msgid "not resolved" @@ -2840,39 +2862,39 @@ #: ../templates/classic/html/issue.search.html:143 msgid "Assigned to:" -msgstr "Assigné à:" +msgstr "Affecté à?:" #: ../templates/classic/html/issue.search.html:146 msgid "assigned to me" -msgstr "assigné à moi" +msgstr "affecté à moi" #: ../templates/classic/html/issue.search.html:148 msgid "unassigned" -msgstr "non assigné" +msgstr "non affecté" #: ../templates/classic/html/issue.search.html:158 msgid "No Sort or group:" -msgstr "Aucun tri ou groupe:" +msgstr "Aucun tri ou groupe?:" #: ../templates/classic/html/issue.search.html:166 msgid "Pagesize:" -msgstr "Taille de la page:" +msgstr "Taille de la page?:" #: ../templates/classic/html/issue.search.html:172 msgid "Start With:" -msgstr "Commence par" +msgstr "Commence par?:" #: ../templates/classic/html/issue.search.html:178 msgid "Sort Descending:" -msgstr "Tri descendant:" +msgstr "Tri descendant?:" #: ../templates/classic/html/issue.search.html:185 msgid "Group Descending:" -msgstr "Groupage descendant:" +msgstr "Groupe descendant?:" #: ../templates/classic/html/issue.search.html:192 msgid "Query name**:" -msgstr "Nom de requ?te**:" +msgstr "Nom de requ?te**?:" #: ../templates/classic/html/issue.search.html:204 #: ../templates/classic/html/page.html:31 @@ -2883,29 +2905,25 @@ #: ../templates/classic/html/issue.search.html:209 msgid "*: The \"all text\" field will look in message bodies and issue titles" -msgstr "" -"*: Le champ \"tout le texte\" recherchera dans tous les corps de message et " -"les titres de demande" +msgstr "*?: le champ ??tout le texte?? recherchera dans tous les corps de message et les titres de l'anomalie" #: ../templates/classic/html/issue.search.html:212 msgid "" "**: If you supply a name, the query will be saved off and available as a " "link in the sidebar" -msgstr "" -"**: Si vous donnez un nom, la requête sera sauvegardée et " -"disponible comme lien dans la barre latérale" +msgstr "**?: si vous attribuez un nom, la requête sera enregistrée et disponible comme lien dans la barre latérale" #: ../templates/classic/html/keyword.item.html:3 msgid "Keyword editing - ${tracker}" -msgstr "Édition de mots-clé - ${tracker}" +msgstr "Modification de mots clé - ${tracker}" #: ../templates/classic/html/keyword.item.html:5 msgid "Keyword editing" -msgstr "Édition de mots-clé" +msgstr "Modification de mot-clés" #: ../templates/classic/html/keyword.item.html:11 msgid "Existing Keywords" -msgstr "Mots-clé existants" +msgstr "Mot-clés existants" #: ../templates/classic/html/keyword.item.html:20 msgid "" @@ -2917,9 +2935,7 @@ #: ../templates/classic/html/keyword.item.html:27 msgid "To create a new keyword, enter it below and click \"Submit New Entry\"." -msgstr "" -"Pour créer un nouveau mot-clé, entrez-le ci-dessous et cliquer " -"\"Soumettre une nouvelle entrée\"." +msgstr "Pour créer un nouveau mot-clé, saisissez-le ci-dessous et cliquer sur ??Soumettre une nouvelle entrée??." #: ../templates/classic/html/keyword.item.html:37 msgid "Keyword" @@ -2947,7 +2963,7 @@ #: ../templates/classic/html/msg.item.html:15 msgid "New Message Editing" -msgstr "Édition d'un nouveau message" +msgstr "Modification d'un nouveau message" #: ../templates/classic/html/msg.item.html:18 msgid "Message${id}" @@ -2955,7 +2971,7 @@ #: ../templates/classic/html/msg.item.html:21 msgid "Message${id} Editing" -msgstr "Édition de Message${id}" +msgstr "Modification du message?${id}" #: ../templates/classic/html/msg.item.html:33 msgid "Author" @@ -2971,12 +2987,11 @@ #: ../templates/classic/html/page.html:41 msgid "Your Queries (edit)" -msgstr "" -"Vos requêtes (modifier)" +msgstr "Vos requêtes (modifier)" #: ../templates/classic/html/page.html:52 msgid "Issues" -msgstr "Demandes" +msgstr "Anomalies" #: ../templates/classic/html/page.html:54 #: ../templates/classic/html/page.html:74 @@ -2985,15 +3000,15 @@ #: ../templates/classic/html/page.html:56 msgid "Show Unassigned" -msgstr "Montrer les non-assignés" +msgstr "Afficher les non-affect?es" #: ../templates/classic/html/page.html:58 msgid "Show All" -msgstr "Montrer tout" +msgstr "Tout afficher" #: ../templates/classic/html/page.html:61 msgid "Show issue:" -msgstr "Montrer la demande:" +msgstr "Voir l'anomalie?:" #: ../templates/classic/html/page.html:72 msgid "Keywords" @@ -3032,18 +3047,18 @@ #: ../templates/classic/html/page.html:104 #: ../templates/minimal/html/page.html:45 msgid "Remember me?" -msgstr "Se souvenir de moi ?" +msgstr "Se souvenir" #: ../templates/classic/html/page.html:108 #: ../templates/classic/html/user.register.html:63 #: ../templates/minimal/html/page.html:50 #: ../templates/minimal/html/user.register.html:58 msgid "Register" -msgstr "S'enregistrer" +msgstr "S'inscrire" #: ../templates/classic/html/page.html:111 msgid "Lost your login?" -msgstr "Perdu votre login ?" +msgstr "Retrouver votre identifiant" #: ../templates/classic/html/page.html:116 msgid "Hello, ${user}" @@ -3051,7 +3066,7 @@ #: ../templates/classic/html/page.html:118 msgid "Your Issues" -msgstr "Vos demandes" +msgstr "Vos anomalies" #: ../templates/classic/html/page.html:119 #: ../templates/minimal/html/page.html:57 @@ -3082,7 +3097,7 @@ #: ../templates/classic/html/page.html:183 msgid "------------" -msgstr "" +msgstr "------------" #: ../templates/classic/html/page.html:210 msgid "no value" @@ -3090,15 +3105,15 @@ #: ../templates/classic/html/query.edit.html:4 msgid "\"Your Queries\" Editing - ${tracker}" -msgstr "Édition de \"Vos requêtes\" - ${tracker}" +msgstr "Modification de ??Vos requêtes?? - ${tracker}" #: ../templates/classic/html/query.edit.html:6 msgid "\"Your Queries\" Editing" -msgstr "Édition de \"Vos requêtes\"" +msgstr "Modification de ??Vos requêtes??" #: ../templates/classic/html/query.edit.html:11 msgid "You are not allowed to edit queries." -msgstr "Vous n'avez pas l'autorisation d'éditer des requêtes." +msgstr "Vous n'avez pas l'autorisation de modifier des requêtes." #: ../templates/classic/html/query.edit.html:28 msgid "Query" @@ -3106,11 +3121,11 @@ #: ../templates/classic/html/query.edit.html:29 msgid "Include in \"Your Queries\"" -msgstr "Inclus dans \"Vos requêtes\"" +msgstr "Inclus dans ??Vos requêtes??" #: ../templates/classic/html/query.edit.html:31 msgid "Private to you?" -msgstr "Privé ?" +msgstr "Privé??" #: ../templates/classic/html/query.edit.html:44 msgid "leave out" @@ -3126,12 +3141,12 @@ #: ../templates/classic/html/query.edit.html:54 msgid "[query is retired]" -msgstr "[requête abandonnée]" +msgstr "[requête retirée]" #: ../templates/classic/html/query.edit.html:67 #: ../templates/classic/html/query.edit.html:92 msgid "edit" -msgstr "éditer" +msgstr "modifier" #: ../templates/classic/html/query.edit.html:71 msgid "yes" @@ -3143,7 +3158,7 @@ #: ../templates/classic/html/query.edit.html:79 msgid "Delete" -msgstr "Effacer" +msgstr "Supprimer" #: ../templates/classic/html/query.edit.html:94 msgid "[not yours to edit]" @@ -3151,7 +3166,7 @@ #: ../templates/classic/html/query.edit.html:102 msgid "Save Selection" -msgstr "Sauvegarder la s?lection" +msgstr "Enregistrer la s?lection" #: ../templates/classic/html/user.forgotten.html:3 msgid "Password reset request - ${tracker}" @@ -3165,14 +3180,11 @@ msgid "" "You have two options if you have forgotten your password. If you know the " "email address you registered with, enter it below." -msgstr "" -"Vous avez deux solutions si vous avez oublié votre mot de passe. Si " -"vous connaissez l'adresse de messagerie avec laquelle vous vous êtes " -"enregistré, introduisez-là ci-dessous." +msgstr "Vous avez deux solutions si vous avez oublié votre mot de passe. Si vous connaissez l'adresse ?lectronique avec laquelle vous vous êtes enregistré, saisissez là ci-dessous." #: ../templates/classic/html/user.forgotten.html:16 msgid "Email Address:" -msgstr "Adresse de messagerie:" +msgstr "Adresse ?lectronique?:" #: ../templates/classic/html/user.forgotten.html:24 #: ../templates/classic/html/user.forgotten.html:34 @@ -3181,21 +3193,20 @@ #: ../templates/classic/html/user.forgotten.html:30 msgid "Or, if you know your username, then enter it below." -msgstr "" -"ou, si vous connaissez votre nom d'utilisateur, introduisez-le ci-dessous." +msgstr "ou, si vous connaissez votre nom d'utilisateur, saisissez-le ci-dessous." #: ../templates/classic/html/user.forgotten.html:33 msgid "Username:" -msgstr "Nom d'utilisateur:" +msgstr "Nom d'utilisateur?:" #: ../templates/classic/html/user.forgotten.html:39 msgid "" "A confirmation email will be sent to you - please follow the instructions " "within it to complete the reset process." msgstr "" -"un courriel de confirmation va vous être envoyé - veuillez " -"suivre les instructions qui y sont données pour terminer le processus " -"de réinitialisation de votre mot de passe." +"un courriel de confirmation va vous être envoyé - suivez\n" +"les instructions qu'il contient pour terminer le processus de\n" +"réinitialisation de votre mot de passe." #: ../templates/classic/html/user.index.html:3 #: ../templates/minimal/html/user.index.html:3 @@ -3225,7 +3236,7 @@ #: ../templates/classic/html/user.index.html:17 #: ../templates/minimal/html/user.index.html:15 msgid "Email address" -msgstr "Adresse de messagerie" +msgstr "Adresse ?lectronique" #: ../templates/classic/html/user.index.html:18 msgid "Phone number" @@ -3233,16 +3244,16 @@ #: ../templates/classic/html/user.index.html:19 msgid "Retire" -msgstr "Abandonner" +msgstr "Retirer" #: ../templates/classic/html/user.index.html:32 msgid "retire" -msgstr "abandonner" +msgstr "retirer" #: ../templates/classic/html/user.item.html:7 #: ../templates/minimal/html/user.item.html:7 msgid "User ${id}: ${title} - ${tracker}" -msgstr "Utilisateur ${id}: ${title} - ${tracker}" +msgstr "Utilisateur ${id}?: ${title} - ${tracker}" #: ../templates/classic/html/user.item.html:10 #: ../templates/minimal/html/user.item.html:10 @@ -3257,17 +3268,17 @@ #: ../templates/classic/html/user.item.html:16 #: ../templates/minimal/html/user.item.html:16 msgid "New User Editing" -msgstr "Édition d'un nouvel utilisateur" +msgstr "Cr?ation d'un nouvel utilisateur" #: ../templates/classic/html/user.item.html:19 #: ../templates/minimal/html/user.item.html:19 msgid "User${id}" -msgstr "User${id}" +msgstr "Utilisateur?${id}" #: ../templates/classic/html/user.item.html:22 #: ../templates/minimal/html/user.item.html:22 msgid "User${id} Editing" -msgstr "Édition de User${id}" +msgstr "Modification de l'utilisateur?${id}" #: ../templates/classic/html/user.item.html:43 #: ../templates/classic/html/user.register.html:21 @@ -3300,9 +3311,7 @@ #: ../templates/classic/html/user.item.html:61 #: ../templates/minimal/html/user.item.html:58 msgid "(to give the user more than one role, enter a comma,separated,list)" -msgstr "" -"(pour donner ? l'utilisateur plus d'un rôle, introduisez une liste," -"séparée,par,des,virgules)" +msgstr "(pour donner ? l'utilisateur plus d'un rôle, saisissez une liste,séparée,par,des,virgules)" #: ../templates/classic/html/user.item.html:66 #: ../templates/classic/html/user.register.html:41 @@ -3324,21 +3333,21 @@ #: ../templates/minimal/html/user.item.html:63 #: ../templates/minimal/html/user.register.html:46 msgid "E-mail address" -msgstr "Adresse de messagerie" +msgstr "Adresse ?lectronique" #: ../templates/classic/html/user.item.html:91 #: ../templates/classic/html/user.register.html:53 #: ../templates/minimal/html/user.item.html:71 #: ../templates/minimal/html/user.register.html:50 msgid "Alternate E-mail addresses
    One address per line" -msgstr "Adresses de messagerie alternatives
    Une adresse par ligne" +msgstr "Adresses ?lectronique alternatives
    Une adresse par ligne" #: ../templates/classic/html/user.register.html:4 #: ../templates/classic/html/user.register.html:7 #: ../templates/minimal/html/user.register.html:4 #: ../templates/minimal/html/user.register.html:7 msgid "Registering with ${tracker}" -msgstr "Inscription auprès de ${tracker}" +msgstr "Inscription ? ${tracker}" #: ../templates/classic/html/user.rego_progress.html:4 #: ../templates/minimal/html/user.rego_progress.html:4 @@ -3355,23 +3364,19 @@ msgid "" "You will shortly receive an email to confirm your registration. To complete " "the registration process, visit the link indicated in the email." -msgstr "" -"Vous recevrez sous peu un courriel confirmant votre inscription. Pour " -"clôturer le processus d'inscription, veuillez suivre le lien " -"indiqué dans le courriel." +msgstr "Vous recevrez sous peu un courriel confirmant votre inscription. Pour clôturer le processus d'inscription, suivez le lien indiqué dans le courriel." #: ../templates/minimal/html/home.html:2 msgid "Tracker home - ${tracker}" -msgstr "Base du pisteur - ${tracker}" +msgstr "Accueil de Tracker - ${tracker}" #: ../templates/minimal/html/home.html:4 msgid "Tracker home" -msgstr "Base du pisteur" +msgstr "Accueil de Tracker" #: ../templates/minimal/html/home.html:16 msgid "Please select from one of the menu options on the left." -msgstr "" -"Veuillez sélectionner l'une des options de menu à la gauche." +msgstr "Sélectionnez l'une des options du menu de gauche." #: ../templates/minimal/html/home.html:19 msgid "Please log in or register." @@ -3379,4 +3384,6 @@ #: ../templates/minimal/html/page.html:55 msgid "Hello,
    ${user}" -msgstr "Bienvenue,
    ${user}" +msgstr "Bienvenue,
    ${user}" + + Added: tracker/roundup-src/locale/it.po ============================================================================== --- (empty file) +++ tracker/roundup-src/locale/it.po Sun Mar 15 22:43:30 2009 @@ -0,0 +1,3043 @@ +# Italian message file for Roundup Issue Tracker +# Marco Ghidinelli , 2007 +# +# $Id: it.po,v 1.2 2007-08-24 05:31:13 a1s Exp $ +# +# roundup.pot revision 1.22 +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: roundup cvs\n" +"Report-Msgid-Bugs-To: roundup-devel at lists.sourceforge.net\n" +"POT-Creation-Date: 2006-12-18 13:36+0200\n" +"PO-Revision-Date: 2007-07-17 11:05+0200\n" +"Last-Translator: Marco Ghidinelli \n" +"Language-Team: italian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0" +" : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +# ../roundup/admin.py:1052 ../roundup/admin.py:85:981 :1030:1052 +#: ../roundup/admin.py:85 ../roundup/admin.py:981 ../roundup/admin.py:1030 +#: ../roundup/admin.py:1052 +#, python-format +msgid "no such class \"%(classname)s\"" +msgstr "classe \"%(classname)s\" mancante" + +# ../roundup/admin.py:95 ../roundup/admin.py:99 ../roundup/admin.py:95:99 +#: ../roundup/admin.py:95 ../roundup/admin.py:99 +#, python-format +msgid "argument \"%(arg)s\" not propname=value" +msgstr "argomento \"%(arg)s\" non nel formato nome=valore" + +#: ../roundup/admin.py:112 +#, python-format +msgid "" +"Problem: %(message)s\n" +"\n" +msgstr "" +"Problema: %(message)s\n" +"\n" + +#: ../roundup/admin.py:113 +#, python-format +msgid "" +"%(message)sUsage: roundup-admin [options] [ ]\n" +"\n" +"Options:\n" +" -i instance home -- specify the issue tracker \"home directory\" to " +"administer\n" +" -u -- the user[:password] to use for commands\n" +" -d -- print full designators not just class id numbers\n" +" -c -- when outputting lists of data, comma-separate them.\n" +" Same as '-S \",\"'.\n" +" -S -- when outputting lists of data, string-separate them\n" +" -s -- when outputting lists of data, space-separate them.\n" +" Same as '-S \" \"'.\n" +" -V -- be verbose when importing\n" +" -v -- report Roundup and Python versions (and quit)\n" +"\n" +" Only one of -s, -c or -S can be specified.\n" +"\n" +"Help:\n" +" roundup-admin -h\n" +" roundup-admin help -- this help\n" +" roundup-admin help -- command-specific help\n" +" roundup-admin help all -- all available help\n" +msgstr "" + +#: ../roundup/admin.py:140 +msgid "Commands:" +msgstr "Comandi:" + +#: ../roundup/admin.py:147 +msgid "" +"Commands may be abbreviated as long as the abbreviation\n" +"matches only one command, e.g. l == li == lis == list." +msgstr "" +"I comandi possono essere abbreviati finch?? l'abbreviazione rimane univoca\n" +"es: l == li == lis == list." + +#: ../roundup/admin.py:177 +msgid "" +"\n" +"All commands (except help) require a tracker specifier. This is just\n" +"the path to the roundup tracker you're working with. A roundup tracker\n" +"is where roundup keeps the database and configuration file that defines\n" +"an issue tracker. It may be thought of as the issue tracker's \"home\n" +"directory\". It may be specified in the environment variable TRACKER_HOME\n" +"or on the command line as \"-i tracker\".\n" +"\n" +"A designator is a classname and a nodeid concatenated, eg. bug1, " +"user10, ...\n" +"\n" +"Property values are represented as strings in command arguments and in the\n" +"printed results:\n" +" . Strings are, well, strings.\n" +" . Date values are printed in the full date format in the local time zone,\n" +" and accepted in the full format or any of the partial formats explained\n" +" below.\n" +" . Link values are printed as node designators. When given as an argument,\n" +" node designators and key strings are both accepted.\n" +" . Multilink values are printed as lists of node designators joined\n" +" by commas. When given as an argument, node designators and key\n" +" strings are both accepted; an empty string, a single node, or a list\n" +" of nodes joined by commas is accepted.\n" +"\n" +"When property values must contain spaces, just surround the value with\n" +"quotes, either ' or \". A single space may also be backslash-quoted. If a\n" +"value must contain a quote character, it must be backslash-quoted or inside\n" +"quotes. Examples:\n" +" hello world (2 tokens: hello, world)\n" +" \"hello world\" (1 token: hello world)\n" +" \"Roch'e\" Compaan (2 tokens: Roch'e Compaan)\n" +" Roch\\'e Compaan (2 tokens: Roch'e Compaan)\n" +" address=\"1 2 3\" (1 token: address=1 2 3)\n" +" \\\\ (1 token: \\)\n" +" \\n\\r\\t (1 token: a newline, carriage-return and " +"tab)\n" +"\n" +"When multiple nodes are specified to the roundup get or roundup set\n" +"commands, the specified properties are retrieved or set on all the listed\n" +"nodes.\n" +"\n" +"When multiple results are returned by the roundup get or roundup find\n" +"commands, they are printed one per line (default) or joined by commas (with\n" +"the -c) option.\n" +"\n" +"Where the command changes data, a login name/password is required. The\n" +"login may be specified as either \"name\" or \"name:password\".\n" +" . ROUNDUP_LOGIN environment variable\n" +" . the -u command-line option\n" +"If either the name or password is not supplied, they are obtained from the\n" +"command-line.\n" +"\n" +"Date format examples:\n" +" \"2000-04-17.03:45\" means \n" +" \"2000-04-17\" means \n" +" \"01-25\" means \n" +" \"08-13.22:13\" means \n" +" \"11-07.09:32:43\" means \n" +" \"14:25\" means \n" +" \"8:47:11\" means \n" +" \".\" means \"right now\"\n" +"\n" +"Command help:\n" +msgstr "" + +#: ../roundup/admin.py:240 +#, python-format +msgid "%s:" +msgstr "%s:" + +#: ../roundup/admin.py:245 +msgid "" +"Usage: help topic\n" +" Give help about topic.\n" +"\n" +" commands -- list commands\n" +" -- help specific to a command\n" +" initopts -- init command options\n" +" all -- all available help\n" +" " +msgstr "" + +#: ../roundup/admin.py:268 +#, python-format +msgid "Sorry, no help for \"%(topic)s\"" +msgstr "Nessun aiuto per \"%(topic)s\"" + +# ../roundup/admin.py:340 ../roundup/admin.py:396 ../roundup/admin.py:340:396 +#: ../roundup/admin.py:340 ../roundup/admin.py:396 +msgid "Templates:" +msgstr "Modelli predefiniti:" + +# ../roundup/admin.py:343 ../roundup/admin.py:407 ../roundup/admin.py:343:407 +#: ../roundup/admin.py:343 ../roundup/admin.py:407 +msgid "Back ends:" +msgstr "Back ends:" + +#: ../roundup/admin.py:346 +msgid "" +"Usage: install [template [backend [key=val[,key=val]]]]\n" +" Install a new Roundup tracker.\n" +"\n" +" The command will prompt for the tracker home directory\n" +" (if not supplied through TRACKER_HOME or the -i option).\n" +" The template and backend may be specified on the command-line\n" +" as arguments, in that order.\n" +"\n" +" Command line arguments following the backend allows you to\n" +" pass initial values for config options. For example, passing\n" +" \"web_http_auth=no,rdbms_user=dinsdale\" will override defaults\n" +" for options http_auth in section [web] and user in section [rdbms].\n" +" Please be careful to not use spaces in this argument! (Enclose\n" +" whole argument in quotes if you need spaces in option value).\n" +"\n" +" The initialise command must be called after this command in order\n" +" to initialise the tracker's database. You may edit the tracker's\n" +" initial database contents before running that command by editing\n" +" the tracker's dbinit.py module init() function.\n" +"\n" +" See also initopts help.\n" +" " +msgstr "" + +# ../roundup/admin.py:1243 ../roundup/admin.py:369:466 :1020:1042 :1072:1171 +# :1243 :527:606 :656:714 :735:763 :834:901 :972 +#: ../roundup/admin.py:369 ../roundup/admin.py:466 ../roundup/admin.py:527 +#: ../roundup/admin.py:606 ../roundup/admin.py:656 ../roundup/admin.py:714 +#: ../roundup/admin.py:735 ../roundup/admin.py:763 ../roundup/admin.py:834 +#: ../roundup/admin.py:901 ../roundup/admin.py:972 ../roundup/admin.py:1020 +#: ../roundup/admin.py:1042 ../roundup/admin.py:1072 ../roundup/admin.py:1171 +#: ../roundup/admin.py:1243 +msgid "Not enough arguments supplied" +msgstr "Non sono stati forniti abbastanza argomenti" + +#: ../roundup/admin.py:375 +#, python-format +msgid "Instance home parent directory \"%(parent)s\" does not exist" +msgstr "la directory radice dell'istanza \"%(parent)s\" non esiste" + +#: ../roundup/admin.py:383 +#, python-format +msgid "" +"WARNING: There appears to be a tracker in \"%(tracker_home)s\"!\n" +"If you re-install it, you will lose all the data!\n" +"Erase it? Y/N: " +msgstr "" +"ATTENZIONE: ?? presente un tracker nella directory \"%(tracker_home)s\"!\n" +"Se verr?? reinstallata, tutti i dati precedentemente salvati andranno persi\n" +"Cancellare la directory specificata? Y/N: " + +#: ../roundup/admin.py:398 +msgid "Select template [classic]: " +msgstr "Seleziona il modello predefinito [classic]: " + +#: ../roundup/admin.py:409 +msgid "Select backend [anydbm]: " +msgstr "Seleziona il backend [anydbm]: " + +#: ../roundup/admin.py:419 +#, python-format +msgid "Error in configuration settings: \"%s\"" +msgstr "Erorre nei settaggi di configurazione: \"%s\"" + +#: ../roundup/admin.py:428 +#, python-format +msgid "" +"\n" +"---------------------------------------------------------------------------\n" +" You should now edit the tracker configuration file:\n" +" %(config_file)s" +msgstr "" + +#: ../roundup/admin.py:438 +msgid " ... at a minimum, you must set following options:" +msgstr " ... devono essere configurate almeno le seguenti opzioni:" + +#: ../roundup/admin.py:443 +#, python-format +msgid "" +"\n" +" If you wish to modify the database schema,\n" +" you should also edit the schema file:\n" +" %(database_config_file)s\n" +" You may also change the database initialisation file:\n" +" %(database_init_file)s\n" +" ... see the documentation on customizing for more information.\n" +"\n" +" You MUST run the \"roundup-admin initialise\" command once you've " +"performed\n" +" the above steps.\n" +"---------------------------------------------------------------------------\n" +msgstr "" + +#: ../roundup/admin.py:461 +msgid "" +"Usage: genconfig \n" +" Generate a new tracker config file (ini style) with default values\n" +" in .\n" +" " +msgstr "" + +#. password +#: ../roundup/admin.py:471 +msgid "" +"Usage: initialise [adminpw]\n" +" Initialise a new Roundup tracker.\n" +"\n" +" The administrator details will be set at this step.\n" +"\n" +" Execute the tracker's initialisation function dbinit.init()\n" +" " +msgstr "" + +#: ../roundup/admin.py:485 +msgid "Admin Password: " +msgstr "Password dell'amministratore" + +#: ../roundup/admin.py:486 +msgid " Confirm: " +msgstr " Conferma: " + +#: ../roundup/admin.py:490 +msgid "Instance home does not exist" +msgstr "La home dell'istanza non esiste" + +#: ../roundup/admin.py:494 +msgid "Instance has not been installed" +msgstr "L'istanza non ?? stata installata" + +#: ../roundup/admin.py:499 +msgid "" +"WARNING: The database is already initialised!\n" +"If you re-initialise it, you will lose all the data!\n" +"Erase it? Y/N: " +msgstr "" + +#: ../roundup/admin.py:520 +msgid "" +"Usage: get property designator[,designator]*\n" +" Get the given property of one or more designator(s).\n" +"\n" +" Retrieves the property value of the nodes specified\n" +" by the designators.\n" +" " +msgstr "" + +# ../roundup/admin.py:560 ../roundup/admin.py:575 ../roundup/admin.py:560:575 +#: ../roundup/admin.py:560 ../roundup/admin.py:575 +#, python-format +msgid "property %s is not of type Multilink or Link so -d flag does not apply." +msgstr "" + +# ../roundup/admin.py:1054 ../roundup/admin.py:583:983 :1032:1054 +#: ../roundup/admin.py:583 ../roundup/admin.py:983 ../roundup/admin.py:1032 +#: ../roundup/admin.py:1054 +#, python-format +msgid "no such %(classname)s node \"%(nodeid)s\"" +msgstr "" + +#: ../roundup/admin.py:585 +#, python-format +msgid "no such %(classname)s property \"%(propname)s\"" +msgstr "" + +#: ../roundup/admin.py:594 +msgid "" +"Usage: set items property=value property=value ...\n" +" Set the given properties of one or more items(s).\n" +"\n" +" The items are specified as a class or as a comma-separated\n" +" list of item designators (ie \"designator[,designator,...]\").\n" +"\n" +" This command sets the properties to the values for all designators\n" +" given. If the value is missing (ie. \"property=\") then the " +"property\n" +" is un-set. If the property is a multilink, you specify the linked\n" +" ids for the multilink as comma-separated numbers (ie \"1,2,3\").\n" +" " +msgstr "" + +#: ../roundup/admin.py:648 +msgid "" +"Usage: find classname propname=value ...\n" +" Find the nodes of the given class with a given link property value.\n" +"\n" +" Find the nodes of the given class with a given link property value.\n" +" The value may be either the nodeid of the linked node, or its key\n" +" value.\n" +" " +msgstr "" + +# ../roundup/admin.py:920 ../roundup/admin.py:701:854 :866:920 +#: ../roundup/admin.py:701 ../roundup/admin.py:854 ../roundup/admin.py:866 +#: ../roundup/admin.py:920 +#, python-format +msgid "%(classname)s has no property \"%(propname)s\"" +msgstr "la classe %(classname)s non ha la propriet?? \"%(propname)s\"" + +#: ../roundup/admin.py:708 +msgid "" +"Usage: specification classname\n" +" Show the properties for a classname.\n" +"\n" +" This lists the properties for a given class.\n" +" " +msgstr "" + +#: ../roundup/admin.py:723 +#, python-format +msgid "%(key)s: %(value)s (key property)" +msgstr "%(key)s %(value)s (chiave)" + +#: ../roundup/admin.py:725 +#, python-format +msgid "%(key)s: %(value)s" +msgstr "%(key)s:??%(value)s" + +#: ../roundup/admin.py:728 +msgid "" +"Usage: display designator[,designator]*\n" +" Show the property values for the given node(s).\n" +"\n" +" This lists the properties and their associated values for the given\n" +" node.\n" +" " +msgstr "" + +#: ../roundup/admin.py:752 +#, python-format +msgid "%(key)s: %(value)r" +msgstr "%(key)s:??%(value)r" + +#: ../roundup/admin.py:755 +msgid "" +"Usage: create classname property=value ...\n" +" Create a new entry of a given class.\n" +"\n" +" This creates a new entry of the given class using the property\n" +" name=value arguments provided on the command line after the \"create" +"\"\n" +" command.\n" +" " +msgstr "" + +#: ../roundup/admin.py:782 +#, python-format +msgid "%(propname)s (Password): " +msgstr "%(propname)s??(Password):??" + +#: ../roundup/admin.py:784 +#, python-format +msgid " %(propname)s (Again): " +msgstr " %(propname)s (Ripeti password): " + +#: ../roundup/admin.py:786 +msgid "Sorry, try again..." +msgstr "Mi dispiace, riprova..." + +#: ../roundup/admin.py:790 +#, python-format +msgid "%(propname)s (%(proptype)s): " +msgstr "%(propname)s (%(proptype)s): " + +#: ../roundup/admin.py:808 +#, python-format +msgid "you must provide the \"%(propname)s\" property." +msgstr "deve essere fornita la propriet?? \"%(propname)s\"." + +#: ../roundup/admin.py:819 +msgid "" +"Usage: list classname [property]\n" +" List the instances of a class.\n" +"\n" +" Lists all instances of the given class. If the property is not\n" +" specified, the \"label\" property is used. The label property is\n" +" tried in order: the key, \"name\", \"title\" and then the first\n" +" property, alphabetically.\n" +"\n" +" With -c, -S or -s print a list of item id's if no property\n" +" specified. If property specified, print list of that property\n" +" for every class instance.\n" +" " +msgstr "" + +#: ../roundup/admin.py:832 +msgid "Too many arguments supplied" +msgstr "" + +#: ../roundup/admin.py:868 +#, python-format +msgid "%(nodeid)4s: %(value)s" +msgstr "" + +#: ../roundup/admin.py:872 +msgid "" +"Usage: table classname [property[,property]*]\n" +" List the instances of a class in tabular form.\n" +"\n" +" Lists all instances of the given class. If the properties are not\n" +" specified, all properties are displayed. By default, the column\n" +" widths are the width of the largest value. The width may be\n" +" explicitly defined by defining the property as \"name:width\".\n" +" For example::\n" +"\n" +" roundup> table priority id,name:10\n" +" Id Name\n" +" 1 fatal-bug\n" +" 2 bug\n" +" 3 usability\n" +" 4 feature\n" +"\n" +" Also to make the width of the column the width of the label,\n" +" leave a trailing : without a width on the property. For example::\n" +"\n" +" roundup> table priority id,name:\n" +" Id Name\n" +" 1 fata\n" +" 2 bug\n" +" 3 usab\n" +" 4 feat\n" +"\n" +" will result in a the 4 character wide \"Name\" column.\n" +" " +msgstr "" + +#: ../roundup/admin.py:916 +#, python-format +msgid "\"%(spec)s\" not name:width" +msgstr "" + +#: ../roundup/admin.py:966 +msgid "" +"Usage: history designator\n" +" Show the history entries of a designator.\n" +"\n" +" Lists the journal entries for the node identified by the " +"designator.\n" +" " +msgstr "" + +#: ../roundup/admin.py:987 +msgid "" +"Usage: commit\n" +" Commit changes made to the database during an interactive session.\n" +"\n" +" The changes made during an interactive session are not\n" +" automatically written to the database - they must be committed\n" +" using this command.\n" +"\n" +" One-off commands on the command-line are automatically committed if\n" +" they are successful.\n" +" " +msgstr "" + +#: ../roundup/admin.py:1001 +msgid "" +"Usage: rollback\n" +" Undo all changes that are pending commit to the database.\n" +"\n" +" The changes made during an interactive session are not\n" +" automatically written to the database - they must be committed\n" +" manually. This command undoes all those changes, so a commit\n" +" immediately after would make no changes to the database.\n" +" " +msgstr "" + +#: ../roundup/admin.py:1013 +msgid "" +"Usage: retire designator[,designator]*\n" +" Retire the node specified by designator.\n" +"\n" +" This action indicates that a particular node is not to be retrieved\n" +" by the list or find commands, and its key value may be re-used.\n" +" " +msgstr "" + +#: ../roundup/admin.py:1036 +msgid "" +"Usage: restore designator[,designator]*\n" +" Restore the retired node specified by designator.\n" +"\n" +" The given nodes will become available for users again.\n" +" " +msgstr "" + +#. grab the directory to export to +#: ../roundup/admin.py:1058 +msgid "" +"Usage: export [[-]class[,class]] export_dir\n" +" Export the database to colon-separated-value files.\n" +" To exclude the files (e.g. for the msg or file class),\n" +" use the exporttables command.\n" +"\n" +" Optionally limit the export to just the named classes\n" +" or exclude the named classes, if the 1st argument starts with '-'.\n" +"\n" +" This action exports the current data from the database into\n" +" colon-separated-value files that are placed in the nominated\n" +" destination directory.\n" +" " +msgstr "" + +#: ../roundup/admin.py:1136 +msgid "" +"Usage: exporttables [[-]class[,class]] export_dir\n" +" Export the database to colon-separated-value files, excluding the\n" +" files below $TRACKER_HOME/db/files/ (which can be archived " +"separately).\n" +" To include the files, use the export command.\n" +"\n" +" Optionally limit the export to just the named classes\n" +" or exclude the named classes, if the 1st argument starts with '-'.\n" +"\n" +" This action exports the current data from the database into\n" +" colon-separated-value files that are placed in the nominated\n" +" destination directory.\n" +" " +msgstr "" + +#: ../roundup/admin.py:1151 +msgid "" +"Usage: import import_dir\n" +" Import a database from the directory containing CSV files,\n" +" two per class to import.\n" +"\n" +" The files used in the import are:\n" +"\n" +" .csv\n" +" This must define the same properties as the class (including\n" +" having a \"header\" line with those property names.)\n" +" -journals.csv\n" +" This defines the journals for the items being imported.\n" +"\n" +" The imported nodes will have the same nodeid as defined in the\n" +" import file, thus replacing any existing content.\n" +"\n" +" The new nodes are added to the existing database - if you want to\n" +" create a new database using the imported data, then create a new\n" +" database (or, tediously, retire all the old data.)\n" +" " +msgstr "" + +#: ../roundup/admin.py:1225 +msgid "" +"Usage: pack period | date\n" +"\n" +" Remove journal entries older than a period of time specified or\n" +" before a certain date.\n" +"\n" +" A period is specified using the suffixes \"y\", \"m\", and \"d\". " +"The\n" +" suffix \"w\" (for \"week\") means 7 days.\n" +"\n" +" \"3y\" means three years\n" +" \"2y 1m\" means two years and one month\n" +" \"1m 25d\" means one month and 25 days\n" +" \"2w 3d\" means two weeks and three days\n" +"\n" +" Date format is \"YYYY-MM-DD\" eg:\n" +" 2001-01-01\n" +"\n" +" " +msgstr "" + +#: ../roundup/admin.py:1253 +msgid "Invalid format" +msgstr "" + +#: ../roundup/admin.py:1263 +msgid "" +"Usage: reindex [classname|designator]*\n" +" Re-generate a tracker's search indexes.\n" +"\n" +" This will re-generate the search indexes for a tracker.\n" +" This will typically happen automatically.\n" +" " +msgstr "" + +#: ../roundup/admin.py:1277 +#, python-format +msgid "no such item \"%(designator)s\"" +msgstr "" + +#: ../roundup/admin.py:1287 +msgid "" +"Usage: security [Role name]\n" +" Display the Permissions available to one or all Roles.\n" +" " +msgstr "" + +#: ../roundup/admin.py:1295 +#, python-format +msgid "No such Role \"%(role)s\"" +msgstr "Non ?? presente il ruolo \"%(role)s\"" + +#: ../roundup/admin.py:1301 +#, python-format +msgid "New Web users get the Roles \"%(role)s\"" +msgstr "I nuovi utenti Web otterranno i ruoli \"%(role)s\"" + +#: ../roundup/admin.py:1303 +#, python-format +msgid "New Web users get the Role \"%(role)s\"" +msgstr "I nuovi utenti Web otterranno il ruolo \"%(role)s)\"" + +#: ../roundup/admin.py:1306 +#, python-format +msgid "New Email users get the Roles \"%(role)s\"" +msgstr "I nuovi utenti Email otterranno i ruoli \"%(role)s)\"" + +#: ../roundup/admin.py:1308 +#, python-format +msgid "New Email users get the Role \"%(role)s\"" +msgstr "I nuovi utenti Email otterranno il ruolo \"%(role)s\"" + +#: ../roundup/admin.py:1311 +#, python-format +msgid "Role \"%(name)s\":" +msgstr "Ruolo \"%(name)s\":" + +#: ../roundup/admin.py:1316 +#, python-format +msgid " %(description)s (%(name)s for \"%(klass)s\": %(properties)s only)" +msgstr "" + +#: ../roundup/admin.py:1319 +#, python-format +msgid " %(description)s (%(name)s for \"%(klass)s\" only)" +msgstr "" + +#: ../roundup/admin.py:1322 +#, python-format +msgid " %(description)s (%(name)s)" +msgstr "" + +#: ../roundup/admin.py:1351 +#, python-format +msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)" +msgstr "" + +#: ../roundup/admin.py:1357 +#, python-format +msgid "Multiple commands match \"%(command)s\": %(list)s" +msgstr "" + +#: ../roundup/admin.py:1364 +msgid "Enter tracker home: " +msgstr "" + +# ../roundup/admin.py:1371:1377 :1397 +#: ../roundup/admin.py:1371 ../roundup/admin.py:1377 ../roundup/admin.py:1397 +#, python-format +msgid "Error: %(message)s" +msgstr "" + +#: ../roundup/admin.py:1385 +#, python-format +msgid "Error: Couldn't open tracker: %(message)s" +msgstr "" + +#: ../roundup/admin.py:1410 +#, python-format +msgid "" +"Roundup %s ready for input.\n" +"Type \"help\" for help." +msgstr "" + +#: ../roundup/admin.py:1415 +msgid "Note: command history and editing not available" +msgstr "" + +#: ../roundup/admin.py:1419 +msgid "roundup> " +msgstr "" + +#: ../roundup/admin.py:1421 +msgid "exit..." +msgstr "" + +#: ../roundup/admin.py:1431 +msgid "There are unsaved changes. Commit them (y/N)? " +msgstr "" + +#: ../roundup/backends/back_anydbm.py:2000 +#, python-format +msgid "WARNING: invalid date tuple %r" +msgstr "" + +#: ../roundup/backends/rdbms_common.py:1442 +msgid "create" +msgstr "crea" + +#: ../roundup/backends/rdbms_common.py:1608 +msgid "unlink" +msgstr "collega" + +#: ../roundup/backends/rdbms_common.py:1612 +msgid "link" +msgstr "scollega" + +#: ../roundup/backends/rdbms_common.py:1732 +msgid "set" +msgstr "assegna" + +#: ../roundup/backends/rdbms_common.py:1756 +msgid "retired" +msgstr "ritira" + +#: ../roundup/backends/rdbms_common.py:1786 +msgid "restored" +msgstr "ripristina" + +#: ../roundup/cgi/actions.py:58 +#, python-format +msgid "You do not have permission to %(action)s the %(classname)s class." +msgstr "Non hai i permessi per %{action) la classe %(classname)." + +#: ../roundup/cgi/actions.py:89 +msgid "No type specified" +msgstr "Non hai specificato alcun tipo" + +#: ../roundup/cgi/actions.py:91 +msgid "No ID entered" +msgstr "Non hai fornito alcun ID" + +#: ../roundup/cgi/actions.py:97 +#, python-format +msgid "\"%(input)s\" is not an ID (%(classname)s ID required)" +msgstr "\"%(input)\" non ?? un ID (%(ID della %(classname) ?? obbligatorio" + +#: ../roundup/cgi/actions.py:117 +msgid "You may not retire the admin or anonymous user" +msgstr "Non ?? possibile ritirare l'utente amministratore o l'utente anonimo" + +#: ../roundup/cgi/actions.py:124 +#, python-format +msgid "%(classname)s %(itemid)s has been retired" +msgstr "%(classname)s %(itemid)s ?? stato ritirato" + +# ../roundup/cgi/actions.py:174:202 +#: ../roundup/cgi/actions.py:174 ../roundup/cgi/actions.py:202 +msgid "You do not have permission to edit queries" +msgstr "Non hai il permesso di modificare delle query" + +# ../roundup/cgi/actions.py:180:209 +#: ../roundup/cgi/actions.py:180 ../roundup/cgi/actions.py:209 +msgid "You do not have permission to store queries" +msgstr "Non hai il permesso di archiviare delle query" + +#: ../roundup/cgi/actions.py:298 +#, python-format +msgid "Not enough values on line %(line)s" +msgstr "Non abbastanza valori alla riga %(line)" + +#: ../roundup/cgi/actions.py:345 +msgid "Items edited OK" +msgstr "Item modificato correttamente" + +#: ../roundup/cgi/actions.py:405 +#, python-format +msgid "%(class)s %(id)s %(properties)s edited ok" +msgstr "%(class)s %(id)s %(properties)s modificata correttamente" + +#: ../roundup/cgi/actions.py:408 +#, python-format +msgid "%(class)s %(id)s - nothing changed" +msgstr "%(class)s %(id)s - nessuna modifica" + +#: ../roundup/cgi/actions.py:420 +#, python-format +msgid "%(class)s %(id)s created" +msgstr "%(class)s %(id)s creata" + +#: ../roundup/cgi/actions.py:452 +#, python-format +msgid "You do not have permission to edit %(class)s" +msgstr "Non hai i permessi per modificare i $(class)s" + +#: ../roundup/cgi/actions.py:464 +#, python-format +msgid "You do not have permission to create %(class)s" +msgstr "Non hai il permesso per creare $(class)s" + +#: ../roundup/cgi/actions.py:488 +msgid "You do not have permission to edit user roles" +msgstr "Non hai i permessi per modificare l ruoli dell'utente" + +#: ../roundup/cgi/actions.py:538 +#, python-format +msgid "" +"Edit Error: someone else has edited this %s (%s). View their changes in a new window." +msgstr "" +"Errore di Modifica: qualcun'altro ha modificato questo %s (%s). Visualizza " +"le sue modifiche in una nuova finestra." + +#: ../roundup/cgi/actions.py:566 +#, python-format +msgid "Edit Error: %s" +msgstr "Errore di modifica: %s" + +# ../roundup/cgi/actions.py:597:608 :779:798 +#: ../roundup/cgi/actions.py:597 ../roundup/cgi/actions.py:608 +#: ../roundup/cgi/actions.py:779 ../roundup/cgi/actions.py:798 +#, python-format +msgid "Error: %s" +msgstr "Errore: %s" + +#: ../roundup/cgi/actions.py:634 +msgid "" +"Invalid One Time Key!\n" +"(a Mozilla bug may cause this message to show up erroneously, please check " +"your email)" +msgstr "" +"One Time Key invalido!\n" +"(un bug di Mozilla pu?? causare la erronea presenza di questo messaggio, (per " +"favore controlla la tua email)" + +#: ../roundup/cgi/actions.py:676 +#, python-format +msgid "Password reset and email sent to %s" +msgstr "Password modificata e mandata in email a %s" + +#: ../roundup/cgi/actions.py:685 +msgid "Unknown username" +msgstr "Nome Utente sconosciuto" + +#: ../roundup/cgi/actions.py:693 +msgid "Unknown email address" +msgstr "Indirizzo di email sconosciuto" + +#: ../roundup/cgi/actions.py:698 +msgid "You need to specify a username or address" +msgstr "?? necessario specificare un Nome Utente o un indirizzo email" + +#: ../roundup/cgi/actions.py:723 +#, python-format +msgid "Email sent to %s" +msgstr "Email inviata a %s" + +#: ../roundup/cgi/actions.py:742 +msgid "You are now registered, welcome!" +msgstr "Ora sei un utente registrato, benvenuto!" + +#: ../roundup/cgi/actions.py:787 +msgid "It is not permitted to supply roles at registration." +msgstr "Non ?? permesso fornire ruoli in fase di registrazione." + +#: ../roundup/cgi/actions.py:879 +msgid "You are logged out" +msgstr "Disconnesso" + +#: ../roundup/cgi/actions.py:896 +msgid "Username required" +msgstr "?? richiesto il Nome Utente" + +# ../roundup/cgi/actions.py:931:935 +#: ../roundup/cgi/actions.py:931 ../roundup/cgi/actions.py:935 +msgid "Invalid login" +msgstr "Login invalida" + +#: ../roundup/cgi/actions.py:941 +msgid "You do not have permission to login" +msgstr "Non hai il permesso per eseguire la login" + +#: ../roundup/cgi/cgitb.py:49 +#, python-format +msgid "" +"

    Templating Error

    \n" +"

    %(exc_type)s: %(exc_value)s

    \n" +"

    Debugging information follows

    " +msgstr "" +"

    Errore del sistema di Templating

    \n" +"

    %(exc_type)s: %(exc_value)s

    \n" +"

    Debugging information follows

    " + +#: ../roundup/cgi/cgitb.py:64 +#, python-format +msgid "
  • \"%(name)s\" (%(info)s)
  • " +msgstr "
  • \"%(name)s\" (%(info)s)
  • " + +#: ../roundup/cgi/cgitb.py:67 +#, python-format +msgid "
  • Looking for \"%(name)s\", current path:
      %(path)s
  • " +msgstr "" +"
  • Sto cercando \"%(name)s\", percorso corrente:
      %(path)s
  • " + +#: ../roundup/cgi/cgitb.py:71 +#, python-format +msgid "
  • In %s
  • " +msgstr "
  • In %s
  • " + +#: ../roundup/cgi/cgitb.py:76 +#, python-format +msgid "A problem occurred in your template \"%s\"." +msgstr "?? occorso un problema nel tuo template" + +#: ../roundup/cgi/cgitb.py:84 +#, python-format +msgid "" +"\n" +"
  • While evaluating the %(info)r expression on line %(line)d\n" +"\n" +" \n" +" %(globals)s\n" +" %(locals)s\n" +"
    Current variables:
  • \n" +msgstr "" +"\n" +"
  • Mentre veniva valutato la espressione %(info)r alla riga %(line)d\n" +"\n" +" \n" +" %(globals)s\n" +" %(locals)s\n" +"
    Variabile Corrente:
  • \n" + +#: ../roundup/cgi/cgitb.py:103 +msgid "Full traceback:" +msgstr "Traceback completo:" + +#: ../roundup/cgi/cgitb.py:116 +#, python-format +msgid "%(exc_type)s: %(exc_value)s" +msgstr "%(exc_type)s: %(exc_value)s" + +#: ../roundup/cgi/cgitb.py:120 +msgid "" +"

    A problem occurred while running a Python script. Here is the sequence of " +"function calls leading up to the error, with the most recent (innermost) " +"call first. The exception attributes are:" +msgstr "" +"

    Un problema ?? occorso mentre veniva eseguito uno script Python. Questa ?? " +"la sequenza di chiamate di sistema che hanno condotto a questo errore, con " +"la pi?? recente (la pi?? interna) prima. Le eccezioni sono:" + +#: ../roundup/cgi/cgitb.py:129 +msgid "<file is None - probably inside eval or exec>" +msgstr "" + +#: ../roundup/cgi/cgitb.py:138 +#, python-format +msgid "in %s" +msgstr "in %s" + +# ../roundup/cgi/cgitb.py:172:178 +#: ../roundup/cgi/cgitb.py:172 ../roundup/cgi/cgitb.py:178 +msgid "undefined" +msgstr "indefinito" + +#: ../roundup/cgi/client.py:49 +msgid "" +"An error has occurred\n" +"

    An error has occurred

    \n" +"

    A problem was encountered processing your request.\n" +"The tracker maintainers have been notified of the problem.

    \n" +"" +msgstr "" +"?? accaduto un errore\n" +"

    ?? accaduto un errore

    \n" +"

    ?? accaduto un errore mentre veniva processata la richiesta.\n" +"La notifica del problema ?? stata notificata al manutentore del tracker.

    \n" +"" + +#: ../roundup/cgi/client.py:326 +msgid "Form Error: " +msgstr "Errore nella Form: " + +#: ../roundup/cgi/client.py:381 +#, python-format +msgid "Unrecognized charset: %r" +msgstr "Codice di carattere sconosciuto: %r" + +#: ../roundup/cgi/client.py:509 +msgid "Anonymous users are not allowed to use the web interface" +msgstr "" +"Gli utenti anonimi non hanno il permesso di utilizzare l'interfaccia web" + +#: ../roundup/cgi/client.py:664 +msgid "You are not allowed to view this file." +msgstr "Non si dispone dei permessi per visualizzare questo file." + +#: ../roundup/cgi/client.py:758 +#, python-format +msgid "%(starttag)sTime elapsed: %(seconds)fs%(endtag)s\n" +msgstr "%(starttag)sTempo trascorso: %(seconds)fs%(endtad)s\n" + +#: ../roundup/cgi/client.py:762 +#, python-format +msgid "" +"%(starttag)sCache hits: %(cache_hits)d, misses %(cache_misses)d. Loading " +"items: %(get_items)f secs. Filtering: %(filtering)f secs.%(endtag)s\n" +msgstr "" + +#: ../roundup/cgi/form_parser.py:283 +#, python-format +msgid "link \"%(key)s\" value \"%(entry)s\" not a designator" +msgstr "il collegamento \"%(key)s\" valore \"%(entry)s\" non ?? il designatore" + +#: ../roundup/cgi/form_parser.py:301 +#, python-format +msgid "%(class)s %(property)s is not a link or multilink property" +msgstr "" +"%(class)s %(property)s non ?? una propriet?? di tipo collegamento o " +"multicollegamento" + +#: ../roundup/cgi/form_parser.py:313 +#, python-format +msgid "" +"The form action claims to require property \"%(property)s\" which doesn't " +"exist" +msgstr "" +"L'azione assiociata alla form richiede la propriet?? \"%(property)s\" che non " +"esiste" + +#: ../roundup/cgi/form_parser.py:335 +#, python-format +msgid "" +"You have submitted a %(action)s action for the property \"%(property)s\" " +"which doesn't exist" +msgstr "" +"?? stata inserito una azione %(action)s per la propriet?? \"%(property)s\" che " +"non esiste" + +# ../roundup/cgi/form_parser.py:354:380 +#: ../roundup/cgi/form_parser.py:354 ../roundup/cgi/form_parser.py:380 +#, python-format +msgid "You have submitted more than one value for the %s property" +msgstr "?? stata inserito pi?? di un valore per la propriet?? %s" + +# ../roundup/cgi/form_parser.py:377:383 +#: ../roundup/cgi/form_parser.py:377 ../roundup/cgi/form_parser.py:383 +msgid "Password and confirmation text do not match" +msgstr "La password e il testo di conferma non coincidono" + +#: ../roundup/cgi/form_parser.py:418 +#, python-format +msgid "property \"%(propname)s\": \"%(value)s\" not currently in list" +msgstr "" +"la propriet?? \"%(propname)s\": \"%(value)s\" non ?? al momento nella lista" + +#: ../roundup/cgi/form_parser.py:551 +#, python-format +msgid "Required %(class)s property %(property)s not supplied" +msgid_plural "Required %(class)s properties %(property)s not supplied" +msgstr[0] "La propriet?? %(class)s %(property)s non ?? stata fornita" +msgstr[1] "Le propriet?? %(class)s %(property)s non sono state fornite" + +#: ../roundup/cgi/form_parser.py:574 +msgid "File is empty" +msgstr "Il file ?? vuoto" + +#: ../roundup/cgi/templating.py:73 +#, python-format +msgid "You are not allowed to %(action)s items of class %(class)s" +msgstr "Non si dispone dei permessi per %(action)s item della classe %(class)s" + +#: ../roundup/cgi/templating.py:645 +msgid "(list)" +msgstr "(elenco)" + +#: ../roundup/cgi/templating.py:714 +msgid "Submit New Entry" +msgstr "Crea Nuovo" + +# ../roundup/cgi/templating.py:728:862 :1269:1298 :1318:1364 :1387:1423 +# :1460:1513 :1530:1614 :1634:1652 :1684:1694 :1746:1935 +#: ../roundup/cgi/templating.py:728 ../roundup/cgi/templating.py:862 +#: ../roundup/cgi/templating.py:1269 ../roundup/cgi/templating.py:1298 +#: ../roundup/cgi/templating.py:1318 ../roundup/cgi/templating.py:1364 +#: ../roundup/cgi/templating.py:1387 ../roundup/cgi/templating.py:1423 +#: ../roundup/cgi/templating.py:1460 ../roundup/cgi/templating.py:1513 +#: ../roundup/cgi/templating.py:1530 ../roundup/cgi/templating.py:1614 +#: ../roundup/cgi/templating.py:1634 ../roundup/cgi/templating.py:1652 +#: ../roundup/cgi/templating.py:1684 ../roundup/cgi/templating.py:1694 +#: ../roundup/cgi/templating.py:1746 ../roundup/cgi/templating.py:1935 +msgid "[hidden]" +msgstr "[nascosto]" + +#: ../roundup/cgi/templating.py:729 +msgid "New node - no history" +msgstr "Nuovo nodo - nessuno storico" + +#: ../roundup/cgi/templating.py:844 +msgid "Submit Changes" +msgstr "Inserisci Modifiche" + +#: ../roundup/cgi/templating.py:926 +msgid "The indicated property no longer exists" +msgstr "La caratteristica indicata non esiste" + +#: ../roundup/cgi/templating.py:927 +#, python-format +msgid "%s: %s\n" +msgstr "%s: %s\n" + +#: ../roundup/cgi/templating.py:940 +#, python-format +msgid "The linked class %(classname)s no longer exists" +msgstr "La classe collegata %(classname)s non esiste pi??" + +# ../roundup/cgi/templating.py:973:997 +#: ../roundup/cgi/templating.py:973 ../roundup/cgi/templating.py:997 +msgid "The linked node no longer exists" +msgstr "Il Nodo collegato non esiste pi??" + +#: ../roundup/cgi/templating.py:1050 +#, python-format +msgid "%s: (no value)" +msgstr "%s: (nessun valore)" + +#: ../roundup/cgi/templating.py:1062 +msgid "" +"This event is not handled by the history display!" +msgstr "" +"Questo evento non ?? gestito dal visualizzatore dello storico!" + +#: ../roundup/cgi/templating.py:1074 +msgid "Note:" +msgstr "Note:" + +#: ../roundup/cgi/templating.py:1083 +msgid "History" +msgstr "Storico" + +#: ../roundup/cgi/templating.py:1085 +msgid "Date" +msgstr "Data" + +#: ../roundup/cgi/templating.py:1086 +msgid "User" +msgstr "Utente" + +#: ../roundup/cgi/templating.py:1087 +msgid "Action" +msgstr "Azione" + +#: ../roundup/cgi/templating.py:1088 +msgid "Args" +msgstr "Argomenti" + +#: ../roundup/cgi/templating.py:1130 +#, python-format +msgid "Copy of %(class)s %(id)s" +msgstr "Copia di %(class)s %(id)s" + +#: ../roundup/cgi/templating.py:1391 +msgid "*encrypted*" +msgstr "*crittato*" + +# ../roundup/cgi/templating.py:1491 ../roundup/cgi/templating.py:1039:1464 +# :1485:1491 +#: ../roundup/cgi/templating.py:1464 ../roundup/cgi/templating.py:1485 +#: ../roundup/cgi/templating.py:1491 ../roundup/cgi/templating.py:1039 +msgid "No" +msgstr "No" + +# ../roundup/cgi/templating.py:1488 ../roundup/cgi/templating.py:1039:1464 +# :1483:1488 +#: ../roundup/cgi/templating.py:1464 ../roundup/cgi/templating.py:1483 +#: ../roundup/cgi/templating.py:1488 ../roundup/cgi/templating.py:1039 +msgid "Yes" +msgstr "S??" + +#: ../roundup/cgi/templating.py:1577 +msgid "" +"default value for DateHTMLProperty must be either DateHTMLProperty or string " +"date representation." +msgstr "" +"Il valore predefinito per DateHTMLProperty deve essere DateHTMLProperty " +"oppure una stringa rappresentante una data." + +#: ../roundup/cgi/templating.py:1737 +#, python-format +msgid "Attempt to look up %(attr)s on a missing value" +msgstr "Tentativo di visualizzare %(attr)s con un valore mancante" + +#: ../roundup/cgi/templating.py:1810 +#, python-format +msgid "" +msgstr "" + +#: ../roundup/date.py:301 +msgid "" +"Not a date spec: \"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", \"HH:MM:SS\" or " +"\"yyyy-mm-dd.HH:MM:SS.SSS\"" +msgstr "" +"Non specifica una data: \"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", \"HH:MM:SS\" o " +"\"yyyy-mm-dd.HH:MM:SS.SSS\"" + +#: ../roundup/date.py:363 +#, python-format +msgid "" +"%r not a date / time spec \"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", \"HH:MM:SS\" " +"or \"yyyy-mm-dd.HH:MM:SS.SSS\"" +msgstr "" +"%r non specifica una data / momento \"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", " +"\"HH:MM:SS\" o \"yyyy-mm-dd.HH:MM:SS.SSS\"" + +#: ../roundup/date.py:662 +msgid "" +"Not an interval spec: [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS] [date spec]" +msgstr "" +"Non specifica un intervallo: [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS] [date " +"spec]" + +#: ../roundup/date.py:681 +msgid "Not an interval spec: [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS]" +msgstr "Non specifica un intervallo: [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS]" + +#: ../roundup/date.py:818 +#, python-format +msgid "%(number)s year" +msgid_plural "%(number)s years" +msgstr[0] "%(number)s anno" +msgstr[1] "%(numeber)s anni" + +#: ../roundup/date.py:822 +#, python-format +msgid "%(number)s month" +msgid_plural "%(number)s months" +msgstr[0] "%(number)s mese" +msgstr[1] "%(number)s mesi" + +#: ../roundup/date.py:826 +#, python-format +msgid "%(number)s week" +msgid_plural "%(number)s weeks" +msgstr[0] "%(number)s settimana" +msgstr[1] "%(number)s settimane" + +#: ../roundup/date.py:830 +#, python-format +msgid "%(number)s day" +msgid_plural "%(number)s days" +msgstr[0] "%(number)s giorno" +msgstr[1] "%(number)s giorni" + +#: ../roundup/date.py:834 +msgid "tomorrow" +msgstr "domani" + +#: ../roundup/date.py:836 +msgid "yesterday" +msgstr "ieri" + +#: ../roundup/date.py:839 +#, python-format +msgid "%(number)s hour" +msgid_plural "%(number)s hours" +msgstr[0] "%(number)s ora" +msgstr[1] "%(number)s ore" + +#: ../roundup/date.py:843 +msgid "an hour" +msgstr "un'ora" + +#: ../roundup/date.py:845 +msgid "1 1/2 hours" +msgstr "un'ora e mezza" + +#: ../roundup/date.py:847 +#, python-format +msgid "1 %(number)s/4 hours" +msgid_plural "1 %(number)s/4 hours" +msgstr[0] "%(number)s quarto d'ora" +msgstr[1] "%(number)s quarti d'ora" + +#: ../roundup/date.py:851 +msgid "in a moment" +msgstr "in un momento" + +#: ../roundup/date.py:853 +msgid "just now" +msgstr "proprio ora" + +#: ../roundup/date.py:856 +msgid "1 minute" +msgstr "un minuto" + +#: ../roundup/date.py:859 +#, python-format +msgid "%(number)s minute" +msgid_plural "%(number)s minutes" +msgstr[0] "%(number)s minuto" +msgstr[1] "%(number)s minuti" + +#: ../roundup/date.py:862 +msgid "1/2 an hour" +msgstr "mezzora" + +#: ../roundup/date.py:864 +#, python-format +msgid "%(number)s/4 hour" +msgid_plural "%(number)s/4 hours" +msgstr[0] "%(number)s ora" +msgstr[1] "%(number)s ore" + +#: ../roundup/date.py:868 +#, python-format +msgid "%s ago" +msgstr "%s fa" + +#: ../roundup/date.py:870 +#, python-format +msgid "in %s" +msgstr "in %s" + +#: ../roundup/init.py:134 +#, python-format +msgid "" +"WARNING: directory '%s'\n" +"\tcontains old-style template - ignored" +msgstr "" +"ATTENZIONE: La directory '%s'\n" +"\tcontene un template old-style - ignorato" + +#: ../roundup/mailgw.py:583 +msgid "" +"\n" +"Emails to Roundup trackers must include a Subject: line!\n" +msgstr "" +"\n" +"Le Email al tracker Roundup devono includere il campo Oggetto: \n" + +#: ../roundup/mailgw.py:673 +#, python-format +msgid "" +"\n" +"The message you sent to roundup did not contain a properly formed subject\n" +"line. The subject must contain a class name or designator to indicate the\n" +"'topic' of the message. For example:\n" +" Subject: [issue] This is a new issue\n" +" - this will create a new issue in the tracker with the title 'This is\n" +" a new issue'.\n" +" Subject: [issue1234] This is a followup to issue 1234\n" +" - this will append the message's contents to the existing issue 1234\n" +" in the tracker.\n" +"\n" +"Subject was: '%(subject)s'\n" +msgstr "" +"\n" +"Il messaggio che hai mandato a Roundup non contiene un campo \"Subject: " +"\" (Oggetto) ben formato. L'oggetto deve contenere un nome di una classe o " +"un designatore per indicare l'argomento del messaggio. Per esempio:\n" +" Subject: [issue] Questa ?? una nuova richiesta\n" +" - crea una nuova richiesta titolata: 'Questa ?? una nuova richiesta'.\n" +" Subject: [issue1234] Questa ?? una risposta alla richiesta 1234\n" +" - aggiunge un nuovo messaggio alla richiesta 1234 esistente\n" +"\n" +"Il campo \"Subject: \" (Oggetto) era: '%(subject)s'\n" + +#: ../roundup/mailgw.py:704 +#, python-format +msgid "" +"\n" +"The class name you identified in the subject line (\"%(classname)s\") does " +"not exist in the\n" +"database.\n" +"\n" +"Valid class names are: %(validname)s\n" +"Subject was: \"%(subject)s\"\n" +msgstr "" +"\n" +"La classe che hai identificato nel Subject: (\"%(classname)s\") non esiste " +"nel database.\n" +"\n" +"Classi valide sono: %(validname)s\n" +"Il campo Subject: conteneva il valore \"%(subject)s\"\n" + +#: ../roundup/mailgw.py:739 +#, python-format +msgid "" +"\n" +"I cannot match your message to a node in the database - you need to either\n" +"supply a full designator (with number, eg \"[issue123]\" or keep the\n" +"previous subject title intact so I can match that.\n" +"\n" +"Subject was: \"%(subject)s\"\n" +msgstr "" +"\n" +"Non ?? stato possibile far corrispondere il tuo messaggio con un nodo del " +"database - devi specificare nel Subject (Oggetto) un designatore corretto " +"(con un numero, per esempio [issue1234]) o alternativamente tenere il " +"Subject precedente intatto.\n" +"Il campo Subject: conteneva il valore \"%(subject)s\"\n" + +#: ../roundup/mailgw.py:772 +#, python-format +msgid "" +"\n" +"The node specified by the designator in the subject of your message\n" +"(\"%(nodeid)s\") does not exist.\n" +"\n" +"Subject was: \"%(subject)s\"\n" +msgstr "" +"\n" +"Il nodo specificato dal desigantore nel Subject del tuo messaggio (\"%" +"(nodeid)s\") non esiste.\n" +"\n" +"Il campo Subject: conteneva il valore \"%(subject)s\"\n" + +#: ../roundup/mailgw.py:800 +#, python-format +msgid "" +"\n" +"The mail gateway is not properly set up. Please contact\n" +"%(mailadmin)s and have them fix the incorrect class specified as:\n" +" %(current_class)s\n" +msgstr "" +"\n" +"Il gateway mail non ?? configurato correttamente. Per favore contatta\n" +"%(mailadmin)s e segnala che la classe specificata come:\n" +" %(current_class)s ?? scorretta.\n" + +#: ../roundup/mailgw.py:823 +#, python-format +msgid "" +"\n" +"The mail gateway is not properly set up. Please contact\n" +"%(mailadmin)s and have them fix the incorrect properties:\n" +" %(errors)s\n" +msgstr "" +"\n" +"il gateway mail non ?? configurato correttamente. Per favore contatta\n" +"%(mailadmin)s e segnala che la propriet?? scorretta:\n" +" %(errors)s\n" + +#: ../roundup/mailgw.py:853 +#, python-format +msgid "" +"\n" +"You are not a registered user.\n" +"\n" +"Unknown address: %(from_address)s\n" +msgstr "" +"\n" +"Non sei un utente registrato.\n" +"\n" +"Indirizzo sconosciuto: %(from_address)s\n" + +#: ../roundup/mailgw.py:861 +msgid "You are not permitted to access this tracker." +msgstr "Non si dispone di permessi sufficienti per accedere a questo tracker" + +#: ../roundup/mailgw.py:868 +#, python-format +msgid "You are not permitted to edit %(classname)s." +msgstr "Non si dispone dei permessi sufficienti per modificare %(classname)s" + +#: ../roundup/mailgw.py:872 +#, python-format +msgid "You are not permitted to create %(classname)s." +msgstr "Non si dispone dei permessi sufficienti per creare %(classname)s" + +#: ../roundup/mailgw.py:919 +#, python-format +msgid "" +"\n" +"There were problems handling your subject line argument list:\n" +"- %(errors)s\n" +"\n" +"Subject was: \"%(subject)s\"\n" +msgstr "" +"\n" +"Si ?? verificato un problema nel gestire la lista degli argomenti nel Subject " +"del messaggio:- %(errors)s\n" +"\n" +"Il Subject era: \"%(subject)s\"\n" + +#: ../roundup/mailgw.py:947 +msgid "" +"\n" +"Roundup requires the submission to be plain text. The message parser could\n" +"not find a text/plain part to use.\n" +msgstr "" +"\n" +"Roundup richiede che i valori immessi siano in formato testo. Il parser dei " +"messaggi non ha trovato alcuna parte text/plain da utilizzare.\n" + +#: ../roundup/mailgw.py:969 +msgid "You are not permitted to create files." +msgstr "Non si dispone dei permessi necessari a creare file." + +#: ../roundup/mailgw.py:983 +#, python-format +msgid "You are not permitted to add files to %(classname)s." +msgstr "" +"Non si dispone dei permessi necessari per aggiungere file a %(classname)s" + +#: ../roundup/mailgw.py:1001 +msgid "You are not permitted to create messages." +msgstr "Non si disponde dei permessi necessari per creare messaggi." + +#: ../roundup/mailgw.py:1009 +#, python-format +msgid "" +"\n" +"Mail message was rejected by a detector.\n" +"%(error)s\n" +msgstr "" +"\n" +"La Mail ?? stata rifiutata da un detector.\n" +"%(error)s\n" + +#: ../roundup/mailgw.py:1017 +#, python-format +msgid "You are not permitted to add messages to %(classname)s." +msgstr "Non si dispone dei permessi per aggiungere messaggi a %(classname)s" + +#: ../roundup/mailgw.py:1044 +#, python-format +msgid "You are not permitted to edit property %(prop)s of class %(classname)s." +msgstr "" +"Non si dispone dei permessi necessari per modificare la propriet?? %(prop)s " +"della classe %(classname)s" + +#: ../roundup/mailgw.py:1052 +#, python-format +msgid "" +"\n" +"There was a problem with the message you sent:\n" +" %(message)s\n" +msgstr "" +"\n" +"Si ?? verificato un problema con il messaggio che hai inviato:\n" +" %(message)s\n" + +#: ../roundup/mailgw.py:1074 +msgid "not of form [arg=value,value,...;arg=value,value,...]" +msgstr "Non nel formato [arg=valore,valore,...;arg=valore,valore,...]" + +#: ../roundup/roundupdb.py:146 +msgid "files" +msgstr "file" + +#: ../roundup/roundupdb.py:146 +msgid "messages" +msgstr "messaggi" + +#: ../roundup/roundupdb.py:146 +msgid "nosy" +msgstr "ficcanaso" + +#: ../roundup/roundupdb.py:146 +msgid "superseder" +msgstr "soprassiede" + +#: ../roundup/roundupdb.py:146 +msgid "title" +msgstr "titolo" + +#: ../roundup/roundupdb.py:147 +msgid "assignedto" +msgstr "assegnato a" + +#: ../roundup/roundupdb.py:147 +msgid "priority" +msgstr "priorit??" + +#: ../roundup/roundupdb.py:147 +msgid "status" +msgstr "stato" + +#: ../roundup/roundupdb.py:147 +msgid "topic" +msgstr "argomento" + +#: ../roundup/roundupdb.py:150 +msgid "activity" +msgstr "attivit??" + +#. following properties are common for all hyperdb classes +#. they are listed here to keep things in one place +#: ../roundup/roundupdb.py:150 +msgid "actor" +msgstr "attore" + +#: ../roundup/roundupdb.py:150 +msgid "creation" +msgstr "creazione" + +#: ../roundup/roundupdb.py:150 +msgid "creator" +msgstr "creatore" + +#: ../roundup/roundupdb.py:308 +#, python-format +msgid "New submission from %(authname)s%(authaddr)s:" +msgstr "" +"?? stata aperta una nuova richiesta di assistenza da parte di\n" +"%(authname)s%(authaddr)s.\n" +"Il testo della nuova richiesta ?? il seguente:" + +#: ../roundup/roundupdb.py:311 +#, python-format +msgid "%(authname)s%(authaddr)s added the comment:" +msgstr "" +"?? stato aggiunto un nuovo messaggio da\n" +"%(authname)s%(authaddr)s.\n" +"Il testo del messaggio ?? il seguente:" + +#: ../roundup/roundupdb.py:314 +msgid "System message:" +msgstr "Messaggio dal sistema:" + +#: ../roundup/roundupdb.py:597 +#, python-format +msgid "" +"\n" +"Now:\n" +"%(new)s\n" +"Was:\n" +"%(old)s" +msgstr "" + +#: ../roundup/scripts/roundup_demo.py:32 +#, python-format +msgid "Enter directory path to create demo tracker [%s]: " +msgstr "" + +#: ../roundup/scripts/roundup_gettext.py:22 +#, python-format +msgid "Usage: %(program)s " +msgstr "" + +#: ../roundup/scripts/roundup_gettext.py:37 +#, python-format +msgid "No tracker templates found in directory %s" +msgstr "" + +#: ../roundup/scripts/roundup_mailgw.py:36 +#, python-format +msgid "" +"Usage: %(program)s [-v] [-c class] [[-C class] -S field=value]* [method]\n" +"\n" +"Options:\n" +" -v: print version and exit\n" +" -c: default class of item to create (else the tracker's " +"MAIL_DEFAULT_CLASS)\n" +" -C / -S: see below\n" +"\n" +"The roundup mail gateway may be called in one of four ways:\n" +" . with an instance home as the only argument,\n" +" . with both an instance home and a mail spool file,\n" +" . with both an instance home and a POP/APOP server account, or\n" +" . with both an instance home and a IMAP/IMAPS server account.\n" +"\n" +"It also supports optional -C and -S arguments that allows you to set a\n" +"fields for a class created by the roundup-mailgw. The default class if\n" +"not specified is msg, but the other classes: issue, file, user can\n" +"also be used. The -S or --set options uses the same\n" +"property=value[;property=value] notation accepted by the command line\n" +"roundup command or the commands that can be given on the Subject line\n" +"of an email message.\n" +"\n" +"It can let you set the type of the message on a per email address basis.\n" +"\n" +"PIPE:\n" +" In the first case, the mail gateway reads a single message from the\n" +" standard input and submits the message to the roundup.mailgw module.\n" +"\n" +"UNIX mailbox:\n" +" In the second case, the gateway reads all messages from the mail spool\n" +" file and submits each in turn to the roundup.mailgw module. The file is\n" +" emptied once all messages have been successfully handled. The file is\n" +" specified as:\n" +" mailbox /path/to/mailbox\n" +"\n" +"POP:\n" +" In the third case, the gateway reads all messages from the POP server\n" +" specified and submits each in turn to the roundup.mailgw module. The\n" +" server is specified as:\n" +" pop username:password at server\n" +" The username and password may be omitted:\n" +" pop username at server\n" +" pop server\n" +" are both valid. The username and/or password will be prompted for if\n" +" not supplied on the command-line.\n" +"\n" +"POPS:\n" +" Connect to a POP server over ssl. This requires python 2.4 or later.\n" +" This supports the same notation as POP.\n" +"\n" +"APOP:\n" +" Same as POP, but using Authenticated POP:\n" +" apop username:password at server\n" +"\n" +"IMAP:\n" +" Connect to an IMAP server. This supports the same notation as that of\n" +" POP mail.\n" +" imap username:password at server\n" +" It also allows you to specify a specific mailbox other than INBOX using\n" +" this format:\n" +" imap username:password at server mailbox\n" +"\n" +"IMAPS:\n" +" Connect to an IMAP server over ssl.\n" +" This supports the same notation as IMAP.\n" +" imaps username:password at server [mailbox]\n" +"\n" +msgstr "" + +#: ../roundup/scripts/roundup_mailgw.py:151 +msgid "Error: not enough source specification information" +msgstr "Errore: insufficienti informazioni sul sorgente" + +#: ../roundup/scripts/roundup_mailgw.py:167 +msgid "Error: a later version of python is required" +msgstr "Erorre: ?? richiesta una versione pi?? aggiornata di python" + +#: ../roundup/scripts/roundup_mailgw.py:170 +msgid "Error: pop specification not valid" +msgstr "Errore: il pop server specificato non ?? valido." + +#: ../roundup/scripts/roundup_mailgw.py:177 +msgid "Error: apop specification not valid" +msgstr "Errore: il apop server specificato non ?? valido." + +#: ../roundup/scripts/roundup_mailgw.py:189 +msgid "" +"Error: The source must be either \"mailbox\", \"pop\", \"apop\", \"imap\" or " +"\"imaps\"" +msgstr "" +"Errore: la sorgente deve essere una tra \"mailbox\", \"pop\", \"apop\", " +"\"imap\" o \"imaps\"" + +#: ../roundup/scripts/roundup_server.py:157 +msgid "" +"Roundup trackers index\n" +"

    Roundup trackers index

      \n" +msgstr "" +"indice dei ticket Roundup\n" +"

      indice dei ticket Roundup

        \n" + +#: ../roundup/scripts/roundup_server.py:293 +#, python-format +msgid "Error: %s: %s" +msgstr "Errore: %s: %s" + +#: ../roundup/scripts/roundup_server.py:303 +msgid "WARNING: ignoring \"-g\" argument, not root" +msgstr "ATTENZIONE: ignoro il parametro \"-g\", non sei root" + +#: ../roundup/scripts/roundup_server.py:309 +msgid "Can't change groups - no grp module" +msgstr "Non ?? possibile cambiare gruppo - nessun modulo grp" + +#: ../roundup/scripts/roundup_server.py:318 +#, python-format +msgid "Group %(group)s doesn't exist" +msgstr "Il gruppo %(group)s non esiste" + +#: ../roundup/scripts/roundup_server.py:329 +msgid "Can't run as root!" +msgstr "Non pu?? essere eseguito come root!" + +#: ../roundup/scripts/roundup_server.py:332 +msgid "WARNING: ignoring \"-u\" argument, not root" +msgstr "" + +#: ../roundup/scripts/roundup_server.py:338 +msgid "Can't change users - no pwd module" +msgstr "Non ?? possibile cambiare utente - nessun modulo pwd" + +#: ../roundup/scripts/roundup_server.py:347 +#, python-format +msgid "User %(user)s doesn't exist" +msgstr "L'utente $(user)s non esiste" + +#: ../roundup/scripts/roundup_server.py:481 +#, python-format +msgid "Multiprocess mode \"%s\" is not available, switching to single-process" +msgstr "" +"La modalit?? multiprocesso non ?? disponibile, viene utilizzata quella a " +"singolo processo" + +#: ../roundup/scripts/roundup_server.py:504 +#, python-format +msgid "Unable to bind to port %s, port already in use." +msgstr "Impossibile bindare alla porta %s, la porta risulta gi?? in uso." + +#: ../roundup/scripts/roundup_server.py:572 +msgid "" +" -c Windows Service options.\n" +" If you want to run the server as a Windows Service, you\n" +" must use configuration file to specify tracker homes.\n" +" Logfile option is required to run Roundup Tracker service.\n" +" Typing \"roundup-server -c help\" shows Windows Services\n" +" specifics." +msgstr "" + +#: ../roundup/scripts/roundup_server.py:579 +msgid "" +" -u runs the Roundup web server as this UID\n" +" -g runs the Roundup web server as this GID\n" +" -d run the server in the background and write the server's PID\n" +" to the file indicated by PIDfile. The -l option *must* be\n" +" specified if -d is used." +msgstr "" + +#: ../roundup/scripts/roundup_server.py:586 +#, python-format +msgid "" +"%(message)sUsage: roundup-server [options] [name=tracker home]*\n" +"\n" +"Options:\n" +" -v print the Roundup version number and exit\n" +" -h print this text and exit\n" +" -S create or update configuration file and exit\n" +" -C use configuration file \n" +" -n set the host name of the Roundup web server instance\n" +" -p set the port to listen on (default: %(port)s)\n" +" -l log to the file indicated by fname instead of stderr/stdout\n" +" -N log client machine names instead of IP addresses (much " +"slower)\n" +" -t multiprocess mode (default: %(mp_def)s).\n" +" Allowed values: %(mp_types)s.\n" +"%(os_part)s\n" +"\n" +"Long options:\n" +" --version print the Roundup version number and exit\n" +" --help print this text and exit\n" +" --save-config create or update configuration file and exit\n" +" --config use configuration file \n" +" All settings of the [main] section of the configuration file\n" +" also may be specified in form --=\n" +"\n" +"Examples:\n" +"\n" +" roundup-server -S -C /opt/roundup/etc/roundup-server.ini \\\n" +" -n localhost -p 8917 -l /var/log/roundup.log \\\n" +" support=/var/spool/roundup-trackers/support\n" +"\n" +" roundup-server -C /opt/roundup/etc/roundup-server.ini\n" +"\n" +" roundup-server support=/var/spool/roundup-trackers/support\n" +"\n" +" roundup-server -d /var/run/roundup.pid -l /var/log/roundup.log \\\n" +" support=/var/spool/roundup-trackers/support\n" +"\n" +"Configuration file format:\n" +" Roundup Server configuration file has common .ini file format.\n" +" Configuration file created with 'roundup-server -S' contains\n" +" detailed explanations for each option. Please see that file\n" +" for option descriptions.\n" +"\n" +"How to use \"name=tracker home\":\n" +" These arguments set the tracker home(s) to use. The name is how the\n" +" tracker is identified in the URL (it's the first part of the URL path).\n" +" The tracker home is the directory that was identified when you did\n" +" \"roundup-admin init\". You may specify any number of these name=home\n" +" pairs on the command-line. Make sure the name part doesn't include\n" +" any url-unsafe characters like spaces, as these confuse IE.\n" +msgstr "" + +#: ../roundup/scripts/roundup_server.py:741 +msgid "Instances must be name=home" +msgstr "L'istanza deve essere nel formato nome=home" + +#: ../roundup/scripts/roundup_server.py:755 +#, python-format +msgid "Configuration saved to %s" +msgstr "Configurazione salvata in %s" + +#: ../roundup/scripts/roundup_server.py:773 +msgid "Sorry, you can't run the server as a daemon on this Operating System" +msgstr "" +"Spiacente, non ?? possibile utilizzare il server come demone su questo " +"sistema operativo." + +#: ../roundup/scripts/roundup_server.py:788 +#, python-format +msgid "Roundup server started on %(HOST)s:%(PORT)s" +msgstr "Il server Roundup ?? stato attivato su %(HOST)s:%(PORT)s" + +#: ../templates/classic/html/_generic.collision.html:4 +#: ../templates/minimal/html/_generic.collision.html:4 +msgid "${class} Edit Collision - ${tracker}" +msgstr "Collisione tra modifiche: ${class} - ${tracker}" + +#: ../templates/classic/html/_generic.collision.html:7 +#: ../templates/minimal/html/_generic.collision.html:7 +msgid "${class} Edit Collision" +msgstr "Collisione tra modifiche: ${class}" + +#: ../templates/classic/html/_generic.collision.html:14 +#: ../templates/minimal/html/_generic.collision.html:14 +msgid "" +"\n" +" There has been a collision. Another user updated this node\n" +" while you were editing. Please reload\n" +" the node and review your edits.\n" +msgstr "" +"\n" +" Si ?? verificata una collisione. Un altro utente ha modificato questo nodo\n" +" mentre tu lo stavi modificando. Per favore ricarica il nodo e rivedi le tue modifiche.\n" + +#: ../templates/classic/html/_generic.help-empty.html:6 +msgid "Please specify your search parameters!" +msgstr "Per favore specifica un parametro di ricerca." + +#: ../templates/classic/html/_generic.help-list.html:20 +#: ../templates/classic/html/_generic.index.html:14 +#: ../templates/classic/html/_generic.item.html:12 +#: ../templates/classic/html/file.item.html:9 +#: ../templates/classic/html/issue.index.html:16 +#: ../templates/classic/html/issue.item.html:28 +#: ../templates/classic/html/msg.item.html:26 +#: ../templates/classic/html/user.index.html:9 +#: ../templates/classic/html/user.item.html:35 +#: ../templates/minimal/html/_generic.index.html:14 +#: ../templates/minimal/html/_generic.item.html:12 +#: ../templates/minimal/html/user.index.html:9 +#: ../templates/minimal/html/user.item.html:35 +#: ../templates/minimal/html/user.register.html:14 +msgid "You are not allowed to view this page." +msgstr "Non si dispone dei permessi necessari per visualizzare questa pagina." + +#: ../templates/classic/html/_generic.help-list.html:34 +msgid "1..25 out of 50" +msgstr "1..25 di 50" + +#: ../templates/classic/html/_generic.help-search.html:9 +msgid "" +"Generic template ${template} or version for class ${classname} is not yet " +"implemented" +msgstr "" +"Il template generico ${template} o la versione per la classe ${classname} " +"non sono ancora stati implementati" + +#: ../templates/classic/html/_generic.help-submit.html:57 +#: ../templates/classic/html/_generic.help.html:31 +#: ../templates/minimal/html/_generic.help.html:31 +msgid " Cancel " +msgstr " Annulla " + +#: ../templates/classic/html/_generic.help-submit.html:63 +#: ../templates/classic/html/_generic.help.html:34 +#: ../templates/minimal/html/_generic.help.html:34 +msgid " Apply " +msgstr " Applica " + +#: ../templates/classic/html/_generic.help.html:9 +#: ../templates/classic/html/user.help.html:13 +#: ../templates/minimal/html/_generic.help.html:9 +msgid "${property} help - ${tracker}" +msgstr "aiuto ${property} - ${tracker}" + +#: ../templates/classic/html/_generic.help.html:41 +#: ../templates/classic/html/help.html:21 +#: ../templates/classic/html/issue.index.html:80 +#: ../templates/minimal/html/_generic.help.html:41 +msgid "<< previous" +msgstr "« precedente" + +#: ../templates/classic/html/_generic.help.html:53 +#: ../templates/classic/html/help.html:28 +#: ../templates/classic/html/issue.index.html:88 +#: ../templates/minimal/html/_generic.help.html:53 +msgid "${start}..${end} out of ${total}" +msgstr "${start}..${end} di ${total}" + +#: ../templates/classic/html/_generic.help.html:57 +#: ../templates/classic/html/help.html:32 +#: ../templates/classic/html/issue.index.html:91 +#: ../templates/minimal/html/_generic.help.html:57 +msgid "next >>" +msgstr "successivo »" + +#: ../templates/classic/html/_generic.index.html:6 +#: ../templates/classic/html/_generic.item.html:4 +#: ../templates/minimal/html/_generic.index.html:6 +#: ../templates/minimal/html/_generic.item.html:4 +msgid "${class} editing - ${tracker}" +msgstr "Modifica di ${class} - ${tracker}" + +#: ../templates/classic/html/_generic.index.html:9 +#: ../templates/classic/html/_generic.item.html:7 +#: ../templates/minimal/html/_generic.index.html:9 +#: ../templates/minimal/html/_generic.item.html:7 +msgid "${class} editing" +msgstr "Modifica di ${class}" + +#: ../templates/classic/html/_generic.index.html:19 +#: ../templates/classic/html/_generic.item.html:16 +#: ../templates/classic/html/file.item.html:13 +#: ../templates/classic/html/issue.index.html:20 +#: ../templates/classic/html/issue.item.html:32 +#: ../templates/classic/html/msg.item.html:30 +#: ../templates/classic/html/user.index.html:13 +#: ../templates/classic/html/user.item.html:39 +#: ../templates/minimal/html/_generic.index.html:19 +#: ../templates/minimal/html/_generic.item.html:17 +#: ../templates/minimal/html/user.index.html:13 +#: ../templates/minimal/html/user.register.html:17 +msgid "Please login with your username and password." +msgstr "Inserisci il tuo nome utente e la tua password." + +#: ../templates/classic/html/_generic.index.html:28 +#: ../templates/minimal/html/_generic.index.html:28 +msgid "" +"

        You may edit the contents of the ${classname} class " +"using this form. Commas, newlines and double quotes (\") must be handled " +"delicately. You may include commas and newlines by enclosing the values in " +"double-quotes (\"). Double quotes themselves must be quoted by doubling " +"(\"\").

        Multilink properties have their " +"multiple values colon (\":\") separated (... ,\"one:two:three\", ...)

        " +"

        Remove entries by deleting their line. Add new " +"entries by appending them to the table - put an X in the id column.

        " +msgstr "" + +#: ../templates/classic/html/_generic.index.html:50 +#: ../templates/minimal/html/_generic.index.html:50 +msgid "Edit Items" +msgstr "Modifica L'Oggetto" + +#: ../templates/classic/html/file.index.html:4 +msgid "List of files - ${tracker}" +msgstr "Elenco dei File - ${tracker}" + +#: ../templates/classic/html/file.index.html:5 +msgid "List of files" +msgstr "Elenco dei File" + +#: ../templates/classic/html/file.index.html:10 +msgid "Download" +msgstr "" + +#: ../templates/classic/html/file.index.html:11 +#: ../templates/classic/html/file.item.html:27 +msgid "Content Type" +msgstr "" + +#: ../templates/classic/html/file.index.html:12 +msgid "Uploaded By" +msgstr "Uploadato Da" + +#: ../templates/classic/html/file.index.html:13 +#: ../templates/classic/html/msg.item.html:48 +msgid "Date" +msgstr "Data" + +#: ../templates/classic/html/file.item.html:2 +msgid "File display - ${tracker}" +msgstr "" + +#: ../templates/classic/html/file.item.html:4 +msgid "File display" +msgstr "" + +#: ../templates/classic/html/file.item.html:23 +#: ../templates/classic/html/user.register.html:17 +msgid "Name" +msgstr "Nome" + +#: ../templates/classic/html/file.item.html:45 +msgid "download" +msgstr "" + +#: ../templates/classic/html/home.classlist.html:2 +#: ../templates/minimal/html/home.classlist.html:2 +msgid "List of classes - ${tracker}" +msgstr "Elenco delle Classi - ${tracker}" + +#: ../templates/classic/html/home.classlist.html:4 +#: ../templates/minimal/html/home.classlist.html:4 +msgid "List of classes" +msgstr "Elenco delle Classi" + +#: ../templates/classic/html/issue.index.html:4 +#: ../templates/classic/html/issue.index.html:10 +msgid "List of issues" +msgstr "Elenco dei Ticket" + +#: ../templates/classic/html/issue.index.html:27 +#: ../templates/classic/html/issue.item.html:49 +msgid "Priority" +msgstr "Priorit??" + +#: ../templates/classic/html/issue.index.html:28 +msgid "ID" +msgstr "ID" + +#: ../templates/classic/html/issue.index.html:29 +msgid "Creation" +msgstr "Creazione" + +#: ../templates/classic/html/issue.index.html:30 +msgid "Activity" +msgstr "Attivit??" + +#: ../templates/classic/html/issue.index.html:31 +msgid "Actor" +msgstr "Attore" + +#: ../templates/classic/html/issue.index.html:32 +msgid "Topic" +msgstr "Argomento" + +#: ../templates/classic/html/issue.index.html:33 +#: ../templates/classic/html/issue.item.html:44 +msgid "Title" +msgstr "Titolo" + +#: ../templates/classic/html/issue.index.html:34 +#: ../templates/classic/html/issue.item.html:51 +msgid "Status" +msgstr "Stato" + +#: ../templates/classic/html/issue.index.html:35 +msgid "Creator" +msgstr "Creatore" + +#: ../templates/classic/html/issue.index.html:36 +msgid "Assigned To" +msgstr "Assegnato A" + +#: ../templates/classic/html/issue.index.html:104 +msgid "Download as CSV" +msgstr "Scarica come CSV" + +#: ../templates/classic/html/issue.index.html:114 +msgid "Sort on:" +msgstr "Ordina per:" + +#: ../templates/classic/html/issue.index.html:118 +#: ../templates/classic/html/issue.index.html:139 +msgid "- nothing -" +msgstr "- niente -" + +#: ../templates/classic/html/issue.index.html:126 +#: ../templates/classic/html/issue.index.html:147 +msgid "Descending:" +msgstr "Decrescente:" + +#: ../templates/classic/html/issue.index.html:135 +msgid "Group on:" +msgstr "Raggruppa per:" + +#: ../templates/classic/html/issue.index.html:154 +msgid "Redisplay" +msgstr "Aggiorna" + +#: ../templates/classic/html/issue.item.html:7 +msgid "Issue ${id}: ${title} - ${tracker}" +msgstr "Ticket ${id}: ${title} - ${tracker}" + +#: ../templates/classic/html/issue.item.html:10 +msgid "New Issue - ${tracker}" +msgstr "Nuovo Ticket - ${tracker}" + +#: ../templates/classic/html/issue.item.html:14 +msgid "New Issue" +msgstr "Nuovo Ticket" + +#: ../templates/classic/html/issue.item.html:16 +msgid "New Issue Editing" +msgstr "Modifica Nuovo Ticket" + +#: ../templates/classic/html/issue.item.html:19 +msgid "Issue${id}" +msgstr "Ticket${id}" + +#: ../templates/classic/html/issue.item.html:22 +msgid "Issue${id} Editing" +msgstr "Modifica Ticket${id}" + +#: ../templates/classic/html/issue.item.html:56 +msgid "Superseder" +msgstr "Soprassede" + +#: ../templates/classic/html/issue.item.html:61 +msgid "View:" +msgstr "Visualizza:" + +#: ../templates/classic/html/issue.item.html:67 +msgid "Nosy List" +msgstr "Lista Ficcanaso" + +#: ../templates/classic/html/issue.item.html:76 +msgid "Assigned To" +msgstr "Assegnato a" + +#: ../templates/classic/html/issue.item.html:78 +msgid "Topics" +msgstr "Argomenti" + +#: ../templates/classic/html/issue.item.html:86 +msgid "Change Note" +msgstr "Modifica Nota" + +#: ../templates/classic/html/issue.item.html:94 +msgid "File" +msgstr "File" + +#: ../templates/classic/html/issue.item.html:106 +msgid "Make a copy" +msgstr "Crea una copia" + +#: ../templates/classic/html/issue.item.html:114 +#: ../templates/classic/html/user.item.html:152 +#: ../templates/classic/html/user.register.html:69 +#: ../templates/minimal/html/user.item.html:147 +msgid "" +"
        Note:  highlighted  fields are required.
        " +msgstr "" +"
        Nota: i campi  evidenziati  sono obbligatori.
        " + +#: ../templates/classic/html/issue.item.html:128 +msgid "" +"Created on ${creation} by ${creator}, last changed " +"${activity} by ${actor}." +msgstr "" +"Creato il ${creation} da ${creator}, ultima modifica " +"${activity} di ${actor}." + +#: ../templates/classic/html/issue.item.html:132 +#: ../templates/classic/html/msg.item.html:61 +msgid "Files" +msgstr "" + +#: ../templates/classic/html/issue.item.html:134 +#: ../templates/classic/html/msg.item.html:63 +msgid "File name" +msgstr "Nome del file" + +#: ../templates/classic/html/issue.item.html:135 +#: ../templates/classic/html/msg.item.html:64 +msgid "Uploaded" +msgstr "Uploadato" + +#: ../templates/classic/html/issue.item.html:136 +msgid "Type" +msgstr "Tipo" + +#: ../templates/classic/html/issue.item.html:137 +#: ../templates/classic/html/query.edit.html:30 +msgid "Edit" +msgstr "Modifica" + +#: ../templates/classic/html/issue.item.html:138 +msgid "Remove" +msgstr "Rimuovi" + +#: ../templates/classic/html/issue.item.html:158 +#: ../templates/classic/html/issue.item.html:179 +#: ../templates/classic/html/query.edit.html:50 +msgid "remove" +msgstr "rimuovi" + +#: ../templates/classic/html/issue.item.html:165 +#: ../templates/classic/html/msg.index.html:9 +msgid "Messages" +msgstr "Messaggi" + +#: ../templates/classic/html/issue.item.html:169 +msgid "msg${id} (view)" +msgstr "msg${id} (visualizza)" + +#: ../templates/classic/html/issue.item.html:170 +msgid "Author: ${author}" +msgstr "Autore: ${author}" + +#: ../templates/classic/html/issue.item.html:172 +msgid "Date: ${date}" +msgstr "Data: ${date}" + +#: ../templates/classic/html/issue.search.html:2 +msgid "Issue searching - ${tracker}" +msgstr "Cerca ticket - ${tracker}" + +#: ../templates/classic/html/issue.search.html:4 +msgid "Issue searching" +msgstr "Cerca Ticket" + +#: ../templates/classic/html/issue.search.html:31 +msgid "Filter on" +msgstr "Filtra su" + +#: ../templates/classic/html/issue.search.html:32 +msgid "Display" +msgstr "Visualizza" + +#: ../templates/classic/html/issue.search.html:33 +msgid "Sort on" +msgstr "Ordina per" + +#: ../templates/classic/html/issue.search.html:34 +msgid "Group on" +msgstr "Raggruppa per" + +#: ../templates/classic/html/issue.search.html:38 +msgid "All text*:" +msgstr "Tutti i testi*:" + +#: ../templates/classic/html/issue.search.html:46 +msgid "Title:" +msgstr "Titolo:" + +#: ../templates/classic/html/issue.search.html:56 +msgid "Topic:" +msgstr "Argomento:" + +#: ../templates/classic/html/issue.search.html:64 +msgid "ID:" +msgstr "ID:" + +#: ../templates/classic/html/issue.search.html:72 +msgid "Creation Date:" +msgstr "Data creazione:" + +#: ../templates/classic/html/issue.search.html:83 +msgid "Creator:" +msgstr "Creatore:" + +#: ../templates/classic/html/issue.search.html:85 +msgid "created by me" +msgstr "creato da me" + +#: ../templates/classic/html/issue.search.html:94 +msgid "Activity:" +msgstr "Attivit??" + +#: ../templates/classic/html/issue.search.html:105 +msgid "Actor:" +msgstr "Attore:" + +#: ../templates/classic/html/issue.search.html:107 +msgid "done by me" +msgstr "fatto da me" + +#: ../templates/classic/html/issue.search.html:118 +msgid "Priority:" +msgstr "Priorit??:" + +#: ../templates/classic/html/issue.search.html:120 +#: ../templates/classic/html/issue.search.html:136 +msgid "not selected" +msgstr "non selezionato" + +#: ../templates/classic/html/issue.search.html:131 +msgid "Status:" +msgstr "Stato:" + +#: ../templates/classic/html/issue.search.html:134 +msgid "not resolved" +msgstr "non risolto" + +#: ../templates/classic/html/issue.search.html:149 +msgid "Assigned to:" +msgstr "Assegnato a:" + +#: ../templates/classic/html/issue.search.html:152 +msgid "assigned to me" +msgstr "assegnato a me" + +#: ../templates/classic/html/issue.search.html:154 +msgid "unassigned" +msgstr "non assegnato" + +#: ../templates/classic/html/issue.search.html:164 +msgid "No Sort or group:" +msgstr "" + +#: ../templates/classic/html/issue.search.html:172 +msgid "Pagesize:" +msgstr "Risposte per pagina" + +#: ../templates/classic/html/issue.search.html:178 +msgid "Start With:" +msgstr "Inizia con:" + +#: ../templates/classic/html/issue.search.html:184 +msgid "Sort Descending:" +msgstr "Ordinamento Decrescente:" + +#: ../templates/classic/html/issue.search.html:191 +msgid "Group Descending:" +msgstr "Raggruppamento Decrescente:" + +#: ../templates/classic/html/issue.search.html:198 +msgid "Query name**:" +msgstr "Nome della query**:" + +#: ../templates/classic/html/issue.search.html:210 +#: ../templates/classic/html/page.html:43 +#: ../templates/classic/html/page.html:92 +#: ../templates/classic/html/user.help-search.html:69 +#: ../templates/minimal/html/page.html:43 +#: ../templates/minimal/html/page.html:91 +msgid "Search" +msgstr "Ricerca" + +#: ../templates/classic/html/issue.search.html:215 +msgid "*: The \"all text\" field will look in message bodies and issue titles" +msgstr "" +"*: Il campo \"tutti i testi\" cerca nel corpo del messaggio e nel titolo del " +"ticket" + +#: ../templates/classic/html/issue.search.html:218 +msgid "" +"**: If you supply a name, the query will be saved off and available as a " +"link in the sidebar" +msgstr "" +"**: Se viene fornito un nome, la query verr?? salvata e resa disponibile come " +"link" + +#: ../templates/classic/html/keyword.item.html:3 +msgid "Keyword editing - ${tracker}" +msgstr "Modifica Parole Chiave - ${tracker}" + +#: ../templates/classic/html/keyword.item.html:5 +msgid "Keyword editing" +msgstr "Modifica Parole Chiave" + +#: ../templates/classic/html/keyword.item.html:11 +msgid "Existing Keywords" +msgstr "Parole Chiave Inserite" + +#: ../templates/classic/html/keyword.item.html:20 +msgid "" +"To edit an existing keyword (for spelling or typing errors), click on its " +"entry above." +msgstr "" +"Per modificare una parola chiave esistente (per errori di pronuncia o " +"digitazione), clicca sul link sopra." + +#: ../templates/classic/html/keyword.item.html:27 +msgid "To create a new keyword, enter it below and click \"Submit New Entry\"." +msgstr "" +"Per creane una nuova parola chiave, inseriscila sotto e clicca su " +"\"Inserisci nuovo\"" + +#: ../templates/classic/html/keyword.item.html:37 +msgid "Keyword" +msgstr "Parola chiave" + +#: ../templates/classic/html/msg.index.html:3 +msgid "List of messages - ${tracker}" +msgstr "Elenco Messaggi - ${tracker}" + +#: ../templates/classic/html/msg.index.html:5 +msgid "Message listing" +msgstr "Elenco Messaggi" + +#: ../templates/classic/html/msg.item.html:6 +msgid "Message ${id} - ${tracker}" +msgstr "Messaggio ${id} - ${tracker}" + +#: ../templates/classic/html/msg.item.html:9 +msgid "New Message - ${tracker}" +msgstr "Nuovo Messaggio - ${tracker}" + +#: ../templates/classic/html/msg.item.html:13 +msgid "New Message" +msgstr "Nuovo Messagggio" + +#: ../templates/classic/html/msg.item.html:15 +msgid "New Message Editing" +msgstr "Modifica Nuovo Messaggio" + +#: ../templates/classic/html/msg.item.html:18 +msgid "Message${id}" +msgstr "Messaggio${id}" + +#: ../templates/classic/html/msg.item.html:21 +msgid "Message${id} Editing" +msgstr "Modifica Messaggio${id}" + +#: ../templates/classic/html/msg.item.html:38 +msgid "Author" +msgstr "Autore" + +#: ../templates/classic/html/msg.item.html:43 +msgid "Recipients" +msgstr "Destinatario" + +#: ../templates/classic/html/msg.item.html:54 +msgid "Content" +msgstr "Contenuto" + +#: ../templates/classic/html/page.html:54 +#: ../templates/minimal/html/page.html:53 +msgid "Your Queries (
        edit)" +msgstr "Le tue Query (modifica)" + +#: ../templates/classic/html/page.html:65 +#: ../templates/minimal/html/page.html:64 +msgid "Issues" +msgstr "Ticket" + +#: ../templates/classic/html/page.html:67 +#: ../templates/classic/html/page.html:105 +#: ../templates/minimal/html/page.html:66 +#: ../templates/minimal/html/page.html:104 +msgid "Create New" +msgstr "Crea Nuovo" + +#: ../templates/classic/html/page.html:69 +#: ../templates/minimal/html/page.html:68 +msgid "Show Unassigned" +msgstr "Mostra Non Assegnati" + +#: ../templates/classic/html/page.html:81 +#: ../templates/minimal/html/page.html:80 +msgid "Show All" +msgstr "Mostra Tutti" + +#: ../templates/classic/html/page.html:93 +#: ../templates/minimal/html/page.html:92 +msgid "Show issue:" +msgstr "Mostra ticket:" + +#: ../templates/classic/html/page.html:103 +#: ../templates/minimal/html/page.html:102 +msgid "Keywords" +msgstr "Parole chiave" + +#: ../templates/classic/html/page.html:108 +#: ../templates/minimal/html/page.html:107 +msgid "Edit Existing" +msgstr "Modifica" + +#: ../templates/classic/html/page.html:114 +#: ../templates/minimal/html/page.html:113 +msgid "Administration" +msgstr "Amministrazione" + +#: ../templates/classic/html/page.html:116 +#: ../templates/minimal/html/page.html:115 +msgid "Class List" +msgstr "Elenco Classi" + +#: ../templates/classic/html/page.html:120 +#: ../templates/minimal/html/page.html:119 +msgid "User List" +msgstr "Elenco Utenti" + +#: ../templates/classic/html/page.html:122 +#: ../templates/minimal/html/page.html:121 +msgid "Add User" +msgstr "Aggiungi Utente" + +#: ../templates/classic/html/page.html:129 +#: ../templates/classic/html/page.html:135 +#: ../templates/minimal/html/page.html:128 +#: ../templates/minimal/html/page.html:134 +msgid "Login" +msgstr "Login" + +#: ../templates/classic/html/page.html:134 +#: ../templates/minimal/html/page.html:133 +msgid "Remember me?" +msgstr "Ricorda la mia login" + +#: ../templates/classic/html/page.html:138 +#: ../templates/classic/html/user.register.html:63 +#: ../templates/minimal/html/page.html:137 +#: ../templates/minimal/html/user.register.html:61 +msgid "Register" +msgstr "Registra" + +#: ../templates/classic/html/page.html:141 +#: ../templates/minimal/html/page.html:140 +msgid "Lost your login?" +msgstr "Dimenticato la tua Login?" + +#: ../templates/classic/html/page.html:146 +#: ../templates/minimal/html/page.html:145 +msgid "Hello, ${user}" +msgstr "Ciao, ${user}" + +#: ../templates/classic/html/page.html:148 +msgid "Your Issues" +msgstr "I Tuoi Ticket" + +#: ../templates/classic/html/page.html:160 +#: ../templates/minimal/html/page.html:147 +msgid "Your Details" +msgstr "I Tuoi Dettagli" + +#: ../templates/classic/html/page.html:162 +#: ../templates/minimal/html/page.html:149 +msgid "Logout" +msgstr "" + +#: ../templates/classic/html/page.html:166 +#: ../templates/minimal/html/page.html:153 +msgid "Help" +msgstr "Aiuto" + +#: ../templates/classic/html/page.html:167 +#: ../templates/minimal/html/page.html:154 +msgid "Roundup docs" +msgstr "Documentazione su Roundup" + +#: ../templates/classic/html/page.html:177 +#: ../templates/minimal/html/page.html:164 +msgid "clear this message" +msgstr "non visualizzare questo messaggio" + +#: ../templates/classic/html/page.html:241 +#: ../templates/classic/html/page.html:256 +#: ../templates/classic/html/page.html:270 +#: ../templates/minimal/html/page.html:228 +#: ../templates/minimal/html/page.html:243 +#: ../templates/minimal/html/page.html:257 +msgid "don't care" +msgstr "non importa" + +#: ../templates/classic/html/page.html:243 +#: ../templates/classic/html/page.html:258 +#: ../templates/classic/html/page.html:271 +#: ../templates/minimal/html/page.html:230 +#: ../templates/minimal/html/page.html:245 +#: ../templates/minimal/html/page.html:258 +msgid "------------" +msgstr "------------" + +#: ../templates/classic/html/page.html:299 +#: ../templates/minimal/html/page.html:286 +msgid "no value" +msgstr "nessun valore" + +#: ../templates/classic/html/query.edit.html:4 +msgid "\"Your Queries\" Editing - ${tracker}" +msgstr "Modifica de \"Le tue Query\" - ${tracker}" + +#: ../templates/classic/html/query.edit.html:6 +msgid "\"Your Queries\" Editing" +msgstr "Modifica de \"Le tue Query\"" + +#: ../templates/classic/html/query.edit.html:11 +msgid "You are not allowed to edit queries." +msgstr "Non si dispone dei permessi necessari per modificare delle query." + +#: ../templates/classic/html/query.edit.html:28 +msgid "Query" +msgstr "Query" + +#: ../templates/classic/html/query.edit.html:29 +msgid "Include in \"Your Queries\"" +msgstr "Includi in \"Le tue Query\"" + +#: ../templates/classic/html/query.edit.html:31 +msgid "Private to you?" +msgstr "Personale?" + +#: ../templates/classic/html/query.edit.html:44 +msgid "leave out" +msgstr "lascia fuori" + +#: ../templates/classic/html/query.edit.html:45 +msgid "include" +msgstr "includi" + +#: ../templates/classic/html/query.edit.html:49 +msgid "leave in" +msgstr "lascia dentro" + +#: ../templates/classic/html/query.edit.html:54 +msgid "[query is retired]" +msgstr "[la query ?? stata ritirata]" + +#: ../templates/classic/html/query.edit.html:67 +#: ../templates/classic/html/query.edit.html:92 +msgid "edit" +msgstr "modifica" + +#: ../templates/classic/html/query.edit.html:71 +msgid "yes" +msgstr "s??" + +#: ../templates/classic/html/query.edit.html:73 +msgid "no" +msgstr "no" + +#: ../templates/classic/html/query.edit.html:79 +msgid "Delete" +msgstr "Elimina" + +#: ../templates/classic/html/query.edit.html:94 +msgid "[not yours to edit]" +msgstr "[non sei il proprietario della query" + +#: ../templates/classic/html/query.edit.html:102 +msgid "Save Selection" +msgstr "Salva la selezione" + +#: ../templates/classic/html/user.forgotten.html:3 +msgid "Password reset request - ${tracker}" +msgstr "Richiesta nuova password - %{tracker}" + +#: ../templates/classic/html/user.forgotten.html:5 +msgid "Password reset request" +msgstr "Richiesta nuova password" + +#: ../templates/classic/html/user.forgotten.html:9 +msgid "" +"You have two options if you have forgotten your password. If you know the " +"email address you registered with, enter it below." +msgstr "" + +#: ../templates/classic/html/user.forgotten.html:16 +msgid "Email Address:" +msgstr "Indirizzo di Email:" + +#: ../templates/classic/html/user.forgotten.html:24 +#: ../templates/classic/html/user.forgotten.html:34 +msgid "Request password reset" +msgstr "Richiedi una nuova password" + +#: ../templates/classic/html/user.forgotten.html:30 +msgid "Or, if you know your username, then enter it below." +msgstr "" + +#: ../templates/classic/html/user.forgotten.html:33 +msgid "Username:" +msgstr "Nome Utente:" + +#: ../templates/classic/html/user.forgotten.html:39 +msgid "" +"A confirmation email will be sent to you - please follow the instructions " +"within it to complete the reset process." +msgstr "" + +#: ../templates/classic/html/user.help-search.html:73 +msgid "Pagesize" +msgstr "Dimensione della Pagina" + +#: ../templates/classic/html/user.help.html:43 +msgid "" +"Your browser is not capable of using frames; you should be redirected " +"immediately, or visit ${link}." +msgstr "" +"Il tuo browser non permette di utilizzare i frame; verrai rediretto " +"immediatamente, oppure alternativamente visita ${link}." + +#: ../templates/classic/html/user.index.html:3 +#: ../templates/minimal/html/user.index.html:3 +msgid "User listing - ${tracker}" +msgstr "Elenco Utenti - ${tracker}" + +#: ../templates/classic/html/user.index.html:5 +#: ../templates/minimal/html/user.index.html:5 +msgid "User listing" +msgstr "Elenco Utenti" + +#: ../templates/classic/html/user.index.html:19 +#: ../templates/minimal/html/user.index.html:19 +msgid "Username" +msgstr "Nome Utente" + +#: ../templates/classic/html/user.index.html:20 +msgid "Real name" +msgstr "Nome Completo" + +#: ../templates/classic/html/user.index.html:21 +#: ../templates/classic/html/user.register.html:45 +msgid "Organisation" +msgstr "Organizzazione" + +#: ../templates/classic/html/user.index.html:22 +#: ../templates/minimal/html/user.index.html:20 +msgid "Email address" +msgstr "Indirizzo di Email" + +#: ../templates/classic/html/user.index.html:23 +msgid "Phone number" +msgstr "Telefono" + +#: ../templates/classic/html/user.index.html:24 +msgid "Retire" +msgstr "Dismetti" + +#: ../templates/classic/html/user.index.html:37 +msgid "retire" +msgstr "dismetti" + +#: ../templates/classic/html/user.item.html:9 +#: ../templates/minimal/html/user.item.html:9 +msgid "User ${id}: ${title} - ${tracker}" +msgstr "Utente ${id}: ${title} - ${tracker}" + +#: ../templates/classic/html/user.item.html:12 +#: ../templates/minimal/html/user.item.html:12 +msgid "New User - ${tracker}" +msgstr "Nuovo Utente - ${tracker}" + +#: ../templates/classic/html/user.item.html:21 +#: ../templates/minimal/html/user.item.html:21 +msgid "New User" +msgstr "Nuovo Utente" + +#: ../templates/classic/html/user.item.html:23 +#: ../templates/minimal/html/user.item.html:23 +msgid "New User Editing" +msgstr "Modifica Nuovo Utente" + +#: ../templates/classic/html/user.item.html:26 +#: ../templates/minimal/html/user.item.html:26 +msgid "User${id}" +msgstr "Utente${id}" + +#: ../templates/classic/html/user.item.html:29 +#: ../templates/minimal/html/user.item.html:29 +msgid "User${id} Editing" +msgstr "Modifica Utente${id}" + +#: ../templates/classic/html/user.item.html:79 +#: ../templates/classic/html/user.register.html:33 +#: ../templates/minimal/html/user.item.html:74 +#: ../templates/minimal/html/user.register.html:41 +msgid "Roles" +msgstr "Ruoli" + +#: ../templates/classic/html/user.item.html:87 +#: ../templates/minimal/html/user.item.html:82 +msgid "(to give the user more than one role, enter a comma,separated,list)" +msgstr "" +"(per fornire ad un utente pi?? di un ruolo, inserire l'elenco separato da " +"spazi)" + +#: ../templates/classic/html/user.item.html:108 +#: ../templates/minimal/html/user.item.html:103 +msgid "(this is a numeric hour offset, the default is ${zone})" +msgstr "" +"(questo ?? la differenza in numero di ore, il valore predefinito ?? ${zone})" + +#: ../templates/classic/html/user.item.html:129 +#: ../templates/classic/html/user.register.html:53 +#: ../templates/minimal/html/user.item.html:124 +#: ../templates/minimal/html/user.register.html:53 +msgid "Alternate E-mail addresses
        One address per line" +msgstr "Indirizzi di mail alternativi
        Un indirizzo per linea" + +#: ../templates/classic/html/user.register.html:4 +#: ../templates/classic/html/user.register.html:7 +#: ../templates/minimal/html/user.register.html:4 +#: ../templates/minimal/html/user.register.html:7 +msgid "Registering with ${tracker}" +msgstr "Registrando con ${tracker}" + +#: ../templates/classic/html/user.register.html:21 +#: ../templates/minimal/html/user.register.html:29 +msgid "Login Name" +msgstr "Nome Utente" + +#: ../templates/classic/html/user.register.html:25 +#: ../templates/minimal/html/user.register.html:33 +msgid "Login Password" +msgstr "Password" + +#: ../templates/classic/html/user.register.html:29 +#: ../templates/minimal/html/user.register.html:37 +msgid "Confirm Password" +msgstr "Conferma Password" + +#: ../templates/classic/html/user.register.html:41 +msgid "Phone" +msgstr "Telefono" + +#: ../templates/classic/html/user.register.html:49 +#: ../templates/minimal/html/user.register.html:49 +msgid "E-mail address" +msgstr "Indirizzo di Email" + +#: ../templates/classic/html/user.rego_progress.html:4 +#: ../templates/minimal/html/user.rego_progress.html:4 +msgid "Registration in progress - ${tracker}" +msgstr "Registrazione in atto - ${tracker}" + +#: ../templates/classic/html/user.rego_progress.html:6 +#: ../templates/minimal/html/user.rego_progress.html:6 +msgid "Registration in progress..." +msgstr "Registrazione in atto..." + +#: ../templates/classic/html/user.rego_progress.html:10 +#: ../templates/minimal/html/user.rego_progress.html:10 +msgid "" +"You will shortly receive an email to confirm your registration. To complete " +"the registration process, visit the link indicated in the email." +msgstr "" +"Riceverai a breve una mail di conferma della tua registrazione. Per " +"completare il processo di registrazione, visita il link indicato nella mail." + +#: ../templates/classic/initial_data.py:5 +msgid "critical" +msgstr "critico" + +#: ../templates/classic/initial_data.py:6 +msgid "urgent" +msgstr "urgente" + +#: ../templates/classic/initial_data.py:7 +msgid "bug" +msgstr "bug" + +#: ../templates/classic/initial_data.py:8 +msgid "feature" +msgstr "" + +#: ../templates/classic/initial_data.py:9 +msgid "wish" +msgstr "" + +#: ../templates/classic/initial_data.py:12 +msgid "unread" +msgstr "" + +#: ../templates/classic/initial_data.py:13 +msgid "deferred" +msgstr "" + +#: ../templates/classic/initial_data.py:14 +msgid "chatting" +msgstr "" + +#: ../templates/classic/initial_data.py:15 +msgid "need-eg" +msgstr "" + +#: ../templates/classic/initial_data.py:16 +msgid "in-progress" +msgstr "" + +#: ../templates/classic/initial_data.py:17 +msgid "testing" +msgstr "" + +#: ../templates/classic/initial_data.py:18 +msgid "done-cbb" +msgstr "" + +#: ../templates/classic/initial_data.py:19 +msgid "resolved" +msgstr "" + +#: ../templates/minimal/html/home.html:2 +msgid "Tracker home - ${tracker}" +msgstr "" + +#: ../templates/minimal/html/home.html:4 +msgid "Tracker home" +msgstr "" + +#: ../templates/minimal/html/home.html:16 +msgid "Please select from one of the menu options on the left." +msgstr "Per favore seleziona una delle opzioni dal men?? a sinistra" + +#: ../templates/minimal/html/home.html:19 +msgid "Please log in or register." +msgstr "Per favore esegui la login o la registrazione." Modified: tracker/roundup-src/locale/lt.po ============================================================================== --- tracker/roundup-src/locale/lt.po (original) +++ tracker/roundup-src/locale/lt.po Sun Mar 15 22:43:30 2009 @@ -1,7 +1,7 @@ # Lithuanian message file for Roundup Issue Tracker # Aiste Kesminaite , 2005 # -# $Id: lt.po,v 1.8 2007/01/04 17:14:29 a1s Exp $ +# $Id: lt.po,v 1.8 2007-01-04 17:14:29 a1s Exp $ # # roundup.pot revision 1.20 # Modified: tracker/roundup-src/locale/roundup.pot ============================================================================== --- tracker/roundup-src/locale/roundup.pot (original) +++ tracker/roundup-src/locale/roundup.pot Sun Mar 15 22:43:30 2009 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: roundup-devel at lists.sourceforge.net\n" -"POT-Creation-Date: 2007-09-27 11:18+0300\n" +"POT-Creation-Date: 2009-03-12 11:58+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,25 +17,34 @@ "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: ../roundup/admin.py:86 ../roundup/admin.py:989 ../roundup/admin.py:1040 -#: ../roundup/admin.py:1063 ../roundup/admin.py:86:989 :1040:1063 +#: ../roundup/actions.py:53 ../roundup/cgi/actions.py:120 +msgid "You may not retire the admin or anonymous user" +msgstr "" + +#: ../roundup/actions.py:66 ../roundup/cgi/actions.py:57 +#, python-format +msgid "You do not have permission to %(action)s the %(classname)s class." +msgstr "" + +#: ../roundup/admin.py:83 ../roundup/admin.py:986 ../roundup/admin.py:1037 +#: ../roundup/admin.py:1060 ../roundup/admin.py:83:986 :1037:1060 #, python-format msgid "no such class \"%(classname)s\"" msgstr "" -#: ../roundup/admin.py:96 ../roundup/admin.py:100 ../roundup/admin.py:96:100 +#: ../roundup/admin.py:93 ../roundup/admin.py:97 ../roundup/admin.py:93:97 #, python-format msgid "argument \"%(arg)s\" not propname=value" msgstr "" -#: ../roundup/admin.py:113 +#: ../roundup/admin.py:110 #, python-format msgid "" "Problem: %(message)s\n" "\n" msgstr "" -#: ../roundup/admin.py:114 +#: ../roundup/admin.py:111 #, python-format msgid "" "%(message)sUsage: roundup-admin [options] [ ]\n" @@ -62,17 +71,17 @@ " roundup-admin help all -- all available help\n" msgstr "" -#: ../roundup/admin.py:141 +#: ../roundup/admin.py:138 msgid "Commands:" msgstr "" -#: ../roundup/admin.py:148 +#: ../roundup/admin.py:145 msgid "" "Commands may be abbreviated as long as the abbreviation\n" "matches only one command, e.g. l == li == lis == list." msgstr "" -#: ../roundup/admin.py:178 +#: ../roundup/admin.py:175 msgid "" "\n" "All commands (except help) require a tracker specifier. This is just\n" @@ -137,12 +146,12 @@ "Command help:\n" msgstr "" -#: ../roundup/admin.py:241 +#: ../roundup/admin.py:238 #, python-format msgid "%s:" msgstr "" -#: ../roundup/admin.py:246 +#: ../roundup/admin.py:243 msgid "" "Usage: help topic\n" " Give help about topic.\n" @@ -154,20 +163,20 @@ " " msgstr "" -#: ../roundup/admin.py:269 +#: ../roundup/admin.py:266 #, python-format msgid "Sorry, no help for \"%(topic)s\"" msgstr "" -#: ../roundup/admin.py:346 ../roundup/admin.py:402 ../roundup/admin.py:346:402 +#: ../roundup/admin.py:343 ../roundup/admin.py:399 ../roundup/admin.py:343:399 msgid "Templates:" msgstr "" -#: ../roundup/admin.py:349 ../roundup/admin.py:413 ../roundup/admin.py:349:413 +#: ../roundup/admin.py:346 ../roundup/admin.py:410 ../roundup/admin.py:346:410 msgid "Back ends:" msgstr "" -#: ../roundup/admin.py:352 +#: ../roundup/admin.py:349 msgid "" "Usage: install [template [backend [key=val[,key=val]]]]\n" " Install a new Roundup tracker.\n" @@ -193,22 +202,22 @@ " " msgstr "" -#: ../roundup/admin.py:375 ../roundup/admin.py:472 ../roundup/admin.py:533 -#: ../roundup/admin.py:612 ../roundup/admin.py:663 ../roundup/admin.py:721 -#: ../roundup/admin.py:742 ../roundup/admin.py:770 ../roundup/admin.py:842 -#: ../roundup/admin.py:909 ../roundup/admin.py:980 ../roundup/admin.py:1030 -#: ../roundup/admin.py:1053 ../roundup/admin.py:1084 ../roundup/admin.py:1180 -#: ../roundup/admin.py:1253 ../roundup/admin.py:375:472 :1030:1053 :1084:1180 -#: :1253 :533:612 :663:721 :742:770 :842:909 :980 +#: ../roundup/admin.py:372 ../roundup/admin.py:469 ../roundup/admin.py:530 +#: ../roundup/admin.py:609 ../roundup/admin.py:660 ../roundup/admin.py:718 +#: ../roundup/admin.py:739 ../roundup/admin.py:767 ../roundup/admin.py:839 +#: ../roundup/admin.py:906 ../roundup/admin.py:977 ../roundup/admin.py:1027 +#: ../roundup/admin.py:1050 ../roundup/admin.py:1081 ../roundup/admin.py:1177 +#: ../roundup/admin.py:1250 ../roundup/admin.py:372:469 :1027:1050 :1081:1177 +#: :1250 :530:609 :660:718 :739:767 :839:906 :977 msgid "Not enough arguments supplied" msgstr "" -#: ../roundup/admin.py:381 +#: ../roundup/admin.py:378 #, python-format msgid "Instance home parent directory \"%(parent)s\" does not exist" msgstr "" -#: ../roundup/admin.py:389 +#: ../roundup/admin.py:386 #, python-format msgid "" "WARNING: There appears to be a tracker in \"%(tracker_home)s\"!\n" @@ -216,20 +225,20 @@ "Erase it? Y/N: " msgstr "" -#: ../roundup/admin.py:404 +#: ../roundup/admin.py:401 msgid "Select template [classic]: " msgstr "" -#: ../roundup/admin.py:415 +#: ../roundup/admin.py:412 msgid "Select backend [anydbm]: " msgstr "" -#: ../roundup/admin.py:425 +#: ../roundup/admin.py:422 #, python-format msgid "Error in configuration settings: \"%s\"" msgstr "" -#: ../roundup/admin.py:434 +#: ../roundup/admin.py:431 #, python-format msgid "" "\n" @@ -238,11 +247,11 @@ " %(config_file)s" msgstr "" -#: ../roundup/admin.py:444 +#: ../roundup/admin.py:441 msgid " ... at a minimum, you must set following options:" msgstr "" -#: ../roundup/admin.py:449 +#: ../roundup/admin.py:446 #, python-format msgid "" "\n" @@ -258,7 +267,7 @@ "---------------------------------------------------------------------------\n" msgstr "" -#: ../roundup/admin.py:467 +#: ../roundup/admin.py:464 msgid "" "Usage: genconfig \n" " Generate a new tracker config file (ini style) with default values\n" @@ -267,7 +276,7 @@ msgstr "" #. password -#: ../roundup/admin.py:477 +#: ../roundup/admin.py:474 msgid "" "Usage: initialise [adminpw]\n" " Initialise a new Roundup tracker.\n" @@ -278,30 +287,30 @@ " " msgstr "" -#: ../roundup/admin.py:491 +#: ../roundup/admin.py:488 msgid "Admin Password: " msgstr "" -#: ../roundup/admin.py:492 +#: ../roundup/admin.py:489 msgid " Confirm: " msgstr "" -#: ../roundup/admin.py:496 +#: ../roundup/admin.py:493 msgid "Instance home does not exist" msgstr "" -#: ../roundup/admin.py:500 +#: ../roundup/admin.py:497 msgid "Instance has not been installed" msgstr "" -#: ../roundup/admin.py:505 +#: ../roundup/admin.py:502 msgid "" "WARNING: The database is already initialised!\n" "If you re-initialise it, you will lose all the data!\n" "Erase it? Y/N: " msgstr "" -#: ../roundup/admin.py:526 +#: ../roundup/admin.py:523 msgid "" "Usage: get property designator[,designator]*\n" " Get the given property of one or more designator(s).\n" @@ -311,23 +320,23 @@ " " msgstr "" -#: ../roundup/admin.py:566 ../roundup/admin.py:581 ../roundup/admin.py:566:581 +#: ../roundup/admin.py:563 ../roundup/admin.py:578 ../roundup/admin.py:563:578 #, python-format msgid "property %s is not of type Multilink or Link so -d flag does not apply." msgstr "" -#: ../roundup/admin.py:589 ../roundup/admin.py:991 ../roundup/admin.py:1042 -#: ../roundup/admin.py:1065 ../roundup/admin.py:589:991 :1042:1065 +#: ../roundup/admin.py:586 ../roundup/admin.py:988 ../roundup/admin.py:1039 +#: ../roundup/admin.py:1062 ../roundup/admin.py:586:988 :1039:1062 #, python-format msgid "no such %(classname)s node \"%(nodeid)s\"" msgstr "" -#: ../roundup/admin.py:591 +#: ../roundup/admin.py:588 #, python-format msgid "no such %(classname)s property \"%(propname)s\"" msgstr "" -#: ../roundup/admin.py:600 +#: ../roundup/admin.py:597 msgid "" "Usage: set items property=value property=value ...\n" " Set the given properties of one or more items(s).\n" @@ -342,7 +351,7 @@ " " msgstr "" -#: ../roundup/admin.py:655 +#: ../roundup/admin.py:652 msgid "" "Usage: find classname propname=value ...\n" " Find the nodes of the given class with a given link property value.\n" @@ -353,13 +362,13 @@ " " msgstr "" -#: ../roundup/admin.py:708 ../roundup/admin.py:862 ../roundup/admin.py:874 -#: ../roundup/admin.py:928 ../roundup/admin.py:708:862 :874:928 +#: ../roundup/admin.py:705 ../roundup/admin.py:859 ../roundup/admin.py:871 +#: ../roundup/admin.py:925 ../roundup/admin.py:705:859 :871:925 #, python-format msgid "%(classname)s has no property \"%(propname)s\"" msgstr "" -#: ../roundup/admin.py:715 +#: ../roundup/admin.py:712 msgid "" "Usage: specification classname\n" " Show the properties for a classname.\n" @@ -368,17 +377,17 @@ " " msgstr "" -#: ../roundup/admin.py:730 +#: ../roundup/admin.py:727 #, python-format msgid "%(key)s: %(value)s (key property)" msgstr "" -#: ../roundup/admin.py:732 ../roundup/admin.py:759 ../roundup/admin.py:732:759 +#: ../roundup/admin.py:729 ../roundup/admin.py:756 ../roundup/admin.py:729:756 #, python-format msgid "%(key)s: %(value)s" msgstr "" -#: ../roundup/admin.py:735 +#: ../roundup/admin.py:732 msgid "" "Usage: display designator[,designator]*\n" " Show the property values for the given node(s).\n" @@ -388,7 +397,7 @@ " " msgstr "" -#: ../roundup/admin.py:762 +#: ../roundup/admin.py:759 msgid "" "Usage: create classname property=value ...\n" " Create a new entry of a given class.\n" @@ -400,31 +409,31 @@ " " msgstr "" -#: ../roundup/admin.py:789 +#: ../roundup/admin.py:786 #, python-format msgid "%(propname)s (Password): " msgstr "" -#: ../roundup/admin.py:791 +#: ../roundup/admin.py:788 #, python-format msgid " %(propname)s (Again): " msgstr "" -#: ../roundup/admin.py:793 +#: ../roundup/admin.py:790 msgid "Sorry, try again..." msgstr "" -#: ../roundup/admin.py:797 +#: ../roundup/admin.py:794 #, python-format msgid "%(propname)s (%(proptype)s): " msgstr "" -#: ../roundup/admin.py:815 +#: ../roundup/admin.py:812 #, python-format msgid "you must provide the \"%(propname)s\" property." msgstr "" -#: ../roundup/admin.py:827 +#: ../roundup/admin.py:824 msgid "" "Usage: list classname [property]\n" " List the instances of a class.\n" @@ -440,16 +449,16 @@ " " msgstr "" -#: ../roundup/admin.py:840 +#: ../roundup/admin.py:837 msgid "Too many arguments supplied" msgstr "" -#: ../roundup/admin.py:876 +#: ../roundup/admin.py:873 #, python-format msgid "%(nodeid)4s: %(value)s" msgstr "" -#: ../roundup/admin.py:880 +#: ../roundup/admin.py:877 msgid "" "Usage: table classname [property[,property]*]\n" " List the instances of a class in tabular form.\n" @@ -481,12 +490,12 @@ " " msgstr "" -#: ../roundup/admin.py:924 +#: ../roundup/admin.py:921 #, python-format msgid "\"%(spec)s\" not name:width" msgstr "" -#: ../roundup/admin.py:974 +#: ../roundup/admin.py:971 msgid "" "Usage: history designator\n" " Show the history entries of a designator.\n" @@ -495,7 +504,7 @@ " " msgstr "" -#: ../roundup/admin.py:995 +#: ../roundup/admin.py:992 msgid "" "Usage: commit\n" " Commit changes made to the database during an interactive session.\n" @@ -509,7 +518,7 @@ " " msgstr "" -#: ../roundup/admin.py:1010 +#: ../roundup/admin.py:1007 msgid "" "Usage: rollback\n" " Undo all changes that are pending commit to the database.\n" @@ -521,7 +530,7 @@ " " msgstr "" -#: ../roundup/admin.py:1023 +#: ../roundup/admin.py:1020 msgid "" "Usage: retire designator[,designator]*\n" " Retire the node specified by designator.\n" @@ -531,7 +540,7 @@ " " msgstr "" -#: ../roundup/admin.py:1047 +#: ../roundup/admin.py:1044 msgid "" "Usage: restore designator[,designator]*\n" " Restore the retired node specified by designator.\n" @@ -541,7 +550,7 @@ msgstr "" #. grab the directory to export to -#: ../roundup/admin.py:1070 +#: ../roundup/admin.py:1067 msgid "" "Usage: export [[-]class[,class]] export_dir\n" " Export the database to colon-separated-value files.\n" @@ -557,7 +566,7 @@ " " msgstr "" -#: ../roundup/admin.py:1145 +#: ../roundup/admin.py:1142 msgid "" "Usage: exporttables [[-]class[,class]] export_dir\n" " Export the database to colon-separated-value files, excluding the\n" @@ -574,7 +583,7 @@ " " msgstr "" -#: ../roundup/admin.py:1160 +#: ../roundup/admin.py:1157 msgid "" "Usage: import import_dir\n" " Import a database from the directory containing CSV files,\n" @@ -597,7 +606,7 @@ " " msgstr "" -#: ../roundup/admin.py:1235 +#: ../roundup/admin.py:1232 msgid "" "Usage: pack period | date\n" "\n" @@ -619,11 +628,11 @@ " " msgstr "" -#: ../roundup/admin.py:1263 +#: ../roundup/admin.py:1260 msgid "Invalid format" msgstr "" -#: ../roundup/admin.py:1274 +#: ../roundup/admin.py:1271 msgid "" "Usage: reindex [classname|designator]*\n" " Re-generate a tracker's search indexes.\n" @@ -633,321 +642,354 @@ " " msgstr "" -#: ../roundup/admin.py:1288 +#: ../roundup/admin.py:1285 #, python-format msgid "no such item \"%(designator)s\"" msgstr "" -#: ../roundup/admin.py:1298 +#: ../roundup/admin.py:1295 msgid "" "Usage: security [Role name]\n" " Display the Permissions available to one or all Roles.\n" " " msgstr "" -#: ../roundup/admin.py:1306 +#: ../roundup/admin.py:1303 #, python-format msgid "No such Role \"%(role)s\"" msgstr "" -#: ../roundup/admin.py:1312 +#: ../roundup/admin.py:1309 #, python-format msgid "New Web users get the Roles \"%(role)s\"" msgstr "" -#: ../roundup/admin.py:1314 +#: ../roundup/admin.py:1311 #, python-format msgid "New Web users get the Role \"%(role)s\"" msgstr "" -#: ../roundup/admin.py:1317 +#: ../roundup/admin.py:1314 #, python-format msgid "New Email users get the Roles \"%(role)s\"" msgstr "" -#: ../roundup/admin.py:1319 +#: ../roundup/admin.py:1316 #, python-format msgid "New Email users get the Role \"%(role)s\"" msgstr "" -#: ../roundup/admin.py:1322 +#: ../roundup/admin.py:1319 #, python-format msgid "Role \"%(name)s\":" msgstr "" -#: ../roundup/admin.py:1327 +#: ../roundup/admin.py:1324 #, python-format msgid " %(description)s (%(name)s for \"%(klass)s\": %(properties)s only)" msgstr "" -#: ../roundup/admin.py:1330 +#: ../roundup/admin.py:1327 #, python-format msgid " %(description)s (%(name)s for \"%(klass)s\" only)" msgstr "" -#: ../roundup/admin.py:1333 +#: ../roundup/admin.py:1330 #, python-format msgid " %(description)s (%(name)s)" msgstr "" -#: ../roundup/admin.py:1362 +#: ../roundup/admin.py:1335 +msgid "" +"Usage: migrate\n" +" Update a tracker's database to be compatible with the Roundup\n" +" codebase.\n" +"\n" +" You should run the \"migrate\" command for your tracker once you've\n" +" installed the latest codebase. \n" +"\n" +" Do this before you use the web, command-line or mail interface and\n" +" before any users access the tracker.\n" +"\n" +" This command will respond with either \"Tracker updated\" (if you've\n" +" not previously run it on an RDBMS backend) or \"No migration action\n" +" required\" (if you have run it, or have used another interface to " +"the\n" +" tracker, or possibly because you are using anydbm).\n" +"\n" +" It's safe to run this even if it's not required, so just get into\n" +" the habit.\n" +" " +msgstr "" + +#: ../roundup/admin.py:1354 +msgid "Tracker updated" +msgstr "" + +#: ../roundup/admin.py:1357 +msgid "No migration action required" +msgstr "" + +#: ../roundup/admin.py:1386 #, python-format msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)" msgstr "" -#: ../roundup/admin.py:1368 +#: ../roundup/admin.py:1392 #, python-format msgid "Multiple commands match \"%(command)s\": %(list)s" msgstr "" -#: ../roundup/admin.py:1375 +#: ../roundup/admin.py:1399 msgid "Enter tracker home: " msgstr "" -#: ../roundup/admin.py:1382 ../roundup/admin.py:1388 ../roundup/admin.py:1408 -#: ../roundup/admin.py:1382:1388 :1408 +#: ../roundup/admin.py:1406 ../roundup/admin.py:1412 ../roundup/admin.py:1432 +#: ../roundup/admin.py:1406:1412 :1432 #, python-format msgid "Error: %(message)s" msgstr "" -#: ../roundup/admin.py:1396 +#: ../roundup/admin.py:1420 #, python-format msgid "Error: Couldn't open tracker: %(message)s" msgstr "" -#: ../roundup/admin.py:1421 +#: ../roundup/admin.py:1445 #, python-format msgid "" "Roundup %s ready for input.\n" "Type \"help\" for help." msgstr "" -#: ../roundup/admin.py:1426 +#: ../roundup/admin.py:1450 msgid "Note: command history and editing not available" msgstr "" -#: ../roundup/admin.py:1430 +#: ../roundup/admin.py:1454 msgid "roundup> " msgstr "" -#: ../roundup/admin.py:1432 +#: ../roundup/admin.py:1456 msgid "exit..." msgstr "" -#: ../roundup/admin.py:1442 +#: ../roundup/admin.py:1466 msgid "There are unsaved changes. Commit them (y/N)? " msgstr "" -#: ../roundup/backends/back_anydbm.py:219 +#: ../roundup/backends/back_anydbm.py:218 #: ../roundup/backends/sessions_dbm.py:50 msgid "Couldn't identify database type" msgstr "" -#: ../roundup/backends/back_anydbm.py:245 +#: ../roundup/backends/back_anydbm.py:244 #, python-format msgid "Couldn't open database - the required module '%s' is not available" msgstr "" -#: ../roundup/backends/back_anydbm.py:795 -#: ../roundup/backends/back_anydbm.py:1070 -#: ../roundup/backends/back_anydbm.py:1267 -#: ../roundup/backends/back_anydbm.py:1285 -#: ../roundup/backends/back_anydbm.py:1331 -#: ../roundup/backends/back_anydbm.py:1901 -#: ../roundup/backends/back_anydbm.py:795:1070 -#: ../roundup/backends/back_metakit.py:567 -#: ../roundup/backends/back_metakit.py:834 -#: ../roundup/backends/back_metakit.py:866 -#: ../roundup/backends/back_metakit.py:1601 -#: ../roundup/backends/back_metakit.py:567:834 -#: ../roundup/backends/rdbms_common.py:1320 -#: ../roundup/backends/rdbms_common.py:1549 -#: ../roundup/backends/rdbms_common.py:1755 -#: ../roundup/backends/rdbms_common.py:1775 -#: ../roundup/backends/rdbms_common.py:1828 -#: ../roundup/backends/rdbms_common.py:2436 -#: ../roundup/backends/rdbms_common.py:1320:1549 :1267:1285 :1331:1901 -#: :1755:1775 :1828:2436 :866:1601 +#: ../roundup/backends/back_anydbm.py:799 +#: ../roundup/backends/back_anydbm.py:1074 +#: ../roundup/backends/back_anydbm.py:1271 +#: ../roundup/backends/back_anydbm.py:1289 +#: ../roundup/backends/back_anydbm.py:1335 +#: ../roundup/backends/back_anydbm.py:1905 +#: ../roundup/backends/back_anydbm.py:799:1074 +#: ../roundup/backends/rdbms_common.py:1396 +#: ../roundup/backends/rdbms_common.py:1625 +#: ../roundup/backends/rdbms_common.py:1831 +#: ../roundup/backends/rdbms_common.py:1851 +#: ../roundup/backends/rdbms_common.py:1904 +#: ../roundup/backends/rdbms_common.py:2512 +#: ../roundup/backends/rdbms_common.py:1396:1625 :1271:1289 :1335:1905 +#: :1831:1851 :1904:2512 msgid "Database open read-only" msgstr "" -#: ../roundup/backends/back_anydbm.py:2003 +#: ../roundup/backends/back_anydbm.py:2007 #, python-format msgid "WARNING: invalid date tuple %r" msgstr "" -#: ../roundup/backends/rdbms_common.py:1449 +#: ../roundup/backends/rdbms_common.py:1525 msgid "create" msgstr "" -#: ../roundup/backends/rdbms_common.py:1615 +#: ../roundup/backends/rdbms_common.py:1691 msgid "unlink" msgstr "" -#: ../roundup/backends/rdbms_common.py:1619 +#: ../roundup/backends/rdbms_common.py:1695 msgid "link" msgstr "" -#: ../roundup/backends/rdbms_common.py:1741 +#: ../roundup/backends/rdbms_common.py:1817 msgid "set" msgstr "" -#: ../roundup/backends/rdbms_common.py:1765 +#: ../roundup/backends/rdbms_common.py:1841 msgid "retired" msgstr "" -#: ../roundup/backends/rdbms_common.py:1795 +#: ../roundup/backends/rdbms_common.py:1871 msgid "restored" msgstr "" -#: ../roundup/cgi/actions.py:58 -#, python-format -msgid "You do not have permission to %(action)s the %(classname)s class." -msgstr "" - -#: ../roundup/cgi/actions.py:89 +#: ../roundup/cgi/actions.py:88 msgid "No type specified" msgstr "" -#: ../roundup/cgi/actions.py:91 +#: ../roundup/cgi/actions.py:90 msgid "No ID entered" msgstr "" -#: ../roundup/cgi/actions.py:97 +#: ../roundup/cgi/actions.py:96 #, python-format msgid "\"%(input)s\" is not an ID (%(classname)s ID required)" msgstr "" -#: ../roundup/cgi/actions.py:117 -msgid "You may not retire the admin or anonymous user" +#: ../roundup/cgi/actions.py:108 ../roundup/cgi/actions.py:287 +#: ../roundup/cgi/actions.py:590 ../roundup/cgi/actions.py:636 +#: ../roundup/cgi/actions.py:822 ../roundup/cgi/actions.py:940 +#: ../roundup/cgi/actions.py:108:287 :590:636 :822:940 +msgid "Invalid request" msgstr "" -#: ../roundup/cgi/actions.py:124 +#: ../roundup/cgi/actions.py:126 ../roundup/cgi/actions.py:382 +#: ../roundup/cgi/actions.py:126:382 +#, python-format +msgid "You do not have permission to retire %(class)s" +msgstr "" + +#: ../roundup/cgi/actions.py:134 #, python-format msgid "%(classname)s %(itemid)s has been retired" msgstr "" -#: ../roundup/cgi/actions.py:169 ../roundup/cgi/actions.py:197 -#: ../roundup/cgi/actions.py:169:197 +#: ../roundup/cgi/actions.py:175 ../roundup/cgi/actions.py:203 +#: ../roundup/cgi/actions.py:175:203 msgid "You do not have permission to edit queries" msgstr "" -#: ../roundup/cgi/actions.py:175 ../roundup/cgi/actions.py:204 -#: ../roundup/cgi/actions.py:175:204 +#: ../roundup/cgi/actions.py:181 ../roundup/cgi/actions.py:210 +#: ../roundup/cgi/actions.py:181:210 msgid "You do not have permission to store queries" msgstr "" -#: ../roundup/cgi/actions.py:310 +#: ../roundup/cgi/actions.py:321 ../roundup/cgi/actions.py:507 +#: ../roundup/cgi/actions.py:321:507 #, python-format -msgid "Not enough values on line %(line)s" -msgstr "" - -#: ../roundup/cgi/actions.py:357 -msgid "Items edited OK" +msgid "You do not have permission to create %(class)s" msgstr "" -#: ../roundup/cgi/actions.py:416 +#: ../roundup/cgi/actions.py:329 #, python-format -msgid "%(class)s %(id)s %(properties)s edited ok" +msgid "Not enough values on line %(line)s" msgstr "" -#: ../roundup/cgi/actions.py:419 +#: ../roundup/cgi/actions.py:339 ../roundup/cgi/actions.py:495 +#: ../roundup/cgi/actions.py:339:495 #, python-format -msgid "%(class)s %(id)s - nothing changed" +msgid "You do not have permission to edit %(class)s" msgstr "" -#: ../roundup/cgi/actions.py:431 -#, python-format -msgid "%(class)s %(id)s created" +#: ../roundup/cgi/actions.py:389 +msgid "Items edited OK" msgstr "" -#: ../roundup/cgi/actions.py:463 +#: ../roundup/cgi/actions.py:448 #, python-format -msgid "You do not have permission to edit %(class)s" +msgid "%(class)s %(id)s %(properties)s edited ok" msgstr "" -#: ../roundup/cgi/actions.py:475 +#: ../roundup/cgi/actions.py:451 #, python-format -msgid "You do not have permission to create %(class)s" +msgid "%(class)s %(id)s - nothing changed" msgstr "" -#: ../roundup/cgi/actions.py:499 -msgid "You do not have permission to edit user roles" +#: ../roundup/cgi/actions.py:463 +#, python-format +msgid "%(class)s %(id)s created" msgstr "" -#: ../roundup/cgi/actions.py:549 +#: ../roundup/cgi/actions.py:575 #, python-format msgid "" "Edit Error: someone else has edited this %s (%s). View their changes in a new window." msgstr "" -#: ../roundup/cgi/actions.py:577 +#: ../roundup/cgi/actions.py:607 #, python-format msgid "Edit Error: %s" msgstr "" -#: ../roundup/cgi/actions.py:608 ../roundup/cgi/actions.py:619 -#: ../roundup/cgi/actions.py:790 ../roundup/cgi/actions.py:809 -#: ../roundup/cgi/actions.py:608:619 :790:809 +#: ../roundup/cgi/actions.py:642 ../roundup/cgi/actions.py:658 +#: ../roundup/cgi/actions.py:828 ../roundup/cgi/actions.py:847 +#: ../roundup/cgi/actions.py:642:658 :828:847 #, python-format msgid "Error: %s" msgstr "" -#: ../roundup/cgi/actions.py:645 +#: ../roundup/cgi/actions.py:684 msgid "" "Invalid One Time Key!\n" "(a Mozilla bug may cause this message to show up erroneously, please check " "your email)" msgstr "" -#: ../roundup/cgi/actions.py:687 +#: ../roundup/cgi/actions.py:726 #, python-format msgid "Password reset and email sent to %s" msgstr "" -#: ../roundup/cgi/actions.py:696 +#: ../roundup/cgi/actions.py:735 msgid "Unknown username" msgstr "" -#: ../roundup/cgi/actions.py:704 +#: ../roundup/cgi/actions.py:743 msgid "Unknown email address" msgstr "" -#: ../roundup/cgi/actions.py:709 +#: ../roundup/cgi/actions.py:748 msgid "You need to specify a username or address" msgstr "" -#: ../roundup/cgi/actions.py:734 +#: ../roundup/cgi/actions.py:773 #, python-format msgid "Email sent to %s" msgstr "" -#: ../roundup/cgi/actions.py:753 +#: ../roundup/cgi/actions.py:787 msgid "You are now registered, welcome!" msgstr "" -#: ../roundup/cgi/actions.py:798 +#: ../roundup/cgi/actions.py:836 msgid "It is not permitted to supply roles at registration." msgstr "" -#: ../roundup/cgi/actions.py:890 +#: ../roundup/cgi/actions.py:923 msgid "You are logged out" msgstr "" -#: ../roundup/cgi/actions.py:907 +#: ../roundup/cgi/actions.py:944 msgid "Username required" msgstr "" -#: ../roundup/cgi/actions.py:942 ../roundup/cgi/actions.py:946 -#: ../roundup/cgi/actions.py:942:946 +#: ../roundup/cgi/actions.py:978 ../roundup/cgi/actions.py:982 +#: ../roundup/cgi/actions.py:978:982 msgid "Invalid login" msgstr "" -#: ../roundup/cgi/actions.py:952 +#: ../roundup/cgi/actions.py:988 msgid "You do not have permission to login" msgstr "" +#: ../roundup/cgi/actions.py:1047 +#, python-format +msgid "You do not have permission to view %(class)s" +msgstr "" + #: ../roundup/cgi/cgitb.py:49 #, python-format msgid "" @@ -1018,38 +1060,29 @@ msgid "undefined" msgstr "" -#: ../roundup/cgi/client.py:51 -msgid "" -"An error has occurred\n" -"

        An error has occurred

        \n" -"

        A problem was encountered processing your request.\n" -"The tracker maintainers have been notified of the problem.

        \n" -"" -msgstr "" - -#: ../roundup/cgi/client.py:377 +#: ../roundup/cgi/client.py:517 msgid "Form Error: " msgstr "" -#: ../roundup/cgi/client.py:432 +#: ../roundup/cgi/client.py:575 #, python-format msgid "Unrecognized charset: %r" msgstr "" -#: ../roundup/cgi/client.py:560 +#: ../roundup/cgi/client.py:696 msgid "Anonymous users are not allowed to use the web interface" msgstr "" -#: ../roundup/cgi/client.py:715 +#: ../roundup/cgi/client.py:851 msgid "You are not allowed to view this file." msgstr "" -#: ../roundup/cgi/client.py:808 +#: ../roundup/cgi/client.py:968 #, python-format msgid "%(starttag)sTime elapsed: %(seconds)fs%(endtag)s\n" msgstr "" -#: ../roundup/cgi/client.py:812 +#: ../roundup/cgi/client.py:972 #, python-format msgid "" "%(starttag)sCache hits: %(cache_hits)d, misses %(cache_misses)d. Loading " @@ -1096,14 +1129,14 @@ msgid "property \"%(propname)s\": \"%(value)s\" not currently in list" msgstr "" -#: ../roundup/cgi/form_parser.py:551 +#: ../roundup/cgi/form_parser.py:557 #, python-format msgid "Required %(class)s property %(property)s not supplied" msgid_plural "Required %(class)s properties %(property)s not supplied" msgstr[0] "" msgstr[1] "" -#: ../roundup/cgi/form_parser.py:574 +#: ../roundup/cgi/form_parser.py:580 msgid "File is empty" msgstr "" @@ -1112,344 +1145,348 @@ msgid "You are not allowed to %(action)s items of class %(class)s" msgstr "" -#: ../roundup/cgi/templating.py:657 +#: ../roundup/cgi/templating.py:664 msgid "(list)" msgstr "" -#: ../roundup/cgi/templating.py:726 +#: ../roundup/cgi/templating.py:733 msgid "Submit New Entry" msgstr "" -#: ../roundup/cgi/templating.py:740 ../roundup/cgi/templating.py:873 -#: ../roundup/cgi/templating.py:1294 ../roundup/cgi/templating.py:1323 -#: ../roundup/cgi/templating.py:1343 ../roundup/cgi/templating.py:1356 -#: ../roundup/cgi/templating.py:1407 ../roundup/cgi/templating.py:1430 -#: ../roundup/cgi/templating.py:1466 ../roundup/cgi/templating.py:1503 -#: ../roundup/cgi/templating.py:1556 ../roundup/cgi/templating.py:1573 -#: ../roundup/cgi/templating.py:1657 ../roundup/cgi/templating.py:1677 -#: ../roundup/cgi/templating.py:1695 ../roundup/cgi/templating.py:1727 -#: ../roundup/cgi/templating.py:1737 ../roundup/cgi/templating.py:1789 -#: ../roundup/cgi/templating.py:1978 ../roundup/cgi/templating.py:740:873 -#: :1294:1323 :1343:1356 :1407:1430 :1466:1503 :1556:1573 :1657:1677 :1695:1727 -#: :1737:1789 :1978 +#: ../roundup/cgi/templating.py:747 ../roundup/cgi/templating.py:886 +#: ../roundup/cgi/templating.py:1358 ../roundup/cgi/templating.py:1387 +#: ../roundup/cgi/templating.py:1407 ../roundup/cgi/templating.py:1420 +#: ../roundup/cgi/templating.py:1471 ../roundup/cgi/templating.py:1494 +#: ../roundup/cgi/templating.py:1530 ../roundup/cgi/templating.py:1567 +#: ../roundup/cgi/templating.py:1620 ../roundup/cgi/templating.py:1637 +#: ../roundup/cgi/templating.py:1721 ../roundup/cgi/templating.py:1741 +#: ../roundup/cgi/templating.py:1759 ../roundup/cgi/templating.py:1791 +#: ../roundup/cgi/templating.py:1801 ../roundup/cgi/templating.py:1853 +#: ../roundup/cgi/templating.py:2069 ../roundup/cgi/templating.py:747:886 +#: :1358:1387 :1407:1420 :1471:1494 :1530:1567 :1620:1637 :1721:1741 :1759:1791 +#: :1801:1853 :2069 msgid "[hidden]" msgstr "" -#: ../roundup/cgi/templating.py:741 +#: ../roundup/cgi/templating.py:748 msgid "New node - no history" msgstr "" -#: ../roundup/cgi/templating.py:855 +#: ../roundup/cgi/templating.py:868 msgid "Submit Changes" msgstr "" -#: ../roundup/cgi/templating.py:937 +#: ../roundup/cgi/templating.py:950 msgid "The indicated property no longer exists" msgstr "" -#: ../roundup/cgi/templating.py:938 +#: ../roundup/cgi/templating.py:951 #, python-format msgid "%s: %s\n" msgstr "" -#: ../roundup/cgi/templating.py:951 +#: ../roundup/cgi/templating.py:964 #, python-format msgid "The linked class %(classname)s no longer exists" msgstr "" -#: ../roundup/cgi/templating.py:984 ../roundup/cgi/templating.py:1008 -#: ../roundup/cgi/templating.py:984:1008 +#: ../roundup/cgi/templating.py:998 ../roundup/cgi/templating.py:1023 +#: ../roundup/cgi/templating.py:998:1023 msgid "The linked node no longer exists" msgstr "" -#: ../roundup/cgi/templating.py:1061 +#: ../roundup/cgi/templating.py:1077 #, python-format msgid "%s: (no value)" msgstr "" -#: ../roundup/cgi/templating.py:1073 +#: ../roundup/cgi/templating.py:1089 msgid "" "This event is not handled by the history display!" msgstr "" -#: ../roundup/cgi/templating.py:1085 +#: ../roundup/cgi/templating.py:1101 msgid "Note:" msgstr "" -#: ../roundup/cgi/templating.py:1094 +#: ../roundup/cgi/templating.py:1110 msgid "History" msgstr "" -#: ../roundup/cgi/templating.py:1096 +#: ../roundup/cgi/templating.py:1112 msgid "Date" msgstr "" -#: ../roundup/cgi/templating.py:1097 +#: ../roundup/cgi/templating.py:1113 msgid "User" msgstr "" -#: ../roundup/cgi/templating.py:1098 +#: ../roundup/cgi/templating.py:1114 msgid "Action" msgstr "" -#: ../roundup/cgi/templating.py:1099 +#: ../roundup/cgi/templating.py:1115 msgid "Args" msgstr "" -#: ../roundup/cgi/templating.py:1141 +#: ../roundup/cgi/templating.py:1160 #, python-format msgid "Copy of %(class)s %(id)s" msgstr "" -#: ../roundup/cgi/templating.py:1434 +#: ../roundup/cgi/templating.py:1498 msgid "*encrypted*" msgstr "" -#: ../roundup/cgi/templating.py:1507 ../roundup/cgi/templating.py:1528 -#: ../roundup/cgi/templating.py:1534 ../roundup/cgi/templating.py:1050:1507 -#: :1528:1534 +#: ../roundup/cgi/templating.py:1571 ../roundup/cgi/templating.py:1592 +#: ../roundup/cgi/templating.py:1598 ../roundup/cgi/templating.py:1066:1571 +#: :1592:1598 msgid "No" msgstr "" -#: ../roundup/cgi/templating.py:1507 ../roundup/cgi/templating.py:1526 -#: ../roundup/cgi/templating.py:1531 ../roundup/cgi/templating.py:1050:1507 -#: :1526:1531 +#: ../roundup/cgi/templating.py:1571 ../roundup/cgi/templating.py:1590 +#: ../roundup/cgi/templating.py:1595 ../roundup/cgi/templating.py:1066:1571 +#: :1590:1595 msgid "Yes" msgstr "" -#: ../roundup/cgi/templating.py:1620 +#: ../roundup/cgi/templating.py:1684 msgid "" "default value for DateHTMLProperty must be either DateHTMLProperty or string " "date representation." msgstr "" -#: ../roundup/cgi/templating.py:1780 +#: ../roundup/cgi/templating.py:1844 #, python-format msgid "Attempt to look up %(attr)s on a missing value" msgstr "" -#: ../roundup/cgi/templating.py:1853 +#: ../roundup/cgi/templating.py:1929 #, python-format msgid "" msgstr "" -#: ../roundup/date.py:300 +#: ../roundup/date.py:292 msgid "" "Not a date spec: \"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", \"HH:MM:SS\" or \"yyyy-" "mm-dd.HH:MM:SS.SSS\"" msgstr "" -#: ../roundup/date.py:359 +#: ../roundup/date.py:315 +msgid "Could not determine granularity" +msgstr "" + +#: ../roundup/date.py:365 #, python-format msgid "" "%r not a date / time spec \"yyyy-mm-dd\", \"mm-dd\", \"HH:MM\", \"HH:MM:SS\" " "or \"yyyy-mm-dd.HH:MM:SS.SSS\"" msgstr "" -#: ../roundup/date.py:666 +#: ../roundup/date.py:677 msgid "" "Not an interval spec: [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS] [date spec]" msgstr "" -#: ../roundup/date.py:685 +#: ../roundup/date.py:699 msgid "Not an interval spec: [+-] [#y] [#m] [#w] [#d] [[[H]H:MM]:SS]" msgstr "" -#: ../roundup/date.py:822 +#: ../roundup/date.py:836 #, python-format msgid "%(number)s year" msgid_plural "%(number)s years" msgstr[0] "" msgstr[1] "" -#: ../roundup/date.py:826 +#: ../roundup/date.py:840 #, python-format msgid "%(number)s month" msgid_plural "%(number)s months" msgstr[0] "" msgstr[1] "" -#: ../roundup/date.py:830 +#: ../roundup/date.py:844 #, python-format msgid "%(number)s week" msgid_plural "%(number)s weeks" msgstr[0] "" msgstr[1] "" -#: ../roundup/date.py:834 +#: ../roundup/date.py:848 #, python-format msgid "%(number)s day" msgid_plural "%(number)s days" msgstr[0] "" msgstr[1] "" -#: ../roundup/date.py:838 +#: ../roundup/date.py:852 msgid "tomorrow" msgstr "" -#: ../roundup/date.py:840 +#: ../roundup/date.py:854 msgid "yesterday" msgstr "" -#: ../roundup/date.py:843 +#: ../roundup/date.py:857 #, python-format msgid "%(number)s hour" msgid_plural "%(number)s hours" msgstr[0] "" msgstr[1] "" -#: ../roundup/date.py:847 +#: ../roundup/date.py:861 msgid "an hour" msgstr "" -#: ../roundup/date.py:849 +#: ../roundup/date.py:863 msgid "1 1/2 hours" msgstr "" -#: ../roundup/date.py:851 +#: ../roundup/date.py:865 #, python-format msgid "1 %(number)s/4 hours" msgid_plural "1 %(number)s/4 hours" msgstr[0] "" msgstr[1] "" -#: ../roundup/date.py:855 +#: ../roundup/date.py:869 msgid "in a moment" msgstr "" -#: ../roundup/date.py:857 +#: ../roundup/date.py:871 msgid "just now" msgstr "" -#: ../roundup/date.py:860 +#: ../roundup/date.py:874 msgid "1 minute" msgstr "" -#: ../roundup/date.py:863 +#: ../roundup/date.py:877 #, python-format msgid "%(number)s minute" msgid_plural "%(number)s minutes" msgstr[0] "" msgstr[1] "" -#: ../roundup/date.py:866 +#: ../roundup/date.py:880 msgid "1/2 an hour" msgstr "" -#: ../roundup/date.py:868 +#: ../roundup/date.py:882 #, python-format msgid "%(number)s/4 hour" msgid_plural "%(number)s/4 hours" msgstr[0] "" msgstr[1] "" -#: ../roundup/date.py:872 +#: ../roundup/date.py:886 #, python-format msgid "%s ago" msgstr "" -#: ../roundup/date.py:874 +#: ../roundup/date.py:888 #, python-format msgid "in %s" msgstr "" -#: ../roundup/hyperdb.py:87 +#: ../roundup/hyperdb.py:91 #, python-format msgid "property %s: %s" msgstr "" -#: ../roundup/hyperdb.py:107 +#: ../roundup/hyperdb.py:111 #, python-format msgid "property %s: %r is an invalid date (%s)" msgstr "" -#: ../roundup/hyperdb.py:124 +#: ../roundup/hyperdb.py:128 #, python-format msgid "property %s: %r is an invalid date interval (%s)" msgstr "" -#: ../roundup/hyperdb.py:219 +#: ../roundup/hyperdb.py:223 #, python-format msgid "property %s: %r is not currently an element" msgstr "" -#: ../roundup/hyperdb.py:263 +#: ../roundup/hyperdb.py:267 #, python-format msgid "property %s: %r is not a number" msgstr "" -#: ../roundup/hyperdb.py:276 +#: ../roundup/hyperdb.py:280 #, python-format msgid "\"%s\" not a node designator" msgstr "" -#: ../roundup/hyperdb.py:949 ../roundup/hyperdb.py:957 -#: ../roundup/hyperdb.py:949:957 +#: ../roundup/hyperdb.py:953 ../roundup/hyperdb.py:961 +#: ../roundup/hyperdb.py:953:961 #, python-format msgid "Not a property name: %s" msgstr "" -#: ../roundup/hyperdb.py:1240 +#: ../roundup/hyperdb.py:1244 #, python-format msgid "property %s: %r is not a %s." msgstr "" -#: ../roundup/hyperdb.py:1243 +#: ../roundup/hyperdb.py:1247 #, python-format msgid "you may only enter ID values for property %s" msgstr "" -#: ../roundup/hyperdb.py:1273 +#: ../roundup/hyperdb.py:1277 #, python-format msgid "%r is not a property of %s" msgstr "" -#: ../roundup/init.py:134 +#: ../roundup/init.py:136 #, python-format msgid "" "WARNING: directory '%s'\n" "\tcontains old-style template - ignored" msgstr "" -#: ../roundup/mailgw.py:199 ../roundup/mailgw.py:211 -#: ../roundup/mailgw.py:199:211 +#: ../roundup/mailgw.py:201 ../roundup/mailgw.py:213 +#: ../roundup/mailgw.py:201:213 #, python-format msgid "Message signed with unknown key: %s" msgstr "" -#: ../roundup/mailgw.py:202 +#: ../roundup/mailgw.py:204 #, python-format msgid "Message signed with an expired key: %s" msgstr "" -#: ../roundup/mailgw.py:205 +#: ../roundup/mailgw.py:207 #, python-format msgid "Message signed with a revoked key: %s" msgstr "" -#: ../roundup/mailgw.py:208 +#: ../roundup/mailgw.py:210 msgid "Invalid PGP signature detected." msgstr "" -#: ../roundup/mailgw.py:404 +#: ../roundup/mailgw.py:464 msgid "Unknown multipart/encrypted version." msgstr "" -#: ../roundup/mailgw.py:413 +#: ../roundup/mailgw.py:473 msgid "Unable to decrypt your message." msgstr "" -#: ../roundup/mailgw.py:442 +#: ../roundup/mailgw.py:502 msgid "No PGP signature found in message." msgstr "" -#: ../roundup/mailgw.py:749 +#: ../roundup/mailgw.py:812 msgid "" "\n" "Emails to Roundup trackers must include a Subject: line!\n" msgstr "" -#: ../roundup/mailgw.py:873 +#: ../roundup/mailgw.py:936 #, python-format msgid "" "\n" @@ -1466,7 +1503,7 @@ "Subject was: '%(subject)s'\n" msgstr "" -#: ../roundup/mailgw.py:911 +#: ../roundup/mailgw.py:974 #, python-format msgid "" "\n" @@ -1477,7 +1514,7 @@ "Subject was: \"%(subject)s\"\n" msgstr "" -#: ../roundup/mailgw.py:919 +#: ../roundup/mailgw.py:982 #, python-format msgid "" "\n" @@ -1494,7 +1531,7 @@ "Subject was: '%(subject)s'\n" msgstr "" -#: ../roundup/mailgw.py:960 +#: ../roundup/mailgw.py:1023 #, python-format msgid "" "\n" @@ -1505,7 +1542,7 @@ "Subject was: \"%(subject)s\"\n" msgstr "" -#: ../roundup/mailgw.py:993 +#: ../roundup/mailgw.py:1056 #, python-format msgid "" "\n" @@ -1515,7 +1552,7 @@ "Subject was: \"%(subject)s\"\n" msgstr "" -#: ../roundup/mailgw.py:1021 +#: ../roundup/mailgw.py:1084 #, python-format msgid "" "\n" @@ -1524,7 +1561,7 @@ " %(current_class)s\n" msgstr "" -#: ../roundup/mailgw.py:1044 +#: ../roundup/mailgw.py:1107 #, python-format msgid "" "\n" @@ -1533,7 +1570,7 @@ " %(errors)s\n" msgstr "" -#: ../roundup/mailgw.py:1084 +#: ../roundup/mailgw.py:1147 #, python-format msgid "" "\n" @@ -1542,21 +1579,21 @@ "Unknown address: %(from_address)s\n" msgstr "" -#: ../roundup/mailgw.py:1092 +#: ../roundup/mailgw.py:1155 msgid "You are not permitted to access this tracker." msgstr "" -#: ../roundup/mailgw.py:1099 +#: ../roundup/mailgw.py:1162 #, python-format msgid "You are not permitted to edit %(classname)s." msgstr "" -#: ../roundup/mailgw.py:1103 +#: ../roundup/mailgw.py:1166 #, python-format msgid "You are not permitted to create %(classname)s." msgstr "" -#: ../roundup/mailgw.py:1150 +#: ../roundup/mailgw.py:1213 #, python-format msgid "" "\n" @@ -1566,34 +1603,34 @@ "Subject was: \"%(subject)s\"\n" msgstr "" -#: ../roundup/mailgw.py:1203 +#: ../roundup/mailgw.py:1266 msgid "" "\n" "This tracker has been configured to require all email be PGP signed or\n" "encrypted." msgstr "" -#: ../roundup/mailgw.py:1209 +#: ../roundup/mailgw.py:1273 msgid "" "\n" "Roundup requires the submission to be plain text. The message parser could\n" "not find a text/plain part to use.\n" msgstr "" -#: ../roundup/mailgw.py:1226 +#: ../roundup/mailgw.py:1290 msgid "You are not permitted to create files." msgstr "" -#: ../roundup/mailgw.py:1240 +#: ../roundup/mailgw.py:1304 #, python-format msgid "You are not permitted to add files to %(classname)s." msgstr "" -#: ../roundup/mailgw.py:1258 +#: ../roundup/mailgw.py:1322 msgid "You are not permitted to create messages." msgstr "" -#: ../roundup/mailgw.py:1266 +#: ../roundup/mailgw.py:1330 #, python-format msgid "" "\n" @@ -1601,17 +1638,17 @@ "%(error)s\n" msgstr "" -#: ../roundup/mailgw.py:1274 +#: ../roundup/mailgw.py:1338 #, python-format msgid "You are not permitted to add messages to %(classname)s." msgstr "" -#: ../roundup/mailgw.py:1301 +#: ../roundup/mailgw.py:1365 #, python-format msgid "You are not permitted to edit property %(prop)s of class %(classname)s." msgstr "" -#: ../roundup/mailgw.py:1309 +#: ../roundup/mailgw.py:1374 #, python-format msgid "" "\n" @@ -1619,85 +1656,85 @@ " %(message)s\n" msgstr "" -#: ../roundup/mailgw.py:1331 +#: ../roundup/mailgw.py:1396 msgid "not of form [arg=value,value,...;arg=value,value,...]" msgstr "" -#: ../roundup/roundupdb.py:147 +#: ../roundup/roundupdb.py:174 msgid "files" msgstr "" -#: ../roundup/roundupdb.py:147 +#: ../roundup/roundupdb.py:174 msgid "messages" msgstr "" -#: ../roundup/roundupdb.py:147 +#: ../roundup/roundupdb.py:174 msgid "nosy" msgstr "" -#: ../roundup/roundupdb.py:147 +#: ../roundup/roundupdb.py:174 msgid "superseder" msgstr "" -#: ../roundup/roundupdb.py:147 +#: ../roundup/roundupdb.py:174 msgid "title" msgstr "" -#: ../roundup/roundupdb.py:148 +#: ../roundup/roundupdb.py:175 msgid "assignedto" msgstr "" -#: ../roundup/roundupdb.py:148 +#: ../roundup/roundupdb.py:175 msgid "keyword" msgstr "" -#: ../roundup/roundupdb.py:148 +#: ../roundup/roundupdb.py:175 msgid "priority" msgstr "" -#: ../roundup/roundupdb.py:148 +#: ../roundup/roundupdb.py:175 msgid "status" msgstr "" -#: ../roundup/roundupdb.py:151 +#: ../roundup/roundupdb.py:178 msgid "activity" msgstr "" #. following properties are common for all hyperdb classes #. they are listed here to keep things in one place -#: ../roundup/roundupdb.py:151 +#: ../roundup/roundupdb.py:178 msgid "actor" msgstr "" -#: ../roundup/roundupdb.py:151 +#: ../roundup/roundupdb.py:178 msgid "creation" msgstr "" -#: ../roundup/roundupdb.py:151 +#: ../roundup/roundupdb.py:178 msgid "creator" msgstr "" -#: ../roundup/roundupdb.py:309 +#: ../roundup/roundupdb.py:335 #, python-format msgid "New submission from %(authname)s%(authaddr)s:" msgstr "" -#: ../roundup/roundupdb.py:312 +#: ../roundup/roundupdb.py:338 #, python-format msgid "%(authname)s%(authaddr)s added the comment:" msgstr "" -#: ../roundup/roundupdb.py:315 +#: ../roundup/roundupdb.py:341 #, python-format msgid "Change by %(authname)s%(authaddr)s:" msgstr "" -#: ../roundup/roundupdb.py:342 +#: ../roundup/roundupdb.py:361 #, python-format msgid "File '%(filename)s' not attached - you can download it from %(link)s." msgstr "" -#: ../roundup/roundupdb.py:615 +#: ../roundup/roundupdb.py:661 #, python-format msgid "" "\n" @@ -1760,16 +1797,22 @@ " specified as:\n" " mailbox /path/to/mailbox\n" "\n" +"In all of the following the username and password can be stored in a\n" +"~/.netrc file. In this case only the server name need be specified on\n" +"the command-line.\n" +"\n" +"The username and/or password will be prompted for if not supplied on\n" +"the command-line or in ~/.netrc.\n" +"\n" "POP:\n" " In the third case, the gateway reads all messages from the POP server\n" " specified and submits each in turn to the roundup.mailgw module. The\n" " server is specified as:\n" " pop username:password at server\n" -" The username and password may be omitted:\n" +" Alternatively, one can omit one or both of username and password:\n" " pop username at server\n" " pop server\n" -" are both valid. The username and/or password will be prompted for if\n" -" not supplied on the command-line.\n" +" are both valid.\n" "\n" "POPS:\n" " Connect to a POP server over ssl. This requires python 2.4 or later.\n" @@ -1794,26 +1837,23 @@ "\n" msgstr "" -#: ../roundup/scripts/roundup_mailgw.py:151 +#: ../roundup/scripts/roundup_mailgw.py:157 msgid "Error: not enough source specification information" msgstr "" -#: ../roundup/scripts/roundup_mailgw.py:167 -msgid "Error: a later version of python is required" -msgstr "" - -#: ../roundup/scripts/roundup_mailgw.py:170 -msgid "Error: pop specification not valid" +#: ../roundup/scripts/roundup_mailgw.py:186 +#, python-format +msgid "Error: %s specification not valid" msgstr "" -#: ../roundup/scripts/roundup_mailgw.py:177 -msgid "Error: apop specification not valid" +#: ../roundup/scripts/roundup_mailgw.py:192 +msgid "Error: a later version of python is required" msgstr "" -#: ../roundup/scripts/roundup_mailgw.py:189 +#: ../roundup/scripts/roundup_mailgw.py:203 msgid "" -"Error: The source must be either \"mailbox\", \"pop\", \"apop\", \"imap\" or " -"\"imaps\"" +"Error: The source must be either \"mailbox\", \"pop\", \"pops\", \"apop\", " +"\"imap\" or \"imaps\"" msgstr "" #: ../roundup/scripts/roundup_server.py:76 @@ -1966,18 +2006,18 @@ msgid "Roundup server started on %(HOST)s:%(PORT)s" msgstr "" -#: ../templates/classic/html/_generic.collision.html:4 -#: ../templates/minimal/html/_generic.collision.html:4 +#: ../share/roundup/templates/classic/html/_generic.collision.html:4 +#: ../share/roundup/templates/minimal/html/_generic.collision.html:4 msgid "${class} Edit Collision - ${tracker}" msgstr "" -#: ../templates/classic/html/_generic.collision.html:7 -#: ../templates/minimal/html/_generic.collision.html:7 +#: ../share/roundup/templates/classic/html/_generic.collision.html:7 +#: ../share/roundup/templates/minimal/html/_generic.collision.html:7 msgid "${class} Edit Collision" msgstr "" -#: ../templates/classic/html/_generic.collision.html:14 -#: ../templates/minimal/html/_generic.collision.html:14 +#: ../share/roundup/templates/classic/html/_generic.collision.html:14 +#: ../share/roundup/templates/minimal/html/_generic.collision.html:14 msgid "" "\n" " There has been a collision. Another user updated this node\n" @@ -1985,108 +2025,108 @@ " the node and review your edits.\n" msgstr "" -#: ../templates/classic/html/_generic.help-empty.html:6 +#: ../share/roundup/templates/classic/html/_generic.help-empty.html:6 msgid "Please specify your search parameters!" msgstr "" -#: ../templates/classic/html/_generic.help-list.html:20 -#: ../templates/classic/html/_generic.index.html:14 -#: ../templates/classic/html/_generic.item.html:12 -#: ../templates/classic/html/file.item.html:9 -#: ../templates/classic/html/issue.index.html:16 -#: ../templates/classic/html/issue.item.html:28 -#: ../templates/classic/html/msg.item.html:26 -#: ../templates/classic/html/user.index.html:9 -#: ../templates/classic/html/user.item.html:35 -#: ../templates/minimal/html/_generic.index.html:14 -#: ../templates/minimal/html/_generic.item.html:12 -#: ../templates/minimal/html/user.index.html:9 -#: ../templates/minimal/html/user.item.html:35 -#: ../templates/minimal/html/user.register.html:14 +#: ../share/roundup/templates/classic/html/_generic.help-list.html:20 +#: ../share/roundup/templates/classic/html/_generic.index.html:14 +#: ../share/roundup/templates/classic/html/_generic.item.html:12 +#: ../share/roundup/templates/classic/html/file.item.html:9 +#: ../share/roundup/templates/classic/html/issue.index.html:16 +#: ../share/roundup/templates/classic/html/issue.item.html:28 +#: ../share/roundup/templates/classic/html/msg.item.html:26 +#: ../share/roundup/templates/classic/html/user.index.html:9 +#: ../share/roundup/templates/classic/html/user.item.html:35 +#: ../share/roundup/templates/minimal/html/_generic.index.html:14 +#: ../share/roundup/templates/minimal/html/_generic.item.html:12 +#: ../share/roundup/templates/minimal/html/user.index.html:9 +#: ../share/roundup/templates/minimal/html/user.item.html:35 +#: ../share/roundup/templates/minimal/html/user.register.html:14 msgid "You are not allowed to view this page." msgstr "" -#: ../templates/classic/html/_generic.help-list.html:34 +#: ../share/roundup/templates/classic/html/_generic.help-list.html:34 msgid "1..25 out of 50" msgstr "" -#: ../templates/classic/html/_generic.help-search.html:9 +#: ../share/roundup/templates/classic/html/_generic.help-search.html:9 msgid "" "Generic template ${template} or version for class ${classname} is not yet " "implemented" msgstr "" -#: ../templates/classic/html/_generic.help-submit.html:57 -#: ../templates/classic/html/_generic.help.html:31 -#: ../templates/minimal/html/_generic.help.html:31 +#: ../share/roundup/templates/classic/html/_generic.help-submit.html:57 +#: ../share/roundup/templates/classic/html/_generic.help.html:31 +#: ../share/roundup/templates/minimal/html/_generic.help.html:31 msgid " Cancel " msgstr "" -#: ../templates/classic/html/_generic.help-submit.html:63 -#: ../templates/classic/html/_generic.help.html:34 -#: ../templates/minimal/html/_generic.help.html:34 +#: ../share/roundup/templates/classic/html/_generic.help-submit.html:63 +#: ../share/roundup/templates/classic/html/_generic.help.html:34 +#: ../share/roundup/templates/minimal/html/_generic.help.html:34 msgid " Apply " msgstr "" -#: ../templates/classic/html/_generic.help.html:9 -#: ../templates/classic/html/user.help.html:13 -#: ../templates/minimal/html/_generic.help.html:9 +#: ../share/roundup/templates/classic/html/_generic.help.html:9 +#: ../share/roundup/templates/classic/html/user.help.html:13 +#: ../share/roundup/templates/minimal/html/_generic.help.html:9 msgid "${property} help - ${tracker}" msgstr "" -#: ../templates/classic/html/_generic.help.html:41 -#: ../templates/classic/html/help.html:21 -#: ../templates/classic/html/issue.index.html:81 -#: ../templates/minimal/html/_generic.help.html:41 +#: ../share/roundup/templates/classic/html/_generic.help.html:41 +#: ../share/roundup/templates/classic/html/help.html:21 +#: ../share/roundup/templates/classic/html/issue.index.html:81 +#: ../share/roundup/templates/minimal/html/_generic.help.html:41 msgid "<< previous" msgstr "" -#: ../templates/classic/html/_generic.help.html:53 -#: ../templates/classic/html/help.html:28 -#: ../templates/classic/html/issue.index.html:89 -#: ../templates/minimal/html/_generic.help.html:53 +#: ../share/roundup/templates/classic/html/_generic.help.html:53 +#: ../share/roundup/templates/classic/html/help.html:28 +#: ../share/roundup/templates/classic/html/issue.index.html:89 +#: ../share/roundup/templates/minimal/html/_generic.help.html:53 msgid "${start}..${end} out of ${total}" msgstr "" -#: ../templates/classic/html/_generic.help.html:57 -#: ../templates/classic/html/help.html:32 -#: ../templates/classic/html/issue.index.html:92 -#: ../templates/minimal/html/_generic.help.html:57 +#: ../share/roundup/templates/classic/html/_generic.help.html:57 +#: ../share/roundup/templates/classic/html/help.html:32 +#: ../share/roundup/templates/classic/html/issue.index.html:92 +#: ../share/roundup/templates/minimal/html/_generic.help.html:57 msgid "next >>" msgstr "" -#: ../templates/classic/html/_generic.index.html:6 -#: ../templates/classic/html/_generic.item.html:4 -#: ../templates/minimal/html/_generic.index.html:6 -#: ../templates/minimal/html/_generic.item.html:4 +#: ../share/roundup/templates/classic/html/_generic.index.html:6 +#: ../share/roundup/templates/classic/html/_generic.item.html:4 +#: ../share/roundup/templates/minimal/html/_generic.index.html:6 +#: ../share/roundup/templates/minimal/html/_generic.item.html:4 msgid "${class} editing - ${tracker}" msgstr "" -#: ../templates/classic/html/_generic.index.html:9 -#: ../templates/classic/html/_generic.item.html:7 -#: ../templates/minimal/html/_generic.index.html:9 -#: ../templates/minimal/html/_generic.item.html:7 +#: ../share/roundup/templates/classic/html/_generic.index.html:9 +#: ../share/roundup/templates/classic/html/_generic.item.html:7 +#: ../share/roundup/templates/minimal/html/_generic.index.html:9 +#: ../share/roundup/templates/minimal/html/_generic.item.html:7 msgid "${class} editing" msgstr "" -#: ../templates/classic/html/_generic.index.html:19 -#: ../templates/classic/html/_generic.item.html:16 -#: ../templates/classic/html/file.item.html:13 -#: ../templates/classic/html/issue.index.html:20 -#: ../templates/classic/html/issue.item.html:32 -#: ../templates/classic/html/msg.item.html:30 -#: ../templates/classic/html/user.index.html:13 -#: ../templates/classic/html/user.item.html:39 -#: ../templates/minimal/html/_generic.index.html:19 -#: ../templates/minimal/html/_generic.item.html:17 -#: ../templates/minimal/html/user.index.html:13 -#: ../templates/minimal/html/user.item.html:39 -#: ../templates/minimal/html/user.register.html:17 +#: ../share/roundup/templates/classic/html/_generic.index.html:19 +#: ../share/roundup/templates/classic/html/_generic.item.html:16 +#: ../share/roundup/templates/classic/html/file.item.html:13 +#: ../share/roundup/templates/classic/html/issue.index.html:20 +#: ../share/roundup/templates/classic/html/issue.item.html:32 +#: ../share/roundup/templates/classic/html/msg.item.html:30 +#: ../share/roundup/templates/classic/html/user.index.html:13 +#: ../share/roundup/templates/classic/html/user.item.html:39 +#: ../share/roundup/templates/minimal/html/_generic.index.html:19 +#: ../share/roundup/templates/minimal/html/_generic.item.html:17 +#: ../share/roundup/templates/minimal/html/user.index.html:13 +#: ../share/roundup/templates/minimal/html/user.item.html:39 +#: ../share/roundup/templates/minimal/html/user.register.html:17 msgid "Please login with your username and password." msgstr "" -#: ../templates/classic/html/_generic.index.html:28 -#: ../templates/minimal/html/_generic.index.html:28 +#: ../share/roundup/templates/classic/html/_generic.index.html:28 +#: ../share/roundup/templates/minimal/html/_generic.index.html:28 msgid "" "

        You may edit the contents of the ${classname} class " "using this form. Commas, newlines and double quotes (\") must be handled " @@ -2098,923 +2138,922 @@ "appending them to the table - put an X in the id column.

        " msgstr "" -#: ../templates/classic/html/_generic.index.html:50 -#: ../templates/minimal/html/_generic.index.html:50 +#: ../share/roundup/templates/classic/html/_generic.index.html:50 +#: ../share/roundup/templates/minimal/html/_generic.index.html:50 msgid "Edit Items" msgstr "" -#: ../templates/classic/html/file.index.html:4 +#: ../share/roundup/templates/classic/html/file.index.html:4 msgid "List of files - ${tracker}" msgstr "" -#: ../templates/classic/html/file.index.html:5 +#: ../share/roundup/templates/classic/html/file.index.html:5 msgid "List of files" msgstr "" -#: ../templates/classic/html/file.index.html:10 +#: ../share/roundup/templates/classic/html/file.index.html:10 msgid "Download" msgstr "" -#: ../templates/classic/html/file.index.html:11 -#: ../templates/classic/html/file.item.html:27 +#: ../share/roundup/templates/classic/html/file.index.html:11 +#: ../share/roundup/templates/classic/html/file.item.html:27 msgid "Content Type" msgstr "" -#: ../templates/classic/html/file.index.html:12 +#: ../share/roundup/templates/classic/html/file.index.html:12 msgid "Uploaded By" msgstr "" -#: ../templates/classic/html/file.index.html:13 -#: ../templates/classic/html/msg.item.html:48 +#: ../share/roundup/templates/classic/html/file.index.html:13 +#: ../share/roundup/templates/classic/html/msg.item.html:48 msgid "Date" msgstr "" -#: ../templates/classic/html/file.item.html:2 +#: ../share/roundup/templates/classic/html/file.item.html:2 msgid "File display - ${tracker}" msgstr "" -#: ../templates/classic/html/file.item.html:4 +#: ../share/roundup/templates/classic/html/file.item.html:4 msgid "File display" msgstr "" -#: ../templates/classic/html/file.item.html:23 -#: ../templates/classic/html/user.register.html:17 +#: ../share/roundup/templates/classic/html/file.item.html:23 +#: ../share/roundup/templates/classic/html/user.register.html:17 msgid "Name" msgstr "" -#: ../templates/classic/html/file.item.html:45 +#: ../share/roundup/templates/classic/html/file.item.html:45 msgid "download" msgstr "" -#: ../templates/classic/html/home.classlist.html:2 -#: ../templates/minimal/html/home.classlist.html:2 +#: ../share/roundup/templates/classic/html/home.classlist.html:2 +#: ../share/roundup/templates/minimal/html/home.classlist.html:2 msgid "List of classes - ${tracker}" msgstr "" -#: ../templates/classic/html/home.classlist.html:4 -#: ../templates/minimal/html/home.classlist.html:4 +#: ../share/roundup/templates/classic/html/home.classlist.html:4 +#: ../share/roundup/templates/minimal/html/home.classlist.html:4 msgid "List of classes" msgstr "" -#: ../templates/classic/html/issue.index.html:4 -#: ../templates/classic/html/issue.index.html:10 +#: ../share/roundup/templates/classic/html/issue.index.html:4 +#: ../share/roundup/templates/classic/html/issue.index.html:10 msgid "List of issues" msgstr "" -#: ../templates/classic/html/issue.index.html:27 -#: ../templates/classic/html/issue.item.html:49 +#: ../share/roundup/templates/classic/html/issue.index.html:27 +#: ../share/roundup/templates/classic/html/issue.item.html:49 msgid "Priority" msgstr "" -#: ../templates/classic/html/issue.index.html:28 +#: ../share/roundup/templates/classic/html/issue.index.html:28 msgid "ID" msgstr "" -#: ../templates/classic/html/issue.index.html:29 +#: ../share/roundup/templates/classic/html/issue.index.html:29 msgid "Creation" msgstr "" -#: ../templates/classic/html/issue.index.html:30 +#: ../share/roundup/templates/classic/html/issue.index.html:30 msgid "Activity" msgstr "" -#: ../templates/classic/html/issue.index.html:31 +#: ../share/roundup/templates/classic/html/issue.index.html:31 msgid "Actor" msgstr "" -#: ../templates/classic/html/issue.index.html:32 -#: ../templates/classic/html/keyword.item.html:37 +#: ../share/roundup/templates/classic/html/issue.index.html:32 +#: ../share/roundup/templates/classic/html/keyword.item.html:37 msgid "Keyword" msgstr "" -#: ../templates/classic/html/issue.index.html:33 -#: ../templates/classic/html/issue.item.html:44 +#: ../share/roundup/templates/classic/html/issue.index.html:33 +#: ../share/roundup/templates/classic/html/issue.item.html:44 msgid "Title" msgstr "" -#: ../templates/classic/html/issue.index.html:34 -#: ../templates/classic/html/issue.item.html:51 +#: ../share/roundup/templates/classic/html/issue.index.html:34 +#: ../share/roundup/templates/classic/html/issue.item.html:51 msgid "Status" msgstr "" -#: ../templates/classic/html/issue.index.html:35 +#: ../share/roundup/templates/classic/html/issue.index.html:35 msgid "Creator" msgstr "" -#: ../templates/classic/html/issue.index.html:36 +#: ../share/roundup/templates/classic/html/issue.index.html:36 msgid "Assigned To" msgstr "" -#: ../templates/classic/html/issue.index.html:105 +#: ../share/roundup/templates/classic/html/issue.index.html:105 msgid "Download as CSV" msgstr "" -#: ../templates/classic/html/issue.index.html:115 +#: ../share/roundup/templates/classic/html/issue.index.html:115 msgid "Sort on:" msgstr "" -#: ../templates/classic/html/issue.index.html:119 -#: ../templates/classic/html/issue.index.html:140 +#: ../share/roundup/templates/classic/html/issue.index.html:119 +#: ../share/roundup/templates/classic/html/issue.index.html:140 msgid "- nothing -" msgstr "" -#: ../templates/classic/html/issue.index.html:127 -#: ../templates/classic/html/issue.index.html:148 +#: ../share/roundup/templates/classic/html/issue.index.html:127 +#: ../share/roundup/templates/classic/html/issue.index.html:148 msgid "Descending:" msgstr "" -#: ../templates/classic/html/issue.index.html:136 +#: ../share/roundup/templates/classic/html/issue.index.html:136 msgid "Group on:" msgstr "" -#: ../templates/classic/html/issue.index.html:155 +#: ../share/roundup/templates/classic/html/issue.index.html:155 msgid "Redisplay" msgstr "" -#: ../templates/classic/html/issue.item.html:7 +#: ../share/roundup/templates/classic/html/issue.item.html:7 msgid "Issue ${id}: ${title} - ${tracker}" msgstr "" -#: ../templates/classic/html/issue.item.html:10 +#: ../share/roundup/templates/classic/html/issue.item.html:10 msgid "New Issue - ${tracker}" msgstr "" -#: ../templates/classic/html/issue.item.html:14 +#: ../share/roundup/templates/classic/html/issue.item.html:14 msgid "New Issue" msgstr "" -#: ../templates/classic/html/issue.item.html:16 +#: ../share/roundup/templates/classic/html/issue.item.html:16 msgid "New Issue Editing" msgstr "" -#: ../templates/classic/html/issue.item.html:19 +#: ../share/roundup/templates/classic/html/issue.item.html:19 msgid "Issue${id}" msgstr "" -#: ../templates/classic/html/issue.item.html:22 +#: ../share/roundup/templates/classic/html/issue.item.html:22 msgid "Issue${id} Editing" msgstr "" -#: ../templates/classic/html/issue.item.html:56 +#: ../share/roundup/templates/classic/html/issue.item.html:56 msgid "Superseder" msgstr "" -#: ../templates/classic/html/issue.item.html:61 +#: ../share/roundup/templates/classic/html/issue.item.html:61 msgid "View:" msgstr "" -#: ../templates/classic/html/issue.item.html:67 +#: ../share/roundup/templates/classic/html/issue.item.html:67 msgid "Nosy List" msgstr "" -#: ../templates/classic/html/issue.item.html:76 +#: ../share/roundup/templates/classic/html/issue.item.html:76 msgid "Assigned To" msgstr "" -#: ../templates/classic/html/issue.item.html:78 -#: ../templates/classic/html/page.html:103 -#: ../templates/minimal/html/page.html:102 +#: ../share/roundup/templates/classic/html/issue.item.html:78 +#: ../share/roundup/templates/classic/html/page.html:103 +#: ../share/roundup/templates/minimal/html/page.html:102 msgid "Keywords" msgstr "" -#: ../templates/classic/html/issue.item.html:86 +#: ../share/roundup/templates/classic/html/issue.item.html:86 msgid "Change Note" msgstr "" -#: ../templates/classic/html/issue.item.html:94 +#: ../share/roundup/templates/classic/html/issue.item.html:94 msgid "File" msgstr "" -#: ../templates/classic/html/issue.item.html:106 +#: ../share/roundup/templates/classic/html/issue.item.html:106 msgid "Make a copy" msgstr "" -#: ../templates/classic/html/issue.item.html:114 -#: ../templates/classic/html/user.item.html:153 -#: ../templates/classic/html/user.register.html:69 -#: ../templates/minimal/html/user.item.html:153 +#: ../share/roundup/templates/classic/html/issue.item.html:114 +#: ../share/roundup/templates/classic/html/user.item.html:153 +#: ../share/roundup/templates/classic/html/user.register.html:69 +#: ../share/roundup/templates/minimal/html/user.item.html:153 msgid "" "
        Note:  highlighted  fields are required.
        " msgstr "" -#: ../templates/classic/html/issue.item.html:128 +#: ../share/roundup/templates/classic/html/issue.item.html:128 msgid "" -"Created on ${creation} by ${creator}, last changed " -"${activity} by ${actor}." +"Created on ${creation} by ${creator}, last changed ${activity} by ${actor}." msgstr "" -#: ../templates/classic/html/issue.item.html:132 -#: ../templates/classic/html/msg.item.html:61 +#: ../share/roundup/templates/classic/html/issue.item.html:132 +#: ../share/roundup/templates/classic/html/msg.item.html:61 msgid "Files" msgstr "" -#: ../templates/classic/html/issue.item.html:134 -#: ../templates/classic/html/msg.item.html:63 +#: ../share/roundup/templates/classic/html/issue.item.html:134 +#: ../share/roundup/templates/classic/html/msg.item.html:63 msgid "File name" msgstr "" -#: ../templates/classic/html/issue.item.html:135 -#: ../templates/classic/html/msg.item.html:64 +#: ../share/roundup/templates/classic/html/issue.item.html:135 +#: ../share/roundup/templates/classic/html/msg.item.html:64 msgid "Uploaded" msgstr "" -#: ../templates/classic/html/issue.item.html:136 +#: ../share/roundup/templates/classic/html/issue.item.html:136 msgid "Type" msgstr "" -#: ../templates/classic/html/issue.item.html:137 -#: ../templates/classic/html/query.edit.html:30 +#: ../share/roundup/templates/classic/html/issue.item.html:137 +#: ../share/roundup/templates/classic/html/query.edit.html:30 msgid "Edit" msgstr "" -#: ../templates/classic/html/issue.item.html:138 +#: ../share/roundup/templates/classic/html/issue.item.html:138 msgid "Remove" msgstr "" -#: ../templates/classic/html/issue.item.html:158 -#: ../templates/classic/html/issue.item.html:179 -#: ../templates/classic/html/query.edit.html:50 +#: ../share/roundup/templates/classic/html/issue.item.html:158 +#: ../share/roundup/templates/classic/html/issue.item.html:179 +#: ../share/roundup/templates/classic/html/query.edit.html:50 msgid "remove" msgstr "" -#: ../templates/classic/html/issue.item.html:165 -#: ../templates/classic/html/msg.index.html:9 +#: ../share/roundup/templates/classic/html/issue.item.html:165 +#: ../share/roundup/templates/classic/html/msg.index.html:9 msgid "Messages" msgstr "" -#: ../templates/classic/html/issue.item.html:169 +#: ../share/roundup/templates/classic/html/issue.item.html:169 msgid "msg${id} (view)" msgstr "" -#: ../templates/classic/html/issue.item.html:170 +#: ../share/roundup/templates/classic/html/issue.item.html:170 msgid "Author: ${author}" msgstr "" -#: ../templates/classic/html/issue.item.html:172 +#: ../share/roundup/templates/classic/html/issue.item.html:172 msgid "Date: ${date}" msgstr "" -#: ../templates/classic/html/issue.search.html:2 +#: ../share/roundup/templates/classic/html/issue.search.html:2 msgid "Issue searching - ${tracker}" msgstr "" -#: ../templates/classic/html/issue.search.html:4 +#: ../share/roundup/templates/classic/html/issue.search.html:4 msgid "Issue searching" msgstr "" -#: ../templates/classic/html/issue.search.html:31 +#: ../share/roundup/templates/classic/html/issue.search.html:31 msgid "Filter on" msgstr "" -#: ../templates/classic/html/issue.search.html:32 +#: ../share/roundup/templates/classic/html/issue.search.html:32 msgid "Display" msgstr "" -#: ../templates/classic/html/issue.search.html:33 +#: ../share/roundup/templates/classic/html/issue.search.html:33 msgid "Sort on" msgstr "" -#: ../templates/classic/html/issue.search.html:34 +#: ../share/roundup/templates/classic/html/issue.search.html:34 msgid "Group on" msgstr "" -#: ../templates/classic/html/issue.search.html:38 +#: ../share/roundup/templates/classic/html/issue.search.html:38 msgid "All text*:" msgstr "" -#: ../templates/classic/html/issue.search.html:46 +#: ../share/roundup/templates/classic/html/issue.search.html:46 msgid "Title:" msgstr "" -#: ../templates/classic/html/issue.search.html:56 +#: ../share/roundup/templates/classic/html/issue.search.html:56 msgid "Keyword:" msgstr "" -#: ../templates/classic/html/issue.search.html:58 -#: ../templates/classic/html/issue.search.html:123 -#: ../templates/classic/html/issue.search.html:139 +#: ../share/roundup/templates/classic/html/issue.search.html:58 +#: ../share/roundup/templates/classic/html/issue.search.html:123 +#: ../share/roundup/templates/classic/html/issue.search.html:139 msgid "not selected" msgstr "" -#: ../templates/classic/html/issue.search.html:67 +#: ../share/roundup/templates/classic/html/issue.search.html:67 msgid "ID:" msgstr "" -#: ../templates/classic/html/issue.search.html:75 +#: ../share/roundup/templates/classic/html/issue.search.html:75 msgid "Creation Date:" msgstr "" -#: ../templates/classic/html/issue.search.html:86 +#: ../share/roundup/templates/classic/html/issue.search.html:86 msgid "Creator:" msgstr "" -#: ../templates/classic/html/issue.search.html:88 +#: ../share/roundup/templates/classic/html/issue.search.html:88 msgid "created by me" msgstr "" -#: ../templates/classic/html/issue.search.html:97 +#: ../share/roundup/templates/classic/html/issue.search.html:97 msgid "Activity:" msgstr "" -#: ../templates/classic/html/issue.search.html:108 +#: ../share/roundup/templates/classic/html/issue.search.html:108 msgid "Actor:" msgstr "" -#: ../templates/classic/html/issue.search.html:110 +#: ../share/roundup/templates/classic/html/issue.search.html:110 msgid "done by me" msgstr "" -#: ../templates/classic/html/issue.search.html:121 +#: ../share/roundup/templates/classic/html/issue.search.html:121 msgid "Priority:" msgstr "" -#: ../templates/classic/html/issue.search.html:134 +#: ../share/roundup/templates/classic/html/issue.search.html:134 msgid "Status:" msgstr "" -#: ../templates/classic/html/issue.search.html:137 +#: ../share/roundup/templates/classic/html/issue.search.html:137 msgid "not resolved" msgstr "" -#: ../templates/classic/html/issue.search.html:152 +#: ../share/roundup/templates/classic/html/issue.search.html:152 msgid "Assigned to:" msgstr "" -#: ../templates/classic/html/issue.search.html:155 +#: ../share/roundup/templates/classic/html/issue.search.html:155 msgid "assigned to me" msgstr "" -#: ../templates/classic/html/issue.search.html:157 +#: ../share/roundup/templates/classic/html/issue.search.html:157 msgid "unassigned" msgstr "" -#: ../templates/classic/html/issue.search.html:167 +#: ../share/roundup/templates/classic/html/issue.search.html:167 msgid "No Sort or group:" msgstr "" -#: ../templates/classic/html/issue.search.html:175 +#: ../share/roundup/templates/classic/html/issue.search.html:175 msgid "Pagesize:" msgstr "" -#: ../templates/classic/html/issue.search.html:181 +#: ../share/roundup/templates/classic/html/issue.search.html:181 msgid "Start With:" msgstr "" -#: ../templates/classic/html/issue.search.html:187 +#: ../share/roundup/templates/classic/html/issue.search.html:187 msgid "Sort Descending:" msgstr "" -#: ../templates/classic/html/issue.search.html:194 +#: ../share/roundup/templates/classic/html/issue.search.html:194 msgid "Group Descending:" msgstr "" -#: ../templates/classic/html/issue.search.html:201 +#: ../share/roundup/templates/classic/html/issue.search.html:201 msgid "Query name**:" msgstr "" -#: ../templates/classic/html/issue.search.html:213 -#: ../templates/classic/html/page.html:43 -#: ../templates/classic/html/page.html:92 -#: ../templates/classic/html/user.help-search.html:69 -#: ../templates/minimal/html/page.html:43 -#: ../templates/minimal/html/page.html:91 +#: ../share/roundup/templates/classic/html/issue.search.html:213 +#: ../share/roundup/templates/classic/html/page.html:43 +#: ../share/roundup/templates/classic/html/page.html:92 +#: ../share/roundup/templates/classic/html/user.help-search.html:69 +#: ../share/roundup/templates/minimal/html/page.html:43 +#: ../share/roundup/templates/minimal/html/page.html:91 msgid "Search" msgstr "" -#: ../templates/classic/html/issue.search.html:218 +#: ../share/roundup/templates/classic/html/issue.search.html:218 msgid "*: The \"all text\" field will look in message bodies and issue titles" msgstr "" -#: ../templates/classic/html/issue.search.html:221 +#: ../share/roundup/templates/classic/html/issue.search.html:221 msgid "" "**: If you supply a name, the query will be saved off and available as a link " "in the sidebar" msgstr "" -#: ../templates/classic/html/keyword.item.html:3 +#: ../share/roundup/templates/classic/html/keyword.item.html:3 msgid "Keyword editing - ${tracker}" msgstr "" -#: ../templates/classic/html/keyword.item.html:5 +#: ../share/roundup/templates/classic/html/keyword.item.html:5 msgid "Keyword editing" msgstr "" -#: ../templates/classic/html/keyword.item.html:11 +#: ../share/roundup/templates/classic/html/keyword.item.html:11 msgid "Existing Keywords" msgstr "" -#: ../templates/classic/html/keyword.item.html:20 +#: ../share/roundup/templates/classic/html/keyword.item.html:20 msgid "" "To edit an existing keyword (for spelling or typing errors), click on its " "entry above." msgstr "" -#: ../templates/classic/html/keyword.item.html:27 +#: ../share/roundup/templates/classic/html/keyword.item.html:27 msgid "To create a new keyword, enter it below and click \"Submit New Entry\"." msgstr "" -#: ../templates/classic/html/msg.index.html:3 +#: ../share/roundup/templates/classic/html/msg.index.html:3 msgid "List of messages - ${tracker}" msgstr "" -#: ../templates/classic/html/msg.index.html:5 +#: ../share/roundup/templates/classic/html/msg.index.html:5 msgid "Message listing" msgstr "" -#: ../templates/classic/html/msg.item.html:6 +#: ../share/roundup/templates/classic/html/msg.item.html:6 msgid "Message ${id} - ${tracker}" msgstr "" -#: ../templates/classic/html/msg.item.html:9 +#: ../share/roundup/templates/classic/html/msg.item.html:9 msgid "New Message - ${tracker}" msgstr "" -#: ../templates/classic/html/msg.item.html:13 +#: ../share/roundup/templates/classic/html/msg.item.html:13 msgid "New Message" msgstr "" -#: ../templates/classic/html/msg.item.html:15 +#: ../share/roundup/templates/classic/html/msg.item.html:15 msgid "New Message Editing" msgstr "" -#: ../templates/classic/html/msg.item.html:18 +#: ../share/roundup/templates/classic/html/msg.item.html:18 msgid "Message${id}" msgstr "" -#: ../templates/classic/html/msg.item.html:21 +#: ../share/roundup/templates/classic/html/msg.item.html:21 msgid "Message${id} Editing" msgstr "" -#: ../templates/classic/html/msg.item.html:38 +#: ../share/roundup/templates/classic/html/msg.item.html:38 msgid "Author" msgstr "" -#: ../templates/classic/html/msg.item.html:43 +#: ../share/roundup/templates/classic/html/msg.item.html:43 msgid "Recipients" msgstr "" -#: ../templates/classic/html/msg.item.html:54 +#: ../share/roundup/templates/classic/html/msg.item.html:54 msgid "Content" msgstr "" -#: ../templates/classic/html/page.html:54 -#: ../templates/minimal/html/page.html:53 +#: ../share/roundup/templates/classic/html/page.html:54 +#: ../share/roundup/templates/minimal/html/page.html:53 msgid "Your Queries (edit)" msgstr "" -#: ../templates/classic/html/page.html:65 -#: ../templates/minimal/html/page.html:64 +#: ../share/roundup/templates/classic/html/page.html:65 +#: ../share/roundup/templates/minimal/html/page.html:64 msgid "Issues" msgstr "" -#: ../templates/classic/html/page.html:67 -#: ../templates/classic/html/page.html:105 -#: ../templates/minimal/html/page.html:66 -#: ../templates/minimal/html/page.html:104 +#: ../share/roundup/templates/classic/html/page.html:67 +#: ../share/roundup/templates/classic/html/page.html:105 +#: ../share/roundup/templates/minimal/html/page.html:66 +#: ../share/roundup/templates/minimal/html/page.html:104 msgid "Create New" msgstr "" -#: ../templates/classic/html/page.html:69 -#: ../templates/minimal/html/page.html:68 +#: ../share/roundup/templates/classic/html/page.html:69 +#: ../share/roundup/templates/minimal/html/page.html:68 msgid "Show Unassigned" msgstr "" -#: ../templates/classic/html/page.html:81 -#: ../templates/minimal/html/page.html:80 +#: ../share/roundup/templates/classic/html/page.html:81 +#: ../share/roundup/templates/minimal/html/page.html:80 msgid "Show All" msgstr "" -#: ../templates/classic/html/page.html:93 -#: ../templates/minimal/html/page.html:92 +#: ../share/roundup/templates/classic/html/page.html:93 +#: ../share/roundup/templates/minimal/html/page.html:92 msgid "Show issue:" msgstr "" -#: ../templates/classic/html/page.html:108 -#: ../templates/minimal/html/page.html:107 +#: ../share/roundup/templates/classic/html/page.html:108 +#: ../share/roundup/templates/minimal/html/page.html:107 msgid "Edit Existing" msgstr "" -#: ../templates/classic/html/page.html:114 -#: ../templates/minimal/html/page.html:113 +#: ../share/roundup/templates/classic/html/page.html:114 +#: ../share/roundup/templates/minimal/html/page.html:113 msgid "Administration" msgstr "" -#: ../templates/classic/html/page.html:116 -#: ../templates/minimal/html/page.html:115 +#: ../share/roundup/templates/classic/html/page.html:116 +#: ../share/roundup/templates/minimal/html/page.html:115 msgid "Class List" msgstr "" -#: ../templates/classic/html/page.html:120 -#: ../templates/minimal/html/page.html:119 +#: ../share/roundup/templates/classic/html/page.html:120 +#: ../share/roundup/templates/minimal/html/page.html:119 msgid "User List" msgstr "" -#: ../templates/classic/html/page.html:122 -#: ../templates/minimal/html/page.html:121 +#: ../share/roundup/templates/classic/html/page.html:122 +#: ../share/roundup/templates/minimal/html/page.html:121 msgid "Add User" msgstr "" -#: ../templates/classic/html/page.html:129 -#: ../templates/classic/html/page.html:135 -#: ../templates/minimal/html/page.html:128 -#: ../templates/minimal/html/page.html:134 +#: ../share/roundup/templates/classic/html/page.html:129 +#: ../share/roundup/templates/classic/html/page.html:135 +#: ../share/roundup/templates/minimal/html/page.html:128 +#: ../share/roundup/templates/minimal/html/page.html:134 msgid "Login" msgstr "" -#: ../templates/classic/html/page.html:134 -#: ../templates/minimal/html/page.html:133 +#: ../share/roundup/templates/classic/html/page.html:134 +#: ../share/roundup/templates/minimal/html/page.html:133 msgid "Remember me?" msgstr "" -#: ../templates/classic/html/page.html:138 -#: ../templates/classic/html/user.register.html:63 -#: ../templates/minimal/html/page.html:137 -#: ../templates/minimal/html/user.register.html:61 +#: ../share/roundup/templates/classic/html/page.html:138 +#: ../share/roundup/templates/classic/html/user.register.html:63 +#: ../share/roundup/templates/minimal/html/page.html:137 +#: ../share/roundup/templates/minimal/html/user.register.html:61 msgid "Register" msgstr "" -#: ../templates/classic/html/page.html:141 -#: ../templates/minimal/html/page.html:140 +#: ../share/roundup/templates/classic/html/page.html:141 +#: ../share/roundup/templates/minimal/html/page.html:140 msgid "Lost your login?" msgstr "" -#: ../templates/classic/html/page.html:146 -#: ../templates/minimal/html/page.html:145 +#: ../share/roundup/templates/classic/html/page.html:146 +#: ../share/roundup/templates/minimal/html/page.html:145 msgid "Hello, ${user}" msgstr "" -#: ../templates/classic/html/page.html:148 +#: ../share/roundup/templates/classic/html/page.html:148 msgid "Your Issues" msgstr "" -#: ../templates/classic/html/page.html:160 -#: ../templates/minimal/html/page.html:147 +#: ../share/roundup/templates/classic/html/page.html:160 +#: ../share/roundup/templates/minimal/html/page.html:147 msgid "Your Details" msgstr "" -#: ../templates/classic/html/page.html:162 -#: ../templates/minimal/html/page.html:149 +#: ../share/roundup/templates/classic/html/page.html:162 +#: ../share/roundup/templates/minimal/html/page.html:149 msgid "Logout" msgstr "" -#: ../templates/classic/html/page.html:166 -#: ../templates/minimal/html/page.html:153 +#: ../share/roundup/templates/classic/html/page.html:166 +#: ../share/roundup/templates/minimal/html/page.html:153 msgid "Help" msgstr "" -#: ../templates/classic/html/page.html:167 -#: ../templates/minimal/html/page.html:154 +#: ../share/roundup/templates/classic/html/page.html:167 +#: ../share/roundup/templates/minimal/html/page.html:154 msgid "Roundup docs" msgstr "" -#: ../templates/classic/html/page.html:177 -#: ../templates/minimal/html/page.html:164 +#: ../share/roundup/templates/classic/html/page.html:177 +#: ../share/roundup/templates/minimal/html/page.html:164 msgid "clear this message" msgstr "" -#: ../templates/classic/html/page.html:241 -#: ../templates/classic/html/page.html:256 -#: ../templates/classic/html/page.html:270 -#: ../templates/minimal/html/page.html:228 -#: ../templates/minimal/html/page.html:243 -#: ../templates/minimal/html/page.html:257 +#: ../share/roundup/templates/classic/html/page.html:241 +#: ../share/roundup/templates/classic/html/page.html:256 +#: ../share/roundup/templates/classic/html/page.html:270 +#: ../share/roundup/templates/minimal/html/page.html:228 +#: ../share/roundup/templates/minimal/html/page.html:243 +#: ../share/roundup/templates/minimal/html/page.html:257 msgid "don't care" msgstr "" -#: ../templates/classic/html/page.html:243 -#: ../templates/classic/html/page.html:258 -#: ../templates/classic/html/page.html:271 -#: ../templates/minimal/html/page.html:230 -#: ../templates/minimal/html/page.html:245 -#: ../templates/minimal/html/page.html:258 +#: ../share/roundup/templates/classic/html/page.html:243 +#: ../share/roundup/templates/classic/html/page.html:258 +#: ../share/roundup/templates/classic/html/page.html:271 +#: ../share/roundup/templates/minimal/html/page.html:230 +#: ../share/roundup/templates/minimal/html/page.html:245 +#: ../share/roundup/templates/minimal/html/page.html:258 msgid "------------" msgstr "" -#: ../templates/classic/html/page.html:299 -#: ../templates/minimal/html/page.html:286 +#: ../share/roundup/templates/classic/html/page.html:299 +#: ../share/roundup/templates/minimal/html/page.html:286 msgid "no value" msgstr "" -#: ../templates/classic/html/query.edit.html:4 +#: ../share/roundup/templates/classic/html/query.edit.html:4 msgid "\"Your Queries\" Editing - ${tracker}" msgstr "" -#: ../templates/classic/html/query.edit.html:6 +#: ../share/roundup/templates/classic/html/query.edit.html:6 msgid "\"Your Queries\" Editing" msgstr "" -#: ../templates/classic/html/query.edit.html:11 +#: ../share/roundup/templates/classic/html/query.edit.html:11 msgid "You are not allowed to edit queries." msgstr "" -#: ../templates/classic/html/query.edit.html:28 +#: ../share/roundup/templates/classic/html/query.edit.html:28 msgid "Query" msgstr "" -#: ../templates/classic/html/query.edit.html:29 +#: ../share/roundup/templates/classic/html/query.edit.html:29 msgid "Include in \"Your Queries\"" msgstr "" -#: ../templates/classic/html/query.edit.html:31 +#: ../share/roundup/templates/classic/html/query.edit.html:31 msgid "Private to you?" msgstr "" -#: ../templates/classic/html/query.edit.html:44 +#: ../share/roundup/templates/classic/html/query.edit.html:44 msgid "leave out" msgstr "" -#: ../templates/classic/html/query.edit.html:45 +#: ../share/roundup/templates/classic/html/query.edit.html:45 msgid "include" msgstr "" -#: ../templates/classic/html/query.edit.html:49 +#: ../share/roundup/templates/classic/html/query.edit.html:49 msgid "leave in" msgstr "" -#: ../templates/classic/html/query.edit.html:54 +#: ../share/roundup/templates/classic/html/query.edit.html:54 msgid "[query is retired]" msgstr "" -#: ../templates/classic/html/query.edit.html:67 -#: ../templates/classic/html/query.edit.html:94 +#: ../share/roundup/templates/classic/html/query.edit.html:67 +#: ../share/roundup/templates/classic/html/query.edit.html:94 msgid "edit" msgstr "" -#: ../templates/classic/html/query.edit.html:71 +#: ../share/roundup/templates/classic/html/query.edit.html:71 msgid "yes" msgstr "" -#: ../templates/classic/html/query.edit.html:73 +#: ../share/roundup/templates/classic/html/query.edit.html:73 msgid "no" msgstr "" -#: ../templates/classic/html/query.edit.html:79 +#: ../share/roundup/templates/classic/html/query.edit.html:79 msgid "Delete" msgstr "" -#: ../templates/classic/html/query.edit.html:96 +#: ../share/roundup/templates/classic/html/query.edit.html:96 msgid "[not yours to edit]" msgstr "" -#: ../templates/classic/html/query.edit.html:104 +#: ../share/roundup/templates/classic/html/query.edit.html:104 msgid "Save Selection" msgstr "" -#: ../templates/classic/html/user.forgotten.html:3 +#: ../share/roundup/templates/classic/html/user.forgotten.html:3 msgid "Password reset request - ${tracker}" msgstr "" -#: ../templates/classic/html/user.forgotten.html:5 +#: ../share/roundup/templates/classic/html/user.forgotten.html:5 msgid "Password reset request" msgstr "" -#: ../templates/classic/html/user.forgotten.html:9 +#: ../share/roundup/templates/classic/html/user.forgotten.html:9 msgid "" "You have two options if you have forgotten your password. If you know the " "email address you registered with, enter it below." msgstr "" -#: ../templates/classic/html/user.forgotten.html:16 +#: ../share/roundup/templates/classic/html/user.forgotten.html:16 msgid "Email Address:" msgstr "" -#: ../templates/classic/html/user.forgotten.html:24 -#: ../templates/classic/html/user.forgotten.html:34 +#: ../share/roundup/templates/classic/html/user.forgotten.html:24 +#: ../share/roundup/templates/classic/html/user.forgotten.html:34 msgid "Request password reset" msgstr "" -#: ../templates/classic/html/user.forgotten.html:30 +#: ../share/roundup/templates/classic/html/user.forgotten.html:30 msgid "Or, if you know your username, then enter it below." msgstr "" -#: ../templates/classic/html/user.forgotten.html:33 +#: ../share/roundup/templates/classic/html/user.forgotten.html:33 msgid "Username:" msgstr "" -#: ../templates/classic/html/user.forgotten.html:39 +#: ../share/roundup/templates/classic/html/user.forgotten.html:39 msgid "" "A confirmation email will be sent to you - please follow the instructions " "within it to complete the reset process." msgstr "" -#: ../templates/classic/html/user.help-search.html:73 +#: ../share/roundup/templates/classic/html/user.help-search.html:73 msgid "Pagesize" msgstr "" -#: ../templates/classic/html/user.help.html:43 +#: ../share/roundup/templates/classic/html/user.help.html:43 msgid "" "Your browser is not capable of using frames; you should be redirected " "immediately, or visit ${link}." msgstr "" -#: ../templates/classic/html/user.index.html:3 -#: ../templates/minimal/html/user.index.html:3 +#: ../share/roundup/templates/classic/html/user.index.html:3 +#: ../share/roundup/templates/minimal/html/user.index.html:3 msgid "User listing - ${tracker}" msgstr "" -#: ../templates/classic/html/user.index.html:5 -#: ../templates/minimal/html/user.index.html:5 +#: ../share/roundup/templates/classic/html/user.index.html:5 +#: ../share/roundup/templates/minimal/html/user.index.html:5 msgid "User listing" msgstr "" -#: ../templates/classic/html/user.index.html:19 -#: ../templates/minimal/html/user.index.html:19 +#: ../share/roundup/templates/classic/html/user.index.html:19 +#: ../share/roundup/templates/minimal/html/user.index.html:19 msgid "Username" msgstr "" -#: ../templates/classic/html/user.index.html:20 +#: ../share/roundup/templates/classic/html/user.index.html:20 msgid "Real name" msgstr "" -#: ../templates/classic/html/user.index.html:21 -#: ../templates/classic/html/user.register.html:45 +#: ../share/roundup/templates/classic/html/user.index.html:21 +#: ../share/roundup/templates/classic/html/user.register.html:45 msgid "Organisation" msgstr "" -#: ../templates/classic/html/user.index.html:22 -#: ../templates/minimal/html/user.index.html:20 +#: ../share/roundup/templates/classic/html/user.index.html:22 +#: ../share/roundup/templates/minimal/html/user.index.html:20 msgid "Email address" msgstr "" -#: ../templates/classic/html/user.index.html:23 +#: ../share/roundup/templates/classic/html/user.index.html:23 msgid "Phone number" msgstr "" -#: ../templates/classic/html/user.index.html:24 +#: ../share/roundup/templates/classic/html/user.index.html:24 msgid "Retire" msgstr "" -#: ../templates/classic/html/user.index.html:37 +#: ../share/roundup/templates/classic/html/user.index.html:41 msgid "retire" msgstr "" -#: ../templates/classic/html/user.item.html:9 -#: ../templates/minimal/html/user.item.html:9 +#: ../share/roundup/templates/classic/html/user.item.html:9 +#: ../share/roundup/templates/minimal/html/user.item.html:9 msgid "User ${id}: ${title} - ${tracker}" msgstr "" -#: ../templates/classic/html/user.item.html:12 -#: ../templates/minimal/html/user.item.html:12 +#: ../share/roundup/templates/classic/html/user.item.html:12 +#: ../share/roundup/templates/minimal/html/user.item.html:12 msgid "New User - ${tracker}" msgstr "" -#: ../templates/classic/html/user.item.html:21 -#: ../templates/minimal/html/user.item.html:21 +#: ../share/roundup/templates/classic/html/user.item.html:21 +#: ../share/roundup/templates/minimal/html/user.item.html:21 msgid "New User" msgstr "" -#: ../templates/classic/html/user.item.html:23 -#: ../templates/minimal/html/user.item.html:23 +#: ../share/roundup/templates/classic/html/user.item.html:23 +#: ../share/roundup/templates/minimal/html/user.item.html:23 msgid "New User Editing" msgstr "" -#: ../templates/classic/html/user.item.html:26 -#: ../templates/minimal/html/user.item.html:26 +#: ../share/roundup/templates/classic/html/user.item.html:26 +#: ../share/roundup/templates/minimal/html/user.item.html:26 msgid "User${id}" msgstr "" -#: ../templates/classic/html/user.item.html:29 -#: ../templates/minimal/html/user.item.html:29 +#: ../share/roundup/templates/classic/html/user.item.html:29 +#: ../share/roundup/templates/minimal/html/user.item.html:29 msgid "User${id} Editing" msgstr "" -#: ../templates/classic/html/user.item.html:80 -#: ../templates/classic/html/user.register.html:33 -#: ../templates/minimal/html/user.item.html:80 -#: ../templates/minimal/html/user.register.html:41 +#: ../share/roundup/templates/classic/html/user.item.html:80 +#: ../share/roundup/templates/classic/html/user.register.html:33 +#: ../share/roundup/templates/minimal/html/user.item.html:80 +#: ../share/roundup/templates/minimal/html/user.register.html:41 msgid "Roles" msgstr "" -#: ../templates/classic/html/user.item.html:88 -#: ../templates/minimal/html/user.item.html:88 +#: ../share/roundup/templates/classic/html/user.item.html:88 +#: ../share/roundup/templates/minimal/html/user.item.html:88 msgid "(to give the user more than one role, enter a comma,separated,list)" msgstr "" -#: ../templates/classic/html/user.item.html:109 -#: ../templates/minimal/html/user.item.html:109 +#: ../share/roundup/templates/classic/html/user.item.html:109 +#: ../share/roundup/templates/minimal/html/user.item.html:109 msgid "(this is a numeric hour offset, the default is ${zone})" msgstr "" -#: ../templates/classic/html/user.item.html:130 -#: ../templates/classic/html/user.register.html:53 -#: ../templates/minimal/html/user.item.html:130 -#: ../templates/minimal/html/user.register.html:53 +#: ../share/roundup/templates/classic/html/user.item.html:130 +#: ../share/roundup/templates/classic/html/user.register.html:53 +#: ../share/roundup/templates/minimal/html/user.item.html:130 +#: ../share/roundup/templates/minimal/html/user.register.html:53 msgid "Alternate E-mail addresses
        One address per line" msgstr "" -#: ../templates/classic/html/user.register.html:4 -#: ../templates/classic/html/user.register.html:7 -#: ../templates/minimal/html/user.register.html:4 -#: ../templates/minimal/html/user.register.html:7 +#: ../share/roundup/templates/classic/html/user.register.html:4 +#: ../share/roundup/templates/classic/html/user.register.html:7 +#: ../share/roundup/templates/minimal/html/user.register.html:4 +#: ../share/roundup/templates/minimal/html/user.register.html:7 msgid "Registering with ${tracker}" msgstr "" -#: ../templates/classic/html/user.register.html:21 -#: ../templates/minimal/html/user.register.html:29 +#: ../share/roundup/templates/classic/html/user.register.html:21 +#: ../share/roundup/templates/minimal/html/user.register.html:29 msgid "Login Name" msgstr "" -#: ../templates/classic/html/user.register.html:25 -#: ../templates/minimal/html/user.register.html:33 +#: ../share/roundup/templates/classic/html/user.register.html:25 +#: ../share/roundup/templates/minimal/html/user.register.html:33 msgid "Login Password" msgstr "" -#: ../templates/classic/html/user.register.html:29 -#: ../templates/minimal/html/user.register.html:37 +#: ../share/roundup/templates/classic/html/user.register.html:29 +#: ../share/roundup/templates/minimal/html/user.register.html:37 msgid "Confirm Password" msgstr "" -#: ../templates/classic/html/user.register.html:41 +#: ../share/roundup/templates/classic/html/user.register.html:41 msgid "Phone" msgstr "" -#: ../templates/classic/html/user.register.html:49 -#: ../templates/minimal/html/user.register.html:49 +#: ../share/roundup/templates/classic/html/user.register.html:49 +#: ../share/roundup/templates/minimal/html/user.register.html:49 msgid "E-mail address" msgstr "" -#: ../templates/classic/html/user.rego_progress.html:4 -#: ../templates/minimal/html/user.rego_progress.html:4 +#: ../share/roundup/templates/classic/html/user.rego_progress.html:4 +#: ../share/roundup/templates/minimal/html/user.rego_progress.html:4 msgid "Registration in progress - ${tracker}" msgstr "" -#: ../templates/classic/html/user.rego_progress.html:6 -#: ../templates/minimal/html/user.rego_progress.html:6 +#: ../share/roundup/templates/classic/html/user.rego_progress.html:6 +#: ../share/roundup/templates/minimal/html/user.rego_progress.html:6 msgid "Registration in progress..." msgstr "" -#: ../templates/classic/html/user.rego_progress.html:10 -#: ../templates/minimal/html/user.rego_progress.html:10 +#: ../share/roundup/templates/classic/html/user.rego_progress.html:10 +#: ../share/roundup/templates/minimal/html/user.rego_progress.html:10 msgid "" "You will shortly receive an email to confirm your registration. To complete " "the registration process, visit the link indicated in the email." msgstr "" -#: ../templates/classic/initial_data.py:5 +#: ../share/roundup/templates/classic/initial_data.py:5 msgid "critical" msgstr "" -#: ../templates/classic/initial_data.py:6 +#: ../share/roundup/templates/classic/initial_data.py:6 msgid "urgent" msgstr "" -#: ../templates/classic/initial_data.py:7 +#: ../share/roundup/templates/classic/initial_data.py:7 msgid "bug" msgstr "" -#: ../templates/classic/initial_data.py:8 +#: ../share/roundup/templates/classic/initial_data.py:8 msgid "feature" msgstr "" -#: ../templates/classic/initial_data.py:9 +#: ../share/roundup/templates/classic/initial_data.py:9 msgid "wish" msgstr "" -#: ../templates/classic/initial_data.py:12 +#: ../share/roundup/templates/classic/initial_data.py:12 msgid "unread" msgstr "" -#: ../templates/classic/initial_data.py:13 +#: ../share/roundup/templates/classic/initial_data.py:13 msgid "deferred" msgstr "" -#: ../templates/classic/initial_data.py:14 +#: ../share/roundup/templates/classic/initial_data.py:14 msgid "chatting" msgstr "" -#: ../templates/classic/initial_data.py:15 +#: ../share/roundup/templates/classic/initial_data.py:15 msgid "need-eg" msgstr "" -#: ../templates/classic/initial_data.py:16 +#: ../share/roundup/templates/classic/initial_data.py:16 msgid "in-progress" msgstr "" -#: ../templates/classic/initial_data.py:17 +#: ../share/roundup/templates/classic/initial_data.py:17 msgid "testing" msgstr "" -#: ../templates/classic/initial_data.py:18 +#: ../share/roundup/templates/classic/initial_data.py:18 msgid "done-cbb" msgstr "" -#: ../templates/classic/initial_data.py:19 +#: ../share/roundup/templates/classic/initial_data.py:19 msgid "resolved" msgstr "" -#: ../templates/minimal/html/home.html:2 +#: ../share/roundup/templates/minimal/html/home.html:2 msgid "Tracker home - ${tracker}" msgstr "" -#: ../templates/minimal/html/home.html:4 +#: ../share/roundup/templates/minimal/html/home.html:4 msgid "Tracker home" msgstr "" -#: ../templates/minimal/html/home.html:16 +#: ../share/roundup/templates/minimal/html/home.html:16 msgid "Please select from one of the menu options on the left." msgstr "" -#: ../templates/minimal/html/home.html:19 +#: ../share/roundup/templates/minimal/html/home.html:19 msgid "Please log in or register." msgstr "" Modified: tracker/roundup-src/locale/ru.po ============================================================================== --- tracker/roundup-src/locale/ru.po (original) +++ tracker/roundup-src/locale/ru.po Sun Mar 15 22:43:30 2009 @@ -1,7 +1,7 @@ # Russian message file for Roundup Issue Tracker # alexander smishlajev , 2004 # -# $Id: ru.po,v 1.16 2007/09/16 07:23:04 a1s Exp $ +# $Id: ru.po,v 1.16 2007-09-16 07:23:04 a1s Exp $ # # roundup.pot revision 1.23 # Modified: tracker/roundup-src/locale/zh_CN.po ============================================================================== --- tracker/roundup-src/locale/zh_CN.po (original) +++ tracker/roundup-src/locale/zh_CN.po Sun Mar 15 22:43:30 2009 @@ -1,7 +1,7 @@ # Chinese message file for Roundup Issue Tracker # limodou # -# $Id: zh_CN.po,v 1.3 2005/05/16 09:23:22 a1s Exp $ +# $Id: zh_CN.po,v 1.3 2005-05-16 09:23:22 a1s Exp $ # # roundup.pot revision 1.10 # Modified: tracker/roundup-src/locale/zh_TW.po ============================================================================== --- tracker/roundup-src/locale/zh_TW.po (original) +++ tracker/roundup-src/locale/zh_TW.po Sun Mar 15 22:43:30 2009 @@ -1,7 +1,7 @@ # Chinese Traditional message file for Roundup Issue Tracker # Fred Lin # -# $Id: zh_TW.po,v 1.2 2005/05/16 09:31:48 a1s Exp $ +# $Id: zh_TW.po,v 1.2 2005-05-16 09:31:48 a1s Exp $ # # roundup.pot revision 1.10 # Modified: tracker/roundup-src/roundup/__init__.py ============================================================================== --- tracker/roundup-src/roundup/__init__.py (original) +++ tracker/roundup-src/roundup/__init__.py Sun Mar 15 22:43:30 2009 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: __init__.py,v 1.49 2007/12/23 01:52:07 richard Exp $ +# $Id: __init__.py,v 1.54 2008-09-01 01:58:32 richard Exp $ '''Roundup - issue tracking for knowledge workers. @@ -68,6 +68,6 @@ ''' __docformat__ = 'restructuredtext' -__version__ = '1.4.2' +__version__ = '1.4.7' # vim: set filetype=python ts=4 sw=4 et si Added: tracker/roundup-src/roundup/actions.py ============================================================================== --- (empty file) +++ tracker/roundup-src/roundup/actions.py Sun Mar 15 22:43:30 2009 @@ -0,0 +1,68 @@ +# +# Copyright (C) 2009 Stefan Seefeld +# All rights reserved. +# For license terms see the file COPYING.txt. +# + +from roundup.exceptions import * +from roundup import hyperdb +from roundup.i18n import _ + +class Action: + def __init__(self, db, translator): + self.db = db + self.translator = translator + + def handle(self, *args): + """Action handler procedure""" + raise NotImplementedError + + def execute(self, *args): + """Execute the action specified by this object.""" + + self.permission(*args) + return self.handle(*args) + + + def permission(self, *args): + """Check whether the user has permission to execute this action. + + If not, raise Unauthorised.""" + + pass + + + def gettext(self, msgid): + """Return the localized translation of msgid""" + return self.translator.gettext(msgid) + + + _ = gettext + + +class Retire(Action): + + def handle(self, designator): + + classname, itemid = hyperdb.splitDesignator(designator) + + # make sure we don't try to retire admin or anonymous + if (classname == 'user' and + self.db.user.get(itemid, 'username') in ('admin', 'anonymous')): + raise ValueError, self._( + 'You may not retire the admin or anonymous user') + + # do the retire + self.db.getclass(classname).retire(itemid) + self.db.commit() + + + def permission(self, designator): + + classname, itemid = hyperdb.splitDesignator(designator) + + if not self.db.security.hasPermission('Edit', self.db.getuid(), + classname=classname, itemid=itemid): + raise Unauthorised(self._('You do not have permission to ' + '%(action)s the %(classname)s class.')%info) + Modified: tracker/roundup-src/roundup/admin.py ============================================================================== --- tracker/roundup-src/roundup/admin.py (original) +++ tracker/roundup-src/roundup/admin.py Sun Mar 15 22:43:30 2009 @@ -16,10 +16,9 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: admin.py,v 1.110 2008/02/07 03:28:33 richard Exp $ -'''Administration commands for maintaining Roundup trackers. -''' +"""Administration commands for maintaining Roundup trackers. +""" __docformat__ = 'restructuredtext' import csv, getopt, getpass, os, re, shutil, sys, UserDict @@ -29,12 +28,13 @@ import roundup.instance from roundup.configuration import CoreConfig from roundup.i18n import _ +from roundup.exceptions import UsageError class CommandDict(UserDict.UserDict): - '''Simple dictionary that lets us do lookups using partial keys. + """Simple dictionary that lets us do lookups using partial keys. Original code submitted by Engelbert Gruber. - ''' + """ _marker = [] def get(self, key, default=_marker): if self.data.has_key(key): @@ -49,11 +49,8 @@ raise KeyError, key return l -class UsageError(ValueError): - pass - class AdminTool: - ''' A collection of methods used in maintaining Roundup trackers. + """ A collection of methods used in maintaining Roundup trackers. Typically these methods are accessed through the roundup-admin script. The main() method provided on this class gives the main @@ -63,7 +60,7 @@ given in the method docstring. Additional help may be supplied by help_*() methods. - ''' + """ def __init__(self): self.commands = CommandDict() for k in AdminTool.__dict__.keys(): @@ -78,18 +75,18 @@ self.db_uncommitted = False def get_class(self, classname): - '''Get the class - raise an exception if it doesn't exist. - ''' + """Get the class - raise an exception if it doesn't exist. + """ try: return self.db.getclass(classname) except KeyError: raise UsageError, _('no such class "%(classname)s"')%locals() def props_from_args(self, args): - ''' Produce a dictionary of prop: value from the args list. + """ Produce a dictionary of prop: value from the args list. The args list is specified as ``prop=value prop=value ...``. - ''' + """ props = {} for arg in args: if arg.find('=') == -1: @@ -107,11 +104,11 @@ return props def usage(self, message=''): - ''' Display a simple usage message. - ''' + """ Display a simple usage message. + """ if message: message = _('Problem: %(message)s\n\n')%locals() - print _('''%(message)sUsage: roundup-admin [options] [ ] + print _("""%(message)sUsage: roundup-admin [options] [ ] Options: -i instance home -- specify the issue tracker "home directory" to administer @@ -132,12 +129,12 @@ roundup-admin help -- this help roundup-admin help -- command-specific help roundup-admin help all -- all available help -''')%locals() +""")%locals() self.help_commands() def help_commands(self): - ''' List the commands available with their help summary. - ''' + """List the commands available with their help summary. + """ print _('Commands:'), commands = [''] for command in self.commands.values(): @@ -151,8 +148,8 @@ print def help_commands_html(self, indent_re=re.compile(r'^(\s+)\S+')): - ''' Produce an HTML command list. - ''' + """ Produce an HTML command list. + """ commands = self.commands.values() def sortfun(a, b): return cmp(a.__name__, b.__name__) @@ -161,10 +158,10 @@ h = _(command.__doc__).split('\n') name = command.__name__[3:] usage = h[0] - print ''' + print """ %(name)s %(usage)s

        -

        ''' % locals()
        +
        """ % locals()
                     indent = indent_re.match(h[3])
                     if indent: indent = len(indent.group(1))
                     for line in h[3:]:
        @@ -175,7 +172,7 @@
                     print '
        \n' def help_all(self): - print _(''' + print _(""" All commands (except help) require a tracker specifier. This is just the path to the roundup tracker you're working with. A roundup tracker is where roundup keeps the database and configuration file that defines @@ -236,21 +233,21 @@ "." means "right now" Command help: -''') +""") for name, command in self.commands.items(): print _('%s:')%name print ' ', _(command.__doc__) def do_help(self, args, nl_re=re.compile('[\r\n]'), indent_re=re.compile(r'^(\s+)\S+')): - ""'''Usage: help topic + ''"""Usage: help topic Give help about topic. commands -- list commands -- help specific to a command initopts -- init command options all -- all available help - ''' + """ if len(args)>0: topic = args[0] else: @@ -283,7 +280,7 @@ return 0 def listTemplates(self): - ''' List all the available templates. + """ List all the available templates. Look in the following places, where the later rules take precedence: @@ -299,7 +296,7 @@ this is for when someone unpacks a 3rd-party template 5. this is for someone who "cd"s to the 3rd-party template dir - ''' + """ # OK, try /share/roundup/templates # and /share/roundup/templates # -- this module (roundup.admin) will be installed in something @@ -349,7 +346,7 @@ print _('Back ends:'), ', '.join(backends) def do_install(self, tracker_home, args): - ""'''Usage: install [template [backend [key=val[,key=val]]]] + ''"""Usage: install [template [backend [key=val[,key=val]]]] Install a new Roundup tracker. The command will prompt for the tracker home directory @@ -370,7 +367,7 @@ the tracker's dbinit.py module init() function. See also initopts help. - ''' + """ if len(args) < 1: raise UsageError, _('Not enough arguments supplied') @@ -464,23 +461,23 @@ return 0 def do_genconfig(self, args): - ""'''Usage: genconfig + ''"""Usage: genconfig Generate a new tracker config file (ini style) with default values in . - ''' + """ if len(args) < 1: raise UsageError, _('Not enough arguments supplied') config = CoreConfig() config.save(args[0]) def do_initialise(self, tracker_home, args): - ""'''Usage: initialise [adminpw] + ''"""Usage: initialise [adminpw] Initialise a new Roundup tracker. The administrator details will be set at this step. Execute the tracker's initialisation function dbinit.init() - ''' + """ # password if len(args) > 1: adminpw = args[1] @@ -523,12 +520,12 @@ def do_get(self, args): - ""'''Usage: get property designator[,designator]* + ''"""Usage: get property designator[,designator]* Get the given property of one or more designator(s). Retrieves the property value of the nodes specified by the designators. - ''' + """ if len(args) < 2: raise UsageError, _('Not enough arguments supplied') propname = args[0] @@ -597,7 +594,7 @@ def do_set(self, args): - ""'''Usage: set items property=value property=value ... + ''"""Usage: set items property=value property=value ... Set the given properties of one or more items(s). The items are specified as a class or as a comma-separated @@ -607,7 +604,7 @@ given. If the value is missing (ie. "property=") then the property is un-set. If the property is a multilink, you specify the linked ids for the multilink as comma-separated numbers (ie "1,2,3"). - ''' + """ if len(args) < 2: raise UsageError, _('Not enough arguments supplied') from roundup import hyperdb @@ -652,13 +649,13 @@ return 0 def do_find(self, args): - ""'''Usage: find classname propname=value ... + ''"""Usage: find classname propname=value ... Find the nodes of the given class with a given link property value. Find the nodes of the given class with a given link property value. The value may be either the nodeid of the linked node, or its key value. - ''' + """ if len(args) < 1: raise UsageError, _('Not enough arguments supplied') classname = args[0] @@ -712,11 +709,11 @@ return 0 def do_specification(self, args): - ""'''Usage: specification classname + ''"""Usage: specification classname Show the properties for a classname. This lists the properties for a given class. - ''' + """ if len(args) < 1: raise UsageError, _('Not enough arguments supplied') classname = args[0] @@ -732,12 +729,12 @@ print _('%(key)s: %(value)s')%locals() def do_display(self, args): - ""'''Usage: display designator[,designator]* + ''"""Usage: display designator[,designator]* Show the property values for the given node(s). This lists the properties and their associated values for the given node. - ''' + """ if len(args) < 1: raise UsageError, _('Not enough arguments supplied') @@ -759,13 +756,13 @@ print _('%(key)s: %(value)s')%locals() def do_create(self, args): - ""'''Usage: create classname property=value ... + ''"""Usage: create classname property=value ... Create a new entry of a given class. This creates a new entry of the given class using the property name=value arguments provided on the command line after the "create" command. - ''' + """ if len(args) < 1: raise UsageError, _('Not enough arguments supplied') from roundup import hyperdb @@ -824,7 +821,7 @@ return 0 def do_list(self, args): - ""'''Usage: list classname [property] + ''"""Usage: list classname [property] List the instances of a class. Lists all instances of the given class. If the property is not @@ -835,13 +832,13 @@ With -c, -S or -s print a list of item id's if no property specified. If property specified, print list of that property for every class instance. - ''' + """ if len(args) > 2: raise UsageError, _('Too many arguments supplied') if len(args) < 1: raise UsageError, _('Not enough arguments supplied') classname = args[0] - + # get the class cl = self.get_class(classname) @@ -853,7 +850,7 @@ if self.separator: if len(args) == 2: - # create a list of propnames since user specified propname + # create a list of propnames since user specified propname proplist=[] for nodeid in cl.list(): try: @@ -877,7 +874,7 @@ return 0 def do_table(self, args): - ""'''Usage: table classname [property[,property]*] + ''"""Usage: table classname [property[,property]*] List the instances of a class in tabular form. Lists all instances of the given class. If the properties are not @@ -904,7 +901,7 @@ 4 feat will result in a the 4 character wide "Name" column. - ''' + """ if len(args) < 1: raise UsageError, _('Not enough arguments supplied') classname = args[0] @@ -971,11 +968,11 @@ return 0 def do_history(self, args): - ""'''Usage: history designator + ''"""Usage: history designator Show the history entries of a designator. Lists the journal entries for the node identified by the designator. - ''' + """ if len(args) < 1: raise UsageError, _('Not enough arguments supplied') try: @@ -992,7 +989,7 @@ return 0 def do_commit(self, args): - ""'''Usage: commit + ''"""Usage: commit Commit changes made to the database during an interactive session. The changes made during an interactive session are not @@ -1001,31 +998,31 @@ One-off commands on the command-line are automatically committed if they are successful. - ''' + """ self.db.commit() self.db_uncommitted = False return 0 def do_rollback(self, args): - ""'''Usage: rollback + ''"""Usage: rollback Undo all changes that are pending commit to the database. The changes made during an interactive session are not automatically written to the database - they must be committed manually. This command undoes all those changes, so a commit immediately after would make no changes to the database. - ''' + """ self.db.rollback() self.db_uncommitted = False return 0 def do_retire(self, args): - ""'''Usage: retire designator[,designator]* + ''"""Usage: retire designator[,designator]* Retire the node specified by designator. This action indicates that a particular node is not to be retrieved by the list or find commands, and its key value may be re-used. - ''' + """ if len(args) < 1: raise UsageError, _('Not enough arguments supplied') designators = args[0].split(',') @@ -1044,11 +1041,11 @@ return 0 def do_restore(self, args): - ""'''Usage: restore designator[,designator]* + ''"""Usage: restore designator[,designator]* Restore the retired node specified by designator. The given nodes will become available for users again. - ''' + """ if len(args) < 1: raise UsageError, _('Not enough arguments supplied') designators = args[0].split(',') @@ -1067,7 +1064,7 @@ return 0 def do_export(self, args, export_files=True): - ""'''Usage: export [[-]class[,class]] export_dir + ''"""Usage: export [[-]class[,class]] export_dir Export the database to colon-separated-value files. To exclude the files (e.g. for the msg or file class), use the exporttables command. @@ -1078,7 +1075,7 @@ This action exports the current data from the database into colon-separated-value files that are placed in the nominated destination directory. - ''' + """ # grab the directory to export to if len(args) < 1: raise UsageError, _('Not enough arguments supplied') @@ -1142,7 +1139,7 @@ return 0 def do_exporttables(self, args): - ""'''Usage: exporttables [[-]class[,class]] export_dir + ''"""Usage: exporttables [[-]class[,class]] export_dir Export the database to colon-separated-value files, excluding the files below $TRACKER_HOME/db/files/ (which can be archived separately). To include the files, use the export command. @@ -1153,11 +1150,11 @@ This action exports the current data from the database into colon-separated-value files that are placed in the nominated destination directory. - ''' + """ return self.do_export(args, export_files=False) def do_import(self, args): - ""'''Usage: import import_dir + ''"""Usage: import import_dir Import a database from the directory containing CSV files, two per class to import. @@ -1175,7 +1172,7 @@ The new nodes are added to the existing database - if you want to create a new database using the imported data, then create a new database (or, tediously, retire all the old data.) - ''' + """ if len(args) < 1: raise UsageError, _('Not enough arguments supplied') from roundup import hyperdb @@ -1232,7 +1229,7 @@ return 0 def do_pack(self, args): - ""'''Usage: pack period | date + ''"""Usage: pack period | date Remove journal entries older than a period of time specified or before a certain date. @@ -1248,16 +1245,16 @@ Date format is "YYYY-MM-DD" eg: 2001-01-01 - ''' + """ if len(args) <> 1: raise UsageError, _('Not enough arguments supplied') # are we dealing with a period or a date value = args[0] - date_re = re.compile(r''' + date_re = re.compile(r""" (?P\d\d\d\d-\d\d?-\d\d?)? # yyyy-mm-dd (?P(\d+y\s*)?(\d+m\s*)?(\d+d\s*)?)? - ''', re.VERBOSE) + """, re.VERBOSE) m = date_re.match(value) if not m: raise ValueError, _('Invalid format') @@ -1271,12 +1268,12 @@ return 0 def do_reindex(self, args, desre=re.compile('([A-Za-z]+)([0-9]+)')): - ""'''Usage: reindex [classname|designator]* + ''"""Usage: reindex [classname|designator]* Re-generate a tracker's search indexes. This will re-generate the search indexes for a tracker. This will typically happen automatically. - ''' + """ if args: for arg in args: m = desre.match(arg) @@ -1295,9 +1292,9 @@ return 0 def do_security(self, args): - ""'''Usage: security [Role name] + ''"""Usage: security [Role name] Display the Permissions available to one or all Roles. - ''' + """ if len(args) == 1: role = args[0] try: @@ -1335,7 +1332,7 @@ def do_migrate(self, args): - '''Usage: migrate + ''"""Usage: migrate Update a tracker's database to be compatible with the Roundup codebase. @@ -1352,7 +1349,7 @@ It's safe to run this even if it's not required, so just get into the habit. - ''' + """ if getattr(self.db, 'db_version_updated'): print _('Tracker updated') self.db_uncommitted = True @@ -1361,8 +1358,8 @@ return 0 def run_command(self, args): - '''Run a single command - ''' + """Run a single command + """ command = args[0] # handle help now @@ -1443,8 +1440,8 @@ return ret def interactive(self): - '''Run in an interactive mode - ''' + """Run in an interactive mode + """ print _('Roundup %s ready for input.\nType "help" for help.' % roundup_version) try: Added: tracker/roundup-src/roundup/anypy/README.txt ============================================================================== --- (empty file) +++ tracker/roundup-src/roundup/anypy/README.txt Sun Mar 15 22:43:30 2009 @@ -0,0 +1,57 @@ +roundup.anypy package - Python version compatibility layer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Roundup currently supports Python 2.3 to 2.6; however, some modules +have been introduced, while others have been deprecated. The modules +in this package provide the functionalities which are used by Roundup + +- adapting the most recent Python usage +- using new built-in functionality +- avoiding deprecation warnings + +Use the modules in this package to preserve Roundup's compatibility. + +sets_: sets compatibility module +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since Python 2.4, there is a built-in type 'set'; therefore, the 'sets' +module is deprecated since version 2.6. As far as Roundup is concerned, +the usage is identical; see +http://docs.python.org/library/sets.html#comparison-to-the-built-in-set-types + +Uses the built-in type 'set' if available, and thus avoids +deprecation warnings. Simple usage: + +Change all:: + from sets import Set + +to:: + from roundup.anypy.sets_ import set + +and use 'set' instead of 'Set' (or sets.Set, respectively). +To avoid unnecessary imports, you can:: + + try: + set + except NameError: + from roundup.anypy.sets_ import set + +hashlib_: md5/sha/hashlib compatibility +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The md5 and sha modules are deprecated since Python 2.6; the hashlib +module, introduced with Python 2.5, is recommended instead. + +Change all:: + import md5 + md5.md5(), md5.new() + import sha + sha.sha(), sha.new() + +to:: + from roundup.anypy.hashlib_ import md5 + md5() + from roundup.anypy.hashlib_ import sha1 + sha1() + +# vim: si Added: tracker/roundup-src/roundup/anypy/TODO.txt ============================================================================== --- (empty file) +++ tracker/roundup-src/roundup/anypy/TODO.txt Sun Mar 15 22:43:30 2009 @@ -0,0 +1,8 @@ +Python compatiblity TODO +~~~~~~~~~~~~~~~~~~~~~~~~ + +- the popen2 module is deprecated as of Python 2.6; + the subprocess module is available since Python 2.4, + thus a roundup.anypy.subprocess_ module is needed + +# vim: si Added: tracker/roundup-src/roundup/anypy/__init__.py ============================================================================== --- (empty file) +++ tracker/roundup-src/roundup/anypy/__init__.py Sun Mar 15 22:43:30 2009 @@ -0,0 +1,7 @@ +""" +roundup.anypy - compatibility layer for any Python 2.3+ +""" +VERSION = '.'.join(map(str, + (0, + 1, # hashlib_, sets_ + ))) Added: tracker/roundup-src/roundup/anypy/hashlib_.py ============================================================================== --- (empty file) +++ tracker/roundup-src/roundup/anypy/hashlib_.py Sun Mar 15 22:43:30 2009 @@ -0,0 +1,11 @@ +""" +anypy.hashlib_: encapsulation of hashlib/md5/sha1/sha +""" + +try: + from hashlib import md5, sha1 # new in Python 2.5 +except ImportError: + from md5 import md5 # deprecated in Python 2.6 + from sha import sha as sha1 # deprecated in Python 2.6 + +# vim: ts=8 sts=4 sw=4 si Added: tracker/roundup-src/roundup/anypy/sets_.py ============================================================================== --- (empty file) +++ tracker/roundup-src/roundup/anypy/sets_.py Sun Mar 15 22:43:30 2009 @@ -0,0 +1,30 @@ +""" +anypy.sets_: sets compatibility module + +uses the built-in type 'set' if available, and thus avoids +deprecation warnings. Simple usage: + +Change all + from sets import Set +to + from roundup.anypy.sets_ import set + +and use 'set' instead of 'Set'. +To avoid unnecessary imports, you can: + + try: + set + except NameError: + from roundup.anypy.sets_ import set + +see: +http://docs.python.org/library/sets.html#comparison-to-the-built-in-set-types + +""" + +try: + set = set # built-in since Python 2.4 +except NameError, TypeError: + from sets import Set as set # deprecated as of Python 2.6 + +# vim: ts=8 sts=4 sw=4 si et Modified: tracker/roundup-src/roundup/backends/__init__.py ============================================================================== --- tracker/roundup-src/roundup/backends/__init__.py (original) +++ tracker/roundup-src/roundup/backends/__init__.py Sun Mar 15 22:43:30 2009 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: __init__.py,v 1.40 2007/11/07 20:47:12 richard Exp $ +# $Id: __init__.py,v 1.40 2007-11-07 20:47:12 richard Exp $ '''Container for the hyperdb storage backend implementations. ''' Modified: tracker/roundup-src/roundup/backends/back_anydbm.py ============================================================================== --- tracker/roundup-src/roundup/backends/back_anydbm.py (original) +++ tracker/roundup-src/roundup/backends/back_anydbm.py Sun Mar 15 22:43:30 2009 @@ -15,12 +15,11 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -#$Id: back_anydbm.py,v 1.210 2008/02/07 00:57:59 richard Exp $ -'''This module defines a backend that saves the hyperdatabase in a +"""This module defines a backend that saves the hyperdatabase in a database chosen by anydbm. It is guaranteed to always be available in python versions >2.1.1 (the dumbdbm fallback in 2.1.1 and earlier has several serious bugs, and is not available) -''' +""" __docformat__ = 'restructuredtext' try: @@ -62,16 +61,16 @@ # Now the database # class Database(FileStorage, hyperdb.Database, roundupdb.Database): - '''A database for storing records containing flexible data types. + """A database for storing records containing flexible data types. Transaction stuff TODO: - check the timestamp of the class file and nuke the cache if it's modified. Do some sort of conflict checking on the dirty stuff. - perhaps detect write collisions (related to above)? - ''' + """ def __init__(self, config, journaltag=None): - '''Open a hyperdatabase given a specifier to some storage. + """Open a hyperdatabase given a specifier to some storage. The 'storagelocator' is obtained from config.DATABASE. The meaning of 'storagelocator' depends on the particular @@ -84,7 +83,7 @@ None, the database is opened in read-only mode: the Class.create(), Class.set(), Class.retire(), and Class.restore() methods are disabled. - ''' + """ FileStorage.__init__(self, config.UMASK) self.config, self.journaltag = config, journaltag self.dir = config.DATABASE @@ -107,8 +106,8 @@ self.lockfile.flush() def post_init(self): - '''Called once the schema initialisation has finished. - ''' + """Called once the schema initialisation has finished. + """ # reindex the db if necessary if self.indexer.should_reindex(): self.reindex() @@ -146,7 +145,7 @@ # Classes # def __getattr__(self, classname): - '''A convenient way of calling self.getclass(classname).''' + """A convenient way of calling self.getclass(classname).""" if self.classes.has_key(classname): return self.classes[classname] raise AttributeError, classname @@ -166,16 +165,16 @@ description="User is allowed to access "+cn) def getclasses(self): - '''Return a list of the names of all existing classes.''' + """Return a list of the names of all existing classes.""" l = self.classes.keys() l.sort() return l def getclass(self, classname): - '''Get the Class object representing a particular class. + """Get the Class object representing a particular class. If 'classname' is not a valid class name, a KeyError is raised. - ''' + """ try: return self.classes[classname] except KeyError: @@ -185,8 +184,8 @@ # Class DBs # def clear(self): - '''Delete all database contents - ''' + """Delete all database contents + """ logging.getLogger('hyperdb').info('clear') for cn in self.classes.keys(): for dummy in 'nodes', 'journals': @@ -203,14 +202,14 @@ os.remove(path+'.db') def getclassdb(self, classname, mode='r'): - ''' grab a connection to the class db that will be used for + """ grab a connection to the class db that will be used for multiple actions - ''' + """ return self.opendb('nodes.%s'%classname, mode) def determine_db_type(self, path): - ''' determine which DB wrote the class file - ''' + """ determine which DB wrote the class file + """ db_type = '' if os.path.exists(path): db_type = whichdb.whichdb(path) @@ -224,9 +223,9 @@ return db_type def opendb(self, name, mode): - '''Low-level database opener that gets around anydbm/dbm + """Low-level database opener that gets around anydbm/dbm eccentricities. - ''' + """ # figure the class db type path = os.path.join(os.getcwd(), self.dir, name) db_type = self.determine_db_type(path) @@ -253,8 +252,8 @@ # Node IDs # def newid(self, classname): - ''' Generate a new id for the given class - ''' + """ Generate a new id for the given class + """ # open the ids DB - create if if doesn't exist db = self.opendb('_ids', 'c') if db.has_key(classname): @@ -267,8 +266,8 @@ return newid def setid(self, classname, setid): - ''' Set the id counter: used during import of database - ''' + """ Set the id counter: used during import of database + """ # open the ids DB - create if if doesn't exist db = self.opendb('_ids', 'c') db[classname] = str(setid) @@ -278,8 +277,8 @@ # Nodes # def addnode(self, classname, nodeid, node): - ''' add the specified node to its class's db - ''' + """ add the specified node to its class's db + """ # we'll be supplied these props if we're doing an import if not node.has_key('creator'): # add in the "calculated" properties (dupe so we don't affect @@ -294,8 +293,8 @@ self.savenode(classname, nodeid, node) def setnode(self, classname, nodeid, node): - ''' change the specified node - ''' + """ change the specified node + """ self.dirtynodes.setdefault(classname, {})[nodeid] = 1 # can't set without having already loaded the node @@ -303,18 +302,18 @@ self.savenode(classname, nodeid, node) def savenode(self, classname, nodeid, node): - ''' perform the saving of data specified by the set/addnode - ''' + """ perform the saving of data specified by the set/addnode + """ if __debug__: logging.getLogger('hyperdb').debug('save %s%s %r'%(classname, nodeid, node)) self.transactions.append((self.doSaveNode, (classname, nodeid, node))) def getnode(self, classname, nodeid, db=None, cache=1): - ''' get a node from the database + """ get a node from the database Note the "cache" parameter is not used, and exists purely for backward compatibility! - ''' + """ # try the cache cache_dict = self.cache.setdefault(classname, {}) if cache_dict.has_key(nodeid): @@ -355,9 +354,9 @@ return res def destroynode(self, classname, nodeid): - '''Remove a node from the database. Called exclusively by the + """Remove a node from the database. Called exclusively by the destroy() method on Class. - ''' + """ logging.getLogger('hyperdb').info('destroy %s%s'%(classname, nodeid)) # remove from cache and newnodes if it's there @@ -381,9 +380,9 @@ self.transactions.append((FileStorage.destroy, (self, classname, nodeid))) def serialise(self, classname, node): - '''Copy the node contents, converting non-marshallable data into + """Copy the node contents, converting non-marshallable data into marshallable data. - ''' + """ properties = self.getclass(classname).getprops() d = {} for k, v in node.items(): @@ -409,8 +408,8 @@ return d def unserialise(self, classname, node): - '''Decode the marshalled node data - ''' + """Decode the marshalled node data + """ properties = self.getclass(classname).getprops() d = {} for k, v in node.items(): @@ -436,8 +435,8 @@ return d def hasnode(self, classname, nodeid, db=None): - ''' determine if the database has a given node - ''' + """ determine if the database has a given node + """ # try the cache cache = self.cache.setdefault(classname, {}) if cache.has_key(nodeid): @@ -474,7 +473,7 @@ # def addjournal(self, classname, nodeid, action, params, creator=None, creation=None): - ''' Journal the Action + """ Journal the Action 'action' may be: 'create' or 'set' -- 'params' is a dictionary of property values @@ -483,7 +482,7 @@ 'creator' -- the user performing the action, which defaults to the current user. - ''' + """ if __debug__: logging.getLogger('hyperdb').debug('addjournal %s%s %s %r %s %r'%(classname, nodeid, action, params, creator, creation)) @@ -493,7 +492,7 @@ action, params, creator, creation))) def setjournal(self, classname, nodeid, journal): - '''Set the journal to the "journal" list.''' + """Set the journal to the "journal" list.""" if __debug__: logging.getLogger('hyperdb').debug('setjournal %s%s %r'%(classname, nodeid, journal)) @@ -501,11 +500,11 @@ journal))) def getjournal(self, classname, nodeid): - ''' get the journal for id + """ get the journal for id Raise IndexError if the node doesn't exist (as per history()'s API) - ''' + """ # our journal result res = [] @@ -554,8 +553,8 @@ return res def pack(self, pack_before): - ''' Delete all journal entries except "create" before 'pack_before'. - ''' + """ Delete all journal entries except "create" before 'pack_before'. + """ pack_before = pack_before.serialise() for classname in self.getclasses(): packed = 0 @@ -594,7 +593,7 @@ # Basic transaction support # def commit(self, fail_ok=False): - ''' Commit the current transactions. + """ Commit the current transactions. Save all data changed since the database was opened or since the last commit() or rollback(). @@ -604,7 +603,7 @@ database. We don't care if there's a concurrency issue there. The only backend this seems to affect is postgres. - ''' + """ logging.getLogger('hyperdb').info('commit %s transactions'%( len(self.transactions))) @@ -645,8 +644,8 @@ self.transactions = [] def getCachedClassDB(self, classname): - ''' get the class db, looking in our cache of databases for commit - ''' + """ get the class db, looking in our cache of databases for commit + """ # get the database handle db_name = 'nodes.%s'%classname if not self.databases.has_key(db_name): @@ -663,8 +662,8 @@ return (classname, nodeid) def getCachedJournalDB(self, classname): - ''' get the journal db, looking in our cache of databases for commit - ''' + """ get the journal db, looking in our cache of databases for commit + """ # get the database handle db_name = 'journals.%s'%classname if not self.databases.has_key(db_name): @@ -726,8 +725,8 @@ del db[nodeid] def rollback(self): - ''' Reverse all actions from the current transaction. - ''' + """ Reverse all actions from the current transaction. + """ logging.getLogger('hyperdb').info('rollback %s transactions'%( len(self.transactions))) @@ -742,8 +741,8 @@ self.transactions = [] def close(self): - ''' Nothing to do - ''' + """ Nothing to do + """ if self.lockfile is not None: locking.release_lock(self.lockfile) self.lockfile.close() @@ -751,22 +750,22 @@ _marker = [] class Class(hyperdb.Class): - '''The handle to a particular class of nodes in a hyperdatabase.''' + """The handle to a particular class of nodes in a hyperdatabase.""" def enableJournalling(self): - '''Turn journalling on for this class - ''' + """Turn journalling on for this class + """ self.do_journal = 1 def disableJournalling(self): - '''Turn journalling off for this class - ''' + """Turn journalling off for this class + """ self.do_journal = 0 # Editing nodes: def create(self, **propvalues): - '''Create a new node of this class and return its id. + """Create a new node of this class and return its id. The keyword arguments in 'propvalues' map property names to values. @@ -784,15 +783,15 @@ These operations trigger detectors and can be vetoed. Attempts to modify the "creation" or "activity" properties cause a KeyError. - ''' + """ self.fireAuditors('create', None, propvalues) newid = self.create_inner(**propvalues) self.fireReactors('create', newid, None) return newid def create_inner(self, **propvalues): - ''' Called by create, in-between the audit and react calls. - ''' + """ Called by create, in-between the audit and react calls. + """ if propvalues.has_key('id'): raise KeyError, '"id" is reserved' @@ -926,7 +925,7 @@ return newid def get(self, nodeid, propname, default=_marker, cache=1): - '''Get the value of a property on an existing node of this class. + """Get the value of a property on an existing node of this class. 'nodeid' must be the id of an existing node of this class or an IndexError is raised. 'propname' must be the name of a property @@ -936,7 +935,7 @@ Attempts to get the "creation" or "activity" properties should do the right thing. - ''' + """ if propname == 'id': return nodeid @@ -1026,7 +1025,7 @@ return d[propname] def set(self, nodeid, **propvalues): - '''Modify a property on an existing node of this class. + """Modify a property on an existing node of this class. 'nodeid' must be the id of an existing node of this class or an IndexError is raised. @@ -1045,7 +1044,7 @@ These operations trigger detectors and can be vetoed. Attempts to modify the "creation" or "activity" properties cause a KeyError. - ''' + """ self.fireAuditors('set', nodeid, propvalues) oldvalues = copy.deepcopy(self.db.getnode(self.classname, nodeid)) for name,prop in self.getprops(protected=0).items(): @@ -1060,8 +1059,8 @@ return propvalues def set_inner(self, nodeid, **propvalues): - ''' Called by set, in-between the audit and react calls. - ''' + """ Called by set, in-between the audit and react calls. + """ if not propvalues: return propvalues @@ -1257,7 +1256,7 @@ return propvalues def retire(self, nodeid): - '''Retire a node. + """Retire a node. The properties on the node remain available from the get() method, and the node's id is never reused. @@ -1267,7 +1266,7 @@ These operations trigger detectors and can be vetoed. Attempts to modify the "creation" or "activity" properties cause a KeyError. - ''' + """ if self.db.journaltag is None: raise hyperdb.DatabaseError, _('Database open read-only') @@ -1282,10 +1281,10 @@ self.fireReactors('retire', nodeid, None) def restore(self, nodeid): - '''Restpre a retired node. + """Restpre a retired node. Make node available for all operations like it was before retirement. - ''' + """ if self.db.journaltag is None: raise hyperdb.DatabaseError, _('Database open read-only') @@ -1309,15 +1308,15 @@ self.fireReactors('restore', nodeid, None) def is_retired(self, nodeid, cldb=None): - '''Return true if the node is retired. - ''' + """Return true if the node is retired. + """ node = self.db.getnode(self.classname, nodeid, cldb) if node.has_key(self.db.RETIRED_FLAG): return 1 return 0 def destroy(self, nodeid): - '''Destroy a node. + """Destroy a node. WARNING: this method should never be used except in extremely rare situations where there could never be links to the node being @@ -1331,13 +1330,13 @@ Well, I think that's enough warnings. This method exists mostly to support the session storage of the cgi interface. - ''' + """ if self.db.journaltag is None: raise hyperdb.DatabaseError, _('Database open read-only') self.db.destroynode(self.classname, nodeid) def history(self, nodeid): - '''Retrieve the journal of edits on a particular node. + """Retrieve the journal of edits on a particular node. 'nodeid' must be the id of an existing node of this class or an IndexError is raised. @@ -1348,43 +1347,43 @@ 'date' is a Timestamp object specifying the time of the change and 'tag' is the journaltag specified when the database was opened. - ''' + """ if not self.do_journal: raise ValueError, 'Journalling is disabled for this class' return self.db.getjournal(self.classname, nodeid) # Locating nodes: def hasnode(self, nodeid): - '''Determine if the given nodeid actually exists - ''' + """Determine if the given nodeid actually exists + """ return self.db.hasnode(self.classname, nodeid) def setkey(self, propname): - '''Select a String property of this class to be the key property. + """Select a String property of this class to be the key property. 'propname' must be the name of a String property of this class or None, or a TypeError is raised. The values of the key property on all existing nodes must be unique or a ValueError is raised. If the property doesn't exist, KeyError is raised. - ''' + """ prop = self.getprops()[propname] if not isinstance(prop, hyperdb.String): raise TypeError, 'key properties must be String' self.key = propname def getkey(self): - '''Return the name of the key property for this class or None.''' + """Return the name of the key property for this class or None.""" return self.key # TODO: set up a separate index db file for this? profile? def lookup(self, keyvalue): - '''Locate a particular node by its key property and return its id. + """Locate a particular node by its key property and return its id. If this class has no key property, a TypeError is raised. If the 'keyvalue' matches one of the values for the key property among the nodes in this class, the matching node's id is returned; otherwise a KeyError is raised. - ''' + """ if not self.key: raise TypeError, 'No key property set for class %s'%self.classname cldb = self.db.getclassdb(self.classname) @@ -1404,7 +1403,7 @@ # change from spec - allows multiple props to match def find(self, **propspec): - '''Get the ids of nodes in this class which link to the given nodes. + """Get the ids of nodes in this class which link to the given nodes. 'propspec' consists of keyword args propname=nodeid or propname={nodeid:1, } @@ -1417,7 +1416,7 @@ db.issue.find(messages='1') db.issue.find(messages={'1':1,'3':1}, files={'7':1}) - ''' + """ propspec = propspec.items() for propname, itemids in propspec: # check the prop is OK @@ -1464,13 +1463,13 @@ return l def stringFind(self, **requirements): - '''Locate a particular node by matching a set of its String + """Locate a particular node by matching a set of its String properties in a caseless search. If the property is not a String property, a TypeError is raised. The return is a list of the id of all nodes that match. - ''' + """ for propname in requirements.keys(): prop = self.properties[propname] if not isinstance(prop, hyperdb.String): @@ -1495,8 +1494,8 @@ return l def list(self): - ''' Return a list of the ids of the active nodes in this class. - ''' + """ Return a list of the ids of the active nodes in this class. + """ l = [] cn = self.classname cldb = self.db.getclassdb(cn) @@ -1512,11 +1511,11 @@ return l def getnodeids(self, db=None, retired=None): - ''' Return a list of ALL nodeids + """ Return a list of ALL nodeids Set retired=None to get all nodes. Otherwise it'll get all the retired or non-retired nodes, depending on the flag. - ''' + """ res = [] # start off with the new nodes @@ -1561,7 +1560,7 @@ "sort" and "group" are (dir, prop) where dir is '+', '-' or None and prop is a prop name or None - "search_matches" is {nodeid: marker} or None + "search_matches" is a sequence type or None The filter must match all properties specificed. If the property value to match is a list: @@ -1721,7 +1720,7 @@ if search_matches is not None: k = [] for v in matches: - if search_matches.has_key(v[0]): + if v[0] in search_matches: k.append(v) matches = k @@ -1811,18 +1810,18 @@ return matches def count(self): - '''Get the number of nodes in this class. + """Get the number of nodes in this class. If the returned integer is 'numnodes', the ids of all the nodes in this class run from 1 to numnodes, and numnodes+1 will be the id of the next node to be created in this class. - ''' + """ return self.db.countnodes(self.classname) # Manipulating properties: def getprops(self, protected=1): - '''Return a dictionary mapping property names to property objects. + """Return a dictionary mapping property names to property objects. If the "protected" flag is true, we include protected properties - those which may not be modified. @@ -1830,7 +1829,7 @@ methods provide the "creation" and "activity" properties. If the "protected" flag is true, we include protected properties - those which may not be modified. - ''' + """ d = self.properties.copy() if protected: d['id'] = hyperdb.String() @@ -1841,20 +1840,20 @@ return d def addprop(self, **properties): - '''Add properties to this class. + """Add properties to this class. The keyword arguments in 'properties' must map names to property objects, or a TypeError is raised. None of the keys in 'properties' may collide with the names of existing properties, or a ValueError is raised before any properties have been added. - ''' + """ for key in properties.keys(): if self.properties.has_key(key): raise ValueError, key self.properties.update(properties) def index(self, nodeid): - ''' Add (or refresh) the node to search indexes ''' + """ Add (or refresh) the node to search indexes """ # find all the String properties that have indexme for prop, propclass in self.getprops().items(): if isinstance(propclass, hyperdb.String) and propclass.indexme: @@ -1870,9 +1869,9 @@ # import / export support # def export_list(self, propnames, nodeid): - ''' Export a node - generate a list of CSV-able data in the order + """ Export a node - generate a list of CSV-able data in the order specified by propnames for the given node. - ''' + """ properties = self.getprops() l = [] for prop in propnames: @@ -1895,13 +1894,13 @@ return l def import_list(self, propnames, proplist): - ''' Import a node - all information including "id" is present and + """ Import a node - all information including "id" is present and should not be sanity checked. Triggers are not triggered. The journal should be initialised using the "creator" and "created" information. Return the nodeid of the node imported. - ''' + """ if self.db.journaltag is None: raise hyperdb.DatabaseError, _('Database open read-only') properties = self.getprops() @@ -1949,13 +1948,13 @@ return newid def export_journals(self): - '''Export a class's journal - generate a list of lists of + """Export a class's journal - generate a list of lists of CSV-able data: nodeid, date, user, action, params No heading here - the columns are fixed. - ''' + """ properties = self.getprops() r = [] for nodeid in self.getnodeids(): @@ -1989,9 +1988,9 @@ return r def import_journals(self, entries): - '''Import a class's journal. + """Import a class's journal. - Uses setjournal() to set the journal for each item.''' + Uses setjournal() to set the journal for each item.""" properties = self.getprops() d = {} for l in entries: @@ -2021,18 +2020,18 @@ self.db.setjournal(self.classname, nodeid, l) class FileClass(hyperdb.FileClass, Class): - '''This class defines a large chunk of data. To support this, it has a + """This class defines a large chunk of data. To support this, it has a mandatory String property "content" which is typically saved off externally to the hyperdb. The default MIME type of this data is defined by the "default_mime_type" class attribute, which may be overridden by each node if the class defines a "type" String property. - ''' + """ def __init__(self, db, classname, **properties): - '''The newly-created class automatically includes the "content" + """The newly-created class automatically includes the "content" and "type" properties. - ''' + """ if not properties.has_key('content'): properties['content'] = hyperdb.String(indexme='yes') if not properties.has_key('type'): @@ -2040,8 +2039,8 @@ Class.__init__(self, db, classname, **properties) def create(self, **propvalues): - ''' Snarf the "content" propvalue and store in a file - ''' + """ Snarf the "content" propvalue and store in a file + """ # we need to fire the auditors now, or the content property won't # be in propvalues for the auditors to play with self.fireAuditors('create', None, propvalues) @@ -2056,18 +2055,19 @@ # do the database create newid = self.create_inner(**propvalues) + # store off the content as a file + self.db.storefile(self.classname, newid, None, content) + # fire reactors self.fireReactors('create', newid, None) - # store off the content as a file - self.db.storefile(self.classname, newid, None, content) return newid def get(self, nodeid, propname, default=_marker, cache=1): - ''' Trap the content propname and get it from the file + """ Trap the content propname and get it from the file 'cache' exists for backwards compatibility, and is not used. - ''' + """ poss_msg = 'Possibly an access right configuration problem.' if propname == 'content': try: @@ -2082,8 +2082,8 @@ return Class.get(self, nodeid, propname) def set(self, itemid, **propvalues): - ''' Snarf the "content" propvalue and update it in a file - ''' + """ Snarf the "content" propvalue and update it in a file + """ self.fireAuditors('set', itemid, propvalues) # create the oldvalues dict - fill in any missing values @@ -2120,10 +2120,10 @@ return propvalues def index(self, nodeid): - ''' Add (or refresh) the node to search indexes. + """ Add (or refresh) the node to search indexes. Use the content-type property for the content property. - ''' + """ # find all the String properties that have indexme for prop, propclass in self.getprops().items(): if prop == 'content' and propclass.indexme: @@ -2143,11 +2143,11 @@ class IssueClass(Class, roundupdb.IssueClass): # Overridden methods: def __init__(self, db, classname, **properties): - '''The newly-created class automatically includes the "messages", + """The newly-created class automatically includes the "messages", "files", "nosy", and "superseder" properties. If the 'properties' dictionary attempts to specify any of these properties or a "creation" or "activity" property, a ValueError is raised. - ''' + """ if not properties.has_key('title'): properties['title'] = hyperdb.String(indexme='yes') if not properties.has_key('messages'): Deleted: tracker/roundup-src/roundup/backends/back_metakit.py ============================================================================== Modified: tracker/roundup-src/roundup/backends/back_mysql.py ============================================================================== --- tracker/roundup-src/roundup/backends/back_mysql.py (original) +++ tracker/roundup-src/roundup/backends/back_mysql.py Sun Mar 15 22:43:30 2009 @@ -1,4 +1,3 @@ -#$Id: back_mysql.py,v 1.74 2007/10/26 01:34:43 richard Exp $ # # Copyright (c) 2003 Martynas Sklyzmantas, Andrey Lebedev # @@ -67,11 +66,10 @@ # stupid MySQL bug requires us to drop all the tables first for table in tables: command = 'DROP TABLE `%s`'%table[0] - if __debug__: - logging.getLogger('hyperdb').debug(command) + logging.debug(command) cursor.execute(command) command = "DROP DATABASE %s"%config.RDBMS_NAME - logging.getLogger('hyperdb').info(command) + logging.info(command) cursor.execute(command) conn.commit() conn.close() @@ -85,7 +83,7 @@ conn = MySQLdb.connect(**kwargs) cursor = conn.cursor() command = "CREATE DATABASE %s"%config.RDBMS_NAME - logging.getLogger('hyperdb').info(command) + logging.info(command) cursor.execute(command) conn.commit() conn.close() @@ -140,7 +138,7 @@ def sql_open_connection(self): kwargs = connection_dict(self.config, 'db') - logging.getLogger('hyperdb').info('open database %r'%(kwargs['db'],)) + self.log_info('open database %r'%(kwargs['db'],)) try: conn = MySQLdb.connect(**kwargs) except MySQLdb.OperationalError, message: @@ -299,7 +297,7 @@ # convert to new MySQL data type prop = properties[name] if v is not None: - e = self.hyperdb_to_sql_value[prop.__class__](v) + e = self.to_sql_value(prop.__class__)(v) else: e = None l.append(e) @@ -351,7 +349,7 @@ # re-create journal table self.create_journal_table(klass) - dc = self.hyperdb_to_sql_value[hyperdb.Date] + dc = self.to_sql_value(hyperdb.Date) for nodeid, journaldate, journaltag, action, params in olddata: self.save_journal(cn, cols, nodeid, dc(journaldate), journaltag, action, params) @@ -421,9 +419,19 @@ # TODO: create indexes on (selected?) Link property columns, as # they're more likely to be used for lookup + def add_class_key_required_unique_constraint(self, cn, key): + # mysql requires sizes on TEXT indexes + prop = self.classes[cn].getprops()[key] + if isinstance(prop, String): + sql = '''create unique index _%s_key_retired_idx + on _%s(__retired__, _%s(255))'''%(cn, cn, key) + else: + sql = '''create unique index _%s_key_retired_idx + on _%s(__retired__, _%s)'''%(cn, cn, key) + self.sql(sql) + def create_class_table_key_index(self, cn, key): - ''' create the class table for the given spec - ''' + # mysql requires sizes on TEXT indexes prop = self.classes[cn].getprops()[key] if isinstance(prop, String): sql = 'create index _%s_%s_idx on _%s(_%s(255))'%(cn, key, cn, key) @@ -534,7 +542,7 @@ def sql_commit(self, fail_ok=False): ''' Actually commit to the database. ''' - logging.getLogger('hyperdb').info('commit') + self.log_info('commit') # MySQL commits don't seem to ever fail, the latest update winning. # makes you wonder why they have transactions... @@ -548,7 +556,7 @@ self.sql("START TRANSACTION") def sql_close(self): - logging.getLogger('hyperdb').info('close') + self.log_info('close') try: self.conn.close() except MySQLdb.ProgrammingError, message: Modified: tracker/roundup-src/roundup/backends/back_postgresql.py ============================================================================== --- tracker/roundup-src/roundup/backends/back_postgresql.py (original) +++ tracker/roundup-src/roundup/backends/back_postgresql.py Sun Mar 15 22:43:30 2009 @@ -1,4 +1,4 @@ -#$Id: back_postgresql.py,v 1.43 2007/09/28 15:15:06 jpend Exp $ +#$Id: back_postgresql.py,v 1.44 2008-08-07 05:50:03 richard Exp $ # # Copyright (c) 2003 Martynas Sklyzmantas, Andrey Lebedev # @@ -177,7 +177,7 @@ self.sql('''CREATE TABLE __textids ( _textid integer primary key, _class VARCHAR(255), _itemid VARCHAR(255), _prop VARCHAR(255))''') - self.sql('''CREATE TABLE __words (_word VARCHAR(30), + self.sql('''CREATE TABLE __words (_word VARCHAR(30), _textid integer)''') self.sql('CREATE INDEX words_word_idx ON __words(_word)') self.sql('CREATE INDEX words_by_id ON __words (_textid)') @@ -261,7 +261,7 @@ def newid(self, classname): sql = "select nextval('_%s_ids') from dual"%classname self.sql(sql) - return self.cursor.fetchone()[0] + return str(self.cursor.fetchone()[0]) def setid(self, classname, setid): sql = "select setval('_%s_ids', %s) from dual"%(classname, int(setid)) Modified: tracker/roundup-src/roundup/backends/back_sqlite.py ============================================================================== --- tracker/roundup-src/roundup/backends/back_sqlite.py (original) +++ tracker/roundup-src/roundup/backends/back_sqlite.py Sun Mar 15 22:43:30 2009 @@ -1,12 +1,11 @@ -# $Id: back_sqlite.py,v 1.51 2007/06/21 07:35:50 schlatterbeck Exp $ -'''Implements a backend for SQLite. +"""Implements a backend for SQLite. See https://pysqlite.sourceforge.net/ for pysqlite info NOTE: we use the rdbms_common table creation methods which define datatypes for the columns, but sqlite IGNORES these specifications. -''' +""" __docformat__ = 'restructuredtext' import os, base64, marshal, shutil, time, logging @@ -90,10 +89,10 @@ return 1 def sql_open_connection(self): - '''Open a standard, non-autocommitting connection. + """Open a standard, non-autocommitting connection. pysqlite will automatically BEGIN TRANSACTION for us. - ''' + """ # make sure the database directory exists # database itself will be created by sqlite if needed if not os.path.isdir(self.config.DATABASE): @@ -109,6 +108,13 @@ else: conn = sqlite.connect(db, timeout=30) conn.row_factory = sqlite.Row + + # sqlite3 wants us to store Unicode in the db but that's not what's + # been done historically and it's definitely not what the other + # backends do, so we'll stick with UTF-8 + if sqlite_version == 3: + conn.text_factory = str + cursor = conn.cursor() return (conn, cursor) @@ -165,14 +171,14 @@ pass def update_class(self, spec, old_spec, force=0, adding_v2=0): - ''' Determine the differences between the current spec and the + """ Determine the differences between the current spec and the database version of the spec, and update where necessary. If 'force' is true, update the database anyway. SQLite doesn't have ALTER TABLE, so we have to copy and regenerate the tables with the new schema. - ''' + """ new_has = spec.properties.has_key new_spec = spec.schema() new_spec[1].sort() @@ -222,8 +228,8 @@ # re-create and populate the new table self.create_multilink_table(spec, propname) - sql = '''insert into %s (linkid, nodeid) values - (%s, %s)'''%(tn, self.arg, self.arg) + sql = """insert into %s (linkid, nodeid) values + (%s, %s)"""%(tn, self.arg, self.arg) for linkid, nodeid in rows: self.sql(sql, (int(linkid), int(nodeid))) elif old_has(propname): @@ -296,9 +302,9 @@ return 1 def sql_close(self): - ''' Squash any error caused by us already having closed the + """ Squash any error caused by us already having closed the connection. - ''' + """ try: self.conn.close() except sqlite.ProgrammingError, value: @@ -306,9 +312,9 @@ raise def sql_rollback(self): - ''' Squash any error caused by us having closed the connection (and + """ Squash any error caused by us having closed the connection (and therefore not having anything to roll back) - ''' + """ try: self.conn.rollback() except sqlite.ProgrammingError, value: @@ -319,10 +325,10 @@ return ''%id(self) def sql_commit(self, fail_ok=False): - ''' Actually commit to the database. + """ Actually commit to the database. Ignore errors if there's nothing to commit. - ''' + """ try: self.conn.commit() except sqlite.DatabaseError, error: @@ -340,8 +346,8 @@ # old-skool id generation def newid(self, classname): - ''' Generate a new id for the given class - ''' + """ Generate a new id for the given class + """ # get the next ID sql = 'select num from ids where name=%s'%self.arg self.sql(sql, (classname, )) @@ -356,10 +362,10 @@ return str(newid) def setid(self, classname, setid): - ''' Set the id counter: used during import of database + """ Set the id counter: used during import of database We add one to make it behave like the sequences in postgres. - ''' + """ sql = 'update ids set num=%s where name=%s'%(self.arg, self.arg) vals = (int(setid)+1, classname) self.sql(sql, vals) @@ -378,8 +384,8 @@ if sqlite_version in (2,3): def load_journal(self, classname, cols, nodeid): - '''We need to turn the sqlite3.Row into a tuple so it can be - unpacked''' + """We need to turn the sqlite3.Row into a tuple so it can be + unpacked""" l = rdbms_common.Database.load_journal(self, classname, cols, nodeid) cols = range(5) @@ -388,9 +394,9 @@ class sqliteClass: def filter(self, search_matches, filterspec, sort=(None,None), group=(None,None)): - ''' If there's NO matches to a fetch, sqlite returns NULL + """ If there's NO matches to a fetch, sqlite returns NULL instead of nothing - ''' + """ return filter(None, rdbms_common.Class.filter(self, search_matches, filterspec, sort=sort, group=group)) Modified: tracker/roundup-src/roundup/backends/back_tsearch2.py ============================================================================== --- tracker/roundup-src/roundup/backends/back_tsearch2.py (original) +++ tracker/roundup-src/roundup/backends/back_tsearch2.py Sun Mar 15 22:43:30 2009 @@ -1,4 +1,4 @@ -#$Id: back_tsearch2.py,v 1.9 2005/01/08 16:16:59 jlgijsbers Exp $ +#$Id: back_tsearch2.py,v 1.9 2005-01-08 16:16:59 jlgijsbers Exp $ # Note: this backend is EXPERIMENTAL. Do not use if you value your data. import re Modified: tracker/roundup-src/roundup/backends/blobfiles.py ============================================================================== --- tracker/roundup-src/roundup/backends/blobfiles.py (original) +++ tracker/roundup-src/roundup/backends/blobfiles.py Sun Mar 15 22:43:30 2009 @@ -15,10 +15,9 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -#$Id: blobfiles.py,v 1.24 2008/02/07 00:57:59 richard Exp $ -'''This module exports file storage for roundup backends. +"""This module exports file storage for roundup backends. Files are stored into a directory hierarchy. -''' +""" __docformat__ = 'restructuredtext' import os @@ -232,14 +231,28 @@ return filename + self.tempext + def _editInProgress(self, classname, nodeid, property): + """Return true if the file indicated is being edited. + + returns -- True if the current transaction includes an edit to + the file indicated.""" + + for method, args in self.transactions: + if (method == self.doStoreFile and + args == (classname, nodeid, property)): + return True + + return False + + def filename(self, classname, nodeid, property=None, create=0): - '''Determine what the filename for the given node and optionally + """Determine what the filename for the given node and optionally property is. Try a variety of different filenames - the file could be in the usual place, or it could be in a temp file pre-commit *or* it could be in an old-style, backwards-compatible flat directory. - ''' + """ filename = os.path.join(self.dir, 'files', classname, self.subdirFilename(classname, nodeid, property)) # If the caller is going to create the file, return the @@ -252,13 +265,10 @@ # If an edit to this file is in progress, then return the name # of the temporary file containing the edited content. - for method, args in self.transactions: - if (method == self.doStoreFile and - args == (classname, nodeid, property)): - # There is an edit in progress for this file. - if not os.path.exists(tempfile): - raise IOError('content file for %s not found'%tempfile) - return tempfile + if self._editInProgress(classname, nodeid, property): + if not os.path.exists(tempfile): + raise IOError('content file for %s not found'%tempfile) + return tempfile if os.path.exists(filename): return filename @@ -295,10 +305,10 @@ raise IOError('content file for %s not found'%filename) def storefile(self, classname, nodeid, property, content): - '''Store the content of the file in the database. The property may be + """Store the content of the file in the database. The property may be None, in which case the filename does not indicate which property is being saved. - ''' + """ # determine the name of the file to write to name = self.filename(classname, nodeid, property, create=1) @@ -310,7 +320,7 @@ name = self._tempfile(name) # make sure we don't register the rename action more than once - if not os.path.exists(name): + if not self._editInProgress(classname, nodeid, property): # save off the rename action self.transactions.append((self.doStoreFile, (classname, nodeid, property))) @@ -321,8 +331,8 @@ open(name, 'wb').write(content) def getfile(self, classname, nodeid, property): - '''Get the content of the file in the database. - ''' + """Get the content of the file in the database. + """ filename = self.filename(classname, nodeid, property) f = open(filename, 'rb') @@ -333,14 +343,14 @@ f.close() def numfiles(self): - '''Get number of files in storage, even across subdirectories. - ''' + """Get number of files in storage, even across subdirectories. + """ files_dir = os.path.join(self.dir, 'files') return files_in_dir(files_dir) def doStoreFile(self, classname, nodeid, property, **databases): - '''Store the file as part of a transaction commit. - ''' + """Store the file as part of a transaction commit. + """ # determine the name of the file to write to name = self.filename(classname, nodeid, property, 1) @@ -364,8 +374,8 @@ return (classname, nodeid) def rollbackStoreFile(self, classname, nodeid, property, **databases): - '''Remove the temp file as a part of a rollback - ''' + """Remove the temp file as a part of a rollback + """ # determine the name of the file to delete name = self.filename(classname, nodeid, property) if not name.endswith(self.tempext): @@ -373,9 +383,9 @@ os.remove(name) def isStoreFile(self, classname, nodeid): - '''See if there is actually any FileStorage for this node. + """See if there is actually any FileStorage for this node. Is there a better way than using self.filename? - ''' + """ try: fname = self.filename(classname, nodeid) return True @@ -383,9 +393,9 @@ return False def destroy(self, classname, nodeid): - '''If there is actually FileStorage for this node + """If there is actually FileStorage for this node remove it from the filesystem - ''' + """ if self.isStoreFile(classname, nodeid): os.remove(self.filename(classname, nodeid)) Modified: tracker/roundup-src/roundup/backends/indexer_common.py ============================================================================== --- tracker/roundup-src/roundup/backends/indexer_common.py (original) +++ tracker/roundup-src/roundup/backends/indexer_common.py Sun Mar 15 22:43:30 2009 @@ -1,5 +1,7 @@ -#$Id: indexer_common.py,v 1.8 2006/11/11 03:01:54 richard Exp $ -import re, sets +#$Id: indexer_common.py,v 1.11 2008-09-11 19:41:07 schlatterbeck Exp $ +import re +# Python 2.3 ... 2.6 compatibility: +from roundup.anypy.sets_ import set from roundup import hyperdb @@ -8,7 +10,7 @@ "FOR", "IF", "IN", "INTO", "IS", "IT", "NO", "NOT", "OF", "ON", "OR", "SUCH", "THAT", "THE", "THEIR", "THEN", "THERE", "THESE", - "THEY", "THIS", "TO", "WAS", "WILL", "WITH" + "THEY", "THIS", "TO", "WAS", "WILL", "WITH" ] def _isLink(propclass): @@ -17,7 +19,7 @@ class Indexer: def __init__(self, db): - self.stopwords = sets.Set(STOPWORDS) + self.stopwords = set(STOPWORDS) for word in db.config[('main', 'indexer_stopwords')]: self.stopwords.add(word) @@ -26,13 +28,13 @@ def getHits(self, search_terms, klass): return self.find(search_terms) - + def search(self, search_terms, klass, ignore={}): - '''Display search results looking for [search, terms] associated + """Display search results looking for [search, terms] associated with the hyperdb Class "klass". Ignore hits on {class: property}. "dre" is a helper, not an argument. - ''' + """ # do the index lookup hits = self.getHits(search_terms, klass) if not hits: @@ -61,7 +63,9 @@ continue # if it's a property on klass, it's easy - nodeid = entry[1] + # (make sure the nodeid is str() not unicode() as returned by some + # backends as that can cause problems down the track) + nodeid = str(entry[1]) if classname == klass.classname: if not nodeids.has_key(nodeid): nodeids[nodeid] = {} @@ -81,14 +85,21 @@ del propspec[propname] # klass.find tells me the klass nodeids the linked nodes relate to + propdefs = klass.getprops() for resid in klass.find(**propspec): resid = str(resid) - if not nodeids.has_key(id): - nodeids[resid] = {} + if resid in nodeids: + continue # we ignore duplicate resids + nodeids[resid] = {} node_dict = nodeids[resid] # now figure out where it came from for linkprop in propspec.keys(): - for nodeid in klass.get(resid, linkprop): + v = klass.get(resid, linkprop) + # the link might be a Link so deal with a single result or None + if isinstance(propdefs[linkprop], hyperdb.Link): + if v is None: continue + v = [v] + for nodeid in v: if propspec[linkprop].has_key(nodeid): # OK, this node[propname] has a winner if not node_dict.has_key(linkprop): Modified: tracker/roundup-src/roundup/backends/indexer_dbm.py ============================================================================== --- tracker/roundup-src/roundup/backends/indexer_dbm.py (original) +++ tracker/roundup-src/roundup/backends/indexer_dbm.py Sun Mar 15 22:43:30 2009 @@ -14,7 +14,7 @@ # that promote freedom, but obviously am giving up any rights # to compel such. # -#$Id: indexer_dbm.py,v 1.9 2006/04/27 05:48:26 richard Exp $ +#$Id: indexer_dbm.py,v 1.9 2006-04-27 05:48:26 richard Exp $ '''This module provides an indexer class, RoundupIndexer, that stores text indices in a roundup instance. This class makes searching the content of messages, string properties and text files possible. Modified: tracker/roundup-src/roundup/backends/indexer_rdbms.py ============================================================================== --- tracker/roundup-src/roundup/backends/indexer_rdbms.py (original) +++ tracker/roundup-src/roundup/backends/indexer_rdbms.py Sun Mar 15 22:43:30 2009 @@ -1,9 +1,11 @@ -#$Id: indexer_rdbms.py,v 1.15 2006/10/04 01:12:00 richard Exp $ -''' This implements the full-text indexer over two RDBMS tables. The first +#$Id: indexer_rdbms.py,v 1.18 2008-09-01 00:43:02 richard Exp $ +""" This implements the full-text indexer over two RDBMS tables. The first is a mapping of words to occurance IDs. The second maps the IDs to (Class, propname, itemid) instances. -''' -import re, sets +""" +import re +# Python 2.3 ... 2.6 compatibility: +from roundup.anypy.sets_ import set from roundup.backends.indexer_common import Indexer as IndexerBase @@ -14,30 +16,35 @@ self.reindex = 0 def close(self): - '''close the indexing database''' + """close the indexing database""" # just nuke the circular reference self.db = None def save_index(self): - '''Save the changes to the index.''' + """Save the changes to the index.""" # not necessary - the RDBMS connection will handle this for us pass def force_reindex(self): - '''Force a reindexing of the database. This essentially + """Force a reindexing of the database. This essentially empties the tables ids and index and sets a flag so - that the databases are reindexed''' + that the databases are reindexed""" self.reindex = 1 def should_reindex(self): - '''returns True if the indexes need to be rebuilt''' + """returns True if the indexes need to be rebuilt""" return self.reindex def add_text(self, identifier, text, mime_type='text/plain'): - ''' "identifier" is (classname, itemid, property) ''' + """ "identifier" is (classname, itemid, property) """ if mime_type != 'text/plain': return + # Ensure all elements of the identifier are strings 'cos the itemid + # column is varchar even if item ids may be numbers elsewhere in the + # code. ugh. + identifier = tuple(map(str, identifier)) + # first, find the id of the (classname, itemid, property) a = self.db.arg sql = 'select _textid from __textids where _class=%s and '\ @@ -58,9 +65,9 @@ # ok, find all the unique words in the text text = unicode(text, "utf-8", "replace").upper() - wordlist = [w.encode("utf-8", "replace") - for w in re.findall(r'(?u)\b\w{2,25}\b', text)] - words = sets.Set() + wordlist = [w.encode("utf-8") + for w in re.findall(r'(?u)\b\w{2,25}\b', text)] + words = set() for word in wordlist: if self.is_stopword(word): continue if len(word) > 25: continue @@ -72,17 +79,17 @@ self.db.cursor.executemany(sql, words) def find(self, wordlist): - '''look up all the words in the wordlist. + """look up all the words in the wordlist. If none are found return an empty dictionary * more rules here - ''' + """ if not wordlist: - return {} + return [] l = [word.upper() for word in wordlist if 26 > len(word) > 2] if not l: - return {} + return [] if self.db.implements_intersect: # simple AND search @@ -91,7 +98,7 @@ self.db.cursor.execute(sql, tuple(l)) r = self.db.cursor.fetchall() if not r: - return {} + return [] a = ','.join([self.db.arg] * len(r)) sql = 'select _class, _itemid, _prop from __textids '\ 'where _textid in (%s)'%a @@ -120,7 +127,7 @@ r = map(lambda x: x[0], self.db.cursor.fetchall()) if not r: - return {} + return [] a = ','.join([self.db.arg] * len(r)) sql = 'select _class, _itemid, _prop from __textids '\ Modified: tracker/roundup-src/roundup/backends/indexer_xapian.py ============================================================================== --- tracker/roundup-src/roundup/backends/indexer_xapian.py (original) +++ tracker/roundup-src/roundup/backends/indexer_xapian.py Sun Mar 15 22:43:30 2009 @@ -1,4 +1,4 @@ -#$Id: indexer_xapian.py,v 1.6 2007/10/25 07:02:42 richard Exp $ +#$Id: indexer_xapian.py,v 1.6 2007-10-25 07:02:42 richard Exp $ ''' This implements the full-text indexer using the Xapian indexer. ''' import re, os Modified: tracker/roundup-src/roundup/backends/locking.py ============================================================================== --- tracker/roundup-src/roundup/backends/locking.py (original) +++ tracker/roundup-src/roundup/backends/locking.py Sun Mar 15 22:43:30 2009 @@ -19,7 +19,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -# $Id: locking.py,v 1.8 2004/02/11 23:55:09 richard Exp $ +# $Id: locking.py,v 1.8 2004-02-11 23:55:09 richard Exp $ '''This module provides a generic interface to acquire and release exclusive access to a file. Modified: tracker/roundup-src/roundup/backends/portalocker.py ============================================================================== --- tracker/roundup-src/roundup/backends/portalocker.py (original) +++ tracker/roundup-src/roundup/backends/portalocker.py Sun Mar 15 22:43:30 2009 @@ -2,7 +2,7 @@ # Requires python 1.5.2 or better. # ID line added by richard for Roundup file tracking -# $Id: portalocker.py,v 1.9 2006/09/09 05:42:45 richard Exp $ +# $Id: portalocker.py,v 1.9 2006-09-09 05:42:45 richard Exp $ """Cross-platform (posix/nt) API for flock-style file locking. Modified: tracker/roundup-src/roundup/backends/rdbms_common.py ============================================================================== --- tracker/roundup-src/roundup/backends/rdbms_common.py (original) +++ tracker/roundup-src/roundup/backends/rdbms_common.py Sun Mar 15 22:43:30 2009 @@ -15,7 +15,6 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -#$Id: rdbms_common.py,v 1.195 2008/02/07 05:01:42 richard Exp $ """ Relational database (SQL) backend common code. Basics: @@ -72,9 +71,6 @@ from sessions_rdbms import Sessions, OneTimeKeys from roundup.date import Range -# number of rows to keep in memory -ROW_CACHE_SIZE = 100 - # dummy value meaning "argument not passed" _marker = [] @@ -109,7 +105,7 @@ - some functionality is specific to the actual SQL database, hence the sql_* methods that are NotImplemented - - we keep a cache of the latest ROW_CACHE_SIZE row fetches. + - we keep a cache of the latest N row fetches (where N is configurable). """ def __init__(self, config, journaltag=None): """ Open the database and load the schema from it. @@ -126,6 +122,7 @@ # keep a cache of the N most recently retrieved rows of any kind # (classname, nodeid) = row + self.cache_size = config.RDBMS_CACHE_SIZE self.cache = {} self.cache_lru = [] self.stats = {'cache_hits': 0, 'cache_misses': 0, 'get_items': 0, @@ -157,8 +154,7 @@ def sql(self, sql, args=None): """ Execute the sql with the optional args. """ - if __debug__: - logging.getLogger('hyperdb').debug('SQL %r %r'%(sql, args)) + self.log_debug('SQL %r %r'%(sql, args)) if args: self.cursor.execute(sql, args) else: @@ -254,13 +250,15 @@ Return boolean whether we need to save the schema. """ version = self.database_schema.get('version', 1) + if version > self.current_db_version: + raise DatabaseError('attempting to run rev %d DATABASE with rev ' + '%d CODE!'%(version, self.current_db_version)) if version == self.current_db_version: # nothing to do return 0 if version < 2: - if __debug__: - logging.getLogger('hyperdb').info('upgrade to version 2') + self.log_info('upgrade to version 2') # change the schema structure self.database_schema = {'tables': self.database_schema} @@ -273,8 +271,7 @@ self.create_version_2_tables() if version < 3: - if __debug__: - logging.getLogger('hyperdb').info('upgrade to version 3') + self.log_info('upgrade to version 3') self.fix_version_2_tables() if version < 4: @@ -388,6 +385,19 @@ hyperdb.Boolean : 'BOOLEAN', hyperdb.Number : 'REAL', } + + def hyperdb_to_sql_datatype(self, propclass): + + datatype = self.hyperdb_to_sql_datatypes.get(propclass) + if datatype: + return datatype + + for k, v in self.hyperdb_to_sql_datatypes.iteritems(): + if issubclass(propclass, k): + return v + + raise ValueError, '%r is not a hyperdb property class' % propclass + def determine_columns(self, properties): """ Figure the column names and multilink properties from the spec @@ -395,10 +405,10 @@ instance of a hyperdb "type" _or_ a string repr of that type. """ cols = [ - ('_actor', self.hyperdb_to_sql_datatypes[hyperdb.Link]), - ('_activity', self.hyperdb_to_sql_datatypes[hyperdb.Date]), - ('_creator', self.hyperdb_to_sql_datatypes[hyperdb.Link]), - ('_creation', self.hyperdb_to_sql_datatypes[hyperdb.Date]), + ('_actor', self.hyperdb_to_sql_datatype(hyperdb.Link)), + ('_activity', self.hyperdb_to_sql_datatype(hyperdb.Date)), + ('_creator', self.hyperdb_to_sql_datatype(hyperdb.Link)), + ('_creation', self.hyperdb_to_sql_datatype(hyperdb.Date)), ] mls = [] # add the multilinks separately @@ -412,7 +422,7 @@ #and prop.find('Multilink') != -1: #mls.append(col) - datatype = self.hyperdb_to_sql_datatypes[prop.__class__] + datatype = self.hyperdb_to_sql_datatype(prop.__class__) cols.append(('_'+col, datatype)) # Intervals stored as two columns @@ -490,7 +500,7 @@ self.create_multilink_table(spec, propname) else: # add the column - coltype = self.hyperdb_to_sql_datatypes[prop.__class__] + coltype = self.hyperdb_to_sql_datatype(prop.__class__) sql = 'alter table _%s add column _%s %s'%( spec.classname, propname, coltype) self.sql(sql) @@ -562,7 +572,7 @@ # they're more likely to be used for lookup def add_class_key_required_unique_constraint(self, cn, key): - sql = '''create unique index _%s_key_retired_idx + sql = '''create unique index _%s_key_retired_idx on _%s(__retired__, _%s)'''%(cn, cn, key) self.sql(sql) @@ -608,7 +618,7 @@ sql = """create table %s__journal ( nodeid integer, date %s, tag varchar(255), action varchar(255), params text)""" % (spec.classname, - self.hyperdb_to_sql_datatypes[hyperdb.Date]) + self.hyperdb_to_sql_datatype(hyperdb.Date)) self.sql(sql) self.create_journal_table_indexes(spec) @@ -769,12 +779,24 @@ hyperdb.Number : lambda x: x, hyperdb.Multilink : lambda x: x, # used in journal marshalling } + + def to_sql_value(self, propklass): + + fn = self.hyperdb_to_sql_value.get(propklass) + if fn: + return fn + + for k, v in self.hyperdb_to_sql_value.iteritems(): + if issubclass(propklass, k): + return v + + raise ValueError, '%r is not a hyperdb property class' % propklass + def addnode(self, classname, nodeid, node): """ Add the specified node to its class's db. """ - if __debug__: - logging.getLogger('hyperdb').debug('addnode %s%s %r'%(classname, - nodeid, node)) + self.log_debug('addnode %s%s %r'%(classname, + nodeid, node)) # determine the column definitions and multilink tables cl = self.classes[classname] @@ -823,7 +845,7 @@ prop = props[col[1:]] value = values[col[1:]] if value is not None: - value = self.hyperdb_to_sql_value[prop.__class__](value) + value = self.to_sql_value(prop.__class__)(value) vals.append(value) vals.append(nodeid) vals = tuple(vals) @@ -847,9 +869,8 @@ def setnode(self, classname, nodeid, values, multilink_changes={}): """ Change the specified node. """ - if __debug__: - logging.getLogger('hyperdb').debug('setnode %s%s %r' - % (classname, nodeid, values)) + self.log_debug('setnode %s%s %r' + % (classname, nodeid, values)) # clear this node out of the cache if it's in there key = (classname, nodeid) @@ -895,7 +916,7 @@ if value is None: e = None else: - e = self.hyperdb_to_sql_value[prop.__class__](value) + e = self.to_sql_value(prop.__class__)(value) vals.append(e) vals.append(int(nodeid)) @@ -941,11 +962,11 @@ # XXX numeric ids self.sql(sql, (int(nodeid), int(addid))) if remove: - sql = 'delete from %s where nodeid=%s and linkid=%s'%(tn, - self.arg, self.arg) - for removeid in remove: - # XXX numeric ids - self.sql(sql, (int(nodeid), int(removeid))) + s = ','.join([self.arg]*len(remove)) + sql = 'delete from %s where nodeid=%s and linkid in (%s)'%(tn, + self.arg, s) + # XXX numeric ids + self.sql(sql, [int(nodeid)] + remove) sql_to_hyperdb_value = { hyperdb.String : str, @@ -958,6 +979,19 @@ hyperdb.Number : _num_cvt, hyperdb.Multilink : lambda x: x, # used in journal marshalling } + + def to_hyperdb_value(self, propklass): + + fn = self.sql_to_hyperdb_value.get(propklass) + if fn: + return fn + + for k, v in self.sql_to_hyperdb_value.iteritems(): + if issubclass(propklass, k): + return v + + raise ValueError, '%r is not a hyperdb property class' % propklass + def getnode(self, classname, nodeid): """ Get a node from the database. """ @@ -1000,7 +1034,7 @@ continue value = values[col] if value is not None: - value = self.sql_to_hyperdb_value[props[name].__class__](value) + value = self.to_hyperdb_value(props[name].__class__)(value) node[name] = value @@ -1009,7 +1043,7 @@ # get the link ids sql = 'select linkid from %s_%s where nodeid=%s'%(classname, col, self.arg) - self.cursor.execute(sql, (nodeid,)) + self.sql(sql, (nodeid,)) # extract the first column from the result # XXX numeric ids items = [int(x[0]) for x in self.cursor.fetchall()] @@ -1021,7 +1055,7 @@ self.cache[key] = node # update the LRU self.cache_lru.insert(0, key) - if len(self.cache_lru) > ROW_CACHE_SIZE: + if len(self.cache_lru) > self.cache_size: del self.cache[self.cache_lru.pop()] if __debug__: @@ -1070,6 +1104,12 @@ def hasnode(self, classname, nodeid): """ Determine if the database has a given node. """ + # If this node is in the cache, then we do not need to go to + # the database. (We don't consider this an LRU hit, though.) + if self.cache.has_key((classname, nodeid)): + # Return 1, not True, to match the type of the result of + # the SQL operation below. + return 1 sql = 'select count(*) from _%s where id=%s'%(classname, self.arg) self.sql(sql, (nodeid,)) return int(self.cursor.fetchone()[0]) @@ -1104,9 +1144,8 @@ # create the journal entry cols = 'nodeid,date,tag,action,params' - if __debug__: - logging.getLogger('hyperdb').debug('addjournal %s%s %r %s %s %r'%(classname, - nodeid, journaldate, journaltag, action, params)) + self.log_debug('addjournal %s%s %r %s %s %r'%(classname, + nodeid, journaldate, journaltag, action, params)) # make the journalled data marshallable if isinstance(params, type({})): @@ -1114,7 +1153,7 @@ params = repr(params) - dc = self.hyperdb_to_sql_value[hyperdb.Date] + dc = self.to_sql_value(hyperdb.Date) journaldate = dc(journaldate) self.save_journal(classname, cols, nodeid, journaldate, @@ -1129,12 +1168,11 @@ # create the journal entry cols = 'nodeid,date,tag,action,params' - dc = self.hyperdb_to_sql_value[hyperdb.Date] + dc = self.to_sql_value(hyperdb.Date) for nodeid, journaldate, journaltag, action, params in journal: - if __debug__: - logging.getLogger('hyperdb').debug('addjournal %s%s %r %s %s %r'%( - classname, nodeid, journaldate, journaltag, action, - params)) + self.log_debug('addjournal %s%s %r %s %s %r'%( + classname, nodeid, journaldate, journaltag, action, + params)) # make the journalled data marshallable if isinstance(params, type({})): @@ -1152,7 +1190,7 @@ if not value: continue property = properties[param] - cvt = self.hyperdb_to_sql_value[property.__class__] + cvt = self.to_sql_value(property.__class__) if isinstance(property, Password): params[param] = cvt(value) elif isinstance(property, Date): @@ -1173,7 +1211,7 @@ journal = self.load_journal(classname, cols, nodeid) # now unmarshal the data - dc = self.sql_to_hyperdb_value[hyperdb.Date] + dc = self.to_hyperdb_value(hyperdb.Date) res = [] properties = self.getclass(classname).getprops() for nodeid, date_stamp, user, action, params in journal: @@ -1186,7 +1224,7 @@ if property is None: # deleted property continue - cvt = self.sql_to_hyperdb_value[property.__class__] + cvt = self.to_hyperdb_value(property.__class__) if isinstance(property, Password): params[param] = cvt(value) elif isinstance(property, Date): @@ -1223,7 +1261,7 @@ def pack(self, pack_before): """ Delete all journal entries except "create" before 'pack_before'. """ - date_stamp = self.hyperdb_to_sql_value[Date](pack_before) + date_stamp = self.to_sql_value(Date)(pack_before) # do the delete for classname in self.classes.keys(): @@ -1702,10 +1740,17 @@ # handle additions for id in value: - if not self.db.getclass(link_class).hasnode(id): - raise IndexError, '%s has no node %s'%(link_class, id) if id in l: continue + # We can safely check this condition after + # checking that this is an addition to the + # multilink since the condition was checked for + # existing entries at the point they were added to + # the multilink. Since the hasnode call will + # result in a SQL query, it is more efficient to + # avoid the check if possible. + if not self.db.getclass(link_class).hasnode(id): + raise IndexError, '%s has no node %s'%(link_class, id) # register the link with the newly linked node if self.do_journal and self.properties[propname].do_journal: self.db.addjournal(link_class, id, 'link', @@ -1920,7 +1965,7 @@ # sqlite) sql = "select id from _%s where _%s=%s and __retired__=%s"%( self.classname, self.key, self.db.arg, self.db.arg) - self.db.sql(sql, (keyvalue, 0)) + self.db.sql(sql, (str(keyvalue), 0)) # see if there was a result that's not retired row = self.db.sql_fetchone() @@ -2099,7 +2144,7 @@ backward-compatibility reasons a single (dir, prop) tuple is also allowed. - "search_matches" is {nodeid: marker} or None + "search_matches" is a container type or None The filter must match all properties specificed. If the property value to match is a list: @@ -2108,7 +2153,7 @@ 2. Other properties must match any of the elements in the list. """ # we can't match anything if search_matches is empty - if search_matches == {}: + if not search_matches and search_matches is not None: return [] if __debug__: @@ -2160,7 +2205,7 @@ if p.sort_type < 2: mlfilt = 1 tn = '%s_%s'%(pcn, k) - if v in ('-1', ['-1']): + if v in ('-1', ['-1'], []): # only match rows that have count(linkid)=0 in the # corresponding multilink table) where.append(self._subselect(pcn, tn)) @@ -2223,7 +2268,7 @@ d[entry] = entry l = [] if d.has_key(None) or not d: - if d.has_key(None):del d[None] + if d.has_key(None): del d[None] l.append('_%s._%s is NULL'%(pln, k)) if d: v = d.keys() @@ -2249,7 +2294,7 @@ cn, ln, pln, k, ln)) oc = '_%s._%s'%(ln, lp) elif isinstance(propclass, Date) and p.sort_type < 2: - dc = self.db.hyperdb_to_sql_value[hyperdb.Date] + dc = self.db.to_sql_value(hyperdb.Date) if isinstance(v, type([])): s = ','.join([a for x in v]) where.append('_%s._%s in (%s)'%(pln, k, s)) @@ -2319,8 +2364,7 @@ # add results of full text search if search_matches is not None: - v = search_matches.keys() - s = ','.join([a for x in v]) + s = ','.join([a for x in search_matches]) where.append('_%s.id in (%s)'%(icn, s)) args = args + v @@ -2656,11 +2700,12 @@ self.db.indexer.add_text((self.classname, newid, 'content'), content, mime_type) + # store off the content as a file + self.db.storefile(self.classname, newid, None, content) + # fire reactors self.fireReactors('create', newid, None) - # store off the content as a file - self.db.storefile(self.classname, newid, None, content) return newid def get(self, nodeid, propname, default=_marker, cache=1): Modified: tracker/roundup-src/roundup/backends/sessions_dbm.py ============================================================================== --- tracker/roundup-src/roundup/backends/sessions_dbm.py (original) +++ tracker/roundup-src/roundup/backends/sessions_dbm.py Sun Mar 15 22:43:30 2009 @@ -1,4 +1,4 @@ -#$Id: sessions_dbm.py,v 1.9 2007/09/27 06:18:53 jpend Exp $ +#$Id: sessions_dbm.py,v 1.10 2008-08-18 05:04:01 richard Exp $ """This module defines a very basic store that's used by the CGI interface to store session and one-time-key information. @@ -139,15 +139,15 @@ if sess is None or now > sess + 60: self.set(sessid, __timestamp=now) - def clean(self, now): - """Age sessions, remove when they haven't been used for a week. - """ + def clean(self): + ''' Remove session records that haven't been used for a week. ''' + now = time.time() week = 60*60*24*7 for sessid in self.list(): sess = self.get(sessid, '__timestamp', None) if sess is None: - sess=time.time() self.updateTimestamp(sessid) + continue interval = now - sess if interval > week: self.destroy(sessid) Modified: tracker/roundup-src/roundup/backends/sessions_rdbms.py ============================================================================== --- tracker/roundup-src/roundup/backends/sessions_rdbms.py (original) +++ tracker/roundup-src/roundup/backends/sessions_rdbms.py Sun Mar 15 22:43:30 2009 @@ -1,4 +1,4 @@ -#$Id: sessions_rdbms.py,v 1.7 2007/09/25 19:49:19 jpend Exp $ +#$Id: sessions_rdbms.py,v 1.8 2008-08-18 05:04:01 richard Exp $ """This module defines a very basic store that's used by the CGI interface to store session and one-time-key information. @@ -84,10 +84,11 @@ self.name, self.db.arg, self.name, self.db.arg), (now, infoid, now-60)) - def clean(self, now): - """Age sessions, remove when they haven't been used for a week. - """ - old = now - 60*60*24*7 + def clean(self): + ''' Remove session records that haven't been used for a week. ''' + now = time.time() + week = 60*60*24*7 + old = now - week self.cursor.execute('delete from %ss where %s_time < %s'%(self.name, self.name, self.db.arg), (old, )) Modified: tracker/roundup-src/roundup/backends/tsearch2_setup.py ============================================================================== --- tracker/roundup-src/roundup/backends/tsearch2_setup.py (original) +++ tracker/roundup-src/roundup/backends/tsearch2_setup.py Sun Mar 15 22:43:30 2009 @@ -1,4 +1,4 @@ -#$Id: tsearch2_setup.py,v 1.2 2005/01/08 11:25:23 jlgijsbers Exp $ +#$Id: tsearch2_setup.py,v 1.2 2005-01-08 11:25:23 jlgijsbers Exp $ # All the SQL in this module is taken from the tsearch2 module in the contrib # tree of PostgreSQL 7.4.6. PostgreSQL, and this code, has the following Modified: tracker/roundup-src/roundup/cgi/PageTemplates/GlobalTranslationService.py ============================================================================== --- tracker/roundup-src/roundup/cgi/PageTemplates/GlobalTranslationService.py (original) +++ tracker/roundup-src/roundup/cgi/PageTemplates/GlobalTranslationService.py Sun Mar 15 22:43:30 2009 @@ -16,7 +16,7 @@ # 2. make imports use roundup.cgi """Global Translation Service for providing I18n to Page Templates. -$Id: GlobalTranslationService.py,v 1.4 2004/05/29 00:08:07 a1s Exp $ +$Id: GlobalTranslationService.py,v 1.4 2004-05-29 00:08:07 a1s Exp $ """ import re Modified: tracker/roundup-src/roundup/cgi/PageTemplates/__init__.py ============================================================================== --- tracker/roundup-src/roundup/cgi/PageTemplates/__init__.py (original) +++ tracker/roundup-src/roundup/cgi/PageTemplates/__init__.py Sun Mar 15 22:43:30 2009 @@ -15,7 +15,7 @@ This wrapper allows the Page Template modules to be segregated in a separate package. -$Id: __init__.py,v 1.3 2004/05/21 05:56:46 richard Exp $''' +$Id: __init__.py,v 1.3 2004-05-21 05:56:46 richard Exp $''' __version__='$$'[11:-2] Modified: tracker/roundup-src/roundup/cgi/TAL/TranslationContext.py ============================================================================== --- tracker/roundup-src/roundup/cgi/TAL/TranslationContext.py (original) +++ tracker/roundup-src/roundup/cgi/TAL/TranslationContext.py Sun Mar 15 22:43:30 2009 @@ -16,7 +16,7 @@ The translation context provides a container for the information needed to perform translation of a marked string from a page template. -$Id: TranslationContext.py,v 1.1 2004/05/21 05:36:30 richard Exp $ +$Id: TranslationContext.py,v 1.1 2004-05-21 05:36:30 richard Exp $ """ DEFAULT_DOMAIN = "default" Modified: tracker/roundup-src/roundup/cgi/TranslationService.py ============================================================================== --- tracker/roundup-src/roundup/cgi/TranslationService.py (original) +++ tracker/roundup-src/roundup/cgi/TranslationService.py Sun Mar 15 22:43:30 2009 @@ -13,8 +13,8 @@ # translate(domain, msgid, mapping, context, target_language, default) # -__version__ = "$Revision: 1.4 $"[11:-2] -__date__ = "$Date: 2007/01/14 22:54:15 $"[7:-2] +__version__ = "$Revision: 1.6 $"[11:-2] +__date__ = "$Date: 2008-08-18 05:04:01 $"[7:-2] from roundup import i18n from roundup.cgi.PageTemplates import Expressions, PathIterator, TALES @@ -37,11 +37,16 @@ def gettext(self, msgid): if not isinstance(msgid, unicode): msgid = unicode(msgid, 'utf8') - return self.ugettext(msgid).encode(self.OUTPUT_ENCODING) + msgtrans=self.ugettext(msgid) + return msgtrans.encode(self.OUTPUT_ENCODING) def ngettext(self, singular, plural, number): - return self.ungettext(singular, plural, number).encode( - self.OUTPUT_ENCODING) + if not isinstance(singular, unicode): + singular = unicode(singular, 'utf8') + if not isinstance(plural, unicode): + plural = unicode(plural, 'utf8') + msgtrans=self.ungettext(singular, plural, number) + return msgtrans.encode(self.OUTPUT_ENCODING) class TranslationService(TranslationServiceMixin, i18n.RoundupTranslations): pass Modified: tracker/roundup-src/roundup/cgi/ZTUtils/Batch.py ============================================================================== --- tracker/roundup-src/roundup/cgi/ZTUtils/Batch.py (original) +++ tracker/roundup-src/roundup/cgi/ZTUtils/Batch.py Sun Mar 15 22:43:30 2009 @@ -12,7 +12,7 @@ ############################################################################## __doc__='''Batch class, for iterating over a sequence in batches -$Id: Batch.py,v 1.3 2004/02/11 23:55:09 richard Exp $''' +$Id: Batch.py,v 1.3 2004-02-11 23:55:09 richard Exp $''' __docformat__ = 'restructuredtext' __version__='$Revision: 1.3 $'[11:-2] Modified: tracker/roundup-src/roundup/cgi/ZTUtils/Iterator.py ============================================================================== --- tracker/roundup-src/roundup/cgi/ZTUtils/Iterator.py (original) +++ tracker/roundup-src/roundup/cgi/ZTUtils/Iterator.py Sun Mar 15 22:43:30 2009 @@ -18,7 +18,7 @@ iterator. The next() method fetches the next item, and returns true if it succeeds. -$Id: Iterator.py,v 1.4 2005/02/16 22:07:33 richard Exp $''' +$Id: Iterator.py,v 1.4 2005-02-16 22:07:33 richard Exp $''' __docformat__ = 'restructuredtext' __version__='$Revision: 1.4 $'[11:-2] Modified: tracker/roundup-src/roundup/cgi/ZTUtils/__init__.py ============================================================================== --- tracker/roundup-src/roundup/cgi/ZTUtils/__init__.py (original) +++ tracker/roundup-src/roundup/cgi/ZTUtils/__init__.py Sun Mar 15 22:43:30 2009 @@ -16,7 +16,7 @@ - removed Zope imports -$Id: __init__.py,v 1.3 2004/02/11 23:55:09 richard Exp $''' +$Id: __init__.py,v 1.3 2004-02-11 23:55:09 richard Exp $''' __docformat__ = 'restructuredtext' __version__='$Revision: 1.3 $'[11:-2] Modified: tracker/roundup-src/roundup/cgi/actions.py ============================================================================== --- tracker/roundup-src/roundup/cgi/actions.py (original) +++ tracker/roundup-src/roundup/cgi/actions.py Sun Mar 15 22:43:30 2009 @@ -1,8 +1,7 @@ -#$Id: actions.py,v 1.71 2007/09/20 23:44:58 jpend Exp $ - -import re, cgi, StringIO, urllib, Cookie, time, random, csv, codecs +import re, cgi, StringIO, urllib, time, random, csv, codecs from roundup import hyperdb, token, date, password +from roundup.actions import Action as BaseAction from roundup.i18n import _ import roundup.exceptions from roundup.cgi import exceptions, templating @@ -104,30 +103,37 @@ def handle(self): """Retire the context item.""" - # if we want to view the index template now, then unset the nodeid + # ensure modification comes via POST + if self.client.env['REQUEST_METHOD'] != 'POST': + self.client.error_message.append(self._('Invalid request')) + + # if we want to view the index template now, then unset the itemid # context info (a special-case for retire actions on the index page) - nodeid = self.nodeid + itemid = self.nodeid if self.template == 'index': self.client.nodeid = None # make sure we don't try to retire admin or anonymous if self.classname == 'user' and \ - self.db.user.get(nodeid, 'username') in ('admin', 'anonymous'): + self.db.user.get(itemid, 'username') in ('admin', 'anonymous'): raise ValueError, self._( 'You may not retire the admin or anonymous user') + # check permission + if not self.hasPermission('Retire', classname=self.classname, + itemid=itemid): + raise exceptions.Unauthorised, self._( + 'You do not have permission to retire %(class)s' + ) % {'class': self.classname} + # do the retire - self.db.getclass(self.classname).retire(nodeid) + self.db.getclass(self.classname).retire(itemid) self.db.commit() self.client.ok_message.append( self._('%(classname)s %(itemid)s has been retired')%{ - 'classname': self.classname.capitalize(), 'itemid': nodeid}) + 'classname': self.classname.capitalize(), 'itemid': itemid}) - def hasPermission(self, permission, classname=Action._marker, itemid=None): - if itemid is None: - itemid = self.nodeid - return Action.hasPermission(self, permission, classname, itemid, '__retired__') class SearchAction(Action): name = 'search' @@ -234,7 +240,7 @@ if isinstance(prop, hyperdb.String): v = self.form[key].value l = token.token_split(v) - if len(l) > 1 or l[0] != v: + if len(l) != 1 or l[0] != v: self.form.value.remove(self.form[key]) # replace the single value with the split list for v in l: @@ -275,12 +281,19 @@ The "rows" CGI var defines the CSV-formatted entries for the class. New nodes are identified by the ID 'X' (or any other non-existent ID) and removed lines are retired. - """ + # ensure modification comes via POST + if self.client.env['REQUEST_METHOD'] != 'POST': + self.client.error_message.append(self._('Invalid request')) + + # figure the properties list for the class cl = self.db.classes[self.classname] - idlessprops = cl.getprops(protected=0).keys() - idlessprops.sort() - props = ['id'] + idlessprops + props_without_id = cl.getprops(protected=0).keys() + + # the incoming CSV data will always have the properties in colums + # sorted and starting with the "id" column + props_without_id.sort() + props = ['id'] + props_without_id # do the edit rows = StringIO.StringIO(self.form['rows'].value) @@ -294,25 +307,38 @@ if values == props: continue - # extract the nodeid - nodeid, values = values[0], values[1:] - found[nodeid] = 1 + # extract the itemid + itemid, values = values[0], values[1:] + found[itemid] = 1 # see if the node exists - if nodeid in ('x', 'X') or not cl.hasnode(nodeid): + if itemid in ('x', 'X') or not cl.hasnode(itemid): exists = 0 + + # check permission to create this item + if not self.hasPermission('Create', classname=self.classname): + raise exceptions.Unauthorised, self._( + 'You do not have permission to create %(class)s' + ) % {'class': self.classname} else: exists = 1 # confirm correct weight - if len(idlessprops) != len(values): + if len(props_without_id) != len(values): self.client.error_message.append( self._('Not enough values on line %(line)s')%{'line':line}) return # extract the new values d = {} - for name, value in zip(idlessprops, values): + for name, value in zip(props_without_id, values): + # check permission to edit this property on this item + if exists and not self.hasPermission('Edit', itemid=itemid, + classname=self.classname, property=name): + raise exceptions.Unauthorised, self._( + 'You do not have permission to edit %(class)s' + ) % {'class': self.classname} + prop = cl.properties[name] value = value.strip() # only add the property if it has a value @@ -341,15 +367,21 @@ # perform the edit if exists: # edit existing - cl.set(nodeid, **d) + cl.set(itemid, **d) else: # new node found[cl.create(**d)] = 1 # retire the removed entries - for nodeid in cl.list(): - if not found.has_key(nodeid): - cl.retire(nodeid) + for itemid in cl.list(): + if not found.has_key(itemid): + # check permission to retire this item + if not self.hasPermission('Retire', itemid=itemid, + classname=self.classname): + raise exceptions.Unauthorised, self._( + 'You do not have permission to retire %(class)s' + ) % {'class': self.classname} + cl.retire(itemid) # all OK self.db.commit() @@ -486,26 +518,20 @@ _cn_marker = [] def editItemPermission(self, props, classname=_cn_marker, itemid=None): - """Determine whether the user has permission to edit this item. - - Base behaviour is to check the user can edit this class. If we're - editing the "user" class, users are allowed to edit their own details. - Unless it's the "roles" property, which requires the special Permission - "Web Roles". - """ - if self.classname == 'user': - if props.has_key('roles') and not self.hasPermission('Web Roles'): - raise exceptions.Unauthorised, self._( - "You do not have permission to edit user roles") - if self.isEditingSelf(): - return 1 + """Determine whether the user has permission to edit this item.""" if itemid is None: itemid = self.nodeid if classname is self._cn_marker: classname = self.classname - if self.hasPermission('Edit', itemid=itemid, classname=classname): - return 1 - return 0 + # The user must have permission to edit each of the properties + # being changed. + for p in props: + if not self.hasPermission('Edit', itemid=itemid, + classname=classname, property=p): + return 0 + # Since the user has permission to edit all of the properties, + # the edit is OK. + return 1 def newItemPermission(self, props, classname=None): """Determine whether the user has permission to create this item. @@ -559,6 +585,10 @@ See parsePropsFromForm and _editnodes for special variables. """ + # ensure modification comes via POST + if self.client.env['REQUEST_METHOD'] != 'POST': + self.client.error_message.append(self._('Invalid request')) + user_activity = self.lastUserActivity() if user_activity: props = self.detectCollision(user_activity, self.lastNodeActivity()) @@ -601,6 +631,10 @@ This follows the same form as the EditItemAction, with the same special form values. ''' + # ensure modification comes via POST + if self.client.env['REQUEST_METHOD'] != 'POST': + self.client.error_message.append(self._('Invalid request')) + # parse the props from the form try: props, links = self.client.parsePropsFromForm(create=1) @@ -609,6 +643,11 @@ % str(message)) return + # guard against new user creation that would bypass security checks + for key in props: + if 'user' in key: + return + # handle the props - edit or create try: # when it hits the None element, it'll set self.nodeid @@ -741,13 +780,8 @@ # re-open the database for real, using the user self.client.opendb(user) - # if we have a session, update it - if hasattr(self.client, 'session'): - self.client.db.getSessionManager().set(self.client.session, - user=user, last_use=time.time()) - else: - # new session cookie - self.client.set_cookie(user, expire=None) + # update session data + self.client.session_api.set(user=user) # nice message message = self._('You are now registered, welcome!') @@ -779,10 +813,14 @@ def handle(self): """Attempt to create a new user based on the contents of the form - and then set the cookie. + and then remember it in session. Return 1 on successful login. """ + # ensure modification comes via POST + if self.client.env['REQUEST_METHOD'] != 'POST': + self.client.error_message.append(self._('Invalid request')) + # parse the props from the form try: props, links = self.client.parsePropsFromForm(create=1) @@ -876,15 +914,10 @@ class LogoutAction(Action): def handle(self): - """Make us really anonymous - nuke the cookie too.""" + """Make us really anonymous - nuke the session too.""" # log us out self.client.make_user_anonymous() - - # construct the logout cookie - now = Cookie._getdate() - self.client.additional_headers['Set-Cookie'] = \ - '%s=deleted; Max-Age=0; expires=%s; Path=%s;' % ( - self.client.cookie_name, now, self.client.cookie_path) + self.client.session_api.destroy() # Let the user know what's going on self.client.ok_message.append(self._('You are logged out')) @@ -902,6 +935,10 @@ Sets up a session for the user which contains the login credentials. """ + # ensure modification comes via POST + if self.client.env['REQUEST_METHOD'] != 'POST': + self.client.error_message.append(self._('Invalid request')) + # we need the username at a minimum if not self.form.has_key('__login_name'): self.client.error_message.append(self._('Username required')) @@ -924,11 +961,10 @@ # now we're OK, re-open the database for real, using the user self.client.opendb(self.client.user) - # set the session cookie + # save user in session + self.client.session_api.set(user=self.client.user) if self.form.has_key('remember'): - self.client.set_cookie(self.client.user, expire=86400*365) - else: - self.client.set_cookie(self.client.user, expire=None) + self.client.session_api.update(set_cookie=True, expire=24*3600*365) # If we came from someplace, go back there if self.form.has_key('__came_from'): @@ -974,14 +1010,6 @@ columns = request.columns klass = self.db.getclass(request.classname) - # validate the request - allprops = klass.getprops() - for c in filterspec.keys() + columns + [x[1] for x in group + sort]: - if not allprops.has_key(c): - # Can't use FormError, since that would try to use - # the same bogus field specs - raise exceptions.SeriousError, "Property %s does not exist" % c - # full-text search if request.search_text: matches = self.db.indexer.search( @@ -1006,14 +1034,63 @@ self.client.STORAGE_CHARSET, self.client.charset, 'replace') writer = csv.writer(wfile) - # mvl: protect against connection loss self.client._socket_op(writer.writerow, columns) # and search for itemid in klass.filter(matches, filterspec, sort, group): - # mvl: likewise - self.client._socket_op(writer.writerow, [str(klass.get(itemid, col)) for col in columns]) + row = [] + for name in columns: + # check permission to view this property on this item + if exists and not self.hasPermission('View', itemid=itemid, + classname=request.classname, property=name): + raise exceptions.Unauthorised, self._( + 'You do not have permission to view %(class)s' + ) % {'class': request.classname} + row.append(str(klass.get(itemid, name))) + self.client._socket_op(writer.writerow, row) return '\n' + +class Bridge(BaseAction): + """Make roundup.actions.Action executable via CGI request. + + Using this allows users to write actions executable from multiple frontends. + CGI Form content is translated into a dictionary, which then is passed as + argument to 'handle()'. XMLRPC requests have to pass this dictionary + directly. + """ + + def __init__(self, *args): + + # As this constructor is callable from multiple frontends, each with + # different Action interfaces, we have to look at the arguments to + # figure out how to complete construction. + if (len(args) == 1 and + hasattr(args[0], '__class__') and + args[0].__class__.__name__ == 'Client'): + self.cgi = True + self.execute = self.execute_cgi + self.client = args[0] + self.form = self.client.form + else: + self.cgi = False + + def execute_cgi(self): + args = {} + for key in self.form.keys(): + args[key] = self.form.getvalue(key) + self.permission(args) + return self.handle(args) + + def permission(self, args): + """Raise Unauthorised if the current user is not allowed to execute + this action. Users may override this method.""" + + pass + + def handle(self, args): + + raise NotImplementedError + # vim: set filetype=python sts=4 sw=4 et si : Modified: tracker/roundup-src/roundup/cgi/apache.py ============================================================================== --- tracker/roundup-src/roundup/cgi/apache.py (original) +++ tracker/roundup-src/roundup/cgi/apache.py Sun Mar 15 22:43:30 2009 @@ -21,7 +21,7 @@ # 29-apr-2004 [als] created __version__ = "$Revision: 1.6 $"[11:-2] -__date__ = "$Date: 2006/11/09 00:36:21 $"[7:-2] +__date__ = "$Date: 2006-11-09 00:36:21 $"[7:-2] import cgi import os @@ -77,6 +77,13 @@ """NOOP. There aint no such thing as 'end_headers' in mod_python""" pass + + def sendfile(self, filename, offset = 0, len = -1): + """Send 'filename' to the user.""" + + return self._req.sendfile(filename, offset, len) + + def handler(req): """HTTP request handler""" _options = req.get_options() Modified: tracker/roundup-src/roundup/cgi/cgitb.py ============================================================================== --- tracker/roundup-src/roundup/cgi/cgitb.py (original) +++ tracker/roundup-src/roundup/cgi/cgitb.py Sun Mar 15 22:43:30 2009 @@ -1,7 +1,7 @@ # # This module was written by Ka-Ping Yee, . # -# $Id: cgitb.py,v 1.12 2004/07/13 10:18:00 a1s Exp $ +# $Id: cgitb.py,v 1.12 2004-07-13 10:18:00 a1s Exp $ """Extended CGI traceback handler by Ka-Ping Yee, . """ Modified: tracker/roundup-src/roundup/cgi/client.py ============================================================================== --- tracker/roundup-src/roundup/cgi/client.py (original) +++ tracker/roundup-src/roundup/cgi/client.py Sun Mar 15 22:43:30 2009 @@ -1,13 +1,12 @@ -# $Id: client.py,v 1.238 2007/09/22 21:20:57 jpend Exp $ - """WWW request handler (also used in the stand-alone server). """ __docformat__ = 'restructuredtext' -import base64, binascii, cgi, codecs, mimetypes, os -import random, re, rfc822, stat, time, urllib, urlparse +import base64, binascii, cgi, codecs, httplib, mimetypes, os +import quopri, random, re, rfc822, stat, sys, time, urllib, urlparse import Cookie, socket, errno from Cookie import CookieError, BaseCookie, SimpleCookie +from cStringIO import StringIO from roundup import roundupdb, date, hyperdb, password from roundup.cgi import templating, cgitb, TranslationService @@ -17,6 +16,7 @@ from roundup.cgi.form_parser import FormParser from roundup.mailer import Mailer, MessageSendError from roundup.cgi import accept_language +from roundup import xmlrpc def initialiseSecurity(security): '''Create some Permissions and Roles on the security object @@ -41,22 +41,22 @@ def clean_message(message, mc=re.compile(CLEAN_MESSAGE_RE, re.I)): return mc.sub(clean_message_callback, message) def clean_message_callback(match, ok={'a':1,'i':1,'b':1,'br':1}): - ''' Strip all non ,, and
        tags from a string - ''' + """ Strip all non
        ,, and
        tags from a string + """ if ok.has_key(match.group(3).lower()): return match.group(1) return '<%s>'%match.group(2) -error_message = ""'''An error has occurred +error_message = ''"""An error has occurred

        An error has occurred

        A problem was encountered processing your request. The tracker maintainers have been notified of the problem.

        -''' +""" class LiberalCookie(SimpleCookie): - ''' Python's SimpleCookie throws an exception if the cookie uses invalid + """ Python's SimpleCookie throws an exception if the cookie uses invalid syntax. Other applications on the same server may have done precisely this, preventing roundup from working through no fault of roundup. Numerous other python apps have run into the same problem: @@ -67,7 +67,7 @@ This particular implementation comes from trac's solution to the problem. Unfortunately it requires some hackery in SimpleCookie's internals to provide a more liberal __set method. - ''' + """ def load(self, rawdata, ignore_parse_errors=True): if ignore_parse_errors: self.bad_cookies = [] @@ -88,8 +88,114 @@ dict.__setitem__(self, key, None) +class Session: + """ + Needs DB to be already opened by client + + Session attributes at instantiation: + + - "client" - reference to client for add_cookie function + - "session_db" - session DB manager + - "cookie_name" - name of the cookie with session id + - "_sid" - session id for current user + - "_data" - session data cache + + session = Session(client) + session.set(name=value) + value = session.get(name) + + session.destroy() # delete current session + session.clean_up() # clean up session table + + session.update(set_cookie=True, expire=3600*24*365) + # refresh session expiration time, setting persistent + # cookie if needed to last for 'expire' seconds + + """ + + def __init__(self, client): + self._data = {} + self._sid = None + + self.client = client + self.session_db = client.db.getSessionManager() + + # parse cookies for session id + self.cookie_name = 'roundup_session_%s' % \ + re.sub('[^a-zA-Z]', '', client.instance.config.TRACKER_NAME) + cookies = LiberalCookie(client.env.get('HTTP_COOKIE', '')) + if self.cookie_name in cookies: + if not self.session_db.exists(cookies[self.cookie_name].value): + self._sid = None + # remove old cookie + self.client.add_cookie(self.cookie_name, None) + else: + self._sid = cookies[self.cookie_name].value + self._data = self.session_db.getall(self._sid) + + def _gen_sid(self): + """ generate a unique session key """ + while 1: + s = '%s%s'%(time.time(), random.random()) + s = binascii.b2a_base64(s).strip() + if not self.session_db.exists(s): + break + + # clean up the base64 + if s[-1] == '=': + if s[-2] == '=': + s = s[:-2] + else: + s = s[:-1] + return s + + def clean_up(self): + """Remove expired sessions""" + self.session_db.clean() + + def destroy(self): + self.client.add_cookie(self.cookie_name, None) + self._data = {} + self.session_db.destroy(self._sid) + self.client.db.commit() + + def get(self, name, default=None): + return self._data.get(name, default) + + def set(self, **kwargs): + self._data.update(kwargs) + if not self._sid: + self._sid = self._gen_sid() + self.session_db.set(self._sid, **self._data) + # add session cookie + self.update(set_cookie=True) + + # XXX added when patching 1.4.4 for backward compatibility + # XXX remove + self.client.session = self._sid + else: + self.session_db.set(self._sid, **self._data) + self.client.db.commit() + + def update(self, set_cookie=False, expire=None): + """ update timestamp in db to avoid expiration + + if 'set_cookie' is True, set cookie with 'expire' seconds lifetime + if 'expire' is None - session will be closed with the browser + + XXX the session can be purged within a week even if a cookie + lifetime is longer + """ + self.session_db.updateTimestamp(self._sid) + self.client.db.commit() + + if set_cookie: + self.client.add_cookie(self.cookie_name, self._sid, expire=expire) + + + class Client: - '''Instantiate to handle one CGI request. + """Instantiate to handle one CGI request. See inner_main for request processing. @@ -106,9 +212,11 @@ During the processing of a request, the following attributes are used: + - "db" - "error_message" holds a list of error messages - "ok_message" holds a list of OK messages - - "session" is the current user session id + - "session" is deprecated in favor of session_api (XXX remove) + - "session_api" is the interface to store data in session - "user" is the current user's name - "userid" is the current user's id - "template" is the current :template context @@ -116,18 +224,18 @@ - "nodeid" is the current context item id User Identification: - If the user has no login cookie, then they are anonymous and are logged + Users that are absent in session data are anonymous and are logged in as that user. This typically gives them all Permissions assigned to the Anonymous Role. - Once a user logs in, they are assigned a session. The Client instance - keeps the nodeid of the session as the "session" attribute. + Every user is assigned a session. "session_api" is the interface to work + with session data. Special form variables: Note that in various places throughout this code, special form variables of the form : are used. The colon (":") part may actually be one of either ":" or "@". - ''' + """ # charset used for data storage and form templates # Note: must be in lower case for comparisons! @@ -186,11 +294,9 @@ # this is the "cookie path" for this tracker (ie. the path part of # the "base" url) self.cookie_path = urlparse.urlparse(self.base)[2] - self.cookie_name = 'roundup_session_' + re.sub('[^a-zA-Z]', '', - self.instance.config.TRACKER_NAME) # cookies to set in http responce # {(path, name): (value, expire)} - self.add_cookies = {} + self._cookies = {} # see if we need to re-parse the environment for the form (eg Zope) if form is None: @@ -216,7 +322,7 @@ # default character set self.charset = self.STORAGE_CHARSET - # parse cookies (used in charset and session lookups) + # parse cookies (used for charset lookups) # use our own LiberalCookie to handle bad apps on the same # server that have set cookies that are out of spec self.cookie = LiberalCookie(self.env.get('HTTP_COOKIE', '')) @@ -246,16 +352,49 @@ self.ngettext = translator.ngettext def main(self): - ''' Wrap the real main in a try/finally so we always close off the db. - ''' + """ Wrap the real main in a try/finally so we always close off the db. + """ try: - self.inner_main() + if self.env.get('CONTENT_TYPE') == 'text/xml': + self.handle_xmlrpc() + else: + self.inner_main() finally: if hasattr(self, 'db'): self.db.close() + + def handle_xmlrpc(self): + + # Pull the raw XML out of the form. The "value" attribute + # will be the raw content of the POST request. + assert self.form.file + input = self.form.value + # So that the rest of Roundup can query the form in the + # usual way, we create an empty list of fields. + self.form.list = [] + + # Set the charset and language, since other parts of + # Roundup may depend upon that. + self.determine_charset() + self.determine_language() + # Open the database as the correct user. + self.determine_user() + + # Call the appropriate XML-RPC method. + handler = xmlrpc.RoundupDispatcher(self.db, + self.instance.actions, + self.translator, + allow_none=True) + output = handler.dispatch(input) + self.db.commit() + + self.setHeader("Content-Type", "text/xml") + self.setHeader("Content-Length", str(len(output))) + self.write(output) + def inner_main(self): - '''Process a request. + """Process a request. The most common requests are handled like so: @@ -285,48 +424,57 @@ doesn't have permission - NotFound (raised wherever it needs to be) percolates up to the CGI interface that called the client - ''' + """ self.ok_message = [] self.error_message = [] try: self.determine_charset() self.determine_language() - # make sure we're identified (even anonymously) - self.determine_user() - - # figure out the context and desired content template - self.determine_context() - - # possibly handle a form submit action (may change self.classname - # and self.template, and may also append error/ok_messages) - html = self.handle_action() + try: + # make sure we're identified (even anonymously) + self.determine_user() - if html: - self.write_html(html) - return + # figure out the context and desired content template + self.determine_context() - # now render the page - # we don't want clients caching our dynamic pages - self.additional_headers['Cache-Control'] = 'no-cache' -# Pragma: no-cache makes Mozilla and its ilk double-load all pages!! -# self.additional_headers['Pragma'] = 'no-cache' - - # pages with messages added expire right now - # simple views may be cached for a small amount of time - # TODO? make page expire time configurable - # always expire pages, as IE just doesn't seem to do the - # right thing here :( - date = time.time() - 1 - #if self.error_message or self.ok_message: - # date = time.time() - 1 - #else: - # date = time.time() + 5 - self.additional_headers['Expires'] = rfc822.formatdate(date) + # possibly handle a form submit action (may change self.classname + # and self.template, and may also append error/ok_messages) + html = self.handle_action() + + if html: + self.write_html(html) + return + + # now render the page + # we don't want clients caching our dynamic pages + self.additional_headers['Cache-Control'] = 'no-cache' + # Pragma: no-cache makes Mozilla and its ilk + # double-load all pages!! + # self.additional_headers['Pragma'] = 'no-cache' + + # pages with messages added expire right now + # simple views may be cached for a small amount of time + # TODO? make page expire time configurable + # always expire pages, as IE just doesn't seem to do the + # right thing here :( + date = time.time() - 1 + #if self.error_message or self.ok_message: + # date = time.time() - 1 + #else: + # date = time.time() + 5 + self.additional_headers['Expires'] = rfc822.formatdate(date) - # render the content - try: + # render the content self.write_html(self.renderContext()) + except SendFile, designator: + # The call to serve_file may result in an Unauthorised + # exception or a NotModified exception. Those + # exceptions will be handled by the outermost set of + # exception handlers. + self.serve_file(designator) + except SendStaticFile, file: + self.serve_static_file(str(file)) except IOError: # IOErrors here are due to the client disconnecting before # recieving the reply. @@ -342,26 +490,17 @@ self.additional_headers['Location'] = str(url) self.response_code = 302 self.write_html('Redirecting to
        %s'%(url, url)) - except SendFile, designator: - try: - self.serve_file(designator) - except NotModified: - # send the 304 response - self.response_code = 304 - self.header() - except SendStaticFile, file: - try: - self.serve_static_file(str(file)) - except NotModified: - # send the 304 response - self.response_code = 304 - self.header() except Unauthorised, message: # users may always see the front page + self.response_code = 403 self.classname = self.nodeid = None self.template = '' self.error_message.append(message) self.write_html(self.renderContext()) + except NotModified: + # send the 304 response + self.response_code = 304 + self.header() except NotFound, e: self.response_code = 404 self.template = '404' @@ -380,63 +519,32 @@ if self.instance.config.WEB_DEBUG: self.write_html(cgitb.html(i18n=self.translator)) else: - self.mailer.exception_message(self.exception_data()) + self.mailer.exception_message() return self.write_html(self._(error_message)) - def exception_data(self): - result = '' - try: - for k,v in self.env.items(): - result += "%s=%s\n" % (k,v) - for k,v in self.request.headers.items(): - result += "%s=%s\n" % (k,v) - result += "user:" + repr(self.user) + "\n" - except: - pass - return result - def clean_sessions(self): - """Age sessions, remove when they haven't been used for a week. + """Deprecated + XXX remove + """ + self.clean_up() - Do it only once an hour. + def clean_up(self): + """Remove expired sessions and One Time Keys. - Note: also cleans One Time Keys, and other "session" based stuff. + Do it only once an hour. """ - sessions = self.db.getSessionManager() - last_clean = sessions.get('last_clean', 'last_use', 0) - - # time to clean? - #week = 60*60*24*7 hour = 60*60 now = time.time() + + # XXX: hack - use OTK table to store last_clean time information + # 'last_clean' string is used instead of otk key + last_clean = self.db.getOTKManager().get('last_clean', 'last_use', 0) if now - last_clean < hour: - # Release the database lock obtained when looking at last_clean - self.db.rollback() 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 - - try: - sessions.clean(now) - self.db.getOTKManager().clean(now) - 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 - self.db.rollback() - return + self.session_api.clean_up() + self.db.getOTKManager().clean() + self.db.getOTKManager().set('last_clean', last_use=now) self.db.commit(fail_ok=True) def determine_charset(self): @@ -529,9 +637,12 @@ """Determine who the user is""" self.opendb('admin') - # make sure we have the session Class - self.clean_sessions() - sessions = self.db.getSessionManager() + # get session data from db + # XXX: rename + self.session_api = Session(self) + + # take the opportunity to cleanup expired sessions and otks + self.clean_up() user = None # first up, try http authorization if enabled @@ -555,27 +666,17 @@ login.verifyLogin(username, password) except LoginError, err: self.make_user_anonymous() - self.response_code = 403 raise Unauthorised, err - user = username - # if user was not set by http authorization, try session cookie - if (not user and self.cookie.has_key(self.cookie_name) - and (self.cookie[self.cookie_name].value != 'deleted')): - # get the session key from the cookie - self.session = self.cookie[self.cookie_name].value - # get the user from the session - try: - # update the lifetime datestamp - sessions.updateTimestamp(self.session) - self.db.commit() - user = sessions.get(self.session, 'user') - except KeyError: - # not valid, ignore id - pass + # if user was not set by http authorization, try session lookup + if not user: + user = self.session_api.get('user') + if user: + # update session lifetime datestamp + self.session_api.update() - # if no user name set by http authorization or session cookie + # if no user name set by http authorization or session lookup # the user is anonymous if not user: user = 'anonymous' @@ -708,10 +809,6 @@ klass = self.db.getclass(self.classname) except KeyError: raise NotFound, '%s/%s'%(self.classname, self.nodeid) - if long(self.nodeid) > 2**31: - # Postgres will complain with a ProgrammingError - # if we try to pass in numbers that are too large - raise NotFound, '%s/%s'%(self.classname, self.nodeid) if not klass.hasnode(self.nodeid): raise NotFound, '%s/%s'%(self.classname, self.nodeid) # with a designator, we default to item view @@ -731,8 +828,8 @@ self.template = template_override def serve_file(self, designator, dre=re.compile(r'([^\d]+)(\d+)')): - ''' Serve the file from the content property of the designated item. - ''' + """ Serve the file from the content property of the designated item. + """ m = dre.match(str(designator)) if not m: raise NotFound, str(designator) @@ -754,14 +851,41 @@ "this file.") mime_type = klass.get(nodeid, 'type') - content = klass.get(nodeid, 'content') + + # if the mime_type is HTML-ish then make sure we're allowed to serve up + # HTML-ish content + if mime_type in ('text/html', 'text/x-html'): + if not self.instance.config['WEB_ALLOW_HTML_FILE']: + # do NOT serve the content up as HTML + mime_type = 'application/octet-stream' + + # If this object is a file (i.e., an instance of FileClass), + # see if we can find it in the filesystem. If so, we may be + # able to use the more-efficient request.sendfile method of + # sending the file. If not, just get the "content" property + # in the usual way, and use that. + content = None + filename = None + if isinstance(klass, hyperdb.FileClass): + try: + filename = self.db.filename(classname, nodeid) + except AttributeError: + # The database doesn't store files in the filesystem + # and therefore doesn't provide the "filename" method. + pass + except IOError: + # The file does not exist. + pass + if not filename: + content = klass.get(nodeid, 'content') + lmt = klass.get(nodeid, 'activity').timestamp() - self._serve_file(lmt, mime_type, content) + self._serve_file(lmt, mime_type, content, filename) def serve_static_file(self, file): - ''' Serve up the file named from the templates dir - ''' + """ Serve up the file named from the templates dir + """ # figure the filename - try STATIC_FILES, then TEMPLATES dir for dir_option in ('STATIC_FILES', 'TEMPLATES'): prefix = self.instance.config[dir_option] @@ -788,21 +912,14 @@ else: mime_type = 'text/plain' - # snarf the content - f = open(filename, 'rb') - try: - content = f.read() - finally: - f.close() + self._serve_file(lmt, mime_type, '', filename) - self._serve_file(lmt, mime_type, content) + def _serve_file(self, lmt, mime_type, content=None, filename=None): + """ guts of serve_file() and serve_static_file() + """ - def _serve_file(self, lmt, mime_type, content): - ''' guts of serve_file() and serve_static_file() - ''' # spit out headers self.additional_headers['Content-Type'] = mime_type - self.additional_headers['Content-Length'] = str(len(content)) self.additional_headers['Last-Modified'] = rfc822.formatdate(lmt) ims = None @@ -819,14 +936,17 @@ if lmtt <= ims: raise NotModified - self.write(content) + if filename: + self.write_file(filename) + else: + self.additional_headers['Content-Length'] = str(len(content)) + self.write(content) def renderContext(self): - ''' Return a PageTemplate for the named page - ''' + """ Return a PageTemplate for the named page + """ name = self.classname extension = self.template - pt = self.instance.templates.get(name, extension) # catch errors so we can handle PT rendering errors more nicely args = { @@ -834,6 +954,7 @@ 'error_message': self.error_message } try: + pt = self.instance.templates.get(name, extension) # let the template render figure stuff out result = pt.render(self, None, None, **args) self.additional_headers['Content-Type'] = pt.content_type @@ -861,12 +982,35 @@ raise Unauthorised, str(message) except: # everything else - return cgitb.pt_html(i18n=self.translator) + if self.instance.config.WEB_DEBUG: + return cgitb.pt_html(i18n=self.translator) + exc_info = sys.exc_info() + try: + # If possible, send the HTML page template traceback + # to the administrator. + to = [self.mailer.config.ADMIN_EMAIL] + subject = "Templating Error: %s" % exc_info[1] + content = cgitb.pt_html() + message, writer = self.mailer.get_standard_message( + to, subject) + writer.addheader('Content-Transfer-Encoding', 'quoted-printable') + body = writer.startbody('text/html; charset=utf-8') + content = StringIO(content) + quopri.encode(content, body, 0) + self.mailer.smtp_send(to, message) + # Now report the error to the user. + return self._(error_message) + except: + # Reraise the original exception. The user will + # receive an error message, and the adminstrator will + # receive a traceback, albeit with less information + # than the one we tried to generate above. + raise exc_info[0], exc_info[1], exc_info[2] # these are the actions that are available actions = ( ('edit', EditItemAction), - # ('editcsv', EditCSVAction), + ('editcsv', EditCSVAction), ('new', NewItemAction), ('register', RegisterAction), ('confrego', ConfRegoAction), @@ -879,7 +1023,7 @@ ('export_csv', ExportCSVAction), ) def handle_action(self): - ''' Determine whether there should be an Action called. + """ Determine whether there should be an Action called. The action is defined by the form variable :action which identifies the method on this object to call. The actions @@ -890,7 +1034,7 @@ We explicitly catch Reject and ValueError exceptions and present their messages to the user. - ''' + """ if self.form.has_key(':action'): action = self.form[':action'].value.lower() elif self.form.has_key('@action'): @@ -944,6 +1088,14 @@ pass if err_errno not in self.IGNORE_NET_ERRORS: raise + except IOError: + # Apache's mod_python will raise IOError -- without an + # accompanying errno -- when a write to the client fails. + # A common case is that the client has closed the + # connection. There's no way to be certain that this is + # the situation that has occurred here, but that is the + # most likely case. + pass def write(self, content): if not self.headers_done: @@ -971,14 +1123,236 @@ # and write self._socket_op(self.request.wfile.write, content) + def http_strip(self, content): + """Remove HTTP Linear White Space from 'content'. + + 'content' -- A string. + + returns -- 'content', with all leading and trailing LWS + removed.""" + + # RFC 2616 2.2: Basic Rules + # + # LWS = [CRLF] 1*( SP | HT ) + return content.strip(" \r\n\t") + + def http_split(self, content): + """Split an HTTP list. + + 'content' -- A string, giving a list of items. + + returns -- A sequence of strings, containing the elements of + the list.""" + + # RFC 2616 2.1: Augmented BNF + # + # Grammar productions of the form "#rule" indicate a + # comma-separated list of elements matching "rule". LWS + # is then removed from each element, and empty elements + # removed. + + # Split at commas. + elements = content.split(",") + # Remove linear whitespace at either end of the string. + elements = [self.http_strip(e) for e in elements] + # Remove any now-empty elements. + return [e for e in elements if e] + + def handle_range_header(self, length, etag): + """Handle the 'Range' and 'If-Range' headers. + + 'length' -- the length of the content available for the + resource. + + 'etag' -- the entity tag for this resources. + + returns -- If the request headers (including 'Range' and + 'If-Range') indicate that only a portion of the entity should + be returned, then the return value is a pair '(offfset, + length)' indicating the first byte and number of bytes of the + content that should be returned to the client. In addition, + this method will set 'self.response_code' to indicate Partial + Content. In all other cases, the return value is 'None'. If + appropriate, 'self.response_code' will be + set to indicate 'REQUESTED_RANGE_NOT_SATISFIABLE'. In that + case, the caller should not send any data to the client.""" + + # RFC 2616 14.35: Range + # + # See if the Range header is present. + ranges_specifier = self.env.get("HTTP_RANGE") + if ranges_specifier is None: + return None + # RFC 2616 14.27: If-Range + # + # Check to see if there is an If-Range header. + # Because the specification says: + # + # The If-Range header ... MUST be ignored if the request + # does not include a Range header, we check for If-Range + # after checking for Range. + if_range = self.env.get("HTTP_IF_RANGE") + if if_range: + # The grammar for the If-Range header is: + # + # If-Range = "If-Range" ":" ( entity-tag | HTTP-date ) + # entity-tag = [ weak ] opaque-tag + # weak = "W/" + # opaque-tag = quoted-string + # + # We only support strong entity tags. + if_range = self.http_strip(if_range) + if (not if_range.startswith('"') + or not if_range.endswith('"')): + return None + # If the condition doesn't match the entity tag, then we + # must send the client the entire file. + if if_range != etag: + return + # The grammar for the Range header value is: + # + # ranges-specifier = byte-ranges-specifier + # byte-ranges-specifier = bytes-unit "=" byte-range-set + # byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec ) + # byte-range-spec = first-byte-pos "-" [last-byte-pos] + # first-byte-pos = 1*DIGIT + # last-byte-pos = 1*DIGIT + # suffix-byte-range-spec = "-" suffix-length + # suffix-length = 1*DIGIT + # + # Look for the "=" separating the units from the range set. + specs = ranges_specifier.split("=", 1) + if len(specs) != 2: + return None + # Check that the bytes-unit is in fact "bytes". If it is not, + # we do not know how to process this range. + bytes_unit = self.http_strip(specs[0]) + if bytes_unit != "bytes": + return None + # Seperate the range-set into range-specs. + byte_range_set = self.http_strip(specs[1]) + byte_range_specs = self.http_split(byte_range_set) + # We only handle exactly one range at this time. + if len(byte_range_specs) != 1: + return None + # Parse the spec. + byte_range_spec = byte_range_specs[0] + pos = byte_range_spec.split("-", 1) + if len(pos) != 2: + return None + # Get the first and last bytes. + first = self.http_strip(pos[0]) + last = self.http_strip(pos[1]) + # We do not handle suffix ranges. + if not first: + return None + # Convert the first and last positions to integers. + try: + first = int(first) + if last: + last = int(last) + else: + last = length - 1 + except: + # The positions could not be parsed as integers. + return None + # Check that the range makes sense. + if (first < 0 or last < 0 or last < first): + return None + if last >= length: + # RFC 2616 10.4.17: 416 Requested Range Not Satisfiable + # + # If there is an If-Range header, RFC 2616 says that we + # should just ignore the invalid Range header. + if if_range: + return None + # Return code 416 with a Content-Range header giving the + # allowable range. + self.response_code = httplib.REQUESTED_RANGE_NOT_SATISFIABLE + self.setHeader("Content-Range", "bytes */%d" % length) + return None + # RFC 2616 10.2.7: 206 Partial Content + # + # Tell the client that we are honoring the Range request by + # indicating that we are providing partial content. + self.response_code = httplib.PARTIAL_CONTENT + # RFC 2616 14.16: Content-Range + # + # Tell the client what data we are providing. + # + # content-range-spec = byte-content-range-spec + # byte-content-range-spec = bytes-unit SP + # byte-range-resp-spec "/" + # ( instance-length | "*" ) + # byte-range-resp-spec = (first-byte-pos "-" last-byte-pos) + # | "*" + # instance-length = 1 * DIGIT + self.setHeader("Content-Range", + "bytes %d-%d/%d" % (first, last, length)) + return (first, last - first + 1) + + def write_file(self, filename): + """Send the contents of 'filename' to the user.""" + + # Determine the length of the file. + stat_info = os.stat(filename) + length = stat_info[stat.ST_SIZE] + # Assume we will return the entire file. + offset = 0 + # If the headers have not already been finalized, + if not self.headers_done: + # RFC 2616 14.19: ETag + # + # Compute the entity tag, in a format similar to that + # used by Apache. + etag = '"%x-%x-%x"' % (stat_info[stat.ST_INO], + length, + stat_info[stat.ST_MTIME]) + self.setHeader("ETag", etag) + # RFC 2616 14.5: Accept-Ranges + # + # Let the client know that we will accept range requests. + self.setHeader("Accept-Ranges", "bytes") + # RFC 2616 14.35: Range + # + # If there is a Range header, we may be able to avoid + # sending the entire file. + content_range = self.handle_range_header(length, etag) + if content_range: + offset, length = content_range + # RFC 2616 14.13: Content-Length + # + # Tell the client how much data we are providing. + self.setHeader("Content-Length", length) + # Send the HTTP header. + self.header() + # If the client doesn't actually want the body, or if we are + # indicating an invalid range. + if (self.env['REQUEST_METHOD'] == 'HEAD' + or self.response_code == httplib.REQUESTED_RANGE_NOT_SATISFIABLE): + return + # Use the optimized "sendfile" operation, if possible. + if hasattr(self.request, "sendfile"): + self._socket_op(self.request.sendfile, filename, offset, length) + return + # Fallback to the "write" operation. + f = open(filename, 'rb') + try: + if offset: + f.seek(offset) + content = f.read(length) + finally: + f.close() + self.write(content) + def setHeader(self, header, value): - '''Override a header to be returned to the user's browser. - ''' + """Override a header to be returned to the user's browser. + """ self.additional_headers[header] = value def header(self, headers=None, response=None): - '''Put up the appropriate header. - ''' + """Put up the appropriate header. + """ if headers is None: headers = {'Content-Type':'text/html; charset=utf-8'} if response is None: @@ -992,7 +1366,7 @@ headers = headers.items() - for ((path, name), (value, expire)) in self.add_cookies.items(): + for ((path, name), (value, expire)) in self._cookies.items(): cookie = "%s=%s; Path=%s;"%(name, value, path) if expire is not None: cookie += " expires=%s;"%Cookie._getdate(expire) @@ -1027,48 +1401,30 @@ path = self.cookie_path if not value: expire = -1 - self.add_cookies[(path, name)] = (value, expire) + self._cookies[(path, name)] = (value, expire) def set_cookie(self, user, expire=None): - """Set up a session cookie for the user. + """Deprecated. Use session_api calls directly - Also store away the user's login info against the session. + XXX remove """ - sessions = self.db.getSessionManager() - - # generate a unique session key - while 1: - s = '%s%s'%(time.time(), random.random()) - s = binascii.b2a_base64(s).strip() - if not sessions.exists(s): - break - self.session = s - # clean up the base64 - if self.session[-1] == '=': - if self.session[-2] == '=': - self.session = self.session[:-2] - else: - self.session = self.session[:-1] - - # insert the session in the sessiondb - sessions.set(self.session, user=user) - self.db.commit() - - # add session cookie - self.add_cookie(self.cookie_name, self.session, expire=expire) + # insert the session in the session db + self.session_api.set(user=user) + # refresh session cookie + self.session_api.update(set_cookie=True, expire=expire) def make_user_anonymous(self): - ''' Make us anonymous + """ Make us anonymous This method used to handle non-existence of the 'anonymous' user, but that user is mandatory now. - ''' + """ self.userid = self.db.user.lookup('anonymous') self.user = 'anonymous' def standard_message(self, to, subject, body, author=None): - '''Send a standard email message from Roundup. + """Send a standard email message from Roundup. "to" - recipients list "subject" - Subject @@ -1076,7 +1432,7 @@ "author" - (name, address) tuple or None for admin email Arguments are passed to the Mailer.standard_message code. - ''' + """ try: self.mailer.standard_message(to, subject, body, author) except MessageSendError, e: Modified: tracker/roundup-src/roundup/cgi/exceptions.py ============================================================================== --- tracker/roundup-src/roundup/cgi/exceptions.py (original) +++ tracker/roundup-src/roundup/cgi/exceptions.py Sun Mar 15 22:43:30 2009 @@ -1,20 +1,14 @@ -#$Id: exceptions.py,v 1.6 2004/11/18 14:10:27 a1s Exp $ -'''Exceptions for use in Roundup's web interface. -''' +"""Exceptions for use in Roundup's web interface. +""" __docformat__ = 'restructuredtext' +from roundup.exceptions import LoginError, Unauthorised import cgi class HTTPException(Exception): pass -class LoginError(HTTPException): - pass - -class Unauthorised(HTTPException): - pass - class Redirect(HTTPException): pass @@ -50,13 +44,13 @@ escaped. """ def __str__(self): - return ''' + return """ Roundup issue tracker: An error has occurred

        %s

        -'''%cgi.escape(self.args[0]) +"""%cgi.escape(self.args[0]) # vim: set filetype=python sts=4 sw=4 et si : Modified: tracker/roundup-src/roundup/cgi/form_parser.py ============================================================================== --- tracker/roundup-src/roundup/cgi/form_parser.py (original) +++ tracker/roundup-src/roundup/cgi/form_parser.py Sun Mar 15 22:43:30 2009 @@ -425,7 +425,9 @@ if entry not in existing: existing.append(entry) value = existing - value.sort() + # Sort the value in the same order used by + # Multilink.from_raw. + value.sort(key = lambda x: int(x)) elif value == '': # other types should be None'd if there's no value @@ -483,9 +485,13 @@ except IndexError, message: raise FormError(str(message)) - # make sure the existing multilink is sorted + # make sure the existing multilink is sorted. We must + # be sure to use the same sort order in all places, + # since we want to compare values with "=" or "!=". + # The canonical order (given in Multilink.from_raw) is + # by the numeric value of the IDs. if isinstance(proptype, hyperdb.Multilink): - existing.sort() + existing.sort(key = lambda x: int(x)) # "missing" existing values may not be None if not existing: @@ -563,11 +569,11 @@ # either have a non-empty content property or no property at all. In # the latter case, nothing will change. for (cn, id), props in all_props.items(): - if (id == '-1') and not props: + if id is not None and id.startswith('-') and not props: # new item (any class) with no content - ignore del all_props[(cn, id)] elif isinstance(self.db.classes[cn], hyperdb.FileClass): - if id == '-1': + if id is not None and id.startswith('-'): if not props.get('content', ''): del all_props[(cn, id)] elif props.has_key('content') and not props['content']: Modified: tracker/roundup-src/roundup/cgi/templating.py ============================================================================== --- tracker/roundup-src/roundup/cgi/templating.py (original) +++ tracker/roundup-src/roundup/cgi/templating.py Sun Mar 15 22:43:30 2009 @@ -341,7 +341,7 @@ # we want config to be exposed self.config = client.db.config - def __getitem__(self, item, desre=re.compile(r'(?P\w+)(?P[-\d]+)')): + def __getitem__(self, item, desre=re.compile(r'(?P[a-zA-Z_]+)(?P[-\d]+)')): # check to see if we're actually accessing an item m = desre.match(item) if m: @@ -473,6 +473,14 @@ raise Unauthorised("edit", self._classname, translator=self._client.translator) + def retire_check(self): + """ Raise the Unauthorised exception if the user's not permitted to + retire items of this class. + """ + if not self.is_retire_ok(): + raise Unauthorised("retire", self._classname, + translator=self._client.translator) + class HTMLClass(HTMLInputMixin, HTMLPermissions): """ Accesses through a class (either through *class* or *db.*) @@ -497,6 +505,12 @@ return self._db.security.hasPermission('Create', self._client.userid, self._classname) + def is_retire_ok(self): + """ Is the user allowed to retire items of the current class? + """ + return self._db.security.hasPermission('Retire', self._client.userid, + self._classname) + def is_view_ok(self): """ Is the user allowed to View the current class? """ @@ -530,24 +544,10 @@ for klass, htmlklass in propclasses: if not isinstance(prop, klass): continue - if form.has_key(item): - if isinstance(prop, hyperdb.Multilink): - value = lookupIds(self._db, prop, - handleListCGIValue(form[item]), fail_ok=1) - elif isinstance(prop, hyperdb.Link): - value = form[item].value.strip() - if value: - value = lookupIds(self._db, prop, [value], - fail_ok=1)[0] - else: - value = None - else: - value = form[item].value.strip() or None + if isinstance(prop, hyperdb.Multilink): + value = [] else: - if isinstance(prop, hyperdb.Multilink): - value = [] - else: - value = None + value = None return htmlklass(self._client, self._classname, None, prop, item, value, self._anonymous) @@ -615,9 +615,16 @@ s = StringIO.StringIO() writer = csv.writer(s) writer.writerow(props) + check = self._client.db.security.hasPermission for nodeid in self._klass.list(): l = [] for name in props: + # check permission to view this property on this item + if not check('View', self._client.userid, itemid=nodeid, + classname=self._klass.classname, property=name): + raise Unauthorised('view', self._klass.classname, + translator=self._client.translator) + row.append(str(klass.get(itemid, name))) value = self._klass.get(nodeid, name) if value is None: l.append('') @@ -695,7 +702,7 @@ if 'username' in properties.split( ',' ): sort = 'username' else: - sort = find_sort_key(self._klass) + sort = self._klass.orderprop() sort = '&@sort=' + sort if property: property = '&property=%s'%property @@ -775,13 +782,19 @@ HTMLInputMixin.__init__(self) def is_edit_ok(self): - """ Is the user allowed to Edit the current class? + """ Is the user allowed to Edit this item? """ return self._db.security.hasPermission('Edit', self._client.userid, self._classname, itemid=self._nodeid) + def is_retire_ok(self): + """ Is the user allowed to Reture this item? + """ + return self._db.security.hasPermission('Retire', self._client.userid, + self._classname, itemid=self._nodeid) + def is_view_ok(self): - """ Is the user allowed to View the current class? + """ Is the user allowed to View this item? """ if self._db.security.hasPermission('View', self._client.userid, self._classname, itemid=self._nodeid): @@ -789,7 +802,7 @@ return self.is_edit_ok() def is_only_view_ok(self): - """ Is the user only allowed to View (ie. not Edit) the current class? + """ Is the user only allowed to View (ie. not Edit) this item? """ return self.is_view_ok() and not self.is_edit_ok() @@ -878,7 +891,7 @@ prop = self[prop_n] if not isinstance(prop, HTMLProperty): continue - current[prop_n] = prop.plain() + current[prop_n] = prop.plain(escape=1) # make link if hrefable if (self._props.has_key(prop_n) and isinstance(self._props[prop_n], hyperdb.Link)): @@ -979,6 +992,7 @@ if labelprop is not None and \ labelprop != 'id': label = linkcl.get(linkid, labelprop) + label = cgi.escape(label) except IndexError: comments['no_link'] = self._( "The linked node" @@ -1002,7 +1016,8 @@ # there's no labelprop! if labelprop is not None and labelprop != 'id': try: - label = linkcl.get(args[k], labelprop) + label = cgi.escape(linkcl.get(args[k], + labelprop)) except IndexError: comments['no_link'] = self._( "The linked node" @@ -1012,7 +1027,8 @@ label = None if label is not None: if hrefable: - old = '%s'%(classname, args[k], label) + old = '%s'%(classname, + args[k], label) else: old = label; cell.append('%s: %s' % (self._(k), old)) @@ -1113,7 +1129,10 @@ # new template, using the specified classname and request pt = self._client.instance.templates.get(req.classname, 'search') - + # The context for a search page should be the class, not any + # node. + self._client.nodeid = None + # use our fabricated request return pt.render(self._client, req.classname, req) @@ -1203,6 +1222,25 @@ else: self._formname = name + # If no value is already present for this property, see if one + # is specified in the current form. + form = self._client.form + if not self._value and form.has_key(self._formname): + if isinstance(prop, hyperdb.Multilink): + value = lookupIds(self._db, prop, + handleListCGIValue(form[self._formname]), + fail_ok=1) + elif isinstance(prop, hyperdb.Link): + value = form.getfirst(self._formname).strip() + if value: + value = lookupIds(self._db, prop, [value], + fail_ok=1)[0] + else: + value = None + else: + value = form.getfirst(self._formname).strip() or None + self._value = value + HTMLInputMixin.__init__(self) def __repr__(self): @@ -1242,9 +1280,27 @@ return self.is_edit_ok() class StringHTMLProperty(HTMLProperty): - hyper_re = re.compile(r'((?P\w{3,6}://\S+[\w/])|' - r'(?P[-+=%/\w\.]+@[\w\.\-]+)|' - r'(?P(?P[A-Za-z_]+)(\s*)(?P\d+)))') + hyper_re = re.compile(r'''( + (?P + ( + (ht|f)tp(s?):// # protocol + ([\w]+(:\w+)?@)? # username/password + ([\w\-]+) # hostname + ((\.[\w-]+)+)? # .domain.etc + | # ... or ... + ([\w]+(:\w+)?@)? # username/password + www\. # "www." + ([\w\-]+\.)+ # hostname + [\w]{2,5} # TLD + ) + (:[\d]{1,5})? # port + (/[\w\-$.+!*(),;:@&=?/~\\#%]*)? # path etc. + )| + (?P[-+=%/\w\.]+@[\w\.\-]+)| + (?P(?P[A-Za-z_]+)(\s*)(?P\d+)) + )''', re.X | re.I) + protocol_re = re.compile('^(ht|f)tp(s?)://', re.I) + def _hyper_repl_item(self,match,replacement): item = match.group('item') cls = match.group('class').lower() @@ -1260,8 +1316,16 @@ def _hyper_repl(self, match): if match.group('url'): - s = match.group('url') - return '%s'%(s, s) + u = s = match.group('url') + if not self.protocol_re.search(s): + u = 'http://' + s + # catch an escaped ">" at the end of the URL + if s.endswith('>'): + u = s = s[:-4] + e = '>' + else: + e = '' + return '%s%s'%(u, s, e) elif match.group('email'): s = match.group('email') return '%s'%(s, s) @@ -1283,14 +1347,14 @@ """ Render a "hyperlinked" version of the text """ return self.plain(hyperlink=1) - def plain(self, escape=0, hyperlink=0, unchecked=0): + def plain(self, escape=0, hyperlink=0): """Render a "plain" representation of the property - "escape" turns on/off HTML quoting - "hyperlink" turns on/off in-text hyperlinking of URLs, email addresses and designators """ - if not self.is_view_ok() and not unchecked: + if not self.is_view_ok(): return self._('[hidden]') if self._value is None: @@ -1360,7 +1424,7 @@ s = self.plain(escape=0, hyperlink=0) if hyperlink: s = self.hyper_re.sub(self._hyper_repl_rst, s) - return ReStructuredText(s, writer_name="html")["body"].encode("utf-8", + return ReStructuredText(s, writer_name="html")["html_body"].encode("utf-8", "replace") def field(self, **kwargs): @@ -1369,7 +1433,7 @@ If not editable, just display the value via plain(). """ if not self.is_edit_ok(): - return self.plain() + return self.plain(escape=1) value = self._value if value is None: @@ -1423,7 +1487,7 @@ return value class PasswordHTMLProperty(HTMLProperty): - def plain(self): + def plain(self, escape=0): """ Render a "plain" representation of the property """ if not self.is_view_ok(): @@ -1439,7 +1503,7 @@ If not editable, just display the value via plain(). """ if not self.is_edit_ok(): - return self.plain() + return self.plain(escape=1) return self.input(type="password", name=self._formname, size=size) @@ -1459,7 +1523,7 @@ size=size) class NumberHTMLProperty(HTMLProperty): - def plain(self): + def plain(self, escape=0): """ Render a "plain" representation of the property """ if not self.is_view_ok(): @@ -1476,7 +1540,7 @@ If not editable, just display the value via plain(). """ if not self.is_edit_ok(): - return self.plain() + return self.plain(escape=1) value = self._value if value is None: @@ -1496,7 +1560,7 @@ class BooleanHTMLProperty(HTMLProperty): - def plain(self): + def plain(self, escape=0): """ Render a "plain" representation of the property """ if not self.is_view_ok(): @@ -1512,7 +1576,7 @@ If not editable, just display the value via plain(). """ if not self.is_edit_ok(): - return self.plain() + return self.plain(escape=1) value = self._value if isinstance(value, str) or isinstance(value, unicode): @@ -1549,7 +1613,7 @@ if self._offset is None : self._offset = self._prop.offset (self._db) - def plain(self): + def plain(self, escape=0): """ Render a "plain" representation of the property """ if not self.is_view_ok(): @@ -1600,7 +1664,7 @@ """ if not self.is_edit_ok(): if format is self._marker: - return self.plain() + return self.plain(escape=1) else: return self.pretty(format) @@ -1708,7 +1772,7 @@ else : date = "" return ('%s'%(self._classname, self._name, form, date, width, height, label)) @@ -1720,7 +1784,7 @@ if self._value and not isinstance(self._value, (str, unicode)): self._value.setTranslator(self._client.translator) - def plain(self): + def plain(self, escape=0): """ Render a "plain" representation of the property """ if not self.is_view_ok(): @@ -1744,7 +1808,7 @@ If not editable, just display the value via plain(). """ if not self.is_edit_ok(): - return self.plain() + return self.plain(escape=1) value = self._value if value is None: @@ -1793,7 +1857,10 @@ linkcl = self._db.classes[self._prop.classname] k = linkcl.labelprop(1) if num_re.match(self._value): - value = str(linkcl.get(self._value, k)) + try: + value = str(linkcl.get(self._value, k)) + except IndexError: + value = self._value else : value = self._value if escape: @@ -1806,7 +1873,7 @@ If not editable, just display the value via plain(). """ if not self.is_edit_ok(): - return self.plain() + return self.plain(escape=1) # edit field linkcl = self._db.getclass(self._prop.classname) @@ -1842,10 +1909,16 @@ If not editable, just display the value via plain(). """ if not self.is_edit_ok(): - return self.plain() + return self.plain(escape=1) + # Since None indicates the default, we need another way to + # indicate "no selection". We use -1 for this purpose, as + # that is the value we use when submitting a form without the + # value set. if value is None: value = self._value + elif value == '-1': + value = None linkcl = self._db.getclass(self._prop.classname) l = [''%(self._formname, height)] - k = linkcl.labelprop(1) - + # make sure we list the current values if they're retired for val in value: if val not in options: options.insert(0, val) + if not height: + height = len(options) + if value: + # The "no selection" option. + height += 1 + height = min(height, 7) + l = [' + + + + + + + + + + + + +
        +     
        +  
        +
        
        Added: tracker/roundup-src/share/roundup/templates/classic/html/_generic.help-search.html
        ==============================================================================
        --- (empty file)
        +++ tracker/roundup-src/share/roundup/templates/classic/html/_generic.help-search.html	Sun Mar 15 22:43:30 2009
        @@ -0,0 +1,13 @@
        +
        +  
        +    Frame for search input fields
        +  
        +  
        +    

        Generic template + help-search + or version for class + user + is not yet implemented

        + + + Added: tracker/roundup-src/share/roundup/templates/classic/html/_generic.help-submit.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/_generic.help-submit.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,73 @@ + + + + + + Generic submit page for framed helper windows + + + + + +
        + 
        +
        + +
        + + + + +
        + + + Added: tracker/roundup-src/share/roundup/templates/classic/html/_generic.help.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/_generic.help.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,98 @@ + + + + + + + <tal:x i18n:name="property" + tal:content="property" i18n:translate="" /> help - <span i18n:name="tracker" + tal:replace="config/TRACKER_NAME" /> + + + + + +
        + +
        + + + + +
        + + + + + + +
        + + + + + + + + + + + + + + + + +
         x
        + + + +
         x
        + +
        + + Added: tracker/roundup-src/share/roundup/templates/classic/html/_generic.index.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/_generic.index.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,70 @@ + + + +<span tal:replace="python:context._classname.capitalize()" + i18n:name="class" /> editing - <span i18n:name="tracker" + tal:replace="config/TRACKER_NAME" /> + editing + + + +You are not allowed to view this page. + +Please login with your username and password. + + + +

        + You may edit the contents of the + + class using this form. Commas, newlines and double quotes (") must be + handled delicately. You may include commas and newlines by enclosing the + values in double-quotes ("). Double quotes themselves must be quoted by + doubling (""). +

        + +

        + Multilink properties have their multiple values colon (":") separated + (... ,"one:two:three", ...) +

        + +

        + Remove entries by deleting their line. Add new entries by appending + them to the table - put an X in the id column. +

        +
        +
        + +
        + + +
        +
        + + + + + + + + + + +
         
         
        + + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/_generic.item.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/_generic.item.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,53 @@ + +<span tal:replace="python:context._classname.capitalize()" + i18n:name="class" /> editing - <span i18n:name="tracker" + tal:replace="config/TRACKER_NAME" /> + editing + + + +

        + You are not allowed to view this page.

        + +

        + Please login with your username and password.

        + +
        + +
        + + + + + + + + + + + + + + + +
          + submit button will go here +
        + +
        + + + +
        + + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/file.index.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/file.index.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,31 @@ + + +List of files - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker" /> +List of files + + + + + + + + + + + + + + + + + +
        DownloadContent TypeUploaded ByDate
        + dld link + content typecreator's namecreation date
        + + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/file.item.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/file.item.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,53 @@ + +File display - <span + i18n:name="tracker" tal:replace="config/TRACKER_NAME" /> +File display + + + +

        + You are not allowed to view this page.

        + +

        + Please login with your username and password.

        + +
        + + + + + + + + + + + + + + + +
        Name
        Content Type
        +   + + + + submit button here
        +
        + +download + + + + + + Added: tracker/roundup-src/share/roundup/templates/classic/html/help.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/help.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,38 @@ + + + + + + x + + + + + + + + + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/help_controls.js ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/help_controls.js Sun Mar 15 22:43:30 2009 @@ -0,0 +1,324 @@ +// initial values for either Nosy, Superseder, Keyword and Waiting On, +// depending on which has called +original_field = form[field].value; + +// Some browsers (ok, IE) don't define the "undefined" variable. +undefined = document.geez_IE_is_really_friggin_annoying; + +function trim(value) { + var temp = value; + var obj = /^(\s*)([\W\w]*)(\b\s*$)/; + if (obj.test(temp)) { temp = temp.replace(obj, '$2'); } + var obj = / /g; + while (temp.match(obj)) { temp = temp.replace(obj, " "); } + return temp; +} + +function determineList() { + // generate a comma-separated list of the checked items + var list = new String(''); + + // either a checkbox object or an array of checkboxes + var check = document.frm_help.check; + + if ((check.length == undefined) && (check.checked != undefined)) { + // only one checkbox on page + if (check.checked) { + list = check.value; + } + } else { + // array of checkboxes + for (box=0; box < check.length; box++) { + if (check[box].checked) { + if (list.length == 0) { + separator = ''; + } + else { + separator = ','; + } + // we used to use an Array and push / join, but IE5.0 sux + list = list + separator + check[box].value; + } + } + } + return list; +} + +/** + * update the field in the opening window; + * the text_field variable must be set in the calling page + */ +function updateOpener() { + // write back to opener window + if (document.frm_help.check==undefined) { return; } + form[field].value = text_field.value; +} + +function updateList() { + // write back to opener window + if (document.frm_help.check==undefined) { return; } + form[field].value = determineList(); +} + +function updatePreview() { + // update the preview box + if (document.frm_help.check==undefined) { return; } + writePreview(determineList()); +} + +function clearList() { + // uncheck all checkboxes + if (document.frm_help.check==undefined) { return; } + for (box=0; box < document.frm_help.check.length; box++) { + document.frm_help.check[box].checked = false; + } +} + +function reviseList_framed(form, textfield) { + // update the checkboxes based on the preview field + // alert('reviseList_framed') + // alert(form) + if (form.check==undefined) + return; + // alert(textfield) + var to_check; + var list = textfield.value.split(","); + if (form.check.length==undefined) { + check = form.check; + to_check = false; + for (val in list) { + if (check.value==trim(list[val])) { + to_check = true; + break; + } + } + check.checked = to_check; + } else { + for (box=0; box < form.check.length; box++) { + check = form.check[box]; + to_check = false; + for (val in list) { + if (check.value==trim(list[val])) { + to_check = true; + break; + } + } + check.checked = to_check; + } + } +} + +function reviseList(vals) { + // update the checkboxes based on the preview field + if (document.frm_help.check==undefined) { return; } + var to_check; + var list = vals.split(","); + if (document.frm_help.check.length==undefined) { + check = document.frm_help.check; + to_check = false; + for (val in list) { + if (check.value==trim(list[val])) { + to_check = true; + break; + } + } + check.checked = to_check; + } else { + for (box=0; box < document.frm_help.check.length; box++) { + check = document.frm_help.check[box]; + to_check = false; + for (val in list) { + if (check.value==trim(list[val])) { + to_check = true; + break; + } + } + check.checked = to_check; + } + } +} + +function resetList() { + // reset preview and check boxes to initial values + if (document.frm_help.check==undefined) { return; } + writePreview(original_field); + reviseList(original_field); +} + +function writePreview(val) { + // writes a value to the text_preview + document.frm_help.text_preview.value = val; +} + +function focusField(name) { + for(i=0; i < document.forms.length; ++i) { + var obj = document.forms[i].elements[name]; + if (obj && obj.focus) {obj.focus();} + } +} + +function selectField(name) { + for(i=0; i < document.forms.length; ++i) { + var obj = document.forms[i].elements[name]; + if (obj && obj.focus){obj.focus();} + if (obj && obj.select){obj.select();} + } +} + +function checkRequiredFields(fields) +{ + var bonk=''; + var res=''; + var argv = checkRequiredFields.arguments; + var argc = argv.length; + var input = ''; + var val=''; + + for (var i=0; i < argc; i++) { + fi = argv[i]; + input = document.getElementById(fi); + if (input) { + val = input.value + if (val == '' || val == '-1' || val == -1) { + if (res == '') { + res = fi; + bonk = input; + } else { + res += ', '+fi; + } + } + } else { + alert('Field with id='+fi+' not found!') + } + } + if (res == '') { + return submit_once(); + } else { + alert('Missing value here ('+res+')!'); + if (window.event && window.event.returnvalue) { + event.returnValue = 0; // work-around for IE + } + bonk.focus(); + return false; + } +} + +/** + * seeks the given value (2nd argument) + * in the value of the given input element (1st argument), + * which is considered a list of values, separated by commas + */ +function has_value(input, val) +{ + var actval = input.value + var arr = feld.value.split(','); + var max = arr.length; + for (i=0;i remove_val() + * + * This will work nicely even for batched lists + */ +function append_val(name, val) +{ + var feld = document.itemSynopsis[name]; + var actval = feld.value; + if (actval == '') { + feld.value = val + } else { + var arr = feld.value.split(','); + var max = arr.length; + for (i=0;i append_val() + */ +function remove_val(name, val) +{ + var feld = document.itemSynopsis[name]; + var actval = feld.value; + var changed=false; + if (actval == '') { + return + } else { + var arr = feld.value.split(','); + var max = arr.length; + var neu = '' + for (i=0;i +List of classes - <span + i18n:name="tracker" tal:replace="config/TRACKER_NAME" /> +List of classes + + + + + + + + + + + + + +
        + classname +
        nametype
        + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/home.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/home.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,10 @@ + + Added: tracker/roundup-src/share/roundup/templates/classic/html/issue.index.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/issue.index.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,166 @@ + + + + <span tal:omit-tag="true" i18n:translate="" >List of issues</span> + <span tal:condition="request/dispname" + tal:replace="python:' - %s '%request.dispname" + /> - <span tal:replace="config/TRACKER_NAME" /> + + + List of issues + + + + +

        + You are not allowed to view this page.

        + +

        + Please login with your username and password.

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        PriorityIDCreationActivityActorKeywordTitleStatusCreatorAssigned To
        + + + +
               + title +    
        + + + + + + +
        +
        + +Download as CSV + +
        + + + + + + + + + + + + + + + + + + + +
        + Sort on: + + + Descending: +
        + Group on: + + + Descending: +
        + + +
        +
        + +
        + + +
        vim: sw=1 ts=8 et si + Added: tracker/roundup-src/share/roundup/templates/classic/html/issue.item.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/issue.item.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,197 @@ + + + +<tal:block condition="context/id" i18n:translate="" + >Issue <tal:x tal:content="context/id" i18n:name="id" + />: <tal:x content="context/title" i18n:name="title" + /> - <tal:x content="config/TRACKER_NAME" i18n:name="tracker" +/></tal:block> +<tal:block condition="not:context/id" i18n:translate="" + >New Issue - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker" +/></tal:block> + + + New Issue + New Issue Editing + Issue + Issue Editing + + + + +

        + You are not allowed to view this page.

        + +

        + Please login with your username and password.

        + +
        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        Titletitle
        PrioritypriorityStatusstatus
        Superseder + + + +
        View: + +
        +
        Nosy List + +
        +
        Assigned Toassignedto menuKeywords + + +
        Change Note + +
        File
        +   + + + + submit button + Make a copy +
        +
        + + + + + + + + +
        Note: highlighted fields are required.
        +
        + +

        + Created on + by , + last changed + by . +

        + + + + + + + + + + + + + + + + +
        Files
        File nameUploadedTypeEditRemove
        + dld link + + creator's name, + creation date + + edit + +
        + + + +
        +
        + + + + + + + + + + + + + + +
        Messages
        msg (view)Author: Date: +
        + + + +
        +
        +
        content
        +
        + + + +
        + + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/issue.search.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/issue.search.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,234 @@ + +Issue searching - <span + i18n:name="tracker" tal:replace="config/TRACKER_NAME" /> +Issue searching + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
         Filter onDisplaySort onGroup on
        All text*:   
        Title: 
        Keyword: + +
        ID: 
        Creation Date:
        Creator: + +
        Activity: 
        Actor: + +  
        Priority: + +
        Status: + + + + +
        Assigned to: + + + + +
        No Sort or group:  
        Pagesize:
        Start With:
        Sort Descending: +
        Group Descending: +
        Query name**: + + +
        +   + +
          + + *: The "all text" field will look in message bodies and issue titles +
        + + **: If you supply a name, the query will be saved off and available as a + link in the sidebar + +
        + +
        + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/keyword.item.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/keyword.item.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,55 @@ + + +Keyword editing - <span + i18n:name="tracker" tal:replace="config/TRACKER_NAME" /> +Keyword editing + + + + + + + + + + +
        Existing Keywords
        + keyword here +
        + To edit an existing keyword (for spelling or typing errors), + click on its entry above. +
        + +

        + To create a new keyword, enter it below and click "Submit New Entry". +

        + +
        + + + + + + + + + + + +
        Keywordname
        +   + + + + submit button will go here +
        +
        + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/msg.index.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/msg.index.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,25 @@ + +List of messages - <span tal:replace="config/TRACKER_NAME" + i18n:name="tracker"/> +Message listing + + + + + + + + + + + + + + + +
        Messages
        authordate
        content
        + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/msg.item.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/msg.item.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,83 @@ + + + +<tal:block condition="context/id" i18n:translate="" + >Message <span tal:replace="context/id" i18n:name="id" + /> - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker" +/></tal:block> +<tal:block condition="not:context/id" i18n:translate="" + >New Message - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker" +/></tal:block> + + + New Message + New Message Editing + Message + Message Editing + + + +

        + You are not allowed to view this page.

        + +

        + Please login with your username and password.

        + +
        + + + + + + + + + + + + + + + + +
        Author
        Recipients
        Date
        + + + + + + +
        Content
        + + + + + + + + + + + +
        Files
        File nameUploaded
        + dld link + + creator's name, + creation date +
        + + + +
        + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/page.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/page.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,347 @@ + + + +title goes here + + + + + + + + + + + + + + + + + + + + + + + +
          +
        +

        body title

        +
        + +
        +

        +

        + + clear this message +

        +
        Page content goes here
        + +
        +
        + + + +
        + + + + + + + + + + + + + + + + (cal) + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
        • + +
        • +
        • + + +
        • +
        + + + + + + + + + + + + + + + + + + + + + + + + + Added: tracker/roundup-src/share/roundup/templates/classic/html/query.edit.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/query.edit.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,111 @@ + + +"Your Queries" Editing - <span tal:replace="config/TRACKER_NAME" + i18n:name="tracker" /> +"Your Queries" Editing + + + +You are not allowed to edit queries. + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        QueryInclude in "Your Queries"EditPrivate to you? 
        query + + + [query is retired]
        query + + edit + + + +
        query + + + edit + [not yours to edit]
        + + + +
        + +
        + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/query.item.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/query.item.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,3 @@ + + + Added: tracker/roundup-src/share/roundup/templates/classic/html/style.css ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/style.css Sun Mar 15 22:43:30 2009 @@ -0,0 +1,433 @@ +/* main page styles */ +body.body { + font-family: sans-serif, Arial, Helvetica; + background-color: white; + color: #333; + margin: 0; +} +a[href]:hover { + color:blue; + text-decoration: underline; +} +a[href], a[href]:link { + color:blue; + text-decoration: none; +} + +table.body { + border: 0; + padding: 0; + border-spacing: 0; + border-collapse: separate; +} + +td.page-header-left { + padding: 5px; + border-bottom: 1px solid #444; +} +td.sidebar { + padding: 1px 0 0 1px; + white-space: nowrap; +} + +/* don't display the sidebar when printing */ + at media print { + td.page-header-left { + display: none; + } + td.sidebar { + display: none; + } + .index-controls { + display: none; + } + #searchbox { + display: none; + } +} + +td.page-header-top { + padding: 5px; + border-bottom: 1px solid #444; +} +#searchbox { + float: right; +} + +div#body-title { + float: left; +} + + +div#searchbox { + float: right; + padding-top: 1em; +} + +div#searchbox input#search-text { + width: 10em; +} + +form { + margin: 0; +} + +textarea { + font-family: monospace; +} + +td.sidebar p.classblock { + padding: 2px 5px 2px 5px; + margin: 1px; + border: 1px solid #444; + background-color: #eee; +} + +td.sidebar p.userblock { + padding: 2px 5px 2px 5px; + margin: 1px 1px 1px 1px; + border: 1px solid #444; + background-color: #eef; +} + +.form-small { + padding: 0; + font-size: 75%; +} + + +td.content { + padding: 1px 5px 1px 5px; + vertical-align: top; + width: 100%; +} + +td.date, th.date { + white-space: nowrap; +} + +p.ok-message { + background-color: #22bb22; + padding: 5px; + color: white; + font-weight: bold; +} +p.error-message { + background-color: #bb2222; + padding: 5px; + color: white; + font-weight: bold; +} +p.error-message a[href] { + color: white; + text-decoration: underline; +} + + +/* style for search forms */ +ul.search-checkboxes { + display: inline; + padding: 0; + list-style: none; +} +ul.search-checkboxes > li { + display: inline; + padding-right: .5em; +} + + +/* style for forms */ +table.form { + padding: 2px; + border-spacing: 0; + border-collapse: separate; +} + +table.form th { + color: #338; + text-align: right; + vertical-align: top; + font-weight: normal; + white-space: nowrap; +} + +table.form th.header { + font-weight: bold; + background-color: #eef; + text-align: left; +} + +table.form th.required { + font-weight: bold; +} + +table.form td { + color: #333; + empty-cells: show; + vertical-align: top; +} + +table.form td.optional { + font-weight: bold; + font-style: italic; +} + +table.form td.html { + color: #777; +} + +/* style for lists */ +table.list { + border-spacing: 0; + border-collapse: separate; + width: 100%; +} + +table.list th { + padding: 0 4px 0 4px; + color: #404070; + background-color: #eef; + border: 1px solid white; + vertical-align: top; + empty-cells: show; +} +table.list th a[href]:hover { color: #404070 } +table.list th a[href]:link { color: #404070 } +table.list th a[href] { color: #404070 } +table.list th.group { + background-color: #f4f4ff; + text-align: center; +} + +table.list td { + padding: 0 4px 0 4px; + border: 1px solid white; + color: #404070; + background-color: #efefef; + vertical-align: top; + empty-cells: show; +} + +table.list tr.navigation th { + width: 33%; + border-style: hidden; + text-align: center; +} +table.list tr.navigation td { + border: none +} +table.list tr.navigation th:first-child { + text-align: left; +} +table.list tr.navigation th:last-child { + text-align: right; +} + + +/* style for message displays */ +table.messages { + border-spacing: 0; + border-collapse: separate; + width: 100%; +} + +table.messages th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.messages th { + font-weight: bold; + color: black; + text-align: left; + border-bottom: 1px solid #afafaf; +} + +table.messages td { + font-family: monospace; + background-color: #efefef; + border-bottom: 1px solid #afafaf; + color: black; + empty-cells: show; + border-right: 1px solid #afafaf; + vertical-align: top; + padding: 2px 5px 2px 5px; +} + +table.messages td:first-child { + border-left: 1px solid #afafaf; + border-right: 1px solid #afafaf; +} + +/* style for file displays */ +table.files { + border-spacing: 0; + border-collapse: separate; + width: 100%; +} + +table.files th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.files th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; +} + +table.files td { + font-family: monospace; + empty-cells: show; +} + +/* style for history displays */ +table.history { + border-spacing: 0; + border-collapse: separate; + width: 100%; +} + +table.history th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; + font-size: 100%; +} + +table.history th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; + font-size: 90%; +} + +table.history td { + font-size: 90%; + vertical-align: top; + empty-cells: show; +} + + +/* style for class list */ +table.classlist { + border-spacing: 0; + border-collapse: separate; + width: 100%; +} + +table.classlist th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.classlist th { + font-weight: bold; + text-align: left; +} + + +/* style for class help display */ +table.classhelp { /* the table-layout: fixed; */ + table-layout: fixed; /* compromises quality for speed */ + overflow: hidden; + font-size: .9em; + padding-bottom: 3em; +} + +table.classhelp th { + font-weight: normal; + text-align: left; + color: #444; + background-color: #efefef; + border-bottom: 1px solid #afafaf; + border-top: 1px solid #afafaf; + text-transform: uppercase; + vertical-align: middle; + line-height:1.5em; +} + +table.classhelp td { + vertical-align: middle; + padding-right: .2em; + border-bottom: 1px solid #efefef; + text-align: left; + empty-cells: show; + white-space: nowrap; + vertical-align: middle; +} + +table.classhelp tr:hover { + background-color: #eee; +} + +label.classhelp-label { + cursor: pointer; +} + +#classhelp-controls { + position: fixed; + display: block; + top: auto; + right: 0; + bottom: 0; + left: 0; + padding: .5em; + border-top: 2px solid #444; + background-color: #eee; +} + +#classhelp-controls input.apply { + width: 7em; + font-weight: bold; + margin-right: 2em; + margin-left: 2em; +} + +#classhelp-controls input.preview { + margin-right: 3em; + margin-left: 1em; +} + +/* style for "other" displays */ +table.otherinfo { + border-spacing: 0; + border-collapse: separate; + width: 100%; +} + +table.otherinfo th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.otherinfo th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; +} +input[type="text"]:focus, +input[type="checkbox"]:focus, +input[type="radio"]:focus, +input[type="password"]:focus, +textarea:focus, select:focus { + background-color: #ffffc0; +} + +/* vim: sts=2 sw=2 et +*/ Added: tracker/roundup-src/share/roundup/templates/classic/html/user.forgotten.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/user.forgotten.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,43 @@ + + +Password reset request - <span + i18n:name="tracker" tal:replace="config/TRACKER_NAME" /> +Password reset request + + +

        You have two options if you have forgotten your password. +If you know the email address you registered with, enter it below.

        + +
        + + + + + + + + + +
        Email Address:
          + + + +
        + +

        Or, if you know your username, then enter it below.

        + + + + +
        Username:
        +
        + +

        A confirmation email will be sent to you - +please follow the instructions within it to complete the reset process.

        + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/user.help-search.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/user.help-search.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,85 @@ + + + Search input for user helper + + + + + +
        +    
        + + + + + + + + + + + + + + + + + + + + + + + + +
        Name
        Phone
        role + +
          + + + + + + +
        + +
        +
        +
        +  
        +
        
        Added: tracker/roundup-src/share/roundup/templates/classic/html/user.help.html
        ==============================================================================
        --- (empty file)
        +++ tracker/roundup-src/share/roundup/templates/classic/html/user.help.html	Sun Mar 15 22:43:30 2009
        @@ -0,0 +1,49 @@
        +
        +
        +  
        +      
        +      
        +      
        +      <tal:x i18n:translate=""><tal:x i18n:name="property"
        +       tal:content="property" i18n:translate="" /> help - <span i18n:name="tracker"
        +	       tal:replace="config/TRACKER_NAME" /></tal:x>
        +      
        +      
        +      
        +  
        +
        +  
        +  
        +  
        +  
        +  
        +
        +
        +  <body>
        +<p i18n:translate="">
        +Your browser is not capable of using frames; you should be redirected immediately,
        +or visit <a href="#" tal:attributes="href string:?${qs}&template=help-noframes"
        +i18n:name="link">this link</a>.
        +</p>
        +</body>
        +
        +
        +
        
        Added: tracker/roundup-src/share/roundup/templates/classic/html/user.index.html
        ==============================================================================
        --- (empty file)
        +++ tracker/roundup-src/share/roundup/templates/classic/html/user.index.html	Sun Mar 15 22:43:30 2009
        @@ -0,0 +1,49 @@
        +
        +
        +User listing - <span
        + i18n:name="tracker" tal:replace="config/TRACKER_NAME" />
        +User listing
        +
        +
        +You are not allowed to view this page.
        +
        +Please login with your username and password.
        +
        +
        +
        + 
        + 
        + 
        + 
        + 
        + 
        +
        +
        +
        + 
        + 
        + 
        + 
        + 
        + 
        +
        +
        +
        UsernameReal nameOrganisationEmail addressPhone numberRetire
        + username +      +
        + + + +
        +
        + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/user.item.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/user.item.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,169 @@ + + + +<tal:if condition="context/id" i18n:translate="" + >User <tal:x content="context/id" i18n:name="id" + />: <tal:x content="context/username" i18n:name="title" + /> - <tal:x content="config/TRACKER_NAME" i18n:name="tracker" +/></tal:if> +<tal:if condition="not:context/id" i18n:translate="" + >New User - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker" +/></tal:if> + + + + + + + New User + New User Editing + User + User Editing + + + + +

        + You are not allowed to view this page.

        + +

        + Please login with your username and password.

        + +
        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        Name
        Login Name
        Login Password
        Confirm Password
        + + + + + + + (to give the user more than one role, + enter a comma,separated,list) +
        Phone
        Organisation
        Timezone + (this is a numeric hour offset, the default is + ) +
        E-mail address + calvin at the-z.org + + + +   +
        + +
        +   + + + + +
        +
        + + + + + + + + +
        Note: highlighted fields are required.
        +
        + + + +
        + + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/user.register.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/user.register.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,81 @@ + + +Registering with <span i18n:name="tracker" + tal:replace="db/config/TRACKER_NAME" /> +Registering with + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        Namerealname
        Login Nameusername
        Login Passwordpassword
        Confirm Passwordpassword
        Rolesroles + +
        Phonephone
        Organisationorganisation
        E-mail addressaddress
        Alternate E-mail addresses
        One address per line
        alternate_addresses
          + + + + +
        +
        + + + + + + + + +
        Note: highlighted fields are required.
        +
        + + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/user.rego_progress.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/user.rego_progress.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,16 @@ + + +Registration in progress - <span i18n:name="tracker" + tal:replace="config/TRACKER_NAME" /> +Registration in progress... + + +

        You will shortly receive an email +to confirm your registration. To complete the registration process, +visit the link indicated in the email. +

        + + +
        Added: tracker/roundup-src/share/roundup/templates/classic/html/user_utils.js ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/classic/html/user_utils.js Sun Mar 15 22:43:30 2009 @@ -0,0 +1,114 @@ +// User Editing Utilities + +/** + * for new users: + * Depending on the input field which calls it, takes the value + * and dispatches it to certain other input fields: + * + * address + * +-> username + * | `-> realname + * `-> organisation + */ +function split_name(that) { + var raw = that.value + var val = trim(raw) + if (val == '') { + return + } + var username='' + var realname='' + var address='' + switch (that.name) { + case 'address': + address=val + break + case 'username': + username=val + break + case 'realname': + realname=val + break + case 'firstname': + case 'lastname': + return + default: + alert('Ooops - unknown name field '+that.name+'!') + return + } + var the_form = that.form; + + function field_empty(name) { + return the_form[name].value == '' + } + + // no break statements - on purpose! + switch (that.name) { + case 'address': + var split1 = address.split('@') + if (field_empty('username')) { + username = split1[0] + the_form.username.value = username + } + if (field_empty('organisation')) { + the_form.organisation.value = default_organisation(split1[1]) + } + case 'username': + if (field_empty('realname')) { + realname = Cap(username.split('.').join(' ')) + the_form.realname.value = realname + } + case 'realname': + if (field_empty('username')) { + username = Cap(realname.replace(' ', '.')) + the_form.username.value = username + } + if (the_form.firstname && the_form.lastname) { + var split2 = realname.split(' ') + var firstname='', lastname='' + firstname = split2[0] + lastname = split2.slice(1).join(' ') + if (field_empty('firstname')) { + the_form.firstname.value = firstname + } + if (field_empty('lastname')) { + the_form.lastname.value = lastname + } + } + } +} + +function SubCap(str) { + switch (str) { + case 'de': case 'do': case 'da': + case 'du': case 'von': + return str; + } + if (str.toLowerCase().slice(0,2) == 'mc') { + return 'Mc'+str.slice(2,3).toUpperCase()+str.slice(3).toLowerCase() + } + return str.slice(0,1).toUpperCase()+str.slice(1).toLowerCase() +} + +function Cap(str) { + var liz = str.split(' ') + for (var i=0; i/db/files/] +# type = String() [MIME type of the content, default 'text/plain'] +msg = FileClass(db, "msg", + author=Link("user", do_journal='no'), + recipients=Multilink("user", do_journal='no'), + date=Date(), + summary=String(), + files=Multilink("file"), + messageid=String(), + inreplyto=String()) + +file = FileClass(db, "file", + name=String()) + +# IssueClass automatically gets these properties in addition to the Class ones: +# title = String() +# messages = Multilink("msg") +# files = Multilink("file") +# nosy = Multilink("user") +# superseder = Multilink("issue") +issue = IssueClass(db, "issue", + assignedto=Link("user"), + keyword=Multilink("keyword"), + priority=Link("priority"), + status=Link("status")) + +# +# TRACKER SECURITY SETTINGS +# +# See the configuration and customisation document for information +# about security setup. + +# +# REGULAR USERS +# +# Give the regular users access to the web and email interface +db.security.addPermissionToRole('User', 'Web Access') +db.security.addPermissionToRole('User', 'Email Access') + +# Assign the access and edit Permissions for issue, file and message +# to regular users now +for cl in 'issue', 'file', 'msg', 'keyword': + db.security.addPermissionToRole('User', 'View', cl) + db.security.addPermissionToRole('User', 'Edit', cl) + db.security.addPermissionToRole('User', 'Create', cl) +for cl in 'priority', 'status': + db.security.addPermissionToRole('User', 'View', cl) + +# May users view other user information? Comment these lines out +# if you don't want them to +db.security.addPermissionToRole('User', 'View', 'user') + +# Users should be able to edit their own details -- this permission is +# limited to only the situation where the Viewed or Edited item is their own. +def own_record(db, userid, itemid): + '''Determine whether the userid matches the item being accessed.''' + return userid == itemid +p = db.security.addPermission(name='View', klass='user', check=own_record, + description="User is allowed to view their own user details") +db.security.addPermissionToRole('User', p) +p = db.security.addPermission(name='Edit', klass='user', check=own_record, + description="User is allowed to edit their own user details") +db.security.addPermissionToRole('User', p) + +# Users should be able to edit and view their own queries. They should also +# be able to view any marked as not private. They should not be able to +# edit others' queries, even if they're not private +def view_query(db, userid, itemid): + private_for = db.query.get(itemid, 'private_for') + if not private_for: return True + return userid == private_for +def edit_query(db, userid, itemid): + return userid == db.query.get(itemid, 'creator') +p = db.security.addPermission(name='View', klass='query', check=view_query, + description="User is allowed to view their own and public queries") +db.security.addPermissionToRole('User', p) +p = db.security.addPermission(name='Edit', klass='query', check=edit_query, + description="User is allowed to edit their queries") +db.security.addPermissionToRole('User', p) +p = db.security.addPermission(name='Retire', klass='query', check=edit_query, + description="User is allowed to retire their queries") +db.security.addPermissionToRole('User', p) +p = db.security.addPermission(name='Create', klass='query', + description="User is allowed to create queries") +db.security.addPermissionToRole('User', p) + + +# +# ANONYMOUS USER PERMISSIONS +# +# Let anonymous users access the web interface. Note that almost all +# trackers will need this Permission. The only situation where it's not +# required is in a tracker that uses an HTTP Basic Authenticated front-end. +db.security.addPermissionToRole('Anonymous', 'Web Access') + +# Let anonymous users access the email interface (note that this implies +# that they will be registered automatically, hence they will need the +# "Create" user Permission below) +# This is disabled by default to stop spam from auto-registering users on +# public trackers. +#db.security.addPermissionToRole('Anonymous', 'Email Access') + +# Assign the appropriate permissions to the anonymous user's Anonymous +# Role. Choices here are: +# - Allow anonymous users to register +db.security.addPermissionToRole('Anonymous', 'Create', 'user') + +# Allow anonymous users access to view issues (and the related, linked +# information) +for cl in 'issue', 'file', 'msg', 'keyword', 'priority', 'status': + db.security.addPermissionToRole('Anonymous', 'View', cl) + +# [OPTIONAL] +# Allow anonymous users access to create or edit "issue" items (and the +# related file and message items) +#for cl in 'issue', 'file', 'msg': +# db.security.addPermissionToRole('Anonymous', 'Create', cl) +# db.security.addPermissionToRole('Anonymous', 'Edit', cl) + + +# vim: set filetype=python sts=4 sw=4 et si : Added: tracker/roundup-src/share/roundup/templates/minimal/TEMPLATE-INFO.txt ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/TEMPLATE-INFO.txt Sun Mar 15 22:43:30 2009 @@ -0,0 +1,8 @@ +Name: minimal +Description: This is an empty tracker - it must be customised for it to be + useful! It only defines the bare minimum of information - the + user database and the two default users (admin and anonymous). + The rest is entirely up to you! Not recommended for first-time + Roundup users (it's easier to tweak the Classic tracker). +Intended-For: Roundup experts who need a clean slate to start with. + Added: tracker/roundup-src/share/roundup/templates/minimal/detectors/userauditor.py ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/detectors/userauditor.py Sun Mar 15 22:43:30 2009 @@ -0,0 +1,94 @@ +# Copyright (c) 2003 Richard Jones (richard at mechanicalcat.net) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +#$Id$ + +import re + +# regular expression thanks to: http://www.regular-expressions.info/email.html +# this is the "99.99% solution for syntax only". +email_regexp = (r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*", r"(localhost|(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9]))") +email_rfc = re.compile('^' + email_regexp[0] + '@' + email_regexp[1] + '$', re.IGNORECASE) +email_local = re.compile('^' + email_regexp[0] + '$', re.IGNORECASE) + +def valid_address(address): + ''' If we see an @-symbol in the address then check against the full + RFC syntax. Otherwise it is a local-only address so only check + the local part of the RFC syntax. + ''' + if '@' in address: + return email_rfc.match(address) + else: + return email_local.match(address) + +def get_addresses(user): + ''' iterate over all known addresses in a newvalues dict + this takes of the address/alterate_addresses handling + ''' + if user.has_key('address'): + yield user['address'] + if user.get('alternate_addresses', None): + for address in user['alternate_addresses'].split('\n'): + yield address + +def audit_user_fields(db, cl, nodeid, newvalues): + ''' Make sure user properties are valid. + + - email address is syntactically valid + - email address is unique + - roles specified exist + - timezone is valid + ''' + + for address in get_addresses(newvalues): + if not valid_address(address): + raise ValueError, 'Email address syntax is invalid' + + check_main = db.user.stringFind(address=address) + # make sure none of the alts are owned by anyone other than us (x!=nodeid) + check_alts = [x for x in db.user.filter(None, {'alternate_addresses' : address}) if x != nodeid] + if check_main or check_alts: + raise ValueError, 'Email address %s already in use' % address + + for rolename in [r.lower().strip() for r in newvalues.get('roles', '').split(',')]: + if rolename and not db.security.role.has_key(rolename): + raise ValueError, 'Role "%s" does not exist'%rolename + + tz = newvalues.get('timezone', None) + if tz: + # if they set a new timezone validate the timezone by attempting to + # use it before we store it to the db. + import roundup.date + import datetime + try: + TZ = roundup.date.get_timezone(tz) + dt = datetime.datetime.now() + local = TZ.localize(dt).utctimetuple() + except IOError: + raise ValueError, 'Timezone "%s" does not exist' % tz + except ValueError: + raise ValueError, 'Timezone "%s" exceeds valid range [-23...23]' % tz + +def init(db): + # fire before changes are made + db.user.audit('set', audit_user_fields) + db.user.audit('create', audit_user_fields) + +# vim: sts=4 sw=4 et si Added: tracker/roundup-src/share/roundup/templates/minimal/extensions/README.txt ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/extensions/README.txt Sun Mar 15 22:43:30 2009 @@ -0,0 +1,6 @@ +This directory is for tracker extensions: + +- CGI Actions +- Templating functions + +See the customisation doc for more information. Added: tracker/roundup-src/share/roundup/templates/minimal/html/_generic.404.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/_generic.404.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,9 @@ + + +Item Not Found + + + +There is no with id + + Added: tracker/roundup-src/share/roundup/templates/minimal/html/_generic.calendar.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/_generic.calendar.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,18 @@ + + + + + + + + + + + Added: tracker/roundup-src/share/roundup/templates/minimal/html/_generic.collision.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/_generic.collision.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,16 @@ + +<span tal:replace="python:context._classname.capitalize()" + i18n:name="class" /> Edit Collision - <span i18n:name="tracker" + tal:replace="config/TRACKER_NAME" /> + Edit Collision + + + + Added: tracker/roundup-src/share/roundup/templates/minimal/html/_generic.help.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/_generic.help.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,98 @@ + + + + + + + <tal:x i18n:name="property" + tal:content="property" i18n:translate="" /> help - <span i18n:name="tracker" + tal:replace="config/TRACKER_NAME" /> + + + + + +
        + +
        + + + + +
        + + + + + + +
        + + + + + + + + + + + + + + + + +
         x
        + + + +
         x
        + +
        + + Added: tracker/roundup-src/share/roundup/templates/minimal/html/_generic.index.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/_generic.index.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,70 @@ + + + +<span tal:replace="python:context._classname.capitalize()" + i18n:name="class" /> editing - <span i18n:name="tracker" + tal:replace="config/TRACKER_NAME" /> + editing + + + +You are not allowed to view this page. + +Please login with your username and password. + + + +

        + You may edit the contents of the + + class using this form. Commas, newlines and double quotes (") must be + handled delicately. You may include commas and newlines by enclosing the + values in double-quotes ("). Double quotes themselves must be quoted by + doubling (""). +

        + +

        + Multilink properties have their multiple values colon (":") separated + (... ,"one:two:three", ...) +

        + +

        + Remove entries by deleting their line. Add new entries by appending + them to the table - put an X in the id column. +

        +
        +
        + +
        + + +
        +
        + + + + + + + + + + +
         
         
        + + + +
        Added: tracker/roundup-src/share/roundup/templates/minimal/html/_generic.item.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/_generic.item.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,65 @@ + +<span tal:replace="python:context._classname.capitalize()" + i18n:name="class" /> editing - <span i18n:name="tracker" + tal:replace="config/TRACKER_NAME" /> + editing + + + +You are not allowed to view this page. + +Please login with your username and password. + +
        + + + + + + + + + + + + + + + +
          + submit button will go here +
        + +
        + + + + + + + + + +
        + + + + + + + + + Added: tracker/roundup-src/share/roundup/templates/minimal/html/help_controls.js ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/help_controls.js Sun Mar 15 22:43:30 2009 @@ -0,0 +1,111 @@ +// initial values for either Nosy, Superseder, Keyword and Waiting On, +// depending on which has called +original_field = form[field].value; + +// Some browsers (ok, IE) don't define the "undefined" variable. +undefined = document.geez_IE_is_really_friggin_annoying; + +function trim(value) { + var temp = value; + var obj = /^(\s*)([\W\w]*)(\b\s*$)/; + if (obj.test(temp)) { temp = temp.replace(obj, '$2'); } + var obj = / /g; + while (temp.match(obj)) { temp = temp.replace(obj, " "); } + return temp; +} + +function determineList() { + // generate a comma-separated list of the checked items + var list = new String(''); + for (box=0; box < document.frm_help.check.length; box++) { + if (document.frm_help.check[box].checked) { + if (list.length == 0) { + separator = ''; + } + else { + separator = ','; + } + // we used to use an Array and push / join, but IE5.0 sux + list = list + separator + document.frm_help.check[box].value; + } + } + return list; +} + +function updateList() { + // write back to opener window + if (document.frm_help.check==undefined) { return; } + form[field].value = determineList(); +} + +function updatePreview() { + // update the preview box + if (document.frm_help.check==undefined) { return; } + writePreview(determineList()); +} + +function clearList() { + // uncheck all checkboxes + if (document.frm_help.check==undefined) { return; } + for (box=0; box < document.frm_help.check.length; box++) { + document.frm_help.check[box].checked = false; + } +} + +function reviseList(vals) { + // update the checkboxes based on the preview field + if (document.frm_help.check==undefined) { return; } + var to_check; + var list = vals.split(","); + if (document.frm_help.check.length==undefined) { + check = document.frm_help.check; + to_check = false; + for (val in list) { + if (check.value==trim(list[val])) { + to_check = true; + break; + } + } + check.checked = to_check; + } else { + for (box=0; box < document.frm_help.check.length; box++) { + check = document.frm_help.check[box]; + to_check = false; + for (val in list) { + if (check.value==trim(list[val])) { + to_check = true; + break; + } + } + check.checked = to_check; + } + } +} + +function resetList() { + // reset preview and check boxes to initial values + if (document.frm_help.check==undefined) { return; } + writePreview(original_field); + reviseList(original_field); +} + +function writePreview(val) { + // writes a value to the text_preview + document.frm_help.text_preview.value = val; +} + +function focusField(name) { + for(i=0; i < document.forms.length; ++i) { + var obj = document.forms[i].elements[name]; + if (obj && obj.focus) {obj.focus();} + } +} + +function selectField(name) { + for(i=0; i < document.forms.length; ++i) { + var obj = document.forms[i].elements[name]; + if (obj && obj.focus){obj.focus();} + if (obj && obj.select){obj.select();} + } +} + Added: tracker/roundup-src/share/roundup/templates/minimal/html/home.classlist.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/home.classlist.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,25 @@ + +List of classes - <span + i18n:name="tracker" tal:replace="config/TRACKER_NAME" /> +List of classes + + + + + + + + + + + + + +
        + classname +
        nametype
        + + +
        Added: tracker/roundup-src/share/roundup/templates/minimal/html/home.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/home.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,25 @@ + +Tracker home - <span + i18n:name="tracker" tal:replace="config/TRACKER_NAME" /> +Tracker home + + + + + +

        +Please select from one of the menu options on the left. +

        +

        +Please log in or register. +

        +
        + + +
        Added: tracker/roundup-src/share/roundup/templates/minimal/html/page.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/page.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,334 @@ + + + +title goes here + + + + + + + + + + + + + + + + + + + + + + + +
          +
        +

        body title

        +
        + +
        +

        +

        + + clear this message +

        +
        Page content goes here
        + +
        +
        + + + +
        + + + + + + + + + + + + + + + + (cal) + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
        • + +
        • +
        • + + +
        • +
        + + + + + + + + + + + + + + + + + + + + + + + + + Added: tracker/roundup-src/share/roundup/templates/minimal/html/style.css ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/style.css Sun Mar 15 22:43:30 2009 @@ -0,0 +1,423 @@ +/* main page styles */ +body.body { + font-family: sans-serif, Arial, Helvetica; + background-color: white; + color: #333; + margin: 0; +} +a[href]:hover { + color:blue; + text-decoration: underline; +} +a[href], a[href]:link { + color:blue; + text-decoration: none; +} + +table.body { + border: 0; + padding: 0; + border-spacing: 0; + border-collapse: separate; +} + +td.page-header-left { + padding: 5px; + border-bottom: 1px solid #444; +} +td.sidebar { + padding: 1px 0 0 1px; + white-space: nowrap; +} + +/* don't display the sidebar when printing */ + at media print { + td.page-header-left { + display: none; + } + td.sidebar { + display: none; + } + .index-controls { + display: none; + } + #searchbox { + display: none; + } +} + +td.page-header-top { + padding: 5px; + border-bottom: 1px solid #444; +} +#searchbox { + float: right; +} + +div#body-title { + float: left; +} + + +div#searchbox { + float: right; + padding-top: 1em; +} + +div#searchbox input#search-text { + width: 10em; +} + +form { + margin: 0; +} + +textarea { + font-family: monospace; +} + +td.sidebar p.classblock { + padding: 2px 5px 2px 5px; + margin: 1px; + border: 1px solid #444; + background-color: #eee; +} + +td.sidebar p.userblock { + padding: 2px 5px 2px 5px; + margin: 1px 1px 1px 1px; + border: 1px solid #444; + background-color: #eef; +} + +.form-small { + padding: 0; + font-size: 75%; +} + + +td.content { + padding: 1px 5px 1px 5px; + vertical-align: top; + width: 100%; +} + +td.date, th.date { + white-space: nowrap; +} + +p.ok-message { + background-color: #22bb22; + padding: 5px; + color: white; + font-weight: bold; +} +p.error-message { + background-color: #bb2222; + padding: 5px; + color: white; + font-weight: bold; +} +p.error-message a[href] { + color: white; + text-decoration: underline; +} + + +/* style for search forms */ +ul.search-checkboxes { + display: inline; + padding: none; + list-style: none; +} +ul.search-checkboxes > li { + display: inline; + padding-right: .5em; +} + + +/* style for forms */ +table.form { + padding: 2px; + border-spacing: 0; + border-collapse: separate; +} + +table.form th { + color: #338; + text-align: right; + vertical-align: top; + font-weight: normal; + white-space: nowrap; +} + +table.form th.header { + font-weight: bold; + background-color: #eef; + text-align: left; +} + +table.form th.required { + font-weight: bold; +} + +table.form td { + color: #333; + empty-cells: show; + vertical-align: top; +} + +table.form td.optional { + font-weight: bold; + font-style: italic; +} + +table.form td.html { + color: #777; +} + +/* style for lists */ +table.list { + border-spacing: 0; + border-collapse: separate; + width: 100%; +} + +table.list th { + padding: 0 4px 0 4px; + color: #404070; + background-color: #eef; + border: 1px solid white; + vertical-align: top; + empty-cells: show; +} +table.list th a[href]:hover { color: #404070 } +table.list th a[href]:link { color: #404070 } +table.list th a[href] { color: #404070 } +table.list th.group { + background-color: #f4f4ff; + text-align: center; +} + +table.list td { + padding: 0 4px 0 4px; + border: 1px solid white; + color: #404070; + background-color: #efefef; + vertical-align: top; + empty-cells: show; +} + +table.list tr.navigation th { + width: 33%; + border-style: hidden; + text-align: center; +} +table.list tr.navigation td { + border: none +} +table.list tr.navigation th:first-child { + text-align: left; +} +table.list tr.navigation th:last-child { + text-align: right; +} + + +/* style for message displays */ +table.messages { + border-spacing: 0; + border-collapse: separate; + width: 100%; +} + +table.messages th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.messages th { + font-weight: bold; + color: black; + text-align: left; + border-bottom: 1px solid #afafaf; +} + +table.messages td { + font-family: monospace; + background-color: #efefef; + border-bottom: 1px solid #afafaf; + color: black; + empty-cells: show; + border-right: 1px solid #afafaf; + vertical-align: top; + padding: 2px 5px 2px 5px; +} + +table.messages td:first-child { + border-left: 1px solid #afafaf; + border-right: 1px solid #afafaf; +} + +/* style for file displays */ +table.files { + border-spacing: 0; + border-collapse: separate; + width: 100%; +} + +table.files th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.files th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; +} + +table.files td { + font-family: monospace; + empty-cells: show; +} + +/* style for history displays */ +table.history { + border-spacing: 0; + border-collapse: separate; + width: 100%; +} + +table.history th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; + font-size: 100%; +} + +table.history th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; + font-size: 90%; +} + +table.history td { + font-size: 90%; + vertical-align: top; + empty-cells: show; +} + + +/* style for class list */ +table.classlist { + border-spacing: 0; + border-collapse: separate; + width: 100%; +} + +table.classlist th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.classlist th { + font-weight: bold; + text-align: left; +} + + +/* style for class help display */ +table.classhelp { /* the table-layout: fixed; */ + table-layout: fixed; /* compromises quality for speed */ + overflow: hidden; + font-size: .9em; + padding-bottom: 3em; +} + +table.classhelp th { + font-weight: normal; + text-align: left; + color: #444; + background-color: #efefef; + border-bottom: 1px solid #afafaf; + border-top: 1px solid #afafaf; + text-transform: uppercase; + vertical-align: middle; + line-height:1.5em; +} + +table.classhelp td { + vertical-align: middle; + padding-right: .2em; + border-bottom: 1px solid #efefef; + text-align: left; + empty-cells: show; + white-space: nowrap; + vertical-align: middle; +} + +table.classhelp tr:hover { + background-color: #eee; +} + +label.classhelp-label { + cursor: pointer; +} + +#classhelp-controls { + position: fixed; + display: block; + top: auto; + right: 0; + bottom: 0; + left: 0; + padding: .5em; + border-top: 2px solid #444; + background-color: #eee; +} + +#classhelp-controls input.apply { + width: 7em; + font-weight: bold; + margin-right: 2em; + margin-left: 2em; +} + +#classhelp-controls input.preview { + margin-right: 3em; + margin-left: 1em; +} + +/* style for "other" displays */ +table.otherinfo { + border-spacing: 0; + border-collapse: separate; + width: 100%; +} + +table.otherinfo th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.otherinfo th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; +} Added: tracker/roundup-src/share/roundup/templates/minimal/html/user.index.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/user.index.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,35 @@ + + +User listing - <span + i18n:name="tracker" tal:replace="config/TRACKER_NAME" /> +User listing + + +You are not allowed to view this page. + +Please login with your username and password. + + + + + + + + + + + + +
        UsernameEmail address
        + username + address
        + + +
        Added: tracker/roundup-src/share/roundup/templates/minimal/html/user.item.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/user.item.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,169 @@ + + + +<tal:if condition="context/id" i18n:translate="" + >User <tal:x content="context/id" i18n:name="id" + />: <tal:x content="context/username" i18n:name="title" + /> - <tal:x content="config/TRACKER_NAME" i18n:name="tracker" +/></tal:if> +<tal:if condition="not:context/id" i18n:translate="" + >New User - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker" +/></tal:if> + + + + + + + New User + New User Editing + User + User Editing + + + + +

        + You are not allowed to view this page.

        + +

        + Please login with your username and password.

        + +
        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        Name
        Login Name
        Login Password
        Confirm Password
        + + + + + + + (to give the user more than one role, + enter a comma,separated,list) +
        Phone
        Organisation
        Timezone + (this is a numeric hour offset, the default is + ) +
        E-mail address + calvin at the-z.org + + + +   +
        + +
        +   + + + + +
        +
        + + + + + + + + +
        Note: highlighted fields are required.
        +
        + + + +
        + + + +
        Added: tracker/roundup-src/share/roundup/templates/minimal/html/user.register.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/user.register.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,73 @@ + + +Registering with <span i18n:name="tracker" + tal:replace="db/config/TRACKER_NAME" /> +Registering with + + + + +You are not allowed to view this page. + +Please login with your username and password. + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        Login Nameusername
        Login Passwordpassword
        Confirm Passwordpassword
        Rolesroles + +
        E-mail addressaddress
        Alternate E-mail addresses
        One address per line
        alternate_addresses
          + + +
        +
        + +
        + +
        + + + +
        Added: tracker/roundup-src/share/roundup/templates/minimal/html/user.rego_progress.html ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/html/user.rego_progress.html Sun Mar 15 22:43:30 2009 @@ -0,0 +1,16 @@ + + +Registration in progress - <span i18n:name="tracker" + tal:replace="config/TRACKER_NAME" /> +Registration in progress... + + +

        You will shortly receive an email +to confirm your registration. To complete the registration process, +visit the link indicated in the email. +

        + + +
        Added: tracker/roundup-src/share/roundup/templates/minimal/initial_data.py ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/initial_data.py Sun Mar 15 22:43:30 2009 @@ -0,0 +1,14 @@ +# +# TRACKER DATABASE INITIALIZATION +# + +# create the two default users +user = db.getclass('user') +user.create(username="admin", password=adminpw, + address=admin_email, roles='Admin') +user.create(username="anonymous", roles='Anonymous') + +# add any additional database creation steps here - but only if you +# haven't initialised the database with the admin "initialise" command + +# vim: set et sts=4 sw=4 : Added: tracker/roundup-src/share/roundup/templates/minimal/schema.py ============================================================================== --- (empty file) +++ tracker/roundup-src/share/roundup/templates/minimal/schema.py Sun Mar 15 22:43:30 2009 @@ -0,0 +1,65 @@ +# +# TRACKER SCHEMA +# + +# Class automatically gets these properties: +# creation = Date() +# activity = Date() +# creator = Link('user') +# actor = Link('user') + +# The "Minimal" template gets only one class, the required "user" +# class. That's it. And even that has the bare minimum of properties. + +# Note: roles is a comma-separated string of Role names +user = Class(db, "user", username=String(), password=Password(), + address=String(), alternate_addresses=String(), roles=String()) +user.setkey("username") +# +# TRACKER SECURITY SETTINGS +# +# See the configuration and customisation document for information +# about security setup. + +# +# REGULAR USERS +# +# Give the regular users access to the web and email interface +db.security.addPermissionToRole('User', 'Web Access') +db.security.addPermissionToRole('User', 'Email Access') + +# May users view other user information? +# Comment these lines out if you don't want them to +db.security.addPermissionToRole('User', 'View', 'user') + +# Users should be able to edit their own details -- this permission is +# limited to only the situation where the Viewed or Edited item is their own. +def own_record(db, userid, itemid): + '''Determine whether the userid matches the item being accessed.''' + return userid == itemid +p = db.security.addPermission(name='View', klass='user', check=own_record, + description="User is allowed to view their own user details") +db.security.addPermissionToRole('User', p) +p = db.security.addPermission(name='Edit', klass='user', check=own_record, + description="User is allowed to edit their own user details") +db.security.addPermissionToRole('User', p) + +# +# ANONYMOUS USER PERMISSIONS +# +# Let anonymous users access the web interface. Note that almost all +# trackers will need this Permission. The only situation where it's not +# required is in a tracker that uses an HTTP Basic Authenticated front-end. +db.security.addPermissionToRole('Anonymous', 'Web Access') + +# Let anonymous users access the email interface (note that this implies +# that they will be registered automatically, hence they will need the +# "Create" user Permission below) +db.security.addPermissionToRole('Anonymous', 'Email Access') + +# Assign the appropriate permissions to the anonymous user's +# Anonymous Role. Choices here are: +# - Allow anonymous users to register +db.security.addPermissionToRole('Anonymous', 'Create', 'user') + +# vim: set et sts=4 sw=4 : Modified: tracker/roundup-src/test/README.txt ============================================================================== --- tracker/roundup-src/test/README.txt (original) +++ tracker/roundup-src/test/README.txt Sun Mar 15 22:43:30 2009 @@ -1,4 +1,4 @@ -$Id: README.txt,v 1.3 2004/10/24 08:37:58 a1s Exp $ +$Id: README.txt,v 1.3 2004-10-24 08:37:58 a1s Exp $ Structure of the tests: Modified: tracker/roundup-src/test/db_test_base.py ============================================================================== --- tracker/roundup-src/test/db_test_base.py (original) +++ tracker/roundup-src/test/db_test_base.py Sun Mar 15 22:43:30 2009 @@ -15,9 +15,11 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: db_test_base.py,v 1.96 2008/02/07 03:28:34 richard Exp $ +# $Id: db_test_base.py,v 1.101 2008-08-19 01:40:59 richard Exp $ -import unittest, os, shutil, errno, imp, sys, time, pprint, sets, base64, os.path +import unittest, os, shutil, errno, imp, sys, time, pprint, base64, os.path +# Python 2.3 ... 2.6 compatibility: +from roundup.anypy.sets_ import set from roundup.hyperdb import String, Password, Link, Multilink, Date, \ Interval, DatabaseError, Boolean, Number, Node @@ -55,13 +57,18 @@ except OSError, error: if error.errno not in (errno.ENOENT, errno.ESRCH): raise # create the instance - init.install(dirname, os.path.join(os.path.dirname(__file__), '..', - 'templates/classic')) + init.install(dirname, os.path.join(os.path.dirname(__file__), + '..', + 'share', + 'roundup', + 'templates', + 'classic')) init.write_select_db(dirname, backend) config.save(os.path.join(dirname, 'config.ini')) tracker = instance.open(dirname) if tracker.exists(): tracker.nuke() + init.write_select_db(dirname, backend) tracker.init(password.Password('sekrit')) return tracker @@ -80,7 +87,8 @@ issue = module.IssueClass(db, "issue", title=String(indexme="yes"), status=Link("status"), nosy=Multilink("user"), deadline=Date(), foo=Interval(), files=Multilink("file"), assignedto=Link('user'), - priority=Link('priority'), spam=Multilink('msg')) + priority=Link('priority'), spam=Multilink('msg'), + feedback=Link('msg')) stuff = module.Class(db, "stuff", stuff=String()) session = module.Class(db, 'session', title=String()) msg = module.FileClass(db, "msg", date=Date(), @@ -288,12 +296,12 @@ if commit: self.db.commit() self.assertEqual(self.db.issue.get(nid, "nosy"), []) # make sure we accept a frozen set - self.db.issue.set(nid, nosy=frozenset([u1,u2])) + self.db.issue.set(nid, nosy=set([u1,u2])) if commit: self.db.commit() l = [u1,u2]; l.sort() m = self.db.issue.get(nid, "nosy"); m.sort() self.assertEqual(l, m) - + # XXX one day, maybe... # def testMultilinkOrdering(self): @@ -329,6 +337,19 @@ c = self.db.issue.get(nid, "deadline") self.assertEqual(c, d) + def testDateLeapYear(self): + nid = self.db.issue.create(title='spam', status='1', + deadline=date.Date('2008-02-29')) + self.assertEquals(str(self.db.issue.get(nid, 'deadline')), + '2008-02-29.00:00:00') + self.assertEquals(self.db.issue.filter(None, + {'deadline': '2008-02-29'}), [nid]) + self.db.issue.set(nid, deadline=date.Date('2008-03-01')) + self.assertEquals(str(self.db.issue.get(nid, 'deadline')), + '2008-03-01.00:00:00') + self.assertEquals(self.db.issue.filter(None, + {'deadline': '2008-02-29'}), []) + def testDateUnset(self): for commit in (0,1): nid = self.db.issue.create(title="spam", status='1') @@ -468,12 +489,12 @@ others = nodeids[:] others.remove('1') - self.assertEqual(sets.Set(self.db.status.getnodeids()), - sets.Set(nodeids)) - self.assertEqual(sets.Set(self.db.status.getnodeids(retired=True)), - sets.Set(['1'])) - self.assertEqual(sets.Set(self.db.status.getnodeids(retired=False)), - sets.Set(others)) + self.assertEqual(set(self.db.status.getnodeids()), + set(nodeids)) + self.assertEqual(set(self.db.status.getnodeids(retired=True)), + set(['1'])) + self.assertEqual(set(self.db.status.getnodeids(retired=False)), + set(others)) self.assert_(self.db.status.is_retired('1')) @@ -844,6 +865,15 @@ # unindexed stopword self.assertEquals(self.db.indexer.search(['the'], self.db.issue), {}) + def testIndexerSearchingLink(self): + m1 = self.db.msg.create(content="one two") + i1 = self.db.issue.create(messages=[m1]) + m2 = self.db.msg.create(content="two three") + i2 = self.db.issue.create(feedback=m2) + self.db.commit() + self.assertEquals(self.db.indexer.search(['two'], self.db.issue), + {i1: {'messages': [m1]}, i2: {'feedback': [m2]}}) + def testIndexerSearchMulti(self): m1 = self.db.msg.create(content="one two") m2 = self.db.msg.create(content="two three") @@ -1711,7 +1741,7 @@ keys = props.keys() keys.sort() self.assertEqual(keys, ['activity', 'actor', 'assignedto', 'creation', - 'creator', 'deadline', 'files', 'fixer', 'foo', 'id', 'messages', + 'creator', 'deadline', 'feedback', 'files', 'fixer', 'foo', 'id', 'messages', 'nosy', 'priority', 'spam', 'status', 'superseder', 'title']) self.assertEqual(self.db.issue.get('1', "fixer"), None) @@ -1725,7 +1755,7 @@ keys = props.keys() keys.sort() self.assertEqual(keys, ['activity', 'actor', 'assignedto', 'creation', - 'creator', 'deadline', 'files', 'foo', 'id', 'messages', + 'creator', 'deadline', 'feedback', 'files', 'foo', 'id', 'messages', 'nosy', 'priority', 'spam', 'status', 'superseder']) self.assertEqual(self.db.issue.list(), ['1']) @@ -1740,8 +1770,8 @@ keys = props.keys() keys.sort() self.assertEqual(keys, ['activity', 'actor', 'assignedto', 'creation', - 'creator', 'deadline', 'files', 'fixer', 'foo', 'id', 'messages', - 'nosy', 'priority', 'spam', 'status', 'superseder']) + 'creator', 'deadline', 'feedback', 'files', 'fixer', 'foo', 'id', + 'messages', 'nosy', 'priority', 'spam', 'status', 'superseder']) self.assertEqual(self.db.issue.list(), ['1']) def testNosyMail(self) : @@ -1763,16 +1793,16 @@ messages = [m], nosy = [db.user.lookup("fred")]) db.issue.nosymessage(i, m, {}) - mail_msg = res["mail_msg"].getvalue() + mail_msg = str(res["mail_msg"]) self.assertEqual(res["mail_to"], ["fred at example.com"]) self.failUnless("From: admin" in mail_msg) self.failUnless("Subject: [issue1] spam" in mail_msg) self.failUnless("New submission from admin" in mail_msg) self.failUnless("one two" in mail_msg) self.failIf("File 'test1.txt' not attached" in mail_msg) - self.failUnless(base64.b64encode("xxx") in mail_msg) + self.failUnless(base64.encodestring("xxx").rstrip() in mail_msg) self.failUnless("File 'test2.txt' not attached" in mail_msg) - self.failIf(base64.b64encode("yyy") in mail_msg) + self.failIf(base64.encodestring("yyy").rstrip() in mail_msg) finally : Mailer.smtp_send = backup @@ -2026,7 +2056,7 @@ self.db.getjournal('a', aid) class RDBMSTest: - ''' tests specific to RDBMS backends ''' + """ tests specific to RDBMS backends """ def test_indexTest(self): self.assertEqual(self.db.sql_index_exists('_issue', '_issue_id_idx'), 1) self.assertEqual(self.db.sql_index_exists('_issue', '_issue_x_idx'), 0) Modified: tracker/roundup-src/test/test_anydbm.py ============================================================================== --- tracker/roundup-src/test/test_anydbm.py (original) +++ tracker/roundup-src/test/test_anydbm.py Sun Mar 15 22:43:30 2009 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_anydbm.py,v 1.4 2004/11/03 01:34:21 richard Exp $ +# $Id: test_anydbm.py,v 1.4 2004-11-03 01:34:21 richard Exp $ import unittest, os, shutil, time from roundup.backends import get_backend Added: tracker/roundup-src/test/test_anypy_hashlib.py ============================================================================== --- (empty file) +++ tracker/roundup-src/test/test_anypy_hashlib.py Sun Mar 15 22:43:30 2009 @@ -0,0 +1,139 @@ +#! /usr/bin/env python +import unittest +import warnings + +import roundup.anypy.hashlib_ + +class UntestableWarning(Warning): + pass + +# suppress deprecation warnings; -> warnings.filters[0]: +warnings.simplefilter(action='ignore', + category=DeprecationWarning, + append=0) + +try: + import sha +except: + warnings.warn('sha module functions', UntestableWarning) + sha = None + +try: + import md5 +except: + warnings.warn('md5 module functions', UntestableWarning) + md5 = None + +try: + import hashlib +except: + warnings.warn('hashlib module functions', UntestableWarning) + hashlib = None + +# preserve other warning filters set elsewhere: +del warnings.filters[0] + +if not ((sha or md5) and hashlib): + warnings.warn('anypy.hashlib_ continuity', UntestableWarning) + +class TestCase_anypy_hashlib(unittest.TestCase): + """test the hashlib compatibility layer""" + + testdata = ( + ('', + 'da39a3ee5e6b4b0d3255bfef95601890afd80709', + 'd41d8cd98f00b204e9800998ecf8427e'), + ('Strange women lying in ponds distributing swords' + ' is no basis for a system of government.', + 'da9b2b00466b00411038c057681fe67349f92d7d', + 'b71c5178d316ec446c25386f4857d4f9'), + ('Ottos Mops hopst fort', + 'fdf7e6c54cf07108c86edd8d47c90450671c2c81', + 'a3dce74bee59ee92f1038263e5252500'), + ('Dieser Satz kein Verb', + '3030aded8a079b92043a39dc044a35443959dcdd', + '2f20c69d514228011fb0d32e14dd5d80'), + ) + + # the following two are always excecuted: + def test_sha1_expected_anypy(self): + """...anypy.hashlib_.sha1().hexdigest() yields expected results""" + for src, SHA, MD5 in self.testdata: + self.assertEqual(roundup.anypy.hashlib_.sha1(src).hexdigest(), SHA) + + def test_md5_expected_anypy(self): + """...anypy.hashlib_.md5().hexdigest() yields expected results""" + for src, SHA, MD5 in self.testdata: + self.assertEqual(roundup.anypy.hashlib_.md5(src).hexdigest(), MD5) + + # execution depending on availability of modules: + if md5 and hashlib: + def test_md5_continuity(self): + """md5.md5().digest() == hashlib.md5().digest()""" + if md5.md5 is hashlib.md5: + return + else: + for s, i1, i2 in self.testdata: + self.assertEqual(md5.md5(s).digest(), + hashlib.md5().digest()) + + if md5: + def test_md5_expected(self): + """md5.md5().hexdigest() yields expected results""" + for src, SHA, MD5 in self.testdata: + self.assertEqual(md5.md5(src).hexdigest(), MD5) + + def test_md5_new_expected(self): + """md5.new is md5.md5, or at least yields expected results""" + if md5.new is md5.md5: + return + else: + for src, SHA, MD5 in self.testdata: + self.assertEqual(md5.new(src).hexdigest(), MD5) + + if sha and hashlib: + def test_sha1_continuity(self): + """sha.sha().digest() == hashlib.sha1().digest()""" + if sha.sha is hashlib.sha1: + return + else: + for s in self.testdata: + self.assertEqual(sha.sha(s).digest(), + hashlib.sha1().digest()) + + if sha: + def test_sha_expected(self): + """sha.sha().hexdigest() yields expected results""" + for src, SHA, MD5 in self.testdata: + self.assertEqual(sha.sha(src).hexdigest(), SHA) + + # fails for me with Python 2.3; unittest module bug? + def test_sha_new_expected(self): + """sha.new is sha.sha, or at least yields expected results""" + if sha.new is sha.sha: + return + else: + for src, SHA, MD5 in self.testdata: + self.assertEqual(sha.new(src).hexdigest(), SHA) + + if hashlib: + def test_sha1_expected_hashlib(self): + """hashlib.sha1().hexdigest() yields expected results""" + for src, SHA, MD5 in self.testdata: + self.assertEqual(hashlib.sha1(src).hexdigest(), SHA) + + def test_md5_expected_hashlib(self): + """hashlib.md5().hexdigest() yields expected results""" + for src, SHA, MD5 in self.testdata: + self.assertEqual(hashlib.md5(src).hexdigest(), MD5) + +def test_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestCase_anypy_hashlib)) + return suite + +if __name__ == '__main__': + runner = unittest.TextTestRunner() + unittest.main(testRunner=runner) + +# vim: ts=8 et sts=4 sw=4 si Modified: tracker/roundup-src/test/test_cgi.py ============================================================================== --- tracker/roundup-src/test/test_cgi.py (original) +++ tracker/roundup-src/test/test_cgi.py Sun Mar 15 22:43:30 2009 @@ -8,7 +8,7 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # -# $Id: test_cgi.py,v 1.33 2007/10/05 03:07:14 richard Exp $ +# $Id: test_cgi.py,v 1.36 2008-08-07 06:12:57 richard Exp $ import unittest, os, shutil, errno, sys, difflib, cgi, re @@ -77,7 +77,7 @@ string=hyperdb.String(), number=hyperdb.Number(), boolean=hyperdb.Boolean(), link=hyperdb.Link('test'), multilink=hyperdb.Multilink('test'), date=hyperdb.Date(), - interval=hyperdb.Interval()) + messages=hyperdb.Multilink('msg'), interval=hyperdb.Interval()) # compile the labels re classes = '|'.join(self.db.classes.keys()) @@ -85,10 +85,11 @@ re.VERBOSE) def parseForm(self, form, classname='test', nodeid=None): - cl = client.Client(self.instance, None, {'PATH_INFO':'/'}, - makeForm(form)) + cl = client.Client(self.instance, None, {'PATH_INFO':'/', + 'REQUEST_METHOD':'POST'}, makeForm(form)) cl.classname = classname cl.nodeid = nodeid + cl.language = ('en',) cl.db = self.db return cl.parsePropsFromForm(create=1) @@ -204,6 +205,7 @@ cl.classname = 'issue' cl.nodeid = issue cl.db = self.db + cl.language = ('en',) item = HTMLItem(cl, 'issue', issue) self.assertEqual(item.status.id, '1') self.assertEqual(item.status.name, '2') @@ -222,6 +224,7 @@ cl.classname = 'issue' cl.nodeid = issue cl.db = self.db + cl.language = ('en',) cl.userid = '1' item = HTMLItem(cl, 'issue', issue) for keyword in item.keyword: @@ -304,6 +307,7 @@ cl.classname = 'issue' cl.nodeid = None cl.db = self.db + cl.language = ('en',) self.assertEqual(cl.parsePropsFromForm(create=1), ({('issue', None): {'nosy': ['1','2', '3']}}, [])) @@ -564,13 +568,24 @@ }), ({('test', None): {'string': 'a'}, ('issue', '-1'): {'nosy': ['1']}, - ('issue', '-2'): {} }, [('issue', '-2', 'superseder', [('issue', '-1')]) ] ) ) + def testMessages(self): + self.assertEqual(self.parseForm({ + 'msg-1 at content': 'asdf', + 'msg-2 at content': 'qwer', + '@link at messages': 'msg-1, msg-2'}), + ({('test', None): {}, + ('msg', '-2'): {'content': 'qwer'}, + ('msg', '-1'): {'content': 'asdf'}}, + [('test', None, 'messages', [('msg', '-1'), ('msg', '-2')])] + ) + ) + def testLinkBadDesignator(self): self.assertRaises(FormError, self.parseForm, {'test-1 at link@link': 'blah'}) @@ -600,12 +615,13 @@ # # XXX test all default permissions def _make_client(self, form, classname='user', nodeid='2', userid='2'): - cl = client.Client(self.instance, None, {'PATH_INFO':'/'}, - makeForm(form)) + cl = client.Client(self.instance, None, {'PATH_INFO':'/', + 'REQUEST_METHOD':'POST'}, makeForm(form)) cl.classname = 'user' cl.nodeid = '1' cl.db = self.db cl.userid = '2' + cl.language = ('en',) return cl def testClassPermission(self): Modified: tracker/roundup-src/test/test_dates.py ============================================================================== --- tracker/roundup-src/test/test_dates.py (original) +++ tracker/roundup-src/test/test_dates.py Sun Mar 15 22:43:30 2009 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_dates.py,v 1.44 2007/12/23 00:23:23 richard Exp $ +# $Id: test_dates.py,v 1.45 2008-03-07 01:11:55 richard Exp $ from __future__ import nested_scopes import unittest @@ -37,7 +37,9 @@ ae(str(date), '2000-02-29.00:00:00') date = Date("2001-02-27 + 2d") ae(str(date), '2001-03-01.00:00:00') - + date = Date("2009", add_granularity=True) + self.assertRaises(ValueError, Date, ". +30d", add_granularity=True) + def testDate(self): ae = self.assertEqual date = Date("2000-04-17") @@ -68,6 +70,9 @@ ae(str(Date('1900-02-01')), '1900-02-01.00:00:00') ae(str(Date('1800-07-15')), '1800-07-15.00:00:00') + def testLeapYear(self): + self.assertEquals(str(Date('2008-02-29')), '2008-02-29.00:00:00') + def testDateError(self): self.assertRaises(ValueError, Date, "12") # Date cannot handle dates before year 1 Modified: tracker/roundup-src/test/test_hyperdbvals.py ============================================================================== --- tracker/roundup-src/test/test_hyperdbvals.py (original) +++ tracker/roundup-src/test/test_hyperdbvals.py Sun Mar 15 22:43:30 2009 @@ -8,9 +8,10 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # -# $Id: test_hyperdbvals.py,v 1.3 2006/08/18 01:26:19 richard Exp $ +# $Id: test_hyperdbvals.py,v 1.3 2006-08-18 01:26:19 richard Exp $ -import unittest, os, shutil, errno, sys, difflib, cgi, re, sha +import unittest, os, shutil, errno, sys, difflib, cgi, re +from roundup.anypy.hashlib_ import sha1 from roundup import init, instance, password, hyperdb, date @@ -80,7 +81,7 @@ self.assert_(isinstance(val, password.Password)) val = self._test('password', '{crypt}a string') self.assert_(isinstance(val, password.Password)) - s = sha.sha('a string').hexdigest() + s = sha1('a string').hexdigest() val = self._test('password', '{SHA}'+s) self.assert_(isinstance(val, password.Password)) self.assertEqual(val, 'a string') Modified: tracker/roundup-src/test/test_indexer.py ============================================================================== --- tracker/roundup-src/test/test_indexer.py (original) +++ tracker/roundup-src/test/test_indexer.py Sun Mar 15 22:43:30 2009 @@ -18,10 +18,19 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -# $Id: test_indexer.py,v 1.10 2006/02/07 04:59:05 richard Exp $ +# $Id: test_indexer.py,v 1.13 2008-09-11 19:10:30 schlatterbeck Exp $ import os, unittest, shutil +from roundup.backends import get_backend, have_backend +from roundup.backends.indexer_rdbms import Indexer + +# borrow from other tests +from db_test_base import setupSchema, config +from test_postgresql import postgresqlOpener +from test_mysql import mysqlOpener +from test_sqlite import sqliteOpener + class db: class config(dict): DATABASE = 'test-index' @@ -38,29 +47,40 @@ self.dex = Indexer(db) self.dex.load_index() + def assertSeqEqual(self, s1, s2): + # First argument is the db result we're testing, second is the + # desired result. Some db results don't have iterable rows, so we + # have to work around that. + # Also work around some dbs not returning items in the expected + # order. + s1 = list([tuple([r[n] for n in range(len(r))]) for r in s1]) + s1.sort() + if s1 != s2: + self.fail('contents of %r != %r'%(s1, s2)) + def test_basics(self): self.dex.add_text(('test', '1', 'foo'), 'a the hello world') self.dex.add_text(('test', '2', 'foo'), 'blah blah the world') - self.assertEqual(self.dex.find(['world']), [('test', '1', 'foo'), + self.assertSeqEqual(self.dex.find(['world']), [('test', '1', 'foo'), ('test', '2', 'foo')]) - self.assertEqual(self.dex.find(['blah']), [('test', '2', 'foo')]) - self.assertEqual(self.dex.find(['blah', 'hello']), []) + self.assertSeqEqual(self.dex.find(['blah']), [('test', '2', 'foo')]) + self.assertSeqEqual(self.dex.find(['blah', 'hello']), []) def test_change(self): self.dex.add_text(('test', '1', 'foo'), 'a the hello world') self.dex.add_text(('test', '2', 'foo'), 'blah blah the world') - self.assertEqual(self.dex.find(['world']), [('test', '1', 'foo'), + self.assertSeqEqual(self.dex.find(['world']), [('test', '1', 'foo'), ('test', '2', 'foo')]) self.dex.add_text(('test', '1', 'foo'), 'a the hello') - self.assertEqual(self.dex.find(['world']), [('test', '2', 'foo')]) + self.assertSeqEqual(self.dex.find(['world']), [('test', '2', 'foo')]) def test_clear(self): self.dex.add_text(('test', '1', 'foo'), 'a the hello world') self.dex.add_text(('test', '2', 'foo'), 'blah blah the world') - self.assertEqual(self.dex.find(['world']), [('test', '1', 'foo'), + self.assertSeqEqual(self.dex.find(['world']), [('test', '1', 'foo'), ('test', '2', 'foo')]) self.dex.add_text(('test', '1', 'foo'), '') - self.assertEqual(self.dex.find(['world']), [('test', '2', 'foo')]) + self.assertSeqEqual(self.dex.find(['world']), [('test', '2', 'foo')]) def tearDown(self): shutil.rmtree('test-index') @@ -75,15 +95,74 @@ def tearDown(self): shutil.rmtree('test-index') +class RDBMSIndexerTest(IndexerTest): + def setUp(self): + # remove previous test, ignore errors + if os.path.exists(config.DATABASE): + shutil.rmtree(config.DATABASE) + self.db = self.module.Database(config, 'admin') + self.dex = Indexer(self.db) + def tearDown(self): + if hasattr(self, 'db'): + self.db.close() + if os.path.exists(config.DATABASE): + shutil.rmtree(config.DATABASE) + +class postgresqlIndexerTest(postgresqlOpener, RDBMSIndexerTest): + def setUp(self): + postgresqlOpener.setUp(self) + RDBMSIndexerTest.setUp(self) + def tearDown(self): + RDBMSIndexerTest.tearDown(self) + postgresqlOpener.tearDown(self) + +class mysqlIndexerTest(mysqlOpener, RDBMSIndexerTest): + def setUp(self): + mysqlOpener.setUp(self) + RDBMSIndexerTest.setUp(self) + def tearDown(self): + RDBMSIndexerTest.tearDown(self) + mysqlOpener.tearDown(self) + +class sqliteIndexerTest(sqliteOpener, RDBMSIndexerTest): + pass + def test_suite(): suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(IndexerTest)) + try: import xapian suite.addTest(unittest.makeSuite(XapianIndexerTest)) except ImportError: print "Skipping Xapian indexer tests" pass + + if have_backend('postgresql'): + # make sure we start with a clean slate + if postgresqlOpener.module.db_exists(config): + postgresqlOpener.module.db_nuke(config, 1) + suite.addTest(unittest.makeSuite(postgresqlIndexerTest)) + else: + print "Skipping postgresql indexer tests" + + if have_backend('mysql'): + # make sure we start with a clean slate + if mysqlOpener.module.db_exists(config): + mysqlOpener.module.db_nuke(config) + suite.addTest(unittest.makeSuite(mysqlIndexerTest)) + else: + print "Skipping mysql indexer tests" + + if have_backend('sqlite'): + # make sure we start with a clean slate + if sqliteOpener.module.db_exists(config): + sqliteOpener.module.db_nuke(config) + suite.addTest(unittest.makeSuite(sqliteIndexerTest)) + else: + print "Skipping sqlite indexer tests" + return suite if __name__ == '__main__': Modified: tracker/roundup-src/test/test_locking.py ============================================================================== --- tracker/roundup-src/test/test_locking.py (original) +++ tracker/roundup-src/test/test_locking.py Sun Mar 15 22:43:30 2009 @@ -18,7 +18,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -# $Id: test_locking.py,v 1.4 2003/10/25 22:53:26 richard Exp $ +# $Id: test_locking.py,v 1.4 2003-10-25 22:53:26 richard Exp $ import os, unittest, tempfile Modified: tracker/roundup-src/test/test_mailgw.py ============================================================================== --- tracker/roundup-src/test/test_mailgw.py (original) +++ tracker/roundup-src/test/test_mailgw.py Sun Mar 15 22:43:30 2009 @@ -1,3 +1,4 @@ +# -*- encoding: utf-8 -*- # # Copyright (c) 2001 Richard Jones, richard at bofh.asn.au. # This module is free software, and you may redistribute it and/or modify @@ -8,7 +9,7 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # -# $Id: test_mailgw.py,v 1.93 2008/02/07 03:55:14 richard Exp $ +# $Id: test_mailgw.py,v 1.96 2008-08-19 01:40:59 richard Exp $ # TODO: test bcc @@ -23,6 +24,7 @@ from roundup.mailgw import MailGW, Unauthorized, uidFromAddress, \ parseContent, IgnoreLoop, IgnoreBulk, MailUsageError, MailUsageHelp from roundup import init, instance, password, rfc2822, __version__ +from roundup.anypy.sets_ import set import db_test_base @@ -39,19 +41,27 @@ def compareMessages(self, new, old): """Compare messages for semantic equivalence.""" new, old = Message(new), Message(old) + + # all Roundup-generated messages have "Precedence: bulk" + old['Precedence'] = 'bulk' + + # don't try to compare the date del new['date'], old['date'] if not new == old: res = [] for key in new.keys(): + if key.startswith('from '): + # skip the unix from line + continue if key.lower() == 'x-roundup-version': # version changes constantly, so handle it specially if new[key] != __version__: - res.append(' %s: %s != %s' % (key, __version__, + res.append(' %s: %r != %r' % (key, __version__, new[key])) elif new.get(key, '') != old.get(key, ''): - res.append(' %s: %s != %s' % (key, old.get(key, ''), + res.append(' %s: %r != %r' % (key, old.get(key, ''), new.get(key, ''))) body_diff = self.compareStrings(new.fp.read(), old.fp.read()) @@ -230,7 +240,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork, mary at test.test, richard at test.test -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork, mary at test.test, richard at test.test From: "Bork, Chef" @@ -274,7 +284,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork, mary at test.test, richard at test.test -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: mary at test.test, richard at test.test From: "Bork, Chef" @@ -315,7 +325,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork, mary at test.test, richard at test.test -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: mary at test.test, richard at test.test From: "Bork, Chef" @@ -344,9 +354,7 @@ _______________________________________________________________________ ''') - multipart_msg = '''Content-Type: text/plain; - charset="iso-8859-1" -From: mary + multipart_msg = '''From: mary To: issue_tracker at your.tracker.email.domain.example Message-Id: In-Reply-To: @@ -460,7 +468,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork, richard at test.test -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork, richard at test.test From: "Contrary, Mary" @@ -508,7 +516,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork, john at test.test, mary at test.test -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork, john at test.test, mary at test.test From: richard @@ -556,7 +564,7 @@ self.compareMessages(new_mail, """ FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork, richard at test.test -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork, richard at test.test From: "Bork, Chef" @@ -569,7 +577,7 @@ Content-Transfer-Encoding: quoted-printable -Changes by Bork, Chef : +Change by Bork, Chef : ---------- @@ -599,7 +607,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork, john at test.test, mary at test.test -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork, john at test.test, mary at test.test From: richard @@ -679,7 +687,10 @@ This is a followup '''), nodeid) - # now try a longer interval + + + def testFollowupTitleMatchInterval(self): + nodeid = self.doNewIssue() self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation +1d' self.assertEqual(self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" @@ -709,7 +720,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork, richard at test.test -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork, richard at test.test From: John Doe @@ -755,7 +766,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork From: richard @@ -801,7 +812,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork, john at test.test, richard at test.test -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork, john at test.test, richard at test.test From: John Doe @@ -846,7 +857,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork, richard at test.test -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork, richard at test.test From: John Doe @@ -891,7 +902,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork From: richard @@ -1053,6 +1064,29 @@ m.sort() self.assertNotEqual(l, m) + def testNewUserAuthorHighBit(self): + l = set(self.db.user.list()) + # From: name has Euro symbol in it + message = '''Content-Type: text/plain; + charset="iso-8859-1" +From: =?utf8?b?SOKCrGxsbw==?= +To: issue_tracker at your.tracker.email.domain.example +Message-Id: +Subject: [issue] Testing... + +This is a test submission of a new issue. +''' + p = [ + self.db.security.getPermission('Create', 'user'), + self.db.security.getPermission('Email Access', None), + ] + self.db.security.role['anonymous'].permissions=p + self._handle_mail(message) + m = set(self.db.user.list()) + new = list(m - l)[0] + name = self.db.user.get(new, 'realname') + self.assertEquals(name, 'H???llo') + def testEnc01(self): self.doNewIssue() self._handle_mail('''Content-Type: text/plain; @@ -1072,7 +1106,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork, richard at test.test -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork, richard at test.test From: "Contrary, Mary" @@ -1099,6 +1133,53 @@ _______________________________________________________________________ ''') + def testEncNonUTF8(self): + self.doNewIssue() + self.instance.config.EMAIL_CHARSET = 'iso-8859-1' + self._handle_mail('''Content-Type: text/plain; + charset="iso-8859-1" +From: mary +To: issue_tracker at your.tracker.email.domain.example +Message-Id: +In-Reply-To: +Subject: [issue1] Testing... +Content-Type: text/plain; + charset="iso-8859-1" +Content-Transfer-Encoding: quoted-printable + +A message with encoding (encoded oe =F6) + +''') + self.compareMessages(self._get_mail(), +'''FROM: roundup-admin at your.tracker.email.domain.example +TO: chef at bork.bork.bork, richard at test.test +Content-Type: text/plain; charset="iso-8859-1" +Subject: [issue1] Testing... +To: chef at bork.bork.bork, richard at test.test +From: "Contrary, Mary" +Reply-To: Roundup issue tracker +MIME-Version: 1.0 +Message-Id: +In-Reply-To: +X-Roundup-Name: Roundup issue tracker +X-Roundup-Loop: hello +X-Roundup-Issue-Status: chatting +Content-Transfer-Encoding: quoted-printable + + +Contrary, Mary added the comment: + +A message with encoding (encoded oe =F6) + +---------- +status: unread -> chatting + +_______________________________________________________________________ +Roundup issue tracker + +_______________________________________________________________________ +''') + def testMultipartEnc01(self): self.doNewIssue() @@ -1126,7 +1207,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork, richard at test.test -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork, richard at test.test From: "Contrary, Mary" @@ -1203,7 +1284,7 @@ self.compareMessages(self._get_mail(), '''FROM: roundup-admin at your.tracker.email.domain.example TO: chef at bork.bork.bork -Content-Type: text/plain; charset=utf-8 +Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef at bork.bork.bork From: richard Modified: tracker/roundup-src/test/test_mailsplit.py ============================================================================== --- tracker/roundup-src/test/test_mailsplit.py (original) +++ tracker/roundup-src/test/test_mailsplit.py Sun Mar 15 22:43:30 2009 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_mailsplit.py,v 1.15 2003/10/25 22:53:26 richard Exp $ +# $Id: test_mailsplit.py,v 1.15 2003-10-25 22:53:26 richard Exp $ import unittest, cStringIO Deleted: tracker/roundup-src/test/test_metakit.py ============================================================================== Modified: tracker/roundup-src/test/test_multipart.py ============================================================================== --- tracker/roundup-src/test/test_multipart.py (original) +++ tracker/roundup-src/test/test_multipart.py Sun Mar 15 22:43:30 2009 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_multipart.py,v 1.8 2007/09/22 07:25:35 jpend Exp $ +# $Id: test_multipart.py,v 1.8 2007-09-22 07:25:35 jpend Exp $ import unittest from cStringIO import StringIO Modified: tracker/roundup-src/test/test_mysql.py ============================================================================== --- tracker/roundup-src/test/test_mysql.py (original) +++ tracker/roundup-src/test/test_mysql.py Sun Mar 15 22:43:30 2009 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_mysql.py,v 1.15 2004/11/10 22:22:59 richard Exp $ +# $Id: test_mysql.py,v 1.15 2004-11-10 22:22:59 richard Exp $ import unittest, os, shutil, time, imp Modified: tracker/roundup-src/test/test_postgresql.py ============================================================================== --- tracker/roundup-src/test/test_postgresql.py (original) +++ tracker/roundup-src/test/test_postgresql.py Sun Mar 15 22:43:30 2009 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_postgresql.py,v 1.13 2006/08/23 12:57:10 schlatterbeck Exp $ +# $Id: test_postgresql.py,v 1.13 2006-08-23 12:57:10 schlatterbeck Exp $ import unittest Modified: tracker/roundup-src/test/test_schema.py ============================================================================== --- tracker/roundup-src/test/test_schema.py (original) +++ tracker/roundup-src/test/test_schema.py Sun Mar 15 22:43:30 2009 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_schema.py,v 1.15 2004/10/16 12:43:11 a1s Exp $ +# $Id: test_schema.py,v 1.15 2004-10-16 12:43:11 a1s Exp $ import unittest, os, shutil Modified: tracker/roundup-src/test/test_security.py ============================================================================== --- tracker/roundup-src/test/test_security.py (original) +++ tracker/roundup-src/test/test_security.py Sun Mar 15 22:43:30 2009 @@ -18,7 +18,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -# $Id: test_security.py,v 1.10 2006/02/03 04:04:37 richard Exp $ +# $Id: test_security.py,v 1.10 2006-02-03 04:04:37 richard Exp $ import os, unittest, shutil Modified: tracker/roundup-src/test/test_sqlite.py ============================================================================== --- tracker/roundup-src/test/test_sqlite.py (original) +++ tracker/roundup-src/test/test_sqlite.py Sun Mar 15 22:43:30 2009 @@ -14,8 +14,8 @@ # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. -# -# $Id: test_sqlite.py,v 1.5 2004/11/03 01:34:21 richard Exp $ +# +# $Id: test_sqlite.py,v 1.6 2008-09-01 00:43:02 richard Exp $ import unittest, os, shutil, time from roundup.backends import get_backend, have_backend Modified: tracker/roundup-src/test/test_templating.py ============================================================================== --- tracker/roundup-src/test/test_templating.py (original) +++ tracker/roundup-src/test/test_templating.py Sun Mar 15 22:43:30 2009 @@ -12,7 +12,8 @@ def setUp(self): self.form = FieldStorage() self.client = MockNull() - self.client.db = MockDatabase() + self.client.db = db = MockDatabase() + db.security.hasPermission = lambda *args, **kw: True self.client.form = self.form class HTMLDatabaseTestCase(TemplatingTestCase): @@ -69,6 +70,87 @@ self.assertEqual(lookupKeys(shrubbery, 'spam', ['ok','2']), ['ok', 'eggs']) +class HTMLClassTestCase(TemplatingTestCase) : + + def test_link(self): + """Make sure lookup of a Link property works even in the + presence of multiple values in the form.""" + def lookup(key) : + self.assertEqual(key, key.strip()) + return "Status%s"%key + self.form.list.append(MiniFieldStorage("status", "1")) + self.form.list.append(MiniFieldStorage("status", "2")) + status = hyperdb.Link("status") + self.client.db.classes = dict \ + ( issue = MockNull(getprops = lambda : dict(status = status)) + , status = MockNull(get = lambda id, name : id, lookup = lookup) + ) + cls = HTMLClass(self.client, "issue") + cls["status"] + + def test_multilink(self): + """`lookup` of an item will fail if leading or trailing whitespace + has not been stripped. + """ + def lookup(key) : + self.assertEqual(key, key.strip()) + return "User%s"%key + self.form.list.append(MiniFieldStorage("nosy", "1, 2")) + nosy = hyperdb.Multilink("user") + self.client.db.classes = dict \ + ( issue = MockNull(getprops = lambda : dict(nosy = nosy)) + , user = MockNull(get = lambda id, name : id, lookup = lookup) + ) + cls = HTMLClass(self.client, "issue") + cls["nosy"] + + def test_url_match(self): + '''Test the URL regular expression in StringHTMLProperty. + ''' + def t(s, nothing=False, **groups): + m = StringHTMLProperty.hyper_re.search(s) + if nothing: + if m: + self.assertEquals(m, None, '%r matched (%r)'%(s, m.groupdict())) + return + else: + self.assertNotEquals(m, None, '%r did not match'%s) + d = m.groupdict() + for g in groups: + self.assertEquals(d[g], groups[g], '%s %r != %r in %r'%(g, d[g], + groups[g], s)) + + #t('123.321.123.321', 'url') + t('http://localhost/', url='http://localhost/') + t('http://roundup.net/', url='http://roundup.net/') + t('http://richard at localhost/', url='http://richard at localhost/') + t('http://richard:sekrit at localhost/', + url='http://richard:sekrit at localhost/') + t('', url='HTTP://roundup.net/') + t('www.a.ex', url='www.a.ex') + t('foo.a.ex', nothing=True) + t('StDevValidTimeSeries.GetObservation', nothing=True) + t('http://a.ex', url='http://a.ex') + t('http://a.ex/?foo&bar=baz\\.@!$%()qwerty', + url='http://a.ex/?foo&bar=baz\\.@!$%()qwerty') + t('www.foo.net', url='www.foo.net') + t('richard at com.example', email='richard at com.example') + t('r at a.com', email='r at a.com') + t('i1', **{'class':'i', 'id':'1'}) + t('item123', **{'class':'item', 'id':'123'}) + t('www.user:pass at host.net', email='pass at host.net') + t('user:pass at www.host.net', url='user:pass at www.host.net') + t('123.35', nothing=True) + t('-.3535', nothing=True) + + def test_url_replace(self): + p = StringHTMLProperty(self.client, 'test', '1', None, 'test', '') + def t(s): return p.hyper_re.sub(p._hyper_repl, s) + ae = self.assertEquals + ae(t('http://roundup.net/'), 'http://roundup.net/') + ae(t('<HTTP://roundup.net/>'), '<HTTP://roundup.net/>') + ae(t('<www.roundup.net>'), '<www.roundup.net>') + ''' class HTMLPermissions: def is_edit_ok(self): @@ -243,6 +325,7 @@ suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(HTMLDatabaseTestCase)) suite.addTest(unittest.makeSuite(FunctionsTestCase)) + suite.addTest(unittest.makeSuite(HTMLClassTestCase)) return suite if __name__ == '__main__': Modified: tracker/roundup-src/test/test_token.py ============================================================================== --- tracker/roundup-src/test/test_token.py (original) +++ tracker/roundup-src/test/test_token.py Sun Mar 15 22:43:30 2009 @@ -8,7 +8,7 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # -# $Id: test_token.py,v 1.3 2003/10/25 22:53:26 richard Exp $ +# $Id: test_token.py,v 1.3 2003-10-25 22:53:26 richard Exp $ import unittest, time Modified: tracker/roundup-src/test/test_tsearch2.py ============================================================================== --- tracker/roundup-src/test/test_tsearch2.py (original) +++ tracker/roundup-src/test/test_tsearch2.py Sun Mar 15 22:43:30 2009 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_tsearch2.py,v 1.1 2004/12/16 22:22:55 jlgijsbers Exp $ +# $Id: test_tsearch2.py,v 1.1 2004-12-16 22:22:55 jlgijsbers Exp $ import unittest Added: tracker/roundup-src/test/test_userauditor.py ============================================================================== --- (empty file) +++ tracker/roundup-src/test/test_userauditor.py Sun Mar 15 22:43:30 2009 @@ -0,0 +1,112 @@ +# $Id$ + +import os, unittest, shutil +from db_test_base import setupTracker + +class UserAuditorTest(unittest.TestCase): + def setUp(self): + self.dirname = '_test_user_auditor' + self.instance = setupTracker(self.dirname) + self.db = self.instance.open('admin') + + try: + import pytz + self.pytz = True + except ImportError: + self.pytz = False + + self.db.user.create(username='kyle', address='kyle at example.com', + realname='Kyle Broflovski', roles='User') + + def tearDown(self): + self.db.close() + try: + shutil.rmtree(self.dirname) + except OSError, error: + if error.errno not in (errno.ENOENT, errno.ESRCH): raise + + def testBadTimezones(self): + self.assertRaises(ValueError, self.db.user.create, username='eric', timezone='24') + + userid = self.db.user.lookup('kyle') + + self.assertRaises(ValueError, self.db.user.set, userid, timezone='3000') + self.assertRaises(ValueError, self.db.user.set, userid, timezone='24') + self.assertRaises(ValueError, self.db.user.set, userid, timezone='-24') + self.assertRaises(ValueError, self.db.user.set, userid, timezone='-3000') + + if self.pytz: + try: + from pytz import UnknownTimeZoneError + except: + UnknownTimeZoneError = ValueError + self.assertRaises(UnknownTimeZoneError, self.db.user.set, userid, timezone='MiddleOf/Nowhere') + + def testGoodTimezones(self): + self.db.user.create(username='test_user01', timezone='12') + + if self.pytz: + self.db.user.create(username='test_user02', timezone='MST') + + userid = self.db.user.lookup('kyle') + + # TODO: roundup should accept non-integer offsets since those are valid + # this is the offset for Tehran, Iran + #self.db.user.set(userid, timezone='3.5') + + self.db.user.set(userid, timezone='-23') + self.db.user.set(userid, timezone='23') + self.db.user.set(userid, timezone='0') + + if self.pytz: + self.db.user.set(userid, timezone='US/Eastern') + + def testBadEmailAddresses(self): + userid = self.db.user.lookup('kyle') + self.assertRaises(ValueError, self.db.user.set, userid, address='kyle @ example.com') + self.assertRaises(ValueError, self.db.user.set, userid, address='one at example.com,two at example.com') + self.assertRaises(ValueError, self.db.user.set, userid, address='weird@@example.com') + self.assertRaises(ValueError, self.db.user.set, userid, address='embedded\nnewline at example.com') + # verify that we check alternates as well + self.assertRaises(ValueError, self.db.user.set, userid, alternate_addresses='kyle @ example.com') + # make sure we accept local style addresses + self.db.user.set(userid, address='kyle') + # verify we are case insensitive + self.db.user.set(userid, address='kyle at EXAMPLE.COM') + + def testUniqueEmailAddresses(self): + self.db.user.create(username='kenny', address='kenny at example.com', alternate_addresses='sp_ken at example.com') + self.assertRaises(ValueError, self.db.user.create, username='test_user01', address='kenny at example.com') + uid = self.db.user.create(username='eric', address='eric at example.com') + self.assertRaises(ValueError, self.db.user.set, uid, address='kenny at example.com') + + # make sure we check alternates + self.assertRaises(ValueError, self.db.user.set, uid, address='kenny at example.com') + self.assertRaises(ValueError, self.db.user.set, uid, address='sp_ken at example.com') + self.assertRaises(ValueError, self.db.user.set, uid, alternate_addresses='kenny at example.com') + + def testBadRoles(self): + userid = self.db.user.lookup('kyle') + self.assertRaises(ValueError, self.db.user.set, userid, roles='BadRole') + self.assertRaises(ValueError, self.db.user.set, userid, roles='User,BadRole') + + def testGoodRoles(self): + userid = self.db.user.lookup('kyle') + # make sure we handle commas in weird places + self.db.user.set(userid, roles='User,') + self.db.user.set(userid, roles=',User') + # make sure we strip whitespace + self.db.user.set(userid, roles=' User ') + # check for all-whitespace (treat as no role) + self.db.user.set(userid, roles=' ') + +def test_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(UserAuditorTest)) + return suite + +if __name__ == '__main__': + runner = unittest.TextTestRunner() + unittest.main(testRunner=runner) + +# vim: filetype=python sts=4 sw=4 et si Added: tracker/roundup-src/test/test_xmlrpc.py ============================================================================== --- (empty file) +++ tracker/roundup-src/test/test_xmlrpc.py Sun Mar 15 22:43:30 2009 @@ -0,0 +1,126 @@ +# +# Copyright (C) 2007 Stefan Seefeld +# All rights reserved. +# For license terms see the file COPYING.txt. +# + +import unittest, os, shutil, errno, sys, difflib, cgi, re + +from roundup.cgi.exceptions import * +from roundup import init, instance, password, hyperdb, date +from roundup.xmlrpc import RoundupInstance +from roundup.backends import list_backends + +import db_test_base + +NEEDS_INSTANCE = 1 + +class TestCase(unittest.TestCase): + + backend = None + + def setUp(self): + self.dirname = '_test_xmlrpc' + # set up and open a tracker + self.instance = db_test_base.setupTracker(self.dirname, self.backend) + + # open the database + self.db = self.instance.open('admin') + self.joeid = 'user' + self.db.user.create(username='joe', + password=password.Password('random'), address='random at home.org', + realname='Joe Random', roles='User') + + self.db.commit() + self.db.close() + self.db = self.instance.open('joe') + self.server = RoundupInstance(self.db, self.instance.actions, None) + + def tearDown(self): + self.db.close() + try: + shutil.rmtree(self.dirname) + except OSError, error: + if error.errno not in (errno.ENOENT, errno.ESRCH): raise + + def testAccess(self): + # Retrieve all three users. + results = self.server.list('user', 'id') + self.assertEqual(len(results), 3) + + # Obtain data for 'joe'. + results = self.server.display(self.joeid) + self.assertEqual(results['username'], 'joe') + self.assertEqual(results['realname'], 'Joe Random') + + def testChange(self): + # Reset joe's 'realname'. + results = self.server.set(self.joeid, 'realname=Joe Doe') + results = self.server.display(self.joeid, 'realname') + self.assertEqual(results['realname'], 'Joe Doe') + + # check we can't change admin's details + self.assertRaises(Unauthorised, self.server.set, 'user1', 'realname=Joe Doe') + + def testCreate(self): + results = self.server.create('issue', 'title=foo') + issueid = 'issue' + results + results = self.server.display(issueid, 'title') + self.assertEqual(results['title'], 'foo') + + def testFileCreate(self): + results = self.server.create('file', 'content=hello\r\nthere') + fileid = 'file' + results + results = self.server.display(fileid, 'content') + self.assertEqual(results['content'], 'hello\r\nthere') + + def testAction(self): + # As this action requires special previledges, we temporarily switch + # to 'admin' + self.db.setCurrentUser('admin') + users_before = self.server.list('user') + try: + tmp = 'user' + self.db.user.create(username='tmp') + self.server.action('retire', tmp) + finally: + self.db.setCurrentUser('joe') + users_after = self.server.list('user') + self.assertEqual(users_before, users_after) + + def testAuthDeniedEdit(self): + # Wrong permissions (caught by roundup security module). + self.assertRaises(Unauthorised, self.server.set, + 'user1', 'realname=someone') + + def testAuthDeniedCreate(self): + self.assertRaises(Unauthorised, self.server.create, + 'user', {'username': 'blah'}) + + def testAuthAllowedEdit(self): + self.db.setCurrentUser('admin') + try: + self.server.set('user2', 'realname=someone') + except Unauthorised, err: + self.fail('raised %s'%err) + finally: + self.db.setCurrentUser('joe') + + def testAuthAllowedCreate(self): + self.db.setCurrentUser('admin') + try: + self.server.create('user', 'username=blah') + except Unauthorised, err: + self.fail('raised %s'%err) + finally: + self.db.setCurrentUser('joe') + +def test_suite(): + suite = unittest.TestSuite() + for l in list_backends(): + dct = dict(backend = l) + subcls = type(TestCase)('TestCase_%s'%l, (TestCase,), dct) + suite.addTest(unittest.makeSuite(subcls)) + return suite + +if __name__ == '__main__': + runner = unittest.TextTestRunner() + unittest.main(testRunner=runner) Modified: tracker/roundup-src/tools/load_tracker.py ============================================================================== --- tracker/roundup-src/tools/load_tracker.py (original) +++ tracker/roundup-src/tools/load_tracker.py Sun Mar 15 22:43:30 2009 @@ -1,5 +1,5 @@ #! /usr/bin/env python -# $Id: load_tracker.py,v 1.6 2005/06/08 02:24:06 anthonybaxter Exp $ +# $Id: load_tracker.py,v 1.6 2005-06-08 02:24:06 anthonybaxter Exp $ ''' Usage: %s Modified: tracker/roundup-src/tools/pygettext.py ============================================================================== --- tracker/roundup-src/tools/pygettext.py (original) +++ tracker/roundup-src/tools/pygettext.py Sun Mar 15 22:43:30 2009 @@ -1,10 +1,11 @@ -#! /usr/bin/env python +#! /usr/bin/env python2.5 +# -*- coding: iso-8859-1 -*- # Originally written by Barry Warsaw # -# Minimally patched to make it even more xgettext compatible +# Minimally patched to make it even more xgettext compatible # by Peter Funk # -# 2001-12-18 J?rgen Hermann +# 2002-11-22 J?rgen Hermann # Added checks that _() only contains string literals, and # command line args are resolved to module lists, i.e. you # can now pass a filename, a module or package name, or a @@ -24,17 +25,17 @@ Many systems (Solaris, Linux, Gnu) provide extensive tools that ease the internationalization of C programs. Most of these tools are independent of the programming language and can be used from within Python programs. -Martin von Loewis' work[1] helps considerably in this regard. +Martin von Loewis' work[1] helps considerably in this regard. There's one problem though; xgettext is the program that scans source code looking for message strings, but it groks only C (or C++). Python introduces a few wrinkles, such as dual quoting characters, triple quoted -strings, and raw strings. xgettext understands none of this. +strings, and raw strings. xgettext understands none of this. Enter pygettext, which uses Python's standard tokenize module to scan Python source code, generating .pot files identical to what GNU xgettext[2] generates for C and C++ code. From there, the standard GNU tools can be -used. +used. A word about marking Python strings as candidates for translation. GNU xgettext recognizes the following keywords: gettext, dgettext, dcgettext, @@ -42,7 +43,7 @@ code. C and C++ have a trick: they use the C preprocessor. Most internationalized C source includes a #define for gettext() to _() so that what has to be written in the source is much less. Thus these are both -translatable strings: +translatable strings: gettext("Translatable String") _("Translatable String") @@ -58,7 +59,7 @@ xgettext where ever possible. However some options are still missing or are not fully implemented. Also, xgettext's use of command line switches with option arguments is broken, and in these cases, pygettext just defines -additional switches. +additional switches. Usage: pygettext [options] inputfile ... @@ -155,7 +156,9 @@ """) import os +import imp import sys +import glob import time import getopt import token @@ -255,19 +258,17 @@ def containsAny(str, set): - """ Check whether 'str' contains ANY of the chars in 'set' - """ + """Check whether 'str' contains ANY of the chars in 'set'""" return 1 in [c in str for c in set] def _visit_pyfiles(list, dirname, names): - """ Helper for getFilesForName(). - """ + """Helper for getFilesForName().""" # get extension for python source files if not globals().has_key('_py_ext'): - import imp global _py_ext - _py_ext = [triple[0] for triple in imp.get_suffixes() if triple[2] == imp.PY_SOURCE][0] + _py_ext = [triple[0] for triple in imp.get_suffixes() + if triple[2] == imp.PY_SOURCE][0] # don't recurse into CVS directories if 'CVS' in names: @@ -275,20 +276,18 @@ # add all *.py files to list list.extend( - [os.path.join(dirname, file) - for file in names - if os.path.splitext(file)[1] == _py_ext]) + [os.path.join(dirname, file) for file in names + if os.path.splitext(file)[1] == _py_ext] + ) def _get_modpkg_path(dotted_name, pathlist=None): - """ Get the filesystem path for a module or a package. + """Get the filesystem path for a module or a package. - Return the file system path to a file for a module, - and to a directory for a package. Return None if - the name is not found, or is a builtin or extension module. + Return the file system path to a file for a module, and to a directory for + a package. Return None if the name is not found, or is a builtin or + extension module. """ - import imp - # split off top-most name parts = dotted_name.split('.', 1) @@ -309,8 +308,10 @@ else: # plain name try: - file, pathname, description = imp.find_module(dotted_name, pathlist) - if file: file.close() + file, pathname, description = imp.find_module( + dotted_name, pathlist) + if file: + file.close() if description[2] not in [imp.PY_SOURCE, imp.PKG_DIRECTORY]: pathname = None except ImportError: @@ -320,15 +321,12 @@ def getFilesForName(name): - """ Get a list of module files for a filename, a module or package name, - or a directory. + """Get a list of module files for a filename, a module or package name, + or a directory. """ - import imp - if not os.path.exists(name): # check for glob chars if containsAny(name, "*?[]"): - import glob files = glob.glob(name) list = [] for file in files: @@ -414,7 +412,7 @@ def __openseen(self, ttype, tstring, lineno): if ttype == tokenize.OP and tstring == ')': # We've seen the last of the translatable strings. Record the - # line number of the first line of the strings and update the list + # line number of the first line of the strings and update the list # of messages seen. Reset state for the next batch. If there # were no strings inside _(), then just ignore this entry. if self.__data: @@ -425,8 +423,13 @@ elif ttype not in [tokenize.COMMENT, token.INDENT, token.DEDENT, token.NEWLINE, tokenize.NL]: # warn if we see anything else than STRING or whitespace - print >>sys.stderr, _('*** %(file)s:%(lineno)s: Seen unexpected token "%(token)s"') % { - 'token': tstring, 'file': self.__curfile, 'lineno': self.__lineno} + print >> sys.stderr, _( + '*** %(file)s:%(lineno)s: Seen unexpected token "%(token)s"' + ) % { + 'token': tstring, + 'file': self.__curfile, + 'lineno': self.__lineno + } self.__state = self.__waiting def __addentry(self, msg, lineno=None, isdocstring=0): @@ -442,7 +445,7 @@ def write(self, fp): options = self.__options - timestamp = time.ctime(time.time()) + timestamp = time.strftime('%Y-%m-%d %H:%M+%Z') # The time stamp in the header doesn't have the same format as that # generated by xgettext... print >> fp, pot_header % {'time': timestamp, 'version': __version__} @@ -661,6 +664,6 @@ main() # some more test strings _(u'a unicode string') - _('*** Seen unexpected token "%(token)s"' % {'token': 'test'}) # this one creates a warning + # this one creates a warning + _('*** Seen unexpected token "%(token)s"') % {'token': 'test'} _('more' 'than' 'one' 'string') - From python-checkins at python.org Sun Mar 15 22:43:38 2009 From: python-checkins at python.org (georg.brandl) Date: Sun, 15 Mar 2009 22:43:38 +0100 (CET) Subject: [Python-checkins] r70389 - python/trunk/Objects/typeobject.c Message-ID: <20090315214338.8BDF51E4010@bag.python.org> Author: georg.brandl Date: Sun Mar 15 22:43:38 2009 New Revision: 70389 Log: Fix a small nit in the error message if bool() falls back on __len__ and it returns the wrong type: it would tell the user that __nonzero__ should return bool or int. Modified: python/trunk/Objects/typeobject.c Modified: python/trunk/Objects/typeobject.c ============================================================================== --- python/trunk/Objects/typeobject.c (original) +++ python/trunk/Objects/typeobject.c Sun Mar 15 22:43:38 2009 @@ -5096,6 +5096,7 @@ PyObject *func, *args; static PyObject *nonzero_str, *len_str; int result = -1; + int using_len = 0; func = lookup_maybe(self, "__nonzero__", &nonzero_str); if (func == NULL) { @@ -5104,6 +5105,7 @@ func = lookup_maybe(self, "__len__", &len_str); if (func == NULL) return PyErr_Occurred() ? -1 : 1; + using_len = 1; } args = PyTuple_New(0); if (args != NULL) { @@ -5114,8 +5116,10 @@ result = PyObject_IsTrue(temp); else { PyErr_Format(PyExc_TypeError, - "__nonzero__ should return " + "%s should return " "bool or int, returned %s", + (using_len ? "__len__" + : "__nonzero__"), temp->ob_type->tp_name); result = -1; } From python-checkins at python.org Sun Mar 15 22:44:43 2009 From: python-checkins at python.org (georg.brandl) Date: Sun, 15 Mar 2009 22:44:43 +0100 (CET) Subject: [Python-checkins] r70390 - python/trunk/Doc/library/contextlib.rst Message-ID: <20090315214443.F311E1E4010@bag.python.org> Author: georg.brandl Date: Sun Mar 15 22:44:43 2009 New Revision: 70390 Log: #5491: clarify nested() semantics. Modified: python/trunk/Doc/library/contextlib.rst Modified: python/trunk/Doc/library/contextlib.rst ============================================================================== --- python/trunk/Doc/library/contextlib.rst (original) +++ python/trunk/Doc/library/contextlib.rst Sun Mar 15 22:44:43 2009 @@ -63,14 +63,15 @@ from contextlib import nested - with nested(A, B, C) as (X, Y, Z): + with nested(A(), B(), C()) as (X, Y, Z): do_something() is equivalent to this:: - with A as X: - with B as Y: - with C as Z: + m1, m2, m3 = A(), B(), C() + with m1 as X: + with m2 as Y: + with m3 as Z: do_something() Note that if the :meth:`__exit__` method of one of the nested context managers From python-checkins at python.org Sun Mar 15 22:44:44 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 15 Mar 2009 22:44:44 +0100 (CET) Subject: [Python-checkins] r70391 - tracker/roundup-src/roundup/scripts/roundup_xmlrpc_server.py Message-ID: <20090315214444.2D2651E4011@bag.python.org> Author: martin.v.loewis Date: Sun Mar 15 22:44:43 2009 New Revision: 70391 Log: Add 1.4.7 file missing in previous commit. Added: tracker/roundup-src/roundup/scripts/roundup_xmlrpc_server.py (contents, props changed) Added: tracker/roundup-src/roundup/scripts/roundup_xmlrpc_server.py ============================================================================== --- (empty file) +++ tracker/roundup-src/roundup/scripts/roundup_xmlrpc_server.py Sun Mar 15 22:44:43 2009 @@ -0,0 +1,175 @@ +#! /usr/bin/env python +# +# Copyright (C) 2007 Stefan Seefeld +# All rights reserved. +# For license terms see the file COPYING.txt. +# + +import base64, getopt, os, sys, socket, urllib +from roundup.xmlrpc import translate +from roundup.xmlrpc import RoundupInstance +import roundup.instance +from roundup.instance import TrackerError +from roundup.cgi.exceptions import Unauthorised +from SimpleXMLRPCServer import SimpleXMLRPCServer +from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler + + +class RequestHandler(SimpleXMLRPCRequestHandler): + """A SimpleXMLRPCRequestHandler with support for basic + HTTP Authentication.""" + + TRACKER_HOMES = {} + TRACKERS = {} + + def is_rpc_path_valid(self): + path = self.path.split('/') + name = urllib.unquote(path[1]).lower() + return name in self.TRACKER_HOMES + + def get_tracker(self, name): + """Return a tracker instance for given tracker name.""" + + if name in self.TRACKERS: + return self.TRACKERS[name] + + if name not in self.TRACKER_HOMES: + raise Exception('No such tracker "%s"'%name) + tracker_home = self.TRACKER_HOMES[name] + tracker = roundup.instance.open(tracker_home) + self.TRACKERS[name] = tracker + return tracker + + + def authenticate(self, tracker): + + + # Try to extract username and password from HTTP Authentication. + username, password = None, None + authorization = self.headers.get('authorization', ' ') + scheme, challenge = authorization.split(' ', 1) + + if scheme.lower() == 'basic': + decoded = base64.decodestring(challenge) + if ':' in decoded: + username, password = decoded.split(':') + else: + username = decoded + if not username: + username = 'anonymous' + db = tracker.open('admin') + try: + userid = db.user.lookup(username) + except KeyError: # No such user + db.close() + raise Unauthorised, 'Invalid user' + stored = db.user.get(userid, 'password') + if stored != password: + # Wrong password + db.close() + raise Unauthorised, 'Invalid user' + db.setCurrentUser(username) + return db + + + def do_POST(self): + """Extract username and password from authorization header.""" + + db = None + try: + path = self.path.split('/') + tracker_name = urllib.unquote(path[1]).lower() + tracker = self.get_tracker(tracker_name) + db = self.authenticate(tracker) + + instance = RoundupInstance(db, tracker.actions, None) + self.server.register_instance(instance) + SimpleXMLRPCRequestHandler.do_POST(self) + except Unauthorised, message: + self.send_error(403, '%s (%s)'%(self.path, message)) + except: + if db: + db.close() + exc, val, tb = sys.exc_info() + print exc, val, tb + raise + if db: + db.close() + + +class Server(SimpleXMLRPCServer): + + def _dispatch(self, method, params): + + retn = SimpleXMLRPCServer._dispatch(self, method, params) + retn = translate(retn) + return retn + + +def usage(): + print """Usage: %s: [options] [name=tracker home]+ + +Options: + -e, --encoding -- specify the encoding to use + -V -- be verbose when importing + -p, --port -- port to listen on + +"""%sys.argv[0] + +def run(): + + try: + opts, args = getopt.getopt(sys.argv[1:], + 'e:i:p:V', ['encoding=', 'port=']) + except getopt.GetoptError, e: + usage() + return 1 + + verbose = False + port = 8000 + encoding = None + + for opt, arg in opts: + if opt == '-V': + verbose = True + elif opt in ['-p', '--port']: + port = int(arg) + elif opt in ['-e', '--encoding']: + encoding = encoding + + tracker_homes = {} + for arg in args: + try: + name, home = arg.split('=', 1) + # Validate the argument + tracker = roundup.instance.open(home) + except ValueError: + print 'Instances must be name=home' + sys.exit(-1) + except TrackerError: + print 'Tracker home does not exist.' + sys.exit(-1) + + tracker_homes[name] = home + + RequestHandler.TRACKER_HOMES=tracker_homes + + if sys.version_info[0:2] < (2,5): + if encoding: + print 'encodings not supported with python < 2.5' + sys.exit(-1) + server = Server(('', port), RequestHandler) + else: + server = Server(('', port), RequestHandler, + allow_none=True, encoding=encoding) + + # Go into the main listener loop + print 'Roundup XMLRPC server started on %s:%d' \ + % (socket.gethostname(), port) + try: + server.serve_forever() + except KeyboardInterrupt: + print 'Keyboard Interrupt: exiting' + +if __name__ == '__main__': + run() From python-checkins at python.org Sun Mar 15 22:46:00 2009 From: python-checkins at python.org (georg.brandl) Date: Sun, 15 Mar 2009 22:46:00 +0100 (CET) Subject: [Python-checkins] r70392 - python/trunk/Doc/c-api/typeobj.rst Message-ID: <20090315214600.56B231E400C@bag.python.org> Author: georg.brandl Date: Sun Mar 15 22:46:00 2009 New Revision: 70392 Log: #5488: add missing struct member. Modified: python/trunk/Doc/c-api/typeobj.rst Modified: python/trunk/Doc/c-api/typeobj.rst ============================================================================== --- python/trunk/Doc/c-api/typeobj.rst (original) +++ python/trunk/Doc/c-api/typeobj.rst Sun Mar 15 22:46:00 2009 @@ -1180,6 +1180,7 @@ binaryfunc nb_inplace_add; binaryfunc nb_inplace_subtract; binaryfunc nb_inplace_multiply; + binaryfunc nb_inplace_divide; binaryfunc nb_inplace_remainder; ternaryfunc nb_inplace_power; binaryfunc nb_inplace_lshift; From python-checkins at python.org Sun Mar 15 22:47:43 2009 From: python-checkins at python.org (georg.brandl) Date: Sun, 15 Mar 2009 22:47:43 +0100 (CET) Subject: [Python-checkins] r70393 - python/trunk/Doc/library/xml.dom.rst Message-ID: <20090315214743.283D11E4002@bag.python.org> Author: georg.brandl Date: Sun Mar 15 22:47:42 2009 New Revision: 70393 Log: #5478: fix copy-paste oversight in function signature. Modified: python/trunk/Doc/library/xml.dom.rst Modified: python/trunk/Doc/library/xml.dom.rst ============================================================================== --- python/trunk/Doc/library/xml.dom.rst (original) +++ python/trunk/Doc/library/xml.dom.rst Sun Mar 15 22:47:42 2009 @@ -611,7 +611,7 @@ Same as equivalent method in the :class:`Document` class. -.. method:: Element.getElementsByTagNameNS(tagName) +.. method:: Element.getElementsByTagNameNS(namespaceURI, localName) Same as equivalent method in the :class:`Document` class. From python-checkins at python.org Sun Mar 15 22:51:16 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 15 Mar 2009 22:51:16 +0100 (CET) Subject: [Python-checkins] r70394 - tracker/roundup-src/roundup/cgi/client.py Message-ID: <20090315215116.55D6C1E4002@bag.python.org> Author: martin.v.loewis Date: Sun Mar 15 22:51:16 2009 New Revision: 70394 Log: Reapply r54913 (erik.forsberg) 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 Modified: tracker/roundup-src/roundup/cgi/client.py ============================================================================== --- tracker/roundup-src/roundup/cgi/client.py (original) +++ tracker/roundup-src/roundup/cgi/client.py Sun Mar 15 22:51:16 2009 @@ -542,9 +542,29 @@ if now - last_clean < hour: return - self.session_api.clean_up() - self.db.getOTKManager().clean() - self.db.getOTKManager().set('last_clean', last_use=now) + # 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 + + try: + self.session_api.clean_up() + self.db.getOTKManager().clean() + self.db.getOTKManager().set('last_clean', last_use=now) + 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 + self.db.rollback() + return self.db.commit(fail_ok=True) def determine_charset(self): From python-checkins at python.org Sun Mar 15 22:51:48 2009 From: python-checkins at python.org (georg.brandl) Date: Sun, 15 Mar 2009 22:51:48 +0100 (CET) Subject: [Python-checkins] r70395 - python/trunk/Doc/library/idle.rst Message-ID: <20090315215148.687681E4002@bag.python.org> Author: georg.brandl Date: Sun Mar 15 22:51:48 2009 New Revision: 70395 Log: #5276: document IDLESTARTUP and .Idle.py. Modified: python/trunk/Doc/library/idle.rst Modified: python/trunk/Doc/library/idle.rst ============================================================================== --- python/trunk/Doc/library/idle.rst (original) +++ python/trunk/Doc/library/idle.rst Sun Mar 15 22:51:48 2009 @@ -253,6 +253,24 @@ black +Startup +------- + +Upon startup with the ``-s`` option, IDLE will execute the file referenced by +the environment variables :envvar:`IDLESTARTUP` or :envvar:`PYTHONSTARTUP`. +Idle first checks for ``IDLESTARTUP``; if ``IDLESTARTUP`` is present the file +referenced is run. If ``IDLESTARTUP`` is not present, Idle checks for +``PYTHONSTARTUP``. Files referenced by these environment variables are +convenient places to store functions that are used frequently from the Idle +shell, or for executing import statements to import common modules. + +In addition, ``Tk`` also loads a startup file if it is present. Note that the +Tk file is loaded unconditionally. This additional file is ``.Idle.py`` and is +looked for in the user's home directory. Statements in this file will be +executed in the Tk namespace, so this file is not useful for importing functions +to be used from Idle's Python shell. + + Command line usage ^^^^^^^^^^^^^^^^^^ From python-checkins at python.org Sun Mar 15 22:53:06 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 15 Mar 2009 22:53:06 +0100 (CET) Subject: [Python-checkins] r70396 - tracker/roundup-src/roundup/cgi/client.py Message-ID: <20090315215306.1474C1E4002@bag.python.org> Author: martin.v.loewis Date: Sun Mar 15 22:53:05 2009 New Revision: 70396 Log: Reapply r65435: Release DB locks if we don't want to clean. This should prevent the subsequent update of our own session to run into a conflict. Modified: tracker/roundup-src/roundup/cgi/client.py Modified: tracker/roundup-src/roundup/cgi/client.py ============================================================================== --- tracker/roundup-src/roundup/cgi/client.py (original) +++ tracker/roundup-src/roundup/cgi/client.py Sun Mar 15 22:53:05 2009 @@ -540,6 +540,8 @@ # 'last_clean' string is used instead of otk key last_clean = self.db.getOTKManager().get('last_clean', 'last_use', 0) if now - last_clean < hour: + # Release the database lock obtained when looking at last_clean + self.db.rollback() return # This is a bit ugly, but right now, I'm too lazy to fix a new API From python-checkins at python.org Sun Mar 15 22:53:56 2009 From: python-checkins at python.org (georg.brandl) Date: Sun, 15 Mar 2009 22:53:56 +0100 (CET) Subject: [Python-checkins] r70397 - python/trunk/Doc/reference/executionmodel.rst Message-ID: <20090315215356.40BF61E4002@bag.python.org> Author: georg.brandl Date: Sun Mar 15 22:53:56 2009 New Revision: 70397 Log: #5469: add with statement to list of name-binding constructs. Modified: python/trunk/Doc/reference/executionmodel.rst Modified: python/trunk/Doc/reference/executionmodel.rst ============================================================================== --- python/trunk/Doc/reference/executionmodel.rst (original) +++ python/trunk/Doc/reference/executionmodel.rst Sun Mar 15 22:53:56 2009 @@ -87,9 +87,10 @@ The following constructs bind names: formal parameters to functions, :keyword:`import` statements, class and function definitions (these bind the class or function name in the defining block), and targets that are identifiers -if occurring in an assignment, :keyword:`for` loop header, or in the second -position of an :keyword:`except` clause header. The :keyword:`import` statement -of the form "``from ...import *``" binds all names defined in the imported +if occurring in an assignment, :keyword:`for` loop header, in the second +position of an :keyword:`except` clause header or after :keyword:`as` in a +:keyword:`with` statement. The :keyword:`import` statement +of the form ``from ... import *`` binds all names defined in the imported module, except those beginning with an underscore. This form may only be used at the module level. From python-checkins at python.org Sun Mar 15 22:57:20 2009 From: python-checkins at python.org (georg.brandl) Date: Sun, 15 Mar 2009 22:57:20 +0100 (CET) Subject: [Python-checkins] r70398 - in python/branches/py3k: Doc/reference/executionmodel.rst Message-ID: <20090315215720.C09851E4002@bag.python.org> Author: georg.brandl Date: Sun Mar 15 22:57:20 2009 New Revision: 70398 Log: Merged revisions 70397 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70397 | georg.brandl | 2009-03-15 22:53:56 +0100 (So, 15 M?r 2009) | 1 line #5469: add with statement to list of name-binding constructs. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/reference/executionmodel.rst Modified: python/branches/py3k/Doc/reference/executionmodel.rst ============================================================================== --- python/branches/py3k/Doc/reference/executionmodel.rst (original) +++ python/branches/py3k/Doc/reference/executionmodel.rst Sun Mar 15 22:57:20 2009 @@ -86,9 +86,10 @@ The following constructs bind names: formal parameters to functions, :keyword:`import` statements, class and function definitions (these bind the class or function name in the defining block), and targets that are identifiers -if occurring in an assignment, :keyword:`for` loop header, or in the second -position of an :keyword:`except` clause header. The :keyword:`import` statement -of the form "``from ...import *``" binds all names defined in the imported +if occurring in an assignment, :keyword:`for` loop header, or after +:keyword:`as` in a :keyword:`with` statement or :keyword.`except` clause. +The :keyword:`import` statement +of the form ``from ... import *`` binds all names defined in the imported module, except those beginning with an underscore. This form may only be used at the module level. From python-checkins at python.org Sun Mar 15 22:58:38 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 15 Mar 2009 22:58:38 +0100 (CET) Subject: [Python-checkins] r70399 - tracker/roundup-src/roundup/roundupdb.py Message-ID: <20090315215838.A51641E4002@bag.python.org> Author: martin.v.loewis Date: Sun Mar 15 22:58:38 2009 New Revision: 70399 Log: Reapply r54384 (erik.forsberg): Extensions to roundup to allow author of property-only changes to be seen. Use of these extensions in busybody.py. Should fix problem noted in msg322 of http://psf.upfronthosting.co.za/roundup/meta/issue32. Modified: tracker/roundup-src/roundup/roundupdb.py Modified: tracker/roundup-src/roundup/roundupdb.py ============================================================================== --- tracker/roundup-src/roundup/roundupdb.py (original) +++ tracker/roundup-src/roundup/roundupdb.py Sun Mar 15 22:58:38 2009 @@ -278,7 +278,7 @@ sendmessage = nosymessage def send_message(self, nodeid, msgid, note, sendto, from_address=None, - bcc_sendto=[]): + bcc_sendto=[], authid=None): '''Actually send the nominated message from this node to the sendto recipients, with the note appended. ''' @@ -308,7 +308,12 @@ title = self.get(nodeid, 'title') or '%s message copy'%cn # figure author information - if msgid: + if authid: + authname = users.get(authid, 'realname') + if not authname: + authname = users.get(authid, 'username', '') + authaddr = users.get(authid, 'address', '') + elif msgid: authid = messages.get(msgid, 'author') else: authid = self.db.getuid() @@ -338,7 +343,8 @@ m.append(_("%(authname)s%(authaddr)s added the comment:") % locals()) else: - m.append(_("Change by %(authname)s%(authaddr)s:") % locals()) + m.append(_("Changes by %(authname)s%(authaddr)s:") + % locals()) m.append('') # add the content From python-checkins at python.org Sun Mar 15 22:59:38 2009 From: python-checkins at python.org (georg.brandl) Date: Sun, 15 Mar 2009 22:59:38 +0100 (CET) Subject: [Python-checkins] r70400 - in python/trunk/Doc: howto/regex.rst library/re.rst Message-ID: <20090315215938.0D0E51E4002@bag.python.org> Author: georg.brandl Date: Sun Mar 15 22:59:37 2009 New Revision: 70400 Log: Fix markup in re docs and give a mail address in regex howto, so that the recommendation to send suggestions to the author can be followed. Modified: python/trunk/Doc/howto/regex.rst python/trunk/Doc/library/re.rst Modified: python/trunk/Doc/howto/regex.rst ============================================================================== --- python/trunk/Doc/howto/regex.rst (original) +++ python/trunk/Doc/howto/regex.rst Sun Mar 15 22:59:37 2009 @@ -4,7 +4,7 @@ Regular Expression HOWTO **************************** -:Author: A.M. Kuchling +:Author: A.M. Kuchling :Release: 0.05 .. TODO: Modified: python/trunk/Doc/library/re.rst ============================================================================== --- python/trunk/Doc/library/re.rst (original) +++ python/trunk/Doc/library/re.rst Sun Mar 15 22:59:37 2009 @@ -1110,7 +1110,7 @@ string)`` or ``re.search(pattern, string)``. :func:`match` has an optional second parameter that gives an index in the string -where the search is to start: +where the search is to start:: >>> pattern = re.compile("o") >>> pattern.match("dog") # No match as "o" is not at the start of "dog." From python-checkins at python.org Sun Mar 15 23:03:50 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 15 Mar 2009 23:03:50 +0100 (CET) Subject: [Python-checkins] r70401 - tracker/roundup-src/roundup/cgi/templating.py Message-ID: <20090315220350.322C31E4002@bag.python.org> Author: martin.v.loewis Date: Sun Mar 15 23:03:50 2009 New Revision: 70401 Log: Reapply r62493: Add support for unchecked display of properties. Modified: tracker/roundup-src/roundup/cgi/templating.py Modified: tracker/roundup-src/roundup/cgi/templating.py ============================================================================== --- tracker/roundup-src/roundup/cgi/templating.py (original) +++ tracker/roundup-src/roundup/cgi/templating.py Sun Mar 15 23:03:50 2009 @@ -1347,14 +1347,14 @@ """ Render a "hyperlinked" version of the text """ return self.plain(hyperlink=1) - def plain(self, escape=0, hyperlink=0): + def plain(self, escape=0, hyperlink=0, unchecked=0): """Render a "plain" representation of the property - "escape" turns on/off HTML quoting - "hyperlink" turns on/off in-text hyperlinking of URLs, email addresses and designators """ - if not self.is_view_ok(): + if not self.is_view_ok() and not unchecked: return self._('[hidden]') if self._value is None: From python-checkins at python.org Sun Mar 15 23:06:49 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 15 Mar 2009 23:06:49 +0100 (CET) Subject: [Python-checkins] r70402 - in tracker/roundup-src/roundup: cgi/client.py mailer.py Message-ID: <20090315220649.616181E4002@bag.python.org> Author: martin.v.loewis Date: Sun Mar 15 23:06:49 2009 New Revision: 70402 Log: Reapply r65325: Put request information into exception emails. Modified: tracker/roundup-src/roundup/cgi/client.py tracker/roundup-src/roundup/mailer.py Modified: tracker/roundup-src/roundup/cgi/client.py ============================================================================== --- tracker/roundup-src/roundup/cgi/client.py (original) +++ tracker/roundup-src/roundup/cgi/client.py Sun Mar 15 23:06:49 2009 @@ -519,9 +519,21 @@ if self.instance.config.WEB_DEBUG: self.write_html(cgitb.html(i18n=self.translator)) else: - self.mailer.exception_message() + self.mailer.exception_message(self.exception_data()) return self.write_html(self._(error_message)) + def exception_data(self): + result = '' + try: + for k,v in self.env.items(): + result += "%s=%s\n" % (k,v) + for k,v in self.request.headers.items(): + result += "%s=%s\n" % (k,v) + result += "user:" + repr(self.user) + "\n" + except: + pass + return result + def clean_sessions(self): """Deprecated XXX remove Modified: tracker/roundup-src/roundup/mailer.py ============================================================================== --- tracker/roundup-src/roundup/mailer.py (original) +++ tracker/roundup-src/roundup/mailer.py Sun Mar 15 23:06:49 2009 @@ -169,14 +169,14 @@ # because of spam) pass - def exception_message(self): + def exception_message(self, data=''): '''Send a message to the admins with information about the latest traceback. ''' subject = '%s: %s'%(self.config.TRACKER_NAME, sys.exc_info()[1]) to = [self.config.ADMIN_EMAIL] content = '\n'.join(traceback.format_exception(*sys.exc_info())) - self.standard_message(to, subject, content) + self.standard_message(to, subject, data+content) def smtp_send(self, to, message): """Send a message over SMTP, using roundup's config. From python-checkins at python.org Sun Mar 15 23:07:50 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 15 Mar 2009 23:07:50 +0100 (CET) Subject: [Python-checkins] r70403 - tracker/roundup-src/roundup/cgi/client.py Message-ID: <20090315220750.0E98C1E4002@bag.python.org> Author: martin.v.loewis Date: Sun Mar 15 23:07:49 2009 New Revision: 70403 Log: Reapply r65398: Don't pass huge itemids into the backend. Modified: tracker/roundup-src/roundup/cgi/client.py Modified: tracker/roundup-src/roundup/cgi/client.py ============================================================================== --- tracker/roundup-src/roundup/cgi/client.py (original) +++ tracker/roundup-src/roundup/cgi/client.py Sun Mar 15 23:07:49 2009 @@ -843,6 +843,10 @@ klass = self.db.getclass(self.classname) except KeyError: raise NotFound, '%s/%s'%(self.classname, self.nodeid) + if long(self.nodeid) > 2**31: + # Postgres will complain with a ProgrammingError + # if we try to pass in numbers that are too large + raise NotFound, '%s/%s'%(self.classname, self.nodeid) if not klass.hasnode(self.nodeid): raise NotFound, '%s/%s'%(self.classname, self.nodeid) # with a designator, we default to item view From python-checkins at python.org Sun Mar 15 23:09:15 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sun, 15 Mar 2009 23:09:15 +0100 (CET) Subject: [Python-checkins] r70404 - tracker/roundup-src/roundup/cgi/actions.py Message-ID: <20090315220915.D9DFC1E4002@bag.python.org> Author: martin.v.loewis Date: Sun Mar 15 23:09:15 2009 New Revision: 70404 Log: Reapply r65359: Validate CSV export request. Modified: tracker/roundup-src/roundup/cgi/actions.py Modified: tracker/roundup-src/roundup/cgi/actions.py ============================================================================== --- tracker/roundup-src/roundup/cgi/actions.py (original) +++ tracker/roundup-src/roundup/cgi/actions.py Sun Mar 15 23:09:15 2009 @@ -1010,6 +1010,14 @@ columns = request.columns klass = self.db.getclass(request.classname) + # validate the request + allprops = klass.getprops() + for c in filterspec.keys() + columns + [x[1] for x in group + sort]: + if not allprops.has_key(c): + # Can't use FormError, since that would try to use + # the same bogus field specs + raise exceptions.SeriousError, "Property %s does not exist" % c + # full-text search if request.search_text: matches = self.db.indexer.search( From python-checkins at python.org Sun Mar 15 23:11:07 2009 From: python-checkins at python.org (georg.brandl) Date: Sun, 15 Mar 2009 23:11:07 +0100 (CET) Subject: [Python-checkins] r70405 - python/trunk/Lib/Queue.py Message-ID: <20090315221107.7BE041E4002@bag.python.org> Author: georg.brandl Date: Sun Mar 15 23:11:07 2009 New Revision: 70405 Log: Move the previously local import of threading to module level. This is cleaner and avoids lockups in obscure cases where a Queue is instantiated while the import lock is already held by another thread. OKed by Tim Peters. Modified: python/trunk/Lib/Queue.py Modified: python/trunk/Lib/Queue.py ============================================================================== --- python/trunk/Lib/Queue.py (original) +++ python/trunk/Lib/Queue.py Sun Mar 15 23:11:07 2009 @@ -1,6 +1,10 @@ """A multi-producer, multi-consumer queue.""" from time import time as _time +try: + import threading as _threading +except ImportError: + import dummy_threading as _threading from collections import deque import heapq @@ -20,26 +24,22 @@ If maxsize is <= 0, the queue size is infinite. """ def __init__(self, maxsize=0): - try: - import threading - except ImportError: - import dummy_threading as threading self.maxsize = maxsize self._init(maxsize) # mutex must be held whenever the queue is mutating. All methods # that acquire mutex must release it before returning. mutex # is shared between the three conditions, so acquiring and # releasing the conditions also acquires and releases mutex. - self.mutex = threading.Lock() + self.mutex = _threading.Lock() # Notify not_empty whenever an item is added to the queue; a # thread waiting to get is notified then. - self.not_empty = threading.Condition(self.mutex) + self.not_empty = _threading.Condition(self.mutex) # Notify not_full whenever an item is removed from the queue; # a thread waiting to put is notified then. - self.not_full = threading.Condition(self.mutex) + self.not_full = _threading.Condition(self.mutex) # Notify all_tasks_done whenever the number of unfinished tasks # drops to zero; thread waiting to join() is notified to resume - self.all_tasks_done = threading.Condition(self.mutex) + self.all_tasks_done = _threading.Condition(self.mutex) self.unfinished_tasks = 0 def task_done(self): From python-checkins at python.org Sun Mar 15 23:43:14 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Sun, 15 Mar 2009 23:43:14 +0100 (CET) Subject: [Python-checkins] r70406 - python/trunk/Lib/distutils/tests/test_msvc9compiler.py Message-ID: <20090315224314.3D4321E4002@bag.python.org> Author: hirokazu.yamamoto Date: Sun Mar 15 23:43:14 2009 New Revision: 70406 Log: Added skip for old MSVC. Modified: python/trunk/Lib/distutils/tests/test_msvc9compiler.py Modified: python/trunk/Lib/distutils/tests/test_msvc9compiler.py ============================================================================== --- python/trunk/Lib/distutils/tests/test_msvc9compiler.py (original) +++ python/trunk/Lib/distutils/tests/test_msvc9compiler.py Sun Mar 15 23:43:14 2009 @@ -34,6 +34,10 @@ if sys.platform != 'win32': # this test is only for win32 return + from distutils.msvccompiler import get_build_version + if get_build_version() < 8.0: + # this test is only for MSVC8.0 or above + return from distutils.msvc9compiler import Reg self.assertRaises(KeyError, Reg.get_value, 'xxx', 'xxx') From python-checkins at python.org Mon Mar 16 00:04:11 2009 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 16 Mar 2009 00:04:11 +0100 (CET) Subject: [Python-checkins] r70407 - tracker/roundup-src/roundup/cgi/actions.py Message-ID: <20090315230411.287181E4002@bag.python.org> Author: martin.v.loewis Date: Mon Mar 16 00:04:11 2009 New Revision: 70407 Log: Remove access to undefined variable "exists". Modified: tracker/roundup-src/roundup/cgi/actions.py Modified: tracker/roundup-src/roundup/cgi/actions.py ============================================================================== --- tracker/roundup-src/roundup/cgi/actions.py (original) +++ tracker/roundup-src/roundup/cgi/actions.py Mon Mar 16 00:04:11 2009 @@ -1049,7 +1049,7 @@ row = [] for name in columns: # check permission to view this property on this item - if exists and not self.hasPermission('View', itemid=itemid, + if not self.hasPermission('View', itemid=itemid, classname=request.classname, property=name): raise exceptions.Unauthorised, self._( 'You do not have permission to view %(class)s' From python-checkins at python.org Mon Mar 16 00:15:49 2009 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 16 Mar 2009 00:15:49 +0100 (CET) Subject: [Python-checkins] r70408 - tracker/roundup-src/roundup/cgi/templating.py Message-ID: <20090315231549.0A7341E400C@bag.python.org> Author: martin.v.loewis Date: Mon Mar 16 00:15:48 2009 New Revision: 70408 Log: Suppress email error report if somebody fills bogus values into :startwith or :pagesize. Modified: tracker/roundup-src/roundup/cgi/templating.py Modified: tracker/roundup-src/roundup/cgi/templating.py ============================================================================== --- tracker/roundup-src/roundup/cgi/templating.py (original) +++ tracker/roundup-src/roundup/cgi/templating.py Mon Mar 16 00:15:48 2009 @@ -2400,13 +2400,21 @@ for name in ':pagesize @pagesize'.split(): if self.form.has_key(name): self.special_char = name[0] - self.pagesize = int(self.form.getfirst(name)) + try: + self.pagesize = int(self.form.getfirst(name)) + except ValueError: + # Not an integer. XXX report to user somehow? + pass self.startwith = 0 for name in ':startwith @startwith'.split(): if self.form.has_key(name): self.special_char = name[0] - self.startwith = int(self.form.getfirst(name)) + try: + self.startwith = int(self.form.getfirst(name)) + except ValueError: + # Not an integer. XXX report to user somehow? + pass # dispname if self.form.has_key('@dispname'): From buildbot at python.org Mon Mar 16 00:34:33 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 15 Mar 2009 23:34:33 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090315233433.61A0C1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/728 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Mon Mar 16 00:55:21 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 15 Mar 2009 23:55:21 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090315235521.EC39D1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/412 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: georg.brandl BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Mon Mar 16 00:59:46 2009 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 16 Mar 2009 00:59:46 +0100 (CET) Subject: [Python-checkins] r70409 - in tracker/roundup-src/roundup: cgi/client.py mailer.py Message-ID: <20090315235946.A87FD1E4002@bag.python.org> Author: martin.v.loewis Date: Mon Mar 16 00:59:46 2009 New Revision: 70409 Log: get_standard_message does not anymore return a tuple, but an email Message. Modified: tracker/roundup-src/roundup/cgi/client.py tracker/roundup-src/roundup/mailer.py Modified: tracker/roundup-src/roundup/cgi/client.py ============================================================================== --- tracker/roundup-src/roundup/cgi/client.py (original) +++ tracker/roundup-src/roundup/cgi/client.py Mon Mar 16 00:59:46 2009 @@ -1029,15 +1029,14 @@ to = [self.mailer.config.ADMIN_EMAIL] subject = "Templating Error: %s" % exc_info[1] content = cgitb.pt_html() - message, writer = self.mailer.get_standard_message( - to, subject) - writer.addheader('Content-Transfer-Encoding', 'quoted-printable') - body = writer.startbody('text/html; charset=utf-8') - content = StringIO(content) - quopri.encode(content, body, 0) - self.mailer.smtp_send(to, message) + message = self.mailer.get_standard_message(to, subject) + # delete existing content-type headers + del message['Content-type'] + message['Content-type'] = 'text/html; charset=utf-8' + message.set_payload(content) + self.mailer.smtp_send(to, str(message)) # Now report the error to the user. - return self._(error_message) + return self._(self.error_message) except: # Reraise the original exception. The user will # receive an error message, and the adminstrator will Modified: tracker/roundup-src/roundup/mailer.py ============================================================================== --- tracker/roundup-src/roundup/mailer.py (original) +++ tracker/roundup-src/roundup/mailer.py Mon Mar 16 00:59:46 2009 @@ -55,7 +55,7 @@ Subject and author are encoded using the EMAIL_CHARSET from the config (default UTF-8). - Returns a Message object and body part writer. + Returns a Message object. ''' # encode header values if they need to be charset = getattr(self.config, 'EMAIL_CHARSET', 'utf-8') From python-checkins at python.org Mon Mar 16 01:06:00 2009 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 16 Mar 2009 01:06:00 +0100 (CET) Subject: [Python-checkins] r70410 - tracker/roundup-src/roundup/roundupdb.py Message-ID: <20090316000600.9FA621E404D@bag.python.org> Author: martin.v.loewis Date: Mon Mar 16 01:06:00 2009 New Revision: 70410 Log: Convert Message to str before sending it. Modified: tracker/roundup-src/roundup/roundupdb.py Modified: tracker/roundup-src/roundup/roundupdb.py ============================================================================== --- tracker/roundup-src/roundup/roundupdb.py (original) +++ tracker/roundup-src/roundup/roundupdb.py Mon Mar 16 01:06:00 2009 @@ -505,9 +505,9 @@ encode_quopri(message) if first: - mailer.smtp_send(sendto + bcc_sendto, message) + mailer.smtp_send(sendto + bcc_sendto, str(message)) else: - mailer.smtp_send(sendto, message) + mailer.smtp_send(sendto, str(message)) first = False def email_signature(self, nodeid, msgid): From buildbot at python.org Mon Mar 16 01:16:28 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 16 Mar 2009 00:16:28 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090316001628.8FEC31E406E@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/238 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 16 01:18:02 2009 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 16 Mar 2009 01:18:02 +0100 (CET) Subject: [Python-checkins] r70411 - tracker/roundup-src/roundup/mailer.py Message-ID: <20090316001802.EF0501E400C@bag.python.org> Author: martin.v.loewis Date: Mon Mar 16 01:18:02 2009 New Revision: 70411 Log: Stop sending multiple content-type and content-transfer-encoding headers. Modified: tracker/roundup-src/roundup/mailer.py Modified: tracker/roundup-src/roundup/mailer.py ============================================================================== --- tracker/roundup-src/roundup/mailer.py (original) +++ tracker/roundup-src/roundup/mailer.py Mon Mar 16 01:18:02 2009 @@ -23,6 +23,7 @@ orig = msg.get_payload() encdata = quopri.encodestring(orig) msg.set_payload(encdata) + del msg['Content-Transfer-Encoding'] msg['Content-Transfer-Encoding'] = 'quoted-printable' class Mailer: @@ -70,8 +71,8 @@ message = MIMEMultipart() else: message = Message() + message.set_type('text/plain') message.set_charset(charset) - message['Content-Type'] = 'text/plain; charset="%s"'%charset try: message['Subject'] = subject.encode('ascii') From buildbot at python.org Mon Mar 16 01:21:22 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 16 Mar 2009 00:21:22 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu trunk Message-ID: <20090316002122.325101E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%20trunk/builds/964 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl,hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Mon Mar 16 01:30:20 2009 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 16 Mar 2009 01:30:20 +0100 (CET) Subject: [Python-checkins] r70412 - in tracker/roundup-src/roundup: cgi/client.py mailer.py Message-ID: <20090316003020.AC4D01E401D@bag.python.org> Author: martin.v.loewis Date: Mon Mar 16 01:30:20 2009 New Revision: 70412 Log: Set encoding to quoted-printable on messages. Modified: tracker/roundup-src/roundup/cgi/client.py tracker/roundup-src/roundup/mailer.py Modified: tracker/roundup-src/roundup/cgi/client.py ============================================================================== --- tracker/roundup-src/roundup/cgi/client.py (original) +++ tracker/roundup-src/roundup/cgi/client.py Mon Mar 16 01:30:20 2009 @@ -14,7 +14,7 @@ from roundup.exceptions import * from roundup.cgi.exceptions import * from roundup.cgi.form_parser import FormParser -from roundup.mailer import Mailer, MessageSendError +from roundup.mailer import Mailer, MessageSendError, encode_quopri from roundup.cgi import accept_language from roundup import xmlrpc @@ -1034,6 +1034,7 @@ del message['Content-type'] message['Content-type'] = 'text/html; charset=utf-8' message.set_payload(content) + encode_quopri(message) self.mailer.smtp_send(to, str(message)) # Now report the error to the user. return self._(self.error_message) Modified: tracker/roundup-src/roundup/mailer.py ============================================================================== --- tracker/roundup-src/roundup/mailer.py (original) +++ tracker/roundup-src/roundup/mailer.py Mon Mar 16 01:30:20 2009 @@ -116,6 +116,7 @@ """ message = self.get_standard_message(to, subject, author) message.set_payload(content) + encode_quopri(message) self.smtp_send(to, str(message)) def bounce_message(self, bounced_message, to, error, From python-checkins at python.org Mon Mar 16 02:34:49 2009 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 16 Mar 2009 02:34:49 +0100 (CET) Subject: [Python-checkins] r70413 - tracker/roundup-src/roundup/backends/rdbms_common.py Message-ID: <20090316013449.7E0011E4002@bag.python.org> Author: martin.v.loewis Date: Mon Mar 16 02:34:49 2009 New Revision: 70413 Log: Update arguments for search_matches filter. Modified: tracker/roundup-src/roundup/backends/rdbms_common.py Modified: tracker/roundup-src/roundup/backends/rdbms_common.py ============================================================================== --- tracker/roundup-src/roundup/backends/rdbms_common.py (original) +++ tracker/roundup-src/roundup/backends/rdbms_common.py Mon Mar 16 02:34:49 2009 @@ -2366,7 +2366,7 @@ if search_matches is not None: s = ','.join([a for x in search_matches]) where.append('_%s.id in (%s)'%(icn, s)) - args = args + v + args = args + search_matches.keys() # construct the SQL frum.append('_'+icn) From python-checkins at python.org Mon Mar 16 08:24:12 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 16 Mar 2009 08:24:12 +0100 (CET) Subject: [Python-checkins] r70414 - peps/trunk/pep-0378.txt Message-ID: <20090316072412.6D7641E4049@bag.python.org> Author: raymond.hettinger Date: Mon Mar 16 08:24:12 2009 New Revision: 70414 Log: Clarify that the PEP intent is not to serve as an internationalization tool or to accommodate every possible convention. It intends to provide a generally useful tool for improving readability in many contexts. Also, clarify the groupings are for the integer part of a number. Digits to the right of the decimal point are unchanged. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Mon Mar 16 08:24:12 2009 @@ -35,7 +35,8 @@ .. _`many other challenges`: http://docs.python.org/library/locale.html#background-details-hints-tips-and-caveats -It is not the goal to replace the locale module or to +It is not the goal to replace the locale module, to perform +internationalization takes, or accommodate every possible convention. Such tasks are better suited to robust tools like `Babel`_ . Instead, our goal is to make a common, everyday task easier for many users. @@ -59,12 +60,6 @@ Scanning the web, I've found that thousands separators are usually one of COMMA, DOT, SPACE, APOSTROPHE or UNDERSCORE. -James Knight observed that Indian/Pakistani numbering systems -group by hundreds. Ben Finney noted that Chinese group by -ten-thousands. Eric Smith pointed-out that these are already -handled by the "n" specifier in the locale module (albeit only -for integers). - Visual Basic and its brethren (like `MS Excel`_) use a completely different style and have ultra-flexible custom format specifiers like:: @@ -157,8 +152,11 @@ format(1234, "8,d") --> ' 1,234' format(1234, "8_d") --> ' 1_234' -This proposal meets mosts needs , but it comes at the expense -of being a little more complicated to learn and remember. +This proposal meets mosts needs, but it comes at the expense +of taking a bit more effort to parse. Not every possible +convention is covered, but at least one of the options (spaces +or underscores) should be readable, understandable, and useful +to folks from many diverse backgrounds. As shown in the examples, the *width* argument means the total length including the thousands separators and decimal separators. @@ -220,6 +218,21 @@ is to set the convention once and have it apply everywhere (others commented that locale already provides a way to do this). +* There are some precedents for grouping digits in the fractional + part of a floating point number, but this PEP does not venture into + that territory. Only digits to the left of the decimal point are + grouped. This does not preclude future extensions; it just focuses + on a single, generally useful extension to the formatting language. + +* James Knight observed that Indian/Pakistani numbering systems + group by hundreds. Ben Finney noted that Chinese group by + ten-thousands. Eric Smith pointed-out that these are already + handled by the "n" specifier in the locale module (albeit only + for integers). This PEP does not attempt to support all of those + possibilities. It focuees on a single, relatively common grouping + convention that offers a quick way to improve readability in many + (though not all) contexts. + Copyright ========= From python-checkins at python.org Mon Mar 16 08:24:50 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 16 Mar 2009 08:24:50 +0100 (CET) Subject: [Python-checkins] r70415 - peps/trunk/pep-0378.txt Message-ID: <20090316072450.EE1FD1E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 16 08:24:50 2009 New Revision: 70415 Log: Complete the last checkin. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Mon Mar 16 08:24:50 2009 @@ -36,10 +36,10 @@ .. _`many other challenges`: http://docs.python.org/library/locale.html#background-details-hints-tips-and-caveats It is not the goal to replace the locale module, to perform -internationalization takes, or -accommodate every possible convention. Such tasks are better -suited to robust tools like `Babel`_ . Instead, our goal is to -make a common, everyday task easier for many users. +internationalization tasks, or accommodate every possible +convention. Such tasks are better suited to robust tools like +`Babel`_ . Instead, the goal is to make a common, everyday +task easier for many users. .. _`Babel`: http://babel.edgewall.org/ From python-checkins at python.org Mon Mar 16 20:14:15 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 16 Mar 2009 20:14:15 +0100 (CET) Subject: [Python-checkins] r70416 - peps/trunk/pep-0378.txt Message-ID: <20090316191415.34D9D1E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 16 20:14:15 2009 New Revision: 70416 Log: * Make a permalink to docs that won't change as new docs get issued. * Note that the proposal only applies to non-exponential based ten presentations. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Mon Mar 16 20:14:15 2009 @@ -49,7 +49,7 @@ * `Python 2.6 docs`_ - .. _Python 2.6 docs: http://docs.python.org/library/string.html#formatstrings + .. _Python 2.6 docs: http://www.python.org/doc/2.6.1/library/string.html#formatstrings * PEP 3101 Advanced String Formatting @@ -126,6 +126,10 @@ format(1234, "08,d") --> '0001,234' format(1234.5, "08,.1f") --> '01,234.5' +The ',' option is defined as shown above for types 'd', 'f', +and 'F'. It is undefined for other types (binary, octal, hex, +character, exponential, general, percentage, etc.) + Proposal II (from Eric Smith) ============================= @@ -163,6 +167,10 @@ No change is proposed for the locale module. +The thousands separator is defined as shown above for types +'d', 'f', and 'F'. It is undefined for other types (binary, +octal, hex, character, exponential, general, percentage, etc.) + Comparison ========== From python-checkins at python.org Mon Mar 16 20:32:36 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 16 Mar 2009 20:32:36 +0100 (CET) Subject: [Python-checkins] r70417 - peps/trunk/pep-0378.txt Message-ID: <20090316193236.601D31E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 16 20:32:36 2009 New Revision: 70417 Log: Include the author's recommendation. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Mon Mar 16 20:32:36 2009 @@ -179,6 +179,7 @@ to a COMMA for a thousands separator and a DOT as a decimal separator. The second allows either separator to be one of several possibilities. +The PEP author recommends Proposal II. Other Ideas From python-checkins at python.org Mon Mar 16 20:42:04 2009 From: python-checkins at python.org (georg.brandl) Date: Mon, 16 Mar 2009 20:42:04 +0100 (CET) Subject: [Python-checkins] r70418 - python/trunk/Doc/library/string.rst Message-ID: <20090316194204.173AC1E4002@bag.python.org> Author: georg.brandl Date: Mon Mar 16 20:42:03 2009 New Revision: 70418 Log: Add token markup. Modified: python/trunk/Doc/library/string.rst Modified: python/trunk/Doc/library/string.rst ============================================================================== --- python/trunk/Doc/library/string.rst (original) +++ python/trunk/Doc/library/string.rst Mon Mar 16 20:42:03 2009 @@ -221,7 +221,7 @@ .. productionlist:: sf replacement_field: "{" `field_name` ["!" `conversion`] [":" `format_spec`] "}" - field_name: (`identifier` | `integer`) ("." `attribute_name` | "[" element_index "]")* + field_name: (`identifier` | `integer`) ("." `attribute_name` | "[" `element_index` "]")* attribute_name: `identifier` element_index: `integer` conversion: "r" | "s" From python-checkins at python.org Mon Mar 16 20:57:45 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 16 Mar 2009 20:57:45 +0100 (CET) Subject: [Python-checkins] r70419 - peps/trunk/pep-0378.txt Message-ID: <20090316195745.6D4281E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 16 20:57:45 2009 New Revision: 70419 Log: Typo. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Mon Mar 16 20:57:45 2009 @@ -238,7 +238,7 @@ ten-thousands. Eric Smith pointed-out that these are already handled by the "n" specifier in the locale module (albeit only for integers). This PEP does not attempt to support all of those - possibilities. It focuees on a single, relatively common grouping + possibilities. It focues on a single, relatively common grouping convention that offers a quick way to improve readability in many (though not all) contexts. From python-checkins at python.org Mon Mar 16 22:07:43 2009 From: python-checkins at python.org (georg.brandl) Date: Mon, 16 Mar 2009 22:07:43 +0100 (CET) Subject: [Python-checkins] r70420 - peps/trunk/pep-0379.txt Message-ID: <20090316210743.179821E4002@bag.python.org> Author: georg.brandl Date: Mon Mar 16 22:07:42 2009 New Revision: 70420 Log: Add new PEP 379 from Jervis Whitley. Added: peps/trunk/pep-0379.txt (contents, props changed) Added: peps/trunk/pep-0379.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-0379.txt Mon Mar 16 22:07:42 2009 @@ -0,0 +1,188 @@ +PEP: 379 +Title: Adding an Assignment Expression +Version: $Revision$ +Last-Modified: $Date$ +Author: Jervis Whitley +Status: Draft +Type: Standards Track +Content-Type: text/plain +Created: 14-Mar-2009 +Python-Version: 3.2 +Post-History: + + +Abstract + + This PEP adds a new assignment expression to the Python language + to make it possible to assign the result of an expression in + almost any place. The new expression will allow the assignment of + the result of an expression at first use (in a comparison for + example). + + +Motivation and Summary + + Issue1714448 "if something as x:" [1] describes a feature to allow + assignment of the result of an expression in an if statement to a + name. It supposed that the 'as' syntax could be borrowed for this + purpose. Many times it is not the expression itself that is + interesting, rather one of the terms that make up the + expression. To be clear, something like this: + + if (f_result() == [1, 2, 3]) as res: + + seems awfully limited, when this: + + if (f_result() as res) == [1, 2, 3] : + + is probably the desired result. + + +Use Cases + + See the Examples section near the end. + + +Specification + + A new expression is proposed with the (nominal) syntax: + + EXPR -> VAR + + This single expression does the following: + + - Evaluate the value of EXPR, an arbitrary expression; + - Assign the result to VAR, a single assignment target; and + - Leave the result of EXPR on the Top of Stack (TOS) + + Here '->' or (RARROW) has been used to illustrate the concept that + the result of EXPR is assigned to VAR. + + The translation of the proposed syntax is: + + VAR = (EXPR) + (EXPR) + + The assignment target can be either an attribute, a subscript or + name: + + f() -> name[0] # where 'name' exists previously. + + f() -> name.attr # again 'name' exists prior to this + expression. + + f() -> name + + This expression should be available anywhere that an expression is + currently accepted. + + All exceptions that are currently raised during invalid + assignments will continue to be raised when using the assignment + expression. For example, a NameError will be raised when in + example 1 and 2 above if 'name' is not previously defined, or an + IndexError if index 0 was out of range. + + +Examples from the Standard Library + + The following two examples were chosen after a brief search + through the standard library, specifically both are from ast.py + which happened to be open at the time of the search. + + Original: + + def walk(node): + from collections import deque + todo = deque([node]) + while todo: + node = todo.popleft() + todo.extend(iter_child_nodes(node)) + yield node + + Using assignment expression: + + def walk(node): + from collections import deque + todo = deque([node]) + while todo: + todo.extend(iter_child_nodes(todo.popleft() -> node)) + yield node + + Original: + + def get_docstring(node, clean=True): + if not isinstance(node, (FunctionDef, ClassDef, Module)): + raise TypeError("%r can't have docstrings" + % node.__class__.__name__) + if node.body and isinstance(node.body[0], Expr) and \ + isinstance(node.body[0].value, Str): + if clean: + import inspect + return inspect.cleandoc(node.body[0].value.s) + return node.body[0].value.s + + Using assignment expresion: + + def get_docstring(node, clean=True): + if not isinstance(node, (FunctionDef, ClassDef, Module)): + raise TypeError("%r can't have docstrings" + % node.__class__.__name__) + if node.body -> body and isinstance(body[0] -> elem, Expr) and \ + isinstance(elem.value -> value, Str): + if clean: + import inspect + return inspect.cleandoc(value.s) + return value.s + + +Examples + + The examples shown below highlight some of the desirable features + of the assignment expression, and some of the possible corner + cases. + + 1. Assignment in an if statement for use later. + + def expensive(): + import time; time.sleep(1) + return 'spam' + + if expensive() -> res in ('spam', 'eggs'): + dosomething(res) + + 2. Assignment in a while loop clause. + + while len(expensive() -> res) == 4: + dosomething(res) + + 3. Keep the iterator object from the for loop. + + for ch in expensive() -> res: + sell_on_internet(res) + + 4. Corner case. + + for ch -> please_dont in expensive(): + pass + # who would want to do this? Not I. + + +References + + [1] Issue1714448 "if something as x:", k0wax + http://bugs.python.org/issue1714448 + + +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 Mon Mar 16 22:09:05 2009 From: python-checkins at python.org (georg.brandl) Date: Mon, 16 Mar 2009 22:09:05 +0100 (CET) Subject: [Python-checkins] r70421 - peps/trunk/pep-0379.txt Message-ID: <20090316210905.681E21E4002@bag.python.org> Author: georg.brandl Date: Mon Mar 16 22:09:05 2009 New Revision: 70421 Log: Add 2.7 to target versions. Modified: peps/trunk/pep-0379.txt Modified: peps/trunk/pep-0379.txt ============================================================================== --- peps/trunk/pep-0379.txt (original) +++ peps/trunk/pep-0379.txt Mon Mar 16 22:09:05 2009 @@ -7,7 +7,7 @@ Type: Standards Track Content-Type: text/plain Created: 14-Mar-2009 -Python-Version: 3.2 +Python-Version: 2.7, 3.2 Post-History: From python-checkins at python.org Mon Mar 16 22:32:59 2009 From: python-checkins at python.org (georg.brandl) Date: Mon, 16 Mar 2009 22:32:59 +0100 (CET) Subject: [Python-checkins] r70422 - peps/trunk/pep-0379.txt Message-ID: <20090316213259.19F121E4002@bag.python.org> Author: georg.brandl Date: Mon Mar 16 22:32:58 2009 New Revision: 70422 Log: PEP8 nit. Modified: peps/trunk/pep-0379.txt Modified: peps/trunk/pep-0379.txt ============================================================================== --- peps/trunk/pep-0379.txt (original) +++ peps/trunk/pep-0379.txt Mon Mar 16 22:32:58 2009 @@ -33,7 +33,7 @@ seems awfully limited, when this: - if (f_result() as res) == [1, 2, 3] : + if (f_result() as res) == [1, 2, 3]: is probably the desired result. From python-checkins at python.org Mon Mar 16 23:16:12 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 16 Mar 2009 23:16:12 +0100 (CET) Subject: [Python-checkins] r70423 - peps/trunk/pep-0378.txt Message-ID: <20090316221612.06E521E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 16 23:16:11 2009 New Revision: 70423 Log: Rearranged and updated to reflect Guido's comments. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Mon Mar 16 23:16:11 2009 @@ -33,7 +33,7 @@ for the locale module describe these and `many other challenges`_ in detail. -.. _`many other challenges`: http://docs.python.org/library/locale.html#background-details-hints-tips-and-caveats +.. _`many other challenges`: http://www.python.org/doc/2.6.1/library/locale.html#background-details-hints-tips-and-caveats It is not the goal to replace the locale module, to perform internationalization tasks, or accommodate every possible @@ -44,6 +44,47 @@ .. _`Babel`: http://babel.edgewall.org/ +Main Proposal (from Eric Smith) +=============================== + +Make both the thousands separator and decimal separator user +specifiable but not locale aware. For simplicity, limit the +choices to a COMMA, DOT, SPACE, APOSTROPHE or UNDERSCORE. +The SPACE can be either U+0020 or U+00A0. + +Whenever a separator is followed by a precision, it is a +decimal separator and an optional separator preceding it is a +thousands separator. When the precision is absent, a lone +specifier means a thousands separator:: + +[[fill]align][sign][#][0][width][tsep][dsep precision]][type] + +Examples:: + + format(1234, "8.1f") --> ' 1234.0' + format(1234, "8,1f") --> ' 1234,0' + format(1234, "8.,1f") --> ' 1.234,0' + format(1234, "8 ,f") --> ' 1 234,0' + format(1234, "8d") --> ' 1234' + format(1234, "8,d") --> ' 1,234' + format(1234, "8_d") --> ' 1_234' + +This proposal meets mosts needs, but it comes at the expense +of taking a bit more effort to parse. Not every possible +convention is covered, but at least one of the options (spaces +or underscores) should be readable, understandable, and useful +to folks from many diverse backgrounds. + +As shown in the examples, the *width* argument means the total +length including the thousands separators and decimal separators. + +No change is proposed for the locale module. + +The thousands separator is defined as shown above for types +'d', 'e', 'f', 'g', 'E', 'G'and 'F'. To allow future extensions, it is +undefined for other types: binary, octal, hex, character, etc. + + Current Version of the Mini-Language ==================================== @@ -54,25 +95,20 @@ * PEP 3101 Advanced String Formatting -Research so far -=============== +Research into what Other Languages Do +===================================== Scanning the web, I've found that thousands separators are usually one of COMMA, DOT, SPACE, APOSTROPHE or UNDERSCORE. -Visual Basic and its brethren (like `MS Excel`_) use a completely -different style and have ultra-flexible custom format -specifiers like:: - - "_($* #,##0_)". - -.. _`MS Excel`: http://www.brainbell.com/tutorials/ms-office/excel/Create_Custom_Number_Formats.htm - -`COBOL`_ uses picture clauses like:: +`C-Sharp`_ provides both styles (picture formatting and type specifiers). +The type specifier approach is locale aware. The picture formatting only +offers a COMMA as a thousands separator:: - PICTURE $***,**9.99CR + String.Format("{0:n}", 12400) ==> "12,400" + String.Format("{0:0,0}", 12400) ==> "12,400" -.. _`COBOL`: http://en.wikipedia.org/wiki/Cobol#Syntactic_features +.. _`C-Sharp`: http://blog.stevex.net/index.php/string-formatting-in-csharp/ `Common Lisp`_ uses a COLON before the ``~D`` decimal type specifier to emit a COMMA as a thousands separator. The general form of ``~D`` is @@ -86,18 +122,28 @@ .. _`Common Lisp`: http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node200.html -`C-Sharp`_ provides both styles (picture formatting and type specifiers). -The type specifier approach is locale aware. The picture formatting only -offers a COMMA as a thousands separator:: - String.Format("{0:n}", 12400) ==> "12,400" - String.Format("{0:0,0}", 12400) ==> "12,400" +* The `ADA language`_ allows UNDERSCORES in its numeric literals. -.. _`C-Sharp`: http://blog.stevex.net/index.php/string-formatting-in-csharp/ +.. _`ADA language`: http://archive.adaic.com/standards/83lrm/html/lrm-02-04.html + +Visual Basic and its brethren (like `MS Excel`_) use a completely +different style and have ultra-flexible custom format +specifiers like:: + + "_($* #,##0_)". + +.. _`MS Excel`: http://www.brainbell.com/tutorials/ms-office/excel/Create_Custom_Number_Formats.htm + +`COBOL`_ uses picture clauses like:: + + PICTURE $***,**9.99CR + +.. _`COBOL`: http://en.wikipedia.org/wiki/Cobol#Syntactic_features -Proposal I (from Nick Coghlan) -============================== +Alternative Proposal (from Nick Coghlan) +======================================== A comma will be added to the format() specifier mini-language:: @@ -126,86 +172,14 @@ format(1234, "08,d") --> '0001,234' format(1234.5, "08,.1f") --> '01,234.5' -The ',' option is defined as shown above for types 'd', 'f', -and 'F'. It is undefined for other types (binary, octal, hex, -character, exponential, general, percentage, etc.) - - -Proposal II (from Eric Smith) -============================= - -Make both the thousands separator and decimal separator user -specifiable but not locale aware. For simplicity, limit the -choices to a COMMA, DOT, SPACE, APOSTROPHE or UNDERSCORE. -The SPACE can be either U+0020 or U+00A0. - -Whenever a separator is followed by a precision, it is a -decimal separator and an optional separator preceding it is a -thousands separator. When the precision is absent, a lone -specifier means a thousands separator:: - -[[fill]align][sign][#][0][width][tsep][dsep precision]][type] - -Examples:: - - format(1234, "8.1f") --> ' 1234.0' - format(1234, "8,1f") --> ' 1234,0' - format(1234, "8.,1f") --> ' 1.234,0' - format(1234, "8 ,f") --> ' 1 234,0' - format(1234, "8d") --> ' 1234' - format(1234, "8,d") --> ' 1,234' - format(1234, "8_d") --> ' 1_234' - -This proposal meets mosts needs, but it comes at the expense -of taking a bit more effort to parse. Not every possible -convention is covered, but at least one of the options (spaces -or underscores) should be readable, understandable, and useful -to folks from many diverse backgrounds. - -As shown in the examples, the *width* argument means the total -length including the thousands separators and decimal separators. - -No change is proposed for the locale module. - -The thousands separator is defined as shown above for types -'d', 'f', and 'F'. It is undefined for other types (binary, -octal, hex, character, exponential, general, percentage, etc.) - - -Comparison -========== - -The difference between the two proposals is that the first is hard-wired -to a COMMA for a thousands separator and a DOT as a decimal separator. -The second allows either separator to be one of several possibilities. - -The PEP author recommends Proposal II. - - -Other Ideas -=========== - -* Lie Ryan suggested a convenience function of the form:: - - create_format(self, type='i', base=16, seppos=4, sep=':', - charset='0123456789abcdef', maxwidth=32, - minwidth=32, pad='0') - -* Eric Smith would like the C version of the mini-language - parser to be exposed with hooks that would make it easier - to write custom *__format__* methods. That way, methods like - *Decimal.__format__* would not have to be written from scratch. - -* Antoine Pitrou noted that the provision for a SPACE separator - should also allow a non-breaking space (U+00A0). - -* A poster on the newgroup, Wolfgang Rohdewald, noted that a - convention in Switzerland is to use an APOSTROPHE as a - thousands separator, ``12`000.99``. - -* The `ADA language`_ allows UNDERSCORES in its numeric literals. - -.. _`ADA language`: http://archive.adaic.com/standards/83lrm/html/lrm-02-04.html +The ',' option is defined as shown above for types 'd', 'e', +'f', 'g', 'E', 'G'and 'F'. To allow future extensions, it is +undefined for other types: binary, octal, hex, character, +etc. + +This alternative proposal has the virtue of being simpler +than the main proposal but is much less flexible and meets +the needs of fewer users right out of the box. Commentary From python-checkins at python.org Mon Mar 16 23:30:11 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 16 Mar 2009 23:30:11 +0100 (CET) Subject: [Python-checkins] r70424 - python/branches/py3k/Doc/library/importlib.rst Message-ID: <20090316223011.58FEF1E4038@bag.python.org> Author: brett.cannon Date: Mon Mar 16 23:30:11 2009 New Revision: 70424 Log: Fix a doc typo. Modified: python/branches/py3k/Doc/library/importlib.rst Modified: python/branches/py3k/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k/Doc/library/importlib.rst (original) +++ python/branches/py3k/Doc/library/importlib.rst Mon Mar 16 23:30:11 2009 @@ -121,7 +121,7 @@ If the requested module is already exists in :data:`sys.modules`, that module should be used and reloaded. Otherwise a new module is to be created by the loader and inserted into - :data:`sys.modules`before any loading begins to prevent recursion from + :data:`sys.modules` before any loading begins to prevent recursion from the import. If the loader inserted into a module and the load fails it must be removed by the loader from :data:`sys.modules`; modules already in :data:`sys.modules` before the loader began execution should be left From python-checkins at python.org Tue Mar 17 00:03:40 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 17 Mar 2009 00:03:40 +0100 (CET) Subject: [Python-checkins] r70425 - peps/trunk/pep-0378.txt Message-ID: <20090316230340.F0EBC1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 17 00:03:40 2009 New Revision: 70425 Log: List the % type specifier as included in the PEP. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Tue Mar 17 00:03:40 2009 @@ -81,8 +81,9 @@ No change is proposed for the locale module. The thousands separator is defined as shown above for types -'d', 'e', 'f', 'g', 'E', 'G'and 'F'. To allow future extensions, it is -undefined for other types: binary, octal, hex, character, etc. +'d', 'e', 'f', 'g', '%', 'E', 'G' and 'F'. To allow future +extensions, it is undefined for other types: binary, octal, +hex, character, etc. Current Version of the Mini-Language @@ -173,7 +174,7 @@ format(1234.5, "08,.1f") --> '01,234.5' The ',' option is defined as shown above for types 'd', 'e', -'f', 'g', 'E', 'G'and 'F'. To allow future extensions, it is +'f', 'g', 'E', 'G', '%' and 'F'. To allow future extensions, it is undefined for other types: binary, octal, hex, character, etc. From python-checkins at python.org Tue Mar 17 01:06:05 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 17 Mar 2009 01:06:05 +0100 (CET) Subject: [Python-checkins] r70426 - peps/trunk/pep-0378.txt Message-ID: <20090317000605.BEF691E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 17 01:06:05 2009 New Revision: 70426 Log: Swap the main and alternative proposals. Also refer to each by their original names (Proposal I and Proposal II). Explain Guido's issue with Proposal II. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Tue Mar 17 01:06:05 2009 @@ -44,46 +44,45 @@ .. _`Babel`: http://babel.edgewall.org/ -Main Proposal (from Eric Smith) -=============================== +Main Proposal (from Nick Coghlan, originally called Proposal I) +=============================================================== -Make both the thousands separator and decimal separator user -specifiable but not locale aware. For simplicity, limit the -choices to a COMMA, DOT, SPACE, APOSTROPHE or UNDERSCORE. -The SPACE can be either U+0020 or U+00A0. +A comma will be added to the format() specifier mini-language:: -Whenever a separator is followed by a precision, it is a -decimal separator and an optional separator preceding it is a -thousands separator. When the precision is absent, a lone -specifier means a thousands separator:: +[[fill]align][sign][#][0][width][,][.precision][type] -[[fill]align][sign][#][0][width][tsep][dsep precision]][type] +The ',' option indicates that commas should be included in the +output as a thousands separator. As with locales which do not +use a period as the decimal point, locales which use a +different convention for digit separation will need to use the +locale module to obtain appropriate formatting. -Examples:: +The proposal works well with floats, ints, and decimals. +It also allows easy substitution for other separators. +For example:: - format(1234, "8.1f") --> ' 1234.0' - format(1234, "8,1f") --> ' 1234,0' - format(1234, "8.,1f") --> ' 1.234,0' - format(1234, "8 ,f") --> ' 1 234,0' - format(1234, "8d") --> ' 1234' - format(1234, "8,d") --> ' 1,234' - format(1234, "8_d") --> ' 1_234' + format(n, "6,d").replace(",", "_") -This proposal meets mosts needs, but it comes at the expense -of taking a bit more effort to parse. Not every possible -convention is covered, but at least one of the options (spaces -or underscores) should be readable, understandable, and useful -to folks from many diverse backgrounds. +This technique is completely general but it is awkward in the +one case where the commas and periods need to be swapped:: -As shown in the examples, the *width* argument means the total -length including the thousands separators and decimal separators. + format(n, "6,f").replace(",", "X").replace(".", ",").replace("X", ".") -No change is proposed for the locale module. +The *width* argument means the total length including the commas +and decimal point:: -The thousands separator is defined as shown above for types -'d', 'e', 'f', 'g', '%', 'E', 'G' and 'F'. To allow future -extensions, it is undefined for other types: binary, octal, -hex, character, etc. + format(1234, "08,d") --> '0001,234' + format(1234.5, "08,.1f") --> '01,234.5' + +The ',' option is defined as shown above for types 'd', 'e', +'f', 'g', 'E', 'G', '%' and 'F'. To allow future extensions, it is +undefined for other types: binary, octal, hex, character, +etc. + +This proposal has the virtue of being simpler than the alternative +proposal but is much less flexible and meets the needs of fewer +users right out of the box. It is expected that some other +solution will arise for specifying alternative separators. Current Version of the Mini-Language @@ -143,44 +142,51 @@ .. _`COBOL`: http://en.wikipedia.org/wiki/Cobol#Syntactic_features -Alternative Proposal (from Nick Coghlan) -======================================== +Alternative Proposal (from Eric Smith, originally called Proposal II) +===================================================================== -A comma will be added to the format() specifier mini-language:: - -[[fill]align][sign][#][0][width][,][.precision][type] +Make both the thousands separator and decimal separator user +specifiable but not locale aware. For simplicity, limit the +choices to a COMMA, DOT, SPACE, APOSTROPHE or UNDERSCORE. +The SPACE can be either U+0020 or U+00A0. -The ',' option indicates that commas should be included in the -output as a thousands separator. As with locales which do not -use a period as the decimal point, locales which use a -different convention for digit separation will need to use the -locale module to obtain appropriate formatting. +Whenever a separator is followed by a precision, it is a +decimal separator and an optional separator preceding it is a +thousands separator. When the precision is absent, a lone +specifier means a thousands separator:: -The proposal works well with floats, ints, and decimals. -It also allows easy substitution for other separators. -For example:: +[[fill]align][sign][#][0][width][tsep][dsep precision]][type] - format(n, "6,d").replace(",", "_") +Examples:: -This technique is completely general but it is awkward in the -one case where the commas and periods need to be swapped:: + format(1234, "8.1f") --> ' 1234.0' + format(1234, "8,1f") --> ' 1234,0' + format(1234, "8.,1f") --> ' 1.234,0' + format(1234, "8 ,f") --> ' 1 234,0' + format(1234, "8d") --> ' 1234' + format(1234, "8,d") --> ' 1,234' + format(1234, "8_d") --> ' 1_234' - format(n, "6,f").replace(",", "X").replace(".", ",").replace("X", ".") +This proposal meets mosts needs, but it comes at the expense +of taking a bit more effort to parse. Not every possible +convention is covered, but at least one of the options (spaces +or underscores) should be readable, understandable, and useful +to folks from many diverse backgrounds. -The *width* argument means the total length including the commas -and decimal point:: +As shown in the examples, the *width* argument means the total +length including the thousands separators and decimal separators. - format(1234, "08,d") --> '0001,234' - format(1234.5, "08,.1f") --> '01,234.5' +No change is proposed for the locale module. -The ',' option is defined as shown above for types 'd', 'e', -'f', 'g', 'E', 'G', '%' and 'F'. To allow future extensions, it is -undefined for other types: binary, octal, hex, character, -etc. +The thousands separator is defined as shown above for types +'d', 'e', 'f', 'g', '%', 'E', 'G' and 'F'. To allow future +extensions, it is undefined for other types: binary, octal, +hex, character, etc. -This alternative proposal has the virtue of being simpler -than the main proposal but is much less flexible and meets -the needs of fewer users right out of the box. +The drawback to this alternative proposal is the difficulty +of mentally parsing whether a single separator is a thousands +separator or decimal separator. Perhaps it is too arcane +to link the decimal separator with the precision specifier. Commentary From python-checkins at python.org Tue Mar 17 03:45:54 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 17 Mar 2009 03:45:54 +0100 (CET) Subject: [Python-checkins] r70427 - peps/trunk/pep-0378.txt Message-ID: <20090317024554.E3F491E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 17 03:45:54 2009 New Revision: 70427 Log: Unmatched brackets. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Tue Mar 17 03:45:54 2009 @@ -155,7 +155,7 @@ thousands separator. When the precision is absent, a lone specifier means a thousands separator:: -[[fill]align][sign][#][0][width][tsep][dsep precision]][type] +[[fill]align][sign][#][0][width][tsep][dsep precision][type] Examples:: From python-checkins at python.org Tue Mar 17 04:14:25 2009 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 17 Mar 2009 04:14:25 +0100 (CET) Subject: [Python-checkins] r70428 - peps/trunk/pep-0378.txt Message-ID: <20090317031425.B2DE61E4002@bag.python.org> Author: guido.van.rossum Date: Tue Mar 17 04:14:25 2009 New Revision: 70428 Log: Mark as Accepted (with Nick's simpler proposal). Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Tue Mar 17 04:14:25 2009 @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Raymond Hettinger -Status: Draft +Status: Accepted Type: Standards Track Content-Type: text/x-rst Created: 12-Mar-2009 From python-checkins at python.org Tue Mar 17 09:34:18 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 17 Mar 2009 09:34:18 +0100 (CET) Subject: [Python-checkins] r70429 - peps/trunk/pep-3101.txt Message-ID: <20090317083418.DB5DD1E4002@bag.python.org> Author: mark.dickinson Date: Tue Mar 17 09:34:18 2009 New Revision: 70429 Log: Fix typo. Modified: peps/trunk/pep-3101.txt Modified: peps/trunk/pep-3101.txt ============================================================================== --- peps/trunk/pep-3101.txt (original) +++ peps/trunk/pep-3101.txt Tue Mar 17 09:34:18 2009 @@ -276,7 +276,7 @@ positive numbers If the '#' character is present, integers use the 'alternate form' - for formatting. This means that binary, octal, and hexidecimal + for formatting. This means that binary, octal, and hexadecimal output will be prefixed with '0b', '0o', and '0x', respectively. 'width' is a decimal integer defining the minimum field width. If From python-checkins at python.org Tue Mar 17 19:01:03 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 17 Mar 2009 19:01:03 +0100 (CET) Subject: [Python-checkins] r70430 - in python/trunk: Lib/decimal.py Lib/test/test_decimal.py Misc/NEWS Message-ID: <20090317180103.562951E4002@bag.python.org> Author: mark.dickinson Date: Tue Mar 17 19:01:03 2009 New Revision: 70430 Log: Fix bug in Decimal __format__ method that swapped left and right alignment. Modified: python/trunk/Lib/decimal.py python/trunk/Lib/test/test_decimal.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/decimal.py ============================================================================== --- python/trunk/Lib/decimal.py (original) +++ python/trunk/Lib/decimal.py Tue Mar 17 19:01:03 2009 @@ -5551,9 +5551,9 @@ align = spec_dict['align'] if align == '<': - result = padding + sign + body - elif align == '>': result = sign + body + padding + elif align == '>': + result = padding + sign + body elif align == '=': result = sign + padding + body else: #align == '^' Modified: python/trunk/Lib/test/test_decimal.py ============================================================================== --- python/trunk/Lib/test/test_decimal.py (original) +++ python/trunk/Lib/test/test_decimal.py Tue Mar 17 19:01:03 2009 @@ -704,6 +704,12 @@ ('.0g', '-sNaN', '-sNaN'), ('', '1.00', '1.00'), + + # check alignment + ('<6', '123', '123 '), + ('>6', '123', ' 123'), + ('^6', '123', ' 123 '), + ('=+6', '123', '+ 123'), ] for fmt, d, result in test_values: self.assertEqual(format(Decimal(d), fmt), result) Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 17 19:01:03 2009 @@ -174,6 +174,9 @@ Library ------- +- Fix Decimal.__format__ bug that swapped the meanings of the '<' and + '>' alignment characters. + - Issue #1222: locale.format() bug when the thousands separator is a space character. From python-checkins at python.org Tue Mar 17 19:07:41 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 17 Mar 2009 19:07:41 +0100 (CET) Subject: [Python-checkins] r70431 - in python/branches/release26-maint: Lib/decimal.py Lib/test/test_decimal.py Misc/NEWS Message-ID: <20090317180741.CAD991E4002@bag.python.org> Author: mark.dickinson Date: Tue Mar 17 19:07:41 2009 New Revision: 70431 Log: Merged revisions 70430 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70430 | mark.dickinson | 2009-03-17 18:01:03 +0000 (Tue, 17 Mar 2009) | 3 lines Fix bug in Decimal __format__ method that swapped left and right alignment. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/decimal.py python/branches/release26-maint/Lib/test/test_decimal.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/decimal.py ============================================================================== --- python/branches/release26-maint/Lib/decimal.py (original) +++ python/branches/release26-maint/Lib/decimal.py Tue Mar 17 19:07:41 2009 @@ -5491,9 +5491,9 @@ align = spec_dict['align'] if align == '<': - result = padding + sign + body - elif align == '>': result = sign + body + padding + elif align == '>': + result = padding + sign + body elif align == '=': result = sign + padding + body else: #align == '^' Modified: python/branches/release26-maint/Lib/test/test_decimal.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_decimal.py (original) +++ python/branches/release26-maint/Lib/test/test_decimal.py Tue Mar 17 19:07:41 2009 @@ -704,6 +704,12 @@ ('.0g', '-sNaN', '-sNaN'), ('', '1.00', '1.00'), + + # check alignment + ('<6', '123', '123 '), + ('>6', '123', ' 123'), + ('^6', '123', ' 123 '), + ('=+6', '123', '+ 123'), ] for fmt, d, result in test_values: self.assertEqual(format(Decimal(d), fmt), result) Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Tue Mar 17 19:07:41 2009 @@ -89,6 +89,9 @@ Library ------- +- Fix Decimal.__format__ bug that swapped the meanings of the '<' and + '>' alignment characters. + - Issue #1222: locale.format() bug when the thousands separator is a space character. From python-checkins at python.org Tue Mar 17 19:10:15 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 17 Mar 2009 19:10:15 +0100 (CET) Subject: [Python-checkins] r70432 - in python/branches/py3k: Lib/decimal.py Lib/test/test_decimal.py Misc/NEWS Message-ID: <20090317181015.8298C1E4002@bag.python.org> Author: mark.dickinson Date: Tue Mar 17 19:10:15 2009 New Revision: 70432 Log: Merged revisions 70430 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70430 | mark.dickinson | 2009-03-17 18:01:03 +0000 (Tue, 17 Mar 2009) | 3 lines Fix bug in Decimal __format__ method that swapped left and right alignment. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/decimal.py python/branches/py3k/Lib/test/test_decimal.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/decimal.py ============================================================================== --- python/branches/py3k/Lib/decimal.py (original) +++ python/branches/py3k/Lib/decimal.py Tue Mar 17 19:10:15 2009 @@ -5630,9 +5630,9 @@ align = spec_dict['align'] if align == '<': - result = padding + sign + body - elif align == '>': result = sign + body + padding + elif align == '>': + result = padding + sign + body elif align == '=': result = sign + padding + body else: #align == '^' Modified: python/branches/py3k/Lib/test/test_decimal.py ============================================================================== --- python/branches/py3k/Lib/test/test_decimal.py (original) +++ python/branches/py3k/Lib/test/test_decimal.py Tue Mar 17 19:10:15 2009 @@ -693,6 +693,12 @@ ('.0g', '-sNaN', '-sNaN'), ('', '1.00', '1.00'), + + # check alignment + ('<6', '123', '123 '), + ('>6', '123', ' 123'), + ('^6', '123', ' 123 '), + ('=+6', '123', '+ 123'), ] for fmt, d, result in test_values: self.assertEqual(format(Decimal(d), fmt), result) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 17 19:10:15 2009 @@ -206,6 +206,9 @@ Library ------- +- Fix Decimal.__format__ bug that swapped the meanings of the '<' and + '>' alignment characters. + - Issue #1222: locale.format() bug when the thousands separator is a space character. From python-checkins at python.org Tue Mar 17 19:13:31 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 17 Mar 2009 19:13:31 +0100 (CET) Subject: [Python-checkins] r70433 - in python/branches/release30-maint: Lib/decimal.py Lib/test/test_decimal.py Misc/NEWS Message-ID: <20090317181331.2ACAB1E4002@bag.python.org> Author: mark.dickinson Date: Tue Mar 17 19:13:30 2009 New Revision: 70433 Log: Merged revisions 70432 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70432 | mark.dickinson | 2009-03-17 18:10:15 +0000 (Tue, 17 Mar 2009) | 10 lines Merged revisions 70430 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70430 | mark.dickinson | 2009-03-17 18:01:03 +0000 (Tue, 17 Mar 2009) | 3 lines Fix bug in Decimal __format__ method that swapped left and right alignment. ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/decimal.py python/branches/release30-maint/Lib/test/test_decimal.py python/branches/release30-maint/Misc/NEWS Modified: python/branches/release30-maint/Lib/decimal.py ============================================================================== --- python/branches/release30-maint/Lib/decimal.py (original) +++ python/branches/release30-maint/Lib/decimal.py Tue Mar 17 19:13:30 2009 @@ -5576,9 +5576,9 @@ align = spec_dict['align'] if align == '<': - result = padding + sign + body - elif align == '>': result = sign + body + padding + elif align == '>': + result = padding + sign + body elif align == '=': result = sign + padding + body else: #align == '^' Modified: python/branches/release30-maint/Lib/test/test_decimal.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_decimal.py (original) +++ python/branches/release30-maint/Lib/test/test_decimal.py Tue Mar 17 19:13:30 2009 @@ -694,6 +694,12 @@ ('.0g', '-sNaN', '-sNaN'), ('', '1.00', '1.00'), + + # check alignment + ('<6', '123', '123 '), + ('>6', '123', ' 123'), + ('^6', '123', ' 123 '), + ('=+6', '123', '+ 123'), ] for fmt, d, result in test_values: self.assertEqual(format(Decimal(d), fmt), result) Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Tue Mar 17 19:13:30 2009 @@ -24,6 +24,9 @@ Library ------- +- Fix Decimal.__format__ bug that swapped the meanings of the '<' and + '>' alignment characters. + - Issue #1222: locale.format() bug when the thousands separator is a space character. From python-checkins at python.org Tue Mar 17 19:15:08 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 17 Mar 2009 19:15:08 +0100 (CET) Subject: [Python-checkins] r70434 - python/branches/py3k/Misc/NEWS Message-ID: <20090317181508.EB2851E4002@bag.python.org> Author: mark.dickinson Date: Tue Mar 17 19:15:08 2009 New Revision: 70434 Log: Move Misc/NEWS item to the right place. Modified: python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 17 19:15:08 2009 @@ -21,6 +21,9 @@ Library ------- +- Fix Decimal.__format__ bug that swapped the meanings of the '<' and + '>' alignment characters. + - The error detection code in FileIO.close() could fail to reflect the `errno` value, and report it as -1 instead. @@ -206,9 +209,6 @@ Library ------- -- Fix Decimal.__format__ bug that swapped the meanings of the '<' and - '>' alignment characters. - - Issue #1222: locale.format() bug when the thousands separator is a space character. From python-checkins at python.org Tue Mar 17 19:16:12 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 17 Mar 2009 19:16:12 +0100 (CET) Subject: [Python-checkins] r70435 - python/branches/release30-maint Message-ID: <20090317181612.820621E4002@bag.python.org> Author: mark.dickinson Date: Tue Mar 17 19:16:12 2009 New Revision: 70435 Log: Blocked revisions 70434 via svnmerge ........ r70434 | mark.dickinson | 2009-03-17 18:15:08 +0000 (Tue, 17 Mar 2009) | 2 lines Move Misc/NEWS item to the right place. ........ Modified: python/branches/release30-maint/ (props changed) From python-checkins at python.org Tue Mar 17 20:38:35 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 17 Mar 2009 20:38:35 +0100 (CET) Subject: [Python-checkins] r70436 - peps/trunk/pep-0378.txt Message-ID: <20090317193835.3CECA1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 17 20:38:35 2009 New Revision: 70436 Log: Add notes on what Java does. Modified: peps/trunk/pep-0378.txt Modified: peps/trunk/pep-0378.txt ============================================================================== --- peps/trunk/pep-0378.txt (original) +++ peps/trunk/pep-0378.txt Tue Mar 17 20:38:35 2009 @@ -141,6 +141,16 @@ .. _`COBOL`: http://en.wikipedia.org/wiki/Cobol#Syntactic_features +Java offers a `Decimal.Format Class`_ that uses picture patterns (one +for positive numbers and an optional one for negatives) such as: +``"#,##0.00;(#,##0.00)"``. It allows arbitrary groupings including +hundreds and ten-thousands and uneven groupings. The special patten +characters are non-localized (using a DOT for a decimal separator and +a COMMA for a grouping separator). The user can supply an alternate +set of symbols using the formatter's *DecimalFormatSymbols* object. + +.. _`Decimal.Format Class`: http://java.sun.com/javase/6/docs/api/java/text/DecimalFormat.html + Alternative Proposal (from Eric Smith, originally called Proposal II) ===================================================================== From python-checkins at python.org Tue Mar 17 20:59:58 2009 From: python-checkins at python.org (brett.cannon) Date: Tue, 17 Mar 2009 20:59:58 +0100 (CET) Subject: [Python-checkins] r70437 - peps/trunk/pep-0379.txt Message-ID: <20090317195958.876D71E4002@bag.python.org> Author: brett.cannon Date: Tue Mar 17 20:59:58 2009 New Revision: 70437 Log: WIthdraw PEP 379 at the request of the author. Modified: peps/trunk/pep-0379.txt Modified: peps/trunk/pep-0379.txt ============================================================================== --- peps/trunk/pep-0379.txt (original) +++ peps/trunk/pep-0379.txt Tue Mar 17 20:59:58 2009 @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Jervis Whitley -Status: Draft +Status: Withdrawn Type: Standards Track Content-Type: text/plain Created: 14-Mar-2009 From buildbot at python.org Tue Mar 17 21:06:32 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 17 Mar 2009 20:06:32 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.0 Message-ID: <20090317200632.2C9041E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.0/builds/205 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/3.0.heller-x86-osx5/build/Lib/multiprocessing/managers.py", line 188, in handle_request result = func(c, *args, **kwds) File "/Users/buildbot/buildarea/3.0.heller-x86-osx5/build/Lib/multiprocessing/managers.py", line 306, in debug_info keys.sort() TypeError: unorderable types: str() < int() 1 test failed: test_multiprocessing make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 17 21:29:52 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 17 Mar 2009 21:29:52 +0100 (CET) Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst Message-ID: <20090317202952.2C3821E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 17 21:29:51 2009 New Revision: 70438 Log: I thought this was begging for an example Modified: python/trunk/Doc/library/functions.rst Modified: python/trunk/Doc/library/functions.rst ============================================================================== --- python/trunk/Doc/library/functions.rst (original) +++ python/trunk/Doc/library/functions.rst Tue Mar 17 21:29:51 2009 @@ -596,6 +596,25 @@ its :meth:`next` method; if the value returned is equal to *sentinel*, :exc:`StopIteration` will be raised, otherwise the value will be returned. + Example usage: :: + + >>> iterator = iter(range(10)) + >>> iterator + + >>> iterator.next() + 0 + >>> iterator.next() + 1 + >>> def my_generator(): + ... for i in range(10): + ... yield i + ... + >>> iterator = iter(my_generator().next, 7) + >>> iterator + + >>> list(iterator) + [0, 1, 2, 3, 4, 5, 6] + .. versionadded:: 2.2 From python at rcn.com Tue Mar 17 21:45:46 2009 From: python at rcn.com (Raymond Hettinger) Date: Tue, 17 Mar 2009 13:45:46 -0700 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org> Message-ID: <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> FWIW, I think the examples need to be *very* short. The functions.rst page is growing hard to read because of all of the lengthy examples, caveats, warnings, and saying verbosity. We don't want to turn the main docs into a tutorial. It makes them harder to use. If someone just wants to scan what the builtin functions do, they now face a very lengthy page of reading. It's getting too fat. I think the example below is way too long. Raymond ----- Original Message ----- From: "benjamin.peterson" To: Sent: Tuesday, March 17, 2009 1:29 PM Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst > Author: benjamin.peterson > Date: Tue Mar 17 21:29:51 2009 > New Revision: 70438 > > Log: > I thought this was begging for an example > > Modified: > python/trunk/Doc/library/functions.rst > > Modified: python/trunk/Doc/library/functions.rst > ============================================================================== > --- python/trunk/Doc/library/functions.rst (original) > +++ python/trunk/Doc/library/functions.rst Tue Mar 17 21:29:51 2009 > @@ -596,6 +596,25 @@ > its :meth:`next` method; if the value returned is equal to *sentinel*, > :exc:`StopIteration` will be raised, otherwise the value will be returned. > > + Example usage: :: > + > + >>> iterator = iter(range(10)) > + >>> iterator > + > + >>> iterator.next() > + 0 > + >>> iterator.next() > + 1 > + >>> def my_generator(): > + ... for i in range(10): > + ... yield i > + ... > + >>> iterator = iter(my_generator().next, 7) > + >>> iterator > + > + >>> list(iterator) > + [0, 1, 2, 3, 4, 5, 6] > + > .. versionadded:: 2.2 > > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins From benjamin at python.org Tue Mar 17 21:53:44 2009 From: benjamin at python.org (Benjamin Peterson) Date: Tue, 17 Mar 2009 15:53:44 -0500 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> Message-ID: <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> 2009/3/17 Raymond Hettinger : > FWIW, I think the examples need to be *very* short. > The functions.rst page is growing hard to read because > of all of the lengthy examples, caveats, warnings, and > saying verbosity. ?We don't want to turn the main docs > into a tutorial. ?It makes them harder to use. ? If someone > just wants to scan what the builtin functions do, they now > face a very lengthy page of reading. ?It's getting too fat. I think what really needs to happen is that function.rst and stdtypes.rst need to split up into multiple pages. I believe Georg had some intentions of doing that one day. It might make a good sprint project. > > I think the example below is way too long. Because it makes the page too long or because the code is too long? -- Regards, Benjamin From python at rcn.com Tue Mar 17 21:57:20 2009 From: python at rcn.com (Raymond Hettinger) Date: Tue, 17 Mar 2009 13:57:20 -0700 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> Message-ID: <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> > I think what really needs to happen is that function.rst and > stdtypes.rst need to split up into multiple pages. That may be, but the function page itself is already far too long. Please move your example to the tutorial. It is too long and adds too little value. I'm strongly opposed to adding more of this stuff to the functions page except in cases like super() which are very difficult to understand without an example. Raymond From ncoghlan at gmail.com Tue Mar 17 22:04:19 2009 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 18 Mar 2009 07:04:19 +1000 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> Message-ID: <49C01053.6070205@gmail.com> Raymond Hettinger wrote: > FWIW, I think the examples need to be *very* short. > The functions.rst page is growing hard to read because > of all of the lengthy examples, caveats, warnings, and > saying verbosity. We don't want to turn the main docs > into a tutorial. It makes them harder to use. If someone > just wants to scan what the builtin functions do, they now > face a very lengthy page of reading. It's getting too fat. > > I think the example below is way too long. Perhaps the page just needs an overview section or table at the start that just gives a one line description of each method, and then links to the more detailed descriptions with longer examples? Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- From python at rcn.com Tue Mar 17 22:11:25 2009 From: python at rcn.com (Raymond Hettinger) Date: Tue, 17 Mar 2009 14:11:25 -0700 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <49C01053.6070205@gmail.com> Message-ID: <7F54AAA1F4EA41C8B46974B920539CA2@RaymondLaptop1> ----- Original Message ----- From: "Nick Coghlan" To: "Raymond Hettinger" Cc: "benjamin.peterson" Sent: Tuesday, March 17, 2009 2:04 PM Subject: Re: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst > Raymond Hettinger wrote: >> FWIW, I think the examples need to be *very* short. >> The functions.rst page is growing hard to read because >> of all of the lengthy examples, caveats, warnings, and >> saying verbosity. We don't want to turn the main docs >> into a tutorial. It makes them harder to use. If someone >> just wants to scan what the builtin functions do, they now >> face a very lengthy page of reading. It's getting too fat. >> >> I think the example below is way too long. > > Perhaps the page just needs an overview section or table at the start > that just gives a one line description of each method, and then links to > the more detailed descriptions with longer examples? I did that with itertools but don't think it's a good general technique throughout the docs. The goal here is to make sure that we don't go down the slippery slope of merging the tutorial with the main docs. This particular example has a very low information density and it the kind of thing that goes on a docs wiki. It is also not a movitating example. Contrast that with docs for _ABCs which use a table, a short block of explanatory text and a single, succinct highly motivating example that shows how to effectively use all of the ABCs. Raymond From martin at v.loewis.de Tue Mar 17 22:12:00 2009 From: martin at v.loewis.de (=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=) Date: Tue, 17 Mar 2009 22:12:00 +0100 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> Message-ID: <49C01220.4010408@v.loewis.de> >> I think what really needs to happen is that function.rst and >> stdtypes.rst need to split up into multiple pages. > > That may be, but the function page itself is already far too > long. Please move your example to the tutorial. It is too long > and adds too little value. I'm strongly opposed to adding more > of this stuff to the functions page except in cases like super() > which are very difficult to understand without an example. I'm strongly opposed to cluttering the tutorial with examples for each and every language detail. Examples do belong into the library reference. Please leave the example where it is. Regards, Martin From python at rcn.com Tue Mar 17 22:14:53 2009 From: python at rcn.com (Raymond Hettinger) Date: Tue, 17 Mar 2009 14:14:53 -0700 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <1afaf6160903171402k69555ec0m6f02e62e0294cd70@mail.gmail.com> Message-ID: > I don't consider the two argument usage of iter() a tutorial topic. I'll rewrite the example so that it's length is proportionate to its information content. We really do need to show some editorial restraint. It's easy to damage the usability of the docs with clutter, not matter how well intentioned. On a separate topic, we also need to make an effort to look at all of the big/loud caveat/warning blocks to make sure they are really necessary. No other language docs advertise themselves as being full of minefields. Look at the main Java docs for comparison. They are shot and sweet and say what a function does, period. Raymond From benjamin at python.org Tue Mar 17 22:21:39 2009 From: benjamin at python.org (Benjamin Peterson) Date: Tue, 17 Mar 2009 16:21:39 -0500 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <1afaf6160903171402k69555ec0m6f02e62e0294cd70@mail.gmail.com> Message-ID: <1afaf6160903171421k7822e50ah5aab11aac1072a4d@mail.gmail.com> 2009/3/17 Raymond Hettinger schrieb: > Look at the main Java > docs for comparison. ?They are shot and sweet and say what > a function does, period. Telling precisely what a function does is important, but to take a cliche, "a code example tells a thousand words." Functions aren't used alone in programs; they're in context. Examples provide higher level guidance about how a function is usually used. -- Regards, Benjamin From python at rcn.com Tue Mar 17 22:21:38 2009 From: python at rcn.com (Raymond Hettinger) Date: Tue, 17 Mar 2009 14:21:38 -0700 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <49C01220.4010408@v.loewis.de> Message-ID: <992AED9B2B5B415185282009E7D2B8F2@RaymondLaptop1> [Martin v. L?wis] Examples do belong into the library > reference. Please leave the example where it is. Any objections to my making the example shorter? The functions.rst page is now approx 1600 lines long. Don't you think that is a little long for only a handful of functions. It is no longer easily possible to read in one sitting what all of the builtin functions do. Raymond From martin at v.loewis.de Tue Mar 17 22:26:06 2009 From: martin at v.loewis.de (=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=) Date: Tue, 17 Mar 2009 22:26:06 +0100 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <1afaf6160903171402k69555ec0m6f02e62e0294cd70@mail.gmail.com> Message-ID: <49C0156E.1010309@v.loewis.de> > On a separate topic, we also need to make an effort to look > at all of the big/loud caveat/warning blocks to make sure they > are really necessary. No other language docs advertise themselves as > being full of minefields. Look at the main Java > docs for comparison. They are shot and sweet and say what > a function does, period. I hear frequent complaints that this style of documentation is unusable to casual users. They don't want a specification of an API; they want to know how to use it. And they don't want to filter that out of the tutorial, but they want to see how to use it when they read the API. So examples *must* go along with the specification. If you would have to perform some navigation action to find them - that should be ok. But you must not need to search for examples. Notice that examples are not necessarily tutorials. Tutorials are designed to teach the reader some skill, by sequentially confronting him with new facts. OTOH, examples in API documentation often serve as specification-by-example, i.e. allow the user to skip the plain-english specification, and build a mental model for the API just by reading the example. Regards, Martin From benjamin at python.org Tue Mar 17 22:02:14 2009 From: benjamin at python.org (Benjamin Peterson) Date: Tue, 17 Mar 2009 16:02:14 -0500 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> Message-ID: <1afaf6160903171402k69555ec0m6f02e62e0294cd70@mail.gmail.com> 2009/3/17 Raymond Hettinger schrieb: >> I think what really needs to happen is that function.rst and >> stdtypes.rst need to split up into multiple pages. > > That may be, but the function page itself is already far too > long. ?Please move your example to the tutorial. ?It is too long > and adds too little value. ?I'm strongly opposed to adding more > of this stuff to the functions page except in cases like super() > which are very difficult to understand without an example. I don't consider the two argument usage of iter() a tutorial topic. How about removing the first part of the example with simple iter() usage? -- Regards, Benjamin From python at rcn.com Tue Mar 17 22:29:08 2009 From: python at rcn.com (Raymond Hettinger) Date: Tue, 17 Mar 2009 14:29:08 -0700 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <1afaf6160903171402k69555ec0m6f02e62e0294cd70@mail.gmail.com> <1afaf6160903171421k7822e50ah5aab11aac1072a4d@mail.gmail.com> Message-ID: [Benjamin Peterson] > Telling precisely what a function does is important, but to take a > cliche, "a code example tells a thousand words." Functions aren't used > alone in programs; they're in context. Examples provide higher level > guidance about how a function is usually used. Just show some judgment and restraint. Using the above philosophy, we could easily double or treble the size of the docs and in the process hurt their usability. Also, make some effort to find the smallest possible code fragment that communicates what the function does. Raymond From martin at v.loewis.de Tue Mar 17 22:31:29 2009 From: martin at v.loewis.de (=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=) Date: Tue, 17 Mar 2009 22:31:29 +0100 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: <992AED9B2B5B415185282009E7D2B8F2@RaymondLaptop1> References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <49C01220.4010408@v.loewis.de> <992AED9B2B5B415185282009E7D2B8F2@RaymondLaptop1> Message-ID: <49C016B1.40209@v.loewis.de> > Examples do belong into the library >> reference. Please leave the example where it is. > > Any objections to my making the example shorter? > > The functions.rst page is now approx 1600 lines long. > Don't you think that is a little long for only a handful > of functions. It is no longer easily possible to read > in one sitting what all of the builtin functions do. I think that should be possible - for example, you don't need to show the names of the types (the reader scan try out themselves), or invoke next twice (in case it might be unclear what the return value is, start the range with 17). However, I'd rather prefer to see some general solution for moving examples out of the reader's flow if he doesn't want them (e.g. by having two versions of the page, or using JS trickery). Regards, Martin From python at rcn.com Tue Mar 17 22:39:15 2009 From: python at rcn.com (Raymond Hettinger) Date: Tue, 17 Mar 2009 14:39:15 -0700 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <1afaf6160903171402k69555ec0m6f02e62e0294cd70@mail.gmail.com> <49C0156E.1010309@v.loewis.de> Message-ID: [MvL] > I hear frequent complaints that this style of documentation is unusable > to casual users. They don't want a specification of an API; they want to > know how to use it. And they don't want to filter that out of the > tutorial, but they want to see how to use it when they read the API. > So examples *must* go along with the specification. Of course, we're in complete agreement. I've included that much in almost all the docs I've written (all of collections.rst, the examples in the Queue module, the thorough docs with examples in itertools). There is however a matter of economy of expression and not having lengthy examples with low information content. At some point, verbosity defeats its own goal of being communicative. Fred Drake used to put a good did of editorial review into the docs but that seems to have gone out the window. Cut and pasting console sessions like the one we're talking about has a breezy, wiki-like feel that doesn't show that someone made an effort to focus their thoughts and produce a minimal, motivating example. For the second argument for iter(), there are good, succinct motivating examples such as converting file reads (which terminate with an empty string) into iterators. The example currently listed is just a toy that makes the optional argument look silly. If there are going to be examples, they should be good ones. Raymond From martin at v.loewis.de Tue Mar 17 22:41:55 2009 From: martin at v.loewis.de (=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=) Date: Tue, 17 Mar 2009 22:41:55 +0100 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <1afaf6160903171402k69555ec0m6f02e62e0294cd70@mail.gmail.com> <49C0156E.1010309@v.loewis.de> Message-ID: <49C01923.8010906@v.loewis.de> > If there are going to be examples, they should be good ones. Can't object to that :-) Martin From benjamin at python.org Tue Mar 17 22:43:02 2009 From: benjamin at python.org (Benjamin Peterson) Date: Tue, 17 Mar 2009 16:43:02 -0500 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: <49C01923.8010906@v.loewis.de> References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <1afaf6160903171402k69555ec0m6f02e62e0294cd70@mail.gmail.com> <49C0156E.1010309@v.loewis.de> <49C01923.8010906@v.loewis.de> Message-ID: <1afaf6160903171443i38143754t41d8b05240843081@mail.gmail.com> 2009/3/17 "Martin v. L?wis" : >> If there are going to be examples, they should be good ones. > > Can't object to that :-) +1 :) -- Regards, Benjamin From python at rcn.com Tue Mar 17 22:43:11 2009 From: python at rcn.com (Raymond Hettinger) Date: Tue, 17 Mar 2009 14:43:11 -0700 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <49C01220.4010408@v.loewis.de> <992AED9B2B5B415185282009E7D2B8F2@RaymondLaptop1> <49C016B1.40209@v.loewis.de> Message-ID: <25FC15A3334A4B98AE4CB76611FBE596@RaymondLaptop1> [MvL] > However, I'd rather prefer to see some general solution for > moving examples out of the reader's flow if he doesn't want > them (e.g. by having two versions of the page, or using > JS trickery). That seems like a good idea for HTML docs but we should probably have a larger discussion on whether the docs need to retain their usability in printed form. The docs probably need to be staticly usable and not just accessible through a browser or PDF viewer. I could see having links to a docs wiki. That way, people can load-up examples, comments, links to real-world code and whatnot while leading the main docs uncluttered. Raymond From benjamin at python.org Tue Mar 17 22:50:06 2009 From: benjamin at python.org (Benjamin Peterson) Date: Tue, 17 Mar 2009 16:50:06 -0500 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: <25FC15A3334A4B98AE4CB76611FBE596@RaymondLaptop1> References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <49C01220.4010408@v.loewis.de> <992AED9B2B5B415185282009E7D2B8F2@RaymondLaptop1> <49C016B1.40209@v.loewis.de> <25FC15A3334A4B98AE4CB76611FBE596@RaymondLaptop1> Message-ID: <1afaf6160903171450k6f95c4b0g47f56b0ac1ddf929@mail.gmail.com> 2009/3/17 Raymond Hettinger schrieb: > > I could see having links to a docs wiki. ?That way, people > can load-up examples, comments, links to real-world > code and whatnot ?while leading the main docs uncluttered. I think one of Georg's goals is to implement a comment system for Sphinx. That would let users post examples and suggest improvements. However, I don't think that negates the need for examples in the official docs because digging through user comments can take a while to find gems. -- Regards, Benjamin From amk at amk.ca Tue Mar 17 23:05:45 2009 From: amk at amk.ca (A.M. Kuchling) Date: Tue, 17 Mar 2009 18:05:45 -0400 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: <25FC15A3334A4B98AE4CB76611FBE596@RaymondLaptop1> References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <49C01220.4010408@v.loewis.de> <992AED9B2B5B415185282009E7D2B8F2@RaymondLaptop1> <49C016B1.40209@v.loewis.de> <25FC15A3334A4B98AE4CB76611FBE596@RaymondLaptop1> Message-ID: <20090317220545.GA17150@amk-desktop.matrixgroup.net> On Tue, Mar 17, 2009 at 02:43:11PM -0700, Raymond Hettinger wrote: > That seems like a good idea for HTML docs but we should probably have a > larger discussion on whether the docs > need to retain their usability in printed form. The docs > probably need to be staticly usable and not just accessible > through a browser or PDF viewer. IMHO: printing the documentation no longer matters. I cannot remember the last time I printed the documentation for an application or program; I either buy a tutorial book, which is never just a reprinting of the docs, or I look it up online. I own reference books for things like MySQL, but they gather dust; a bookmark for 'MySQL 5.0 docs' is so much easier than flipping around in abook. Most developers work on network-connected machines. Even if they're not network-connected, machines have large enough hard-drives so that everyone can keep the formatted HTML docs around. --amk From martin at v.loewis.de Tue Mar 17 23:07:29 2009 From: martin at v.loewis.de (=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=) Date: Tue, 17 Mar 2009 23:07:29 +0100 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: <25FC15A3334A4B98AE4CB76611FBE596@RaymondLaptop1> References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <49C01220.4010408@v.loewis.de> <992AED9B2B5B415185282009E7D2B8F2@RaymondLaptop1> <49C016B1.40209@v.loewis.de> <25FC15A3334A4B98AE4CB76611FBE596@RaymondLaptop1> Message-ID: <49C01F21.4030609@v.loewis.de> > That seems like a good idea for HTML docs but we should probably have a > larger discussion on whether the docs > need to retain their usability in printed form. The docs > probably need to be staticly usable and not just accessible > through a browser or PDF viewer. Right, we should discuss that. I feel that "clutter" is less problematic in a printed form. If you can find the subheadings quickly, you can easily skim (thumb?) through the pages until you find what you need - more easily than scrolling on a HTML page. > I could see having links to a docs wiki. That way, people > can load-up examples, comments, links to real-world > code and whatnot while leading the main docs uncluttered. People often refer to the PHP documentation as a successful example for integrating examples - often user-provided ones. If somebody could provide online-editing for the documentation - that would be also useful (in particular if that could transfer to the next release of the documentation). Regards, Martin From amk at amk.ca Tue Mar 17 23:13:08 2009 From: amk at amk.ca (A.M. Kuchling) Date: Tue, 17 Mar 2009 18:13:08 -0400 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: <992AED9B2B5B415185282009E7D2B8F2@RaymondLaptop1> References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <49C01220.4010408@v.loewis.de> <992AED9B2B5B415185282009E7D2B8F2@RaymondLaptop1> Message-ID: <20090317221308.GB17150@amk-desktop.matrixgroup.net> On Tue, Mar 17, 2009 at 02:21:38PM -0700, Raymond Hettinger wrote: > The functions.rst page is now approx 1600 lines long. > Don't you think that is a little long for only a handful > of functions. It is no longer easily possible to read > in one sitting what all of the builtin functions do. Right now that page is an alphabetical list of functions. Should it be broken up into thematically-related groups? e.g. abs(), bin(), complex() go into a 'Math Built-In' section, all(), any(), iter(), go into 'Iterator Built-Ins', and so on? --amk From solipsis at pitrou.net Tue Mar 17 23:13:42 2009 From: solipsis at pitrou.net (Antoine Pitrou) Date: Tue, 17 Mar 2009 22:13:42 +0000 (UTC) Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <49C01053.6070205@gmail.com> Message-ID: Nick Coghlan gmail.com> writes: > > Perhaps the page just needs an overview section or table at the start > that just gives a one line description of each method, and then links to > the more detailed descriptions with longer examples? Or perhaps the examples should be folded by default in the HTML rendering, with a simple way (a '+' sign or something) to unfold them. This is not even AJAX, just simple Javascript grafted on an otherwise static HTML page. As for reading the raw ReST source, I don't think ReST is pleasant to read anyway - or only for very short texts. From benjamin at python.org Tue Mar 17 23:16:03 2009 From: benjamin at python.org (Benjamin Peterson) Date: Tue, 17 Mar 2009 17:16:03 -0500 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <49C01053.6070205@gmail.com> Message-ID: <1afaf6160903171516h9c51c97m76cd5eacd7543d17@mail.gmail.com> 2009/3/17 Antoine Pitrou : > As for reading the raw ReST source, I don't think ReST is pleasant to read > anyway - or only for very short texts. You can read the text output ("make text"). That has less markup. -- Regards, Benjamin From python at rcn.com Tue Mar 17 23:30:11 2009 From: python at rcn.com (Raymond Hettinger) Date: Tue, 17 Mar 2009 15:30:11 -0700 Subject: [Python-checkins] r70438- python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org><305682430D3843B8B04885CFFC5140BC@RaymondLaptop1><1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com><793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1><49C01220.4010408@v.loewis.de><992AED9B2B5B415185282009E7D2B8F2@RaymondLaptop1> <20090317221308.GB17150@amk-desktop.matrixgroup.net> Message-ID: <544EC8FA37264C288C75D4D5CDC587A2@RaymondLaptop1> [A.M. Kuchling] > Right now that page is an alphabetical list of functions. Should it > be broken up into thematically-related groups? e.g. abs(), bin(), > complex() go into a 'Math Built-In' section, all(), any(), iter(), go > into 'Iterator Built-Ins', and so on? -1 Right now, the alphabetical list is the only way I can find things. If they get subgrouped, then you have to guess which grouping they go in before you can find them. Also, that still doesn't help with the basic task of learning what all of the builtins do. I think anyone trying to learn the language look at that task as an early milestone. Raymond From python at rcn.com Tue Mar 17 23:32:14 2009 From: python at rcn.com (Raymond Hettinger) Date: Tue, 17 Mar 2009 15:32:14 -0700 Subject: [Python-checkins] r70438 -python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org><305682430D3843B8B04885CFFC5140BC@RaymondLaptop1><49C01053.6070205@gmail.com> <1afaf6160903171516h9c51c97m76cd5eacd7543d17@mail.gmail.com> Message-ID: <8BA326FF671F49D39D003089CB02639C@RaymondLaptop1> > You can read the text output ("make text"). That has less markup. The point is that is even the html page or the text form is voluminous. Raymond From python-checkins at python.org Wed Mar 18 00:03:47 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 00:03:47 +0100 (CET) Subject: [Python-checkins] r70439 - in python/trunk: Lib/decimal.py Lib/test/test_decimal.py Misc/NEWS Message-ID: <20090317230347.18B6E1E4002@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 00:03:46 2009 New Revision: 70439 Log: Issue #2110: Add support for thousands separator and 'n' format specifier to Decimal __format__ method. Modified: python/trunk/Lib/decimal.py python/trunk/Lib/test/test_decimal.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/decimal.py ============================================================================== --- python/trunk/Lib/decimal.py (original) +++ python/trunk/Lib/decimal.py Wed Mar 18 00:03:46 2009 @@ -3506,18 +3506,16 @@ return self # My components are also immutable return self.__class__(str(self)) - # PEP 3101 support. See also _parse_format_specifier and _format_align - def __format__(self, specifier, context=None): + # PEP 3101 support. the _localeconv keyword argument should be + # considered private: it's provided for ease of testing only. + def __format__(self, specifier, context=None, _localeconv=None): """Format a Decimal instance according to the given specifier. The specifier should be a standard format specifier, with the form described in PEP 3101. Formatting types 'e', 'E', 'f', - 'F', 'g', 'G', and '%' are supported. If the formatting type - is omitted it defaults to 'g' or 'G', depending on the value - of context.capitals. - - At this time the 'n' format specifier type (which is supposed - to use the current locale) is not supported. + 'F', 'g', 'G', 'n' and '%' are supported. If the formatting + type is omitted it defaults to 'g' or 'G', depending on the + value of context.capitals. """ # Note: PEP 3101 says that if the type is not present then @@ -3528,17 +3526,20 @@ if context is None: context = getcontext() - spec = _parse_format_specifier(specifier) + spec = _parse_format_specifier(specifier, _localeconv=_localeconv) - # special values don't care about the type or precision... + # special values don't care about the type or precision if self._is_special: - return _format_align(str(self), spec) + sign = _format_sign(self._sign, spec) + body = str(self.copy_abs()) + return _format_align(sign, body, spec) # a type of None defaults to 'g' or 'G', depending on context - # if type is '%', adjust exponent of self accordingly if spec['type'] is None: spec['type'] = ['g', 'G'][context.capitals] - elif spec['type'] == '%': + + # if type is '%', adjust exponent of self accordingly + if spec['type'] == '%': self = _dec_from_triple(self._sign, self._int, self._exp+2) # round if necessary, taking rounding mode from the context @@ -3547,53 +3548,45 @@ if precision is not None: if spec['type'] in 'eE': self = self._round(precision+1, rounding) - elif spec['type'] in 'gG': - if len(self._int) > precision: - self = self._round(precision, rounding) elif spec['type'] in 'fF%': self = self._rescale(-precision, rounding) + elif spec['type'] in 'gG' and len(self._int) > precision: + self = self._round(precision, rounding) # special case: zeros with a positive exponent can't be # represented in fixed point; rescale them to 0e0. - elif not self and self._exp > 0 and spec['type'] in 'fF%': + if not self and self._exp > 0 and spec['type'] in 'fF%': self = self._rescale(0, rounding) # figure out placement of the decimal point leftdigits = self._exp + len(self._int) - if spec['type'] in 'fF%': - dotplace = leftdigits - elif spec['type'] in 'eE': + if spec['type'] in 'eE': if not self and precision is not None: dotplace = 1 - precision else: dotplace = 1 + elif spec['type'] in 'fF%': + dotplace = leftdigits elif spec['type'] in 'gG': if self._exp <= 0 and leftdigits > -6: dotplace = leftdigits else: dotplace = 1 - # figure out main part of numeric string... - if dotplace <= 0: - num = '0.' + '0'*(-dotplace) + self._int - elif dotplace >= len(self._int): - # make sure we're not padding a '0' with extra zeros on the right - assert dotplace==len(self._int) or self._int != '0' - num = self._int + '0'*(dotplace-len(self._int)) + # find digits before and after decimal point, and get exponent + if dotplace < 0: + intpart = '0' + fracpart = '0'*(-dotplace) + self._int + elif dotplace > len(self._int): + intpart = self._int + '0'*(dotplace-len(self._int)) + fracpart = '' else: - num = self._int[:dotplace] + '.' + self._int[dotplace:] - - # ...then the trailing exponent, or trailing '%' - if leftdigits != dotplace or spec['type'] in 'eE': - echar = {'E': 'E', 'e': 'e', 'G': 'E', 'g': 'e'}[spec['type']] - num = num + "{0}{1:+}".format(echar, leftdigits-dotplace) - elif spec['type'] == '%': - num = num + '%' - - # add sign - if self._sign == 1: - num = '-' + num - return _format_align(num, spec) - + intpart = self._int[:dotplace] or '0' + fracpart = self._int[dotplace:] + exp = leftdigits-dotplace + + # done with the decimal-specific stuff; hand over the rest + # of the formatting to the _format_number function + return _format_number(self._sign, intpart, fracpart, exp, spec) def _dec_from_triple(sign, coefficient, exponent, special=False): """Create a decimal instance directly, without any validation, @@ -5437,14 +5430,13 @@ _exact_half = re.compile('50*$').match ##### PEP3101 support functions ############################################## -# The functions parse_format_specifier and format_align have little to do -# with the Decimal class, and could potentially be reused for other pure +# The functions in this section have little to do with the Decimal +# class, and could potentially be reused or adapted for other pure # Python numeric classes that want to implement __format__ # # A format specifier for Decimal looks like: # -# [[fill]align][sign][0][minimumwidth][.precision][type] -# +# [[fill]align][sign][0][minimumwidth][,][.precision][type] _parse_format_specifier_regex = re.compile(r"""\A (?: @@ -5454,14 +5446,23 @@ (?P[-+ ])? (?P0)? (?P(?!0)\d+)? +(?P,)? (?:\.(?P0|(?!0)\d+))? -(?P[eEfFgG%])? +(?P[eEfFgGn%])? \Z """, re.VERBOSE) del re -def _parse_format_specifier(format_spec): +# The locale module is only needed for the 'n' format specifier. The +# rest of the PEP 3101 code functions quite happily without it, so we +# don't care too much if locale isn't present. +try: + import locale as _locale +except ImportError: + pass + +def _parse_format_specifier(format_spec, _localeconv=None): """Parse and validate a format specifier. Turns a standard numeric format specifier into a dict, with the @@ -5471,9 +5472,14 @@ align: alignment type, either '<', '>', '=' or '^' sign: either '+', '-' or ' ' minimumwidth: nonnegative integer giving minimum width + zeropad: boolean, indicating whether to pad with zeros + thousands_sep: string to use as thousands separator, or '' + grouping: grouping for thousands separators, in format + used by localeconv + decimal_point: string to use for decimal point precision: nonnegative integer giving precision, or None type: one of the characters 'eEfFgG%', or None - unicode: either True or False (always True for Python 3.x) + unicode: boolean (always True for Python 3.x) """ m = _parse_format_specifier_regex.match(format_spec) @@ -5483,26 +5489,25 @@ # get the dictionary format_dict = m.groupdict() - # defaults for fill and alignment + # zeropad; defaults for fill and alignment. If zero padding + # is requested, the fill and align fields should be absent. fill = format_dict['fill'] align = format_dict['align'] - if format_dict.pop('zeropad') is not None: - # in the face of conflict, refuse the temptation to guess - if fill is not None and fill != '0': + format_dict['zeropad'] = (format_dict['zeropad'] is not None) + if format_dict['zeropad']: + if fill is not None: raise ValueError("Fill character conflicts with '0'" " in format specifier: " + format_spec) - if align is not None and align != '=': + if align is not None: raise ValueError("Alignment conflicts with '0' in " "format specifier: " + format_spec) - fill = '0' - align = '=' format_dict['fill'] = fill or ' ' format_dict['align'] = align or '<' + # default sign handling: '-' for negative, '' for positive if format_dict['sign'] is None: format_dict['sign'] = '-' - # turn minimumwidth and precision entries into integers. # minimumwidth defaults to 0; precision remains None if not given format_dict['minimumwidth'] = int(format_dict['minimumwidth'] or '0') if format_dict['precision'] is not None: @@ -5514,58 +5519,172 @@ if format_dict['type'] in 'gG' or format_dict['type'] is None: format_dict['precision'] = 1 + # determine thousands separator, grouping, and decimal separator, and + # add appropriate entries to format_dict + if format_dict['type'] == 'n': + # apart from separators, 'n' behaves just like 'g' + format_dict['type'] = 'g' + if _localeconv is None: + _localeconv = _locale.localeconv() + if format_dict['thousands_sep'] is not None: + raise ValueError("Explicit thousands separator conflicts with " + "'n' type in format specifier: " + format_spec) + format_dict['thousands_sep'] = _localeconv['thousands_sep'] + format_dict['grouping'] = _localeconv['grouping'] + format_dict['decimal_point'] = _localeconv['decimal_point'] + else: + if format_dict['thousands_sep'] is None: + format_dict['thousands_sep'] = '' + format_dict['grouping'] = [3, 0] + format_dict['decimal_point'] = '.' + # record whether return type should be str or unicode format_dict['unicode'] = isinstance(format_spec, unicode) return format_dict -def _format_align(body, spec_dict): - """Given an unpadded, non-aligned numeric string, add padding and - aligment to conform with the given format specifier dictionary (as - output from parse_format_specifier). - - It's assumed that if body is negative then it starts with '-'. - Any leading sign ('-' or '+') is stripped from the body before - applying the alignment and padding rules, and replaced in the - appropriate position. +def _format_align(sign, body, spec): + """Given an unpadded, non-aligned numeric string 'body' and sign + string 'sign', add padding and aligment conforming to the given + format specifier dictionary 'spec' (as produced by + parse_format_specifier). - """ - # figure out the sign; we only examine the first character, so if - # body has leading whitespace the results may be surprising. - if len(body) > 0 and body[0] in '-+': - sign = body[0] - body = body[1:] - else: - sign = '' - - if sign != '-': - if spec_dict['sign'] in ' +': - sign = spec_dict['sign'] - else: - sign = '' + Also converts result to unicode if necessary. + """ # how much extra space do we have to play with? - minimumwidth = spec_dict['minimumwidth'] - fill = spec_dict['fill'] - padding = fill*(max(minimumwidth - (len(sign+body)), 0)) + minimumwidth = spec['minimumwidth'] + fill = spec['fill'] + padding = fill*(minimumwidth - len(sign) - len(body)) - align = spec_dict['align'] + align = spec['align'] if align == '<': result = sign + body + padding elif align == '>': result = padding + sign + body elif align == '=': result = sign + padding + body - else: #align == '^' + elif align == '^': half = len(padding)//2 result = padding[:half] + sign + body + padding[half:] + else: + raise ValueError('Unrecognised alignment field') # make sure that result is unicode if necessary - if spec_dict['unicode']: + if spec['unicode']: result = unicode(result) return result +def _group_lengths(grouping): + """Convert a localeconv-style grouping into a (possibly infinite) + iterable of integers representing group lengths. + + """ + # The result from localeconv()['grouping'], and the input to this + # function, should be a list of integers in one of the + # following three forms: + # + # (1) an empty list, or + # (2) nonempty list of positive integers + [0] + # (3) list of positive integers + [locale.CHAR_MAX], or + + from itertools import chain, repeat + if not grouping: + return [] + elif grouping[-1] == 0 and len(grouping) >= 2: + return chain(grouping[:-1], repeat(grouping[-2])) + elif grouping[-1] == _locale.CHAR_MAX: + return grouping[:-1] + else: + raise ValueError('unrecognised format for grouping') + +def _insert_thousands_sep(digits, spec, min_width=1): + """Insert thousands separators into a digit string. + + spec is a dictionary whose keys should include 'thousands_sep' and + 'grouping'; typically it's the result of parsing the format + specifier using _parse_format_specifier. + + The min_width keyword argument gives the minimum length of the + result, which will be padded on the left with zeros if necessary. + + If necessary, the zero padding adds an extra '0' on the left to + avoid a leading thousands separator. For example, inserting + commas every three digits in '123456', with min_width=8, gives + '0,123,456', even though that has length 9. + + """ + + sep = spec['thousands_sep'] + grouping = spec['grouping'] + + groups = [] + for l in _group_lengths(grouping): + if groups: + min_width -= len(sep) + if l <= 0: + raise ValueError("group length should be positive") + # max(..., 1) forces at least 1 digit to the left of a separator + l = min(max(len(digits), min_width, 1), l) + groups.append('0'*(l - len(digits)) + digits[-l:]) + digits = digits[:-l] + min_width -= l + if not digits and min_width <= 0: + break + else: + l = max(len(digits), min_width, 1) + groups.append('0'*(l - len(digits)) + digits[-l:]) + return sep.join(reversed(groups)) + +def _format_sign(is_negative, spec): + """Determine sign character.""" + + if is_negative: + return '-' + elif spec['sign'] in ' +': + return spec['sign'] + else: + return '' + +def _format_number(is_negative, intpart, fracpart, exp, spec): + """Format a number, given the following data: + + is_negative: true if the number is negative, else false + intpart: string of digits that must appear before the decimal point + fracpart: string of digits that must come after the point + exp: exponent, as an integer + spec: dictionary resulting from parsing the format specifier + + This function uses the information in spec to: + insert separators (decimal separator and thousands separators) + format the sign + format the exponent + add trailing '%' for the '%' type + zero-pad if necessary + fill and align if necessary + """ + + sign = _format_sign(is_negative, spec) + + if fracpart: + fracpart = spec['decimal_point'] + fracpart + + if exp != 0 or spec['type'] in 'eE': + echar = {'E': 'E', 'e': 'e', 'G': 'E', 'g': 'e'}[spec['type']] + fracpart += "{0}{1:+}".format(echar, exp) + if spec['type'] == '%': + fracpart += '%' + + if spec['zeropad']: + min_width = spec['minimumwidth'] - len(fracpart) - len(sign) + else: + min_width = 0 + intpart = _insert_thousands_sep(intpart, spec, min_width) + + return _format_align(sign, intpart+fracpart, spec) + + ##### Useful Constants (internal use only) ################################ # Reusable defaults Modified: python/trunk/Lib/test/test_decimal.py ============================================================================== --- python/trunk/Lib/test/test_decimal.py (original) +++ python/trunk/Lib/test/test_decimal.py Wed Mar 18 00:03:46 2009 @@ -616,6 +616,7 @@ self.assertEqual(eval('Decimal(10)' + sym + 'E()'), '10' + rop + 'str') + class DecimalFormatTest(unittest.TestCase): '''Unit tests for the format function.''' def test_formatting(self): @@ -705,15 +706,110 @@ ('', '1.00', '1.00'), - # check alignment + # test alignment and padding ('<6', '123', '123 '), ('>6', '123', ' 123'), ('^6', '123', ' 123 '), ('=+6', '123', '+ 123'), + ('#<10', 'NaN', 'NaN#######'), + ('#<10', '-4.3', '-4.3######'), + ('#<+10', '0.0130', '+0.0130###'), + ('#< 10', '0.0130', ' 0.0130###'), + ('@>10', '-Inf', '@-Infinity'), + ('#>5', '-Inf', '-Infinity'), + ('?^5', '123', '?123?'), + ('%^6', '123', '%123%%'), + (' ^6', '-45.6', '-45.6 '), + ('/=10', '-45.6', '-/////45.6'), + ('/=+10', '45.6', '+/////45.6'), + ('/= 10', '45.6', ' /////45.6'), + + # thousands separator + (',', '1234567', '1,234,567'), + (',', '123456', '123,456'), + (',', '12345', '12,345'), + (',', '1234', '1,234'), + (',', '123', '123'), + (',', '12', '12'), + (',', '1', '1'), + (',', '0', '0'), + (',', '-1234567', '-1,234,567'), + (',', '-123456', '-123,456'), + ('7,', '123456', '123,456'), + ('8,', '123456', '123,456 '), + ('08,', '123456', '0,123,456'), # special case: extra 0 needed + ('+08,', '123456', '+123,456'), # but not if there's a sign + (' 08,', '123456', ' 123,456'), + ('08,', '-123456', '-123,456'), + ('+09,', '123456', '+0,123,456'), + # ... with fractional part... + ('07,', '1234.56', '1,234.56'), + ('08,', '1234.56', '1,234.56'), + ('09,', '1234.56', '01,234.56'), + ('010,', '1234.56', '001,234.56'), + ('011,', '1234.56', '0,001,234.56'), + ('012,', '1234.56', '0,001,234.56'), + ('08,.1f', '1234.5', '01,234.5'), + # no thousands separators in fraction part + (',', '1.23456789', '1.23456789'), + (',%', '123.456789', '12,345.6789%'), + (',e', '123456', '1.23456e+5'), + (',E', '123456', '1.23456E+5'), ] for fmt, d, result in test_values: self.assertEqual(format(Decimal(d), fmt), result) + def test_n_format(self): + try: + from locale import CHAR_MAX + except ImportError: + return + + # Set up some localeconv-like dictionaries + en_US = { + 'decimal_point' : '.', + 'grouping' : [3, 3, 0], + 'thousands_sep': ',' + } + + fr_FR = { + 'decimal_point' : ',', + 'grouping' : [CHAR_MAX], + 'thousands_sep' : '' + } + + ru_RU = { + 'decimal_point' : ',', + 'grouping' : [3, 3, 0], + 'thousands_sep' : ' ' + } + + crazy = { + 'decimal_point' : '&', + 'grouping' : [1, 4, 2, CHAR_MAX], + 'thousands_sep' : '-' + } + + + def get_fmt(x, locale, fmt='n'): + return Decimal.__format__(Decimal(x), fmt, _localeconv=locale) + + self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7') + self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7') + self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7') + self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7') + + self.assertEqual(get_fmt(123456789, en_US), '123,456,789') + self.assertEqual(get_fmt(123456789, fr_FR), '123456789') + self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789') + self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3') + + self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8') + self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8') + self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8') + self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8') + + class DecimalArithmeticOperatorsTest(unittest.TestCase): '''Unit tests for all arithmetic operators, binary and unary.''' Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Wed Mar 18 00:03:46 2009 @@ -174,6 +174,9 @@ Library ------- +- Issue #2110: Add support for thousands separator and 'n' type + specifier to Decimal.__format__ + - Fix Decimal.__format__ bug that swapped the meanings of the '<' and '>' alignment characters. From python-checkins at python.org Wed Mar 18 00:12:51 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 00:12:51 +0100 (CET) Subject: [Python-checkins] r70440 - in python/branches/py3k: Lib/decimal.py Lib/test/test_decimal.py Misc/NEWS Message-ID: <20090317231251.CF2CE1E4002@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 00:12:51 2009 New Revision: 70440 Log: Merged revisions 70439 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70439 | mark.dickinson | 2009-03-17 23:03:46 +0000 (Tue, 17 Mar 2009) | 3 lines Issue #2110: Add support for thousands separator and 'n' format specifier to Decimal __format__ method. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/decimal.py python/branches/py3k/Lib/test/test_decimal.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/decimal.py ============================================================================== --- python/branches/py3k/Lib/decimal.py (original) +++ python/branches/py3k/Lib/decimal.py Wed Mar 18 00:12:51 2009 @@ -3587,18 +3587,16 @@ return self # My components are also immutable return self.__class__(str(self)) - # PEP 3101 support. See also _parse_format_specifier and _format_align - def __format__(self, specifier, context=None): + # PEP 3101 support. the _localeconv keyword argument should be + # considered private: it's provided for ease of testing only. + def __format__(self, specifier, context=None, _localeconv=None): """Format a Decimal instance according to the given specifier. The specifier should be a standard format specifier, with the form described in PEP 3101. Formatting types 'e', 'E', 'f', - 'F', 'g', 'G', and '%' are supported. If the formatting type - is omitted it defaults to 'g' or 'G', depending on the value - of context.capitals. - - At this time the 'n' format specifier type (which is supposed - to use the current locale) is not supported. + 'F', 'g', 'G', 'n' and '%' are supported. If the formatting + type is omitted it defaults to 'g' or 'G', depending on the + value of context.capitals. """ # Note: PEP 3101 says that if the type is not present then @@ -3609,17 +3607,20 @@ if context is None: context = getcontext() - spec = _parse_format_specifier(specifier) + spec = _parse_format_specifier(specifier, _localeconv=_localeconv) - # special values don't care about the type or precision... + # special values don't care about the type or precision if self._is_special: - return _format_align(str(self), spec) + sign = _format_sign(self._sign, spec) + body = str(self.copy_abs()) + return _format_align(sign, body, spec) # a type of None defaults to 'g' or 'G', depending on context - # if type is '%', adjust exponent of self accordingly if spec['type'] is None: spec['type'] = ['g', 'G'][context.capitals] - elif spec['type'] == '%': + + # if type is '%', adjust exponent of self accordingly + if spec['type'] == '%': self = _dec_from_triple(self._sign, self._int, self._exp+2) # round if necessary, taking rounding mode from the context @@ -3628,53 +3629,45 @@ if precision is not None: if spec['type'] in 'eE': self = self._round(precision+1, rounding) - elif spec['type'] in 'gG': - if len(self._int) > precision: - self = self._round(precision, rounding) elif spec['type'] in 'fF%': self = self._rescale(-precision, rounding) + elif spec['type'] in 'gG' and len(self._int) > precision: + self = self._round(precision, rounding) # special case: zeros with a positive exponent can't be # represented in fixed point; rescale them to 0e0. - elif not self and self._exp > 0 and spec['type'] in 'fF%': + if not self and self._exp > 0 and spec['type'] in 'fF%': self = self._rescale(0, rounding) # figure out placement of the decimal point leftdigits = self._exp + len(self._int) - if spec['type'] in 'fF%': - dotplace = leftdigits - elif spec['type'] in 'eE': + if spec['type'] in 'eE': if not self and precision is not None: dotplace = 1 - precision else: dotplace = 1 + elif spec['type'] in 'fF%': + dotplace = leftdigits elif spec['type'] in 'gG': if self._exp <= 0 and leftdigits > -6: dotplace = leftdigits else: dotplace = 1 - # figure out main part of numeric string... - if dotplace <= 0: - num = '0.' + '0'*(-dotplace) + self._int - elif dotplace >= len(self._int): - # make sure we're not padding a '0' with extra zeros on the right - assert dotplace==len(self._int) or self._int != '0' - num = self._int + '0'*(dotplace-len(self._int)) + # find digits before and after decimal point, and get exponent + if dotplace < 0: + intpart = '0' + fracpart = '0'*(-dotplace) + self._int + elif dotplace > len(self._int): + intpart = self._int + '0'*(dotplace-len(self._int)) + fracpart = '' else: - num = self._int[:dotplace] + '.' + self._int[dotplace:] - - # ...then the trailing exponent, or trailing '%' - if leftdigits != dotplace or spec['type'] in 'eE': - echar = {'E': 'E', 'e': 'e', 'G': 'E', 'g': 'e'}[spec['type']] - num = num + "{0}{1:+}".format(echar, leftdigits-dotplace) - elif spec['type'] == '%': - num = num + '%' - - # add sign - if self._sign == 1: - num = '-' + num - return _format_align(num, spec) - + intpart = self._int[:dotplace] or '0' + fracpart = self._int[dotplace:] + exp = leftdigits-dotplace + + # done with the decimal-specific stuff; hand over the rest + # of the formatting to the _format_number function + return _format_number(self._sign, intpart, fracpart, exp, spec) def _dec_from_triple(sign, coefficient, exponent, special=False): """Create a decimal instance directly, without any validation, @@ -5516,14 +5509,13 @@ _exact_half = re.compile('50*$').match ##### PEP3101 support functions ############################################## -# The functions parse_format_specifier and format_align have little to do -# with the Decimal class, and could potentially be reused for other pure +# The functions in this section have little to do with the Decimal +# class, and could potentially be reused or adapted for other pure # Python numeric classes that want to implement __format__ # # A format specifier for Decimal looks like: # -# [[fill]align][sign][0][minimumwidth][.precision][type] -# +# [[fill]align][sign][0][minimumwidth][,][.precision][type] _parse_format_specifier_regex = re.compile(r"""\A (?: @@ -5533,14 +5525,23 @@ (?P[-+ ])? (?P0)? (?P(?!0)\d+)? +(?P,)? (?:\.(?P0|(?!0)\d+))? -(?P[eEfFgG%])? +(?P[eEfFgGn%])? \Z """, re.VERBOSE) del re -def _parse_format_specifier(format_spec): +# The locale module is only needed for the 'n' format specifier. The +# rest of the PEP 3101 code functions quite happily without it, so we +# don't care too much if locale isn't present. +try: + import locale as _locale +except ImportError: + pass + +def _parse_format_specifier(format_spec, _localeconv=None): """Parse and validate a format specifier. Turns a standard numeric format specifier into a dict, with the @@ -5550,9 +5551,13 @@ align: alignment type, either '<', '>', '=' or '^' sign: either '+', '-' or ' ' minimumwidth: nonnegative integer giving minimum width + zeropad: boolean, indicating whether to pad with zeros + thousands_sep: string to use as thousands separator, or '' + grouping: grouping for thousands separators, in format + used by localeconv + decimal_point: string to use for decimal point precision: nonnegative integer giving precision, or None type: one of the characters 'eEfFgG%', or None - unicode: either True or False (always True for Python 3.x) """ m = _parse_format_specifier_regex.match(format_spec) @@ -5562,26 +5567,25 @@ # get the dictionary format_dict = m.groupdict() - # defaults for fill and alignment + # zeropad; defaults for fill and alignment. If zero padding + # is requested, the fill and align fields should be absent. fill = format_dict['fill'] align = format_dict['align'] - if format_dict.pop('zeropad') is not None: - # in the face of conflict, refuse the temptation to guess - if fill is not None and fill != '0': + format_dict['zeropad'] = (format_dict['zeropad'] is not None) + if format_dict['zeropad']: + if fill is not None: raise ValueError("Fill character conflicts with '0'" " in format specifier: " + format_spec) - if align is not None and align != '=': + if align is not None: raise ValueError("Alignment conflicts with '0' in " "format specifier: " + format_spec) - fill = '0' - align = '=' format_dict['fill'] = fill or ' ' format_dict['align'] = align or '<' + # default sign handling: '-' for negative, '' for positive if format_dict['sign'] is None: format_dict['sign'] = '-' - # turn minimumwidth and precision entries into integers. # minimumwidth defaults to 0; precision remains None if not given format_dict['minimumwidth'] = int(format_dict['minimumwidth'] or '0') if format_dict['precision'] is not None: @@ -5593,54 +5597,163 @@ if format_dict['type'] in 'gG' or format_dict['type'] is None: format_dict['precision'] = 1 - # record whether return type should be str or unicode - format_dict['unicode'] = True + # determine thousands separator, grouping, and decimal separator, and + # add appropriate entries to format_dict + if format_dict['type'] == 'n': + # apart from separators, 'n' behaves just like 'g' + format_dict['type'] = 'g' + if _localeconv is None: + _localeconv = _locale.localeconv() + if format_dict['thousands_sep'] is not None: + raise ValueError("Explicit thousands separator conflicts with " + "'n' type in format specifier: " + format_spec) + format_dict['thousands_sep'] = _localeconv['thousands_sep'] + format_dict['grouping'] = _localeconv['grouping'] + format_dict['decimal_point'] = _localeconv['decimal_point'] + else: + if format_dict['thousands_sep'] is None: + format_dict['thousands_sep'] = '' + format_dict['grouping'] = [3, 0] + format_dict['decimal_point'] = '.' return format_dict -def _format_align(body, spec_dict): - """Given an unpadded, non-aligned numeric string, add padding and - aligment to conform with the given format specifier dictionary (as - output from parse_format_specifier). - - It's assumed that if body is negative then it starts with '-'. - Any leading sign ('-' or '+') is stripped from the body before - applying the alignment and padding rules, and replaced in the - appropriate position. +def _format_align(sign, body, spec): + """Given an unpadded, non-aligned numeric string 'body' and sign + string 'sign', add padding and aligment conforming to the given + format specifier dictionary 'spec' (as produced by + parse_format_specifier). """ - # figure out the sign; we only examine the first character, so if - # body has leading whitespace the results may be surprising. - if len(body) > 0 and body[0] in '-+': - sign = body[0] - body = body[1:] - else: - sign = '' - - if sign != '-': - if spec_dict['sign'] in ' +': - sign = spec_dict['sign'] - else: - sign = '' - # how much extra space do we have to play with? - minimumwidth = spec_dict['minimumwidth'] - fill = spec_dict['fill'] - padding = fill*(max(minimumwidth - (len(sign+body)), 0)) + minimumwidth = spec['minimumwidth'] + fill = spec['fill'] + padding = fill*(minimumwidth - len(sign) - len(body)) - align = spec_dict['align'] + align = spec['align'] if align == '<': result = sign + body + padding elif align == '>': result = padding + sign + body elif align == '=': result = sign + padding + body - else: #align == '^' + elif align == '^': half = len(padding)//2 result = padding[:half] + sign + body + padding[half:] + else: + raise ValueError('Unrecognised alignment field') return result +def _group_lengths(grouping): + """Convert a localeconv-style grouping into a (possibly infinite) + iterable of integers representing group lengths. + + """ + # The result from localeconv()['grouping'], and the input to this + # function, should be a list of integers in one of the + # following three forms: + # + # (1) an empty list, or + # (2) nonempty list of positive integers + [0] + # (3) list of positive integers + [locale.CHAR_MAX], or + + from itertools import chain, repeat + if not grouping: + return [] + elif grouping[-1] == 0 and len(grouping) >= 2: + return chain(grouping[:-1], repeat(grouping[-2])) + elif grouping[-1] == _locale.CHAR_MAX: + return grouping[:-1] + else: + raise ValueError('unrecognised format for grouping') + +def _insert_thousands_sep(digits, spec, min_width=1): + """Insert thousands separators into a digit string. + + spec is a dictionary whose keys should include 'thousands_sep' and + 'grouping'; typically it's the result of parsing the format + specifier using _parse_format_specifier. + + The min_width keyword argument gives the minimum length of the + result, which will be padded on the left with zeros if necessary. + + If necessary, the zero padding adds an extra '0' on the left to + avoid a leading thousands separator. For example, inserting + commas every three digits in '123456', with min_width=8, gives + '0,123,456', even though that has length 9. + + """ + + sep = spec['thousands_sep'] + grouping = spec['grouping'] + + groups = [] + for l in _group_lengths(grouping): + if groups: + min_width -= len(sep) + if l <= 0: + raise ValueError("group length should be positive") + # max(..., 1) forces at least 1 digit to the left of a separator + l = min(max(len(digits), min_width, 1), l) + groups.append('0'*(l - len(digits)) + digits[-l:]) + digits = digits[:-l] + min_width -= l + if not digits and min_width <= 0: + break + else: + l = max(len(digits), min_width, 1) + groups.append('0'*(l - len(digits)) + digits[-l:]) + return sep.join(reversed(groups)) + +def _format_sign(is_negative, spec): + """Determine sign character.""" + + if is_negative: + return '-' + elif spec['sign'] in ' +': + return spec['sign'] + else: + return '' + +def _format_number(is_negative, intpart, fracpart, exp, spec): + """Format a number, given the following data: + + is_negative: true if the number is negative, else false + intpart: string of digits that must appear before the decimal point + fracpart: string of digits that must come after the point + exp: exponent, as an integer + spec: dictionary resulting from parsing the format specifier + + This function uses the information in spec to: + insert separators (decimal separator and thousands separators) + format the sign + format the exponent + add trailing '%' for the '%' type + zero-pad if necessary + fill and align if necessary + """ + + sign = _format_sign(is_negative, spec) + + if fracpart: + fracpart = spec['decimal_point'] + fracpart + + if exp != 0 or spec['type'] in 'eE': + echar = {'E': 'E', 'e': 'e', 'G': 'E', 'g': 'e'}[spec['type']] + fracpart += "{0}{1:+}".format(echar, exp) + if spec['type'] == '%': + fracpart += '%' + + if spec['zeropad']: + min_width = spec['minimumwidth'] - len(fracpart) - len(sign) + else: + min_width = 0 + intpart = _insert_thousands_sep(intpart, spec, min_width) + + return _format_align(sign, intpart+fracpart, spec) + + ##### Useful Constants (internal use only) ################################ # Reusable defaults Modified: python/branches/py3k/Lib/test/test_decimal.py ============================================================================== --- python/branches/py3k/Lib/test/test_decimal.py (original) +++ python/branches/py3k/Lib/test/test_decimal.py Wed Mar 18 00:12:51 2009 @@ -605,6 +605,7 @@ self.assertEqual(eval('Decimal(10)' + sym + 'E()'), '10' + rop + 'str') + class DecimalFormatTest(unittest.TestCase): '''Unit tests for the format function.''' def test_formatting(self): @@ -694,15 +695,110 @@ ('', '1.00', '1.00'), - # check alignment + # test alignment and padding ('<6', '123', '123 '), ('>6', '123', ' 123'), ('^6', '123', ' 123 '), ('=+6', '123', '+ 123'), + ('#<10', 'NaN', 'NaN#######'), + ('#<10', '-4.3', '-4.3######'), + ('#<+10', '0.0130', '+0.0130###'), + ('#< 10', '0.0130', ' 0.0130###'), + ('@>10', '-Inf', '@-Infinity'), + ('#>5', '-Inf', '-Infinity'), + ('?^5', '123', '?123?'), + ('%^6', '123', '%123%%'), + (' ^6', '-45.6', '-45.6 '), + ('/=10', '-45.6', '-/////45.6'), + ('/=+10', '45.6', '+/////45.6'), + ('/= 10', '45.6', ' /////45.6'), + + # thousands separator + (',', '1234567', '1,234,567'), + (',', '123456', '123,456'), + (',', '12345', '12,345'), + (',', '1234', '1,234'), + (',', '123', '123'), + (',', '12', '12'), + (',', '1', '1'), + (',', '0', '0'), + (',', '-1234567', '-1,234,567'), + (',', '-123456', '-123,456'), + ('7,', '123456', '123,456'), + ('8,', '123456', '123,456 '), + ('08,', '123456', '0,123,456'), # special case: extra 0 needed + ('+08,', '123456', '+123,456'), # but not if there's a sign + (' 08,', '123456', ' 123,456'), + ('08,', '-123456', '-123,456'), + ('+09,', '123456', '+0,123,456'), + # ... with fractional part... + ('07,', '1234.56', '1,234.56'), + ('08,', '1234.56', '1,234.56'), + ('09,', '1234.56', '01,234.56'), + ('010,', '1234.56', '001,234.56'), + ('011,', '1234.56', '0,001,234.56'), + ('012,', '1234.56', '0,001,234.56'), + ('08,.1f', '1234.5', '01,234.5'), + # no thousands separators in fraction part + (',', '1.23456789', '1.23456789'), + (',%', '123.456789', '12,345.6789%'), + (',e', '123456', '1.23456e+5'), + (',E', '123456', '1.23456E+5'), ] for fmt, d, result in test_values: self.assertEqual(format(Decimal(d), fmt), result) + def test_n_format(self): + try: + from locale import CHAR_MAX + except ImportError: + return + + # Set up some localeconv-like dictionaries + en_US = { + 'decimal_point' : '.', + 'grouping' : [3, 3, 0], + 'thousands_sep': ',' + } + + fr_FR = { + 'decimal_point' : ',', + 'grouping' : [CHAR_MAX], + 'thousands_sep' : '' + } + + ru_RU = { + 'decimal_point' : ',', + 'grouping' : [3, 3, 0], + 'thousands_sep' : ' ' + } + + crazy = { + 'decimal_point' : '&', + 'grouping' : [1, 4, 2, CHAR_MAX], + 'thousands_sep' : '-' + } + + + def get_fmt(x, locale, fmt='n'): + return Decimal.__format__(Decimal(x), fmt, _localeconv=locale) + + self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7') + self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7') + self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7') + self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7') + + self.assertEqual(get_fmt(123456789, en_US), '123,456,789') + self.assertEqual(get_fmt(123456789, fr_FR), '123456789') + self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789') + self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3') + + self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8') + self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8') + self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8') + self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8') + + class DecimalArithmeticOperatorsTest(unittest.TestCase): '''Unit tests for all arithmetic operators, binary and unary.''' Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Mar 18 00:12:51 2009 @@ -21,6 +21,9 @@ Library ------- +- Issue #2110: Add support for thousands separator and 'n' type + specifier to Decimal.__format__ + - Fix Decimal.__format__ bug that swapped the meanings of the '<' and '>' alignment characters. From python-checkins at python.org Wed Mar 18 00:14:34 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 00:14:34 +0100 (CET) Subject: [Python-checkins] r70441 - python/branches/release30-maint Message-ID: <20090317231434.F28621E4002@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 00:14:34 2009 New Revision: 70441 Log: Blocked revisions 70440 via svnmerge ................ r70440 | mark.dickinson | 2009-03-17 23:12:51 +0000 (Tue, 17 Mar 2009) | 10 lines Merged revisions 70439 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70439 | mark.dickinson | 2009-03-17 23:03:46 +0000 (Tue, 17 Mar 2009) | 3 lines Issue #2110: Add support for thousands separator and 'n' format specifier to Decimal __format__ method. ........ ................ Modified: python/branches/release30-maint/ (props changed) From python at rcn.com Wed Mar 18 00:14:59 2009 From: python at rcn.com (Raymond Hettinger) Date: Tue, 17 Mar 2009 16:14:59 -0700 Subject: [Python-checkins] r70440 - in python/branches/py3k: Lib/decimal.pyLib/test/test_decimal.py Misc/NEWS References: <20090317231251.CF2CE1E4002@bag.python.org> Message-ID: <443DCD7DC7FE44449E7D87AE409544A0@RaymondLaptop1> > Issue #2110: Add support for thousands separator and 'n' format specifier > to Decimal __format__ method. Very nice. Thank you. Raymond From python-checkins at python.org Wed Mar 18 00:15:40 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 00:15:40 +0100 (CET) Subject: [Python-checkins] r70442 - python/branches/release26-maint Message-ID: <20090317231540.78C051E4002@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 00:15:40 2009 New Revision: 70442 Log: Blocked revisions 70439 via svnmerge ........ r70439 | mark.dickinson | 2009-03-17 23:03:46 +0000 (Tue, 17 Mar 2009) | 3 lines Issue #2110: Add support for thousands separator and 'n' format specifier to Decimal __format__ method. ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Wed Mar 18 00:19:00 2009 From: python-checkins at python.org (bob.ippolito) Date: Wed, 18 Mar 2009 00:19:00 +0100 (CET) Subject: [Python-checkins] r70443 - in python/trunk: Lib/json/__init__.py Lib/json/decoder.py Lib/json/encoder.py Lib/json/scanner.py Lib/json/tests/test_check_circular.py Lib/json/tests/test_decode.py Lib/json/tests/test_dump.py Lib/json/tests/test_encode_basestring_ascii.py Lib/json/tests/test_fail.py Lib/json/tests/test_float.py Lib/json/tests/test_unicode.py Lib/json/tool.py Modules/_json.c Message-ID: <20090317231900.8292E1E4002@bag.python.org> Author: bob.ippolito Date: Wed Mar 18 00:19:00 2009 New Revision: 70443 Log: merge json library with simplejson 2.0.9 (issue 4136) Added: python/trunk/Lib/json/tests/test_check_circular.py Modified: python/trunk/Lib/json/__init__.py python/trunk/Lib/json/decoder.py python/trunk/Lib/json/encoder.py python/trunk/Lib/json/scanner.py python/trunk/Lib/json/tests/test_decode.py python/trunk/Lib/json/tests/test_dump.py python/trunk/Lib/json/tests/test_encode_basestring_ascii.py python/trunk/Lib/json/tests/test_fail.py python/trunk/Lib/json/tests/test_float.py python/trunk/Lib/json/tests/test_unicode.py python/trunk/Lib/json/tool.py python/trunk/Modules/_json.c Modified: python/trunk/Lib/json/__init__.py ============================================================================== --- python/trunk/Lib/json/__init__.py (original) +++ python/trunk/Lib/json/__init__.py Wed Mar 18 00:19:00 2009 @@ -1,11 +1,13 @@ -r"""A simple, fast, extensible JSON encoder and decoder - -JSON (JavaScript Object Notation) is a subset of +r"""JSON (JavaScript Object Notation) is a subset of JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data interchange format. -json exposes an API familiar to uses of the standard library -marshal and pickle modules. +:mod:`json` exposes an API familiar to users of the standard library +:mod:`marshal` and :mod:`pickle` modules. It is the externally maintained +version of the :mod:`json` library contained in Python 2.6, but maintains +compatibility with Python 2.4 and Python 2.5 and (currently) has +significant performance advantages, even without using the optional C +extension for speedups. Encoding basic Python object hierarchies:: @@ -32,23 +34,28 @@ >>> json.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':')) '[1,2,3,{"4":5,"6":7}]' -Pretty printing (using repr() because of extraneous whitespace in the output):: +Pretty printing:: >>> import json - >>> print repr(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)) - '{\n "4": 5, \n "6": 7\n}' + >>> s = json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4) + >>> print '\n'.join([l.rstrip() for l in s.splitlines()]) + { + "4": 5, + "6": 7 + } Decoding JSON:: >>> import json - >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') - [u'foo', {u'bar': [u'baz', None, 1.0, 2]}] - >>> json.loads('"\\"foo\\bar"') - u'"foo\x08ar' + >>> obj = [u'foo', {u'bar': [u'baz', None, 1.0, 2]}] + >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') == obj + True + >>> json.loads('"\\"foo\\bar"') == u'"foo\x08ar' + True >>> from StringIO import StringIO >>> io = StringIO('["streaming API"]') - >>> json.load(io) - [u'streaming API'] + >>> json.load(io)[0] == 'streaming API' + True Specializing JSON object decoding:: @@ -61,43 +68,36 @@ >>> json.loads('{"__complex__": true, "real": 1, "imag": 2}', ... object_hook=as_complex) (1+2j) - >>> import decimal - >>> json.loads('1.1', parse_float=decimal.Decimal) - Decimal('1.1') + >>> from decimal import Decimal + >>> json.loads('1.1', parse_float=Decimal) == Decimal('1.1') + True -Extending JSONEncoder:: +Specializing JSON object encoding:: >>> import json - >>> class ComplexEncoder(json.JSONEncoder): - ... def default(self, obj): - ... if isinstance(obj, complex): - ... return [obj.real, obj.imag] - ... return json.JSONEncoder.default(self, obj) + >>> def encode_complex(obj): + ... if isinstance(obj, complex): + ... return [obj.real, obj.imag] + ... raise TypeError(repr(o) + " is not JSON serializable") ... - >>> dumps(2 + 1j, cls=ComplexEncoder) + >>> json.dumps(2 + 1j, default=encode_complex) '[2.0, 1.0]' - >>> ComplexEncoder().encode(2 + 1j) + >>> json.JSONEncoder(default=encode_complex).encode(2 + 1j) + '[2.0, 1.0]' + >>> ''.join(json.JSONEncoder(default=encode_complex).iterencode(2 + 1j)) '[2.0, 1.0]' - >>> list(ComplexEncoder().iterencode(2 + 1j)) - ['[', '2.0', ', ', '1.0', ']'] -Using json.tool from the shell to validate and -pretty-print:: +Using json.tool from the shell to validate and pretty-print:: - $ echo '{"json":"obj"}' | python -mjson.tool + $ echo '{"json":"obj"}' | python -m json.tool { "json": "obj" } - $ echo '{ 1.2:3.4}' | python -mjson.tool + $ echo '{ 1.2:3.4}' | python -m json.tool Expecting property name: line 1 column 2 (char 2) - -Note that the JSON produced by this module's default settings -is a subset of YAML, so it may be used as a serializer for that as well. - """ - -__version__ = '1.9' +__version__ = '2.0.9' __all__ = [ 'dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONEncoder', @@ -125,28 +125,29 @@ """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a ``.write()``-supporting file-like object). - If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types + If ``skipkeys`` is true then ``dict`` keys that are not basic types (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) will be skipped instead of raising a ``TypeError``. - If ``ensure_ascii`` is ``False``, then the some chunks written to ``fp`` + If ``ensure_ascii`` is false, then the some chunks written to ``fp`` may be ``unicode`` instances, subject to normal Python ``str`` to ``unicode`` coercion rules. Unless ``fp.write()`` explicitly understands ``unicode`` (as in ``codecs.getwriter()``) this is likely to cause an error. - If ``check_circular`` is ``False``, then the circular reference check + If ``check_circular`` is false, then the circular reference check for container types will be skipped and a circular reference will result in an ``OverflowError`` (or worse). - If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to + If ``allow_nan`` is false, then it will be a ``ValueError`` to serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in strict compliance of the JSON specification, instead of using the JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). - If ``indent`` is a non-negative integer, then JSON array elements and object - members will be pretty-printed with that indent level. An indent level - of 0 will only insert newlines. ``None`` is the most compact representation. + If ``indent`` is a non-negative integer, then JSON array elements and + object members will be pretty-printed with that indent level. An indent + level of 0 will only insert newlines. ``None`` is the most compact + representation. If ``separators`` is an ``(item_separator, dict_separator)`` tuple then it will be used instead of the default ``(', ', ': ')`` separators. @@ -163,8 +164,8 @@ """ # cached encoder - if (skipkeys is False and ensure_ascii is True and - check_circular is True and allow_nan is True and + if (not skipkeys and ensure_ascii and + check_circular and allow_nan and cls is None and indent is None and separators is None and encoding == 'utf-8' and default is None and not kw): iterable = _default_encoder.iterencode(obj) @@ -186,19 +187,19 @@ encoding='utf-8', default=None, **kw): """Serialize ``obj`` to a JSON formatted ``str``. - If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types + If ``skipkeys`` is false then ``dict`` keys that are not basic types (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) will be skipped instead of raising a ``TypeError``. - If ``ensure_ascii`` is ``False``, then the return value will be a + If ``ensure_ascii`` is false, then the return value will be a ``unicode`` instance subject to normal Python ``str`` to ``unicode`` coercion rules instead of being escaped to an ASCII ``str``. - If ``check_circular`` is ``False``, then the circular reference check + If ``check_circular`` is false, then the circular reference check for container types will be skipped and a circular reference will result in an ``OverflowError`` (or worse). - If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to + If ``allow_nan`` is false, then it will be a ``ValueError`` to serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in strict compliance of the JSON specification, instead of using the JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). @@ -223,8 +224,8 @@ """ # cached encoder - if (skipkeys is False and ensure_ascii is True and - check_circular is True and allow_nan is True and + if (not skipkeys and ensure_ascii and + check_circular and allow_nan and cls is None and indent is None and separators is None and encoding == 'utf-8' and default is None and not kw): return _default_encoder.encode(obj) @@ -242,8 +243,8 @@ def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, **kw): - """Deserialize ``fp`` (a ``.read()``-supporting file-like object - containing a JSON document) to a Python object. + """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing + a JSON document) to a Python object. If the contents of ``fp`` is encoded with an ASCII based encoding other than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must Modified: python/trunk/Lib/json/decoder.py ============================================================================== --- python/trunk/Lib/json/decoder.py (original) +++ python/trunk/Lib/json/decoder.py Wed Mar 18 00:19:00 2009 @@ -1,10 +1,10 @@ """Implementation of JSONDecoder """ - import re import sys +import struct -from json.scanner import Scanner, pattern +from json.scanner import make_scanner try: from _json import scanstring as c_scanstring except ImportError: @@ -14,7 +14,14 @@ FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL -NaN, PosInf, NegInf = float('nan'), float('inf'), float('-inf') +def _floatconstants(): + _BYTES = '7FF80000000000007FF0000000000000'.decode('hex') + if sys.byteorder != 'big': + _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1] + nan, inf = struct.unpack('dd', _BYTES) + return nan, inf, -inf + +NaN, PosInf, NegInf = _floatconstants() def linecol(doc, pos): @@ -27,49 +34,26 @@ def errmsg(msg, doc, pos, end=None): + # Note that this function is called from _json lineno, colno = linecol(doc, pos) if end is None: fmt = '{0}: line {1} column {2} (char {3})' return fmt.format(msg, lineno, colno, pos) + #fmt = '%s: line %d column %d (char %d)' + #return fmt % (msg, lineno, colno, pos) endlineno, endcolno = linecol(doc, end) fmt = '{0}: line {1} column {2} - line {3} column {4} (char {5} - {6})' return fmt.format(msg, lineno, colno, endlineno, endcolno, pos, end) + #fmt = '%s: line %d column %d - line %d column %d (char %d - %d)' + #return fmt % (msg, lineno, colno, endlineno, endcolno, pos, end) _CONSTANTS = { '-Infinity': NegInf, 'Infinity': PosInf, 'NaN': NaN, - 'true': True, - 'false': False, - 'null': None, } - -def JSONConstant(match, context, c=_CONSTANTS): - s = match.group(0) - fn = getattr(context, 'parse_constant', None) - if fn is None: - rval = c[s] - else: - rval = fn(s) - return rval, None -pattern('(-?Infinity|NaN|true|false|null)')(JSONConstant) - - -def JSONNumber(match, context): - match = JSONNumber.regex.match(match.string, *match.span()) - integer, frac, exp = match.groups() - if frac or exp: - fn = getattr(context, 'parse_float', None) or float - res = fn(integer + (frac or '') + (exp or '')) - else: - fn = getattr(context, 'parse_int', None) or int - res = fn(integer) - return res, None -pattern(r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?')(JSONNumber) - - STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS) BACKSLASH = { '"': u'"', '\\': u'\\', '/': u'/', @@ -78,8 +62,16 @@ DEFAULT_ENCODING = "utf-8" +def py_scanstring(s, end, encoding=None, strict=True, + _b=BACKSLASH, _m=STRINGCHUNK.match): + """Scan the string s for a JSON string. End is the index of the + character in s after the quote that started the JSON string. + Unescapes all valid JSON string escape sequences and raises ValueError + on attempt to decode an invalid string. If strict is False then literal + control characters are allowed in the string. -def py_scanstring(s, end, encoding=None, strict=True, _b=BACKSLASH, _m=STRINGCHUNK.match): + Returns a tuple of the decoded string and the index of the character in s + after the end quote.""" if encoding is None: encoding = DEFAULT_ENCODING chunks = [] @@ -92,14 +84,18 @@ errmsg("Unterminated string starting at", s, begin)) end = chunk.end() content, terminator = chunk.groups() + # Content is contains zero or more unescaped string characters if content: if not isinstance(content, unicode): content = unicode(content, encoding) _append(content) + # Terminator is the end of string, a literal control character, + # or a backslash denoting that an escape sequence follows if terminator == '"': break elif terminator != '\\': if strict: + #msg = "Invalid control character %r at" % (terminator,) msg = "Invalid control character {0!r} at".format(terminator) raise ValueError(errmsg(msg, s, end)) else: @@ -110,136 +106,157 @@ except IndexError: raise ValueError( errmsg("Unterminated string starting at", s, begin)) + # If not a unicode escape sequence, must be in the lookup table if esc != 'u': try: - m = _b[esc] + char = _b[esc] except KeyError: - msg = "Invalid \\escape: {0!r}".format(esc) + msg = "Invalid \\escape: " + repr(esc) raise ValueError(errmsg(msg, s, end)) end += 1 else: + # Unicode escape sequence esc = s[end + 1:end + 5] next_end = end + 5 - msg = "Invalid \\uXXXX escape" - try: - if len(esc) != 4: - raise ValueError - uni = int(esc, 16) - if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535: - msg = "Invalid \\uXXXX\\uXXXX surrogate pair" - if not s[end + 5:end + 7] == '\\u': - raise ValueError - esc2 = s[end + 7:end + 11] - if len(esc2) != 4: - raise ValueError - uni2 = int(esc2, 16) - uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00)) - next_end += 6 - m = unichr(uni) - except ValueError: + if len(esc) != 4: + msg = "Invalid \\uXXXX escape" raise ValueError(errmsg(msg, s, end)) + uni = int(esc, 16) + # Check for surrogate pair on UCS-4 systems + if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535: + msg = "Invalid \\uXXXX\\uXXXX surrogate pair" + if not s[end + 5:end + 7] == '\\u': + raise ValueError(errmsg(msg, s, end)) + esc2 = s[end + 7:end + 11] + if len(esc2) != 4: + raise ValueError(errmsg(msg, s, end)) + uni2 = int(esc2, 16) + uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00)) + next_end += 6 + char = unichr(uni) end = next_end - _append(m) + # Append the unescaped character + _append(char) return u''.join(chunks), end -# Use speedup -if c_scanstring is not None: - scanstring = c_scanstring -else: - scanstring = py_scanstring - -def JSONString(match, context): - encoding = getattr(context, 'encoding', None) - strict = getattr(context, 'strict', True) - return scanstring(match.string, match.end(), encoding, strict) -pattern(r'"')(JSONString) - - -WHITESPACE = re.compile(r'\s*', FLAGS) +# Use speedup if available +scanstring = c_scanstring or py_scanstring +WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS) +WHITESPACE_STR = ' \t\n\r' -def JSONObject(match, context, _w=WHITESPACE.match): +def JSONObject((s, end), encoding, strict, scan_once, object_hook, + _w=WHITESPACE.match, _ws=WHITESPACE_STR): pairs = {} - s = match.string - end = _w(s, match.end()).end() + # Use a slice to prevent IndexError from being raised, the following + # check will raise a more specific ValueError if the string is empty nextchar = s[end:end + 1] - # Trivial empty object - if nextchar == '}': - return pairs, end + 1 + # Normally we expect nextchar == '"' if nextchar != '"': - raise ValueError(errmsg("Expecting property name", s, end)) + if nextchar in _ws: + end = _w(s, end).end() + nextchar = s[end:end + 1] + # Trivial empty object + if nextchar == '}': + return pairs, end + 1 + elif nextchar != '"': + raise ValueError(errmsg("Expecting property name", s, end)) end += 1 - encoding = getattr(context, 'encoding', None) - strict = getattr(context, 'strict', True) - iterscan = JSONScanner.iterscan while True: key, end = scanstring(s, end, encoding, strict) - end = _w(s, end).end() + + # To skip some function call overhead we optimize the fast paths where + # the JSON key separator is ": " or just ":". if s[end:end + 1] != ':': - raise ValueError(errmsg("Expecting : delimiter", s, end)) - end = _w(s, end + 1).end() + end = _w(s, end).end() + if s[end:end + 1] != ':': + raise ValueError(errmsg("Expecting : delimiter", s, end)) + + end += 1 + try: - value, end = iterscan(s, idx=end, context=context).next() + if s[end] in _ws: + end += 1 + if s[end] in _ws: + end = _w(s, end + 1).end() + except IndexError: + pass + + try: + value, end = scan_once(s, end) except StopIteration: raise ValueError(errmsg("Expecting object", s, end)) pairs[key] = value - end = _w(s, end).end() - nextchar = s[end:end + 1] + + try: + nextchar = s[end] + if nextchar in _ws: + end = _w(s, end + 1).end() + nextchar = s[end] + except IndexError: + nextchar = '' end += 1 + if nextchar == '}': break - if nextchar != ',': + elif nextchar != ',': raise ValueError(errmsg("Expecting , delimiter", s, end - 1)) - end = _w(s, end).end() - nextchar = s[end:end + 1] + + try: + nextchar = s[end] + if nextchar in _ws: + end += 1 + nextchar = s[end] + if nextchar in _ws: + end = _w(s, end + 1).end() + nextchar = s[end] + except IndexError: + nextchar = '' + end += 1 if nextchar != '"': raise ValueError(errmsg("Expecting property name", s, end - 1)) - object_hook = getattr(context, 'object_hook', None) + if object_hook is not None: pairs = object_hook(pairs) return pairs, end -pattern(r'{')(JSONObject) - -def JSONArray(match, context, _w=WHITESPACE.match): +def JSONArray((s, end), scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR): values = [] - s = match.string - end = _w(s, match.end()).end() - # Look-ahead for trivial empty array nextchar = s[end:end + 1] + if nextchar in _ws: + end = _w(s, end + 1).end() + nextchar = s[end:end + 1] + # Look-ahead for trivial empty array if nextchar == ']': return values, end + 1 - iterscan = JSONScanner.iterscan + _append = values.append while True: try: - value, end = iterscan(s, idx=end, context=context).next() + value, end = scan_once(s, end) except StopIteration: raise ValueError(errmsg("Expecting object", s, end)) - values.append(value) - end = _w(s, end).end() + _append(value) nextchar = s[end:end + 1] + if nextchar in _ws: + end = _w(s, end + 1).end() + nextchar = s[end:end + 1] end += 1 if nextchar == ']': break - if nextchar != ',': + elif nextchar != ',': raise ValueError(errmsg("Expecting , delimiter", s, end)) - end = _w(s, end).end() - return values, end -pattern(r'\[')(JSONArray) - - -ANYTHING = [ - JSONObject, - JSONArray, - JSONString, - JSONConstant, - JSONNumber, -] -JSONScanner = Scanner(ANYTHING) + try: + if s[end] in _ws: + end += 1 + if s[end] in _ws: + end = _w(s, end + 1).end() + except IndexError: + pass + return values, end class JSONDecoder(object): """Simple JSON decoder @@ -268,10 +285,8 @@ It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as their corresponding ``float`` values, which is outside the JSON spec. - """ - _scanner = Scanner(ANYTHING) - __all__ = ['__init__', 'decode', 'raw_decode'] + """ def __init__(self, encoding=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, strict=True): @@ -282,8 +297,8 @@ Note that currently only encodings that are a superset of ASCII work, strings of other encodings should be passed in as ``unicode``. - ``object_hook``, if specified, will be called with the result of - every JSON object decoded and its return value will be used in + ``object_hook``, if specified, will be called with the result + of every JSON object decoded and its return value will be used in place of the given ``dict``. This can be used to provide custom deserializations (e.g. to support JSON-RPC class hinting). @@ -298,21 +313,24 @@ for JSON integers (e.g. float). ``parse_constant``, if specified, will be called with one of the - following strings: -Infinity, Infinity, NaN, null, true, false. + following strings: -Infinity, Infinity, NaN. This can be used to raise an exception if invalid JSON numbers are encountered. """ self.encoding = encoding self.object_hook = object_hook - self.parse_float = parse_float - self.parse_int = parse_int - self.parse_constant = parse_constant + self.parse_float = parse_float or float + self.parse_int = parse_int or int + self.parse_constant = parse_constant or _CONSTANTS.__getitem__ self.strict = strict + self.parse_object = JSONObject + self.parse_array = JSONArray + self.parse_string = scanstring + self.scan_once = make_scanner(self) def decode(self, s, _w=WHITESPACE.match): - """ - Return the Python representation of ``s`` (a ``str`` or ``unicode`` + """Return the Python representation of ``s`` (a ``str`` or ``unicode`` instance containing a JSON document) """ @@ -322,18 +340,17 @@ raise ValueError(errmsg("Extra data", s, end, len(s))) return obj - def raw_decode(self, s, **kw): - """Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning - with a JSON document) and return a 2-tuple of the Python + def raw_decode(self, s, idx=0): + """Decode a JSON document from ``s`` (a ``str`` or ``unicode`` + beginning with a JSON document) and return a 2-tuple of the Python representation and the index in ``s`` where the document ended. This can be used to decode a JSON document from a string that may have extraneous data at the end. """ - kw.setdefault('context', self) try: - obj, end = self._scanner.iterscan(s, **kw).next() + obj, end = self.scan_once(s, idx) except StopIteration: raise ValueError("No JSON object could be decoded") return obj, end Modified: python/trunk/Lib/json/encoder.py ============================================================================== --- python/trunk/Lib/json/encoder.py (original) +++ python/trunk/Lib/json/encoder.py Wed Mar 18 00:19:00 2009 @@ -1,15 +1,15 @@ """Implementation of JSONEncoder """ - import re -import math try: from _json import encode_basestring_ascii as c_encode_basestring_ascii except ImportError: c_encode_basestring_ascii = None - -__all__ = ['JSONEncoder'] +try: + from _json import make_encoder as c_make_encoder +except ImportError: + c_make_encoder = None ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]') ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])') @@ -25,30 +25,12 @@ } for i in range(0x20): ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i)) + #ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) +# Assume this produces an infinity on all machines (probably not guaranteed) +INFINITY = float('1e66666') FLOAT_REPR = repr -def floatstr(o, allow_nan=True): - # Check for specials. Note that this type of test is processor- and/or - # platform-specific, so do tests which don't depend on the internals. - - if math.isnan(o): - text = 'NaN' - elif math.isinf(o): - if math.copysign(1., o) == 1.: - text = 'Infinity' - else: - text = '-Infinity' - else: - return FLOAT_REPR(o) - - if not allow_nan: - msg = "Out of range float values are not JSON compliant: " + repr(o) - raise ValueError(msg) - - return text - - def encode_basestring(s): """Return a JSON representation of a Python string @@ -59,6 +41,9 @@ def py_encode_basestring_ascii(s): + """Return an ASCII-only JSON representation of a Python string + + """ if isinstance(s, str) and HAS_UTF8.search(s) is not None: s = s.decode('utf-8') def replace(match): @@ -69,20 +54,19 @@ n = ord(s) if n < 0x10000: return '\\u{0:04x}'.format(n) + #return '\\u%04x' % (n,) else: # surrogate pair n -= 0x10000 s1 = 0xd800 | ((n >> 10) & 0x3ff) s2 = 0xdc00 | (n & 0x3ff) return '\\u{0:04x}\\u{1:04x}'.format(s1, s2) + #return '\\u%04x\\u%04x' % (s1, s2) return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"' -if c_encode_basestring_ascii is not None: - encode_basestring_ascii = c_encode_basestring_ascii -else: - encode_basestring_ascii = py_encode_basestring_ascii - +encode_basestring_ascii = ( + c_encode_basestring_ascii or py_encode_basestring_ascii) class JSONEncoder(object): """Extensible JSON encoder for Python data structures. @@ -113,7 +97,6 @@ implementation (to raise ``TypeError``). """ - __all__ = ['__init__', 'default', 'encode', 'iterencode'] item_separator = ', ' key_separator = ': ' def __init__(self, skipkeys=False, ensure_ascii=True, @@ -121,25 +104,25 @@ indent=None, separators=None, encoding='utf-8', default=None): """Constructor for JSONEncoder, with sensible defaults. - If skipkeys is False, then it is a TypeError to attempt + If skipkeys is false, then it is a TypeError to attempt encoding of keys that are not str, int, long, float or None. If skipkeys is True, such items are simply skipped. - If ensure_ascii is True, the output is guaranteed to be str + If ensure_ascii is true, the output is guaranteed to be str objects with all incoming unicode characters escaped. If ensure_ascii is false, the output will be unicode object. - If check_circular is True, then lists, dicts, and custom encoded + If check_circular is true, then lists, dicts, and custom encoded objects will be checked for circular references during encoding to prevent an infinite recursion (which would cause an OverflowError). Otherwise, no such check takes place. - If allow_nan is True, then NaN, Infinity, and -Infinity will be + If allow_nan is true, then NaN, Infinity, and -Infinity will be encoded as such. This behavior is not JSON specification compliant, but is consistent with most JavaScript based encoders and decoders. Otherwise, it will be a ValueError to encode such floats. - If sort_keys is True, then the output of dictionaries will be + If sort_keys is true, then the output of dictionaries will be sorted by key; this is useful for regression tests to ensure that JSON serializations can be compared on a day-to-day basis. @@ -161,23 +144,144 @@ The default is UTF-8. """ + self.skipkeys = skipkeys self.ensure_ascii = ensure_ascii self.check_circular = check_circular self.allow_nan = allow_nan self.sort_keys = sort_keys self.indent = indent - self.current_indent_level = 0 if separators is not None: self.item_separator, self.key_separator = separators if default is not None: self.default = default self.encoding = encoding - def _newline_indent(self): - return '\n' + (' ' * (self.indent * self.current_indent_level)) + def default(self, o): + """Implement this method in a subclass such that it returns + a serializable object for ``o``, or calls the base implementation + (to raise a ``TypeError``). + + For example, to support arbitrary iterators, you could + implement default like this:: + + def default(self, o): + try: + iterable = iter(o) + except TypeError: + pass + else: + return list(iterable) + return JSONEncoder.default(self, o) + + """ + raise TypeError(repr(o) + " is not JSON serializable") - def _iterencode_list(self, lst, markers=None): + def encode(self, o): + """Return a JSON string representation of a Python data structure. + + >>> JSONEncoder().encode({"foo": ["bar", "baz"]}) + '{"foo": ["bar", "baz"]}' + + """ + # This is for extremely simple cases and benchmarks. + if isinstance(o, basestring): + if isinstance(o, str): + _encoding = self.encoding + if (_encoding is not None + and not (_encoding == 'utf-8')): + o = o.decode(_encoding) + if self.ensure_ascii: + return encode_basestring_ascii(o) + else: + return encode_basestring(o) + # This doesn't pass the iterator directly to ''.join() because the + # exceptions aren't as detailed. The list call should be roughly + # equivalent to the PySequence_Fast that ''.join() would do. + chunks = self.iterencode(o, _one_shot=True) + if not isinstance(chunks, (list, tuple)): + chunks = list(chunks) + return ''.join(chunks) + + def iterencode(self, o, _one_shot=False): + """Encode the given object and yield each string + representation as available. + + For example:: + + for chunk in JSONEncoder().iterencode(bigobject): + mysocket.write(chunk) + + """ + if self.check_circular: + markers = {} + else: + markers = None + if self.ensure_ascii: + _encoder = encode_basestring_ascii + else: + _encoder = encode_basestring + if self.encoding != 'utf-8': + def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding): + if isinstance(o, str): + o = o.decode(_encoding) + return _orig_encoder(o) + + def floatstr(o, allow_nan=self.allow_nan, + _repr=FLOAT_REPR, _inf=INFINITY, _neginf=-INFINITY): + # Check for specials. Note that this type of test is processor + # and/or platform-specific, so do tests which don't depend on the + # internals. + + if o != o: + text = 'NaN' + elif o == _inf: + text = 'Infinity' + elif o == _neginf: + text = '-Infinity' + else: + return _repr(o) + + if not allow_nan: + raise ValueError( + "Out of range float values are not JSON compliant: " + + repr(o)) + + return text + + + if (_one_shot and c_make_encoder is not None + and not self.indent and not self.sort_keys): + _iterencode = c_make_encoder( + markers, self.default, _encoder, self.indent, + self.key_separator, self.item_separator, self.sort_keys, + self.skipkeys, self.allow_nan) + else: + _iterencode = _make_iterencode( + markers, self.default, _encoder, self.indent, floatstr, + self.key_separator, self.item_separator, self.sort_keys, + self.skipkeys, _one_shot) + return _iterencode(o, 0) + +def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, + _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot, + ## HACK: hand-optimized bytecode; turn globals into locals + False=False, + True=True, + ValueError=ValueError, + basestring=basestring, + dict=dict, + float=float, + id=id, + int=int, + isinstance=isinstance, + list=list, + long=long, + str=str, + tuple=tuple, + ): + + def _iterencode_list(lst, _current_indent_level): if not lst: yield '[]' return @@ -186,31 +290,51 @@ if markerid in markers: raise ValueError("Circular reference detected") markers[markerid] = lst - yield '[' - if self.indent is not None: - self.current_indent_level += 1 - newline_indent = self._newline_indent() - separator = self.item_separator + newline_indent - yield newline_indent + buf = '[' + if _indent is not None: + _current_indent_level += 1 + newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) + separator = _item_separator + newline_indent + buf += newline_indent else: newline_indent = None - separator = self.item_separator + separator = _item_separator first = True for value in lst: if first: first = False else: - yield separator - for chunk in self._iterencode(value, markers): - yield chunk + buf = separator + if isinstance(value, basestring): + yield buf + _encoder(value) + elif value is None: + yield buf + 'null' + elif value is True: + yield buf + 'true' + elif value is False: + yield buf + 'false' + elif isinstance(value, (int, long)): + yield buf + str(value) + elif isinstance(value, float): + yield buf + _floatstr(value) + else: + yield buf + if isinstance(value, (list, tuple)): + chunks = _iterencode_list(value, _current_indent_level) + elif isinstance(value, dict): + chunks = _iterencode_dict(value, _current_indent_level) + else: + chunks = _iterencode(value, _current_indent_level) + for chunk in chunks: + yield chunk if newline_indent is not None: - self.current_indent_level -= 1 - yield self._newline_indent() + _current_indent_level -= 1 + yield '\n' + (' ' * (_indent * _current_indent_level)) yield ']' if markers is not None: del markers[markerid] - def _iterencode_dict(self, dct, markers=None): + def _iterencode_dict(dct, _current_indent_level): if not dct: yield '{}' return @@ -220,78 +344,76 @@ raise ValueError("Circular reference detected") markers[markerid] = dct yield '{' - key_separator = self.key_separator - if self.indent is not None: - self.current_indent_level += 1 - newline_indent = self._newline_indent() - item_separator = self.item_separator + newline_indent + if _indent is not None: + _current_indent_level += 1 + newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) + item_separator = _item_separator + newline_indent yield newline_indent else: newline_indent = None - item_separator = self.item_separator + item_separator = _item_separator first = True - if self.ensure_ascii: - encoder = encode_basestring_ascii - else: - encoder = encode_basestring - allow_nan = self.allow_nan - if self.sort_keys: - keys = dct.keys() - keys.sort() - items = [(k, dct[k]) for k in keys] + if _sort_keys: + items = dct.items() + items.sort(key=lambda kv: kv[0]) else: items = dct.iteritems() - _encoding = self.encoding - _do_decode = (_encoding is not None - and not (_encoding == 'utf-8')) for key, value in items: - if isinstance(key, str): - if _do_decode: - key = key.decode(_encoding) - elif isinstance(key, basestring): + if isinstance(key, basestring): pass # JavaScript is weakly typed for these, so it makes sense to # also allow them. Many encoders seem to do something like this. elif isinstance(key, float): - key = floatstr(key, allow_nan) - elif isinstance(key, (int, long)): - key = str(key) + key = _floatstr(key) elif key is True: key = 'true' elif key is False: key = 'false' elif key is None: key = 'null' - elif self.skipkeys: + elif isinstance(key, (int, long)): + key = str(key) + elif _skipkeys: continue else: - raise TypeError("key {0!r} is not a string".format(key)) + raise TypeError("key " + repr(key) + " is not a string") if first: first = False else: yield item_separator - yield encoder(key) - yield key_separator - for chunk in self._iterencode(value, markers): - yield chunk + yield _encoder(key) + yield _key_separator + if isinstance(value, basestring): + yield _encoder(value) + elif value is None: + yield 'null' + elif value is True: + yield 'true' + elif value is False: + yield 'false' + elif isinstance(value, (int, long)): + yield str(value) + elif isinstance(value, float): + yield _floatstr(value) + else: + if isinstance(value, (list, tuple)): + chunks = _iterencode_list(value, _current_indent_level) + elif isinstance(value, dict): + chunks = _iterencode_dict(value, _current_indent_level) + else: + chunks = _iterencode(value, _current_indent_level) + for chunk in chunks: + yield chunk if newline_indent is not None: - self.current_indent_level -= 1 - yield self._newline_indent() + _current_indent_level -= 1 + yield '\n' + (' ' * (_indent * _current_indent_level)) yield '}' if markers is not None: del markers[markerid] - def _iterencode(self, o, markers=None): + def _iterencode(o, _current_indent_level): if isinstance(o, basestring): - if self.ensure_ascii: - encoder = encode_basestring_ascii - else: - encoder = encode_basestring - _encoding = self.encoding - if (_encoding is not None and isinstance(o, str) - and not (_encoding == 'utf-8')): - o = o.decode(_encoding) - yield encoder(o) + yield _encoder(o) elif o is None: yield 'null' elif o is True: @@ -301,12 +423,12 @@ elif isinstance(o, (int, long)): yield str(o) elif isinstance(o, float): - yield floatstr(o, self.allow_nan) + yield _floatstr(o) elif isinstance(o, (list, tuple)): - for chunk in self._iterencode_list(o, markers): + for chunk in _iterencode_list(o, _current_indent_level): yield chunk elif isinstance(o, dict): - for chunk in self._iterencode_dict(o, markers): + for chunk in _iterencode_dict(o, _current_indent_level): yield chunk else: if markers is not None: @@ -314,71 +436,10 @@ if markerid in markers: raise ValueError("Circular reference detected") markers[markerid] = o - for chunk in self._iterencode_default(o, markers): + o = _default(o) + for chunk in _iterencode(o, _current_indent_level): yield chunk if markers is not None: del markers[markerid] - def _iterencode_default(self, o, markers=None): - newobj = self.default(o) - return self._iterencode(newobj, markers) - - def default(self, o): - """Implement this method in a subclass such that it returns a serializable - object for ``o``, or calls the base implementation (to raise a - ``TypeError``). - - For example, to support arbitrary iterators, you could implement - default like this:: - - def default(self, o): - try: - iterable = iter(o) - except TypeError: - pass - else: - return list(iterable) - return JSONEncoder.default(self, o) - - """ - raise TypeError(repr(o) + " is not JSON serializable") - - def encode(self, o): - """Return a JSON string representation of a Python data structure. - - >>> JSONEncoder().encode({"foo": ["bar", "baz"]}) - '{"foo": ["bar", "baz"]}' - - """ - # This is for extremely simple cases and benchmarks. - if isinstance(o, basestring): - if isinstance(o, str): - _encoding = self.encoding - if (_encoding is not None - and not (_encoding == 'utf-8')): - o = o.decode(_encoding) - if self.ensure_ascii: - return encode_basestring_ascii(o) - else: - return encode_basestring(o) - # This doesn't pass the iterator directly to ''.join() because the - # exceptions aren't as detailed. The list call should be roughly - # equivalent to the PySequence_Fast that ''.join() would do. - chunks = list(self.iterencode(o)) - return ''.join(chunks) - - def iterencode(self, o): - """Encode the given object and yield each string representation as - available. - - For example:: - - for chunk in JSONEncoder().iterencode(bigobject): - mysocket.write(chunk) - - """ - if self.check_circular: - markers = {} - else: - markers = None - return self._iterencode(o, markers) + return _iterencode Modified: python/trunk/Lib/json/scanner.py ============================================================================== --- python/trunk/Lib/json/scanner.py (original) +++ python/trunk/Lib/json/scanner.py Wed Mar 18 00:19:00 2009 @@ -1,69 +1,66 @@ -"""Iterator based sre token scanner - +"""JSON token scanner """ - import re -import sre_parse -import sre_compile -import sre_constants - -from re import VERBOSE, MULTILINE, DOTALL -from sre_constants import BRANCH, SUBPATTERN - -__all__ = ['Scanner', 'pattern'] - -FLAGS = (VERBOSE | MULTILINE | DOTALL) - -class Scanner(object): - def __init__(self, lexicon, flags=FLAGS): - self.actions = [None] - # Combine phrases into a compound pattern - s = sre_parse.Pattern() - s.flags = flags - p = [] - for idx, token in enumerate(lexicon): - phrase = token.pattern - try: - subpattern = sre_parse.SubPattern(s, - [(SUBPATTERN, (idx + 1, sre_parse.parse(phrase, flags)))]) - except sre_constants.error: - raise - p.append(subpattern) - self.actions.append(token) - - s.groups = len(p) + 1 # NOTE(guido): Added to make SRE validation work - p = sre_parse.SubPattern(s, [(BRANCH, (None, p))]) - self.scanner = sre_compile.compile(p) - - def iterscan(self, string, idx=0, context=None): - """Yield match, end_idx for each match - - """ - match = self.scanner.scanner(string, idx).match - actions = self.actions - lastend = idx - end = len(string) - while True: - m = match() - if m is None: - break - matchbegin, matchend = m.span() - if lastend == matchend: - break - action = actions[m.lastindex] - if action is not None: - rval, next_pos = action(m, context) - if next_pos is not None and next_pos != matchend: - # "fast forward" the scanner - matchend = next_pos - match = self.scanner.scanner(string, matchend).match - yield rval, matchend - lastend = matchend - - -def pattern(pattern, flags=FLAGS): - def decorator(fn): - fn.pattern = pattern - fn.regex = re.compile(pattern, flags) - return fn - return decorator +try: + from _json import make_scanner as c_make_scanner +except ImportError: + c_make_scanner = None + +__all__ = ['make_scanner'] + +NUMBER_RE = re.compile( + r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?', + (re.VERBOSE | re.MULTILINE | re.DOTALL)) + +def py_make_scanner(context): + parse_object = context.parse_object + parse_array = context.parse_array + parse_string = context.parse_string + match_number = NUMBER_RE.match + encoding = context.encoding + strict = context.strict + parse_float = context.parse_float + parse_int = context.parse_int + parse_constant = context.parse_constant + object_hook = context.object_hook + + def _scan_once(string, idx): + try: + nextchar = string[idx] + except IndexError: + raise StopIteration + + if nextchar == '"': + return parse_string(string, idx + 1, encoding, strict) + elif nextchar == '{': + return parse_object((string, idx + 1), encoding, strict, + _scan_once, object_hook) + elif nextchar == '[': + return parse_array((string, idx + 1), _scan_once) + elif nextchar == 'n' and string[idx:idx + 4] == 'null': + return None, idx + 4 + elif nextchar == 't' and string[idx:idx + 4] == 'true': + return True, idx + 4 + elif nextchar == 'f' and string[idx:idx + 5] == 'false': + return False, idx + 5 + + m = match_number(string, idx) + if m is not None: + integer, frac, exp = m.groups() + if frac or exp: + res = parse_float(integer + (frac or '') + (exp or '')) + else: + res = parse_int(integer) + return res, m.end() + elif nextchar == 'N' and string[idx:idx + 3] == 'NaN': + return parse_constant('NaN'), idx + 3 + elif nextchar == 'I' and string[idx:idx + 8] == 'Infinity': + return parse_constant('Infinity'), idx + 8 + elif nextchar == '-' and string[idx:idx + 9] == '-Infinity': + return parse_constant('-Infinity'), idx + 9 + else: + raise StopIteration + + return _scan_once + +make_scanner = c_make_scanner or py_make_scanner Added: python/trunk/Lib/json/tests/test_check_circular.py ============================================================================== --- (empty file) +++ python/trunk/Lib/json/tests/test_check_circular.py Wed Mar 18 00:19:00 2009 @@ -0,0 +1,30 @@ +from unittest import TestCase +import json + +def default_iterable(obj): + return list(obj) + +class TestCheckCircular(TestCase): + def test_circular_dict(self): + dct = {} + dct['a'] = dct + self.assertRaises(ValueError, json.dumps, dct) + + def test_circular_list(self): + lst = [] + lst.append(lst) + self.assertRaises(ValueError, json.dumps, lst) + + def test_circular_composite(self): + dct2 = {} + dct2['a'] = [] + dct2['a'].append(dct2) + self.assertRaises(ValueError, json.dumps, dct2) + + def test_circular_default(self): + json.dumps([set()], default=default_iterable) + self.assertRaises(TypeError, json.dumps, [set()]) + + def test_circular_off_default(self): + json.dumps([set()], default=default_iterable, check_circular=False) + self.assertRaises(TypeError, json.dumps, [set()], check_circular=False) Modified: python/trunk/Lib/json/tests/test_decode.py ============================================================================== --- python/trunk/Lib/json/tests/test_decode.py (original) +++ python/trunk/Lib/json/tests/test_decode.py Wed Mar 18 00:19:00 2009 @@ -13,3 +13,10 @@ rval = json.loads('1', parse_int=float) self.assert_(isinstance(rval, float)) self.assertEquals(rval, 1.0) + + def test_decoder_optimizations(self): + # Several optimizations were made that skip over calls to + # the whitespace regex, so this test is designed to try and + # exercise the uncommon cases. The array cases are already covered. + rval = json.loads('{ "key" : "value" , "k":"v" }') + self.assertEquals(rval, {"key":"value", "k":"v"}) Modified: python/trunk/Lib/json/tests/test_dump.py ============================================================================== --- python/trunk/Lib/json/tests/test_dump.py (original) +++ python/trunk/Lib/json/tests/test_dump.py Wed Mar 18 00:19:00 2009 @@ -11,3 +11,11 @@ def test_dumps(self): self.assertEquals(json.dumps({}), '{}') + + def test_encode_truefalse(self): + self.assertEquals(json.dumps( + {True: False, False: True}, sort_keys=True), + '{"false": true, "true": false}') + self.assertEquals(json.dumps( + {2: 3.0, 4.0: 5L, False: 1, 6L: True, "7": 0}, sort_keys=True), + '{"false": 1, "2": 3.0, "4.0": 5, "6": true, "7": 0}') Modified: python/trunk/Lib/json/tests/test_encode_basestring_ascii.py ============================================================================== --- python/trunk/Lib/json/tests/test_encode_basestring_ascii.py (original) +++ python/trunk/Lib/json/tests/test_encode_basestring_ascii.py Wed Mar 18 00:19:00 2009 @@ -26,10 +26,14 @@ self._test_encode_basestring_ascii(json.encoder.py_encode_basestring_ascii) def test_c_encode_basestring_ascii(self): + if not json.encoder.c_encode_basestring_ascii: + return self._test_encode_basestring_ascii(json.encoder.c_encode_basestring_ascii) def _test_encode_basestring_ascii(self, encode_basestring_ascii): fname = encode_basestring_ascii.__name__ for input_string, expect in CASES: result = encode_basestring_ascii(input_string) - self.assertEquals(result, expect) + self.assertEquals(result, expect, + '{0!r} != {1!r} for {2}({3!r})'.format( + result, expect, fname, input_string)) Modified: python/trunk/Lib/json/tests/test_fail.py ============================================================================== --- python/trunk/Lib/json/tests/test_fail.py (original) +++ python/trunk/Lib/json/tests/test_fail.py Wed Mar 18 00:19:00 2009 @@ -73,4 +73,4 @@ except ValueError: pass else: - self.fail("Expected failure for fail%d.json: %r" % (idx, doc)) + self.fail("Expected failure for fail{0}.json: {1!r}".format(idx, doc)) Modified: python/trunk/Lib/json/tests/test_float.py ============================================================================== --- python/trunk/Lib/json/tests/test_float.py (original) +++ python/trunk/Lib/json/tests/test_float.py Wed Mar 18 00:19:00 2009 @@ -5,5 +5,11 @@ class TestFloat(TestCase): def test_floats(self): - for num in [1617161771.7650001, math.pi, math.pi**100, math.pi**-100]: + for num in [1617161771.7650001, math.pi, math.pi**100, math.pi**-100, 3.1]: self.assertEquals(float(json.dumps(num)), num) + self.assertEquals(json.loads(json.dumps(num)), num) + + def test_ints(self): + for num in [1, 1L, 1<<32, 1<<64]: + self.assertEquals(json.dumps(num), str(num)) + self.assertEquals(int(json.dumps(num)), num) Modified: python/trunk/Lib/json/tests/test_unicode.py ============================================================================== --- python/trunk/Lib/json/tests/test_unicode.py (original) +++ python/trunk/Lib/json/tests/test_unicode.py Wed Mar 18 00:19:00 2009 @@ -51,5 +51,14 @@ def test_unicode_decode(self): for i in range(0, 0xd7ff): u = unichr(i) - js = '"\\u{0:04x}"'.format(i) - self.assertEquals(json.loads(js), u) + s = '"\\u{0:04x}"'.format(i) + self.assertEquals(json.loads(s), u) + + def test_default_encoding(self): + self.assertEquals(json.loads(u'{"a": "\xe9"}'.encode('utf-8')), + {'a': u'\xe9'}) + + def test_unicode_preservation(self): + self.assertEquals(type(json.loads(u'""')), unicode) + self.assertEquals(type(json.loads(u'"a"')), unicode) + self.assertEquals(type(json.loads(u'["a"]')[0]), unicode) Modified: python/trunk/Lib/json/tool.py ============================================================================== --- python/trunk/Lib/json/tool.py (original) +++ python/trunk/Lib/json/tool.py Wed Mar 18 00:19:00 2009 @@ -2,11 +2,11 @@ Usage:: - $ echo '{"json":"obj"}' | python -mjson.tool + $ echo '{"json":"obj"}' | python -m json.tool { "json": "obj" } - $ echo '{ 1.2:3.4}' | python -mjson.tool + $ echo '{ 1.2:3.4}' | python -m json.tool Expecting property name: line 1 column 2 (char 2) """ @@ -24,7 +24,7 @@ infile = open(sys.argv[1], 'rb') outfile = open(sys.argv[2], 'wb') else: - raise SystemExit("{0} [infile [outfile]]".format(sys.argv[0])) + raise SystemExit(sys.argv[0] + " [infile [outfile]]") try: obj = json.load(infile) except ValueError, e: Modified: python/trunk/Modules/_json.c ============================================================================== --- python/trunk/Modules/_json.c (original) +++ python/trunk/Modules/_json.c Wed Mar 18 00:19:00 2009 @@ -1,19 +1,164 @@ #include "Python.h" +#include "structmember.h" +#if PY_VERSION_HEX < 0x02060000 && !defined(Py_TYPE) +#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) +#endif +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#define PyInt_FromSsize_t PyInt_FromLong +#define PyInt_AsSsize_t PyInt_AsLong +#endif +#ifndef Py_IS_FINITE +#define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X)) +#endif + +#ifdef __GNUC__ +#define UNUSED __attribute__((__unused__)) +#else +#define UNUSED +#endif #define DEFAULT_ENCODING "utf-8" + +#define PyScanner_Check(op) PyObject_TypeCheck(op, &PyScannerType) +#define PyScanner_CheckExact(op) (Py_TYPE(op) == &PyScannerType) +#define PyEncoder_Check(op) PyObject_TypeCheck(op, &PyEncoderType) +#define PyEncoder_CheckExact(op) (Py_TYPE(op) == &PyEncoderType) + +static PyTypeObject PyScannerType; +static PyTypeObject PyEncoderType; + +typedef struct _PyScannerObject { + PyObject_HEAD + PyObject *encoding; + PyObject *strict; + PyObject *object_hook; + PyObject *parse_float; + PyObject *parse_int; + PyObject *parse_constant; +} PyScannerObject; + +static PyMemberDef scanner_members[] = { + {"encoding", T_OBJECT, offsetof(PyScannerObject, encoding), READONLY, "encoding"}, + {"strict", T_OBJECT, offsetof(PyScannerObject, strict), READONLY, "strict"}, + {"object_hook", T_OBJECT, offsetof(PyScannerObject, object_hook), READONLY, "object_hook"}, + {"parse_float", T_OBJECT, offsetof(PyScannerObject, parse_float), READONLY, "parse_float"}, + {"parse_int", T_OBJECT, offsetof(PyScannerObject, parse_int), READONLY, "parse_int"}, + {"parse_constant", T_OBJECT, offsetof(PyScannerObject, parse_constant), READONLY, "parse_constant"}, + {NULL} +}; + +typedef struct _PyEncoderObject { + PyObject_HEAD + PyObject *markers; + PyObject *defaultfn; + PyObject *encoder; + PyObject *indent; + PyObject *key_separator; + PyObject *item_separator; + PyObject *sort_keys; + PyObject *skipkeys; + int fast_encode; + int allow_nan; +} PyEncoderObject; + +static PyMemberDef encoder_members[] = { + {"markers", T_OBJECT, offsetof(PyEncoderObject, markers), READONLY, "markers"}, + {"default", T_OBJECT, offsetof(PyEncoderObject, defaultfn), READONLY, "default"}, + {"encoder", T_OBJECT, offsetof(PyEncoderObject, encoder), READONLY, "encoder"}, + {"indent", T_OBJECT, offsetof(PyEncoderObject, indent), READONLY, "indent"}, + {"key_separator", T_OBJECT, offsetof(PyEncoderObject, key_separator), READONLY, "key_separator"}, + {"item_separator", T_OBJECT, offsetof(PyEncoderObject, item_separator), READONLY, "item_separator"}, + {"sort_keys", T_OBJECT, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"}, + {"skipkeys", T_OBJECT, offsetof(PyEncoderObject, skipkeys), READONLY, "skipkeys"}, + {NULL} +}; + +static Py_ssize_t +ascii_escape_char(Py_UNICODE c, char *output, Py_ssize_t chars); +static PyObject * +ascii_escape_unicode(PyObject *pystr); +static PyObject * +ascii_escape_str(PyObject *pystr); +static PyObject * +py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr); +void init_json(void); +static PyObject * +scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr); +static PyObject * +scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr); +static PyObject * +_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx); +static PyObject * +scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds); +static int +scanner_init(PyObject *self, PyObject *args, PyObject *kwds); +static void +scanner_dealloc(PyObject *self); +static int +scanner_clear(PyObject *self); +static PyObject * +encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds); +static int +encoder_init(PyObject *self, PyObject *args, PyObject *kwds); +static void +encoder_dealloc(PyObject *self); +static int +encoder_clear(PyObject *self); +static int +encoder_listencode_list(PyEncoderObject *s, PyObject *rval, PyObject *seq, Py_ssize_t indent_level); +static int +encoder_listencode_obj(PyEncoderObject *s, PyObject *rval, PyObject *obj, Py_ssize_t indent_level); +static int +encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ssize_t indent_level); +static PyObject * +_encoded_const(PyObject *const); +static void +raise_errmsg(char *msg, PyObject *s, Py_ssize_t end); +static PyObject * +encoder_encode_string(PyEncoderObject *s, PyObject *obj); +static int +_convertPyInt_AsSsize_t(PyObject *o, Py_ssize_t *size_ptr); +static PyObject * +_convertPyInt_FromSsize_t(Py_ssize_t *size_ptr); +static PyObject * +encoder_encode_float(PyEncoderObject *s, PyObject *obj); + #define S_CHAR(c) (c >= ' ' && c <= '~' && c != '\\' && c != '"') -#define MIN_EXPANSION 6 +#define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r')) +#define MIN_EXPANSION 6 #ifdef Py_UNICODE_WIDE #define MAX_EXPANSION (2 * MIN_EXPANSION) #else #define MAX_EXPANSION MIN_EXPANSION #endif +static int +_convertPyInt_AsSsize_t(PyObject *o, Py_ssize_t *size_ptr) +{ + /* PyObject to Py_ssize_t converter */ + *size_ptr = PyInt_AsSsize_t(o); + if (*size_ptr == -1 && PyErr_Occurred()); + return 1; + return 0; +} + +static PyObject * +_convertPyInt_FromSsize_t(Py_ssize_t *size_ptr) +{ + /* Py_ssize_t to PyObject converter */ + return PyInt_FromSsize_t(*size_ptr); +} + static Py_ssize_t ascii_escape_char(Py_UNICODE c, char *output, Py_ssize_t chars) { - Py_UNICODE x; + /* Escape unicode code point c to ASCII escape sequences + in char *output. output must have at least 12 bytes unused to + accommodate an escaped surrogate pair "\uXXXX\uXXXX" */ output[chars++] = '\\'; switch (c) { case '\\': output[chars++] = (char)c; break; @@ -30,27 +175,19 @@ Py_UNICODE v = c - 0x10000; c = 0xd800 | ((v >> 10) & 0x3ff); output[chars++] = 'u'; - x = (c & 0xf000) >> 12; - output[chars++] = (x < 10) ? '0' + x : 'a' + (x - 10); - x = (c & 0x0f00) >> 8; - output[chars++] = (x < 10) ? '0' + x : 'a' + (x - 10); - x = (c & 0x00f0) >> 4; - output[chars++] = (x < 10) ? '0' + x : 'a' + (x - 10); - x = (c & 0x000f); - output[chars++] = (x < 10) ? '0' + x : 'a' + (x - 10); + output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf]; + output[chars++] = "0123456789abcdef"[(c >> 8) & 0xf]; + output[chars++] = "0123456789abcdef"[(c >> 4) & 0xf]; + output[chars++] = "0123456789abcdef"[(c ) & 0xf]; c = 0xdc00 | (v & 0x3ff); output[chars++] = '\\'; } #endif output[chars++] = 'u'; - x = (c & 0xf000) >> 12; - output[chars++] = (x < 10) ? '0' + x : 'a' + (x - 10); - x = (c & 0x0f00) >> 8; - output[chars++] = (x < 10) ? '0' + x : 'a' + (x - 10); - x = (c & 0x00f0) >> 4; - output[chars++] = (x < 10) ? '0' + x : 'a' + (x - 10); - x = (c & 0x000f); - output[chars++] = (x < 10) ? '0' + x : 'a' + (x - 10); + output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf]; + output[chars++] = "0123456789abcdef"[(c >> 8) & 0xf]; + output[chars++] = "0123456789abcdef"[(c >> 4) & 0xf]; + output[chars++] = "0123456789abcdef"[(c ) & 0xf]; } return chars; } @@ -58,9 +195,11 @@ static PyObject * ascii_escape_unicode(PyObject *pystr) { + /* Take a PyUnicode pystr and return a new ASCII-only escaped PyString */ Py_ssize_t i; Py_ssize_t input_chars; Py_ssize_t output_size; + Py_ssize_t max_output_size; Py_ssize_t chars; PyObject *rval; char *output; @@ -68,8 +207,10 @@ input_chars = PyUnicode_GET_SIZE(pystr); input_unicode = PyUnicode_AS_UNICODE(pystr); + /* One char input can be up to 6 chars output, estimate 4 of these */ output_size = 2 + (MIN_EXPANSION * 4) + input_chars; + max_output_size = 2 + (input_chars * MAX_EXPANSION); rval = PyString_FromStringAndSize(NULL, output_size); if (rval == NULL) { return NULL; @@ -82,20 +223,24 @@ if (S_CHAR(c)) { output[chars++] = (char)c; } - else { + else { chars = ascii_escape_char(c, output, chars); } if (output_size - chars < (1 + MAX_EXPANSION)) { /* There's more than four, so let's resize by a lot */ - output_size *= 2; + Py_ssize_t new_output_size = output_size * 2; /* This is an upper bound */ - if (output_size > 2 + (input_chars * MAX_EXPANSION)) { - output_size = 2 + (input_chars * MAX_EXPANSION); + if (new_output_size > max_output_size) { + new_output_size = max_output_size; } - if (_PyString_Resize(&rval, output_size) == -1) { - return NULL; + /* Make sure that the output size changed before resizing */ + if (new_output_size != output_size) { + output_size = new_output_size; + if (_PyString_Resize(&rval, output_size) == -1) { + return NULL; + } + output = PyString_AS_STRING(rval); } - output = PyString_AS_STRING(rval); } } output[chars++] = '"'; @@ -108,6 +253,7 @@ static PyObject * ascii_escape_str(PyObject *pystr) { + /* Take a PyString pystr and return a new ASCII-only escaped PyString */ Py_ssize_t i; Py_ssize_t input_chars; Py_ssize_t output_size; @@ -118,33 +264,56 @@ input_chars = PyString_GET_SIZE(pystr); input_str = PyString_AS_STRING(pystr); - /* One char input can be up to 6 chars output, estimate 4 of these */ - output_size = 2 + (MIN_EXPANSION * 4) + input_chars; + + /* Fast path for a string that's already ASCII */ + for (i = 0; i < input_chars; i++) { + Py_UNICODE c = (Py_UNICODE)(unsigned char)input_str[i]; + if (!S_CHAR(c)) { + /* If we have to escape something, scan the string for unicode */ + Py_ssize_t j; + for (j = i; j < input_chars; j++) { + c = (Py_UNICODE)(unsigned char)input_str[j]; + if (c > 0x7f) { + /* We hit a non-ASCII character, bail to unicode mode */ + PyObject *uni; + uni = PyUnicode_DecodeUTF8(input_str, input_chars, "strict"); + if (uni == NULL) { + return NULL; + } + rval = ascii_escape_unicode(uni); + Py_DECREF(uni); + return rval; + } + } + break; + } + } + + if (i == input_chars) { + /* Input is already ASCII */ + output_size = 2 + input_chars; + } + else { + /* One char input can be up to 6 chars output, estimate 4 of these */ + output_size = 2 + (MIN_EXPANSION * 4) + input_chars; + } rval = PyString_FromStringAndSize(NULL, output_size); if (rval == NULL) { return NULL; } output = PyString_AS_STRING(rval); - chars = 0; - output[chars++] = '"'; - for (i = 0; i < input_chars; i++) { - Py_UNICODE c = (Py_UNICODE)input_str[i]; + output[0] = '"'; + + /* We know that everything up to i is ASCII already */ + chars = i + 1; + memcpy(&output[1], input_str, i); + + for (; i < input_chars; i++) { + Py_UNICODE c = (Py_UNICODE)(unsigned char)input_str[i]; if (S_CHAR(c)) { output[chars++] = (char)c; } - else if (c > 0x7F) { - /* We hit a non-ASCII character, bail to unicode mode */ - PyObject *uni; - Py_DECREF(rval); - uni = PyUnicode_DecodeUTF8(input_str, input_chars, "strict"); - if (uni == NULL) { - return NULL; - } - rval = ascii_escape_unicode(uni); - Py_DECREF(uni); - return rval; - } - else { + else { chars = ascii_escape_char(c, output, chars); } /* An ASCII char can't possibly expand to a surrogate! */ @@ -167,9 +336,11 @@ return rval; } -void +static void raise_errmsg(char *msg, PyObject *s, Py_ssize_t end) { + /* Use the Python function json.decoder.errmsg to raise a nice + looking ValueError exception */ static PyObject *errmsg_fn = NULL; PyObject *pymsg; if (errmsg_fn == NULL) { @@ -177,61 +348,97 @@ if (decoder == NULL) return; errmsg_fn = PyObject_GetAttrString(decoder, "errmsg"); + Py_DECREF(decoder); if (errmsg_fn == NULL) return; - Py_DECREF(decoder); } - pymsg = PyObject_CallFunction(errmsg_fn, "(zOn)", msg, s, end); + pymsg = PyObject_CallFunction(errmsg_fn, "(zOO&)", msg, s, _convertPyInt_FromSsize_t, &end); if (pymsg) { PyErr_SetObject(PyExc_ValueError, pymsg); Py_DECREF(pymsg); } -/* - -def linecol(doc, pos): - lineno = doc.count('\n', 0, pos) + 1 - if lineno == 1: - colno = pos - else: - colno = pos - doc.rindex('\n', 0, pos) - return lineno, colno - -def errmsg(msg, doc, pos, end=None): - lineno, colno = linecol(doc, pos) - if end is None: - return '%s: line %d column %d (char %d)' % (msg, lineno, colno, pos) - endlineno, endcolno = linecol(doc, end) - return '%s: line %d column %d - line %d column %d (char %d - %d)' % ( - msg, lineno, colno, endlineno, endcolno, pos, end) - -*/ } static PyObject * join_list_unicode(PyObject *lst) { - static PyObject *ustr = NULL; - static PyObject *joinstr = NULL; - if (ustr == NULL) { - Py_UNICODE c = 0; - ustr = PyUnicode_FromUnicode(&c, 0); + /* return u''.join(lst) */ + static PyObject *joinfn = NULL; + if (joinfn == NULL) { + PyObject *ustr = PyUnicode_FromUnicode(NULL, 0); + if (ustr == NULL) + return NULL; + + joinfn = PyObject_GetAttrString(ustr, "join"); + Py_DECREF(ustr); + if (joinfn == NULL) + return NULL; + } + return PyObject_CallFunctionObjArgs(joinfn, lst, NULL); +} + +static PyObject * +join_list_string(PyObject *lst) +{ + /* return ''.join(lst) */ + static PyObject *joinfn = NULL; + if (joinfn == NULL) { + PyObject *ustr = PyString_FromStringAndSize(NULL, 0); + if (ustr == NULL) + return NULL; + + joinfn = PyObject_GetAttrString(ustr, "join"); + Py_DECREF(ustr); + if (joinfn == NULL) + return NULL; + } + return PyObject_CallFunctionObjArgs(joinfn, lst, NULL); +} + +static PyObject * +_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) { + /* return (rval, idx) tuple, stealing reference to rval */ + PyObject *tpl; + PyObject *pyidx; + /* + steal a reference to rval, returns (rval, idx) + */ + if (rval == NULL) { + return NULL; } - if (joinstr == NULL) { - joinstr = PyString_InternFromString("join"); + pyidx = PyInt_FromSsize_t(idx); + if (pyidx == NULL) { + Py_DECREF(rval); + return NULL; } - if (joinstr == NULL || ustr == NULL) { + tpl = PyTuple_New(2); + if (tpl == NULL) { + Py_DECREF(pyidx); + Py_DECREF(rval); return NULL; } - return PyObject_CallMethodObjArgs(ustr, joinstr, lst, NULL); + PyTuple_SET_ITEM(tpl, 0, rval); + PyTuple_SET_ITEM(tpl, 1, pyidx); + return tpl; } static PyObject * -scanstring_str(PyObject *pystr, Py_ssize_t end, char *encoding, int strict) +scanstring_str(PyObject *pystr, Py_ssize_t end, char *encoding, int strict, Py_ssize_t *next_end_ptr) { + /* Read the JSON string from PyString pystr. + end is the index of the first character after the quote. + encoding is the encoding of pystr (must be an ASCII superset) + if strict is zero then literal control characters are allowed + *next_end_ptr is a return-by-reference index of the character + after the end quote + + Return value is a new PyString (if ASCII-only) or PyUnicode + */ PyObject *rval; Py_ssize_t len = PyString_GET_SIZE(pystr); Py_ssize_t begin = end - 1; Py_ssize_t next = begin; + int has_unicode = 0; char *buf = PyString_AS_STRING(pystr); PyObject *chunks = PyList_New(0); if (chunks == NULL) { @@ -246,7 +453,7 @@ Py_UNICODE c = 0; PyObject *chunk = NULL; for (next = end; next < len; next++) { - c = buf[next]; + c = (unsigned char)buf[next]; if (c == '"' || c == '\\') { break; } @@ -254,6 +461,9 @@ raise_errmsg("Invalid control character at", pystr, next); goto bail; } + else if (c > 0x7f) { + has_unicode = 1; + } } if (!(c == '"' || c == '\\')) { raise_errmsg("Unterminated string starting at", pystr, begin); @@ -261,14 +471,19 @@ } /* Pick up this chunk if it's not zero length */ if (next != end) { - PyObject *strchunk = PyBuffer_FromMemory(&buf[end], next - end); + PyObject *strchunk = PyString_FromStringAndSize(&buf[end], next - end); if (strchunk == NULL) { goto bail; } - chunk = PyUnicode_FromEncodedObject(strchunk, encoding, NULL); - Py_DECREF(strchunk); - if (chunk == NULL) { - goto bail; + if (has_unicode) { + chunk = PyUnicode_FromEncodedObject(strchunk, encoding, NULL); + Py_DECREF(strchunk); + if (chunk == NULL) { + goto bail; + } + } + else { + chunk = strchunk; } if (PyList_Append(chunks, chunk)) { Py_DECREF(chunk); @@ -315,18 +530,18 @@ } /* Decode 4 hex digits */ for (; next < end; next++) { - Py_ssize_t shl = (end - next - 1) << 2; Py_UNICODE digit = buf[next]; + c <<= 4; switch (digit) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - c |= (digit - '0') << shl; break; + c |= (digit - '0'); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - c |= (digit - 'a' + 10) << shl; break; + c |= (digit - 'a' + 10); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - c |= (digit - 'A' + 10) << shl; break; + c |= (digit - 'A' + 10); break; default: raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5); goto bail; @@ -334,43 +549,63 @@ } #ifdef Py_UNICODE_WIDE /* Surrogate pair */ - if (c >= 0xd800 && c <= 0xdbff) { + if ((c & 0xfc00) == 0xd800) { Py_UNICODE c2 = 0; if (end + 6 >= len) { - raise_errmsg("Invalid \\uXXXX\\uXXXX surrogate pair", pystr, - end - 5); + raise_errmsg("Unpaired high surrogate", pystr, end - 5); + goto bail; } if (buf[next++] != '\\' || buf[next++] != 'u') { - raise_errmsg("Invalid \\uXXXX\\uXXXX surrogate pair", pystr, - end - 5); + raise_errmsg("Unpaired high surrogate", pystr, end - 5); + goto bail; } end += 6; /* Decode 4 hex digits */ for (; next < end; next++) { - Py_ssize_t shl = (end - next - 1) << 2; + c2 <<= 4; Py_UNICODE digit = buf[next]; switch (digit) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - c2 |= (digit - '0') << shl; break; + c2 |= (digit - '0'); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - c2 |= (digit - 'a' + 10) << shl; break; + c2 |= (digit - 'a' + 10); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - c2 |= (digit - 'A' + 10) << shl; break; + c2 |= (digit - 'A' + 10); break; default: raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5); goto bail; } } + if ((c2 & 0xfc00) != 0xdc00) { + raise_errmsg("Unpaired high surrogate", pystr, end - 5); + goto bail; + } c = 0x10000 + (((c - 0xd800) << 10) | (c2 - 0xdc00)); } + else if ((c & 0xfc00) == 0xdc00) { + raise_errmsg("Unpaired low surrogate", pystr, end - 5); + goto bail; + } #endif } - chunk = PyUnicode_FromUnicode(&c, 1); - if (chunk == NULL) { - goto bail; + if (c > 0x7f) { + has_unicode = 1; + } + if (has_unicode) { + chunk = PyUnicode_FromUnicode(&c, 1); + if (chunk == NULL) { + goto bail; + } + } + else { + char c_char = Py_CHARMASK(c); + chunk = PyString_FromStringAndSize(&c_char, 1); + if (chunk == NULL) { + goto bail; + } } if (PyList_Append(chunks, chunk)) { Py_DECREF(chunk); @@ -379,21 +614,31 @@ Py_DECREF(chunk); } - rval = join_list_unicode(chunks); + rval = join_list_string(chunks); if (rval == NULL) { goto bail; } Py_CLEAR(chunks); - return Py_BuildValue("(Nn)", rval, end); + *next_end_ptr = end; + return rval; bail: + *next_end_ptr = -1; Py_XDECREF(chunks); return NULL; } static PyObject * -scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict) +scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next_end_ptr) { + /* Read the JSON string from PyUnicode pystr. + end is the index of the first character after the quote. + if strict is zero then literal control characters are allowed + *next_end_ptr is a return-by-reference index of the character + after the end quote + + Return value is a new PyUnicode + */ PyObject *rval; Py_ssize_t len = PyUnicode_GET_SIZE(pystr); Py_ssize_t begin = end - 1; @@ -476,18 +721,18 @@ } /* Decode 4 hex digits */ for (; next < end; next++) { - Py_ssize_t shl = (end - next - 1) << 2; Py_UNICODE digit = buf[next]; + c <<= 4; switch (digit) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - c |= (digit - '0') << shl; break; + c |= (digit - '0'); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - c |= (digit - 'a' + 10) << shl; break; + c |= (digit - 'a' + 10); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - c |= (digit - 'A' + 10) << shl; break; + c |= (digit - 'A' + 10); break; default: raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5); goto bail; @@ -495,38 +740,46 @@ } #ifdef Py_UNICODE_WIDE /* Surrogate pair */ - if (c >= 0xd800 && c <= 0xdbff) { + if ((c & 0xfc00) == 0xd800) { Py_UNICODE c2 = 0; if (end + 6 >= len) { - raise_errmsg("Invalid \\uXXXX\\uXXXX surrogate pair", pystr, - end - 5); + raise_errmsg("Unpaired high surrogate", pystr, end - 5); + goto bail; } if (buf[next++] != '\\' || buf[next++] != 'u') { - raise_errmsg("Invalid \\uXXXX\\uXXXX surrogate pair", pystr, - end - 5); + raise_errmsg("Unpaired high surrogate", pystr, end - 5); + goto bail; } end += 6; /* Decode 4 hex digits */ for (; next < end; next++) { - Py_ssize_t shl = (end - next - 1) << 2; + c2 <<= 4; Py_UNICODE digit = buf[next]; switch (digit) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - c2 |= (digit - '0') << shl; break; + c2 |= (digit - '0'); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - c2 |= (digit - 'a' + 10) << shl; break; + c2 |= (digit - 'a' + 10); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - c2 |= (digit - 'A' + 10) << shl; break; + c2 |= (digit - 'A' + 10); break; default: raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5); goto bail; } } + if ((c2 & 0xfc00) != 0xdc00) { + raise_errmsg("Unpaired high surrogate", pystr, end - 5); + goto bail; + } c = 0x10000 + (((c - 0xd800) << 10) | (c2 - 0xdc00)); } + else if ((c & 0xfc00) == 0xdc00) { + raise_errmsg("Unpaired low surrogate", pystr, end - 5); + goto bail; + } #endif } chunk = PyUnicode_FromUnicode(&c, 1); @@ -544,49 +797,68 @@ if (rval == NULL) { goto bail; } - Py_CLEAR(chunks); - return Py_BuildValue("(Nn)", rval, end); + Py_DECREF(chunks); + *next_end_ptr = end; + return rval; bail: + *next_end_ptr = -1; Py_XDECREF(chunks); return NULL; } PyDoc_STRVAR(pydoc_scanstring, -"scanstring(basestring, end, encoding) -> (str, end)\n"); + "scanstring(basestring, end, encoding, strict=True) -> (str, end)\n" + "\n" + "Scan the string s for a JSON string. End is the index of the\n" + "character in s after the quote that started the JSON string.\n" + "Unescapes all valid JSON string escape sequences and raises ValueError\n" + "on attempt to decode an invalid string. If strict is False then literal\n" + "control characters are allowed in the string.\n" + "\n" + "Returns a tuple of the decoded string and the index of the character in s\n" + "after the end quote." +); static PyObject * -py_scanstring(PyObject* self, PyObject *args) +py_scanstring(PyObject* self UNUSED, PyObject *args) { PyObject *pystr; + PyObject *rval; Py_ssize_t end; + Py_ssize_t next_end = -1; char *encoding = NULL; - int strict = 0; - if (!PyArg_ParseTuple(args, "On|zi:scanstring", &pystr, &end, &encoding, &strict)) { + int strict = 1; + if (!PyArg_ParseTuple(args, "OO&|zi:scanstring", &pystr, _convertPyInt_AsSsize_t, &end, &encoding, &strict)) { return NULL; } if (encoding == NULL) { encoding = DEFAULT_ENCODING; } if (PyString_Check(pystr)) { - return scanstring_str(pystr, end, encoding, strict); + rval = scanstring_str(pystr, end, encoding, strict, &next_end); } else if (PyUnicode_Check(pystr)) { - return scanstring_unicode(pystr, end, strict); + rval = scanstring_unicode(pystr, end, strict, &next_end); } else { - PyErr_Format(PyExc_TypeError, - "first argument must be a string or unicode, not %.80s", + PyErr_Format(PyExc_TypeError, + "first argument must be a string, not %.80s", Py_TYPE(pystr)->tp_name); return NULL; } + return _build_rval_index_tuple(rval, next_end); } PyDoc_STRVAR(pydoc_encode_basestring_ascii, -"encode_basestring_ascii(basestring) -> str\n"); + "encode_basestring_ascii(basestring) -> str\n" + "\n" + "Return an ASCII-only JSON representation of a Python string" +); static PyObject * -py_encode_basestring_ascii(PyObject* self, PyObject *pystr) +py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr) { + /* Return an ASCII-only JSON representation of a Python string */ /* METH_O */ if (PyString_Check(pystr)) { return ascii_escape_str(pystr); @@ -595,18 +867,1444 @@ return ascii_escape_unicode(pystr); } else { - PyErr_Format(PyExc_TypeError, - "first argument must be a string or unicode, not %.80s", + PyErr_Format(PyExc_TypeError, + "first argument must be a string, not %.80s", Py_TYPE(pystr)->tp_name); return NULL; } } -static PyMethodDef json_methods[] = { - {"encode_basestring_ascii", (PyCFunction)py_encode_basestring_ascii, - METH_O, pydoc_encode_basestring_ascii}, - {"scanstring", (PyCFunction)py_scanstring, METH_VARARGS, - pydoc_scanstring}, +static void +scanner_dealloc(PyObject *self) +{ + /* Deallocate scanner object */ + scanner_clear(self); + Py_TYPE(self)->tp_free(self); +} + +static int +scanner_traverse(PyObject *self, visitproc visit, void *arg) +{ + PyScannerObject *s; + assert(PyScanner_Check(self)); + s = (PyScannerObject *)self; + Py_VISIT(s->encoding); + Py_VISIT(s->strict); + Py_VISIT(s->object_hook); + Py_VISIT(s->parse_float); + Py_VISIT(s->parse_int); + Py_VISIT(s->parse_constant); + return 0; +} + +static int +scanner_clear(PyObject *self) +{ + PyScannerObject *s; + assert(PyScanner_Check(self)); + s = (PyScannerObject *)self; + Py_CLEAR(s->encoding); + Py_CLEAR(s->strict); + Py_CLEAR(s->object_hook); + Py_CLEAR(s->parse_float); + Py_CLEAR(s->parse_int); + Py_CLEAR(s->parse_constant); + return 0; +} + +static PyObject * +_parse_object_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) { + /* Read a JSON object from PyString pystr. + idx is the index of the first character after the opening curly brace. + *next_idx_ptr is a return-by-reference index to the first character after + the closing curly brace. + + Returns a new PyObject (usually a dict, but object_hook can change that) + */ + char *str = PyString_AS_STRING(pystr); + Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1; + PyObject *rval = PyDict_New(); + PyObject *key = NULL; + PyObject *val = NULL; + char *encoding = PyString_AS_STRING(s->encoding); + int strict = PyObject_IsTrue(s->strict); + Py_ssize_t next_idx; + if (rval == NULL) + return NULL; + + /* skip whitespace after { */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + + /* only loop if the object is non-empty */ + if (idx <= end_idx && str[idx] != '}') { + while (idx <= end_idx) { + /* read key */ + if (str[idx] != '"') { + raise_errmsg("Expecting property name", pystr, idx); + goto bail; + } + key = scanstring_str(pystr, idx + 1, encoding, strict, &next_idx); + if (key == NULL) + goto bail; + idx = next_idx; + + /* skip whitespace between key and : delimiter, read :, skip whitespace */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + if (idx > end_idx || str[idx] != ':') { + raise_errmsg("Expecting : delimiter", pystr, idx); + goto bail; + } + idx++; + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + + /* read any JSON data type */ + val = scan_once_str(s, pystr, idx, &next_idx); + if (val == NULL) + goto bail; + + if (PyDict_SetItem(rval, key, val) == -1) + goto bail; + + Py_CLEAR(key); + Py_CLEAR(val); + idx = next_idx; + + /* skip whitespace before } or , */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + + /* bail if the object is closed or we didn't get the , delimiter */ + if (idx > end_idx) break; + if (str[idx] == '}') { + break; + } + else if (str[idx] != ',') { + raise_errmsg("Expecting , delimiter", pystr, idx); + goto bail; + } + idx++; + + /* skip whitespace after , delimiter */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + } + } + /* verify that idx < end_idx, str[idx] should be '}' */ + if (idx > end_idx || str[idx] != '}') { + raise_errmsg("Expecting object", pystr, end_idx); + goto bail; + } + /* if object_hook is not None: rval = object_hook(rval) */ + if (s->object_hook != Py_None) { + val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL); + if (val == NULL) + goto bail; + Py_DECREF(rval); + rval = val; + val = NULL; + } + *next_idx_ptr = idx + 1; + return rval; +bail: + Py_XDECREF(key); + Py_XDECREF(val); + Py_DECREF(rval); + return NULL; +} + +static PyObject * +_parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) { + /* Read a JSON object from PyUnicode pystr. + idx is the index of the first character after the opening curly brace. + *next_idx_ptr is a return-by-reference index to the first character after + the closing curly brace. + + Returns a new PyObject (usually a dict, but object_hook can change that) + */ + Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr); + Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1; + PyObject *val = NULL; + PyObject *rval = PyDict_New(); + PyObject *key = NULL; + int strict = PyObject_IsTrue(s->strict); + Py_ssize_t next_idx; + if (rval == NULL) + return NULL; + + /* skip whitespace after { */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + + /* only loop if the object is non-empty */ + if (idx <= end_idx && str[idx] != '}') { + while (idx <= end_idx) { + /* read key */ + if (str[idx] != '"') { + raise_errmsg("Expecting property name", pystr, idx); + goto bail; + } + key = scanstring_unicode(pystr, idx + 1, strict, &next_idx); + if (key == NULL) + goto bail; + idx = next_idx; + + /* skip whitespace between key and : delimiter, read :, skip whitespace */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + if (idx > end_idx || str[idx] != ':') { + raise_errmsg("Expecting : delimiter", pystr, idx); + goto bail; + } + idx++; + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + + /* read any JSON term */ + val = scan_once_unicode(s, pystr, idx, &next_idx); + if (val == NULL) + goto bail; + + if (PyDict_SetItem(rval, key, val) == -1) + goto bail; + + Py_CLEAR(key); + Py_CLEAR(val); + idx = next_idx; + + /* skip whitespace before } or , */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + + /* bail if the object is closed or we didn't get the , delimiter */ + if (idx > end_idx) break; + if (str[idx] == '}') { + break; + } + else if (str[idx] != ',') { + raise_errmsg("Expecting , delimiter", pystr, idx); + goto bail; + } + idx++; + + /* skip whitespace after , delimiter */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + } + } + + /* verify that idx < end_idx, str[idx] should be '}' */ + if (idx > end_idx || str[idx] != '}') { + raise_errmsg("Expecting object", pystr, end_idx); + goto bail; + } + + /* if object_hook is not None: rval = object_hook(rval) */ + if (s->object_hook != Py_None) { + val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL); + if (val == NULL) + goto bail; + Py_DECREF(rval); + rval = val; + val = NULL; + } + *next_idx_ptr = idx + 1; + return rval; +bail: + Py_XDECREF(key); + Py_XDECREF(val); + Py_DECREF(rval); + return NULL; +} + +static PyObject * +_parse_array_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) { + /* Read a JSON array from PyString pystr. + idx is the index of the first character after the opening brace. + *next_idx_ptr is a return-by-reference index to the first character after + the closing brace. + + Returns a new PyList + */ + char *str = PyString_AS_STRING(pystr); + Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1; + PyObject *val = NULL; + PyObject *rval = PyList_New(0); + Py_ssize_t next_idx; + if (rval == NULL) + return NULL; + + /* skip whitespace after [ */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + + /* only loop if the array is non-empty */ + if (idx <= end_idx && str[idx] != ']') { + while (idx <= end_idx) { + + /* read any JSON term and de-tuplefy the (rval, idx) */ + val = scan_once_str(s, pystr, idx, &next_idx); + if (val == NULL) + goto bail; + + if (PyList_Append(rval, val) == -1) + goto bail; + + Py_CLEAR(val); + idx = next_idx; + + /* skip whitespace between term and , */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + + /* bail if the array is closed or we didn't get the , delimiter */ + if (idx > end_idx) break; + if (str[idx] == ']') { + break; + } + else if (str[idx] != ',') { + raise_errmsg("Expecting , delimiter", pystr, idx); + goto bail; + } + idx++; + + /* skip whitespace after , */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + } + } + + /* verify that idx < end_idx, str[idx] should be ']' */ + if (idx > end_idx || str[idx] != ']') { + raise_errmsg("Expecting object", pystr, end_idx); + goto bail; + } + *next_idx_ptr = idx + 1; + return rval; +bail: + Py_XDECREF(val); + Py_DECREF(rval); + return NULL; +} + +static PyObject * +_parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) { + /* Read a JSON array from PyString pystr. + idx is the index of the first character after the opening brace. + *next_idx_ptr is a return-by-reference index to the first character after + the closing brace. + + Returns a new PyList + */ + Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr); + Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1; + PyObject *val = NULL; + PyObject *rval = PyList_New(0); + Py_ssize_t next_idx; + if (rval == NULL) + return NULL; + + /* skip whitespace after [ */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + + /* only loop if the array is non-empty */ + if (idx <= end_idx && str[idx] != ']') { + while (idx <= end_idx) { + + /* read any JSON term */ + val = scan_once_unicode(s, pystr, idx, &next_idx); + if (val == NULL) + goto bail; + + if (PyList_Append(rval, val) == -1) + goto bail; + + Py_CLEAR(val); + idx = next_idx; + + /* skip whitespace between term and , */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + + /* bail if the array is closed or we didn't get the , delimiter */ + if (idx > end_idx) break; + if (str[idx] == ']') { + break; + } + else if (str[idx] != ',') { + raise_errmsg("Expecting , delimiter", pystr, idx); + goto bail; + } + idx++; + + /* skip whitespace after , */ + while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; + } + } + + /* verify that idx < end_idx, str[idx] should be ']' */ + if (idx > end_idx || str[idx] != ']') { + raise_errmsg("Expecting object", pystr, end_idx); + goto bail; + } + *next_idx_ptr = idx + 1; + return rval; +bail: + Py_XDECREF(val); + Py_DECREF(rval); + return NULL; +} + +static PyObject * +_parse_constant(PyScannerObject *s, char *constant, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) { + /* Read a JSON constant from PyString pystr. + constant is the constant string that was found + ("NaN", "Infinity", "-Infinity"). + idx is the index of the first character of the constant + *next_idx_ptr is a return-by-reference index to the first character after + the constant. + + Returns the result of parse_constant + */ + PyObject *cstr; + PyObject *rval; + /* constant is "NaN", "Infinity", or "-Infinity" */ + cstr = PyString_InternFromString(constant); + if (cstr == NULL) + return NULL; + + /* rval = parse_constant(constant) */ + rval = PyObject_CallFunctionObjArgs(s->parse_constant, cstr, NULL); + idx += PyString_GET_SIZE(cstr); + Py_DECREF(cstr); + *next_idx_ptr = idx; + return rval; +} + +static PyObject * +_match_number_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) { + /* Read a JSON number from PyString pystr. + idx is the index of the first character of the number + *next_idx_ptr is a return-by-reference index to the first character after + the number. + + Returns a new PyObject representation of that number: + PyInt, PyLong, or PyFloat. + May return other types if parse_int or parse_float are set + */ + char *str = PyString_AS_STRING(pystr); + Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1; + Py_ssize_t idx = start; + int is_float = 0; + PyObject *rval; + PyObject *numstr; + + /* read a sign if it's there, make sure it's not the end of the string */ + if (str[idx] == '-') { + idx++; + if (idx > end_idx) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + } + + /* read as many integer digits as we find as long as it doesn't start with 0 */ + if (str[idx] >= '1' && str[idx] <= '9') { + idx++; + while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++; + } + /* if it starts with 0 we only expect one integer digit */ + else if (str[idx] == '0') { + idx++; + } + /* no integer digits, error */ + else { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + + /* if the next char is '.' followed by a digit then read all float digits */ + if (idx < end_idx && str[idx] == '.' && str[idx + 1] >= '0' && str[idx + 1] <= '9') { + is_float = 1; + idx += 2; + while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++; + } + + /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */ + if (idx < end_idx && (str[idx] == 'e' || str[idx] == 'E')) { + + /* save the index of the 'e' or 'E' just in case we need to backtrack */ + Py_ssize_t e_start = idx; + idx++; + + /* read an exponent sign if present */ + if (idx < end_idx && (str[idx] == '-' || str[idx] == '+')) idx++; + + /* read all digits */ + while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++; + + /* if we got a digit, then parse as float. if not, backtrack */ + if (str[idx - 1] >= '0' && str[idx - 1] <= '9') { + is_float = 1; + } + else { + idx = e_start; + } + } + + /* copy the section we determined to be a number */ + numstr = PyString_FromStringAndSize(&str[start], idx - start); + if (numstr == NULL) + return NULL; + if (is_float) { + /* parse as a float using a fast path if available, otherwise call user defined method */ + if (s->parse_float != (PyObject *)&PyFloat_Type) { + rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL); + } + else { + rval = PyFloat_FromDouble(PyOS_ascii_atof(PyString_AS_STRING(numstr))); + } + } + else { + /* parse as an int using a fast path if available, otherwise call user defined method */ + if (s->parse_int != (PyObject *)&PyInt_Type) { + rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL); + } + else { + rval = PyInt_FromString(PyString_AS_STRING(numstr), NULL, 10); + } + } + Py_DECREF(numstr); + *next_idx_ptr = idx; + return rval; +} + +static PyObject * +_match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) { + /* Read a JSON number from PyUnicode pystr. + idx is the index of the first character of the number + *next_idx_ptr is a return-by-reference index to the first character after + the number. + + Returns a new PyObject representation of that number: + PyInt, PyLong, or PyFloat. + May return other types if parse_int or parse_float are set + */ + Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr); + Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1; + Py_ssize_t idx = start; + int is_float = 0; + PyObject *rval; + PyObject *numstr; + + /* read a sign if it's there, make sure it's not the end of the string */ + if (str[idx] == '-') { + idx++; + if (idx > end_idx) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + } + + /* read as many integer digits as we find as long as it doesn't start with 0 */ + if (str[idx] >= '1' && str[idx] <= '9') { + idx++; + while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++; + } + /* if it starts with 0 we only expect one integer digit */ + else if (str[idx] == '0') { + idx++; + } + /* no integer digits, error */ + else { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + + /* if the next char is '.' followed by a digit then read all float digits */ + if (idx < end_idx && str[idx] == '.' && str[idx + 1] >= '0' && str[idx + 1] <= '9') { + is_float = 1; + idx += 2; + while (idx < end_idx && str[idx] >= '0' && str[idx] <= '9') idx++; + } + + /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */ + if (idx < end_idx && (str[idx] == 'e' || str[idx] == 'E')) { + Py_ssize_t e_start = idx; + idx++; + + /* read an exponent sign if present */ + if (idx < end_idx && (str[idx] == '-' || str[idx] == '+')) idx++; + + /* read all digits */ + while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++; + + /* if we got a digit, then parse as float. if not, backtrack */ + if (str[idx - 1] >= '0' && str[idx - 1] <= '9') { + is_float = 1; + } + else { + idx = e_start; + } + } + + /* copy the section we determined to be a number */ + numstr = PyUnicode_FromUnicode(&str[start], idx - start); + if (numstr == NULL) + return NULL; + if (is_float) { + /* parse as a float using a fast path if available, otherwise call user defined method */ + if (s->parse_float != (PyObject *)&PyFloat_Type) { + rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL); + } + else { + rval = PyFloat_FromString(numstr, NULL); + } + } + else { + /* no fast path for unicode -> int, just call */ + rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL); + } + Py_DECREF(numstr); + *next_idx_ptr = idx; + return rval; +} + +static PyObject * +scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) +{ + /* Read one JSON term (of any kind) from PyString pystr. + idx is the index of the first character of the term + *next_idx_ptr is a return-by-reference index to the first character after + the number. + + Returns a new PyObject representation of the term. + */ + char *str = PyString_AS_STRING(pystr); + Py_ssize_t length = PyString_GET_SIZE(pystr); + if (idx >= length) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + switch (str[idx]) { + case '"': + /* string */ + return scanstring_str(pystr, idx + 1, + PyString_AS_STRING(s->encoding), + PyObject_IsTrue(s->strict), + next_idx_ptr); + case '{': + /* object */ + return _parse_object_str(s, pystr, idx + 1, next_idx_ptr); + case '[': + /* array */ + return _parse_array_str(s, pystr, idx + 1, next_idx_ptr); + case 'n': + /* null */ + if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') { + Py_INCREF(Py_None); + *next_idx_ptr = idx + 4; + return Py_None; + } + break; + case 't': + /* true */ + if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') { + Py_INCREF(Py_True); + *next_idx_ptr = idx + 4; + return Py_True; + } + break; + case 'f': + /* false */ + if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') { + Py_INCREF(Py_False); + *next_idx_ptr = idx + 5; + return Py_False; + } + break; + case 'N': + /* NaN */ + if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') { + return _parse_constant(s, "NaN", idx, next_idx_ptr); + } + break; + case 'I': + /* Infinity */ + if ((idx + 7 < length) && str[idx + 1] == 'n' && str[idx + 2] == 'f' && str[idx + 3] == 'i' && str[idx + 4] == 'n' && str[idx + 5] == 'i' && str[idx + 6] == 't' && str[idx + 7] == 'y') { + return _parse_constant(s, "Infinity", idx, next_idx_ptr); + } + break; + case '-': + /* -Infinity */ + if ((idx + 8 < length) && str[idx + 1] == 'I' && str[idx + 2] == 'n' && str[idx + 3] == 'f' && str[idx + 4] == 'i' && str[idx + 5] == 'n' && str[idx + 6] == 'i' && str[idx + 7] == 't' && str[idx + 8] == 'y') { + return _parse_constant(s, "-Infinity", idx, next_idx_ptr); + } + break; + } + /* Didn't find a string, object, array, or named constant. Look for a number. */ + return _match_number_str(s, pystr, idx, next_idx_ptr); +} + +static PyObject * +scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) +{ + /* Read one JSON term (of any kind) from PyUnicode pystr. + idx is the index of the first character of the term + *next_idx_ptr is a return-by-reference index to the first character after + the number. + + Returns a new PyObject representation of the term. + */ + Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr); + Py_ssize_t length = PyUnicode_GET_SIZE(pystr); + if (idx >= length) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + switch (str[idx]) { + case '"': + /* string */ + return scanstring_unicode(pystr, idx + 1, + PyObject_IsTrue(s->strict), + next_idx_ptr); + case '{': + /* object */ + return _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr); + case '[': + /* array */ + return _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr); + case 'n': + /* null */ + if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') { + Py_INCREF(Py_None); + *next_idx_ptr = idx + 4; + return Py_None; + } + break; + case 't': + /* true */ + if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') { + Py_INCREF(Py_True); + *next_idx_ptr = idx + 4; + return Py_True; + } + break; + case 'f': + /* false */ + if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') { + Py_INCREF(Py_False); + *next_idx_ptr = idx + 5; + return Py_False; + } + break; + case 'N': + /* NaN */ + if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') { + return _parse_constant(s, "NaN", idx, next_idx_ptr); + } + break; + case 'I': + /* Infinity */ + if ((idx + 7 < length) && str[idx + 1] == 'n' && str[idx + 2] == 'f' && str[idx + 3] == 'i' && str[idx + 4] == 'n' && str[idx + 5] == 'i' && str[idx + 6] == 't' && str[idx + 7] == 'y') { + return _parse_constant(s, "Infinity", idx, next_idx_ptr); + } + break; + case '-': + /* -Infinity */ + if ((idx + 8 < length) && str[idx + 1] == 'I' && str[idx + 2] == 'n' && str[idx + 3] == 'f' && str[idx + 4] == 'i' && str[idx + 5] == 'n' && str[idx + 6] == 'i' && str[idx + 7] == 't' && str[idx + 8] == 'y') { + return _parse_constant(s, "-Infinity", idx, next_idx_ptr); + } + break; + } + /* Didn't find a string, object, array, or named constant. Look for a number. */ + return _match_number_unicode(s, pystr, idx, next_idx_ptr); +} + +static PyObject * +scanner_call(PyObject *self, PyObject *args, PyObject *kwds) +{ + /* Python callable interface to scan_once_{str,unicode} */ + PyObject *pystr; + PyObject *rval; + Py_ssize_t idx; + Py_ssize_t next_idx = -1; + static char *kwlist[] = {"string", "idx", NULL}; + PyScannerObject *s; + assert(PyScanner_Check(self)); + s = (PyScannerObject *)self; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:scan_once", kwlist, &pystr, _convertPyInt_AsSsize_t, &idx)) + return NULL; + + if (PyString_Check(pystr)) { + rval = scan_once_str(s, pystr, idx, &next_idx); + } + else if (PyUnicode_Check(pystr)) { + rval = scan_once_unicode(s, pystr, idx, &next_idx); + } + else { + PyErr_Format(PyExc_TypeError, + "first argument must be a string, not %.80s", + Py_TYPE(pystr)->tp_name); + return NULL; + } + return _build_rval_index_tuple(rval, next_idx); +} + +static PyObject * +scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyScannerObject *s; + s = (PyScannerObject *)type->tp_alloc(type, 0); + if (s != NULL) { + s->encoding = NULL; + s->strict = NULL; + s->object_hook = NULL; + s->parse_float = NULL; + s->parse_int = NULL; + s->parse_constant = NULL; + } + return (PyObject *)s; +} + +static int +scanner_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + /* Initialize Scanner object */ + PyObject *ctx; + static char *kwlist[] = {"context", NULL}; + PyScannerObject *s; + + assert(PyScanner_Check(self)); + s = (PyScannerObject *)self; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx)) + return -1; + + /* PyString_AS_STRING is used on encoding */ + s->encoding = PyObject_GetAttrString(ctx, "encoding"); + if (s->encoding == Py_None) { + Py_DECREF(Py_None); + s->encoding = PyString_InternFromString(DEFAULT_ENCODING); + } + else if (PyUnicode_Check(s->encoding)) { + PyObject *tmp = PyUnicode_AsEncodedString(s->encoding, NULL, NULL); + Py_DECREF(s->encoding); + s->encoding = tmp; + } + if (s->encoding == NULL || !PyString_Check(s->encoding)) + goto bail; + + /* All of these will fail "gracefully" so we don't need to verify them */ + s->strict = PyObject_GetAttrString(ctx, "strict"); + if (s->strict == NULL) + goto bail; + s->object_hook = PyObject_GetAttrString(ctx, "object_hook"); + if (s->object_hook == NULL) + goto bail; + s->parse_float = PyObject_GetAttrString(ctx, "parse_float"); + if (s->parse_float == NULL) + goto bail; + s->parse_int = PyObject_GetAttrString(ctx, "parse_int"); + if (s->parse_int == NULL) + goto bail; + s->parse_constant = PyObject_GetAttrString(ctx, "parse_constant"); + if (s->parse_constant == NULL) + goto bail; + + return 0; + +bail: + Py_CLEAR(s->encoding); + Py_CLEAR(s->strict); + Py_CLEAR(s->object_hook); + Py_CLEAR(s->parse_float); + Py_CLEAR(s->parse_int); + Py_CLEAR(s->parse_constant); + return -1; +} + +PyDoc_STRVAR(scanner_doc, "JSON scanner object"); + +static +PyTypeObject PyScannerType = { + PyObject_HEAD_INIT(NULL) + 0, /* tp_internal */ + "_json.Scanner", /* tp_name */ + sizeof(PyScannerObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + scanner_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 */ + scanner_call, /* tp_call */ + 0, /* tp_str */ + 0,/* PyObject_GenericGetAttr, */ /* tp_getattro */ + 0,/* PyObject_GenericSetAttr, */ /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + scanner_doc, /* tp_doc */ + scanner_traverse, /* tp_traverse */ + scanner_clear, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + scanner_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + scanner_init, /* tp_init */ + 0,/* PyType_GenericAlloc, */ /* tp_alloc */ + scanner_new, /* tp_new */ + 0,/* PyObject_GC_Del, */ /* tp_free */ +}; + +static PyObject * +encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyEncoderObject *s; + s = (PyEncoderObject *)type->tp_alloc(type, 0); + if (s != NULL) { + s->markers = NULL; + s->defaultfn = NULL; + s->encoder = NULL; + s->indent = NULL; + s->key_separator = NULL; + s->item_separator = NULL; + s->sort_keys = NULL; + s->skipkeys = NULL; + } + return (PyObject *)s; +} + +static int +encoder_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + /* initialize Encoder object */ + static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL}; + + PyEncoderObject *s; + PyObject *allow_nan; + + assert(PyEncoder_Check(self)); + s = (PyEncoderObject *)self; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO:make_encoder", kwlist, + &s->markers, &s->defaultfn, &s->encoder, &s->indent, &s->key_separator, &s->item_separator, &s->sort_keys, &s->skipkeys, &allow_nan)) + return -1; + + Py_INCREF(s->markers); + Py_INCREF(s->defaultfn); + Py_INCREF(s->encoder); + Py_INCREF(s->indent); + Py_INCREF(s->key_separator); + Py_INCREF(s->item_separator); + Py_INCREF(s->sort_keys); + Py_INCREF(s->skipkeys); + s->fast_encode = (PyCFunction_Check(s->encoder) && PyCFunction_GetFunction(s->encoder) == (PyCFunction)py_encode_basestring_ascii); + s->allow_nan = PyObject_IsTrue(allow_nan); + return 0; +} + +static PyObject * +encoder_call(PyObject *self, PyObject *args, PyObject *kwds) +{ + /* Python callable interface to encode_listencode_obj */ + static char *kwlist[] = {"obj", "_current_indent_level", NULL}; + PyObject *obj; + PyObject *rval; + Py_ssize_t indent_level; + PyEncoderObject *s; + assert(PyEncoder_Check(self)); + s = (PyEncoderObject *)self; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:_iterencode", kwlist, + &obj, _convertPyInt_AsSsize_t, &indent_level)) + return NULL; + rval = PyList_New(0); + if (rval == NULL) + return NULL; + if (encoder_listencode_obj(s, rval, obj, indent_level)) { + Py_DECREF(rval); + return NULL; + } + return rval; +} + +static PyObject * +_encoded_const(PyObject *obj) +{ + /* Return the JSON string representation of None, True, False */ + if (obj == Py_None) { + static PyObject *s_null = NULL; + if (s_null == NULL) { + s_null = PyString_InternFromString("null"); + } + Py_INCREF(s_null); + return s_null; + } + else if (obj == Py_True) { + static PyObject *s_true = NULL; + if (s_true == NULL) { + s_true = PyString_InternFromString("true"); + } + Py_INCREF(s_true); + return s_true; + } + else if (obj == Py_False) { + static PyObject *s_false = NULL; + if (s_false == NULL) { + s_false = PyString_InternFromString("false"); + } + Py_INCREF(s_false); + return s_false; + } + else { + PyErr_SetString(PyExc_ValueError, "not a const"); + return NULL; + } +} + +static PyObject * +encoder_encode_float(PyEncoderObject *s, PyObject *obj) +{ + /* Return the JSON representation of a PyFloat */ + double i = PyFloat_AS_DOUBLE(obj); + if (!Py_IS_FINITE(i)) { + if (!s->allow_nan) { + PyErr_SetString(PyExc_ValueError, "Out of range float values are not JSON compliant"); + return NULL; + } + if (i > 0) { + return PyString_FromString("Infinity"); + } + else if (i < 0) { + return PyString_FromString("-Infinity"); + } + else { + return PyString_FromString("NaN"); + } + } + /* Use a better float format here? */ + return PyObject_Repr(obj); +} + +static PyObject * +encoder_encode_string(PyEncoderObject *s, PyObject *obj) +{ + /* Return the JSON representation of a string */ + if (s->fast_encode) + return py_encode_basestring_ascii(NULL, obj); + else + return PyObject_CallFunctionObjArgs(s->encoder, obj, NULL); +} + +static int +_steal_list_append(PyObject *lst, PyObject *stolen) +{ + /* Append stolen and then decrement its reference count */ + int rval = PyList_Append(lst, stolen); + Py_DECREF(stolen); + return rval; +} + +static int +encoder_listencode_obj(PyEncoderObject *s, PyObject *rval, PyObject *obj, Py_ssize_t indent_level) +{ + /* Encode Python object obj to a JSON term, rval is a PyList */ + PyObject *newobj; + int rv; + + if (obj == Py_None || obj == Py_True || obj == Py_False) { + PyObject *cstr = _encoded_const(obj); + if (cstr == NULL) + return -1; + return _steal_list_append(rval, cstr); + } + else if (PyString_Check(obj) || PyUnicode_Check(obj)) + { + PyObject *encoded = encoder_encode_string(s, obj); + if (encoded == NULL) + return -1; + return _steal_list_append(rval, encoded); + } + else if (PyInt_Check(obj) || PyLong_Check(obj)) { + PyObject *encoded = PyObject_Str(obj); + if (encoded == NULL) + return -1; + return _steal_list_append(rval, encoded); + } + else if (PyFloat_Check(obj)) { + PyObject *encoded = encoder_encode_float(s, obj); + if (encoded == NULL) + return -1; + return _steal_list_append(rval, encoded); + } + else if (PyList_Check(obj) || PyTuple_Check(obj)) { + return encoder_listencode_list(s, rval, obj, indent_level); + } + else if (PyDict_Check(obj)) { + return encoder_listencode_dict(s, rval, obj, indent_level); + } + else { + PyObject *ident = NULL; + if (s->markers != Py_None) { + int has_key; + ident = PyLong_FromVoidPtr(obj); + if (ident == NULL) + return -1; + has_key = PyDict_Contains(s->markers, ident); + if (has_key) { + if (has_key != -1) + PyErr_SetString(PyExc_ValueError, "Circular reference detected"); + Py_DECREF(ident); + return -1; + } + if (PyDict_SetItem(s->markers, ident, obj)) { + Py_DECREF(ident); + return -1; + } + } + newobj = PyObject_CallFunctionObjArgs(s->defaultfn, obj, NULL); + if (newobj == NULL) { + Py_XDECREF(ident); + return -1; + } + rv = encoder_listencode_obj(s, rval, newobj, indent_level); + Py_DECREF(newobj); + if (rv) { + Py_XDECREF(ident); + return -1; + } + if (ident != NULL) { + if (PyDict_DelItem(s->markers, ident)) { + Py_XDECREF(ident); + return -1; + } + Py_XDECREF(ident); + } + return rv; + } +} + +static int +encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ssize_t indent_level) +{ + /* Encode Python dict dct a JSON term, rval is a PyList */ + static PyObject *open_dict = NULL; + static PyObject *close_dict = NULL; + static PyObject *empty_dict = NULL; + PyObject *kstr = NULL; + PyObject *ident = NULL; + PyObject *key, *value; + Py_ssize_t pos; + int skipkeys; + Py_ssize_t idx; + + if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) { + open_dict = PyString_InternFromString("{"); + close_dict = PyString_InternFromString("}"); + empty_dict = PyString_InternFromString("{}"); + if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) + return -1; + } + if (PyDict_Size(dct) == 0) + return PyList_Append(rval, empty_dict); + + if (s->markers != Py_None) { + int has_key; + ident = PyLong_FromVoidPtr(dct); + if (ident == NULL) + goto bail; + has_key = PyDict_Contains(s->markers, ident); + if (has_key) { + if (has_key != -1) + PyErr_SetString(PyExc_ValueError, "Circular reference detected"); + goto bail; + } + if (PyDict_SetItem(s->markers, ident, dct)) { + goto bail; + } + } + + if (PyList_Append(rval, open_dict)) + goto bail; + + if (s->indent != Py_None) { + /* TODO: DOES NOT RUN */ + indent_level += 1; + /* + newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) + separator = _item_separator + newline_indent + buf += newline_indent + */ + } + + /* TODO: C speedup not implemented for sort_keys */ + + pos = 0; + skipkeys = PyObject_IsTrue(s->skipkeys); + idx = 0; + while (PyDict_Next(dct, &pos, &key, &value)) { + PyObject *encoded; + + if (PyString_Check(key) || PyUnicode_Check(key)) { + Py_INCREF(key); + kstr = key; + } + else if (PyFloat_Check(key)) { + kstr = encoder_encode_float(s, key); + if (kstr == NULL) + goto bail; + } + else if (PyInt_Check(key) || PyLong_Check(key)) { + kstr = PyObject_Str(key); + if (kstr == NULL) + goto bail; + } + else if (key == Py_True || key == Py_False || key == Py_None) { + kstr = _encoded_const(key); + if (kstr == NULL) + goto bail; + } + else if (skipkeys) { + continue; + } + else { + /* TODO: include repr of key */ + PyErr_SetString(PyExc_ValueError, "keys must be a string"); + goto bail; + } + + if (idx) { + if (PyList_Append(rval, s->item_separator)) + goto bail; + } + + encoded = encoder_encode_string(s, kstr); + Py_CLEAR(kstr); + if (encoded == NULL) + goto bail; + if (PyList_Append(rval, encoded)) { + Py_DECREF(encoded); + goto bail; + } + Py_DECREF(encoded); + if (PyList_Append(rval, s->key_separator)) + goto bail; + if (encoder_listencode_obj(s, rval, value, indent_level)) + goto bail; + idx += 1; + } + if (ident != NULL) { + if (PyDict_DelItem(s->markers, ident)) + goto bail; + Py_CLEAR(ident); + } + if (s->indent != Py_None) { + /* TODO: DOES NOT RUN */ + indent_level -= 1; + /* + yield '\n' + (' ' * (_indent * _current_indent_level)) + */ + } + if (PyList_Append(rval, close_dict)) + goto bail; + return 0; + +bail: + Py_XDECREF(kstr); + Py_XDECREF(ident); + return -1; +} + + +static int +encoder_listencode_list(PyEncoderObject *s, PyObject *rval, PyObject *seq, Py_ssize_t indent_level) +{ + /* Encode Python list seq to a JSON term, rval is a PyList */ + static PyObject *open_array = NULL; + static PyObject *close_array = NULL; + static PyObject *empty_array = NULL; + PyObject *ident = NULL; + PyObject *s_fast = NULL; + Py_ssize_t num_items; + PyObject **seq_items; + Py_ssize_t i; + + if (open_array == NULL || close_array == NULL || empty_array == NULL) { + open_array = PyString_InternFromString("["); + close_array = PyString_InternFromString("]"); + empty_array = PyString_InternFromString("[]"); + if (open_array == NULL || close_array == NULL || empty_array == NULL) + return -1; + } + ident = NULL; + s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence"); + if (s_fast == NULL) + return -1; + num_items = PySequence_Fast_GET_SIZE(s_fast); + if (num_items == 0) { + Py_DECREF(s_fast); + return PyList_Append(rval, empty_array); + } + + if (s->markers != Py_None) { + int has_key; + ident = PyLong_FromVoidPtr(seq); + if (ident == NULL) + goto bail; + has_key = PyDict_Contains(s->markers, ident); + if (has_key) { + if (has_key != -1) + PyErr_SetString(PyExc_ValueError, "Circular reference detected"); + goto bail; + } + if (PyDict_SetItem(s->markers, ident, seq)) { + goto bail; + } + } + + seq_items = PySequence_Fast_ITEMS(s_fast); + if (PyList_Append(rval, open_array)) + goto bail; + if (s->indent != Py_None) { + /* TODO: DOES NOT RUN */ + indent_level += 1; + /* + newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) + separator = _item_separator + newline_indent + buf += newline_indent + */ + } + for (i = 0; i < num_items; i++) { + PyObject *obj = seq_items[i]; + if (i) { + if (PyList_Append(rval, s->item_separator)) + goto bail; + } + if (encoder_listencode_obj(s, rval, obj, indent_level)) + goto bail; + } + if (ident != NULL) { + if (PyDict_DelItem(s->markers, ident)) + goto bail; + Py_CLEAR(ident); + } + if (s->indent != Py_None) { + /* TODO: DOES NOT RUN */ + indent_level -= 1; + /* + yield '\n' + (' ' * (_indent * _current_indent_level)) + */ + } + if (PyList_Append(rval, close_array)) + goto bail; + Py_DECREF(s_fast); + return 0; + +bail: + Py_XDECREF(ident); + Py_DECREF(s_fast); + return -1; +} + +static void +encoder_dealloc(PyObject *self) +{ + /* Deallocate Encoder */ + encoder_clear(self); + Py_TYPE(self)->tp_free(self); +} + +static int +encoder_traverse(PyObject *self, visitproc visit, void *arg) +{ + PyEncoderObject *s; + assert(PyEncoder_Check(self)); + s = (PyEncoderObject *)self; + Py_VISIT(s->markers); + Py_VISIT(s->defaultfn); + Py_VISIT(s->encoder); + Py_VISIT(s->indent); + Py_VISIT(s->key_separator); + Py_VISIT(s->item_separator); + Py_VISIT(s->sort_keys); + Py_VISIT(s->skipkeys); + return 0; +} + +static int +encoder_clear(PyObject *self) +{ + /* Deallocate Encoder */ + PyEncoderObject *s; + assert(PyEncoder_Check(self)); + s = (PyEncoderObject *)self; + Py_CLEAR(s->markers); + Py_CLEAR(s->defaultfn); + Py_CLEAR(s->encoder); + Py_CLEAR(s->indent); + Py_CLEAR(s->key_separator); + Py_CLEAR(s->item_separator); + Py_CLEAR(s->sort_keys); + Py_CLEAR(s->skipkeys); + return 0; +} + +PyDoc_STRVAR(encoder_doc, "_iterencode(obj, _current_indent_level) -> iterable"); + +static +PyTypeObject PyEncoderType = { + PyObject_HEAD_INIT(NULL) + 0, /* tp_internal */ + "_json.Encoder", /* tp_name */ + sizeof(PyEncoderObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + encoder_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 */ + encoder_call, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + encoder_doc, /* tp_doc */ + encoder_traverse, /* tp_traverse */ + encoder_clear, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + encoder_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + encoder_init, /* tp_init */ + 0, /* tp_alloc */ + encoder_new, /* tp_new */ + 0, /* tp_free */ +}; + +static PyMethodDef speedups_methods[] = { + {"encode_basestring_ascii", + (PyCFunction)py_encode_basestring_ascii, + METH_O, + pydoc_encode_basestring_ascii}, + {"scanstring", + (PyCFunction)py_scanstring, + METH_VARARGS, + pydoc_scanstring}, {NULL, NULL, 0, NULL} }; @@ -617,5 +2315,15 @@ init_json(void) { PyObject *m; - m = Py_InitModule3("_json", json_methods, module_doc); + PyScannerType.tp_new = PyType_GenericNew; + if (PyType_Ready(&PyScannerType) < 0) + return; + PyEncoderType.tp_new = PyType_GenericNew; + if (PyType_Ready(&PyEncoderType) < 0) + return; + m = Py_InitModule3("_json", speedups_methods, module_doc); + Py_INCREF((PyObject*)&PyScannerType); + PyModule_AddObject(m, "make_scanner", (PyObject*)&PyScannerType); + Py_INCREF((PyObject*)&PyEncoderType); + PyModule_AddObject(m, "make_encoder", (PyObject*)&PyEncoderType); } From buildbot at python.org Wed Mar 18 01:01:44 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 00:01:44 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo 3.0 Message-ID: <20090318000144.A373E1E4002@bag.python.org> The Buildbot has detected a new failure of x86 gentoo 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20gentoo%203.0/builds/239 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Unknown signal 32 sincerely, -The Buildbot From buildbot at python.org Wed Mar 18 01:17:25 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 00:17:25 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090318001725.447E41E400C@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/483 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Wed Mar 18 02:12:01 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 01:12:01 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu trunk Message-ID: <20090318011201.3FFE81E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%20trunk/builds/967 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: bob.ippolito BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python at rcn.com Wed Mar 18 04:05:21 2009 From: python at rcn.com (Raymond Hettinger) Date: Tue, 17 Mar 2009 20:05:21 -0700 Subject: [Python-checkins] r70438 -python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org><305682430D3843B8B04885CFFC5140BC@RaymondLaptop1><49C01053.6070205@gmail.com> Message-ID: <9FF981AA7E7C4F85899A700B50A86B37@RaymondLaptop1> [Antoine Pitrou] > Or perhaps the examples should be folded by default in the HTML rendering, with > a simple way (a '+' sign or something) to unfold them. This is not even AJAX, > just simple Javascript grafted on an otherwise static HTML page. Does the MS chm file format support embedded Javascript? From python-checkins at python.org Wed Mar 18 09:22:51 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 09:22:51 +0100 (CET) Subject: [Python-checkins] r70444 - in python/trunk/Lib: decimal.py test/test_decimal.py Message-ID: <20090318082251.B909E1E4002@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 09:22:51 2009 New Revision: 70444 Log: Fix bug in _insert_thousands_sep: too much zero padding could be added for 'n' formats with non-repeating thousands-separator. Modified: python/trunk/Lib/decimal.py python/trunk/Lib/test/test_decimal.py Modified: python/trunk/Lib/decimal.py ============================================================================== --- python/trunk/Lib/decimal.py (original) +++ python/trunk/Lib/decimal.py Wed Mar 18 09:22:51 2009 @@ -5621,8 +5621,6 @@ groups = [] for l in _group_lengths(grouping): - if groups: - min_width -= len(sep) if l <= 0: raise ValueError("group length should be positive") # max(..., 1) forces at least 1 digit to the left of a separator @@ -5632,6 +5630,7 @@ min_width -= l if not digits and min_width <= 0: break + min_width -= len(sep) else: l = max(len(digits), min_width, 1) groups.append('0'*(l - len(digits)) + digits[-l:]) Modified: python/trunk/Lib/test/test_decimal.py ============================================================================== --- python/trunk/Lib/test/test_decimal.py (original) +++ python/trunk/Lib/test/test_decimal.py Wed Mar 18 09:22:51 2009 @@ -809,6 +809,28 @@ self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8') self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8') + # zero padding + self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234') + self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234') + self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234') + self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234') + + self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345') + self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345') + self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345') + self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345') + self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345') + self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345') + + self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6') + self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6') + self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6') + self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6') + self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6') + self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6') + self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6') + self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6') + class DecimalArithmeticOperatorsTest(unittest.TestCase): '''Unit tests for all arithmetic operators, binary and unary.''' From python-checkins at python.org Wed Mar 18 09:25:36 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 09:25:36 +0100 (CET) Subject: [Python-checkins] r70445 - in python/branches/py3k: Lib/decimal.py Lib/test/test_decimal.py Message-ID: <20090318082536.C2B861E4002@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 09:25:36 2009 New Revision: 70445 Log: Merged revisions 70444 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70444 | mark.dickinson | 2009-03-18 08:22:51 +0000 (Wed, 18 Mar 2009) | 3 lines Fix bug in _insert_thousands_sep: too much zero padding could be added for 'n' formats with non-repeating thousands-separator. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/decimal.py python/branches/py3k/Lib/test/test_decimal.py Modified: python/branches/py3k/Lib/decimal.py ============================================================================== --- python/branches/py3k/Lib/decimal.py (original) +++ python/branches/py3k/Lib/decimal.py Wed Mar 18 09:25:36 2009 @@ -5690,8 +5690,6 @@ groups = [] for l in _group_lengths(grouping): - if groups: - min_width -= len(sep) if l <= 0: raise ValueError("group length should be positive") # max(..., 1) forces at least 1 digit to the left of a separator @@ -5701,6 +5699,7 @@ min_width -= l if not digits and min_width <= 0: break + min_width -= len(sep) else: l = max(len(digits), min_width, 1) groups.append('0'*(l - len(digits)) + digits[-l:]) Modified: python/branches/py3k/Lib/test/test_decimal.py ============================================================================== --- python/branches/py3k/Lib/test/test_decimal.py (original) +++ python/branches/py3k/Lib/test/test_decimal.py Wed Mar 18 09:25:36 2009 @@ -798,6 +798,28 @@ self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8') self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8') + # zero padding + self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234') + self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234') + self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234') + self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234') + + self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345') + self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345') + self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345') + self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345') + self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345') + self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345') + + self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6') + self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6') + self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6') + self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6') + self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6') + self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6') + self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6') + self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6') + class DecimalArithmeticOperatorsTest(unittest.TestCase): '''Unit tests for all arithmetic operators, binary and unary.''' From python-checkins at python.org Wed Mar 18 09:26:22 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 09:26:22 +0100 (CET) Subject: [Python-checkins] r70446 - python/branches/release26-maint Message-ID: <20090318082622.445601E400C@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 09:26:22 2009 New Revision: 70446 Log: Blocked revisions 70444 via svnmerge ........ r70444 | mark.dickinson | 2009-03-18 08:22:51 +0000 (Wed, 18 Mar 2009) | 3 lines Fix bug in _insert_thousands_sep: too much zero padding could be added for 'n' formats with non-repeating thousands-separator. ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Wed Mar 18 09:27:00 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 09:27:00 +0100 (CET) Subject: [Python-checkins] r70447 - python/branches/release30-maint Message-ID: <20090318082700.231F01E4002@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 09:26:59 2009 New Revision: 70447 Log: Blocked revisions 70445 via svnmerge ................ r70445 | mark.dickinson | 2009-03-18 08:25:36 +0000 (Wed, 18 Mar 2009) | 10 lines Merged revisions 70444 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70444 | mark.dickinson | 2009-03-18 08:22:51 +0000 (Wed, 18 Mar 2009) | 3 lines Fix bug in _insert_thousands_sep: too much zero padding could be added for 'n' formats with non-repeating thousands-separator. ........ ................ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Wed Mar 18 10:16:35 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 09:16:35 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090318091635.CAA261E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/733 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From nnorwitz at gmail.com Wed Mar 18 10:18:08 2009 From: nnorwitz at gmail.com (Neal Norwitz) Date: Wed, 18 Mar 2009 04:18:08 -0500 Subject: [Python-checkins] Python Regression Test Failures basics (1) Message-ID: <20090318091808.GA18926@python.psfb.org> 330 tests OK. 1 test failed: test_fork1 36 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_epoll test_gl test_imgfile test_ioctl test_kqueue test_lib2to3 test_linuxaudiodev test_macos test_macostools test_multiprocessing test_ossaudiodev test_pep277 test_py3kwarn test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_tk test_ttk_guionly test_ttk_textonly test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 7 skips unexpected on linux2: test_multiprocessing test_lib2to3 test_ttk_guionly test_epoll test_tk test_ioctl test_ttk_textonly test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_SimpleHTTPServer test_StringIO test___all__ test___future__ test__locale test_abc test_abstract_numbers 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 test_asyncore 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_buffer test_bufio test_bytes test_bz2 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 test_cmd_line test_cmd_line_script 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_compileall test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_cprofile 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 test_dl test_docxmlrpc test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_epoll test_epoll skipped -- kernel doesn't support epoll() test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_fileio test_float test_fnmatch test_fork1 test test_fork1 failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/fork_wait.py", line 55, in test_wait self.assertEquals(a, range(NUM_THREADS)) AssertionError: [] != [0, 1, 2, 3] test_format test_fpformat test_fractions test_frozen test_ftplib test_funcattrs test_functools test_future test_future3 test_future4 test_future5 test_future_builtins 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_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_httpservers [13045 refs] [13045 refs] [23111 refs] test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_importlib test_index test_inspect test_int test_int_literal test_io test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_json test_kqueue test_kqueue skipped -- test works only on BSD test_largefile test_lib2to3 test_lib2to3 skipped -- No module named myfixes 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_macos test_macos skipped -- No module named MacOS test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_memoryio test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_multiprocessing test_multiprocessing skipped -- OSError raises on RLock creation, see issue 3111! test_mutants test_mutex 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 Expecting 's_push: parser stack overflow' in next line s_push: parser stack overflow 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_pipes test_pkg test_pkgimport test_pkgutil test_platform [14700 refs] [14700 refs] test_plistlib test_poll test_popen [13050 refs] [13050 refs] [13050 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_print test_profile test_profilehooks test_property test_pstats test_pty test_pwd test_py3kwarn test_py3kwarn skipped -- test.test_py3kwarn must be run with the -3 flag test_pyclbr test_pydoc [18639 refs] test_pyexpat test_queue test_quopri [15570 refs] [15570 refs] test_random test_re test_repr test_resource test_rfc822 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 [13045 refs] [13045 refs] [13048 refs] [13045 refs] test_slice test_smtplib test_socket test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort test_sqlite test_ssl 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 [13045 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] [14945 refs] [13260 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] [13045 refs] . [13045 refs] [13045 refs] this bit of output is from a test of stdout in a different process ... [13045 refs] [13045 refs] [13260 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry /tmp/python-test/local/lib/python2.7/test/test_sundry.py:66: DeprecationWarning: The posixfile module is deprecated; fcntl.lockf() provides better locking import posixfile test_symtable test_syntax test_sys [13045 refs] [13045 refs] [13274 refs] [13068 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [13048 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading [16541 refs] [17766 refs] [17582 refs] [17582 refs] [17582 refs] [17582 refs] test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tk test_tk skipped -- No module named _tkinter test_tokenize test_trace test_traceback test_transformer test_ttk_guionly test_ttk_guionly skipped -- No module named _tkinter test_ttk_textonly test_ttk_textonly skipped -- No module named runtktests test_tuple test_typechecks test_ucn test_unary test_undocumented_details 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_urllib2_localnet 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 Unhandled exception in thread started by > Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/fork_wait.py", line 29, in f self.alive[id] = os.getpid() AttributeError: 'NoneType' object has no attribute 'getpid' Unhandled exception in thread started by > Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/fork_wait.py", line 29, in f self.alive[id] = os.getpid() AttributeError: 'NoneType' object has no attribute 'getpid' Unhandled exception in thread started by > Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/fork_wait.py", line 29, in f self.alive[id] = os.getpid() AttributeError: 'NoneType' object has no attribute 'getpid' Unhandled exception in thread started by > Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/fork_wait.py", line 29, in f self.alive[id] = os.getpid() AttributeError: 'NoneType' object has no attribute 'getpid' 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_zipimport_support test_zlib 330 tests OK. 1 test failed: test_fork1 36 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_epoll test_gl test_imgfile test_ioctl test_kqueue test_lib2to3 test_linuxaudiodev test_macos test_macostools test_multiprocessing test_ossaudiodev test_pep277 test_py3kwarn test_scriptpackages test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_tk test_ttk_guionly test_ttk_textonly test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 7 skips unexpected on linux2: test_multiprocessing test_lib2to3 test_ttk_guionly test_epoll test_tk test_ioctl test_ttk_textonly [667180 refs] From buildbot at python.org Wed Mar 18 11:10:52 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 10:10:52 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090318101052.DE1A01E400C@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/176 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/test/test_ftplib.py", line 203, in run asyncore.loop(timeout=0.1, count=1) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 204, in loop poll_fun(timeout, map) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 141, in poll read(obj) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 78, in read obj.handle_error() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 74, in read obj.handle_read_event() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 413, in handle_read_event self.handle_read() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/test/test_ssl.py", line 408, in handle_read self.send(data.lower()) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 519, in send self.initiate_send() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 506, in initiate_send num_sent = dispatcher.send(self, self.out_buffer[:512]) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 349, in send result = self.socket.send(data) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/socket.py", line 165, in _dummy raise error(EBADF, 'Bad file descriptor') error: [Errno 9] Bad file descriptor 1 test failed: test_ftplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Mar 18 11:17:27 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Wed, 18 Mar 2009 11:17:27 +0100 (CET) Subject: [Python-checkins] r70448 - in python/trunk/PC/VC6: _ssl.mak build_ssl.py readme.txt Message-ID: <20090318101727.1486F1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Wed Mar 18 11:17:26 2009 New Revision: 70448 Log: Updated openssl support on VC6. (openssl-0.9.6g is old, cannot compile with _ssl.c) If you use http://svn.python.org/projects/external/openssl-0.9.8g, Perl is not needed. This scheme was ported from PCBuild. Modified: python/trunk/PC/VC6/_ssl.mak python/trunk/PC/VC6/build_ssl.py python/trunk/PC/VC6/readme.txt Modified: python/trunk/PC/VC6/_ssl.mak ============================================================================== --- python/trunk/PC/VC6/_ssl.mak (original) +++ python/trunk/PC/VC6/_ssl.mak Wed Mar 18 11:17:26 2009 @@ -3,19 +3,20 @@ 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 +LFLAGS=/nodefaultlib:"msvcrt" !ELSE MODULE=_ssl.pyd TEMP_DIR=x86-temp-release/_ssl CFLAGS=/Ox /MD /LD /DWIN32 -SSL_LIB_DIR=$(SSL_DIR)/out32 +LFLAGS= !ENDIF INCLUDES=-I ../../Include -I .. -I $(SSL_DIR)/inc32 +SSL_LIB_DIR=$(SSL_DIR)/out32 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) ../*.h ../../Include/*.h @if not exist "$(TEMP_DIR)/." mkdir "$(TEMP_DIR)" - cl /nologo $(SOURCE) $(CFLAGS) /Fo$(TEMP_DIR)\$*.obj $(INCLUDES) /link /out:$(MODULE) $(LIBS) + cl /nologo $(SOURCE) $(CFLAGS) /Fo$(TEMP_DIR)\$*.obj $(INCLUDES) /link /out:$(MODULE) $(LIBS) $(LFLAGS) Modified: python/trunk/PC/VC6/build_ssl.py ============================================================================== --- python/trunk/PC/VC6/build_ssl.py (original) +++ python/trunk/PC/VC6/build_ssl.py Wed Mar 18 11:17:26 2009 @@ -13,7 +13,7 @@ # it should configure and build SSL, then build the ssl Python extension # without intervention. -import os, sys, re +import os, sys, re, shutil # Find all "foo.exe" files on the PATH. def find_all_on_path(filename, extras = None): @@ -51,7 +51,6 @@ 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. @@ -59,7 +58,8 @@ candidates = [] for s in sources: try: - s = os.path.abspath(s) + # note: do not abspath s; the build will fail if any + # higher up directory name has spaces in it. fnames = os.listdir(s) except os.error: fnames = [] @@ -82,11 +82,54 @@ print "Found an SSL directory at '%s'" % (best_name,) else: print "Could not find an SSL directory in '%s'" % (sources,) + sys.stdout.flush() return best_name +def fix_makefile(makefile): + """Fix some stuff in all makefiles + """ + if not os.path.isfile(makefile): + return + # 2.4 compatibility + fin = open(makefile) + if 1: # with open(makefile) as fin: + lines = fin.readlines() + fin.close() + fout = open(makefile, 'w') + if 1: # with open(makefile, 'w') as fout: + for line in lines: + if line.startswith("PERL="): + continue + if line.startswith("CP="): + line = "CP=copy\n" + if line.startswith("MKDIR="): + line = "MKDIR=mkdir\n" + if line.startswith("CFLAG="): + line = line.strip() + for algo in ("RC5", "MDC2", "IDEA"): + noalgo = " -DOPENSSL_NO_%s" % algo + if noalgo not in line: + line = line + noalgo + line = line + '\n' + fout.write(line) + fout.close() + +def run_configure(configure, do_script): + print "perl Configure "+configure + os.system("perl Configure "+configure) + print do_script + os.system(do_script) + def main(): debug = "-d" in sys.argv build_all = "-a" in sys.argv + if 1: # Win32 + arch = "x86" + configure = "VC-WIN32" + do_script = "ms\\do_nasm" + makefile="ms\\nt.mak" + m32 = makefile + configure += " no-idea no-rc5 no-mdc2" make_flags = "" if build_all: make_flags = "-a" @@ -95,11 +138,12 @@ 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,) + print "No Perl installation was found. Existing Makefiles are used." + else: + print "Found a working perl at '%s'" % (perl,) + sys.stdout.flush() # Look for SSL 3 levels up from pcbuild - ie, same place zlib etc all live. - ssl_dir = find_best_ssl_dir(("../../..",)) + ssl_dir = find_best_ssl_dir(("..\\..\\..",)) if ssl_dir is None: sys.exit(1) @@ -107,49 +151,44 @@ 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")): + # Due to a bug in this script, the makefile sometimes ended up empty + # Force a regeneration if it is. + if not os.path.isfile(makefile) or os.path.getsize(makefile)==0: + if perl is None: + print "Perl is required to build the makefiles!" + sys.exit(1) + print "Creating the makefiles..." + sys.stdout.flush() # Put our working Perl at the front of our path - os.environ["PATH"] = os.path.split(perl)[0] + \ + os.environ["PATH"] = os.path.dirname(perl) + \ 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 + run_configure(configure, do_script) + if debug: + print "OpenSSL debug builds aren't supported." + #if arch=="x86" and debug: + # # the do_masm script in openssl doesn't generate a debug + # # build makefile so we generate it here: + # os.system("perl util\mk1mf.pl debug "+configure+" >"+makefile) + + fix_makefile(makefile) + shutil.copy(r"crypto\buildinf.h", r"crypto\buildinf_%s.h" % arch) + shutil.copy(r"crypto\opensslconf.h", r"crypto\opensslconf_%s.h" % arch) # 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) + shutil.copy(r"crypto\buildinf_%s.h" % arch, r"crypto\buildinf.h") + shutil.copy(r"crypto\opensslconf_%s.h" % arch, r"crypto\opensslconf.h") + + #makeCommand = "nmake /nologo PERL=\"%s\" -f \"%s\"" %(perl, makefile) + makeCommand = "nmake /nologo -f \"%s\"" % makefile + print "Executing ssl makefiles:", makeCommand + sys.stdout.flush() + rc = os.system(makeCommand) + if rc: + print "Executing "+makefile+" failed" + print rc + sys.exit(rc) finally: os.chdir(old_cd) # And finally, we can build the _ssl module itself for Python. Modified: python/trunk/PC/VC6/readme.txt ============================================================================== --- python/trunk/PC/VC6/readme.txt (original) +++ python/trunk/PC/VC6/readme.txt Wed Mar 18 11:17:26 2009 @@ -203,13 +203,13 @@ http://www.openssl.org You (probably) don't want the "engine" code. For example, get - openssl-0.9.6g.tar.gz + openssl-0.9.8g.tar.gz not - openssl-engine-0.9.6g.tar.gz + openssl-engine-0.9.8g.tar.gz Unpack into the "dist" directory, retaining the folder name from the archive - for example, the latest stable OpenSSL will install as - dist/openssl-0.9.6g + dist/openssl-0.9.8g You can (theoretically) use any version of OpenSSL you like - the build process will automatically select the latest version. From python-checkins at python.org Wed Mar 18 11:26:33 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Wed, 18 Mar 2009 11:26:33 +0100 (CET) Subject: [Python-checkins] r70449 - in python/branches/release26-maint: PC/VC6/_ssl.mak PC/VC6/build_ssl.py PC/VC6/readme.txt Message-ID: <20090318102633.79C9B1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Wed Mar 18 11:26:33 2009 New Revision: 70449 Log: Merged revisions 70448 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70448 | hirokazu.yamamoto | 2009-03-18 19:17:26 +0900 | 3 lines Updated openssl support on VC6. (openssl-0.9.6g is old, cannot compile with _ssl.c) If you use http://svn.python.org/projects/external/openssl-0.9.8g, Perl is not needed. This scheme was ported from PCBuild. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/PC/VC6/_ssl.mak python/branches/release26-maint/PC/VC6/build_ssl.py python/branches/release26-maint/PC/VC6/readme.txt Modified: python/branches/release26-maint/PC/VC6/_ssl.mak ============================================================================== --- python/branches/release26-maint/PC/VC6/_ssl.mak (original) +++ python/branches/release26-maint/PC/VC6/_ssl.mak Wed Mar 18 11:26:33 2009 @@ -3,19 +3,20 @@ 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 +LFLAGS=/nodefaultlib:"msvcrt" !ELSE MODULE=_ssl.pyd TEMP_DIR=x86-temp-release/_ssl CFLAGS=/Ox /MD /LD /DWIN32 -SSL_LIB_DIR=$(SSL_DIR)/out32 +LFLAGS= !ENDIF INCLUDES=-I ../../Include -I .. -I $(SSL_DIR)/inc32 +SSL_LIB_DIR=$(SSL_DIR)/out32 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) ../*.h ../../Include/*.h @if not exist "$(TEMP_DIR)/." mkdir "$(TEMP_DIR)" - cl /nologo $(SOURCE) $(CFLAGS) /Fo$(TEMP_DIR)\$*.obj $(INCLUDES) /link /out:$(MODULE) $(LIBS) + cl /nologo $(SOURCE) $(CFLAGS) /Fo$(TEMP_DIR)\$*.obj $(INCLUDES) /link /out:$(MODULE) $(LIBS) $(LFLAGS) Modified: python/branches/release26-maint/PC/VC6/build_ssl.py ============================================================================== --- python/branches/release26-maint/PC/VC6/build_ssl.py (original) +++ python/branches/release26-maint/PC/VC6/build_ssl.py Wed Mar 18 11:26:33 2009 @@ -13,7 +13,7 @@ # it should configure and build SSL, then build the ssl Python extension # without intervention. -import os, sys, re +import os, sys, re, shutil # Find all "foo.exe" files on the PATH. def find_all_on_path(filename, extras = None): @@ -51,7 +51,6 @@ 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. @@ -59,7 +58,8 @@ candidates = [] for s in sources: try: - s = os.path.abspath(s) + # note: do not abspath s; the build will fail if any + # higher up directory name has spaces in it. fnames = os.listdir(s) except os.error: fnames = [] @@ -82,11 +82,54 @@ print "Found an SSL directory at '%s'" % (best_name,) else: print "Could not find an SSL directory in '%s'" % (sources,) + sys.stdout.flush() return best_name +def fix_makefile(makefile): + """Fix some stuff in all makefiles + """ + if not os.path.isfile(makefile): + return + # 2.4 compatibility + fin = open(makefile) + if 1: # with open(makefile) as fin: + lines = fin.readlines() + fin.close() + fout = open(makefile, 'w') + if 1: # with open(makefile, 'w') as fout: + for line in lines: + if line.startswith("PERL="): + continue + if line.startswith("CP="): + line = "CP=copy\n" + if line.startswith("MKDIR="): + line = "MKDIR=mkdir\n" + if line.startswith("CFLAG="): + line = line.strip() + for algo in ("RC5", "MDC2", "IDEA"): + noalgo = " -DOPENSSL_NO_%s" % algo + if noalgo not in line: + line = line + noalgo + line = line + '\n' + fout.write(line) + fout.close() + +def run_configure(configure, do_script): + print "perl Configure "+configure + os.system("perl Configure "+configure) + print do_script + os.system(do_script) + def main(): debug = "-d" in sys.argv build_all = "-a" in sys.argv + if 1: # Win32 + arch = "x86" + configure = "VC-WIN32" + do_script = "ms\\do_nasm" + makefile="ms\\nt.mak" + m32 = makefile + configure += " no-idea no-rc5 no-mdc2" make_flags = "" if build_all: make_flags = "-a" @@ -95,11 +138,12 @@ 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,) + print "No Perl installation was found. Existing Makefiles are used." + else: + print "Found a working perl at '%s'" % (perl,) + sys.stdout.flush() # Look for SSL 3 levels up from pcbuild - ie, same place zlib etc all live. - ssl_dir = find_best_ssl_dir(("../../..",)) + ssl_dir = find_best_ssl_dir(("..\\..\\..",)) if ssl_dir is None: sys.exit(1) @@ -107,49 +151,44 @@ 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")): + # Due to a bug in this script, the makefile sometimes ended up empty + # Force a regeneration if it is. + if not os.path.isfile(makefile) or os.path.getsize(makefile)==0: + if perl is None: + print "Perl is required to build the makefiles!" + sys.exit(1) + print "Creating the makefiles..." + sys.stdout.flush() # Put our working Perl at the front of our path - os.environ["PATH"] = os.path.split(perl)[0] + \ + os.environ["PATH"] = os.path.dirname(perl) + \ 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 + run_configure(configure, do_script) + if debug: + print "OpenSSL debug builds aren't supported." + #if arch=="x86" and debug: + # # the do_masm script in openssl doesn't generate a debug + # # build makefile so we generate it here: + # os.system("perl util\mk1mf.pl debug "+configure+" >"+makefile) + + fix_makefile(makefile) + shutil.copy(r"crypto\buildinf.h", r"crypto\buildinf_%s.h" % arch) + shutil.copy(r"crypto\opensslconf.h", r"crypto\opensslconf_%s.h" % arch) # 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) + shutil.copy(r"crypto\buildinf_%s.h" % arch, r"crypto\buildinf.h") + shutil.copy(r"crypto\opensslconf_%s.h" % arch, r"crypto\opensslconf.h") + + #makeCommand = "nmake /nologo PERL=\"%s\" -f \"%s\"" %(perl, makefile) + makeCommand = "nmake /nologo -f \"%s\"" % makefile + print "Executing ssl makefiles:", makeCommand + sys.stdout.flush() + rc = os.system(makeCommand) + if rc: + print "Executing "+makefile+" failed" + print rc + sys.exit(rc) finally: os.chdir(old_cd) # And finally, we can build the _ssl module itself for Python. Modified: python/branches/release26-maint/PC/VC6/readme.txt ============================================================================== --- python/branches/release26-maint/PC/VC6/readme.txt (original) +++ python/branches/release26-maint/PC/VC6/readme.txt Wed Mar 18 11:26:33 2009 @@ -203,13 +203,13 @@ http://www.openssl.org You (probably) don't want the "engine" code. For example, get - openssl-0.9.6g.tar.gz + openssl-0.9.8g.tar.gz not - openssl-engine-0.9.6g.tar.gz + openssl-engine-0.9.8g.tar.gz Unpack into the "dist" directory, retaining the folder name from the archive - for example, the latest stable OpenSSL will install as - dist/openssl-0.9.6g + dist/openssl-0.9.8g You can (theoretically) use any version of OpenSSL you like - the build process will automatically select the latest version. From ncoghlan at gmail.com Wed Mar 18 12:28:16 2009 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 18 Mar 2009 21:28:16 +1000 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: <20090317220545.GA17150@amk-desktop.matrixgroup.net> References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> <793BDA8FBE044BD5B4C3FC46DAB140EB@RaymondLaptop1> <49C01220.4010408@v.loewis.de> <992AED9B2B5B415185282009E7D2B8F2@RaymondLaptop1> <49C016B1.40209@v.loewis.de> <25FC15A3334A4B98AE4CB76611FBE596@RaymondLaptop1> <20090317220545.GA17150@amk-desktop.matrixgroup.net> Message-ID: <49C0DAD0.2040100@gmail.com> A.M. Kuchling wrote: > Most developers work on network-connected machines. Even if they're > not network-connected, machines have large enough hard-drives so that > everyone can keep the formatted HTML docs around. Or else they have a second machine which *does* have a 'net connection that they use for looking things up. However, the compiled HTML docs in the Windows binaries are very handy, so I suspect that is going to impose some limits on how tricky Sphinx can get with Javascript. Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- From buildbot at python.org Wed Mar 18 12:39:35 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 11:39:35 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 2.6 Message-ID: <20090318113935.D548B1E400C@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%202.6/builds/173 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Mar 18 12:39:47 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Wed, 18 Mar 2009 12:39:47 +0100 (CET) Subject: [Python-checkins] r70450 - in python/branches/py3k: PC/VC6/_ssl.mak PC/VC6/build_ssl.py PC/VC6/readme.txt Message-ID: <20090318113947.512701E400C@bag.python.org> Author: hirokazu.yamamoto Date: Wed Mar 18 12:39:46 2009 New Revision: 70450 Log: Merged revisions 70448 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70448 | hirokazu.yamamoto | 2009-03-18 19:17:26 +0900 | 3 lines Updated openssl support on VC6. (openssl-0.9.6g is old, cannot compile with _ssl.c) If you use http://svn.python.org/projects/external/openssl-0.9.8g, Perl is not needed. This scheme was ported from PCBuild. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/PC/VC6/_ssl.mak python/branches/py3k/PC/VC6/build_ssl.py python/branches/py3k/PC/VC6/readme.txt Modified: python/branches/py3k/PC/VC6/_ssl.mak ============================================================================== --- python/branches/py3k/PC/VC6/_ssl.mak (original) +++ python/branches/py3k/PC/VC6/_ssl.mak Wed Mar 18 12:39:46 2009 @@ -3,19 +3,20 @@ 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 +LFLAGS=/nodefaultlib:"msvcrt" !ELSE MODULE=_ssl.pyd TEMP_DIR=x86-temp-release/_ssl CFLAGS=/Ox /MD /LD /DWIN32 -SSL_LIB_DIR=$(SSL_DIR)/out32 +LFLAGS= !ENDIF INCLUDES=-I ../../Include -I .. -I $(SSL_DIR)/inc32 +SSL_LIB_DIR=$(SSL_DIR)/out32 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) ../*.h ../../Include/*.h @if not exist "$(TEMP_DIR)/." mkdir "$(TEMP_DIR)" - cl /nologo $(SOURCE) $(CFLAGS) /Fo$(TEMP_DIR)\$*.obj $(INCLUDES) /link /out:$(MODULE) $(LIBS) + cl /nologo $(SOURCE) $(CFLAGS) /Fo$(TEMP_DIR)\$*.obj $(INCLUDES) /link /out:$(MODULE) $(LIBS) $(LFLAGS) Modified: python/branches/py3k/PC/VC6/build_ssl.py ============================================================================== --- python/branches/py3k/PC/VC6/build_ssl.py (original) +++ python/branches/py3k/PC/VC6/build_ssl.py Wed Mar 18 12:39:46 2009 @@ -13,7 +13,7 @@ # it should configure and build SSL, then build the ssl Python extension # without intervention. -import os, sys, re +import os, sys, re, shutil # Find all "foo.exe" files on the PATH. def find_all_on_path(filename, extras = None): @@ -42,16 +42,15 @@ if rc: continue return perl - print "Can not find a suitable PERL:" + print("Can not find a suitable PERL:") if perls: - print " the following perl interpreters were found:" + print(" the following perl interpreters were found:") for p in perls: - print " ", p - print " None of these versions appear suitable for building OpenSSL" + 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" + print(" NO perl interpreters were found on this machine at all!") + print(" Please install ActivePerl and ensure it appears on your path") return None # Locate the best SSL directory given a few roots to look into. @@ -59,7 +58,8 @@ candidates = [] for s in sources: try: - s = os.path.abspath(s) + # note: do not abspath s; the build will fail if any + # higher up directory name has spaces in it. fnames = os.listdir(s) except os.error: fnames = [] @@ -79,14 +79,57 @@ best_parts = parts best_name = c if best_name is not None: - print "Found an SSL directory at '%s'" % (best_name,) + print("Found an SSL directory at '%s'" % (best_name,)) else: - print "Could not find an SSL directory in '%s'" % (sources,) + print("Could not find an SSL directory in '%s'" % (sources,)) + sys.stdout.flush() return best_name +def fix_makefile(makefile): + """Fix some stuff in all makefiles + """ + if not os.path.isfile(makefile): + return + # 2.4 compatibility + fin = open(makefile) + if 1: # with open(makefile) as fin: + lines = fin.readlines() + fin.close() + fout = open(makefile, 'w') + if 1: # with open(makefile, 'w') as fout: + for line in lines: + if line.startswith("PERL="): + continue + if line.startswith("CP="): + line = "CP=copy\n" + if line.startswith("MKDIR="): + line = "MKDIR=mkdir\n" + if line.startswith("CFLAG="): + line = line.strip() + for algo in ("RC5", "MDC2", "IDEA"): + noalgo = " -DOPENSSL_NO_%s" % algo + if noalgo not in line: + line = line + noalgo + line = line + '\n' + fout.write(line) + fout.close() + +def run_configure(configure, do_script): + print("perl Configure "+configure) + os.system("perl Configure "+configure) + print(do_script) + os.system(do_script) + def main(): debug = "-d" in sys.argv build_all = "-a" in sys.argv + if 1: # Win32 + arch = "x86" + configure = "VC-WIN32" + do_script = "ms\\do_nasm" + makefile="ms\\nt.mak" + m32 = makefile + configure += " no-idea no-rc5 no-mdc2" make_flags = "" if build_all: make_flags = "-a" @@ -95,11 +138,12 @@ 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,) + print("No Perl installation was found. Existing Makefiles are used.") + else: + print("Found a working perl at '%s'" % (perl,)) + sys.stdout.flush() # Look for SSL 3 levels up from pcbuild - ie, same place zlib etc all live. - ssl_dir = find_best_ssl_dir(("../../..",)) + ssl_dir = find_best_ssl_dir(("..\\..\\..",)) if ssl_dir is None: sys.exit(1) @@ -107,49 +151,44 @@ 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..." + # Due to a bug in this script, the makefile sometimes ended up empty + # Force a regeneration if it is. + if not os.path.isfile(makefile) or os.path.getsize(makefile)==0: + if perl is None: + print("Perl is required to build the makefiles!") + sys.exit(1) + + print("Creating the makefiles...") + sys.stdout.flush() # Put our working Perl at the front of our path - os.environ["PATH"] = os.path.split(perl)[0] + \ + os.environ["PATH"] = os.path.dirname(perl) + \ 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 + run_configure(configure, do_script) + if debug: + print("OpenSSL debug builds aren't supported.") + #if arch=="x86" and debug: + # # the do_masm script in openssl doesn't generate a debug + # # build makefile so we generate it here: + # os.system("perl util\mk1mf.pl debug "+configure+" >"+makefile) + + fix_makefile(makefile) + shutil.copy(r"crypto\buildinf.h", r"crypto\buildinf_%s.h" % arch) + shutil.copy(r"crypto\opensslconf.h", r"crypto\opensslconf_%s.h" % arch) # 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) + shutil.copy(r"crypto\buildinf_%s.h" % arch, r"crypto\buildinf.h") + shutil.copy(r"crypto\opensslconf_%s.h" % arch, r"crypto\opensslconf.h") + + #makeCommand = "nmake /nologo PERL=\"%s\" -f \"%s\"" %(perl, makefile) + makeCommand = "nmake /nologo -f \"%s\"" % makefile + print("Executing ssl makefiles:", makeCommand) + sys.stdout.flush() + rc = os.system(makeCommand) + if rc: + print("Executing "+makefile+" failed") + print(rc) + sys.exit(rc) finally: os.chdir(old_cd) # And finally, we can build the _ssl module itself for Python. Modified: python/branches/py3k/PC/VC6/readme.txt ============================================================================== --- python/branches/py3k/PC/VC6/readme.txt (original) +++ python/branches/py3k/PC/VC6/readme.txt Wed Mar 18 12:39:46 2009 @@ -150,13 +150,13 @@ http://www.openssl.org You (probably) don't want the "engine" code. For example, get - openssl-0.9.6g.tar.gz + openssl-0.9.8g.tar.gz not - openssl-engine-0.9.6g.tar.gz + openssl-engine-0.9.8g.tar.gz Unpack into the "dist" directory, retaining the folder name from the archive - for example, the latest stable OpenSSL will install as - dist/openssl-0.9.6g + dist/openssl-0.9.8g You can (theoretically) use any version of OpenSSL you like - the build process will automatically select the latest version. From python-checkins at python.org Wed Mar 18 13:46:35 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Wed, 18 Mar 2009 13:46:35 +0100 (CET) Subject: [Python-checkins] r70451 - in python/branches/release30-maint: PC/VC6/_ssl.mak PC/VC6/build_ssl.py PC/VC6/readme.txt Message-ID: <20090318124635.379281E4002@bag.python.org> Author: hirokazu.yamamoto Date: Wed Mar 18 13:46:34 2009 New Revision: 70451 Log: Merged revisions 70450 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70450 | hirokazu.yamamoto | 2009-03-18 20:39:46 +0900 | 11 lines Merged revisions 70448 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70448 | hirokazu.yamamoto | 2009-03-18 19:17:26 +0900 | 3 lines Updated openssl support on VC6. (openssl-0.9.6g is old, cannot compile with _ssl.c) If you use http://svn.python.org/projects/external/openssl-0.9.8g, Perl is not needed. This scheme was ported from PCBuild. ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/PC/VC6/_ssl.mak python/branches/release30-maint/PC/VC6/build_ssl.py python/branches/release30-maint/PC/VC6/readme.txt Modified: python/branches/release30-maint/PC/VC6/_ssl.mak ============================================================================== --- python/branches/release30-maint/PC/VC6/_ssl.mak (original) +++ python/branches/release30-maint/PC/VC6/_ssl.mak Wed Mar 18 13:46:34 2009 @@ -3,19 +3,20 @@ 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 +LFLAGS=/nodefaultlib:"msvcrt" !ELSE MODULE=_ssl.pyd TEMP_DIR=x86-temp-release/_ssl CFLAGS=/Ox /MD /LD /DWIN32 -SSL_LIB_DIR=$(SSL_DIR)/out32 +LFLAGS= !ENDIF INCLUDES=-I ../../Include -I .. -I $(SSL_DIR)/inc32 +SSL_LIB_DIR=$(SSL_DIR)/out32 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) ../*.h ../../Include/*.h @if not exist "$(TEMP_DIR)/." mkdir "$(TEMP_DIR)" - cl /nologo $(SOURCE) $(CFLAGS) /Fo$(TEMP_DIR)\$*.obj $(INCLUDES) /link /out:$(MODULE) $(LIBS) + cl /nologo $(SOURCE) $(CFLAGS) /Fo$(TEMP_DIR)\$*.obj $(INCLUDES) /link /out:$(MODULE) $(LIBS) $(LFLAGS) Modified: python/branches/release30-maint/PC/VC6/build_ssl.py ============================================================================== --- python/branches/release30-maint/PC/VC6/build_ssl.py (original) +++ python/branches/release30-maint/PC/VC6/build_ssl.py Wed Mar 18 13:46:34 2009 @@ -13,7 +13,7 @@ # it should configure and build SSL, then build the ssl Python extension # without intervention. -import os, sys, re +import os, sys, re, shutil # Find all "foo.exe" files on the PATH. def find_all_on_path(filename, extras = None): @@ -42,16 +42,15 @@ if rc: continue return perl - print "Can not find a suitable PERL:" + print("Can not find a suitable PERL:") if perls: - print " the following perl interpreters were found:" + print(" the following perl interpreters were found:") for p in perls: - print " ", p - print " None of these versions appear suitable for building OpenSSL" + 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" + print(" NO perl interpreters were found on this machine at all!") + print(" Please install ActivePerl and ensure it appears on your path") return None # Locate the best SSL directory given a few roots to look into. @@ -59,7 +58,8 @@ candidates = [] for s in sources: try: - s = os.path.abspath(s) + # note: do not abspath s; the build will fail if any + # higher up directory name has spaces in it. fnames = os.listdir(s) except os.error: fnames = [] @@ -79,14 +79,57 @@ best_parts = parts best_name = c if best_name is not None: - print "Found an SSL directory at '%s'" % (best_name,) + print("Found an SSL directory at '%s'" % (best_name,)) else: - print "Could not find an SSL directory in '%s'" % (sources,) + print("Could not find an SSL directory in '%s'" % (sources,)) + sys.stdout.flush() return best_name +def fix_makefile(makefile): + """Fix some stuff in all makefiles + """ + if not os.path.isfile(makefile): + return + # 2.4 compatibility + fin = open(makefile) + if 1: # with open(makefile) as fin: + lines = fin.readlines() + fin.close() + fout = open(makefile, 'w') + if 1: # with open(makefile, 'w') as fout: + for line in lines: + if line.startswith("PERL="): + continue + if line.startswith("CP="): + line = "CP=copy\n" + if line.startswith("MKDIR="): + line = "MKDIR=mkdir\n" + if line.startswith("CFLAG="): + line = line.strip() + for algo in ("RC5", "MDC2", "IDEA"): + noalgo = " -DOPENSSL_NO_%s" % algo + if noalgo not in line: + line = line + noalgo + line = line + '\n' + fout.write(line) + fout.close() + +def run_configure(configure, do_script): + print("perl Configure "+configure) + os.system("perl Configure "+configure) + print(do_script) + os.system(do_script) + def main(): debug = "-d" in sys.argv build_all = "-a" in sys.argv + if 1: # Win32 + arch = "x86" + configure = "VC-WIN32" + do_script = "ms\\do_nasm" + makefile="ms\\nt.mak" + m32 = makefile + configure += " no-idea no-rc5 no-mdc2" make_flags = "" if build_all: make_flags = "-a" @@ -95,11 +138,12 @@ 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,) + print("No Perl installation was found. Existing Makefiles are used.") + else: + print("Found a working perl at '%s'" % (perl,)) + sys.stdout.flush() # Look for SSL 3 levels up from pcbuild - ie, same place zlib etc all live. - ssl_dir = find_best_ssl_dir(("../../..",)) + ssl_dir = find_best_ssl_dir(("..\\..\\..",)) if ssl_dir is None: sys.exit(1) @@ -107,49 +151,44 @@ 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..." + # Due to a bug in this script, the makefile sometimes ended up empty + # Force a regeneration if it is. + if not os.path.isfile(makefile) or os.path.getsize(makefile)==0: + if perl is None: + print("Perl is required to build the makefiles!") + sys.exit(1) + + print("Creating the makefiles...") + sys.stdout.flush() # Put our working Perl at the front of our path - os.environ["PATH"] = os.path.split(perl)[0] + \ + os.environ["PATH"] = os.path.dirname(perl) + \ 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 + run_configure(configure, do_script) + if debug: + print("OpenSSL debug builds aren't supported.") + #if arch=="x86" and debug: + # # the do_masm script in openssl doesn't generate a debug + # # build makefile so we generate it here: + # os.system("perl util\mk1mf.pl debug "+configure+" >"+makefile) + + fix_makefile(makefile) + shutil.copy(r"crypto\buildinf.h", r"crypto\buildinf_%s.h" % arch) + shutil.copy(r"crypto\opensslconf.h", r"crypto\opensslconf_%s.h" % arch) # 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) + shutil.copy(r"crypto\buildinf_%s.h" % arch, r"crypto\buildinf.h") + shutil.copy(r"crypto\opensslconf_%s.h" % arch, r"crypto\opensslconf.h") + + #makeCommand = "nmake /nologo PERL=\"%s\" -f \"%s\"" %(perl, makefile) + makeCommand = "nmake /nologo -f \"%s\"" % makefile + print("Executing ssl makefiles:", makeCommand) + sys.stdout.flush() + rc = os.system(makeCommand) + if rc: + print("Executing "+makefile+" failed") + print(rc) + sys.exit(rc) finally: os.chdir(old_cd) # And finally, we can build the _ssl module itself for Python. Modified: python/branches/release30-maint/PC/VC6/readme.txt ============================================================================== --- python/branches/release30-maint/PC/VC6/readme.txt (original) +++ python/branches/release30-maint/PC/VC6/readme.txt Wed Mar 18 13:46:34 2009 @@ -150,13 +150,13 @@ http://www.openssl.org You (probably) don't want the "engine" code. For example, get - openssl-0.9.6g.tar.gz + openssl-0.9.8g.tar.gz not - openssl-engine-0.9.6g.tar.gz + openssl-engine-0.9.8g.tar.gz Unpack into the "dist" directory, retaining the folder name from the archive - for example, the latest stable OpenSSL will install as - dist/openssl-0.9.6g + dist/openssl-0.9.8g You can (theoretically) use any version of OpenSSL you like - the build process will automatically select the latest version. From buildbot at python.org Wed Mar 18 13:57:47 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 12:57:47 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090318125748.0D6BB1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/485 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Wed Mar 18 14:55:22 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 13:55:22 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.0 Message-ID: <20090318135523.486111E402E@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.0/builds/208 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/3.0.heller-x86-osx5/build/Lib/multiprocessing/managers.py", line 188, in handle_request result = func(c, *args, **kwds) File "/Users/buildbot/buildarea/3.0.heller-x86-osx5/build/Lib/multiprocessing/managers.py", line 306, in debug_info keys.sort() TypeError: unorderable types: str() < int() 1 test failed: test_multiprocessing sincerely, -The Buildbot From python-checkins at python.org Wed Mar 18 15:47:41 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 15:47:41 +0100 (CET) Subject: [Python-checkins] r70452 - in python/branches/py3k: Misc/NEWS Modules/_testcapimodule.c Objects/unicodeobject.c Message-ID: <20090318144741.DABD91E40A5@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 15:47:41 2009 New Revision: 70452 Log: Issue 4474: On platforms with sizeof(wchar_t) == 4 and sizeof(Py_UNICODE) == 2, PyUnicode_FromWideChar now converts each character outside the BMP to the appropriate surrogate pair. Thanks Victor Stinner for the patch. Modified: python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_testcapimodule.c python/branches/py3k/Objects/unicodeobject.c Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Mar 18 15:47:41 2009 @@ -12,6 +12,10 @@ Core and Builtins ----------------- +- Issue #4474: PyUnicode_FromWideChar now converts characters outside + the BMP to surrogate pairs, on systems with sizeof(wchar_t) == 4 + and sizeof(Py_UNICODE) == 2. + - Issue #5237: Allow auto-numbered fields in str.format(). For example: '{} {}'.format(1, 2) == '1 2'. Modified: python/branches/py3k/Modules/_testcapimodule.c ============================================================================== --- python/branches/py3k/Modules/_testcapimodule.c (original) +++ python/branches/py3k/Modules/_testcapimodule.c Wed Mar 18 15:47:41 2009 @@ -708,6 +708,50 @@ } static PyObject * +test_widechar(PyObject *self) +{ +#if defined(SIZEOF_WCHAR_T) && (SIZEOF_WCHAR_T == 4) + const wchar_t wtext[2] = {(wchar_t)0x10ABCDu}; + size_t wtextlen = 1; +#else + const wchar_t wtext[3] = {(wchar_t)0xDBEAu, (wchar_t)0xDFCDu}; + size_t wtextlen = 2; +#endif + PyObject *wide, *utf8; + + wide = PyUnicode_FromWideChar(wtext, wtextlen); + if (wide == NULL) + return NULL; + + utf8 = PyUnicode_FromString("\xf4\x8a\xaf\x8d"); + if (utf8 == NULL) { + Py_DECREF(wide); + return NULL; + } + + if (PyUnicode_GET_SIZE(wide) != PyUnicode_GET_SIZE(utf8)) { + Py_DECREF(wide); + Py_DECREF(utf8); + return raiseTestError("test_widechar", + "wide string and utf8 string " + "have different length"); + } + if (PyUnicode_Compare(wide, utf8)) { + Py_DECREF(wide); + Py_DECREF(utf8); + if (PyErr_Occurred()) + return NULL; + return raiseTestError("test_widechar", + "wide string and utf8 string " + "are different"); + } + + Py_DECREF(wide); + Py_DECREF(utf8); + Py_RETURN_NONE; +} + +static PyObject * test_empty_argparse(PyObject *self) { /* Test that formats can begin with '|'. See issue #4720. */ @@ -1206,6 +1250,7 @@ {"test_s_code", (PyCFunction)test_s_code, METH_NOARGS}, {"test_u_code", (PyCFunction)test_u_code, METH_NOARGS}, {"test_Z_code", (PyCFunction)test_Z_code, METH_NOARGS}, + {"test_widechar", (PyCFunction)test_widechar, METH_NOARGS}, #ifdef WITH_THREAD {"_test_thread_state", test_thread_state, METH_VARARGS}, {"_pending_threadfunc", pending_threadfunc, METH_VARARGS}, Modified: python/branches/py3k/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k/Objects/unicodeobject.c (original) +++ python/branches/py3k/Objects/unicodeobject.c Wed Mar 18 15:47:41 2009 @@ -561,6 +561,66 @@ #ifdef HAVE_WCHAR_H +#if (Py_UNICODE_SIZE == 2) && defined(SIZEOF_WCHAR_T) && (SIZEOF_WCHAR_T == 4) +# define CONVERT_WCHAR_TO_SURROGATES +#endif + +#ifdef CONVERT_WCHAR_TO_SURROGATES + +/* Here sizeof(wchar_t) is 4 but Py_UNICODE_SIZE == 2, so we need + to convert from UTF32 to UTF16. */ + +PyObject *PyUnicode_FromWideChar(register const wchar_t *w, + Py_ssize_t size) +{ + PyUnicodeObject *unicode; + register Py_ssize_t i; + Py_ssize_t alloc; + const wchar_t *orig_w; + + if (w == NULL) { + if (size == 0) + return PyUnicode_FromStringAndSize(NULL, 0); + PyErr_BadInternalCall(); + return NULL; + } + + if (size == -1) { + size = wcslen(w); + } + + alloc = size; + orig_w = w; + for (i = size; i > 0; i--) { + if (*w > 0xFFFF) + alloc++; + w++; + } + w = orig_w; + unicode = _PyUnicode_New(alloc); + if (!unicode) + return NULL; + + /* Copy the wchar_t data into the new object */ + { + register Py_UNICODE *u; + u = PyUnicode_AS_UNICODE(unicode); + for (i = size; i > 0; i--) { + if (*w > 0xFFFF) { + wchar_t ordinal = *w++; + ordinal -= 0x10000; + *u++ = 0xD800 | (ordinal >> 10); + *u++ = 0xDC00 | (ordinal & 0x3FF); + } + else + *u++ = *w++; + } + } + return (PyObject *)unicode; +} + +#else + PyObject *PyUnicode_FromWideChar(register const wchar_t *w, Py_ssize_t size) { @@ -597,6 +657,10 @@ return (PyObject *)unicode; } +#endif /* CONVERT_WCHAR_TO_SURROGATES */ + +#undef CONVERT_WCHAR_TO_SURROGATES + static void makefmt(char *fmt, int longflag, int size_tflag, int zeropad, int width, int precision, char c) { From python-checkins at python.org Wed Mar 18 15:52:01 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 15:52:01 +0100 (CET) Subject: [Python-checkins] r70453 - python/branches/release30-maint Message-ID: <20090318145201.C19D71E4002@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 15:52:01 2009 New Revision: 70453 Log: Blocked revisions 70452 via svnmerge ........ r70452 | mark.dickinson | 2009-03-18 14:47:41 +0000 (Wed, 18 Mar 2009) | 7 lines Issue 4474: On platforms with sizeof(wchar_t) == 4 and sizeof(Py_UNICODE) == 2, PyUnicode_FromWideChar now converts each character outside the BMP to the appropriate surrogate pair. Thanks Victor Stinner for the patch. ........ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Wed Mar 18 16:11:20 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 15:11:20 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090318151120.653B91E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/425 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Wed Mar 18 16:34:21 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 15:34:21 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.0 Message-ID: <20090318153421.2E64E1E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.0/builds/188 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Mar 18 17:07:26 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 17:07:26 +0100 (CET) Subject: [Python-checkins] r70454 - in python/trunk: Misc/NEWS Modules/_testcapimodule.c Objects/unicodeobject.c Message-ID: <20090318160726.9E4121E4002@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 17:07:26 2009 New Revision: 70454 Log: Issue 4474: On platforms with sizeof(wchar_t) == 4 and sizeof(Py_UNICODE) == 2, PyUnicode_FromWideChar now converts each character outside the BMP to the appropriate surrogate pair. Thanks Victor Stinner for the patch. (backport of r70452 from py3k to trunk) Modified: python/trunk/Misc/NEWS python/trunk/Modules/_testcapimodule.c python/trunk/Objects/unicodeobject.c Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Wed Mar 18 17:07:26 2009 @@ -12,6 +12,10 @@ Core and Builtins ----------------- +- Issue #4474: PyUnicode_FromWideChar now converts characters outside + the BMP to surrogate pairs, on systems with sizeof(wchar_t) == 4 + and sizeof(Py_UNICODE) == 2. + - Issue #5237: Allow auto-numbered fields in str.format(). For example: '{} {}'.format(1, 2) == '1 2'. Modified: python/trunk/Modules/_testcapimodule.c ============================================================================== --- python/trunk/Modules/_testcapimodule.c (original) +++ python/trunk/Modules/_testcapimodule.c Wed Mar 18 17:07:26 2009 @@ -621,6 +621,48 @@ } static PyObject * +test_widechar(PyObject *self) +{ +#if defined(SIZEOF_WCHAR_T) && (SIZEOF_WCHAR_T == 4) + const wchar_t wtext[2] = {(wchar_t)0x10ABCDu}; + size_t wtextlen = 1; +#else + const wchar_t wtext[3] = {(wchar_t)0xDBEAu, (wchar_t)0xDFCDu}; + size_t wtextlen = 2; +#endif + PyObject *wide, *utf8; + + wide = PyUnicode_FromWideChar(wtext, wtextlen); + if (wide == NULL) + return NULL; + + utf8 = PyUnicode_FromString("\xf4\x8a\xaf\x8d"); + if (utf8 == NULL) { + Py_DECREF(wide); + return NULL; + } + + if (PyUnicode_GET_SIZE(wide) != PyUnicode_GET_SIZE(utf8)) { + Py_DECREF(wide); + Py_DECREF(utf8); + return raiseTestError("test_widechar", + "wide string and utf8 string have different length"); + } + if (PyUnicode_Compare(wide, utf8)) { + Py_DECREF(wide); + Py_DECREF(utf8); + if (PyErr_Occurred()) + return NULL; + return raiseTestError("test_widechar", + "wide string and utf8 string are differents"); + } + + Py_DECREF(wide); + Py_DECREF(utf8); + Py_RETURN_NONE; +} + +static PyObject * test_empty_argparse(PyObject *self) { /* Test that formats can begin with '|'. See issue #4720. */ @@ -975,6 +1017,7 @@ #endif #ifdef Py_USING_UNICODE {"test_u_code", (PyCFunction)test_u_code, METH_NOARGS}, + {"test_widechar", (PyCFunction)test_widechar, METH_NOARGS}, #endif #ifdef WITH_THREAD {"_test_thread_state", test_thread_state, METH_VARARGS}, Modified: python/trunk/Objects/unicodeobject.c ============================================================================== --- python/trunk/Objects/unicodeobject.c (original) +++ python/trunk/Objects/unicodeobject.c Wed Mar 18 17:07:26 2009 @@ -529,6 +529,60 @@ #ifdef HAVE_WCHAR_H +#if (Py_UNICODE_SIZE == 2) && defined(SIZEOF_WCHAR_T) && (SIZEOF_WCHAR_T == 4) +# define CONVERT_WCHAR_TO_SURROGATES +#endif + +#ifdef CONVERT_WCHAR_TO_SURROGATES + +/* Here sizeof(wchar_t) is 4 but Py_UNICODE_SIZE == 2, so we need + to convert from UTF32 to UTF16. */ + +PyObject *PyUnicode_FromWideChar(register const wchar_t *w, + Py_ssize_t size) +{ + PyUnicodeObject *unicode; + register Py_ssize_t i; + Py_ssize_t alloc; + const wchar_t *orig_w; + + if (w == NULL) { + PyErr_BadInternalCall(); + return NULL; + } + + alloc = size; + orig_w = w; + for (i = size; i > 0; i--) { + if (*w > 0xFFFF) + alloc++; + w++; + } + w = orig_w; + unicode = _PyUnicode_New(alloc); + if (!unicode) + return NULL; + + /* Copy the wchar_t data into the new object */ + { + register Py_UNICODE *u; + u = PyUnicode_AS_UNICODE(unicode); + for (i = size; i > 0; i--) { + if (*w > 0xFFFF) { + wchar_t ordinal = *w++; + ordinal -= 0x10000; + *u++ = 0xD800 | (ordinal >> 10); + *u++ = 0xDC00 | (ordinal & 0x3FF); + } + else + *u++ = *w++; + } + } + return (PyObject *)unicode; +} + +#else + PyObject *PyUnicode_FromWideChar(register const wchar_t *w, Py_ssize_t size) { @@ -559,6 +613,10 @@ return (PyObject *)unicode; } +#endif /* CONVERT_WCHAR_TO_SURROGATES */ + +#undef CONVERT_WCHAR_TO_SURROGATES + static void makefmt(char *fmt, int longflag, int size_tflag, int zeropad, int width, int precision, char c) { From python-checkins at python.org Wed Mar 18 17:08:23 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 17:08:23 +0100 (CET) Subject: [Python-checkins] r70455 - python/branches/release26-maint Message-ID: <20090318160823.BD0BF1E4002@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 17:08:23 2009 New Revision: 70455 Log: Blocked revisions 70454 via svnmerge ........ r70454 | mark.dickinson | 2009-03-18 16:07:26 +0000 (Wed, 18 Mar 2009) | 9 lines Issue 4474: On platforms with sizeof(wchar_t) == 4 and sizeof(Py_UNICODE) == 2, PyUnicode_FromWideChar now converts each character outside the BMP to the appropriate surrogate pair. Thanks Victor Stinner for the patch. (backport of r70452 from py3k to trunk) ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Wed Mar 18 17:09:22 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 17:09:22 +0100 (CET) Subject: [Python-checkins] r70456 - python/branches/py3k Message-ID: <20090318160922.BDBA21E4002@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 17:09:22 2009 New Revision: 70456 Log: Blocked revisions 70454 via svnmerge ........ r70454 | mark.dickinson | 2009-03-18 16:07:26 +0000 (Wed, 18 Mar 2009) | 9 lines Issue 4474: On platforms with sizeof(wchar_t) == 4 and sizeof(Py_UNICODE) == 2, PyUnicode_FromWideChar now converts each character outside the BMP to the appropriate surrogate pair. Thanks Victor Stinner for the patch. (backport of r70452 from py3k to trunk) ........ Modified: python/branches/py3k/ (props changed) From buildbot at python.org Wed Mar 18 17:33:14 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 16:33:14 +0000 Subject: [Python-checkins] buildbot failure in OS X x86 trunk Message-ID: <20090318163315.0C0171E400C@bag.python.org> The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/240 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/threading.py", line 477, in run self.__target(*self.__args, **self.__kwargs) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/bsddb/test/test_thread.py", line 306, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/bsddb/dbutils.py", line 68, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') make: *** [buildbottest] Abort trap sincerely, -The Buildbot From python-checkins at python.org Wed Mar 18 18:10:04 2009 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 18 Mar 2009 18:10:04 +0100 (CET) Subject: [Python-checkins] r70457 - python/trunk/Lib/locale.py Message-ID: <20090318171004.74EAC1E4002@bag.python.org> Author: antoine.pitrou Date: Wed Mar 18 18:10:04 2009 New Revision: 70457 Log: Attempt to fix Solaris buildbot failure on test_locale Modified: python/trunk/Lib/locale.py Modified: python/trunk/Lib/locale.py ============================================================================== --- python/trunk/Lib/locale.py (original) +++ python/trunk/Lib/locale.py Wed Mar 18 18:10:04 2009 @@ -151,7 +151,7 @@ groups.reverse() return ( left_spaces + thousands_sep.join(groups) + right_spaces, - len(groups) - 1 + len(thousands_sep) * (len(groups) - 1) ) # Strip a given amount of excess padding from the given string From python-checkins at python.org Wed Mar 18 18:11:07 2009 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 18 Mar 2009 18:11:07 +0100 (CET) Subject: [Python-checkins] r70458 - in python/branches/release26-maint: Lib/locale.py Message-ID: <20090318171107.1350E1E4025@bag.python.org> Author: antoine.pitrou Date: Wed Mar 18 18:11:06 2009 New Revision: 70458 Log: Merged revisions 70457 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70457 | antoine.pitrou | 2009-03-18 18:10:04 +0100 (mer., 18 mars 2009) | 3 lines Attempt to fix Solaris buildbot failure on test_locale ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/locale.py Modified: python/branches/release26-maint/Lib/locale.py ============================================================================== --- python/branches/release26-maint/Lib/locale.py (original) +++ python/branches/release26-maint/Lib/locale.py Wed Mar 18 18:11:06 2009 @@ -151,7 +151,7 @@ groups.reverse() return ( left_spaces + thousands_sep.join(groups) + right_spaces, - len(groups) - 1 + len(thousands_sep) * (len(groups) - 1) ) # Strip a given amount of excess padding from the given string From solipsis at pitrou.net Wed Mar 18 18:32:01 2009 From: solipsis at pitrou.net (Antoine Pitrou) Date: Wed, 18 Mar 2009 17:32:01 +0000 (UTC) Subject: [Python-checkins] r70438 -python/trunk/Doc/library/functions.rst References: <20090317202952.2C3821E4002@bag.python.org><305682430D3843B8B04885CFFC5140BC@RaymondLaptop1><49C01053.6070205@gmail.com> <9FF981AA7E7C4F85899A700B50A86B37@RaymondLaptop1> Message-ID: Raymond Hettinger rcn.com> writes: > > Does the MS chm file format support embedded Javascript? I have absolutely no idea. Regards Antoine. From buildbot at python.org Wed Mar 18 18:32:46 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 17:32:46 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090318173247.07E361E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/521 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Wed Mar 18 19:24:52 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 18:24:52 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo 2.6 Message-ID: <20090318182452.5F0FE1E4002@bag.python.org> The Buildbot has detected a new failure of x86 gentoo 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20gentoo%202.6/builds/182 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Wed Mar 18 19:25:45 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 18:25:45 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090318182545.2B0511E4062@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/462 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Wed Mar 18 19:26:04 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 18:26:04 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 2.6 Message-ID: <20090318182604.EB26B1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%202.6/builds/183 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Wed Mar 18 20:03:12 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 19:03:12 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090318190312.4BB041E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/179 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Wed Mar 18 21:06:13 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 21:06:13 +0100 (CET) Subject: [Python-checkins] r70459 - in python/branches/py3k: Doc/library/sys.rst Doc/whatsnew/3.1.rst Include/longintrepr.h Include/longobject.h Include/pyport.h Lib/test/test_long.py Lib/test/test_sys.py Misc/NEWS Objects/longobject.c PC/pyconfig.h Python/marshal.c Python/sysmodule.c configure configure.in pyconfig.h.in Message-ID: <20090318200613.047EB1E4020@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 21:06:12 2009 New Revision: 70459 Log: Issue #4258: Make it possible to use 30-bit digits for PyLongs: - new configure option --enable-big-digits - new structseq sys.int_info giving information about the internal format By default, 30-bit digits are enabled on 64-bit machines but disabled on 32-bit machines. Modified: python/branches/py3k/Doc/library/sys.rst python/branches/py3k/Doc/whatsnew/3.1.rst python/branches/py3k/Include/longintrepr.h python/branches/py3k/Include/longobject.h python/branches/py3k/Include/pyport.h python/branches/py3k/Lib/test/test_long.py python/branches/py3k/Lib/test/test_sys.py python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/longobject.c python/branches/py3k/PC/pyconfig.h python/branches/py3k/Python/marshal.c python/branches/py3k/Python/sysmodule.c python/branches/py3k/configure python/branches/py3k/configure.in python/branches/py3k/pyconfig.h.in Modified: python/branches/py3k/Doc/library/sys.rst ============================================================================== --- python/branches/py3k/Doc/library/sys.rst (original) +++ python/branches/py3k/Doc/library/sys.rst Wed Mar 18 21:06:12 2009 @@ -413,6 +413,23 @@ same information. +.. data:: int_info + + A struct sequence that holds information about Python's + internal representation of integers. The attributes are read only. + + +-------------------------+----------------------------------------------+ + | attribute | explanation | + +=========================+==============================================+ + | :const:`bits_per_digit` | number of bits held in each digit. Python | + | | integers are stored internally in base | + | | ``2**int_info.bits_per_digit`` | + +-------------------------+----------------------------------------------+ + | :const:`sizeof_digit` | size in bytes of the C type used to | + | | represent a digit | + +-------------------------+----------------------------------------------+ + + .. function:: intern(string) Enter *string* in the table of "interned" strings and return the interned string Modified: python/branches/py3k/Doc/whatsnew/3.1.rst ============================================================================== --- python/branches/py3k/Doc/whatsnew/3.1.rst (original) +++ python/branches/py3k/Doc/whatsnew/3.1.rst Wed Mar 18 21:06:12 2009 @@ -87,5 +87,28 @@ (Contributed by Fredrik Johansson and Victor Stinner; :issue:`3439`.) +* Integers are now stored internally either in base 2**15 or in base + 2**30, the base being determined at build time. Previously, they + were always stored in base 2**15. Using base 2**30 gives + significant performance improvements on 64-bit machines, but + benchmark results on 32-bit machines have been mixed. Therefore, + the default is to use base 2**30 on 64-bit machines and base 2**15 + on 32-bit machines; on Unix, there's a new configure option + --enable-big-digits that can be used to override this default. + + Apart from the performance improvements this change should be + invisible to end users, with one exception: for testing and + debugging purposes there's a new structseq ``sys.int_info`` that + provides information about the internal format, giving the number of + bits per digit and the size in bytes of the C type used to store + each digit:: + + >>> import sys + >>> sys.int_info + sys.int_info(bits_per_digit=30, sizeof_digit=4) + + + (Contributed by Mark Dickinson; :issue:`4258`.) + .. ====================================================================== Modified: python/branches/py3k/Include/longintrepr.h ============================================================================== --- python/branches/py3k/Include/longintrepr.h (original) +++ python/branches/py3k/Include/longintrepr.h Wed Mar 18 21:06:12 2009 @@ -7,24 +7,62 @@ /* This is published for the benefit of "friend" marshal.c only. */ -/* Parameters of the long integer representation. - These shouldn't have to be changed as C should guarantee that a short - contains at least 16 bits, but it's made changeable anyway. - Note: 'digit' should be able to hold 2*MASK+1, and 'twodigits' - should be able to hold the intermediate results in 'mul' - (at most (BASE-1)*(2*BASE+1) == MASK*(2*MASK+3)). - Also, x_sub assumes that 'digit' is an unsigned type, and overflow - is handled by taking the result mod 2**N for some N > SHIFT. - And, at some places it is assumed that MASK fits in an int, as well. - long_pow() requires that SHIFT be divisible by 5. */ +/* Parameters of the long integer representation. There are two different + sets of parameters: one set for 30-bit digits, stored in an unsigned 32-bit + integer type, and one set for 15-bit digits with each digit stored in an + unsigned short. The value of PYLONG_BITS_IN_DIGIT, defined either at + configure time or in pyport.h, is used to decide which digit size to use. -typedef unsigned short digit; -typedef short sdigit; /* signed variant of digit */ -#define BASE_TWODIGITS_TYPE long -typedef unsigned BASE_TWODIGITS_TYPE twodigits; -typedef BASE_TWODIGITS_TYPE stwodigits; /* signed variant of twodigits */ + Type 'digit' should be able to hold 2*PyLong_BASE-1, and type 'twodigits' + should be an unsigned integer type able to hold all integers up to + PyLong_BASE*PyLong_BASE-1. x_sub assumes that 'digit' is an unsigned type, + and that overflow is handled by taking the result modulo 2**N for some N > + PyLong_SHIFT. The majority of the code doesn't care about the precise + value of PyLong_SHIFT, but there are some notable exceptions: + + - long_pow() requires that PyLong_SHIFT be divisible by 5 + + - PyLong_{As,From}ByteArray require that PyLong_SHIFT be at least 8 + + - long_hash() requires that PyLong_SHIFT is *strictly* less than the number + of bits in an unsigned long, as do the PyLong <-> long (or unsigned long) + conversion functions + + - the long <-> size_t/Py_ssize_t conversion functions expect that + PyLong_SHIFT is strictly less than the number of bits in a size_t + + - the marshal code currently expects that PyLong_SHIFT is a multiple of 15 + + - NSMALLNEGINTS and NSMALLPOSINTS should be small enough to fit in a single + digit; with the current values this forces PyLong_SHIFT >= 9 + The values 15 and 30 should fit all of the above requirements, on any + platform. +*/ + +#if HAVE_STDINT_H +#include +#endif + +#if PYLONG_BITS_IN_DIGIT == 30 +#if !(defined HAVE_UINT64_T && defined HAVE_UINT32_T && \ + defined HAVE_INT64_T && defined HAVE_INT32_T) +#error "30-bit long digits requested, but the necessary types are not available on this platform" +#endif +typedef PY_UINT32_T digit; +typedef PY_INT32_T sdigit; /* signed variant of digit */ +typedef PY_UINT64_T twodigits; +typedef PY_INT64_T stwodigits; /* signed variant of twodigits */ +#define PyLong_SHIFT 30 +#elif PYLONG_BITS_IN_DIGIT == 15 +typedef unsigned short digit; +typedef short sdigit; /* signed variant of digit */ +typedef unsigned long twodigits; +typedef long stwodigits; /* signed variant of twodigits */ #define PyLong_SHIFT 15 +#else +#error "PYLONG_BITS_IN_DIGIT should be 15 or 30" +#endif #define PyLong_BASE ((digit)1 << PyLong_SHIFT) #define PyLong_MASK ((digit)(PyLong_BASE - 1)) Modified: python/branches/py3k/Include/longobject.h ============================================================================== --- python/branches/py3k/Include/longobject.h (original) +++ python/branches/py3k/Include/longobject.h Wed Mar 18 21:06:12 2009 @@ -26,6 +26,7 @@ PyAPI_FUNC(size_t) PyLong_AsSize_t(PyObject *); PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLong(PyObject *); PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLongMask(PyObject *); +PyAPI_FUNC(PyObject *) PyLong_GetInfo(void); /* It may be useful in the future. I've added it in the PyInt -> PyLong cleanup to keep the extra information. [CH] */ Modified: python/branches/py3k/Include/pyport.h ============================================================================== --- python/branches/py3k/Include/pyport.h (original) +++ python/branches/py3k/Include/pyport.h Wed Mar 18 21:06:12 2009 @@ -69,6 +69,57 @@ #endif #endif /* HAVE_LONG_LONG */ +/* a build with 30-bit digits for Python long integers needs an exact-width + * 32-bit unsigned integer type to store those digits. (We could just use + * type 'unsigned long', but that would be wasteful on a system where longs + * are 64-bits.) On Unix systems, the autoconf macro AC_TYPE_UINT32_T defines + * uint32_t to be such a type unless stdint.h or inttypes.h defines uint32_t. + * However, it doesn't set HAVE_UINT32_T, so we do that here. + */ +#if (defined UINT32_MAX || defined uint32_t) +#ifndef PY_UINT32_T +#define HAVE_UINT32_T 1 +#define PY_UINT32_T uint32_t +#endif +#endif + +/* Macros for a 64-bit unsigned integer type; used for type 'twodigits' in the + * long integer implementation, when 30-bit digits are enabled. + */ +#if (defined UINT64_MAX || defined uint64_t) +#ifndef PY_UINT64_T +#define HAVE_UINT64_T 1 +#define PY_UINT64_T uint64_t +#endif +#endif + +/* Signed variants of the above */ +#if (defined INT32_MAX || defined int32_t) +#ifndef PY_INT32_T +#define HAVE_INT32_T 1 +#define PY_INT32_T int32_t +#endif +#endif +#if (defined INT64_MAX || defined int64_t) +#ifndef PY_INT64_T +#define HAVE_INT64_T 1 +#define PY_INT64_T int64_t +#endif +#endif + +/* If PYLONG_BITS_IN_DIGIT is not defined then we'll use 30-bit digits if all + the necessary integer types are available, and we're on a 64-bit platform + (as determined by SIZEOF_VOID_P); otherwise we use 15-bit digits. */ + +#ifndef PYLONG_BITS_IN_DIGIT +#if (defined HAVE_UINT64_T && defined HAVE_INT64_T && \ + defined HAVE_UINT32_T && defined HAVE_INT32_T && SIZEOF_VOID_P >= 8) +#define PYLONG_BITS_IN_DIGIT 30 +#else +#define PYLONG_BITS_IN_DIGIT 15 +#endif +#endif + /* uintptr_t is the C9X name for an unsigned integral type such that a * legitimate void* can be cast to uintptr_t and then back to void* again * without loss of information. Similarly for intptr_t, wrt a signed Modified: python/branches/py3k/Lib/test/test_long.py ============================================================================== --- python/branches/py3k/Lib/test/test_long.py (original) +++ python/branches/py3k/Lib/test/test_long.py Wed Mar 18 21:06:12 2009 @@ -15,7 +15,7 @@ return self.format % self.args # SHIFT should match the value in longintrepr.h for best testing. -SHIFT = 15 +SHIFT = sys.int_info.bits_per_digit BASE = 2 ** SHIFT MASK = BASE - 1 KARATSUBA_CUTOFF = 70 # from longobject.c @@ -120,6 +120,35 @@ y = self.getran(leny) or 1 self.check_division(x, y) + # specific numbers chosen to exercise corner cases of the + # current long division implementation + + # 30-bit cases involving a quotient digit estimate of BASE+1 + self.check_division(1231948412290879395966702881, + 1147341367131428698) + self.check_division(815427756481275430342312021515587883, + 707270836069027745) + self.check_division(627976073697012820849443363563599041, + 643588798496057020) + self.check_division(1115141373653752303710932756325578065, + 1038556335171453937726882627) + # 30-bit cases that require the post-subtraction correction step + self.check_division(922498905405436751940989320930368494, + 949985870686786135626943396) + self.check_division(768235853328091167204009652174031844, + 1091555541180371554426545266) + + # 15-bit cases involving a quotient digit estimate of BASE+1 + self.check_division(20172188947443, 615611397) + self.check_division(1020908530270155025, 950795710) + self.check_division(128589565723112408, 736393718) + self.check_division(609919780285761575, 18613274546784) + # 15-bit cases that require the post-subtraction correction step + self.check_division(710031681576388032, 26769404391308) + self.check_division(1933622614268221, 30212853348836) + + + def test_karatsuba(self): digits = list(range(1, 5)) + list(range(KARATSUBA_CUTOFF, KARATSUBA_CUTOFF + 10)) Modified: python/branches/py3k/Lib/test/test_sys.py ============================================================================== --- python/branches/py3k/Lib/test/test_sys.py (original) +++ python/branches/py3k/Lib/test/test_sys.py Wed Mar 18 21:06:12 2009 @@ -333,6 +333,9 @@ self.assert_(isinstance(sys.executable, str)) self.assertEqual(len(sys.float_info), 11) self.assertEqual(sys.float_info.radix, 2) + self.assertEqual(len(sys.int_info), 2) + self.assert_(sys.int_info.bits_per_digit % 5 == 0) + self.assert_(sys.int_info.sizeof_digit >= 1) self.assert_(isinstance(sys.hexversion, int)) self.assert_(isinstance(sys.maxsize, int)) self.assert_(isinstance(sys.maxunicode, int)) @@ -437,6 +440,7 @@ if hasattr(sys, "gettotalrefcount"): self.header += '2P' self.vheader += '2P' + self.longdigit = sys.int_info.sizeof_digit import _testcapi self.gc_headsize = _testcapi.SIZEOF_PYGC_HEAD self.file = open(test.support.TESTFN, 'wb') @@ -471,7 +475,7 @@ size = self.calcsize gc_header_size = self.gc_headsize # bool objects are not gc tracked - self.assertEqual(sys.getsizeof(True), size(vh) + self.H) + self.assertEqual(sys.getsizeof(True), size(vh) + self.longdigit) # but lists are self.assertEqual(sys.getsizeof([]), size(vh + 'PP') + gc_header_size) @@ -479,8 +483,8 @@ h = self.header vh = self.vheader size = self.calcsize - self.assertEqual(sys.getsizeof(True), size(vh) + self.H) - self.assertEqual(sys.getsizeof(True, -1), size(vh) + self.H) + self.assertEqual(sys.getsizeof(True), size(vh) + self.longdigit) + self.assertEqual(sys.getsizeof(True, -1), size(vh) + self.longdigit) def test_objecttypes(self): # check all types defined in Objects/ @@ -489,7 +493,7 @@ size = self.calcsize check = self.check_sizeof # bool - check(True, size(vh) + self.H) + check(True, size(vh) + self.longdigit) # buffer # XXX # builtin_function_or_method @@ -607,11 +611,12 @@ check(reversed([]), size(h + 'lP')) # long check(0, size(vh)) - check(1, size(vh) + self.H) - check(-1, size(vh) + self.H) - check(32768, size(vh) + 2*self.H) - check(32768*32768-1, size(vh) + 2*self.H) - check(32768*32768, size(vh) + 3*self.H) + check(1, size(vh) + self.longdigit) + check(-1, size(vh) + self.longdigit) + PyLong_BASE = 2**sys.int_info.bits_per_digit + check(PyLong_BASE, size(vh) + 2*self.longdigit) + check(PyLong_BASE**2-1, size(vh) + 2*self.longdigit) + check(PyLong_BASE**2, size(vh) + 3*self.longdigit) # memory check(memoryview(b''), size(h + 'P PP2P2i7P')) # module Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Mar 18 21:06:12 2009 @@ -12,6 +12,13 @@ Core and Builtins ----------------- +- Issue #4258: Make it possible to use base 2**30 instead of base + 2**15 for the internal representation of integers, for performance + reasons. Base 2**30 is enabled by default on 64-bit machines. Add + --enable-big-digits option to configure, which overrides the + default. Add sys.int_info structseq to provide information about + the internal format. + - Issue #4474: PyUnicode_FromWideChar now converts characters outside the BMP to surrogate pairs, on systems with sizeof(wchar_t) == 4 and sizeof(Py_UNICODE) == 2. Modified: python/branches/py3k/Objects/longobject.c ============================================================================== --- python/branches/py3k/Objects/longobject.c (original) +++ python/branches/py3k/Objects/longobject.c Wed Mar 18 21:06:12 2009 @@ -4,6 +4,7 @@ #include "Python.h" #include "longintrepr.h" +#include "structseq.h" #include #include @@ -204,6 +205,7 @@ return (PyObject*)v; } +#if PyLONG_SHIFT==15 /* 2 digits */ if (!(abs_ival >> 2*PyLong_SHIFT)) { v = _PyLong_New(2); @@ -216,6 +218,7 @@ } return (PyObject*)v; } +#endif /* Larger numbers: loop to determine number of digits */ t = abs_ival; @@ -2864,10 +2867,20 @@ CHECK_BINOP(a, b); + /* fast path for single-digit multiplication */ if (ABS(Py_SIZE(a)) <= 1 && ABS(Py_SIZE(b)) <= 1) { - PyObject *r; - r = PyLong_FromLong(MEDIUM_VALUE(a)*MEDIUM_VALUE(b)); - return r; + stwodigits v = (stwodigits)(MEDIUM_VALUE(a)) * MEDIUM_VALUE(b); +#ifdef HAVE_LONG_LONG + return PyLong_FromLongLong((PY_LONG_LONG)v); +#else + /* if we don't have long long then we're almost certainly + using 15-bit digits, so v will fit in a long. In the + unlikely event that we're using 30-bit digits on a platform + without long long, a large v will just cause us to fall + through to the general multiplication code below. */ + if (v >= LONG_MIN && v <= LONG_MAX) + return PyLong_FromLong((long)v); +#endif } z = k_mul(a, b); @@ -3991,6 +4004,45 @@ PyObject_Del, /* tp_free */ }; +static PyTypeObject Int_InfoType; + +PyDoc_STRVAR(int_info__doc__, +"sys.int_info\n\ +\n\ +A struct sequence that holds information about Python's\n\ +internal representation of integers. The attributes are read only."); + +static PyStructSequence_Field int_info_fields[] = { + {"bits_per_digit", "size of a digit in bits"}, + {"sizeof_digit", "size in bytes of the C type used to " + "represent a digit"}, + {NULL, NULL} +}; + +static PyStructSequence_Desc int_info_desc = { + "sys.int_info", /* name */ + int_info__doc__, /* doc */ + int_info_fields, /* fields */ + 2 /* number of fields */ +}; + +PyObject * +PyLong_GetInfo(void) +{ + PyObject* int_info; + int field = 0; + int_info = PyStructSequence_New(&Int_InfoType); + if (int_info == NULL) + return NULL; + PyStructSequence_SET_ITEM(int_info, field++, PyLong_FromLong(PyLong_SHIFT)); + PyStructSequence_SET_ITEM(int_info, field++, PyLong_FromLong(sizeof(digit))); + if (PyErr_Occurred()) { + Py_CLEAR(int_info); + return NULL; + } + return int_info; +} + int _PyLong_Init(void) { @@ -4023,6 +4075,10 @@ v->ob_digit[0] = abs(ival); } #endif + /* initialize int_info */ + if (Int_InfoType.tp_name == 0) + PyStructSequence_InitType(&Int_InfoType, &int_info_desc); + return 1; } Modified: python/branches/py3k/PC/pyconfig.h ============================================================================== --- python/branches/py3k/PC/pyconfig.h (original) +++ python/branches/py3k/PC/pyconfig.h Wed Mar 18 21:06:12 2009 @@ -396,6 +396,42 @@ #endif +/* define signed and unsigned exact-width 32-bit and 64-bit types, used in the + implementation of Python long integers. */ +#ifndef PY_UINT32_T +#if SIZEOF_INT == 4 +#define HAVE_UINT32_T 1 +#define PY_UINT32_T unsigned int +#elif SIZEOF_LONG == 4 +#define HAVE_UINT32_T 1 +#define PY_UINT32_T unsigned long +#endif +#endif + +#ifndef PY_UINT64_T +#if SIZEOF_LONG_LONG == 8 +#define HAVE_UINT64_T 1 +#define PY_UINT64_T unsigned PY_LONG_LONG +#endif +#endif + +#ifndef PY_INT32_T +#if SIZEOF_INT == 4 +#define HAVE_INT32_T 1 +#define PY_INT32_T int +#elif SIZEOF_LONG == 4 +#define HAVE_INT32_T 1 +#define PY_INT32_T long +#endif +#endif + +#ifndef PY_INT64_T +#if SIZEOF_LONG_LONG == 8 +#define HAVE_INT64_T 1 +#define PY_INT64_T PY_LONG_LONG +#endif +#endif + /* Fairly standard from here! */ /* Define to 1 if you have the `copysign' function. */ Modified: python/branches/py3k/Python/marshal.c ============================================================================== --- python/branches/py3k/Python/marshal.c (original) +++ python/branches/py3k/Python/marshal.c Wed Mar 18 21:06:12 2009 @@ -11,6 +11,8 @@ #include "code.h" #include "marshal.h" +#define ABS(x) ((x) < 0 ? -(x) : (x)) + /* High water mark to determine when the marshalled object is dangerously deep * and risks coring the interpreter. When the object stack gets this deep, * raise an exception instead of continuing. @@ -122,6 +124,56 @@ } #endif +/* We assume that Python longs are stored internally in base some power of + 2**15; for the sake of portability we'll always read and write them in base + exactly 2**15. */ + +#define PyLong_MARSHAL_SHIFT 15 +#define PyLong_MARSHAL_BASE ((short)1 << PyLong_MARSHAL_SHIFT) +#define PyLong_MARSHAL_MASK (PyLong_MARSHAL_BASE - 1) +#if PyLong_SHIFT % PyLong_MARSHAL_SHIFT != 0 +#error "PyLong_SHIFT must be a multiple of PyLong_MARSHAL_SHIFT" +#endif +#define PyLong_MARSHAL_RATIO (PyLong_SHIFT / PyLong_MARSHAL_SHIFT) + +static void +w_PyLong(const PyLongObject *ob, WFILE *p) +{ + Py_ssize_t i, j, n, l; + digit d; + + w_byte(TYPE_LONG, p); + if (Py_SIZE(ob) == 0) { + w_long((long)0, p); + return; + } + + /* set l to number of base PyLong_MARSHAL_BASE digits */ + n = ABS(Py_SIZE(ob)); + l = (n-1) * PyLong_MARSHAL_RATIO; + d = ob->ob_digit[n-1]; + assert(d != 0); /* a PyLong is always normalized */ + do { + d >>= PyLong_MARSHAL_SHIFT; + l++; + } while (d != 0); + w_long((long)(Py_SIZE(ob) > 0 ? l : -l), p); + + for (i=0; i < n-1; i++) { + d = ob->ob_digit[i]; + for (j=0; j < PyLong_MARSHAL_RATIO; j++) { + w_short(d & PyLong_MARSHAL_MASK, p); + d >>= PyLong_MARSHAL_SHIFT; + } + assert (d == 0); + } + d = ob->ob_digit[n-1]; + do { + w_short(d & PyLong_MARSHAL_MASK, p); + d >>= PyLong_MARSHAL_SHIFT; + } while (d != 0); +} + static void w_object(PyObject *v, WFILE *p) { @@ -155,14 +207,8 @@ if ((x == -1) && PyErr_Occurred()) { PyLongObject *ob = (PyLongObject *)v; PyErr_Clear(); - w_byte(TYPE_LONG, p); - n = Py_SIZE(ob); - w_long((long)n, p); - if (n < 0) - n = -n; - for (i = 0; i < n; i++) - w_short(ob->ob_digit[i], p); - } + w_PyLong(ob, p); + } else { #if SIZEOF_LONG > 4 long y = Py_ARITHMETIC_RIGHT_SHIFT(long, x, 31); @@ -481,6 +527,56 @@ } static PyObject * +r_PyLong(RFILE *p) +{ + PyLongObject *ob; + int size, i, j, md; + long n; + digit d; + + n = r_long(p); + if (n == 0) + return (PyObject *)_PyLong_New(0); + if (n < -INT_MAX || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, + "bad marshal data (long size out of range)"); + return NULL; + } + + size = 1 + (ABS(n)-1) / PyLong_MARSHAL_RATIO; + ob = _PyLong_New(size); + if (ob == NULL) + return NULL; + Py_SIZE(ob) = n > 0 ? size : -size; + + for (i = 0; i < size-1; i++) { + d = 0; + for (j=0; j < PyLong_MARSHAL_RATIO; j++) { + md = r_short(p); + if (md < 0 || md > PyLong_MARSHAL_BASE) + goto bad_digit; + d += (digit)md << j*PyLong_MARSHAL_SHIFT; + } + ob->ob_digit[i] = d; + } + d = 0; + for (j=0; j < (ABS(n)-1)%PyLong_MARSHAL_RATIO + 1; j++) { + md = r_short(p); + if (md < 0 || md > PyLong_MARSHAL_BASE) + goto bad_digit; + d += (digit)md << j*PyLong_MARSHAL_SHIFT; + } + ob->ob_digit[size-1] = d; + return (PyObject *)ob; + bad_digit: + Py_DECREF(ob); + PyErr_SetString(PyExc_ValueError, + "bad marshal data (digit out of range in long)"); + return NULL; +} + + +static PyObject * r_object(RFILE *p) { /* NULL is a valid return value, it does not necessarily means that @@ -544,38 +640,8 @@ break; case TYPE_LONG: - { - int size; - PyLongObject *ob; - n = r_long(p); - if (n < -INT_MAX || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, - "bad marshal data (long size out of range)"); - retval = NULL; - break; - } - size = n<0 ? -n : n; - ob = _PyLong_New(size); - if (ob == NULL) { - retval = NULL; - break; - } - Py_SIZE(ob) = n; - for (i = 0; i < size; i++) { - int digit = r_short(p); - if (digit < 0) { - Py_DECREF(ob); - PyErr_SetString(PyExc_ValueError, - "bad marshal data (negative digit in long)"); - ob = NULL; - break; - } - if (ob != NULL) - ob->ob_digit[i] = digit; - } - retval = (PyObject *)ob; - break; - } + retval = r_PyLong(p); + break; case TYPE_FLOAT: { Modified: python/branches/py3k/Python/sysmodule.c ============================================================================== --- python/branches/py3k/Python/sysmodule.c (original) +++ python/branches/py3k/Python/sysmodule.c Wed Mar 18 21:06:12 2009 @@ -1012,6 +1012,7 @@ Static objects:\n\ \n\ float_info -- a dict with information about the float implementation.\n\ +int_info -- a struct sequence with information about the int implementation.\n\ maxsize -- the largest supported length of containers.\n\ maxunicode -- the largest supported character\n\ builtin_module_names -- tuple of module names built into this interpreter\n\ @@ -1375,6 +1376,8 @@ PyLong_FromSsize_t(PY_SSIZE_T_MAX)); SET_SYS_FROM_STRING("float_info", PyFloat_GetInfo()); + SET_SYS_FROM_STRING("int_info", + PyLong_GetInfo()); SET_SYS_FROM_STRING("maxunicode", PyLong_FromLong(PyUnicode_GetMax())); SET_SYS_FROM_STRING("builtin_module_names", Modified: python/branches/py3k/configure ============================================================================== --- python/branches/py3k/configure (original) +++ python/branches/py3k/configure Wed Mar 18 21:06:12 2009 @@ -1320,6 +1320,8 @@ --enable-profiling enable C-level code profiling --enable-ipv6 Enable ipv6 (with ipv4) support --disable-ipv6 Disable ipv6 support + --enable-big-digits[=BITS] + use big digits for Python longs [BITS=30] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -6965,6 +6967,386 @@ fi + + { echo "$as_me:$LINENO: checking for uint32_t" >&5 +echo $ECHO_N "checking for uint32_t... $ECHO_C" >&6; } +if test "${ac_cv_c_uint32_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_uint32_t=no + for ac_type in 'uint32_t' 'unsigned int' 'unsigned long int' \ + 'unsigned long long int' 'unsigned short int' 'unsigned char'; 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 * !(($ac_type) -1 >> (32 - 1) == 1)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + case $ac_type in + uint32_t) ac_cv_c_uint32_t=yes ;; + *) ac_cv_c_uint32_t=$ac_type ;; +esac + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_uint32_t" != no && break + done +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_uint32_t" >&5 +echo "${ECHO_T}$ac_cv_c_uint32_t" >&6; } + case $ac_cv_c_uint32_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<\_ACEOF +#define _UINT32_T 1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define uint32_t $ac_cv_c_uint32_t +_ACEOF +;; + esac + + + { echo "$as_me:$LINENO: checking for uint64_t" >&5 +echo $ECHO_N "checking for uint64_t... $ECHO_C" >&6; } +if test "${ac_cv_c_uint64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_uint64_t=no + for ac_type in 'uint64_t' 'unsigned int' 'unsigned long int' \ + 'unsigned long long int' 'unsigned short int' 'unsigned char'; 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 * !(($ac_type) -1 >> (64 - 1) == 1)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + case $ac_type in + uint64_t) ac_cv_c_uint64_t=yes ;; + *) ac_cv_c_uint64_t=$ac_type ;; +esac + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_uint64_t" != no && break + done +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_uint64_t" >&5 +echo "${ECHO_T}$ac_cv_c_uint64_t" >&6; } + case $ac_cv_c_uint64_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<\_ACEOF +#define _UINT64_T 1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define uint64_t $ac_cv_c_uint64_t +_ACEOF +;; + esac + + + { echo "$as_me:$LINENO: checking for int32_t" >&5 +echo $ECHO_N "checking for int32_t... $ECHO_C" >&6; } +if test "${ac_cv_c_int32_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_int32_t=no + for ac_type in 'int32_t' 'int' 'long int' \ + 'long long int' 'short int' 'signed char'; 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 * !(0 < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1))]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + 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 * !(($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1) + < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 2))]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + case $ac_type in + int32_t) ac_cv_c_int32_t=yes ;; + *) ac_cv_c_int32_t=$ac_type ;; +esac + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_int32_t" != no && break + done +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_int32_t" >&5 +echo "${ECHO_T}$ac_cv_c_int32_t" >&6; } + case $ac_cv_c_int32_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int32_t $ac_cv_c_int32_t +_ACEOF +;; + esac + + + { echo "$as_me:$LINENO: checking for int64_t" >&5 +echo $ECHO_N "checking for int64_t... $ECHO_C" >&6; } +if test "${ac_cv_c_int64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_int64_t=no + for ac_type in 'int64_t' 'int' 'long int' \ + 'long long int' 'short int' 'signed char'; 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 * !(0 < ($ac_type) (((($ac_type) 1 << (64 - 2)) - 1) * 2 + 1))]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + 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 * !(($ac_type) (((($ac_type) 1 << (64 - 2)) - 1) * 2 + 1) + < ($ac_type) (((($ac_type) 1 << (64 - 2)) - 1) * 2 + 2))]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + case $ac_type in + int64_t) ac_cv_c_int64_t=yes ;; + *) ac_cv_c_int64_t=$ac_type ;; +esac + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_int64_t" != no && break + done +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_int64_t" >&5 +echo "${ECHO_T}$ac_cv_c_int64_t" >&6; } + case $ac_cv_c_int64_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int64_t $ac_cv_c_int64_t +_ACEOF +;; + esac + { echo "$as_me:$LINENO: checking for ssize_t" >&5 echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6; } if test "${ac_cv_type_ssize_t+set}" = set; then @@ -21687,6 +22069,37 @@ LIBS=$LIBS_SAVE +# determine what size digit to use for Python's longs +{ echo "$as_me:$LINENO: checking digit size for Python's longs" >&5 +echo $ECHO_N "checking digit size for Python's longs... $ECHO_C" >&6; } +# Check whether --enable-big-digits was given. +if test "${enable_big_digits+set}" = set; then + enableval=$enable_big_digits; case $enable_big_digits in +yes) + enable_big_digits=30 ;; +no) + enable_big_digits=15 ;; +15|30) + ;; +*) + { { echo "$as_me:$LINENO: error: bad value $enable_big_digits for --enable-big-digits; value should be 15 or 30" >&5 +echo "$as_me: error: bad value $enable_big_digits for --enable-big-digits; value should be 15 or 30" >&2;} + { (exit 1); exit 1; }; } ;; +esac +{ echo "$as_me:$LINENO: result: $enable_big_digits" >&5 +echo "${ECHO_T}$enable_big_digits" >&6; } + +cat >>confdefs.h <<_ACEOF +#define PYLONG_BITS_IN_DIGIT $enable_big_digits +_ACEOF + + +else + { echo "$as_me:$LINENO: result: no value specified" >&5 +echo "${ECHO_T}no value specified" >&6; } +fi + + # check for wchar.h if test "${ac_cv_header_wchar_h+set}" = set; then { echo "$as_me:$LINENO: checking for wchar.h" >&5 Modified: python/branches/py3k/configure.in ============================================================================== --- python/branches/py3k/configure.in (original) +++ python/branches/py3k/configure.in Wed Mar 18 21:06:12 2009 @@ -1288,6 +1288,10 @@ AC_TYPE_SIGNAL AC_TYPE_SIZE_T AC_TYPE_UID_T +AC_TYPE_UINT32_T +AC_TYPE_UINT64_T +AC_TYPE_INT32_T +AC_TYPE_INT64_T AC_CHECK_TYPE(ssize_t, AC_DEFINE(HAVE_SSIZE_T, 1, Define if your compiler provides ssize_t),,) @@ -3125,6 +3129,25 @@ LIBS=$LIBS_SAVE +# determine what size digit to use for Python's longs +AC_MSG_CHECKING([digit size for Python's longs]) +AC_ARG_ENABLE(big-digits, +AC_HELP_STRING([--enable-big-digits@<:@=BITS@:>@],[use big digits for Python longs [[BITS=30]]]), +[case $enable_big_digits in +yes) + enable_big_digits=30 ;; +no) + enable_big_digits=15 ;; +[15|30]) + ;; +*) + AC_MSG_ERROR([bad value $enable_big_digits for --enable-big-digits; value should be 15 or 30]) ;; +esac +AC_MSG_RESULT($enable_big_digits) +AC_DEFINE_UNQUOTED(PYLONG_BITS_IN_DIGIT, $enable_big_digits, [Define as the preferred size in bits of long digits]) +], +[AC_MSG_RESULT(no value specified)]) + # check for wchar.h AC_CHECK_HEADER(wchar.h, [ AC_DEFINE(HAVE_WCHAR_H, 1, Modified: python/branches/py3k/pyconfig.h.in ============================================================================== --- python/branches/py3k/pyconfig.h.in (original) +++ python/branches/py3k/pyconfig.h.in Wed Mar 18 21:06:12 2009 @@ -855,6 +855,9 @@ /* Defined if PTHREAD_SCOPE_SYSTEM supported. */ #undef PTHREAD_SYSTEM_SCHED_SUPPORTED +/* Define as the preferred size in bits of long digits */ +#undef PYLONG_BITS_IN_DIGIT + /* Define to printf format modifier for Py_ssize_t */ #undef PY_FORMAT_SIZE_T @@ -1036,6 +1039,16 @@ /* Define to force use of thread-safe errno, h_errno, and other functions */ #undef _REENTRANT +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef was allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef was allowed, the + #define below would cause a syntax error. */ +#undef _UINT64_T + /* Define to the level of X/Open that your system supports */ #undef _XOPEN_SOURCE @@ -1062,6 +1075,14 @@ /* Define to `int' if doesn't define. */ #undef gid_t +/* Define to the type of a signed integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef int32_t + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef int64_t + /* Define to `int' if does not define. */ #undef mode_t @@ -1083,6 +1104,14 @@ /* Define to `int' if doesn't define. */ #undef uid_t +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef uint64_t + /* Define to empty if the keyword does not work. */ #undef volatile From python-checkins at python.org Wed Mar 18 21:12:49 2009 From: python-checkins at python.org (mark.dickinson) Date: Wed, 18 Mar 2009 21:12:49 +0100 (CET) Subject: [Python-checkins] r70460 - python/branches/release30-maint Message-ID: <20090318201249.35D851E4002@bag.python.org> Author: mark.dickinson Date: Wed Mar 18 21:12:49 2009 New Revision: 70460 Log: Blocked revisions 70459 via svnmerge ........ r70459 | mark.dickinson | 2009-03-18 20:06:12 +0000 (Wed, 18 Mar 2009) | 7 lines Issue #4258: Make it possible to use 30-bit digits for PyLongs: - new configure option --enable-big-digits - new structseq sys.int_info giving information about the internal format By default, 30-bit digits are enabled on 64-bit machines but disabled on 32-bit machines. ........ Modified: python/branches/release30-maint/ (props changed) From python-checkins at python.org Wed Mar 18 21:26:42 2009 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 18 Mar 2009 21:26:42 +0100 (CET) Subject: [Python-checkins] r70461 - in python/branches/py3k: Lib/locale.py Message-ID: <20090318202642.8BF6E1E4013@bag.python.org> Author: antoine.pitrou Date: Wed Mar 18 21:26:42 2009 New Revision: 70461 Log: svnmerge from trunk for r70457 (sorry, I accidentally deleted the commit message) Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/locale.py Modified: python/branches/py3k/Lib/locale.py ============================================================================== --- python/branches/py3k/Lib/locale.py (original) +++ python/branches/py3k/Lib/locale.py Wed Mar 18 21:26:42 2009 @@ -158,7 +158,7 @@ groups.reverse() return ( left_spaces + thousands_sep.join(groups) + right_spaces, - len(groups) - 1 + len(thousands_sep) * (len(groups) - 1) ) # Strip a given amount of excess padding from the given string From python-checkins at python.org Wed Mar 18 21:28:10 2009 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 18 Mar 2009 21:28:10 +0100 (CET) Subject: [Python-checkins] r70462 - in python/branches/release30-maint: Lib/locale.py Message-ID: <20090318202810.29DA31E400C@bag.python.org> Author: antoine.pitrou Date: Wed Mar 18 21:28:09 2009 New Revision: 70462 Log: Merged revisions 70461 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70461 | antoine.pitrou | 2009-03-18 21:26:42 +0100 (mer., 18 mars 2009) | 3 lines svnmerge from trunk for r70457 (sorry, I accidentally deleted the commit message) ........ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/locale.py Modified: python/branches/release30-maint/Lib/locale.py ============================================================================== --- python/branches/release30-maint/Lib/locale.py (original) +++ python/branches/release30-maint/Lib/locale.py Wed Mar 18 21:28:09 2009 @@ -158,7 +158,7 @@ groups.reverse() return ( left_spaces + thousands_sep.join(groups) + right_spaces, - len(groups) - 1 + len(thousands_sep) * (len(groups) - 1) ) # Strip a given amount of excess padding from the given string From buildbot at python.org Wed Mar 18 21:29:37 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 20:29:37 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090318202938.1C5061E400C@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/427 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_exception_variations make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Mar 18 21:52:16 2009 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Mar 2009 21:52:16 +0100 (CET) Subject: [Python-checkins] r70463 - in python/trunk: Lib/test/test_traceback.py Misc/NEWS Objects/frameobject.c Python/traceback.c Message-ID: <20090318205216.6CDB61E4002@bag.python.org> Author: benjamin.peterson Date: Wed Mar 18 21:52:15 2009 New Revision: 70463 Log: fix strange errors when setting attributes on tracebacks #4034 Modified: python/trunk/Lib/test/test_traceback.py python/trunk/Misc/NEWS python/trunk/Objects/frameobject.c python/trunk/Python/traceback.c Modified: python/trunk/Lib/test/test_traceback.py ============================================================================== --- python/trunk/Lib/test/test_traceback.py (original) +++ python/trunk/Lib/test/test_traceback.py Wed Mar 18 21:52:15 2009 @@ -111,14 +111,6 @@ os.unlink(os.path.join(testdir, f)) os.rmdir(testdir) - def test_members(self): - # Covers Python/structmember.c::listmembers() - try: - 1/0 - except: - import sys - sys.exc_traceback.__members__ - def test_base_exception(self): # Test that exceptions derived from BaseException are formatted right e = KeyboardInterrupt() Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Wed Mar 18 21:52:15 2009 @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #4034: Fix weird attribute error messages of the traceback object. (As a + result traceback.__members__ no longer exists.) + - Issue #4474: PyUnicode_FromWideChar now converts characters outside the BMP to surrogate pairs, on systems with sizeof(wchar_t) == 4 and sizeof(Py_UNICODE) == 2. Modified: python/trunk/Objects/frameobject.c ============================================================================== --- python/trunk/Objects/frameobject.c (original) +++ python/trunk/Objects/frameobject.c Wed Mar 18 21:52:15 2009 @@ -604,7 +604,17 @@ int _PyFrame_Init() { builtin_object = PyString_InternFromString("__builtins__"); - return (builtin_object != NULL); + if (builtin_object == NULL) + return 0; + /* + Traceback objects are not created the normal way (through calling the + type), so PyType_Ready has to be called here. + */ + if (PyType_Ready(&PyTraceBack_Type)) { + Py_DECREF(builtin_object); + return 0; + } + return 1; } PyFrameObject * Modified: python/trunk/Python/traceback.c ============================================================================== --- python/trunk/Python/traceback.c (original) +++ python/trunk/Python/traceback.c Wed Mar 18 21:52:15 2009 @@ -11,20 +11,14 @@ #define OFF(x) offsetof(PyTracebackObject, x) -static struct memberlist tb_memberlist[] = { - {"tb_next", T_OBJECT, OFF(tb_next)}, - {"tb_frame", T_OBJECT, OFF(tb_frame)}, - {"tb_lasti", T_INT, OFF(tb_lasti)}, - {"tb_lineno", T_INT, OFF(tb_lineno)}, +static PyMemberDef tb_memberlist[] = { + {"tb_next", T_OBJECT, OFF(tb_next), READONLY}, + {"tb_frame", T_OBJECT, OFF(tb_frame), READONLY}, + {"tb_lasti", T_INT, OFF(tb_lasti), READONLY}, + {"tb_lineno", T_INT, OFF(tb_lineno), READONLY}, {NULL} /* Sentinel */ }; -static PyObject * -tb_getattr(PyTracebackObject *tb, char *name) -{ - return PyMember_Get((char *)tb, tb_memberlist, name); -} - static void tb_dealloc(PyTracebackObject *tb) { @@ -58,7 +52,7 @@ 0, (destructor)tb_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ - (getattrfunc)tb_getattr, /*tp_getattr*/ + 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ @@ -80,8 +74,8 @@ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ + tb_memberlist, /* tp_members */ + 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ }; From python-checkins at python.org Wed Mar 18 21:58:09 2009 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Mar 2009 21:58:09 +0100 (CET) Subject: [Python-checkins] r70464 - python/trunk/Doc/library/functions.rst Message-ID: <20090318205809.9A10B1E400C@bag.python.org> Author: benjamin.peterson Date: Wed Mar 18 21:58:09 2009 New Revision: 70464 Log: a much better example Modified: python/trunk/Doc/library/functions.rst Modified: python/trunk/Doc/library/functions.rst ============================================================================== --- python/trunk/Doc/library/functions.rst (original) +++ python/trunk/Doc/library/functions.rst Wed Mar 18 21:58:09 2009 @@ -596,24 +596,13 @@ its :meth:`next` method; if the value returned is equal to *sentinel*, :exc:`StopIteration` will be raised, otherwise the value will be returned. - Example usage: :: - - >>> iterator = iter(range(10)) - >>> iterator - - >>> iterator.next() - 0 - >>> iterator.next() - 1 - >>> def my_generator(): - ... for i in range(10): - ... yield i - ... - >>> iterator = iter(my_generator().next, 7) - >>> iterator - - >>> list(iterator) - [0, 1, 2, 3, 4, 5, 6] + One useful application of the second form of :func:`iter` is to read lines of + a file until a certain line is reached. The following example reads a file + until ``"STOP"`` is reached: :: + + with open("mydata.txt") as fp: + for line in iter(fp.readline, "STOP"): + process_line(line) .. versionadded:: 2.2 From python at rcn.com Wed Mar 18 22:07:13 2009 From: python at rcn.com (Raymond Hettinger) Date: Wed, 18 Mar 2009 14:07:13 -0700 Subject: [Python-checkins] r70464 - python/trunk/Doc/library/functions.rst References: <20090318205809.9A10B1E400C@bag.python.org> Message-ID: > a much better example Much improved. Thanks. .Raymond From python-checkins at python.org Wed Mar 18 22:49:29 2009 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 18 Mar 2009 22:49:29 +0100 (CET) Subject: [Python-checkins] r70465 - in python/branches/release26-maint: Lib/test/test_traceback.py Misc/NEWS Objects/frameobject.c Python/traceback.c Message-ID: <20090318214929.D41A71E4002@bag.python.org> Author: benjamin.peterson Date: Wed Mar 18 22:49:29 2009 New Revision: 70465 Log: Merged revisions 70463 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70463 | benjamin.peterson | 2009-03-18 15:52:15 -0500 (Wed, 18 Mar 2009) | 1 line fix strange errors when setting attributes on tracebacks #4034 ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_traceback.py python/branches/release26-maint/Misc/NEWS python/branches/release26-maint/Objects/frameobject.c python/branches/release26-maint/Python/traceback.c Modified: python/branches/release26-maint/Lib/test/test_traceback.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_traceback.py (original) +++ python/branches/release26-maint/Lib/test/test_traceback.py Wed Mar 18 22:49:29 2009 @@ -111,14 +111,6 @@ os.unlink(os.path.join(testdir, f)) os.rmdir(testdir) - def test_members(self): - # Covers Python/structmember.c::listmembers() - try: - 1/0 - except: - import sys - sys.exc_traceback.__members__ - def test_base_exception(self): # Test that exceptions derived from BaseException are formatted right e = KeyboardInterrupt() Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Wed Mar 18 22:49:29 2009 @@ -14,6 +14,9 @@ - xrange() is now registered as a Sequence. +- Issue #4034: Fix weird attribute error messages of the traceback object. (As a + result traceback.__members__ no longer exists.) + - Issue #5247: Improve error message when unknown format codes are used when using str.format() with str, unicode, long, int, and float arguments. Modified: python/branches/release26-maint/Objects/frameobject.c ============================================================================== --- python/branches/release26-maint/Objects/frameobject.c (original) +++ python/branches/release26-maint/Objects/frameobject.c Wed Mar 18 22:49:29 2009 @@ -572,7 +572,17 @@ int _PyFrame_Init() { builtin_object = PyString_InternFromString("__builtins__"); - return (builtin_object != NULL); + if (builtin_object == NULL) + return 0; + /* + Traceback objects are not created the normal way (through calling the + type), so PyType_Ready has to be called here. + */ + if (PyType_Ready(&PyTraceBack_Type)) { + Py_DECREF(builtin_object); + return 0; + } + return 1; } PyFrameObject * Modified: python/branches/release26-maint/Python/traceback.c ============================================================================== --- python/branches/release26-maint/Python/traceback.c (original) +++ python/branches/release26-maint/Python/traceback.c Wed Mar 18 22:49:29 2009 @@ -11,20 +11,14 @@ #define OFF(x) offsetof(PyTracebackObject, x) -static struct memberlist tb_memberlist[] = { - {"tb_next", T_OBJECT, OFF(tb_next)}, - {"tb_frame", T_OBJECT, OFF(tb_frame)}, - {"tb_lasti", T_INT, OFF(tb_lasti)}, - {"tb_lineno", T_INT, OFF(tb_lineno)}, +static PyMemberDef tb_memberlist[] = { + {"tb_next", T_OBJECT, OFF(tb_next), READONLY}, + {"tb_frame", T_OBJECT, OFF(tb_frame), READONLY}, + {"tb_lasti", T_INT, OFF(tb_lasti), READONLY}, + {"tb_lineno", T_INT, OFF(tb_lineno), READONLY}, {NULL} /* Sentinel */ }; -static PyObject * -tb_getattr(PyTracebackObject *tb, char *name) -{ - return PyMember_Get((char *)tb, tb_memberlist, name); -} - static void tb_dealloc(PyTracebackObject *tb) { @@ -58,7 +52,7 @@ 0, (destructor)tb_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ - (getattrfunc)tb_getattr, /*tp_getattr*/ + 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ @@ -80,8 +74,8 @@ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ + tb_memberlist, /* tp_members */ + 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ }; From python-checkins at python.org Wed Mar 18 23:13:20 2009 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 18 Mar 2009 23:13:20 +0100 (CET) Subject: [Python-checkins] r70466 - python/trunk/Lib/collections.py Message-ID: <20090318221320.D20221E4039@bag.python.org> Author: raymond.hettinger Date: Wed Mar 18 23:13:20 2009 New Revision: 70466 Log: Use mixin methods where possible. (2.7 only -- these don't all exist in 3.0) Modified: python/trunk/Lib/collections.py Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Wed Mar 18 23:13:20 2009 @@ -69,24 +69,13 @@ setdefault = MutableMapping.setdefault update = MutableMapping.update pop = MutableMapping.pop - - def keys(self): - return list(self.__keys) - - def values(self): - return map(self.__getitem__, self.__keys) - - def items(self): - return zip(self.__keys, self.values()) - - def iterkeys(self): - return iter(self.__keys) - - def itervalues(self): - return _imap(self.__getitem__, self.__keys) - - def iteritems(self): - return _izip(self.__keys, _imap(self.__getitem__, self.__keys)) + keys = MutableMapping.keys + values = MutableMapping.values + items = MutableMapping.items + iterkeys = MutableMapping.iterkeys + itervalues = MutableMapping.itervalues + iteritems = MutableMapping.iteritems + __ne__ = MutableMapping.__ne__ def __repr__(self): if not self: From buildbot at python.org Thu Mar 19 00:31:06 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 18 Mar 2009 23:31:06 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.0 Message-ID: <20090318233106.E41441E4026@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.0/builds/211 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From g.brandl at gmx.net Thu Mar 19 00:33:11 2009 From: g.brandl at gmx.net (Georg Brandl) Date: Thu, 19 Mar 2009 00:33:11 +0100 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <49C01053.6070205@gmail.com> Message-ID: Antoine Pitrou schrieb: > Nick Coghlan gmail.com> writes: >> >> Perhaps the page just needs an overview section or table at the start >> that just gives a one line description of each method, and then links to >> the more detailed descriptions with longer examples? > > Or perhaps the examples should be folded by default in the HTML rendering, with > a simple way (a '+' sign or something) to unfold them. This is not even AJAX, > just simple Javascript grafted on an otherwise static HTML page. Not a bad idea. Some directive to mark a block of docs as "small print" that can be extended by JS (or is always displayed, maybe in smaller font, if JS is not supported) is easy to do. However, I fear that if it's used too much, people will get annoyed. Let's discuss this a bit more on the docs list. 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 g.brandl at gmx.net Thu Mar 19 00:50:22 2009 From: g.brandl at gmx.net (Georg Brandl) Date: Thu, 19 Mar 2009 00:50:22 +0100 Subject: [Python-checkins] r70438 - python/trunk/Doc/library/functions.rst In-Reply-To: <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> References: <20090317202952.2C3821E4002@bag.python.org> <305682430D3843B8B04885CFFC5140BC@RaymondLaptop1> <1afaf6160903171353k650b5830o3de5d613af5a8c25@mail.gmail.com> Message-ID: Benjamin Peterson schrieb: > 2009/3/17 Raymond Hettinger : >> FWIW, I think the examples need to be *very* short. >> The functions.rst page is growing hard to read because >> of all of the lengthy examples, caveats, warnings, and >> saying verbosity. We don't want to turn the main docs >> into a tutorial. It makes them harder to use. If someone >> just wants to scan what the builtin functions do, they now >> face a very lengthy page of reading. It's getting too fat. > > I think what really needs to happen is that function.rst and > stdtypes.rst need to split up into multiple pages. I believe Georg had > some intentions of doing that one day. It might make a good sprint > project. stdtypes.rst, yes. functions.rst is harder because there is no obvious splitting point. "Functions from A to M" is bad IMO. Grouping by categories too. So what remains is the "hide some content and show on request" way, and to trim down examples to what's absolutely needed to show valid usage. I don't care so much about the printable version -- you'll use the index there anyway to get to the right place. 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 buildbot at python.org Thu Mar 19 01:23:58 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 19 Mar 2009 00:23:58 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090319002359.153EA1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/738 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_ftplib.py", line 203, in run asyncore.loop(timeout=0.1, count=1) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 204, in loop poll_fun(timeout, map) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 141, in poll read(obj) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 78, in read obj.handle_error() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 74, in read obj.handle_read_event() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 413, in handle_read_event self.handle_read() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_ssl.py", line 408, in handle_read self.send(data.lower()) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 519, in send self.initiate_send() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 506, in initiate_send num_sent = dispatcher.send(self, self.out_buffer[:512]) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 349, in send result = self.socket.send(data) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/socket.py", line 165, in _dummy raise error(EBADF, 'Bad file descriptor') error: [Errno 9] Bad file descriptor 1 test failed: test_ftplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Mar 19 03:14:42 2009 From: python-checkins at python.org (brett.cannon) Date: Thu, 19 Mar 2009 03:14:42 +0100 (CET) Subject: [Python-checkins] r70467 - peps/trunk/pep-3143.txt Message-ID: <20090319021442.F15B21E4002@bag.python.org> Author: brett.cannon Date: Thu Mar 19 03:14:42 2009 New Revision: 70467 Log: Add PEP 3143: Standard daemon process library by Ben Finney. Added: peps/trunk/pep-3143.txt Added: peps/trunk/pep-3143.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-3143.txt Thu Mar 19 03:14:42 2009 @@ -0,0 +1,585 @@ +PEP: 3143 +Title: Standard daemon process library +Version: $Revision: 1.1 $ +Last-Modified: $Date: 2009-03-19 12:51 $ +Author: Ben Finney +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 2009-01-26 +Python-Version: 3.2 +Post-History: + + +======== +Abstract +======== + +Writing a program to become a well-behaved Unix daemon is somewhat +complex and tricky to get right, yet the steps are largely similar for +any daemon regardless of what else the program may need to do. + +This PEP introduces a package to the Python standard library that +provides a simple interface to the task of becoming a daemon process. + + +.. contents:: +.. + Table of Contents: + Abstract + Specification + Example usage + Interface + ``DaemonContext`` objects + Motivation + Rationale + Correct daemon behaviour + A daemon is not a service + Reference Implementation + Other daemon implementations + References + Copyright + + +============= +Specification +============= + +Example usage +============= + +Simple example of direct `DaemonContext` usage:: + + import daemon + + from spam import do_main_program + + with daemon.DaemonContext() as daemon_context: + do_main_program() + +More complex example usage:: + + import os + import grp + import signal + import daemon + import lockfile + + from spam import ( + initial_program_setup, + do_main_program, + program_cleanup, + reload_program_config, + ) + + context = daemon.DaemonContext( + working_directory='/var/lib/foo', + umask=0o002, + pidfile=lockfile.FileLock('/var/run/spam.pid'), + ) + + context.signal_map = { + signal.SIGTERM: program_cleanup, + signal.SIGHUP: 'terminate', + signal.SIGUSR1: reload_program_config, + } + + mail_gid = grp.getgrnam('mail').gr_gid + context.gid = mail_gid + + important_file = open('spam.data', 'w') + interesting_file = open('eggs.data', 'w') + context.files_preserve = [important_file, interesting_file] + + initial_program_setup() + + with context: + do_main_program() + + +Interface +========= + +A new package, `daemon`, is added to the standard library. + +A class, `DaemonContext`, is defined to represent the settings and +process context for the program running as a daemon process. + + +``DaemonContext`` objects +========================= + +A `DaemonContext` instance represents the behaviour settings and +process context for the program when it becomes a daemon. The +behaviour and environment is customised by setting options on the +instance, before calling the `open` method. + +Each option can be passed as a keyword argument to the `DaemonContext` +constructor, or subsequently altered by assigning to an attribute on +the instance at any time prior to calling `open`. That is, for +options named `wibble` and `wubble`, the following invocation:: + + foo = daemon.DaemonContext(wibble=bar, wubble=baz) + foo.open() + +is equivalent to:: + + foo = daemon.DaemonContext() + foo.wibble = bar + foo.wubble = baz + foo.open() + +The following options are defined. + +`files_preserve` + :Default: ``None`` + + List of files that should *not* be closed when starting the + daemon. If ``None``, all open file descriptors will be closed. + + Elements of the list are file descriptors (as returned by a file + object's `fileno()` method) or Python `file` objects. Each + specifies a file that is not to be closed during daemon start. + +`chroot_directory` + :Default: ``None`` + + Full path to a directory to set as the effective root directory of + the process. If ``None``, specifies that the root directory is not + to be changed. + +`working_directory` + :Default: ``'/'`` + + Full path of the working directory to which the process should + change on daemon start. + + Since a filesystem cannot be unmounted if a process has its + current working directory on that filesystem, this should either + be left at default or set to a directory that is a sensible ?home + directory? for the daemon while it is running. + +`umask` + :Default: ``0`` + + File access creation mask (?umask?) to set for the process on + daemon start. + + Since a process inherits its umask from its parent process, + starting the daemon will reset the umask to this value so that + files are created by the daemon with access modes as it expects. + +`pidfile` + :Default: ``None`` + + Context manager for a PID lock file. When the daemon context opens + and closes, it enters and exits the `pidfile` context manager. + +`detach_process` + :Default: ``None`` + + If ``True``, detach the process context when opening the daemon + context; if ``False``, do not detach. + + If unspecified (``None``) during initialisation of the instance, + this will be set to ``True`` by default, and ``False`` only if + detaching the process is determined to be redundant; for example, + in the case when the process was started by `init`, by `initd`, or + by `inetd`. + +`signal_map` + :Default: system-dependent + + Mapping from operating system signals to callback actions. + + The mapping is used when the daemon context opens, and determines + the action for each signal's signal handler: + + * A value of ``None`` will ignore the signal (by setting the + signal action to ``signal.SIG_IGN``). + + * A string value will be used as the name of an attribute on the + ``DaemonContext`` instance. The attribute's value will be used + as the action for the signal handler. + + * Any other value will be used as the action for the signal + handler. + + The default value depends on which signals are defined on the + running system. Each item from the list below whose signal is + actually defined in the ``signal`` module will appear in the + default map: + + * ``signal.SIGCLD``: ``None`` + + * ``signal.SIGTTIN``: ``None`` + + * ``signal.SIGTTOU``: ``None`` + + * ``signal.SIGTSTP``: ``None`` + + * ``signal.SIGTERM``: ``'terminate'`` + +`uid` + :Default: ``os.getuid()`` + +`gid` + :Default: ``os.getgid()`` + + The user ID (?UID?) value and group ID (?GID?) value to switch + the process to on daemon start. + + The default values, the real UID and GID of the process, will + relinquish any effective privilege elevation inherited by the + process. + +`prevent_core` + :Default: ``True`` + + If true, prevents the generation of core files, in order to avoid + leaking sensitive information from daemons run as `root`. + +`stdin` + :Default: ``None`` + +`stdout` + :Default: ``None`` + +`stderr` + :Default: ``None`` + + Each of `stdin`, `stdout`, and `stderr` is a file-like object + which will be used as the new file for the standard I/O stream + `sys.stdin`, `sys.stdout`, and `sys.stderr` respectively. The file + should therefore be open, with a minimum of mode 'r' in the case + of `stdin`, and mode 'w+' in the case of `stdout` and `stderr`. + + If the object has a `fileno()` method that returns a file + descriptor, the corresponding file will be excluded from being + closed during daemon start (that is, it will be treated as though + it were listed in `files_preserve`). + + If ``None``, the corresponding system stream is re-bound to the + file named by `os.devnull`. + + +The following methods are defined. + +`open()` + :Return: ``None`` + + Open the daemon context, turning the current program into a daemon + process. This performs the following steps: + + * If the `prevent_core` attribute is true, set the resource limits + for the process to prevent any core dump from the process. + + * If the `chroot_directory` attribute is not ``None``, set the + effective root directory of the process to that directory (via + `os.chroot`). + + This allows running the daemon process inside a ?chroot gaol? + as a means of limiting the system's exposure to rogue behaviour + by the process. Note that the specified directory needs to + already be set up for this purpose. + + * Set the process UID and GID to the `uid` and `gid` attribute + values. + + * Close all open file descriptors. This excludes those listed in + the `files_preserve` attribute, and those that correspond to the + `stdin`, `stdout`, or `stderr` attributes. + + * Change current working directory to the path specified by the + `working_directory` attribute. + + * Reset the file access creation mask to the value specified by + the `umask` attribute. + + * If the `detach_process` option is true, detach the current + process into its own process group, and disassociate from any + controlling terminal. + + * Set signal handlers as specified by the `signal_map` attribute. + + * If any of the attributes `stdin`, `stdout`, `stderr` are not + ``None``, bind the system streams `sys.stdin`, `sys.stdout`, + and/or `sys.stderr` to the files represented by the + corresponding attributes. Where the attribute has a file + descriptor, the descriptor is duplicated (instead of re-binding + the name). + + * If the `pidfile` attribute is not ``None``, enter its context + manager. + + When the function returns, the running program is a daemon + process. + +`close()` + :Return: ``None`` + + Close the daemon context. This does nothing by default, but may be + overridden by a derived class. + +`terminate(signal_number, stack_frame)` + :Return: ``None`` + + Signal handler for the ``signal.SIGTERM`` signal. Performs the + following steps: + + * If the `pidfile` attribute is not ``None``, exit its context + manager. + + * Call the `close()` method. + + * Raise a ``SystemExit`` exception. + +The class also implements the context manager protocol via +``__enter__`` and ``__exit__`` methods. + +`__enter__()` + :Return: The ``DaemonContext`` instance + + Call the instance's `open()` method, then return the instance. + +`__exit__(exc_type, exc_value, exc_traceback)` + :Return: ``True`` or ``False`` as defined by the context manager + protocol + + Call the instance's `close()` method, then return ``True`` if the + exception was handled or ``False`` if it was not. + + +========== +Motivation +========== + +The majority of programs written to be Unix daemons either implement +behaviour very similar to that in the `specification`_, or are +poorly-behaved daemons by the `correct daemon behaviour`_. + +Since these steps should be much the same in most implementations but +are very particular and easy to omit or implement incorrectly, they +are a prime target for a standard well-tested implementation in the +standard library. + + +========= +Rationale +========= + +Correct daemon behaviour +======================== + +According to Stevens in [stevens]_ ?2.6, a program should perform the +following steps to become a Unix daemon process. + +* Close all open file descriptors. + +* Change current working directory. + +* Reset the file access creation mask. + +* Run in the background. + +* Disassociate from process group. + +* Ignore terminal I/O signals. + +* Disassociate from control terminal. + +* Don't reacquire a control terminal. + +* Correctly handle the following circumstances: + + * Started by System V `init` process. + + * Daemon termination by ``SIGTERM`` signal. + + * Children generate ``SIGCLD`` signal. + +The `daemon` tool [slack-daemon]_ lists (in its summary of features) +behaviour that should be performed when turning a program into a +well-behaved Unix daemon process. It differs from this PEP's intent in +that it invokes a *separate* program as a daemon process. The +following features are appropriate for a daemon that starts itself +once the program is already running: + +* Sets up the correct process context for a daemon. + +* Behaves sensibly when started by `initd(8)` or `inetd(8)`. + +* Revokes any suid or sgid privileges to reduce security risks in case + daemon is incorrectly installed with special privileges. + +* Prevents the generation of core files to prevent leaking sensitive + information from daemons run as root (optional). + +* Names the daemon by creating and locking a PID file to guarantee + that only one daemon with the given name can execute at any given + time (optional). + +* Sets the user and group under which to run the daemon (optional, + root only). + +* Creates a chroot gaol (optional, root only). + +* Captures the daemon's stdout and stderr and directs them to syslog + (optional). + +A daemon is not a service +========================= + +This PEP addresses only Unix-style daemons, for which the above +correct behaviour is relevant, as opposed to comparable behaviours on +other operating systems. + +There is a related concept in many systems, called a ?service?. A +service differs from the model in this PEP, in that rather than having +the *current* program continue to run as a daemon process, a service +starts an *additional* process to run in the background, and the +current process communicates with that additional process via some +defined channels. + +The Unix-style daemon model in this PEP can be used, among other +things, to implement the background-process part of a service; but +this PEP does not address the other aspects of setting up and managing +a service. + + +======================== +Reference Implementation +======================== + +The `python-daemon` package [python-daemon]_. + +Other daemon implementations +============================ + +Prior to this PEP, several existing third-party Python libraries or +tools implemented some of this PEP's `correct daemon behaviour`_. + +The `reference implementation`_ is a fairly direct successor from the +following implementations: + +* Many good ideas were contributed by the community to Python cookbook + recipes #66012 [cookbook-66012]_ and #278731 [cookbook-278731]_. + +* The `bda.daemon` library [bda.daemon]_ is an implementation of + [cookbook-66012]_. It is the predecessor of [python-daemon]_. + +Other Python daemon implementations that differ from this PEP: + +* The `zdaemon` tool [zdaemon]_ was written for the Zope project. Like + [slack-daemon]_, it differs from this specification because it is + used to run another program as a daemon process. + +* The Python library `daemon` [clapper-daemon]_ is (according to its + homepage) no longer maintained. As of version 1.0.1, it implements + the basic steps from [stevens]_. + +* The `daemonize` library [seutter-daemonize]_ also implements the + basic steps from [stevens]_. + +* Ray Burr's `daemon.py` module [burr-daemon]_ provides the [stevens]_ + procedure as well as PID file handling and redirection of output to + syslog. + +* Twisted [twisted]_ includes, perhaps unsurprisingly, an + implementation of a process daemonisation API that is integrated + with the rest of the Twisted framework; it differs significantly + from the API in this PEP. + +* The Python `initd` library [dagitses-initd]_, which uses + [clapper-daemon]_, implements an equivalent of Unix `initd(8)` for + controlling a daemon process. + + +========== +References +========== + +.. [stevens] + + `Unix Network Programming`, W. Richard Stevens, 1994 Prentice + Hall. + +.. [slack-daemon] + + The (non-Python) ?libslack? implementation of a `daemon` tool + ``_ by ?raf? . + +.. [python-daemon] + + The `python-daemon` library + ``_ by Ben Finney et + al. + +.. [cookbook-66012] + + Python Cookbook recipe 66012, ?Fork a daemon process on Unix? + ``_. + +.. [cookbook-278731] + + Python Cookbook recipe 278731, ?Creating a daemon the Python way? + ``_. + +.. [bda.daemon] + + The `bda.daemon` library + ``_ by Robert + Niederreiter et al. + +.. [zdaemon] + + The `zdaemon` tool ``_ by + Guido van Rossum et al. + +.. [clapper-daemon] + + The `daemon` library ``_ by + Brian Clapper. + +.. [seutter-daemonize] + + The `daemonize` library ``_ by + Jerry Seutter. + +.. [burr-daemon] + + The `daemon.py` module + ``_ by Ray Burr. + +.. [twisted] + + The `Twisted` application framework + ``_ by Glyph Lefkowitz et + al. + +.. [dagitses-initd] + + The Python `initd` library ``_ + by Michael Andreas Dagitses. + + +========= +Copyright +========= + +This work is hereby placed in the public domain. To the extent that +placing a work in the public domain is not legally possible, the +copyright holder hereby grants to all recipients of this work all +rights and freedoms that would otherwise be restricted by copyright. + + +.. + Local variables: + mode: rst + coding: utf-8 + time-stamp-start: "^:Last-Modified:[ ]+" + time-stamp-end: "$" + time-stamp-line-limit: 20 + time-stamp-format: "%:y-%02m-%02d %02H:%02M" + End: + vim: filetype=rst fileencoding=utf-8 : From python-checkins at python.org Thu Mar 19 04:04:31 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 19 Mar 2009 04:04:31 +0100 (CET) Subject: [Python-checkins] r70468 - python/trunk/Lib/filecmp.py Message-ID: <20090319030431.826F81E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 19 04:04:31 2009 New Revision: 70468 Log: close files after comparing them Modified: python/trunk/Lib/filecmp.py Modified: python/trunk/Lib/filecmp.py ============================================================================== --- python/trunk/Lib/filecmp.py (original) +++ python/trunk/Lib/filecmp.py Thu Mar 19 04:04:31 2009 @@ -11,6 +11,7 @@ import os import stat +import contextlib from itertools import ifilter, ifilterfalse, imap, izip __all__ = ["cmp","dircmp","cmpfiles"] @@ -62,15 +63,14 @@ def _do_cmp(f1, f2): bufsize = BUFSIZE - fp1 = open(f1, 'rb') - fp2 = open(f2, 'rb') - while True: - b1 = fp1.read(bufsize) - b2 = fp2.read(bufsize) - if b1 != b2: - return False - if not b1: - return True + with contextlib.nested(open(f1, 'rb'), open(f2, 'rb')) as (fp1, fp2): + while True: + b1 = fp1.read(bufsize) + b2 = fp2.read(bufsize) + if b1 != b2: + return False + if not b1: + return True # Directory comparison class. # From python-checkins at python.org Thu Mar 19 04:35:27 2009 From: python-checkins at python.org (george.yoshida) Date: Thu, 19 Mar 2009 04:35:27 +0100 (CET) Subject: [Python-checkins] r70469 - peps/trunk/pep-0371.txt Message-ID: <20090319033527.C5B701E4002@bag.python.org> Author: george.yoshida Date: Thu Mar 19 04:35:27 2009 New Revision: 70469 Log: Fix typo Modified: peps/trunk/pep-0371.txt Modified: peps/trunk/pep-0371.txt ============================================================================== --- peps/trunk/pep-0371.txt (original) +++ peps/trunk/pep-0371.txt Thu Mar 19 04:35:27 2009 @@ -336,7 +336,7 @@ Issue 3042 in the tracker proposes that for Python 2.6 there will be two APIs for the threading module - the current one, and the PEP 8 compliant one. Warnings about the upcoming removal of the original - java-style API will be issues when -3 is invoked. + java-style API will be issued when -3 is invoked. In Python 3000, the threading API will become PEP 8 compliant, which means that the multiprocessing module and the threading module will From python-checkins at python.org Thu Mar 19 16:21:10 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 19 Mar 2009 16:21:10 +0100 (CET) Subject: [Python-checkins] r70470 - python/trunk/Lib/collections.py Message-ID: <20090319152110.735961E4002@bag.python.org> Author: raymond.hettinger Date: Thu Mar 19 16:21:10 2009 New Revision: 70470 Log: Improve implementation with better underlying data structure for O(1) deletions. Big-Oh performance now the same as regular dictionaries. Uses a doubly-linked list instead of a list/seq to track insertion order. Modified: python/trunk/Lib/collections.py Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Thu Mar 19 16:21:10 2009 @@ -23,45 +23,57 @@ if len(args) > 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) try: - self.__keys + self.__end except AttributeError: - # Note the underlying data structure for this class is likely to - # change in the future. Do not rely on it or access it directly. - self.__keys = deque() + self.clear() self.update(*args, **kwds) def clear(self): - self.__keys.clear() + self.__end = end = [] + end += [None, end, end] # null entry + self.__map = {} # key --> [key, prev, next] dict.clear(self) def __setitem__(self, key, value): if key not in self: - self.__keys.append(key) + end = self.__end + curr = end[1] + curr[2] = end[1] = self.__map[key] = [key, curr, end] dict.__setitem__(self, key, value) def __delitem__(self, key): dict.__delitem__(self, key) - self.__keys.remove(key) + key, prev, next = self.__map.pop(key) + prev[2] = next + next[1] = prev def __iter__(self): - return iter(self.__keys) + end = self.__end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] def __reversed__(self): - return reversed(self.__keys) + end = self.__end + curr = end[1] + while curr is not end: + yield curr[0] + curr = curr[1] def popitem(self): if not self: raise KeyError('dictionary is empty') - key = self.__keys.pop() - value = dict.pop(self, key) + key = next(reversed(self)) + value = self.pop(key) return key, value def __reduce__(self): items = [[k, self[k]] for k in self] - tmp = self.__keys - del self.__keys + tmp = self.__map, self.__end + del self.__map, self.__end inst_dict = vars(self).copy() - self.__keys = tmp + self.__map, self.__end = tmp if inst_dict: return (self.__class__, (items,), inst_dict) return self.__class__, (items,) From python-checkins at python.org Thu Mar 19 20:19:04 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 19 Mar 2009 20:19:04 +0100 (CET) Subject: [Python-checkins] r70471 - in python/trunk: Doc/library/json.rst Lib/json/__init__.py Lib/json/decoder.py Lib/json/tests/test_decode.py Lib/json/tests/test_unicode.py Misc/NEWS Modules/_json.c Message-ID: <20090319191904.9D94E1E400C@bag.python.org> Author: raymond.hettinger Date: Thu Mar 19 20:19:03 2009 New Revision: 70471 Log: Issue 5381: Add object_pairs_hook to the json module. Modified: python/trunk/Doc/library/json.rst python/trunk/Lib/json/__init__.py python/trunk/Lib/json/decoder.py python/trunk/Lib/json/tests/test_decode.py python/trunk/Lib/json/tests/test_unicode.py python/trunk/Misc/NEWS python/trunk/Modules/_json.c Modified: python/trunk/Doc/library/json.rst ============================================================================== --- python/trunk/Doc/library/json.rst (original) +++ python/trunk/Doc/library/json.rst Thu Mar 19 20:19:03 2009 @@ -166,7 +166,7 @@ :func:`dump`. -.. function:: load(fp[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, **kw]]]]]]]) +.. function:: load(fp[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]]) Deserialize *fp* (a ``.read()``-supporting file-like object containing a JSON document) to a Python object. @@ -182,6 +182,17 @@ *object_hook* will be used instead of the :class:`dict`. This feature can be used to implement custom decoders (e.g. JSON-RPC class hinting). + *object_pairs_hook* is an optional function that will be called with the + result of any object literal decode with an ordered list of pairs. The + return value of *object_pairs_hook* will be used instead of the + :class:`dict`. This feature can be used to implement custom decoders that + rely on the order that the key and value pairs are decoded (for example, + :func:`collections.OrderedDict` will remember the order of insertion). If + *object_hook* is also defined, the *object_pairs_hook* takes priority. + + .. versionchanged:: 2.7 + Added support for *object_pairs_hook*. + *parse_float*, if specified, will be called with the string of every JSON float to be decoded. By default, this is equivalent to ``float(num_str)``. This can be used to use another datatype or parser for JSON floats @@ -202,7 +213,7 @@ class. -.. function:: loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, **kw]]]]]]]) +.. function:: loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]]) Deserialize *s* (a :class:`str` or :class:`unicode` instance containing a JSON document) to a Python object. @@ -218,7 +229,7 @@ Encoders and decoders --------------------- -.. class:: JSONDecoder([encoding[, object_hook[, parse_float[, parse_int[, parse_constant[, strict]]]]]]) +.. class:: JSONDecoder([encoding[, object_hook[, parse_float[, parse_int[, parse_constant[, strict[, object_pairs_hook]]]]]]]) Simple JSON decoder. @@ -259,6 +270,17 @@ :class:`dict`. This can be used to provide custom deserializations (e.g. to support JSON-RPC class hinting). + *object_pairs_hook*, if specified will be called with the result of every + JSON object decoded with an ordered list of pairs. The return value of + *object_pairs_hook* will be used instead of the :class:`dict`. This + feature can be used to implement custom decoders that rely on the order + that the key and value pairs are decoded (for example, + :func:`collections.OrderedDict` will remember the order of insertion). If + *object_hook* is also defined, the *object_pairs_hook* takes priority. + + .. versionchanged:: 2.7 + Added support for *object_pairs_hook*. + *parse_float*, if specified, will be called with the string of every JSON float to be decoded. By default, this is equivalent to ``float(num_str)``. This can be used to use another datatype or parser for JSON floats Modified: python/trunk/Lib/json/__init__.py ============================================================================== --- python/trunk/Lib/json/__init__.py (original) +++ python/trunk/Lib/json/__init__.py Thu Mar 19 20:19:03 2009 @@ -238,11 +238,12 @@ **kw).encode(obj) -_default_decoder = JSONDecoder(encoding=None, object_hook=None) +_default_decoder = JSONDecoder(encoding=None, object_hook=None, + object_pairs_hook=None) def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None, - parse_int=None, parse_constant=None, **kw): + parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing a JSON document) to a Python object. @@ -265,11 +266,11 @@ return loads(fp.read(), encoding=encoding, cls=cls, object_hook=object_hook, parse_float=parse_float, parse_int=parse_int, - parse_constant=parse_constant, **kw) + parse_constant=parse_constant, object_pairs_hook=None, **kw) def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, - parse_int=None, parse_constant=None, **kw): + parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON document) to a Python object. @@ -304,12 +305,14 @@ """ if (cls is None and encoding is None and object_hook is None and parse_int is None and parse_float is None and - parse_constant is None and not kw): + parse_constant is None and object_pairs_hook is None and not kw): return _default_decoder.decode(s) if cls is None: cls = JSONDecoder if object_hook is not None: kw['object_hook'] = object_hook + if object_pairs_hook is not None: + kw['object_pairs_hook'] = object_pairs_hook if parse_float is not None: kw['parse_float'] = parse_float if parse_int is not None: Modified: python/trunk/Lib/json/decoder.py ============================================================================== --- python/trunk/Lib/json/decoder.py (original) +++ python/trunk/Lib/json/decoder.py Thu Mar 19 20:19:03 2009 @@ -147,8 +147,9 @@ WHITESPACE_STR = ' \t\n\r' def JSONObject((s, end), encoding, strict, scan_once, object_hook, - _w=WHITESPACE.match, _ws=WHITESPACE_STR): - pairs = {} + object_pairs_hook, _w=WHITESPACE.match, _ws=WHITESPACE_STR): + pairs = [] + pairs_append = pairs.append # Use a slice to prevent IndexError from being raised, the following # check will raise a more specific ValueError if the string is empty nextchar = s[end:end + 1] @@ -187,7 +188,7 @@ value, end = scan_once(s, end) except StopIteration: raise ValueError(errmsg("Expecting object", s, end)) - pairs[key] = value + pairs_append((key, value)) try: nextchar = s[end] @@ -218,6 +219,10 @@ if nextchar != '"': raise ValueError(errmsg("Expecting property name", s, end - 1)) + if object_pairs_hook is not None: + result = object_pairs_hook(pairs) + return result, end + pairs = dict(pairs) if object_hook is not None: pairs = object_hook(pairs) return pairs, end @@ -289,7 +294,8 @@ """ def __init__(self, encoding=None, object_hook=None, parse_float=None, - parse_int=None, parse_constant=None, strict=True): + parse_int=None, parse_constant=None, strict=True, + object_pairs_hook=None): """``encoding`` determines the encoding used to interpret any ``str`` objects decoded by this instance (utf-8 by default). It has no effect when decoding ``unicode`` objects. @@ -320,6 +326,7 @@ """ self.encoding = encoding self.object_hook = object_hook + self.object_pairs_hook = object_pairs_hook self.parse_float = parse_float or float self.parse_int = parse_int or int self.parse_constant = parse_constant or _CONSTANTS.__getitem__ Modified: python/trunk/Lib/json/tests/test_decode.py ============================================================================== --- python/trunk/Lib/json/tests/test_decode.py (original) +++ python/trunk/Lib/json/tests/test_decode.py Thu Mar 19 20:19:03 2009 @@ -2,6 +2,7 @@ from unittest import TestCase import json +from collections import OrderedDict class TestDecode(TestCase): def test_decimal(self): @@ -20,3 +21,18 @@ # exercise the uncommon cases. The array cases are already covered. rval = json.loads('{ "key" : "value" , "k":"v" }') self.assertEquals(rval, {"key":"value", "k":"v"}) + + def test_object_pairs_hook(self): + s = '{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}' + p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), + ("qrt", 5), ("pad", 6), ("hoy", 7)] + self.assertEqual(json.loads(s), eval(s)) + self.assertEqual(json.loads(s, object_pairs_hook = lambda x: x), p) + od = json.loads(s, object_pairs_hook = OrderedDict) + self.assertEqual(od, OrderedDict(p)) + self.assertEqual(type(od), OrderedDict) + # the object_pairs_hook takes priority over the object_hook + self.assertEqual(json.loads(s, + object_pairs_hook = OrderedDict, + object_hook = lambda x: None), + OrderedDict(p)) Modified: python/trunk/Lib/json/tests/test_unicode.py ============================================================================== --- python/trunk/Lib/json/tests/test_unicode.py (original) +++ python/trunk/Lib/json/tests/test_unicode.py Thu Mar 19 20:19:03 2009 @@ -1,6 +1,7 @@ from unittest import TestCase import json +from collections import OrderedDict class TestUnicode(TestCase): def test_encoding1(self): @@ -54,6 +55,21 @@ s = '"\\u{0:04x}"'.format(i) self.assertEquals(json.loads(s), u) + def test_object_pairs_hook_with_unicode(self): + s = u'{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}' + p = [(u"xkd", 1), (u"kcw", 2), (u"art", 3), (u"hxm", 4), + (u"qrt", 5), (u"pad", 6), (u"hoy", 7)] + self.assertEqual(json.loads(s), eval(s)) + self.assertEqual(json.loads(s, object_pairs_hook = lambda x: x), p) + od = json.loads(s, object_pairs_hook = OrderedDict) + self.assertEqual(od, OrderedDict(p)) + self.assertEqual(type(od), OrderedDict) + # the object_pairs_hook takes priority over the object_hook + self.assertEqual(json.loads(s, + object_pairs_hook = OrderedDict, + object_hook = lambda x: None), + OrderedDict(p)) + def test_default_encoding(self): self.assertEquals(json.loads(u'{"a": "\xe9"}'.encode('utf-8')), {'a': u'\xe9'}) Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Thu Mar 19 20:19:03 2009 @@ -181,6 +181,9 @@ Library ------- +- Issue #5381: Added object_pairs_hook to the json module. This allows + OrderedDicts to be built by the decoder. + - Issue #2110: Add support for thousands separator and 'n' type specifier to Decimal.__format__ Modified: python/trunk/Modules/_json.c ============================================================================== --- python/trunk/Modules/_json.c (original) +++ python/trunk/Modules/_json.c Thu Mar 19 20:19:03 2009 @@ -35,6 +35,7 @@ PyObject *encoding; PyObject *strict; PyObject *object_hook; + PyObject *pairs_hook; PyObject *parse_float; PyObject *parse_int; PyObject *parse_constant; @@ -44,6 +45,7 @@ {"encoding", T_OBJECT, offsetof(PyScannerObject, encoding), READONLY, "encoding"}, {"strict", T_OBJECT, offsetof(PyScannerObject, strict), READONLY, "strict"}, {"object_hook", T_OBJECT, offsetof(PyScannerObject, object_hook), READONLY, "object_hook"}, + {"object_pairs_hook", T_OBJECT, offsetof(PyScannerObject, pairs_hook), READONLY, "object_pairs_hook"}, {"parse_float", T_OBJECT, offsetof(PyScannerObject, parse_float), READONLY, "parse_float"}, {"parse_int", T_OBJECT, offsetof(PyScannerObject, parse_int), READONLY, "parse_int"}, {"parse_constant", T_OBJECT, offsetof(PyScannerObject, parse_constant), READONLY, "parse_constant"}, @@ -891,6 +893,7 @@ Py_VISIT(s->encoding); Py_VISIT(s->strict); Py_VISIT(s->object_hook); + Py_VISIT(s->pairs_hook); Py_VISIT(s->parse_float); Py_VISIT(s->parse_int); Py_VISIT(s->parse_constant); @@ -906,6 +909,7 @@ Py_CLEAR(s->encoding); Py_CLEAR(s->strict); Py_CLEAR(s->object_hook); + Py_CLEAR(s->pairs_hook); Py_CLEAR(s->parse_float); Py_CLEAR(s->parse_int); Py_CLEAR(s->parse_constant); @@ -923,13 +927,17 @@ */ char *str = PyString_AS_STRING(pystr); Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1; - PyObject *rval = PyDict_New(); + PyObject *rval; + PyObject *pairs; + PyObject *item; PyObject *key = NULL; PyObject *val = NULL; char *encoding = PyString_AS_STRING(s->encoding); int strict = PyObject_IsTrue(s->strict); Py_ssize_t next_idx; - if (rval == NULL) + + pairs = PyList_New(0); + if (pairs == NULL) return NULL; /* skip whitespace after { */ @@ -962,11 +970,16 @@ if (val == NULL) goto bail; - if (PyDict_SetItem(rval, key, val) == -1) + item = PyTuple_Pack(2, key, val); + if (item == NULL) goto bail; - Py_CLEAR(key); Py_CLEAR(val); + if (PyList_Append(pairs, item) == -1) { + Py_DECREF(item); + goto bail; + } + Py_DECREF(item); idx = next_idx; /* skip whitespace before } or , */ @@ -992,6 +1005,23 @@ raise_errmsg("Expecting object", pystr, end_idx); goto bail; } + + /* if pairs_hook is not None: rval = object_pairs_hook(pairs) */ + if (s->pairs_hook != Py_None) { + val = PyObject_CallFunctionObjArgs(s->pairs_hook, pairs, NULL); + if (val == NULL) + goto bail; + Py_DECREF(pairs); + *next_idx_ptr = idx + 1; + return val; + } + + rval = PyObject_CallFunctionObjArgs((PyObject *)(&PyDict_Type), + pairs, NULL); + if (rval == NULL) + goto bail; + Py_CLEAR(pairs); + /* if object_hook is not None: rval = object_hook(rval) */ if (s->object_hook != Py_None) { val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL); @@ -1006,7 +1036,7 @@ bail: Py_XDECREF(key); Py_XDECREF(val); - Py_DECREF(rval); + Py_XDECREF(pairs); return NULL; } @@ -1021,12 +1051,16 @@ */ Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr); Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1; - PyObject *val = NULL; - PyObject *rval = PyDict_New(); + PyObject *rval; + PyObject *pairs; + PyObject *item; PyObject *key = NULL; + PyObject *val = NULL; int strict = PyObject_IsTrue(s->strict); Py_ssize_t next_idx; - if (rval == NULL) + + pairs = PyList_New(0); + if (pairs == NULL) return NULL; /* skip whitespace after { */ @@ -1059,11 +1093,16 @@ if (val == NULL) goto bail; - if (PyDict_SetItem(rval, key, val) == -1) + item = PyTuple_Pack(2, key, val); + if (item == NULL) goto bail; - Py_CLEAR(key); Py_CLEAR(val); + if (PyList_Append(pairs, item) == -1) { + Py_DECREF(item); + goto bail; + } + Py_DECREF(item); idx = next_idx; /* skip whitespace before } or , */ @@ -1091,6 +1130,22 @@ goto bail; } + /* if pairs_hook is not None: rval = object_pairs_hook(pairs) */ + if (s->pairs_hook != Py_None) { + val = PyObject_CallFunctionObjArgs(s->pairs_hook, pairs, NULL); + if (val == NULL) + goto bail; + Py_DECREF(pairs); + *next_idx_ptr = idx + 1; + return val; + } + + rval = PyObject_CallFunctionObjArgs((PyObject *)(&PyDict_Type), + pairs, NULL); + if (rval == NULL) + goto bail; + Py_CLEAR(pairs); + /* if object_hook is not None: rval = object_hook(rval) */ if (s->object_hook != Py_None) { val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL); @@ -1105,7 +1160,7 @@ bail: Py_XDECREF(key); Py_XDECREF(val); - Py_DECREF(rval); + Py_XDECREF(pairs); return NULL; } @@ -1648,6 +1703,7 @@ s->encoding = NULL; s->strict = NULL; s->object_hook = NULL; + s->pairs_hook = NULL; s->parse_float = NULL; s->parse_int = NULL; s->parse_constant = NULL; @@ -1690,6 +1746,9 @@ s->object_hook = PyObject_GetAttrString(ctx, "object_hook"); if (s->object_hook == NULL) goto bail; + s->pairs_hook = PyObject_GetAttrString(ctx, "object_pairs_hook"); + if (s->object_hook == NULL) + goto bail; s->parse_float = PyObject_GetAttrString(ctx, "parse_float"); if (s->parse_float == NULL) goto bail; @@ -1706,6 +1765,7 @@ Py_CLEAR(s->encoding); Py_CLEAR(s->strict); Py_CLEAR(s->object_hook); + Py_CLEAR(s->pairs_hook); Py_CLEAR(s->parse_float); Py_CLEAR(s->parse_int); Py_CLEAR(s->parse_constant); From python-checkins at python.org Thu Mar 19 20:25:07 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 19 Mar 2009 20:25:07 +0100 (CET) Subject: [Python-checkins] r70472 - python/trunk/Modules/_json.c Message-ID: <20090319192507.6C35F1E4013@bag.python.org> Author: raymond.hettinger Date: Thu Mar 19 20:24:43 2009 New Revision: 70472 Log: Silence a compiler warning. Modified: python/trunk/Modules/_json.c Modified: python/trunk/Modules/_json.c ============================================================================== --- python/trunk/Modules/_json.c (original) +++ python/trunk/Modules/_json.c Thu Mar 19 20:24:43 2009 @@ -116,7 +116,7 @@ static int encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ssize_t indent_level); static PyObject * -_encoded_const(PyObject *const); +_encoded_const(PyObject *obj); static void raise_errmsg(char *msg, PyObject *s, Py_ssize_t end); static PyObject * From python-checkins at python.org Thu Mar 19 20:59:58 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 19 Mar 2009 20:59:58 +0100 (CET) Subject: [Python-checkins] r70473 - in python/trunk: Doc/library/collections.rst Lib/collections.py Lib/test/test_collections.py Message-ID: <20090319195958.994791E4002@bag.python.org> Author: raymond.hettinger Date: Thu Mar 19 20:59:58 2009 New Revision: 70473 Log: * Add clearer comment to initialization code. * Add optional argument to popitem() -- modeled after Anthon van der Neut's C version. * Fix method markup in docs. Modified: python/trunk/Doc/library/collections.rst python/trunk/Lib/collections.py python/trunk/Lib/test/test_collections.py Modified: python/trunk/Doc/library/collections.rst ============================================================================== --- python/trunk/Doc/library/collections.rst (original) +++ python/trunk/Doc/library/collections.rst Thu Mar 19 20:59:58 2009 @@ -858,8 +858,11 @@ .. versionadded:: 2.7 -The :meth:`popitem` method for ordered dictionaries returns and removes the -last added entry. The key/value pairs are returned in LIFO order. +.. method:: OrderedDict.popitem(last=True) + + The :meth:`popitem` method for ordered dictionaries returns and removes + a (key, value) pair. The pairs are returned in LIFO order if *last* is + true or FIFO order if false. Equality tests between :class:`OrderedDict` objects are order-sensitive and are implemented as ``list(od1.items())==list(od2.items())``. @@ -867,3 +870,8 @@ :class:`Mapping` objects are order-insensitive like regular dictionaries. This allows :class:`OrderedDict` objects to be substituted anywhere a regular dictionary is used. + +.. seealso:: + + `Equivalent OrderedDict recipe `_ + that runs on Python 2.4 or later. Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Thu Mar 19 20:59:58 2009 @@ -30,7 +30,7 @@ def clear(self): self.__end = end = [] - end += [None, end, end] # null entry + end += [None, end, end] # sentinel node for doubly linked list self.__map = {} # key --> [key, prev, next] dict.clear(self) @@ -61,10 +61,10 @@ yield curr[0] curr = curr[1] - def popitem(self): + def popitem(self, last=True): if not self: raise KeyError('dictionary is empty') - key = next(reversed(self)) + key = next(reversed(self)) if last else next(iter(self)) value = self.pop(key) return key, value Modified: python/trunk/Lib/test/test_collections.py ============================================================================== --- python/trunk/Lib/test/test_collections.py (original) +++ python/trunk/Lib/test/test_collections.py Thu Mar 19 20:59:58 2009 @@ -768,12 +768,19 @@ class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol): type2test = OrderedDict + def test_popitem(self): + d = self._empty_mapping() + self.assertRaises(KeyError, d.popitem) + class MyOrderedDict(OrderedDict): pass class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol): type2test = MyOrderedDict + def test_popitem(self): + d = self._empty_mapping() + self.assertRaises(KeyError, d.popitem) import doctest, collections From buildbot at python.org Thu Mar 19 21:11:54 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 19 Mar 2009 20:11:54 +0000 Subject: [Python-checkins] buildbot failure in OS X x86 trunk Message-ID: <20090319201157.BEA521E401A@bag.python.org> The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/247 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_cmd_line_script make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Thu Mar 19 21:13:37 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 19 Mar 2009 20:13:37 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090319201337.701DA1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/741 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Thu Mar 19 21:30:57 2009 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 19 Mar 2009 21:30:57 +0100 (CET) Subject: [Python-checkins] r70474 - in python/branches/py3k: Doc/library/collections.rst Lib/collections.py Lib/test/test_collections.py Message-ID: <20090319203057.1729E1E4002@bag.python.org> Author: raymond.hettinger Date: Thu Mar 19 21:30:56 2009 New Revision: 70474 Log: Forward port r70470 and r70473 for OrderedDict to use a doubly linked list. Modified: python/branches/py3k/Doc/library/collections.rst python/branches/py3k/Lib/collections.py python/branches/py3k/Lib/test/test_collections.py Modified: python/branches/py3k/Doc/library/collections.rst ============================================================================== --- python/branches/py3k/Doc/library/collections.rst (original) +++ python/branches/py3k/Doc/library/collections.rst Thu Mar 19 21:30:56 2009 @@ -836,8 +836,11 @@ .. versionadded:: 3.1 -The :meth:`popitem` method for ordered dictionaries returns and removes the -last added entry. The key/value pairs are returned in LIFO order. +.. method:: OrderedDict.popitem(last=True) + + The :meth:`popitem` method for ordered dictionaries returns and removes + a (key, value) pair. The pairs are returned in LIFO order if *last* is + true or FIFO order if false. Equality tests between :class:`OrderedDict` objects are order-sensitive and are implemented as ``list(od1.items())==list(od2.items())``. @@ -846,6 +849,11 @@ This allows :class:`OrderedDict` objects to be substituted anywhere a regular dictionary is used. +.. seealso:: + + `Equivalent OrderedDict recipe `_ + that runs on Python 2.4 or later. + :class:`UserDict` objects ------------------------- Modified: python/branches/py3k/Lib/collections.py ============================================================================== --- python/branches/py3k/Lib/collections.py (original) +++ python/branches/py3k/Lib/collections.py Thu Mar 19 21:30:56 2009 @@ -23,45 +23,57 @@ if len(args) > 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) try: - self.__keys + self.__end except AttributeError: - # Note the underlying data structure for this class is likely to - # change in the future. Do not rely on it or access it directly. - self.__keys = deque() + self.clear() self.update(*args, **kwds) def clear(self): - self.__keys.clear() + self.__end = end = [] + end += [None, end, end] # sentinel node for doubly linked list + self.__map = {} # key --> [key, prev, next] dict.clear(self) def __setitem__(self, key, value): if key not in self: - self.__keys.append(key) + end = self.__end + curr = end[1] + curr[2] = end[1] = self.__map[key] = [key, curr, end] dict.__setitem__(self, key, value) def __delitem__(self, key): dict.__delitem__(self, key) - self.__keys.remove(key) + key, prev, next = self.__map.pop(key) + prev[2] = next + next[1] = prev def __iter__(self): - return iter(self.__keys) + end = self.__end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] def __reversed__(self): - return reversed(self.__keys) + end = self.__end + curr = end[1] + while curr is not end: + yield curr[0] + curr = curr[1] - def popitem(self): + def popitem(self, last=True): if not self: raise KeyError('dictionary is empty') - key = self.__keys.pop() - value = dict.pop(self, key) + key = next(reversed(self)) if last else next(iter(self)) + value = self.pop(key) return key, value def __reduce__(self): items = [[k, self[k]] for k in self] - tmp = self.__keys - del self.__keys + tmp = self.__map, self.__end + del self.__map, self.__end inst_dict = vars(self).copy() - self.__keys = tmp + self.__map, self.__end = tmp if inst_dict: return (self.__class__, (items,), inst_dict) return self.__class__, (items,) Modified: python/branches/py3k/Lib/test/test_collections.py ============================================================================== --- python/branches/py3k/Lib/test/test_collections.py (original) +++ python/branches/py3k/Lib/test/test_collections.py Thu Mar 19 21:30:56 2009 @@ -770,12 +770,19 @@ class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol): type2test = OrderedDict + def test_popitem(self): + d = self._empty_mapping() + self.assertRaises(KeyError, d.popitem) + class MyOrderedDict(OrderedDict): pass class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol): type2test = MyOrderedDict + def test_popitem(self): + d = self._empty_mapping() + self.assertRaises(KeyError, d.popitem) import doctest, collections From buildbot at python.org Thu Mar 19 22:19:13 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 19 Mar 2009 21:19:13 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090319211914.0263C1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/524 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Fri Mar 20 00:12:42 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 20 Mar 2009 00:12:42 +0100 (CET) Subject: [Python-checkins] r70475 - python/trunk/Lib/collections.py Message-ID: <20090319231242.5229F1E4002@bag.python.org> Author: raymond.hettinger Date: Fri Mar 20 00:12:41 2009 New Revision: 70475 Log: * Add implementation notes. * Re-order methods so that those touching the underlying data structure come first and the derived methods come last. Modified: python/trunk/Lib/collections.py Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Fri Mar 20 00:12:41 2009 @@ -18,6 +18,18 @@ ################################################################################ class OrderedDict(dict, MutableMapping): + 'Dictionary that remembers insertion order' + # The inherited dict maps keys to values. + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted. It simplifies the algorithm. + # Setting a new item cause a new link to append to the doubly linked list. + # Deleting an item uses self.__map to find the link, which is then removed. + # Iteration follows the linked list in order. + # Reverse iteration follows the links backwards. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-Oh running times for all methods is the same as for regular dictionaries. def __init__(self, *args, **kwds): if len(args) > 1: @@ -49,24 +61,17 @@ def __iter__(self): end = self.__end - curr = end[2] + curr = end[2] # start at first link while curr is not end: - yield curr[0] - curr = curr[2] + yield curr[0] # yield KEY for each link + curr = curr[2] # goto next link def __reversed__(self): end = self.__end - curr = end[1] + curr = end[1] # start at last link while curr is not end: - yield curr[0] - curr = curr[1] - - def popitem(self, last=True): - if not self: - raise KeyError('dictionary is empty') - key = next(reversed(self)) if last else next(iter(self)) - value = self.pop(key) - return key, value + yield curr[0] # yield KEY for each link + curr = curr[1] # goto prev link def __reduce__(self): items = [[k, self[k]] for k in self] @@ -89,6 +94,13 @@ iteritems = MutableMapping.iteritems __ne__ = MutableMapping.__ne__ + def popitem(self, last=True): + if not self: + raise KeyError('dictionary is empty') + key = next(reversed(self)) if last else next(iter(self)) + value = self.pop(key) + return key, value + def __repr__(self): if not self: return '%s()' % (self.__class__.__name__,) From python-checkins at python.org Fri Mar 20 00:14:40 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 20 Mar 2009 00:14:40 +0100 (CET) Subject: [Python-checkins] r70476 - python/branches/py3k/Lib/collections.py Message-ID: <20090319231440.9A3481E4002@bag.python.org> Author: raymond.hettinger Date: Fri Mar 20 00:14:39 2009 New Revision: 70476 Log: Forward port 70475: Add implementation notes. Put methods in more readable order. Modified: python/branches/py3k/Lib/collections.py Modified: python/branches/py3k/Lib/collections.py ============================================================================== --- python/branches/py3k/Lib/collections.py (original) +++ python/branches/py3k/Lib/collections.py Fri Mar 20 00:14:39 2009 @@ -18,6 +18,18 @@ ################################################################################ class OrderedDict(dict, MutableMapping): + 'Dictionary that remembers insertion order' + # The inherited dict maps keys to values. + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted. It simplifies the algorithm. + # Setting a new item cause a new link to append to the doubly linked list. + # Deleting an item uses self.__map to find the link, which is then removed. + # Iteration follows the linked list in order. + # Reverse iteration follows the links backwards. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-Oh running times for all methods is the same as for regular dictionaries. def __init__(self, *args, **kwds): if len(args) > 1: @@ -49,24 +61,17 @@ def __iter__(self): end = self.__end - curr = end[2] + curr = end[2] # start at first link while curr is not end: - yield curr[0] - curr = curr[2] + yield curr[0] # yield KEY for each link + curr = curr[2] # goto next link def __reversed__(self): end = self.__end - curr = end[1] + curr = end[1] # start at last link while curr is not end: - yield curr[0] - curr = curr[1] - - def popitem(self, last=True): - if not self: - raise KeyError('dictionary is empty') - key = next(reversed(self)) if last else next(iter(self)) - value = self.pop(key) - return key, value + yield curr[0] # yield KEY for each link + curr = curr[1] # goto prev link def __reduce__(self): items = [[k, self[k]] for k in self] @@ -85,6 +90,13 @@ values = MutableMapping.values items = MutableMapping.items + def popitem(self, last=True): + if not self: + raise KeyError('dictionary is empty') + key = next(reversed(self)) if last else next(iter(self)) + value = self.pop(key) + return key, value + def __repr__(self): if not self: return '%s()' % (self.__class__.__name__,) From python-checkins at python.org Fri Mar 20 00:22:25 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 20 Mar 2009 00:22:25 +0100 (CET) Subject: [Python-checkins] r70477 - python/trunk/Lib/collections.py Message-ID: <20090319232225.6151D1E4059@bag.python.org> Author: raymond.hettinger Date: Fri Mar 20 00:22:25 2009 New Revision: 70477 Log: Fix typo Modified: python/trunk/Lib/collections.py Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Fri Mar 20 00:22:25 2009 @@ -23,13 +23,13 @@ # The internal self.__map dictionary maps keys to links in a doubly linked list. # The doubly linked list starts and ends with a sentinel element. # The sentinel element never gets deleted. It simplifies the algorithm. - # Setting a new item cause a new link to append to the doubly linked list. + # Setting a new item causes a new link to append to the doubly linked list. # Deleting an item uses self.__map to find the link, which is then removed. # Iteration follows the linked list in order. # Reverse iteration follows the links backwards. # The inherited dict provides __getitem__, __len__, __contains__, and get. # The remaining methods are order-aware. - # Big-Oh running times for all methods is the same as for regular dictionaries. + # Big-Oh running times for all methods are the same as for regular dictionaries. def __init__(self, *args, **kwds): if len(args) > 1: From python-checkins at python.org Fri Mar 20 00:23:16 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 20 Mar 2009 00:23:16 +0100 (CET) Subject: [Python-checkins] r70478 - python/branches/py3k/Lib/collections.py Message-ID: <20090319232316.096B21E4036@bag.python.org> Author: raymond.hettinger Date: Fri Mar 20 00:23:15 2009 New Revision: 70478 Log: Fix typo Modified: python/branches/py3k/Lib/collections.py Modified: python/branches/py3k/Lib/collections.py ============================================================================== --- python/branches/py3k/Lib/collections.py (original) +++ python/branches/py3k/Lib/collections.py Fri Mar 20 00:23:15 2009 @@ -23,13 +23,13 @@ # The internal self.__map dictionary maps keys to links in a doubly linked list. # The doubly linked list starts and ends with a sentinel element. # The sentinel element never gets deleted. It simplifies the algorithm. - # Setting a new item cause a new link to append to the doubly linked list. + # Setting a new item causes a new link to append to the doubly linked list. # Deleting an item uses self.__map to find the link, which is then removed. # Iteration follows the linked list in order. # Reverse iteration follows the links backwards. # The inherited dict provides __getitem__, __len__, __contains__, and get. # The remaining methods are order-aware. - # Big-Oh running times for all methods is the same as for regular dictionaries. + # Big-Oh running times for all methods are the same as for regular dictionaries. def __init__(self, *args, **kwds): if len(args) > 1: From buildbot at python.org Fri Mar 20 00:39:59 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 19 Mar 2009 23:39:59 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo 3.x Message-ID: <20090319233959.D21881E4002@bag.python.org> The Buildbot has detected a new failure of x86 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20gentoo%203.x/builds/530 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Unknown signal 32 sincerely, -The Buildbot From buildbot at python.org Fri Mar 20 01:51:54 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 20 Mar 2009 00:51:54 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090320005154.D41991E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/526 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Fri Mar 20 04:02:10 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 20 Mar 2009 03:02:10 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090320030210.5CAE51E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/423 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Fri Mar 20 16:51:56 2009 From: python-checkins at python.org (mark.dickinson) Date: Fri, 20 Mar 2009 16:51:56 +0100 (CET) Subject: [Python-checkins] r70479 - in python/trunk: Doc/library/sys.rst Doc/whatsnew/2.7.rst Include/longintrepr.h Include/longobject.h Include/pyport.h Include/pythonrun.h Lib/test/test_long.py Lib/test/test_sys.py Misc/NEWS Objects/longobject.c PC/pyconfig.h Python/marshal.c Python/pythonrun.c Python/sysmodule.c configure configure.in pyconfig.h.in Message-ID: <20090320155156.C06CB1E406D@bag.python.org> Author: mark.dickinson Date: Fri Mar 20 16:51:55 2009 New Revision: 70479 Log: Issue #4258: Use 30-bit digits for Python longs, on 64-bit platforms. Backport of r70459. Modified: python/trunk/Doc/library/sys.rst python/trunk/Doc/whatsnew/2.7.rst python/trunk/Include/longintrepr.h python/trunk/Include/longobject.h python/trunk/Include/pyport.h python/trunk/Include/pythonrun.h python/trunk/Lib/test/test_long.py python/trunk/Lib/test/test_sys.py python/trunk/Misc/NEWS python/trunk/Objects/longobject.c python/trunk/PC/pyconfig.h python/trunk/Python/marshal.c python/trunk/Python/pythonrun.c python/trunk/Python/sysmodule.c python/trunk/configure python/trunk/configure.in python/trunk/pyconfig.h.in Modified: python/trunk/Doc/library/sys.rst ============================================================================== --- python/trunk/Doc/library/sys.rst (original) +++ python/trunk/Doc/library/sys.rst Fri Mar 20 16:51:55 2009 @@ -498,6 +498,25 @@ .. versionadded:: 1.5.2 +.. data:: long_info + + A struct sequence that holds information about Python's + internal representation of integers. The attributes are read only. + + +-------------------------+----------------------------------------------+ + | attribute | explanation | + +=========================+==============================================+ + | :const:`bits_per_digit` | number of bits held in each digit. Python | + | | integers are stored internally in base | + | | ``2**long_info.bits_per_digit`` | + +-------------------------+----------------------------------------------+ + | :const:`sizeof_digit` | size in bytes of the C type used to | + | | represent a digit | + +-------------------------+----------------------------------------------+ + + .. versionadded:: 2.7 + + .. data:: last_type last_value last_traceback Modified: python/trunk/Doc/whatsnew/2.7.rst ============================================================================== --- python/trunk/Doc/whatsnew/2.7.rst (original) +++ python/trunk/Doc/whatsnew/2.7.rst Fri Mar 20 16:51:55 2009 @@ -86,6 +86,30 @@ (Contributed by Fredrik Johansson and Victor Stinner; :issue:`3439`.) +* Integers are now stored internally either in base 2**15 or in base + 2**30, the base being determined at build time. Previously, they + were always stored in base 2**15. Using base 2**30 gives + significant performance improvements on 64-bit machines, but + benchmark results on 32-bit machines have been mixed. Therefore, + the default is to use base 2**30 on 64-bit machines and base 2**15 + on 32-bit machines; on Unix, there's a new configure option + --enable-big-digits that can be used to override this default. + + Apart from the performance improvements this change should be + invisible to end users, with one exception: for testing and + debugging purposes there's a new structseq ``sys.long_info`` that + provides information about the internal format, giving the number of + bits per digit and the size in bytes of the C type used to store + each digit:: + + >>> import sys + >>> sys.long_info + sys.long_info(bits_per_digit=30, sizeof_digit=4) + + + (Contributed by Mark Dickinson; :issue:`4258`.) + + .. ====================================================================== Modified: python/trunk/Include/longintrepr.h ============================================================================== --- python/trunk/Include/longintrepr.h (original) +++ python/trunk/Include/longintrepr.h Fri Mar 20 16:51:55 2009 @@ -7,26 +7,61 @@ /* This is published for the benefit of "friend" marshal.c only. */ -/* Parameters of the long integer representation. - These shouldn't have to be changed as C should guarantee that a short - contains at least 16 bits, but it's made changeable anyway. - Note: 'digit' should be able to hold 2*MASK+1, and 'twodigits' - should be able to hold the intermediate results in 'mul' - (at most (BASE-1)*(2*BASE+1) == MASK*(2*MASK+3)). - Also, x_sub assumes that 'digit' is an unsigned type, and overflow - is handled by taking the result mod 2**N for some N > SHIFT. - And, at some places it is assumed that MASK fits in an int, as well. - long_pow() requires that SHIFT be divisible by 5. */ +/* Parameters of the long integer representation. There are two different + sets of parameters: one set for 30-bit digits, stored in an unsigned 32-bit + integer type, and one set for 15-bit digits with each digit stored in an + unsigned short. The value of PYLONG_BITS_IN_DIGIT, defined either at + configure time or in pyport.h, is used to decide which digit size to use. + + Type 'digit' should be able to hold 2*PyLong_BASE-1, and type 'twodigits' + should be an unsigned integer type able to hold all integers up to + PyLong_BASE*PyLong_BASE-1. x_sub assumes that 'digit' is an unsigned type, + and that overflow is handled by taking the result modulo 2**N for some N > + PyLong_SHIFT. The majority of the code doesn't care about the precise + value of PyLong_SHIFT, but there are some notable exceptions: + + - long_pow() requires that PyLong_SHIFT be divisible by 5 + + - PyLong_{As,From}ByteArray require that PyLong_SHIFT be at least 8 + + - long_hash() requires that PyLong_SHIFT is *strictly* less than the number + of bits in an unsigned long, as do the PyLong <-> long (or unsigned long) + conversion functions + - the long <-> size_t/Py_ssize_t conversion functions expect that + PyLong_SHIFT is strictly less than the number of bits in a size_t + + - the marshal code currently expects that PyLong_SHIFT is a multiple of 15 + + The values 15 and 30 should fit all of the above requirements, on any + platform. +*/ + +#if HAVE_STDINT_H +#include +#endif + +#if PYLONG_BITS_IN_DIGIT == 30 +#if !(defined HAVE_UINT64_T && defined HAVE_UINT32_T && \ + defined HAVE_INT64_T && defined HAVE_INT32_T) +#error "30-bit long digits requested, but the necessary types are not available on this platform" +#endif +typedef PY_UINT32_T digit; +typedef PY_INT32_T sdigit; /* signed variant of digit */ +typedef PY_UINT64_T twodigits; +typedef PY_INT64_T stwodigits; /* signed variant of twodigits */ +#define PyLong_SHIFT 30 +#elif PYLONG_BITS_IN_DIGIT == 15 typedef unsigned short digit; -typedef short sdigit; /* signed variant of digit */ -#define BASE_TWODIGITS_TYPE long -typedef unsigned BASE_TWODIGITS_TYPE twodigits; -typedef BASE_TWODIGITS_TYPE stwodigits; /* signed variant of twodigits */ - -#define PyLong_SHIFT 15 -#define PyLong_BASE ((digit)1 << PyLong_SHIFT) -#define PyLong_MASK ((digit)(PyLong_BASE - 1)) +typedef short sdigit; /* signed variant of digit */ +typedef unsigned long twodigits; +typedef long stwodigits; /* signed variant of twodigits */ +#define PyLong_SHIFT 15 +#else +#error "PYLONG_BITS_IN_DIGIT should be 15 or 30" +#endif +#define PyLong_BASE ((digit)1 << PyLong_SHIFT) +#define PyLong_MASK ((digit)(PyLong_BASE - 1)) /* b/w compatibility with Python 2.5 */ #define SHIFT PyLong_SHIFT Modified: python/trunk/Include/longobject.h ============================================================================== --- python/trunk/Include/longobject.h (original) +++ python/trunk/Include/longobject.h Fri Mar 20 16:51:55 2009 @@ -24,6 +24,7 @@ PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLong(PyObject *); PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLongMask(PyObject *); PyAPI_FUNC(Py_ssize_t) PyLong_AsSsize_t(PyObject *); +PyAPI_FUNC(PyObject *) PyLong_GetInfo(void); /* For use by intobject.c only */ #define _PyLong_AsSsize_t PyLong_AsSsize_t Modified: python/trunk/Include/pyport.h ============================================================================== --- python/trunk/Include/pyport.h (original) +++ python/trunk/Include/pyport.h Fri Mar 20 16:51:55 2009 @@ -80,6 +80,57 @@ #endif #endif /* HAVE_LONG_LONG */ +/* a build with 30-bit digits for Python long integers needs an exact-width + * 32-bit unsigned integer type to store those digits. (We could just use + * type 'unsigned long', but that would be wasteful on a system where longs + * are 64-bits.) On Unix systems, the autoconf macro AC_TYPE_UINT32_T defines + * uint32_t to be such a type unless stdint.h or inttypes.h defines uint32_t. + * However, it doesn't set HAVE_UINT32_T, so we do that here. + */ +#if (defined UINT32_MAX || defined uint32_t) +#ifndef PY_UINT32_T +#define HAVE_UINT32_T 1 +#define PY_UINT32_T uint32_t +#endif +#endif + +/* Macros for a 64-bit unsigned integer type; used for type 'twodigits' in the + * long integer implementation, when 30-bit digits are enabled. + */ +#if (defined UINT64_MAX || defined uint64_t) +#ifndef PY_UINT64_T +#define HAVE_UINT64_T 1 +#define PY_UINT64_T uint64_t +#endif +#endif + +/* Signed variants of the above */ +#if (defined INT32_MAX || defined int32_t) +#ifndef PY_INT32_T +#define HAVE_INT32_T 1 +#define PY_INT32_T int32_t +#endif +#endif +#if (defined INT64_MAX || defined int64_t) +#ifndef PY_INT64_T +#define HAVE_INT64_T 1 +#define PY_INT64_T int64_t +#endif +#endif + +/* If PYLONG_BITS_IN_DIGIT is not defined then we'll use 30-bit digits if all + the necessary integer types are available, and we're on a 64-bit platform + (as determined by SIZEOF_VOID_P); otherwise we use 15-bit digits. */ + +#ifndef PYLONG_BITS_IN_DIGIT +#if (defined HAVE_UINT64_T && defined HAVE_INT64_T && \ + defined HAVE_UINT32_T && defined HAVE_INT32_T && SIZEOF_VOID_P >= 8) +#define PYLONG_BITS_IN_DIGIT 30 +#else +#define PYLONG_BITS_IN_DIGIT 15 +#endif +#endif + /* uintptr_t is the C9X name for an unsigned integral type such that a * legitimate void* can be cast to uintptr_t and then back to void* again * without loss of information. Similarly for intptr_t, wrt a signed Modified: python/trunk/Include/pythonrun.h ============================================================================== --- python/trunk/Include/pythonrun.h (original) +++ python/trunk/Include/pythonrun.h Fri Mar 20 16:51:55 2009 @@ -123,6 +123,7 @@ PyAPI_FUNC(void) _PyImportHooks_Init(void); PyAPI_FUNC(int) _PyFrame_Init(void); PyAPI_FUNC(int) _PyInt_Init(void); +PyAPI_FUNC(int) _PyLong_Init(void); PyAPI_FUNC(void) _PyFloat_Init(void); PyAPI_FUNC(int) PyByteArray_Init(void); Modified: python/trunk/Lib/test/test_long.py ============================================================================== --- python/trunk/Lib/test/test_long.py (original) +++ python/trunk/Lib/test/test_long.py Fri Mar 20 16:51:55 2009 @@ -15,7 +15,7 @@ return self.format % self.args # SHIFT should match the value in longintrepr.h for best testing. -SHIFT = 15 +SHIFT = sys.long_info.bits_per_digit BASE = 2 ** SHIFT MASK = BASE - 1 KARATSUBA_CUTOFF = 70 # from longobject.c @@ -143,6 +143,35 @@ y = self.getran(leny) or 1L self.check_division(x, y) + # specific numbers chosen to exercise corner cases of the + # current long division implementation + + # 30-bit cases involving a quotient digit estimate of BASE+1 + self.check_division(1231948412290879395966702881L, + 1147341367131428698L) + self.check_division(815427756481275430342312021515587883L, + 707270836069027745L) + self.check_division(627976073697012820849443363563599041L, + 643588798496057020L) + self.check_division(1115141373653752303710932756325578065L, + 1038556335171453937726882627L) + # 30-bit cases that require the post-subtraction correction step + self.check_division(922498905405436751940989320930368494L, + 949985870686786135626943396L) + self.check_division(768235853328091167204009652174031844L, + 1091555541180371554426545266L) + + # 15-bit cases involving a quotient digit estimate of BASE+1 + self.check_division(20172188947443L, 615611397L) + self.check_division(1020908530270155025L, 950795710L) + self.check_division(128589565723112408L, 736393718L) + self.check_division(609919780285761575L, 18613274546784L) + # 15-bit cases that require the post-subtraction correction step + self.check_division(710031681576388032L, 26769404391308L) + self.check_division(1933622614268221L, 30212853348836L) + + + def test_karatsuba(self): digits = range(1, 5) + range(KARATSUBA_CUTOFF, KARATSUBA_CUTOFF + 10) digits.extend([KARATSUBA_CUTOFF * 10, KARATSUBA_CUTOFF * 100]) Modified: python/trunk/Lib/test/test_sys.py ============================================================================== --- python/trunk/Lib/test/test_sys.py (original) +++ python/trunk/Lib/test/test_sys.py Fri Mar 20 16:51:55 2009 @@ -332,6 +332,9 @@ self.assert_(isinstance(sys.executable, basestring)) self.assertEqual(len(sys.float_info), 11) self.assertEqual(sys.float_info.radix, 2) + self.assertEqual(len(sys.long_info), 2) + self.assert_(sys.long_info.bits_per_digit % 5 == 0) + self.assert_(sys.long_info.sizeof_digit >= 1) self.assert_(isinstance(sys.hexversion, int)) self.assert_(isinstance(sys.maxint, int)) if test.test_support.have_unicode: @@ -417,6 +420,7 @@ if hasattr(sys, "gettotalrefcount"): self.header += '2P' self.vheader += '2P' + self.longdigit = sys.long_info.sizeof_digit import _testcapi self.gc_headsize = _testcapi.SIZEOF_PYGC_HEAD self.file = open(test.test_support.TESTFN, 'wb') @@ -594,11 +598,12 @@ check(reversed([]), size(h + 'lP')) # long check(0L, size(vh)) - check(1L, size(vh) + self.H) - check(-1L, size(vh) + self.H) - check(32768L, size(vh) + 2*self.H) - check(32768L*32768L-1, size(vh) + 2*self.H) - check(32768L*32768L, size(vh) + 3*self.H) + check(1L, size(vh) + self.longdigit) + check(-1L, size(vh) + self.longdigit) + PyLong_BASE = 2**sys.long_info.bits_per_digit + check(PyLong_BASE, size(vh) + 2*self.longdigit) + check(PyLong_BASE**2-1, size(vh) + 2*self.longdigit) + check(PyLong_BASE**2, size(vh) + 3*self.longdigit) # module check(unittest, size(h + 'P')) # None Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Fri Mar 20 16:51:55 2009 @@ -12,6 +12,13 @@ Core and Builtins ----------------- +- Issue #4258: Make it possible to use base 2**30 instead of base + 2**15 for the internal representation of integers, for performance + reasons. Base 2**30 is enabled by default on 64-bit machines. Add + --enable-big-digits option to configure, which overrides the + default. Add sys.long_info structseq to provide information about + the internal format. + - Issue #4034: Fix weird attribute error messages of the traceback object. (As a result traceback.__members__ no longer exists.) Modified: python/trunk/Objects/longobject.c ============================================================================== --- python/trunk/Objects/longobject.c (original) +++ python/trunk/Objects/longobject.c Fri Mar 20 16:51:55 2009 @@ -6,6 +6,7 @@ #include "Python.h" #include "longintrepr.h" +#include "structseq.h" #include #include @@ -3646,3 +3647,51 @@ long_new, /* tp_new */ PyObject_Del, /* tp_free */ }; + +static PyTypeObject Long_InfoType; + +PyDoc_STRVAR(long_info__doc__, +"sys.long_info\n\ +\n\ +A struct sequence that holds information about Python's\n\ +internal representation of integers. The attributes are read only."); + +static PyStructSequence_Field long_info_fields[] = { + {"bits_per_digit", "size of a digit in bits"}, + {"sizeof_digit", "size in bytes of the C type used to " + "represent a digit"}, + {NULL, NULL} +}; + +static PyStructSequence_Desc long_info_desc = { + "sys.long_info", /* name */ + long_info__doc__, /* doc */ + long_info_fields, /* fields */ + 2 /* number of fields */ +}; + +PyObject * +PyLong_GetInfo(void) +{ + PyObject* long_info; + int field = 0; + long_info = PyStructSequence_New(&Long_InfoType); + if (long_info == NULL) + return NULL; + PyStructSequence_SET_ITEM(long_info, field++, PyLong_FromLong(PyLong_SHIFT)); + PyStructSequence_SET_ITEM(long_info, field++, PyLong_FromLong(sizeof(digit))); + if (PyErr_Occurred()) { + Py_CLEAR(long_info); + return NULL; + } + return long_info; +} + +int +_PyLong_Init(void) +{ + /* initialize long_info */ + if (Long_InfoType.tp_name == 0) + PyStructSequence_InitType(&Long_InfoType, &long_info_desc); + return 1; +} Modified: python/trunk/PC/pyconfig.h ============================================================================== --- python/trunk/PC/pyconfig.h (original) +++ python/trunk/PC/pyconfig.h Fri Mar 20 16:51:55 2009 @@ -400,6 +400,42 @@ #endif +/* define signed and unsigned exact-width 32-bit and 64-bit types, used in the + implementation of Python long integers. */ +#ifndef PY_UINT32_T +#if SIZEOF_INT == 4 +#define HAVE_UINT32_T 1 +#define PY_UINT32_T unsigned int +#elif SIZEOF_LONG == 4 +#define HAVE_UINT32_T 1 +#define PY_UINT32_T unsigned long +#endif +#endif + +#ifndef PY_UINT64_T +#if SIZEOF_LONG_LONG == 8 +#define HAVE_UINT64_T 1 +#define PY_UINT64_T unsigned PY_LONG_LONG +#endif +#endif + +#ifndef PY_INT32_T +#if SIZEOF_INT == 4 +#define HAVE_INT32_T 1 +#define PY_INT32_T int +#elif SIZEOF_LONG == 4 +#define HAVE_INT32_T 1 +#define PY_INT32_T long +#endif +#endif + +#ifndef PY_INT64_T +#if SIZEOF_LONG_LONG == 8 +#define HAVE_INT64_T 1 +#define PY_INT64_T PY_LONG_LONG +#endif +#endif + /* Fairly standard from here! */ /* Define to 1 if you have the `copysign' function. */ Modified: python/trunk/Python/marshal.c ============================================================================== --- python/trunk/Python/marshal.c (original) +++ python/trunk/Python/marshal.c Fri Mar 20 16:51:55 2009 @@ -11,6 +11,8 @@ #include "code.h" #include "marshal.h" +#define ABS(x) ((x) < 0 ? -(x) : (x)) + /* High water mark to determine when the marshalled object is dangerously deep * and risks coring the interpreter. When the object stack gets this deep, * raise an exception instead of continuing. @@ -119,6 +121,56 @@ } #endif +/* We assume that Python longs are stored internally in base some power of + 2**15; for the sake of portability we'll always read and write them in base + exactly 2**15. */ + +#define PyLong_MARSHAL_SHIFT 15 +#define PyLong_MARSHAL_BASE ((short)1 << PyLong_MARSHAL_SHIFT) +#define PyLong_MARSHAL_MASK (PyLong_MARSHAL_BASE - 1) +#if PyLong_SHIFT % PyLong_MARSHAL_SHIFT != 0 +#error "PyLong_SHIFT must be a multiple of PyLong_MARSHAL_SHIFT" +#endif +#define PyLong_MARSHAL_RATIO (PyLong_SHIFT / PyLong_MARSHAL_SHIFT) + +static void +w_PyLong(const PyLongObject *ob, WFILE *p) +{ + Py_ssize_t i, j, n, l; + digit d; + + w_byte(TYPE_LONG, p); + if (Py_SIZE(ob) == 0) { + w_long((long)0, p); + return; + } + + /* set l to number of base PyLong_MARSHAL_BASE digits */ + n = ABS(Py_SIZE(ob)); + l = (n-1) * PyLong_MARSHAL_RATIO; + d = ob->ob_digit[n-1]; + assert(d != 0); /* a PyLong is always normalized */ + do { + d >>= PyLong_MARSHAL_SHIFT; + l++; + } while (d != 0); + w_long((long)(Py_SIZE(ob) > 0 ? l : -l), p); + + for (i=0; i < n-1; i++) { + d = ob->ob_digit[i]; + for (j=0; j < PyLong_MARSHAL_RATIO; j++) { + w_short(d & PyLong_MARSHAL_MASK, p); + d >>= PyLong_MARSHAL_SHIFT; + } + assert (d == 0); + } + d = ob->ob_digit[n-1]; + do { + w_short(d & PyLong_MARSHAL_MASK, p); + d >>= PyLong_MARSHAL_SHIFT; + } while (d != 0); +} + static void w_object(PyObject *v, WFILE *p) { @@ -164,13 +216,7 @@ } else if (PyLong_CheckExact(v)) { PyLongObject *ob = (PyLongObject *)v; - w_byte(TYPE_LONG, p); - n = ob->ob_size; - w_long((long)n, p); - if (n < 0) - n = -n; - for (i = 0; i < n; i++) - w_short(ob->ob_digit[i], p); + w_PyLong(ob, p); } else if (PyFloat_CheckExact(v)) { if (p->version > 1) { @@ -507,6 +553,56 @@ } static PyObject * +r_PyLong(RFILE *p) +{ + PyLongObject *ob; + int size, i, j, md; + long n; + digit d; + + n = r_long(p); + if (n == 0) + return (PyObject *)_PyLong_New(0); + if (n < -INT_MAX || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, + "bad marshal data (long size out of range)"); + return NULL; + } + + size = 1 + (ABS(n)-1) / PyLong_MARSHAL_RATIO; + ob = _PyLong_New(size); + if (ob == NULL) + return NULL; + Py_SIZE(ob) = n > 0 ? size : -size; + + for (i = 0; i < size-1; i++) { + d = 0; + for (j=0; j < PyLong_MARSHAL_RATIO; j++) { + md = r_short(p); + if (md < 0 || md > PyLong_MARSHAL_BASE) + goto bad_digit; + d += (digit)md << j*PyLong_MARSHAL_SHIFT; + } + ob->ob_digit[i] = d; + } + d = 0; + for (j=0; j < (ABS(n)-1)%PyLong_MARSHAL_RATIO + 1; j++) { + md = r_short(p); + if (md < 0 || md > PyLong_MARSHAL_BASE) + goto bad_digit; + d += (digit)md << j*PyLong_MARSHAL_SHIFT; + } + ob->ob_digit[size-1] = d; + return (PyObject *)ob; + bad_digit: + Py_DECREF(ob); + PyErr_SetString(PyExc_ValueError, + "bad marshal data (digit out of range in long)"); + return NULL; +} + + +static PyObject * r_object(RFILE *p) { /* NULL is a valid return value, it does not necessarily means that @@ -570,38 +666,8 @@ break; case TYPE_LONG: - { - int size; - PyLongObject *ob; - n = r_long(p); - if (n < -INT_MAX || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, - "bad marshal data (long size out of range)"); - retval = NULL; - break; - } - size = n<0 ? -n : n; - ob = _PyLong_New(size); - if (ob == NULL) { - retval = NULL; - break; - } - ob->ob_size = n; - for (i = 0; i < size; i++) { - int digit = r_short(p); - if (digit < 0) { - Py_DECREF(ob); - PyErr_SetString(PyExc_ValueError, - "bad marshal data (negative digit in long)"); - ob = NULL; - break; - } - if (ob != NULL) - ob->ob_digit[i] = digit; - } - retval = (PyObject *)ob; - break; - } + retval = r_PyLong(p); + break; case TYPE_FLOAT: { Modified: python/trunk/Python/pythonrun.c ============================================================================== --- python/trunk/Python/pythonrun.c (original) +++ python/trunk/Python/pythonrun.c Fri Mar 20 16:51:55 2009 @@ -182,6 +182,9 @@ if (!_PyInt_Init()) Py_FatalError("Py_Initialize: can't init ints"); + if (!_PyLong_Init()) + Py_FatalError("Py_Initialize: can't init longs"); + if (!PyByteArray_Init()) Py_FatalError("Py_Initialize: can't init bytearray"); Modified: python/trunk/Python/sysmodule.c ============================================================================== --- python/trunk/Python/sysmodule.c (original) +++ python/trunk/Python/sysmodule.c Fri Mar 20 16:51:55 2009 @@ -1043,6 +1043,8 @@ "\n\ Static objects:\n\ \n\ +float_info -- a dict with information about the float inplementation.\n\ +long_info -- a struct sequence with information about the long implementation.\n\ maxint -- the largest supported integer (the smallest is -maxint-1)\n\ maxsize -- the largest supported length of containers.\n\ maxunicode -- the largest supported character\n\ @@ -1443,6 +1445,8 @@ PyBool_FromLong(Py_Py3kWarningFlag)); SET_SYS_FROM_STRING("float_info", PyFloat_GetInfo()); + SET_SYS_FROM_STRING("long_info", + PyLong_GetInfo()); #ifdef Py_USING_UNICODE SET_SYS_FROM_STRING("maxunicode", PyInt_FromLong(PyUnicode_GetMax())); Modified: python/trunk/configure ============================================================================== --- python/trunk/configure (original) +++ python/trunk/configure Fri Mar 20 16:51:55 2009 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 68299 . +# From configure.in Revision: 68312 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 2.7. # @@ -1324,6 +1324,8 @@ --enable-toolbox-glue disable/enable MacOSX glue code for extensions --enable-ipv6 Enable ipv6 (with ipv4) support --disable-ipv6 Disable ipv6 support + --enable-big-digits[=BITS] + use big digits for Python longs [BITS=30] --enable-unicode[=ucs[24]] Enable Unicode strings (default is yes) @@ -7018,6 +7020,386 @@ fi + + { echo "$as_me:$LINENO: checking for uint32_t" >&5 +echo $ECHO_N "checking for uint32_t... $ECHO_C" >&6; } +if test "${ac_cv_c_uint32_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_uint32_t=no + for ac_type in 'uint32_t' 'unsigned int' 'unsigned long int' \ + 'unsigned long long int' 'unsigned short int' 'unsigned char'; 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 * !(($ac_type) -1 >> (32 - 1) == 1)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + case $ac_type in + uint32_t) ac_cv_c_uint32_t=yes ;; + *) ac_cv_c_uint32_t=$ac_type ;; +esac + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_uint32_t" != no && break + done +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_uint32_t" >&5 +echo "${ECHO_T}$ac_cv_c_uint32_t" >&6; } + case $ac_cv_c_uint32_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<\_ACEOF +#define _UINT32_T 1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define uint32_t $ac_cv_c_uint32_t +_ACEOF +;; + esac + + + { echo "$as_me:$LINENO: checking for uint64_t" >&5 +echo $ECHO_N "checking for uint64_t... $ECHO_C" >&6; } +if test "${ac_cv_c_uint64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_uint64_t=no + for ac_type in 'uint64_t' 'unsigned int' 'unsigned long int' \ + 'unsigned long long int' 'unsigned short int' 'unsigned char'; 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 * !(($ac_type) -1 >> (64 - 1) == 1)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + case $ac_type in + uint64_t) ac_cv_c_uint64_t=yes ;; + *) ac_cv_c_uint64_t=$ac_type ;; +esac + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_uint64_t" != no && break + done +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_uint64_t" >&5 +echo "${ECHO_T}$ac_cv_c_uint64_t" >&6; } + case $ac_cv_c_uint64_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<\_ACEOF +#define _UINT64_T 1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define uint64_t $ac_cv_c_uint64_t +_ACEOF +;; + esac + + + { echo "$as_me:$LINENO: checking for int32_t" >&5 +echo $ECHO_N "checking for int32_t... $ECHO_C" >&6; } +if test "${ac_cv_c_int32_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_int32_t=no + for ac_type in 'int32_t' 'int' 'long int' \ + 'long long int' 'short int' 'signed char'; 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 * !(0 < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1))]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + 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 * !(($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1) + < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 2))]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + case $ac_type in + int32_t) ac_cv_c_int32_t=yes ;; + *) ac_cv_c_int32_t=$ac_type ;; +esac + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_int32_t" != no && break + done +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_int32_t" >&5 +echo "${ECHO_T}$ac_cv_c_int32_t" >&6; } + case $ac_cv_c_int32_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int32_t $ac_cv_c_int32_t +_ACEOF +;; + esac + + + { echo "$as_me:$LINENO: checking for int64_t" >&5 +echo $ECHO_N "checking for int64_t... $ECHO_C" >&6; } +if test "${ac_cv_c_int64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_int64_t=no + for ac_type in 'int64_t' 'int' 'long int' \ + 'long long int' 'short int' 'signed char'; 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 * !(0 < ($ac_type) (((($ac_type) 1 << (64 - 2)) - 1) * 2 + 1))]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + 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 * !(($ac_type) (((($ac_type) 1 << (64 - 2)) - 1) * 2 + 1) + < ($ac_type) (((($ac_type) 1 << (64 - 2)) - 1) * 2 + 2))]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + case $ac_type in + int64_t) ac_cv_c_int64_t=yes ;; + *) ac_cv_c_int64_t=$ac_type ;; +esac + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_int64_t" != no && break + done +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_int64_t" >&5 +echo "${ECHO_T}$ac_cv_c_int64_t" >&6; } + case $ac_cv_c_int64_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int64_t $ac_cv_c_int64_t +_ACEOF +;; + esac + { echo "$as_me:$LINENO: checking for ssize_t" >&5 echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6; } if test "${ac_cv_type_ssize_t+set}" = set; then @@ -21994,6 +22376,37 @@ LIBS=$LIBS_SAVE +# determine what size digit to use for Python's longs +{ echo "$as_me:$LINENO: checking digit size for Python's longs" >&5 +echo $ECHO_N "checking digit size for Python's longs... $ECHO_C" >&6; } +# Check whether --enable-big-digits was given. +if test "${enable_big_digits+set}" = set; then + enableval=$enable_big_digits; case $enable_big_digits in +yes) + enable_big_digits=30 ;; +no) + enable_big_digits=15 ;; +15|30) + ;; +*) + { { echo "$as_me:$LINENO: error: bad value $enable_big_digits for --enable-big-digits; value should be 15 or 30" >&5 +echo "$as_me: error: bad value $enable_big_digits for --enable-big-digits; value should be 15 or 30" >&2;} + { (exit 1); exit 1; }; } ;; +esac +{ echo "$as_me:$LINENO: result: $enable_big_digits" >&5 +echo "${ECHO_T}$enable_big_digits" >&6; } + +cat >>confdefs.h <<_ACEOF +#define PYLONG_BITS_IN_DIGIT $enable_big_digits +_ACEOF + + +else + { echo "$as_me:$LINENO: result: no value specified" >&5 +echo "${ECHO_T}no value specified" >&6; } +fi + + # check for wchar.h if test "${ac_cv_header_wchar_h+set}" = set; then { echo "$as_me:$LINENO: checking for wchar.h" >&5 Modified: python/trunk/configure.in ============================================================================== --- python/trunk/configure.in (original) +++ python/trunk/configure.in Fri Mar 20 16:51:55 2009 @@ -1333,6 +1333,10 @@ AC_TYPE_SIGNAL AC_TYPE_SIZE_T AC_TYPE_UID_T +AC_TYPE_UINT32_T +AC_TYPE_UINT64_T +AC_TYPE_INT32_T +AC_TYPE_INT64_T AC_CHECK_TYPE(ssize_t, AC_DEFINE(HAVE_SSIZE_T, 1, Define if your compiler provides ssize_t),,) @@ -3212,6 +3216,25 @@ LIBS=$LIBS_SAVE +# determine what size digit to use for Python's longs +AC_MSG_CHECKING([digit size for Python's longs]) +AC_ARG_ENABLE(big-digits, +AC_HELP_STRING([--enable-big-digits@<:@=BITS@:>@],[use big digits for Python longs [[BITS=30]]]), +[case $enable_big_digits in +yes) + enable_big_digits=30 ;; +no) + enable_big_digits=15 ;; +[15|30]) + ;; +*) + AC_MSG_ERROR([bad value $enable_big_digits for --enable-big-digits; value should be 15 or 30]) ;; +esac +AC_MSG_RESULT($enable_big_digits) +AC_DEFINE_UNQUOTED(PYLONG_BITS_IN_DIGIT, $enable_big_digits, [Define as the preferred size in bits of long digits]) +], +[AC_MSG_RESULT(no value specified)]) + # check for wchar.h AC_CHECK_HEADER(wchar.h, [ AC_DEFINE(HAVE_WCHAR_H, 1, Modified: python/trunk/pyconfig.h.in ============================================================================== --- python/trunk/pyconfig.h.in (original) +++ python/trunk/pyconfig.h.in Fri Mar 20 16:51:55 2009 @@ -848,6 +848,9 @@ /* Defined if PTHREAD_SCOPE_SYSTEM supported. */ #undef PTHREAD_SYSTEM_SCHED_SUPPORTED +/* Define as the preferred size in bits of long digits */ +#undef PYLONG_BITS_IN_DIGIT + /* Define to printf format modifier for Py_ssize_t */ #undef PY_FORMAT_SIZE_T @@ -1032,6 +1035,16 @@ /* Define to force use of thread-safe errno, h_errno, and other functions */ #undef _REENTRANT +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef was allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef was allowed, the + #define below would cause a syntax error. */ +#undef _UINT64_T + /* Define to the level of X/Open that your system supports */ #undef _XOPEN_SOURCE @@ -1058,6 +1071,14 @@ /* Define to `int' if doesn't define. */ #undef gid_t +/* Define to the type of a signed integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef int32_t + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef int64_t + /* Define to `int' if does not define. */ #undef mode_t @@ -1079,6 +1100,14 @@ /* Define to `int' if doesn't define. */ #undef uid_t +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef uint64_t + /* Define to empty if the keyword does not work. */ #undef volatile From python-checkins at python.org Fri Mar 20 16:53:29 2009 From: python-checkins at python.org (mark.dickinson) Date: Fri, 20 Mar 2009 16:53:29 +0100 (CET) Subject: [Python-checkins] r70480 - python/branches/py3k Message-ID: <20090320155329.AE02D1E401C@bag.python.org> Author: mark.dickinson Date: Fri Mar 20 16:53:29 2009 New Revision: 70480 Log: Blocked revisions 70479 via svnmerge ........ r70479 | mark.dickinson | 2009-03-20 15:51:55 +0000 (Fri, 20 Mar 2009) | 3 lines Issue #4258: Use 30-bit digits for Python longs, on 64-bit platforms. Backport of r70459. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Fri Mar 20 16:56:53 2009 From: python-checkins at python.org (mark.dickinson) Date: Fri, 20 Mar 2009 16:56:53 +0100 (CET) Subject: [Python-checkins] r70481 - python/branches/release26-maint Message-ID: <20090320155653.E60541E4010@bag.python.org> Author: mark.dickinson Date: Fri Mar 20 16:56:53 2009 New Revision: 70481 Log: Blocked revisions 70479 via svnmerge ........ r70479 | mark.dickinson | 2009-03-20 15:51:55 +0000 (Fri, 20 Mar 2009) | 3 lines Issue #4258: Use 30-bit digits for Python longs, on 64-bit platforms. Backport of r70459. ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Fri Mar 20 17:00:50 2009 From: python-checkins at python.org (mark.dickinson) Date: Fri, 20 Mar 2009 17:00:50 +0100 (CET) Subject: [Python-checkins] r70482 - in python/branches/py3k: Doc/library/sys.rst Doc/whatsnew/2.7.rst Include/longintrepr.h Message-ID: <20090320160050.024581E402B@bag.python.org> Author: mark.dickinson Date: Fri Mar 20 17:00:49 2009 New Revision: 70482 Log: Add ..versionadded for sys.int_info, update py3k version of whatsnew/2.7.rst to keep it in sync with the trunk version, and replace SHIFT with PyLong_SHIFT in #error message Modified: python/branches/py3k/Doc/library/sys.rst python/branches/py3k/Doc/whatsnew/2.7.rst python/branches/py3k/Include/longintrepr.h Modified: python/branches/py3k/Doc/library/sys.rst ============================================================================== --- python/branches/py3k/Doc/library/sys.rst (original) +++ python/branches/py3k/Doc/library/sys.rst Fri Mar 20 17:00:49 2009 @@ -429,6 +429,8 @@ | | represent a digit | +-------------------------+----------------------------------------------+ + .. versionadded:: 3.1 + .. function:: intern(string) Modified: python/branches/py3k/Doc/whatsnew/2.7.rst ============================================================================== --- python/branches/py3k/Doc/whatsnew/2.7.rst (original) +++ python/branches/py3k/Doc/whatsnew/2.7.rst Fri Mar 20 17:00:49 2009 @@ -86,6 +86,30 @@ (Contributed by Fredrik Johansson and Victor Stinner; :issue:`3439`.) +* Integers are now stored internally either in base 2**15 or in base + 2**30, the base being determined at build time. Previously, they + were always stored in base 2**15. Using base 2**30 gives + significant performance improvements on 64-bit machines, but + benchmark results on 32-bit machines have been mixed. Therefore, + the default is to use base 2**30 on 64-bit machines and base 2**15 + on 32-bit machines; on Unix, there's a new configure option + --enable-big-digits that can be used to override this default. + + Apart from the performance improvements this change should be + invisible to end users, with one exception: for testing and + debugging purposes there's a new structseq ``sys.long_info`` that + provides information about the internal format, giving the number of + bits per digit and the size in bytes of the C type used to store + each digit:: + + >>> import sys + >>> sys.long_info + sys.long_info(bits_per_digit=30, sizeof_digit=4) + + + (Contributed by Mark Dickinson; :issue:`4258`.) + + .. ====================================================================== Modified: python/branches/py3k/Include/longintrepr.h ============================================================================== --- python/branches/py3k/Include/longintrepr.h (original) +++ python/branches/py3k/Include/longintrepr.h Fri Mar 20 17:00:49 2009 @@ -67,7 +67,7 @@ #define PyLong_MASK ((digit)(PyLong_BASE - 1)) #if PyLong_SHIFT % 5 != 0 -#error "longobject.c requires that SHIFT be divisible by 5" +#error "longobject.c requires that PyLong_SHIFT be divisible by 5" #endif /* Long integer representation. From python-checkins at python.org Fri Mar 20 17:01:41 2009 From: python-checkins at python.org (mark.dickinson) Date: Fri, 20 Mar 2009 17:01:41 +0100 (CET) Subject: [Python-checkins] r70483 - python/branches/release30-maint Message-ID: <20090320160141.C3AC41E4002@bag.python.org> Author: mark.dickinson Date: Fri Mar 20 17:01:41 2009 New Revision: 70483 Log: Blocked revisions 70482 via svnmerge ........ r70482 | mark.dickinson | 2009-03-20 16:00:49 +0000 (Fri, 20 Mar 2009) | 4 lines Add ..versionadded for sys.int_info, update py3k version of whatsnew/2.7.rst to keep it in sync with the trunk version, and replace SHIFT with PyLong_SHIFT in #error message ........ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Fri Mar 20 17:37:59 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 20 Mar 2009 16:37:59 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090320163759.A1F8B1E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/255 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Fri Mar 20 18:09:04 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 20 Mar 2009 17:09:04 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090320170904.772201E4060@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/493 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Fri Mar 20 18:36:13 2009 From: python-checkins at python.org (brett.cannon) Date: Fri, 20 Mar 2009 18:36:13 +0100 (CET) Subject: [Python-checkins] r70484 - in peps/trunk: pep-0284.txt pep-0335.txt pep-0380.txt Message-ID: <20090320173613.575CB1E4002@bag.python.org> Author: brett.cannon Date: Fri Mar 20 18:36:09 2009 New Revision: 70484 Log: Add PEP 380: Syntax for Delegating to a Subgenerator. Also updated Greg's email address in other PEPs. Added: peps/trunk/pep-0380.txt Modified: peps/trunk/pep-0284.txt peps/trunk/pep-0335.txt Modified: peps/trunk/pep-0284.txt ============================================================================== --- peps/trunk/pep-0284.txt (original) +++ peps/trunk/pep-0284.txt Fri Mar 20 18:36:09 2009 @@ -2,8 +2,8 @@ Title: Integer for-loops Version: $Revision$ Last-Modified: $Date$ -Author: eppstein at ics.uci.edu (David Eppstein), - greg at cosc.canterbury.ac.nz (Gregory Ewing) +Author: David Eppstein , + Greg Ewing Status: Rejected Type: Standards Track Created: 1-Mar-2002 Modified: peps/trunk/pep-0335.txt ============================================================================== --- peps/trunk/pep-0335.txt (original) +++ peps/trunk/pep-0335.txt Fri Mar 20 18:36:09 2009 @@ -2,7 +2,7 @@ Title: Overloadable Boolean Operators Version: $Revision$ Last-Modified: $Date$ -Author: Gregory Ewing +Author: Greg Ewing Status: Draft Type: Standards Track Content-Type: text/x-rst Added: peps/trunk/pep-0380.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-0380.txt Fri Mar 20 18:36:09 2009 @@ -0,0 +1,347 @@ +PEP: 380 +Title: Syntax for Delegating to a Subgenerator +Version: $Revision$ +Last-Modified: $Date$ +Author: Gregory Ewing +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 13-Feb-2009 +Python-Version: 2.7 +Post-History: + + +Abstract +======== + +A syntax is proposed for a generator to delegate part of its +operations to another generator. This allows a section of code +containing 'yield' to be factored out and placed in another +generator. Additionally, the subgenerator is allowed to return with a +value, and the value is made available to the delegating generator. + +The new syntax also opens up some opportunities for optimisation when +one generator re-yields values produced by another. + + +Proposal +======== + +The following new expression syntax will be allowed in the body of a +generator: + +:: + + yield from + +where is an expression evaluating to an iterable, from which an +iterator is extracted. The iterator is run to exhaustion, during which +time it yields and receives values directly to or from the caller of +the generator containing the ``yield from`` expression (the +"delegating generator"). + +When the iterator is another generator, the effect is the same as if +the body of the subgenerator were inlined at the point of the ``yield +from`` expression. Furthermore, the subgenerator is allowed to execute +a ``return`` statement with a value, and that value becomes the value of +the ``yield from`` expression. + +In general, the semantics can be understood in terms of the iterator +protocol as follows: + + * Any values that the iterator yields are passed directly to the + caller. + + * Any values sent to the delegating generator using ``send()`` + are passed directly to the iterator. If the sent value is None, + the iterator's ``next()`` method is called. If the sent value is + not None, the iterator's ``send()`` method is called. Any exception + resulting from attempting to call ``next`` or ``send`` is raised + in the delegating generator. + + * Calls to the ``throw()`` method of the delegating generator are + forwarded to the iterator. If the iterator does not have a + ``throw()`` method, the thrown-in exception is raised in the + delegating generator. + + * If the delegating generator's ``close()`` method is called, the + ``close() method of the iterator is called first if it has one, + then the delegating generator is finalised. + + * The value of the ``yield from`` expression is the first argument + to the ``StopIteration`` exception raised by the iterator when it + terminates. + + * ``return expr`` in a generator causes ``StopIteration(expr)`` to + be raised. + +For convenience, the ``StopIteration`` exception will be given a +``value`` attribute that holds its first argument, or None if there +are no arguments. + + +Formal Semantics +---------------- + +1. The statement + +:: + + result = yield from expr + +is semantically equivalent to + +:: + + _i = iter(expr) + try: + _u = _i.next() + while 1: + try: + _v = yield _u + except Exception, _e: + _m = getattr(_i, 'throw', None) + if _m is not None: + _u = _m(_e) + else: + raise + else: + if _v is None: + _u = _i.next() + else: + _u = _i.send(_v) + except StopIteration, _e: + result = _e.value + finally: + _m = getattr(_i, 'close', None) + if _m is not None: + _m() + +except that implementations are free to cache bound methods for the 'next', +'send', 'throw' and 'close' methods of the iterator. + +2. In a generator, the statement + +:: + + return value + +is semantically equivalent to + +:: + + raise StopIteration(value) + +except that, as currently, the exception cannot be caught by ``except`` +clauses within the returning generator. + +3. The StopIteration exception behaves as though defined thusly: + +:: + + class StopIteration(Exception): + + def __init__(self, *args): + if len(args) > 0: + self.value = args[0] + else: + self.value = None + Exception.__init__(self, *args) + + +Rationale +========= + +A Python generator is a form of coroutine, but has the limitation that +it can only yield to its immediate caller. This means that a piece of +code containing a ``yield`` cannot be factored out and put into a +separate function in the same way as other code. Performing such a +factoring causes the called function to itself become a generator, and +it is necessary to explicitly iterate over this second generator and +re-yield any values that it produces. + +If yielding of values is the only concern, this is not very arduous +and can be performed with a loop such as + +:: + + for v in g: + yield v + +However, if the subgenerator is to interact properly with the caller +in the case of calls to ``send()``, ``throw()`` and ``close()``, things +become considerably more complicated. As the formal expansion presented +above illustrates, the necessary code is very longwinded, and it is tricky +to handle all the corner cases correctly. In this situation, the advantages +of a specialised syntax should be clear. + + +Generators as Threads +--------------------- + +A motivating use case for generators being able to return values +concerns the use of generators to implement lightweight threads. When +using generators in that way, it is reasonable to want to spread the +computation performed by the lightweight thread over many functions. +One would like to be able to call a subgenerator as though it were +an ordinary function, passing it parameters and receiving a returned +value. + +Using the proposed syntax, a statement such as + +:: + + y = f(x) + +where f is an ordinary function, can be transformed into a delegation +call + +:: + + y = yield from g(x) + +where g is a generator. One can reason about the behaviour of the +resulting code by thinking of g as an ordinary function that can be +suspended using a ``yield`` statement. + +When using generators as threads in this way, typically one is not +interested in the values being passed in or out of the yields. +However, there are use cases for this as well, where the thread is +seen as a producer or consumer of items. The ``yield from`` +expression allows the logic of the thread to be spread over as +many functions as desired, with the production or consumption of +items occuring in any subfunction, and the items are automatically +routed to or from their ultimate source or destination. + +Concerning ``throw()`` and ``close()``, it is reasonable to expect +that if an exception is thrown into the thread from outside, it should +first be raised in the innermost generator where the thread is suspended, +and propagate outwards from there; and that if the thread is terminated +from outside by calling ``close()``, the chain of active generators +should be finalised from the innermost outwards. + + +Syntax +------ + +The particular syntax proposed has been chosen as suggestive of its +meaning, while not introducing any new keywords and clearly standing +out as being different from a plain ``yield``. + + +Optimisations +------------- + +Using a specialised syntax opens up possibilities for optimisation +when there is a long chain of generators. Such chains can arise, for +instance, when recursively traversing a tree structure. The overhead +of passing ``next()`` calls and yielded values down and up the chain +can cause what ought to be an O(n) operation to become O(n\*\*2). + +A possible strategy is to add a slot to generator objects to hold a +generator being delegated to. When a ``next()`` or ``send()`` call is +made on the generator, this slot is checked first, and if it is +nonempty, the generator that it references is resumed instead. If it +raises StopIteration, the slot is cleared and the main generator is +resumed. + +This would reduce the delegation overhead to a chain of C function +calls involving no Python code execution. A possible enhancement would +be to traverse the whole chain of generators in a loop and directly +resume the one at the end, although the handling of StopIteration is +more complicated then. + + +Use of StopIteration to return values +------------------------------------- + +There are a variety of ways that the return value from the generator +could be passed back. Some alternatives include storing it as an +attribute of the generator-iterator object, or returning it as the +value of the ``close()`` call to the subgenerator. However, the proposed +mechanism is attractive for a couple of reasons: + +* Using the StopIteration exception makes it easy for other kinds + of iterators to participate in the protocol without having to + grow extra attributes or a close() method. + +* It simplifies the implementation, because the point at which the + return value from the subgenerator becomes available is the same + point at which StopIteration is raised. Delaying until any later + time would require storing the return value somewhere. + + +Criticisms +========== + +Under this proposal, the value of a ``yield from`` expression would +be derived in a very different way from that of an ordinary ``yield`` +expression. This suggests that some other syntax not containing the +word ``yield`` might be more appropriate, but no acceptable alternative +has so far been proposed. + +It has been suggested that some mechanism other than ``return`` in +the subgenerator should be used to establish the value returned by +the ``yield from`` expression. However, this would interfere with +the goal of being able to think of the subgenerator as a suspendable +function, since it would not be able to return values in the same way +as other functions. + +The use of an argument to StopIteration to pass the return value +has been criticised as an "abuse of exceptions", without any +concrete justification of this claim. In any case, this is only +one suggested implementation; another mechanism could be used +without losing any essential features of the proposal. + +It has been suggested that a different exception, such as +GeneratorReturn, should be used instead of StopIteration to return a +value. However, no convincing practical reason for this has been put +forward, and the addition of a ``value`` attribute to StopIteration +mitigates any difficulties in extracting a return value from a +StopIteration exception that may or may not have one. Also, using a +different exception would mean that, unlike ordinary functions, +'return' without a value in a generator would not be equivalent to +'return None'. + + +Alternative Proposals +===================== + +Proposals along similar lines have been made before, some using the +syntax ``yield *`` instead of ``yield from``. While ``yield *`` is +more concise, it could be argued that it looks too similar to an +ordinary ``yield`` and the difference might be overlooked when reading +code. + +To the author's knowledge, previous proposals have focused only on +yielding values, and thereby suffered from the criticism that the +two-line for-loop they replace is not sufficiently tiresome to write +to justify a new syntax. By also dealing with calls to ``send()``, +``throw()`` and ``close()``, this proposal provides considerably more +benefit. + + +Implementation +============== + +A `prototype implementation`_ is available, based on the first +optimisation outlined above. + +.. _prototype implementation: http://www.cosc.canterbury.ac.nz/greg.ewing/python/yield-from/ + + +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 Fri Mar 20 18:36:14 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 20 Mar 2009 17:36:14 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090320173615.398821E4020@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/181 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/test/test_ftplib.py", line 203, in run asyncore.loop(timeout=0.1, count=1) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 204, in loop poll_fun(timeout, map) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 141, in poll read(obj) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 78, in read obj.handle_error() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 74, in read obj.handle_read_event() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 413, in handle_read_event self.handle_read() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/test/test_ssl.py", line 408, in handle_read self.send(data.lower()) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 519, in send self.initiate_send() File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 506, in initiate_send num_sent = dispatcher.send(self, self.out_buffer[:512]) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/asyncore.py", line 349, in send result = self.socket.send(data) File "/Users/buildbot/buildarea/2.6.heller-x86-osx5/build/Lib/socket.py", line 165, in _dummy raise error(EBADF, 'Bad file descriptor') error: [Errno 9] Bad file descriptor 1 test failed: test_ftplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Fri Mar 20 18:40:13 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 20 Mar 2009 17:40:13 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090320174014.121F81E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/216 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_distutils test_posix ====================================================================== FAIL: test_get_python_inc (distutils.tests.test_sysconfig.SysconfigTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/distutils/tests/test_sysconfig.py", line 45, in test_get_python_inc self.assert_(os.path.isdir(inc_dir), inc_dir) AssertionError: /home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/Include ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From python-checkins at python.org Fri Mar 20 19:25:49 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 20 Mar 2009 19:25:49 +0100 (CET) Subject: [Python-checkins] r70485 - python/trunk/Doc/library/collections.rst Message-ID: <20090320182549.DF9BE1E4057@bag.python.org> Author: raymond.hettinger Date: Fri Mar 20 19:25:49 2009 New Revision: 70485 Log: Add MutableSet example. Modified: python/trunk/Doc/library/collections.rst Modified: python/trunk/Doc/library/collections.rst ============================================================================== --- python/trunk/Doc/library/collections.rst (original) +++ python/trunk/Doc/library/collections.rst Fri Mar 20 19:25:49 2009 @@ -147,7 +147,12 @@ inherit from both :meth:`Set` and :meth:`Hashable`, then define ``__hash__ = Set._hash``. -(For more about ABCs, see the :mod:`abc` module and :pep:`3119`.) +.. seealso:: + + * `OrderedSet recipe `_ for an + example built on :class:`MutableSet`. + + * For more about ABCs, see the :mod:`abc` module and :pep:`3119`. :class:`Counter` objects From python-checkins at python.org Fri Mar 20 19:30:29 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 20 Mar 2009 19:30:29 +0100 (CET) Subject: [Python-checkins] r70486 - python/branches/release26-maint/Doc/library/collections.rst Message-ID: <20090320183029.BFE2B1E403A@bag.python.org> Author: raymond.hettinger Date: Fri Mar 20 19:30:29 2009 New Revision: 70486 Log: Add MutableSet example. Modified: python/branches/release26-maint/Doc/library/collections.rst Modified: python/branches/release26-maint/Doc/library/collections.rst ============================================================================== --- python/branches/release26-maint/Doc/library/collections.rst (original) +++ python/branches/release26-maint/Doc/library/collections.rst Fri Mar 20 19:30:29 2009 @@ -147,8 +147,12 @@ inherit from both :meth:`Set` and :meth:`Hashable`, then define ``__hash__ = Set._hash``. -(For more about ABCs, see the :mod:`abc` module and :pep:`3119`.) +.. seealso:: + + * `OrderedSet recipe `_ for an + example built on :class:`MutableSet`. + * For more about ABCs, see the :mod:`abc` module and :pep:`3119`. .. _deque-objects: From python-checkins at python.org Fri Mar 20 19:31:58 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 20 Mar 2009 19:31:58 +0100 (CET) Subject: [Python-checkins] r70487 - python/branches/release30-maint/Doc/library/collections.rst Message-ID: <20090320183158.EA74C1E4002@bag.python.org> Author: raymond.hettinger Date: Fri Mar 20 19:31:58 2009 New Revision: 70487 Log: Add MutableSet example. Modified: python/branches/release30-maint/Doc/library/collections.rst Modified: python/branches/release30-maint/Doc/library/collections.rst ============================================================================== --- python/branches/release30-maint/Doc/library/collections.rst (original) +++ python/branches/release30-maint/Doc/library/collections.rst Fri Mar 20 19:31:58 2009 @@ -135,7 +135,12 @@ inherit from both :meth:`Set` and :meth:`Hashable`, then define ``__hash__ = Set._hash``. -(For more about ABCs, see the :mod:`abc` module and :pep:`3119`.) +.. seealso:: + + * `OrderedSet recipe `_ for an + example built on :class:`MutableSet`. + + * For more about ABCs, see the :mod:`abc` module and :pep:`3119`. .. _deque-objects: From python-checkins at python.org Fri Mar 20 19:33:06 2009 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 20 Mar 2009 19:33:06 +0100 (CET) Subject: [Python-checkins] r70488 - python/branches/py3k/Doc/library/collections.rst Message-ID: <20090320183306.7AE5E1E4022@bag.python.org> Author: raymond.hettinger Date: Fri Mar 20 19:33:06 2009 New Revision: 70488 Log: Add MutableSet example. Modified: python/branches/py3k/Doc/library/collections.rst Modified: python/branches/py3k/Doc/library/collections.rst ============================================================================== --- python/branches/py3k/Doc/library/collections.rst (original) +++ python/branches/py3k/Doc/library/collections.rst Fri Mar 20 19:33:06 2009 @@ -132,7 +132,12 @@ inherit from both :meth:`Set` and :meth:`Hashable`, then define ``__hash__ = Set._hash``. -(For more about ABCs, see the :mod:`abc` module and :pep:`3119`.) +.. seealso:: + + * `OrderedSet recipe `_ for an + example built on :class:`MutableSet`. + + * For more about ABCs, see the :mod:`abc` module and :pep:`3119`. :class:`Counter` objects From python-checkins at python.org Sat Mar 21 00:16:15 2009 From: python-checkins at python.org (mark.dickinson) Date: Sat, 21 Mar 2009 00:16:15 +0100 (CET) Subject: [Python-checkins] r70489 - python/trunk/Include/pyport.h Message-ID: <20090320231615.10C301E4002@bag.python.org> Author: mark.dickinson Date: Sat Mar 21 00:16:14 2009 New Revision: 70489 Log: Rewrite Py_ARITHMETIC_RIGHT_SHIFT so that it's valid for all signed integer types T, not just those for which "unsigned T" is legal. Modified: python/trunk/Include/pyport.h Modified: python/trunk/Include/pyport.h ============================================================================== --- python/trunk/Include/pyport.h (original) +++ python/trunk/Include/pyport.h Sat Mar 21 00:16:14 2009 @@ -378,19 +378,23 @@ * C doesn't define whether a right-shift of a signed integer sign-extends * or zero-fills. Here a macro to force sign extension: * Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) - * Return I >> J, forcing sign extension. + * Return I >> J, forcing sign extension. Arithmetically, return the + * floor of I/2**J. * Requirements: - * I is of basic signed type TYPE (char, short, int, long, or long long). - * TYPE is one of char, short, int, long, or long long, although long long - * must not be used except on platforms that support it. - * J is an integer >= 0 and strictly less than the number of bits in TYPE - * (because C doesn't define what happens for J outside that range either). + * I should have signed integer type. In the terminology of C99, this can + * be either one of the five standard signed integer types (signed char, + * short, int, long, long long) or an extended signed integer type. + * J is an integer >= 0 and strictly less than the number of bits in the + * type of I (because C doesn't define what happens for J outside that + * range either). + * TYPE used to specify the type of I, but is now ignored. It's been left + * in for backwards compatibility with versions <= 2.6 or 3.0. * Caution: * I may be evaluated more than once. */ #ifdef SIGNED_RIGHT_SHIFT_ZERO_FILLS #define Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) \ - ((I) < 0 ? ~((~(unsigned TYPE)(I)) >> (J)) : (I) >> (J)) + ((I) < 0 ? -1-((-1-(I)) >> (J)) : (I) >> (J)) #else #define Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) ((I) >> (J)) #endif From python-checkins at python.org Sat Mar 21 00:20:28 2009 From: python-checkins at python.org (mark.dickinson) Date: Sat, 21 Mar 2009 00:20:28 +0100 (CET) Subject: [Python-checkins] r70490 - python/branches/release26-maint Message-ID: <20090320232028.166111E4002@bag.python.org> Author: mark.dickinson Date: Sat Mar 21 00:20:27 2009 New Revision: 70490 Log: Blocked revisions 70489 via svnmerge ........ r70489 | mark.dickinson | 2009-03-20 23:16:14 +0000 (Fri, 20 Mar 2009) | 4 lines Rewrite Py_ARITHMETIC_RIGHT_SHIFT so that it's valid for all signed integer types T, not just those for which "unsigned T" is legal. ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Sat Mar 21 00:23:15 2009 From: python-checkins at python.org (mark.dickinson) Date: Sat, 21 Mar 2009 00:23:15 +0100 (CET) Subject: [Python-checkins] r70491 - in python/branches/py3k: Include/pyport.h Message-ID: <20090320232315.ABD681E4002@bag.python.org> Author: mark.dickinson Date: Sat Mar 21 00:23:15 2009 New Revision: 70491 Log: Merged revisions 70489 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70489 | mark.dickinson | 2009-03-20 23:16:14 +0000 (Fri, 20 Mar 2009) | 4 lines Rewrite Py_ARITHMETIC_RIGHT_SHIFT so that it's valid for all signed integer types T, not just those for which "unsigned T" is legal. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Include/pyport.h Modified: python/branches/py3k/Include/pyport.h ============================================================================== --- python/branches/py3k/Include/pyport.h (original) +++ python/branches/py3k/Include/pyport.h Sat Mar 21 00:23:15 2009 @@ -361,19 +361,23 @@ * C doesn't define whether a right-shift of a signed integer sign-extends * or zero-fills. Here a macro to force sign extension: * Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) - * Return I >> J, forcing sign extension. + * Return I >> J, forcing sign extension. Arithmetically, return the + * floor of I/2**J. * Requirements: - * I is of basic signed type TYPE (char, short, int, long, or long long). - * TYPE is one of char, short, int, long, or long long, although long long - * must not be used except on platforms that support it. - * J is an integer >= 0 and strictly less than the number of bits in TYPE - * (because C doesn't define what happens for J outside that range either). + * I should have signed integer type. In the terminology of C99, this can + * be either one of the five standard signed integer types (signed char, + * short, int, long, long long) or an extended signed integer type. + * J is an integer >= 0 and strictly less than the number of bits in the + * type of I (because C doesn't define what happens for J outside that + * range either). + * TYPE used to specify the type of I, but is now ignored. It's been left + * in for backwards compatibility with versions <= 2.6 or 3.0. * Caution: * I may be evaluated more than once. */ #ifdef SIGNED_RIGHT_SHIFT_ZERO_FILLS #define Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) \ - ((I) < 0 ? ~((~(unsigned TYPE)(I)) >> (J)) : (I) >> (J)) + ((I) < 0 ? -1-((-1-(I)) >> (J)) : (I) >> (J)) #else #define Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) ((I) >> (J)) #endif From python-checkins at python.org Sat Mar 21 00:24:26 2009 From: python-checkins at python.org (mark.dickinson) Date: Sat, 21 Mar 2009 00:24:26 +0100 (CET) Subject: [Python-checkins] r70492 - python/branches/release30-maint Message-ID: <20090320232426.870FC1E4002@bag.python.org> Author: mark.dickinson Date: Sat Mar 21 00:24:26 2009 New Revision: 70492 Log: Blocked revisions 70491 via svnmerge ................ r70491 | mark.dickinson | 2009-03-20 23:23:15 +0000 (Fri, 20 Mar 2009) | 10 lines Merged revisions 70489 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70489 | mark.dickinson | 2009-03-20 23:16:14 +0000 (Fri, 20 Mar 2009) | 4 lines Rewrite Py_ARITHMETIC_RIGHT_SHIFT so that it's valid for all signed integer types T, not just those for which "unsigned T" is legal. ........ ................ Modified: python/branches/release30-maint/ (props changed) From python-checkins at python.org Sat Mar 21 00:33:19 2009 From: python-checkins at python.org (mark.dickinson) Date: Sat, 21 Mar 2009 00:33:19 +0100 (CET) Subject: [Python-checkins] r70493 - python/branches/release26-maint/Objects/longobject.c Message-ID: <20090320233319.4F7B51E4002@bag.python.org> Author: mark.dickinson Date: Sat Mar 21 00:33:19 2009 New Revision: 70493 Log: PyLong_BASE_TWODIGITS_TYPE should be BASE_TWODIGITS_TYPE Modified: python/branches/release26-maint/Objects/longobject.c Modified: python/branches/release26-maint/Objects/longobject.c ============================================================================== --- python/branches/release26-maint/Objects/longobject.c (original) +++ python/branches/release26-maint/Objects/longobject.c Sat Mar 21 00:33:19 2009 @@ -1871,7 +1871,7 @@ carry += v->ob_digit[i+k] - z + ((twodigits)zz << PyLong_SHIFT); v->ob_digit[i+k] = (digit)(carry & PyLong_MASK); - carry = Py_ARITHMETIC_RIGHT_SHIFT(PyLong_BASE_TWODIGITS_TYPE, + carry = Py_ARITHMETIC_RIGHT_SHIFT(BASE_TWODIGITS_TYPE, carry, PyLong_SHIFT); carry -= zz; } @@ -1891,7 +1891,7 @@ carry += v->ob_digit[i+k] + w->ob_digit[i]; v->ob_digit[i+k] = (digit)(carry & PyLong_MASK); carry = Py_ARITHMETIC_RIGHT_SHIFT( - PyLong_BASE_TWODIGITS_TYPE, + BASE_TWODIGITS_TYPE, carry, PyLong_SHIFT); } } From buildbot at python.org Sat Mar 21 01:10:03 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Mar 2009 00:10:03 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 2.6 Message-ID: <20090321001003.76EBD1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%202.6/builds/186 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: mark.dickinson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sat Mar 21 02:35:32 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Mar 2009 01:35:32 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.0 Message-ID: <20090321013532.57CCA1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.0/builds/213 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: mark.dickinson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/3.0.heller-x86-osx5/build/Lib/multiprocessing/managers.py", line 188, in handle_request result = func(c, *args, **kwds) File "/Users/buildbot/buildarea/3.0.heller-x86-osx5/build/Lib/multiprocessing/managers.py", line 306, in debug_info keys.sort() TypeError: unorderable types: str() < int() 1 test failed: test_multiprocessing sincerely, -The Buildbot From buildbot at python.org Sat Mar 21 03:22:35 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Mar 2009 02:22:35 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090321022235.B541E1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/183 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sat Mar 21 04:08:32 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 21 Mar 2009 04:08:32 +0100 (CET) Subject: [Python-checkins] r70494 - in python/branches/py3k: Lib/_pyio.py Lib/test/test_memoryio.py Modules/_stringio.c Message-ID: <20090321030832.4512E1E4002@bag.python.org> Author: benjamin.peterson Date: Sat Mar 21 04:08:31 2009 New Revision: 70494 Log: stringio doesn't have an encoding Modified: python/branches/py3k/Lib/_pyio.py python/branches/py3k/Lib/test/test_memoryio.py python/branches/py3k/Modules/_stringio.c Modified: python/branches/py3k/Lib/_pyio.py ============================================================================== --- python/branches/py3k/Lib/_pyio.py (original) +++ python/branches/py3k/Lib/_pyio.py Sat Mar 21 04:08:31 2009 @@ -1834,3 +1834,7 @@ # TextIOWrapper tells the encoding in its repr. In StringIO, # that's a implementation detail. return object.__repr__(self) + + @property + def encoding(self): + return None Modified: python/branches/py3k/Lib/test/test_memoryio.py ============================================================================== --- python/branches/py3k/Lib/test/test_memoryio.py (original) +++ python/branches/py3k/Lib/test/test_memoryio.py Sat Mar 21 04:08:31 2009 @@ -451,7 +451,7 @@ # These are just dummy values but we nevertheless check them for fear # of unexpected breakage. - self.assertEqual(memio.encoding, "utf-8") + self.assertTrue(memio.encoding is None) self.assertEqual(memio.errors, "strict") self.assertEqual(memio.line_buffering, False) Modified: python/branches/py3k/Modules/_stringio.c ============================================================================== --- python/branches/py3k/Modules/_stringio.c (original) +++ python/branches/py3k/Modules/_stringio.c Sat Mar 21 04:08:31 2009 @@ -665,7 +665,7 @@ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); - return PyUnicode_FromString("utf-8"); + Py_RETURN_NONE; } static PyObject * From python-checkins at python.org Sat Mar 21 04:11:16 2009 From: python-checkins at python.org (brett.cannon) Date: Sat, 21 Mar 2009 04:11:16 +0100 (CET) Subject: [Python-checkins] r70495 - in python/branches/py3k: Doc/glossary.rst Doc/library/sys.rst Doc/reference/simple_stmts.rst Lib/importlib/NOTES Message-ID: <20090321031116.A59951E4002@bag.python.org> Author: brett.cannon Date: Sat Mar 21 04:11:16 2009 New Revision: 70495 Log: Document import's semantics for the language reference. This includes filling in missing details for the sys module. Removed: python/branches/py3k/Lib/importlib/NOTES Modified: python/branches/py3k/Doc/glossary.rst python/branches/py3k/Doc/library/sys.rst python/branches/py3k/Doc/reference/simple_stmts.rst Modified: python/branches/py3k/Doc/glossary.rst ============================================================================== --- python/branches/py3k/Doc/glossary.rst (original) +++ python/branches/py3k/Doc/glossary.rst Sat Mar 21 04:11:16 2009 @@ -182,7 +182,8 @@ finder An object that tries to find the :term:`loader` for a module. It must implement a method named :meth:`find_module`. See :pep:`302` for - details. + details and :class:`importlib.abc.Finder` for an + :term:`abstract base class`. floor division Mathematical division discarding any remainder. The floor division @@ -363,7 +364,8 @@ loader An object that loads a module. It must define a method named :meth:`load_module`. A loader is typically returned by a - :term:`finder`. See :pep:`302` for details. + :term:`finder`. See :pep:`302` for details and + :class:`importlib.abc.Loader` for an :term:`abstract base class`. mapping A container object (such as :class:`dict`) which supports arbitrary key Modified: python/branches/py3k/Doc/library/sys.rst ============================================================================== --- python/branches/py3k/Doc/library/sys.rst (original) +++ python/branches/py3k/Doc/library/sys.rst Sat Mar 21 04:11:16 2009 @@ -478,6 +478,22 @@ characters are stored as UCS-2 or UCS-4. +.. data:: meta_path + + A list of :term:`finder` objects that have their :meth:`find_module` + methods called to see if one of the objects can find the module to be + imported. The :meth:`find_module` method is called at least with the + absolute name of the module being imported. If the module to be imported is + contained in package then the parent package's :attr:`__path__` attribute + is passed in as a second argument. The method returns :keyword:`None` if + the module cannot be found, else returns a :term:`loader`. + + :data:`sys.meta_path` is searched before any implicit default finders or + :data:`sys.path`. + + See :pep:`302` for the original specification. + + .. data:: modules This is a dictionary that maps module names to modules which have already been @@ -508,6 +524,27 @@ :data:`sys.path`. +.. data:: path_hooks + + A list of callables that take a path argument to try to create a + :term:`finder` for the path. If a finder can be created, it is to be + returned by the callable, else raise :exc:`ImportError`. + + Originally specified in :pep:`302`. + + +.. data:: path_importer_cache + + A dictionary acting as a cache for :term:`finder` objects. The keys are + paths that have been passed to :data:`sys.path_hooks` and the values are + the finders that are found. If a path is a valid file system path but no + explicit finder is found on :data:`sys.path_hooks` then :keyword:`None` is + stored to represent the implicit default finder should be used. If the path + is not an existing path then :class:`imp.NullImporter` is set. + + Originally specified in :pep:`302`. + + .. data:: platform This string contains a platform identifier that can be used to append Modified: python/branches/py3k/Doc/reference/simple_stmts.rst ============================================================================== --- python/branches/py3k/Doc/reference/simple_stmts.rst (original) +++ python/branches/py3k/Doc/reference/simple_stmts.rst Sat Mar 21 04:11:16 2009 @@ -642,48 +642,125 @@ Import statements are executed in two steps: (1) find a module, and initialize it if necessary; (2) define a name or names in the local namespace (of the scope -where the :keyword:`import` statement occurs). The first form (without -:keyword:`from`) repeats these steps for each identifier in the list. The form -with :keyword:`from` performs step (1) once, and then performs step (2) -repeatedly. - -In this context, to "initialize" a built-in or extension module means to call an -initialization function that the module must provide for the purpose (in the -reference implementation, the function's name is obtained by prepending string -"init" to the module's name); to "initialize" a Python-coded module means to -execute the module's body. - -.. index:: - single: modules (in module sys) - single: sys.modules - pair: module; name - pair: built-in; module - pair: user-defined; module - pair: filename; extension - triple: module; search; path - module: sys - -The system maintains a table of modules that have been or are being initialized, -indexed by module name. This table is accessible as ``sys.modules``. When a -module name is found in this table, step (1) is finished. If not, a search for -a module definition is started. When a module is found, it is loaded. Details -of the module searching and loading process are implementation and platform -specific. It generally involves searching for a "built-in" module with the -given name and then searching a list of locations given as ``sys.path``. +where the :keyword:`import` statement occurs). The statement comes in two +forms differing on whether it uses the :keyword:`from` keyword. The first form +(without :keyword:`from`) repeats these steps for each identifier in the list. +The form with :keyword:`from` performs step (1) once, and then performs step +(2) repeatedly. For a reference implementation of step (1), see the +:mod:`importlib` module. .. index:: - pair: module; initialization - exception: ImportError - single: code block - exception: SyntaxError + single: package + +To understand how step (1) occurs, one must first understand how Python handles +hierarchical naming of modules. To help organize modules and provide a +hierarchy in naming, Python has a concept of packages. A package can contain +other packages and modules while modules cannot contain other modules or +packages. From a file system perspective, packages are directories and modules +are files. The original `specification for packages +`_ is still available to read, +although minor details have changed since the writing of that document. -If a built-in module is found, its built-in initialization code is executed and -step (1) is finished. If no matching file is found, :exc:`ImportError` is -raised. If a file is found, it is parsed, yielding an executable code block. If -a syntax error occurs, :exc:`SyntaxError` is raised. Otherwise, an empty module -of the given name is created and inserted in the module table, and then the code -block is executed in the context of this module. Exceptions during this -execution terminate step (1). +.. index:: + single: sys.modules + +Once the name of the module is known (unless otherwise specified, the term +"module" will refer to both packages and modules), searching +for the module or package can begin. The first place checked is +:data:`sys.modules`, the cache of all modules that have been imported +previously. If the module is found there then it is used in step (2) of import. + +.. index:: + single: sys.meta_path + single: finder + pair: finder; find_module + single: __path__ + +If the module is not found in the cache, then :data:`sys.meta_path` is searched +(the specification for :data:`sys.meta_path` can be found in :pep:`302`). +The object is a list of :term:`finder` objects which are queried in order as to +whether they know how to load the module by calling their :meth:`find_module` +method with the name of the module. If the module happens to be contained +within a package (as denoted by the existence of a dot in the name), then a +second argument to :meth:`find_module` is given as the value of the +:attr:`__path__` attribute from the parent package (everything up to the last +dot in the name of the module being imported). If a finder can find the module +it returns a :term:`loader` (discussed later) or returns :keyword:`None`. + +.. index:: + single: sys.path_hooks + single: sys.path_importer_cache + single: sys.path + +If none of the finders on :data:`sys.meta_path` are able to find the module +then some implicitly defined finders are queried. Implementations of Python +vary in what implicit meta path finders are defined. The one they all do +define, though, is one that handles :data:`sys.path_hooks`, +:data:`sys.path_importer_cache`, and :data:`sys.path`. + +The implicit finder searches for the requested module in the "paths" specified +in one of two places ("paths" do not have to be file system paths). If the +module being imported is supposed to be contained within a package then the +second argument passed to :meth:`find_module`, :attr:`__path__` on the parent +package, is used as the source of paths. If the module is not contained in a +package then :data:`sys.path` is used as the source of paths. + +Once the source of paths is chosen it is iterated over to find a finder that +can handle that path. The dict at :data:`sys.path_importer_cache` caches +finders for paths and is checked for a finder. If the path does not have a +finder cached then :data:`sys.path_hooks` is searched by calling each object in +the list with a single argument of the path, returning a finder or raises +:exc:`ImportError`. If a finder is returned then it is cached in +:data:`sys.path_importer_cache` and then used for that path entry. If no finder +can be found but the path exists then a value of :keyword:`None` is +stored in :data:`sys.path_importer_cache` to signify that an implicit, +file-based finder that handles modules stored as individual files should be +used for that path. If the path does not exist then a finder which always +returns :keyword:`None` is placed in the cache for the path. + +.. index:: + single: loader + pair: loader; load_module + exception: ImportError + +If no finder can find the module then :exc:`ImportError` is raised. Otherwise +some finder returned a loader whose :meth:`load_module` method is called with +the name of the module to load (see :pep:`302` for the original definition of +loaders). A loader has several responsibilities to perform on a module it +loads. First, if the module already exists in :data:`sys.modules` (a +possibility if the loader is called outside of the import machinery) then it +is to use that module for initialization and not a new module. But if the +module does not exist in :data:`sys.modules` then it is to be added to that +dict before initialization begins. If an error occurs during loading of the +module and it was added to :data:`sys.modules` it is to be removed from the +dict. If an error occurs but the module was already in :data:`sys.modules` it +is left in the dict. + +.. index:: + single: __name__ + single: __file__ + single: __path__ + single: __package__ + single: __loader__ + +The loader must set several attributes on the module. :data:`__name__` is to be +set to the name of the module. :data:`__file__` is to be the "path" to the file +unless the module is built-in (and thus listed in +:data:`sys.builtin_module_names`) in which case the attribute is not set. +If what is being imported is a package then :data:`__path__` is to be set to a +list of paths to be searched when looking for modules and packages contained +within the package being imported. :data:`__package__` is optional but should +be set to the name of package that contains the module or package (the empty +string is used for module not contained in a package). :data:`__loader__` is +also optional but should be set to the loader object that is loading the +module. + +.. index:: + exception: ImportError + +If an error occurs during loading then the loader raises :exc:`ImportError` if +some other exception is not already being propagated. Otherwise the loader +returns the module that was loaded and initialized. When step (1) finishes without raising an exception, step (2) can begin. @@ -723,23 +800,21 @@ raise a :exc:`SyntaxError`. .. index:: - keyword: from - statement: from - triple: hierarchical; module; names - single: packages - single: __init__.py - -**Hierarchical module names:** when the module names contains one or more dots, -the module search path is carried out differently. The sequence of identifiers -up to the last dot is used to find a "package"; the final identifier is then -searched inside the package. A package is generally a subdirectory of a -directory on ``sys.path`` that has a file :file:`__init__.py`. - -.. - [XXX Can't be - bothered to spell this out right now; see the URL - http://www.python.org/doc/essays/packages.html for more details, also about how - the module search works from inside a package.] + single: relative; import + +When specifying what module to import you do not have to specify the absolute +name of the module. When a module or package is contained within another +package it is possible to make a relative import within the same top package +without having to mention the package name. By using leading dots in the +specified module or package after :keyword:`from` you can specify how high to +traverse up the current package hierarchy without specifying exact names. One +leading dot means the current package where the module making the import +exists. Two dots means up one package level. Three dots is up two levels, etc. +So if you execute ``from . import mod`` from a module in the ``pkg`` package +then you will end up importing ``pkg.mod``. If you execute ``from ..subpkg2 +imprt mod`` from within ``pkg.subpkg1`` you will import ``pkg.subpkg2.mod``. +The specification for relative imports is contained within :pep:`328`. + .. index:: builtin: __import__ Deleted: python/branches/py3k/Lib/importlib/NOTES ============================================================================== --- python/branches/py3k/Lib/importlib/NOTES Sat Mar 21 04:11:16 2009 +++ (empty file) @@ -1,7 +0,0 @@ -to do -///// - -* Make sure that there is documentation *somewhere* fully explaining the -semantics of import that can be referenced from the package's documentation -(even if it is in the package documentation itself, although it might be best -in the language specification). From buildbot at python.org Sat Mar 21 04:35:05 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Mar 2009 03:35:05 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090321033505.E24691E4024@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/435 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sat Mar 21 09:40:19 2009 From: python-checkins at python.org (nick.coghlan) Date: Sat, 21 Mar 2009 09:40:19 +0100 (CET) Subject: [Python-checkins] r70496 - peps/trunk/pep-0377.txt Message-ID: <20090321084019.3BDC41E4002@bag.python.org> Author: nick.coghlan Date: Sat Mar 21 09:40:19 2009 New Revision: 70496 Log: Record the rejection of PEP 377 Modified: peps/trunk/pep-0377.txt Modified: peps/trunk/pep-0377.txt ============================================================================== --- peps/trunk/pep-0377.txt (original) +++ peps/trunk/pep-0377.txt Sat Mar 21 09:40:19 2009 @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Nick Coghlan -Status: Draft +Status: Rejected Type: Standards Track Content-Type: text/x-rst Created: 8-Mar-2009 @@ -29,6 +29,16 @@ statement body if ``__enter__()`` raises this exception. +PEP Rejection +============= + +This PEP was rejected by Guido [2] as it imposes too great an increase +in complexity without a proportional increase in expressiveness and +correctness. In the absence of compelling use cases that need the more +complex semantics proposed by this PEP the existing behaviour is +considered acceptable. + + Proposed Change =============== @@ -262,6 +272,9 @@ .. [3] Import-style syntax to reduce indentation of nested with statements (http://mail.python.org/pipermail/python-ideas/2009-March/003188.html) +.. [4] Guido's rejection of the PEP + (http://mail.python.org/pipermail/python-dev/2009-March/087263.html) + Copyright ========= From python-checkins at python.org Sat Mar 21 11:26:42 2009 From: python-checkins at python.org (mark.dickinson) Date: Sat, 21 Mar 2009 11:26:42 +0100 (CET) Subject: [Python-checkins] r70497 - in python/branches/py3k: Lib/test/test_struct.py Misc/ACKS Misc/NEWS Modules/_struct.c Message-ID: <20090321102642.98CD21E4002@bag.python.org> Author: mark.dickinson Date: Sat Mar 21 11:26:31 2009 New Revision: 70497 Log: - Issue #5463: In struct module, remove deprecated overflow wrapping when packing an integer: for example, struct.pack('=L', -1) now raises struct.error instead of returning b'\xff\xff\xff\xff'. Thanks Andreas Schawo for the patch. Modified: python/branches/py3k/Lib/test/test_struct.py python/branches/py3k/Misc/ACKS python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_struct.c Modified: python/branches/py3k/Lib/test/test_struct.py ============================================================================== --- python/branches/py3k/Lib/test/test_struct.py (original) +++ python/branches/py3k/Lib/test/test_struct.py Sat Mar 21 11:26:31 2009 @@ -2,8 +2,6 @@ import unittest import struct import warnings -warnings.filterwarnings("ignore", "struct integer overflow masking is deprecated", - DeprecationWarning) from functools import wraps from test.support import TestFailed, verbose, run_unittest @@ -17,11 +15,9 @@ import _struct except ImportError: PY_STRUCT_RANGE_CHECKING = 0 - PY_STRUCT_OVERFLOW_MASKING = 1 PY_STRUCT_FLOAT_COERCE = 2 else: PY_STRUCT_RANGE_CHECKING = getattr(_struct, '_PY_STRUCT_RANGE_CHECKING', 0) - PY_STRUCT_OVERFLOW_MASKING = getattr(_struct, '_PY_STRUCT_OVERFLOW_MASKING', 0) PY_STRUCT_FLOAT_COERCE = getattr(_struct, '_PY_STRUCT_FLOAT_COERCE', 0) def string_reverse(s): @@ -51,8 +47,7 @@ except (struct.error, OverflowError): pass except DeprecationWarning: - if not PY_STRUCT_OVERFLOW_MASKING: - raise TestFailed("%s%s expected to raise DeprecationWarning" % ( + raise TestFailed("%s%s expected to raise DeprecationWarning" % ( func.__name__, args)) else: raise TestFailed("%s%s did not raise error" % ( @@ -471,11 +466,6 @@ self.check_float_coerce(endian + fmt, 1.0) self.check_float_coerce(endian + fmt, 1.5) - def test_issue4228(self): - # Packing a long may yield either 32 or 64 bits - x = struct.pack('L', -1)[:4] - self.assertEqual(x, b'\xff'*4) - def test_unpack_from(self): test_string = b'abcd01234' fmt = '4s' Modified: python/branches/py3k/Misc/ACKS ============================================================================== --- python/branches/py3k/Misc/ACKS (original) +++ python/branches/py3k/Misc/ACKS Sat Mar 21 11:26:31 2009 @@ -620,6 +620,7 @@ Ty Sarna Ben Sayer Michael Scharf +Andreas Schawo Neil Schemenauer David Scherer Gregor Schmid Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Mar 21 11:26:31 2009 @@ -44,6 +44,13 @@ - Issue #5016: FileIO.seekable() could return False if the file position was negative when truncated to a C int. Patch by Victor Stinner. +Extension Modules +----------------- + +- Issue #5463: In struct module, remove deprecated overflow wrapping + when packing an integer: struct.pack('=L', -1) now raises + struct.error instead of returning b'\xff\xff\xff\xff'. + What's New in Python 3.1 alpha 1 ================================ Modified: python/branches/py3k/Modules/_struct.c ============================================================================== --- python/branches/py3k/Modules/_struct.c (original) +++ python/branches/py3k/Modules/_struct.c Sat Mar 21 11:26:31 2009 @@ -12,20 +12,6 @@ static PyTypeObject PyStructType; -/* If PY_STRUCT_OVERFLOW_MASKING is defined, the struct module will wrap all input - numbers for explicit endians such that they fit in the given type, much - like explicit casting in C. A warning will be raised if the number did - not originally fit within the range of the requested type. If it is - not defined, then all range errors and overflow will be struct.error - exceptions. */ - -#define PY_STRUCT_OVERFLOW_MASKING 1 - -#ifdef PY_STRUCT_OVERFLOW_MASKING -static PyObject *pylong_ulong_mask = NULL; -static PyObject *pyint_zero = NULL; -#endif - /* If PY_STRUCT_FLOAT_COERCE is defined, the struct module will allow float arguments for integer formats with a warning for backwards compatibility. */ @@ -237,107 +223,9 @@ #endif -#ifdef PY_STRUCT_OVERFLOW_MASKING - -/* Helper routine to get a Python integer and raise the appropriate error - if it isn't one */ - -#define INT_OVERFLOW "struct integer overflow masking is deprecated" -static int -get_wrapped_long(PyObject *v, long *p) -{ - if (get_long(v, p) < 0) { - if (PyLong_Check(v) && - PyErr_ExceptionMatches(PyExc_OverflowError)) { - PyObject *wrapped; - long x; - PyErr_Clear(); -#ifdef PY_STRUCT_FLOAT_COERCE - if (PyFloat_Check(v)) { - PyObject *o; - int res; - PyErr_Clear(); - if (PyErr_WarnEx(PyExc_DeprecationWarning, FLOAT_COERCE, 2) < 0) - return -1; - o = PyNumber_Long(v); - if (o == NULL) - return -1; - res = get_wrapped_long(o, p); - Py_DECREF(o); - return res; - } -#endif - if (PyErr_WarnEx(PyExc_DeprecationWarning, INT_OVERFLOW, 2) < 0) - return -1; - wrapped = PyNumber_And(v, pylong_ulong_mask); - if (wrapped == NULL) - return -1; - x = (long)PyLong_AsUnsignedLong(wrapped); - Py_DECREF(wrapped); - if (x == -1 && PyErr_Occurred()) - return -1; - *p = x; - } else { - return -1; - } - } - return 0; -} - -static int -get_wrapped_ulong(PyObject *v, unsigned long *p) -{ - long x = (long)PyLong_AsUnsignedLong(v); - if (x == -1 && PyErr_Occurred()) { - PyObject *wrapped; - PyErr_Clear(); -#ifdef PY_STRUCT_FLOAT_COERCE - if (PyFloat_Check(v)) { - PyObject *o; - int res; - PyErr_Clear(); - if (PyErr_WarnEx(PyExc_DeprecationWarning, FLOAT_COERCE, 2) < 0) - return -1; - o = PyNumber_Long(v); - if (o == NULL) - return -1; - res = get_wrapped_ulong(o, p); - Py_DECREF(o); - return res; - } -#endif - wrapped = PyNumber_And(v, pylong_ulong_mask); - if (wrapped == NULL) - return -1; - if (PyErr_WarnEx(PyExc_DeprecationWarning, INT_OVERFLOW, 2) < 0) { - Py_DECREF(wrapped); - return -1; - } - x = (long)PyLong_AsUnsignedLong(wrapped); - Py_DECREF(wrapped); - if (x == -1 && PyErr_Occurred()) - return -1; - } - *p = (unsigned long)x; - return 0; -} - -#define RANGE_ERROR(x, f, flag, mask) \ - do { \ - if (_range_error(f, flag) < 0) \ - return -1; \ - else \ - (x) &= (mask); \ - } while (0) - -#else - -#define get_wrapped_long get_long -#define get_wrapped_ulong get_ulong #define RANGE_ERROR(x, f, flag, mask) return _range_error(f, flag) -#endif /* Floating point helpers */ @@ -392,26 +280,7 @@ ~ largest, largest); } -#ifdef PY_STRUCT_OVERFLOW_MASKING - { - PyObject *ptype, *pvalue, *ptraceback; - PyObject *msg; - int rval; - PyErr_Fetch(&ptype, &pvalue, &ptraceback); - assert(pvalue != NULL); - msg = PyObject_Str(pvalue); - Py_XDECREF(ptype); - Py_XDECREF(pvalue); - Py_XDECREF(ptraceback); - if (msg == NULL) - return -1; - rval = PyErr_WarnEx(PyExc_DeprecationWarning, - _PyUnicode_AsString(msg), 2); - Py_DECREF(msg); - if (rval == 0) - return 0; - } -#endif + return -1; } @@ -673,7 +542,7 @@ { unsigned long x; unsigned int y; - if (get_wrapped_ulong(v, &x) < 0) + if (get_ulong(v, &x) < 0) return -1; y = (unsigned int)x; #if (SIZEOF_LONG > SIZEOF_INT) @@ -698,7 +567,7 @@ np_ulong(char *p, PyObject *v, const formatdef *f) { unsigned long x; - if (get_wrapped_ulong(v, &x) < 0) + if (get_ulong(v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; @@ -905,7 +774,7 @@ { long x; Py_ssize_t i; - if (get_wrapped_long(v, &x) < 0) + if (get_long(v, &x) < 0) return -1; i = f->size; if (i != SIZEOF_LONG) { @@ -915,10 +784,6 @@ else if ((i == 4) && (x < -2147483648L || x > 2147483647L)) RANGE_ERROR(x, f, 0, 0xffffffffL); #endif -#ifdef PY_STRUCT_OVERFLOW_MASKING - else if ((i == 1) && (x < -128 || x > 127)) - RANGE_ERROR(x, f, 0, 0xffL); -#endif } do { p[--i] = (char)x; @@ -932,7 +797,7 @@ { unsigned long x; Py_ssize_t i; - if (get_wrapped_ulong(v, &x) < 0) + if (get_ulong(v, &x) < 0) return -1; i = f->size; if (i != SIZEOF_LONG) { @@ -1015,14 +880,8 @@ static formatdef bigendian_table[] = { {'x', 1, 0, NULL}, -#ifdef PY_STRUCT_OVERFLOW_MASKING - /* Native packers do range checking without overflow masking. */ - {'b', 1, 0, nu_byte, bp_int}, - {'B', 1, 0, nu_ubyte, bp_uint}, -#else {'b', 1, 0, nu_byte, np_byte}, {'B', 1, 0, nu_ubyte, np_ubyte}, -#endif {'c', 1, 0, nu_char, np_char}, {'s', 1, 0, NULL}, {'p', 1, 0, NULL}, @@ -1133,7 +992,7 @@ { long x; Py_ssize_t i; - if (get_wrapped_long(v, &x) < 0) + if (get_long(v, &x) < 0) return -1; i = f->size; if (i != SIZEOF_LONG) { @@ -1143,10 +1002,6 @@ else if ((i == 4) && (x < -2147483648L || x > 2147483647L)) RANGE_ERROR(x, f, 0, 0xffffffffL); #endif -#ifdef PY_STRUCT_OVERFLOW_MASKING - else if ((i == 1) && (x < -128 || x > 127)) - RANGE_ERROR(x, f, 0, 0xffL); -#endif } do { *p++ = (char)x; @@ -1160,7 +1015,7 @@ { unsigned long x; Py_ssize_t i; - if (get_wrapped_ulong(v, &x) < 0) + if (get_ulong(v, &x) < 0) return -1; i = f->size; if (i != SIZEOF_LONG) { @@ -1234,14 +1089,8 @@ static formatdef lilendian_table[] = { {'x', 1, 0, NULL}, -#ifdef PY_STRUCT_OVERFLOW_MASKING - /* Native packers do range checking without overflow masking. */ - {'b', 1, 0, nu_byte, lp_int}, - {'B', 1, 0, nu_ubyte, lp_uint}, -#else {'b', 1, 0, nu_byte, np_byte}, {'B', 1, 0, nu_ubyte, np_ubyte}, -#endif {'c', 1, 0, nu_char, np_char}, {'s', 1, 0, NULL}, {'p', 1, 0, NULL}, @@ -2125,26 +1974,6 @@ if (PyType_Ready(&PyStructType) < 0) return NULL; -#ifdef PY_STRUCT_OVERFLOW_MASKING - if (pyint_zero == NULL) { - pyint_zero = PyLong_FromLong(0); - if (pyint_zero == NULL) - return NULL; - } - if (pylong_ulong_mask == NULL) { -#if (SIZEOF_LONG == 4) - pylong_ulong_mask = PyLong_FromString("FFFFFFFF", NULL, 16); -#else - pylong_ulong_mask = PyLong_FromString("FFFFFFFFFFFFFFFF", NULL, 16); -#endif - if (pylong_ulong_mask == NULL) - return NULL; - } - -#else - /* This speed trick can't be used until overflow masking goes away, because - native endian always raises exceptions instead of overflow masking. */ - /* Check endian and swap in faster functions */ { int one = 1; @@ -2183,7 +2012,6 @@ native++; } } -#endif /* Add some symbolic constants to the module */ if (StructError == NULL) { @@ -2201,9 +2029,6 @@ PyModule_AddObject(m, "__version__", ver); PyModule_AddIntConstant(m, "_PY_STRUCT_RANGE_CHECKING", 1); -#ifdef PY_STRUCT_OVERFLOW_MASKING - PyModule_AddIntConstant(m, "_PY_STRUCT_OVERFLOW_MASKING", 1); -#endif #ifdef PY_STRUCT_FLOAT_COERCE PyModule_AddIntConstant(m, "_PY_STRUCT_FLOAT_COERCE", 1); #endif From python-checkins at python.org Sat Mar 21 11:28:18 2009 From: python-checkins at python.org (mark.dickinson) Date: Sat, 21 Mar 2009 11:28:18 +0100 (CET) Subject: [Python-checkins] r70498 - python/branches/release30-maint Message-ID: <20090321102818.77D521E4002@bag.python.org> Author: mark.dickinson Date: Sat Mar 21 11:28:18 2009 New Revision: 70498 Log: Blocked revisions 70497 via svnmerge ........ r70497 | mark.dickinson | 2009-03-21 10:26:31 +0000 (Sat, 21 Mar 2009) | 6 lines - Issue #5463: In struct module, remove deprecated overflow wrapping when packing an integer: for example, struct.pack('=L', -1) now raises struct.error instead of returning b'\xff\xff\xff\xff'. Thanks Andreas Schawo for the patch. ........ Modified: python/branches/release30-maint/ (props changed) From python-checkins at python.org Sat Mar 21 11:32:53 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Sat, 21 Mar 2009 11:32:53 +0100 (CET) Subject: [Python-checkins] r70499 - python/trunk/Objects/unicodeobject.c Message-ID: <20090321103253.3B18F1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Sat Mar 21 11:32:52 2009 New Revision: 70499 Log: There is no macro named SIZEOF_SSIZE_T. Should use SIZEOF_SIZE_T instead. Modified: python/trunk/Objects/unicodeobject.c Modified: python/trunk/Objects/unicodeobject.c ============================================================================== --- python/trunk/Objects/unicodeobject.c (original) +++ python/trunk/Objects/unicodeobject.c Sat Mar 21 11:32:52 2009 @@ -3795,7 +3795,7 @@ /* --- MBCS codecs for Windows -------------------------------------------- */ -#if SIZEOF_INT < SIZEOF_SSIZE_T +#if SIZEOF_INT < SIZEOF_SIZE_T #define NEED_RETRY #endif From buildbot at python.org Sat Mar 21 11:45:30 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Mar 2009 10:45:30 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090321104530.4360C1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/497 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Abort trap sincerely, -The Buildbot From python-checkins at python.org Sat Mar 21 11:51:42 2009 From: python-checkins at python.org (mark.dickinson) Date: Sat, 21 Mar 2009 11:51:42 +0100 (CET) Subject: [Python-checkins] r70500 - python/branches/py3k/Misc/NEWS Message-ID: <20090321105142.E77CE1E4002@bag.python.org> Author: mark.dickinson Date: Sat Mar 21 11:51:42 2009 New Revision: 70500 Log: Remove remnants of svn conflict marker from Misc/NEWS Modified: python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Mar 21 11:51:42 2009 @@ -60,7 +60,6 @@ Core and Builtins ----------------- -======= - The io module has been reimplemented in C for speed. - Give dict views an informative __repr__. From python-checkins at python.org Sat Mar 21 11:52:39 2009 From: python-checkins at python.org (mark.dickinson) Date: Sat, 21 Mar 2009 11:52:39 +0100 (CET) Subject: [Python-checkins] r70501 - python/branches/release30-maint Message-ID: <20090321105239.B35661E4002@bag.python.org> Author: mark.dickinson Date: Sat Mar 21 11:52:39 2009 New Revision: 70501 Log: Blocked revisions 70500 via svnmerge ........ r70500 | mark.dickinson | 2009-03-21 10:51:42 +0000 (Sat, 21 Mar 2009) | 2 lines Remove remnants of svn conflict marker from Misc/NEWS ........ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Sat Mar 21 12:12:27 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Mar 2009 11:12:27 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.0 Message-ID: <20090321111227.CFFA01E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.0/builds/193 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sat Mar 21 12:38:13 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Mar 2009 11:38:13 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090321113814.0E9CD1E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/218 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: 3 tests failed: test_distutils test_posix test_subprocess ====================================================================== FAIL: test_get_python_inc (distutils.tests.test_sysconfig.SysconfigTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/distutils/tests/test_sysconfig.py", line 45, in test_get_python_inc self.assert_(os.path.isdir(inc_dir), inc_dir) AssertionError: /home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/Include ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_subprocess.py", line 115, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From buildbot at python.org Sat Mar 21 12:59:13 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Mar 2009 11:59:13 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090321115913.497B01E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/747 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sat Mar 21 14:04:41 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Sat, 21 Mar 2009 14:04:41 +0100 (CET) Subject: [Python-checkins] r70502 - in python/branches/release26-maint: Objects/unicodeobject.c Message-ID: <20090321130441.F25DE1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Sat Mar 21 14:04:41 2009 New Revision: 70502 Log: Merged revisions 70499 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70499 | hirokazu.yamamoto | 2009-03-21 19:32:52 +0900 | 1 line There is no macro named SIZEOF_SSIZE_T. Should use SIZEOF_SIZE_T instead. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Objects/unicodeobject.c Modified: python/branches/release26-maint/Objects/unicodeobject.c ============================================================================== --- python/branches/release26-maint/Objects/unicodeobject.c (original) +++ python/branches/release26-maint/Objects/unicodeobject.c Sat Mar 21 14:04:41 2009 @@ -3737,7 +3737,7 @@ /* --- MBCS codecs for Windows -------------------------------------------- */ -#if SIZEOF_INT < SIZEOF_SSIZE_T +#if SIZEOF_INT < SIZEOF_SIZE_T #define NEED_RETRY #endif From python-checkins at python.org Sat Mar 21 14:23:27 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Sat, 21 Mar 2009 14:23:27 +0100 (CET) Subject: [Python-checkins] r70503 - in python/branches/py3k: Objects/unicodeobject.c Message-ID: <20090321132327.757B31E4002@bag.python.org> Author: hirokazu.yamamoto Date: Sat Mar 21 14:23:27 2009 New Revision: 70503 Log: Merged revisions 70499 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70499 | hirokazu.yamamoto | 2009-03-21 19:32:52 +0900 | 1 line There is no macro named SIZEOF_SSIZE_T. Should use SIZEOF_SIZE_T instead. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Objects/unicodeobject.c Modified: python/branches/py3k/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k/Objects/unicodeobject.c (original) +++ python/branches/py3k/Objects/unicodeobject.c Sat Mar 21 14:23:27 2009 @@ -4217,7 +4217,7 @@ /* --- MBCS codecs for Windows -------------------------------------------- */ -#if SIZEOF_INT < SIZEOF_SSIZE_T +#if SIZEOF_INT < SIZEOF_SIZE_T #define NEED_RETRY #endif From python-checkins at python.org Sat Mar 21 14:37:43 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Sat, 21 Mar 2009 14:37:43 +0100 (CET) Subject: [Python-checkins] r70504 - in python/branches/release30-maint: Objects/unicodeobject.c Message-ID: <20090321133743.A44AD1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Sat Mar 21 14:37:43 2009 New Revision: 70504 Log: Merged revisions 70503 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70503 | hirokazu.yamamoto | 2009-03-21 22:23:27 +0900 | 9 lines Merged revisions 70499 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70499 | hirokazu.yamamoto | 2009-03-21 19:32:52 +0900 | 1 line There is no macro named SIZEOF_SSIZE_T. Should use SIZEOF_SIZE_T instead. ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Objects/unicodeobject.c Modified: python/branches/release30-maint/Objects/unicodeobject.c ============================================================================== --- python/branches/release30-maint/Objects/unicodeobject.c (original) +++ python/branches/release30-maint/Objects/unicodeobject.c Sat Mar 21 14:37:43 2009 @@ -3955,7 +3955,7 @@ /* --- MBCS codecs for Windows -------------------------------------------- */ -#if SIZEOF_INT < SIZEOF_SSIZE_T +#if SIZEOF_INT < SIZEOF_SIZE_T #define NEED_RETRY #endif From python-checkins at python.org Sat Mar 21 15:08:20 2009 From: python-checkins at python.org (tarek.ziade) Date: Sat, 21 Mar 2009 15:08:20 +0100 (CET) Subject: [Python-checkins] r70505 - peps/trunk/pep-0381.txt Message-ID: <20090321140820.5AA821E4002@bag.python.org> Author: tarek.ziade Date: Sat Mar 21 15:08:19 2009 New Revision: 70505 Log: added PEP 381 (mirroring infrastructure for PyPI) Added: peps/trunk/pep-0381.txt (contents, props changed) Added: peps/trunk/pep-0381.txt ============================================================================== --- (empty file) +++ peps/trunk/pep-0381.txt Sat Mar 21 15:08:19 2009 @@ -0,0 +1,307 @@ +PEP: 376 +Title: Mirroring infrastructure for PyPI +Version: $Revision$ +Last-Modified: $Date$ +Author: Tarek Ziad? +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 21-March-2009 +Python-Version: N.A. +Post-History: + +Abstract +======== + +This PEP describes a mirroring infrastructure for PyPI. + +Rationale +========= + +PyPI is hosting over 4000 projects and is used on a daily basis +by people to build applications. Especially systems like `easy_install` +and `zc.buildout` make intensive usage of PyPI. + +For people making intensive use of PyPI, it can act as a single point +of failure. People have started to set up some mirrors, both private and +public. Those mirrors are active mirrors, which means that they are +browsing PyPI to get synced. + +In order to make the system more reliable, this PEP describes: + +- the mirror listing and registering at PyPI +- the pages a public mirror should maintain. + these pages will be used by PyPI, in order to get + hit counts and the last modified date. +- how a mirror should synchronize with PyPI +- how a client can implement a fail-over mechanism +- a contact form for Package maintainers + +Mirror listing and registering +============================== + +A new text page will be added at `http://pypi.python.org/mirrors` +that can be browsed like the simple index. This page gives a list of +the mirrors through a list of links. + +These links are the URL of the simple index of each mirror. +The page will look like this:: + + + # PyPI mirrors + # + # If you want to register a new mirror, send an email + # to the catalog-SIG at python.org with: + # + # - The urls of your mirror: + # - the root of the server + # - the index page + # - the last modified page + # - the local stats page + # - the global stats page + # - the mirrors page + # + # - The name and email of the maintainer. + # + # The registering is done manually and to become a + # mirror, you need to strictly follow the mirror protocol + # described here: + # + # http://wiki.python.org/PEP_374 + # + # root,index,last-modified,local-stats,stats,mirrors + http://example.com/pypi,index,last-modified,local-stats,stats,mirrors + http://example2.com/pypi,index,last-modified,local-stats,stats,mirrors + +When a mirror is proposed on the mailing list, it is manually +added in the mirror list in the PyPI application after it +has been checked to be compliant with the mirroring rules. + +The mirror list page is a simple text page that can be browsed +by any tool that wants to get a list of registered mirrors. +Other package indexes that are not mirrors of PyPI are not added in the +mirror list in PyPI. Although they can provide themselve the +same mirroring list mechanism for their own mirrors. + +Special pages a mirror needs to provide +======================================= + +A mirror needs to provide four pages, beside the index one: + +- last-modified +- local-stats +- stats +- mirrors + +Last modified date +:::::::::::::::::: + +CPAN uses a freshness date system where the mirror last synchronisation +date is made available. + +For PyPI, each mirror needs to maintain an url with a simple text content +that represents the last synchronisation date the mirror maintains. + +The date is provided in GMT time, using the ISO 8601 format +(see http://en.wikipedia.org/wiki/ISO_8601) + +Each mirror will be responsible to maintain its last modified date. + +Conventionaly, this page should be reachable at: `/last-modified`. + +Local statistics +:::::::::::::::: + +Each mirror is responsible to count all the downloads +that where done on it. This is used by PyPI to sum up all +downloads, to be able to display the grand total. + +These statistics are in csv-like form, with a header at the first +line. It needs to obey `PEP 305 `_ +Basically, it should be readable by Python `csv` module. + +The fields in this file are: + +- package: the distutils id of the package. +- filename: the filename that has been downloaded. +- useragent: the User-Agent of the client that has downloaded the package. +- count: the number of downloads. + +The content will look like this:: + + # package,filename,useragent,count + zc.buildout,zc.buildout-1.6.0.tgz,MyAgent,142 + ... + +The counting starts the day the mirror is launched, and there is one file per +day, compressed using the `bzip2` format. Each file is named after the +day. For example `2008-11-06.bz2` is the file for the 6th of November 2008. + +They are then provided in a folder called `days`. For example: + +- /local-stats/days/2008-11-06.bz2 +- /local-stats/days/2008-11-07.bz2 +- /local-stats/days/2008-11-08.bz2 + +Conventionally the name should be `local-stats` but it can be any name +provided when the mirror is registered. + +Statistics page +::::::::::::::: + +PyPI and each mirror are responsible to provide the grand total +page at `/stats`. This page is calculated daily by PyPI, +by reading all mirrors local stats and suming them. + +Therefore the mirrors should not try to rebuild this stat page but simply +get PyPI's one during each synchronization. + +It has the same structure than `local-stats` but also provides +counts for months. + +Examples: + +- /stats/days/2008-11-06.bz2 +- /stats/days/2008-11-07.bz2 +- /stats/days/2008-11-08.bz2 +- /stats/months/2008-11.bz2 +- /stats/months/2008-10.bz2 + +Conventionally the name should be `stats` but it can be any name +provided when the mirror is registered. + + +Mirrors listing page +:::::::::::::::::::: + +Like `/stats`, each mirror should get and provide a copy of the `/mirrors` +page. + +Conventionally the name should be `mirrors` but it can be any name +provided when the mirror is registered. + +How a mirror should synchronize with PyPI +========================================= + +A mirroring protocol calls `Simple Index` was described +and implemented by Martin v. Loewis and Jim Fulton, based on +how `easy_install` works. This section synthesizes it +and give a few relevant links, plus a small part about +`User-Agent`. + +The mirroring protocol +:::::::::::::::::::::: + +XXX Need to describe the protocol here. + +The `zc.pypimirror `_ package +provides an application that respects this protocol to browse PyPI. + +User-agent request header +::::::::::::::::::::::::: + +In order to be able to differentiate actions taken by clients +over PyPI, a specific user agent name should be provided by all +mirroring softwares. + +This is also true for all clients like: + +- `zc.buildout `_ +- `setuptools `_ +- `pip `_ +- etc. + +XXX user agent registering mechanism at PyPI ? + +How a client can use PyPI and its mirrors +::::::::::::::::::::::::::::::::::::::::: + +Clients that are browsing PyPI should be able to use +alternative mirrors, by reading the `/mirrors` page +at PyPI. + +The clients so far that could use this mechanism: + +- setuptools +- zc.buildout (through setuptools) +- pip + +Fail-over mechanism +::::::::::::::::::: + +Clients that are browsing PyPI should be able to use +a fail-over mechanism when PyPI or the used mirror +is not responding. + +This can be done by parsing the `/mirrors` page of PyPI +or the one located on any PyPI mirror. + +It is up to the client to decide wich mirror should +be used. Maybe by looking at its geographical location and +its responsivness. + +This PEP does not describe how this fail-over +mechanism should work, but it is strongly encouraged +that the clients try to use the nearest mirror. + +The clients so far that could use this mechanism: + +- setuptools +- zc.buildout (through setuptools) +- pip + +Extra package indexes +::::::::::::::::::::: + +It is obvious that some package will not be uploaded +to PyPI. Wether because they are private or wether because +the project maintainer runs his own server where people +might get the project package. Although, it is strongly +encouraged that a public package index follows PyPI +and Distutils protocols. + +In other words, the `register` and `upload` command +should be compatible with any package index server out +there. + +Softwares that are compatible with PyPI and Distutils so +far: + +- `PloneSoftwareCenter `_ + wich is used to run plone.org products section. +- `EggBasket `_ + +**An extra package index is not a mirror or PyPI but can have itself +some mirrors** + +Merging several indexes +::::::::::::::::::::::: + +When a client needs to get some packages from several +distinct indexes, it should be able to use each one of them +as a potential source of packages. Different indexes +should be defined as a sorted list for the client to +look for a package. + +Each independant index can of course provide a list of +its mirrors, if the `/mirrors` page is available. + +That permits all combinations at client level, for a reliable +packaging system with all levels of privacy. + +It is up the client to deal with the merging. + +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 Mar 21 15:35:24 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Mar 2009 14:35:24 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090321143525.461D71E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/532 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: hirokazu.yamamoto,mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Sat Mar 21 15:51:10 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Mar 2009 14:51:10 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090321145110.E8D731E403F@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/220 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: hirokazu.yamamoto BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From python-checkins at python.org Sat Mar 21 18:17:57 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 21 Mar 2009 18:17:57 +0100 (CET) Subject: [Python-checkins] r70506 - python/branches/py3k Message-ID: <20090321171757.A28201E4002@bag.python.org> Author: benjamin.peterson Date: Sat Mar 21 18:17:56 2009 New Revision: 70506 Log: Blocked revisions 70286,70290,70292-70293,70295-70296,70298,70300,70305,70315,70319,70466,70470,70472-70473,70475,70477,70479,70485 via svnmerge ........ r70286 | raymond.hettinger | 2009-03-09 19:06:05 -0500 (Mon, 09 Mar 2009) | 1 line Fix markup. ........ r70290 | raymond.hettinger | 2009-03-09 20:07:30 -0500 (Mon, 09 Mar 2009) | 1 line Update url for the spec. ........ r70292 | raymond.hettinger | 2009-03-09 23:40:24 -0500 (Mon, 09 Mar 2009) | 1 line Clarify the meaning of normal and subnormal. ........ r70293 | raymond.hettinger | 2009-03-09 23:49:21 -0500 (Mon, 09 Mar 2009) | 1 line Add a version tag to the decimal module. ........ r70295 | raymond.hettinger | 2009-03-10 03:16:05 -0500 (Tue, 10 Mar 2009) | 1 line Update the decimal FAQ for the from_float() classmethod and improve the recipe for remove_exponent() to make it cut and pasteable. ........ r70296 | raymond.hettinger | 2009-03-10 04:31:48 -0500 (Tue, 10 Mar 2009) | 1 line Small optimization for corner case where maxlen==0. ........ r70298 | raymond.hettinger | 2009-03-10 07:50:59 -0500 (Tue, 10 Mar 2009) | 1 line For collections.deque() objects, expose the maxlen parameter as a read-only attribute. ........ r70300 | raymond.hettinger | 2009-03-10 08:04:30 -0500 (Tue, 10 Mar 2009) | 1 line Fix typo. ........ r70305 | brett.cannon | 2009-03-10 23:51:06 -0500 (Tue, 10 Mar 2009) | 5 lines Require implementations for warnings.showwarning() support the 'line' argument. Was a DeprecationWarning for not supporting it since Python 2.6. Closes issue #3652. ........ r70315 | raymond.hettinger | 2009-03-11 19:25:03 -0500 (Wed, 11 Mar 2009) | 1 line Add reference to solution for a commonly asked question. ........ r70319 | raymond.hettinger | 2009-03-11 19:31:58 -0500 (Wed, 11 Mar 2009) | 1 line Issue 5477: Fix buglet in the itertools documentation. ........ r70466 | raymond.hettinger | 2009-03-18 17:13:20 -0500 (Wed, 18 Mar 2009) | 1 line Use mixin methods where possible. (2.7 only -- these don't all exist in 3.0) ........ r70470 | raymond.hettinger | 2009-03-19 10:21:10 -0500 (Thu, 19 Mar 2009) | 6 lines Improve implementation with better underlying data structure for O(1) deletions. Big-Oh performance now the same as regular dictionaries. Uses a doubly-linked list instead of a list/seq to track insertion order. ........ r70472 | raymond.hettinger | 2009-03-19 14:24:43 -0500 (Thu, 19 Mar 2009) | 1 line Silence a compiler warning. ........ r70473 | raymond.hettinger | 2009-03-19 14:59:58 -0500 (Thu, 19 Mar 2009) | 6 lines * Add clearer comment to initialization code. * Add optional argument to popitem() -- modeled after Anthon van der Neut's C version. * Fix method markup in docs. ........ r70475 | raymond.hettinger | 2009-03-19 18:12:41 -0500 (Thu, 19 Mar 2009) | 6 lines * Add implementation notes. * Re-order methods so that those touching the underlying data structure come first and the derived methods come last. ........ r70477 | raymond.hettinger | 2009-03-19 18:22:25 -0500 (Thu, 19 Mar 2009) | 1 line Fix typo ........ r70479 | mark.dickinson | 2009-03-20 10:51:55 -0500 (Fri, 20 Mar 2009) | 3 lines Issue #4258: Use 30-bit digits for Python longs, on 64-bit platforms. Backport of r70459. ........ r70485 | raymond.hettinger | 2009-03-20 13:25:49 -0500 (Fri, 20 Mar 2009) | 1 line Add MutableSet example. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Sat Mar 21 18:31:58 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 21 Mar 2009 18:31:58 +0100 (CET) Subject: [Python-checkins] r70507 - in python/branches/py3k: Doc/c-api/typeobj.rst Doc/howto/regex.rst Doc/library/contextlib.rst Doc/library/functions.rst Doc/library/idle.rst Doc/library/re.rst Doc/library/string.rst Doc/library/xml.dom.rst Doc/reference/datamodel.rst Lib/distutils/tests/test_msvc9compiler.py Lib/filecmp.py Modules/_codecsmodule.c Objects/tupleobject.c Objects/typeobject.c Message-ID: <20090321173158.8E6CF1E4002@bag.python.org> Author: benjamin.peterson Date: Sat Mar 21 18:31:58 2009 New Revision: 70507 Log: Merged revisions 70342,70385-70387,70389-70390,70392-70393,70395,70400,70405-70406,70418,70438,70464,70468 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70342 | georg.brandl | 2009-03-13 14:03:58 -0500 (Fri, 13 Mar 2009) | 1 line #5486: typos. ........ r70385 | benjamin.peterson | 2009-03-15 09:38:55 -0500 (Sun, 15 Mar 2009) | 1 line fix tuple.index() error message #5495 ........ r70386 | georg.brandl | 2009-03-15 16:32:06 -0500 (Sun, 15 Mar 2009) | 1 line #5496: fix docstring of lookup(). ........ r70387 | georg.brandl | 2009-03-15 16:37:16 -0500 (Sun, 15 Mar 2009) | 1 line #5493: clarify __nonzero__ docs. ........ r70389 | georg.brandl | 2009-03-15 16:43:38 -0500 (Sun, 15 Mar 2009) | 1 line Fix a small nit in the error message if bool() falls back on __len__ and it returns the wrong type: it would tell the user that __nonzero__ should return bool or int. ........ r70390 | georg.brandl | 2009-03-15 16:44:43 -0500 (Sun, 15 Mar 2009) | 1 line #5491: clarify nested() semantics. ........ r70392 | georg.brandl | 2009-03-15 16:46:00 -0500 (Sun, 15 Mar 2009) | 1 line #5488: add missing struct member. ........ r70393 | georg.brandl | 2009-03-15 16:47:42 -0500 (Sun, 15 Mar 2009) | 1 line #5478: fix copy-paste oversight in function signature. ........ r70395 | georg.brandl | 2009-03-15 16:51:48 -0500 (Sun, 15 Mar 2009) | 1 line #5276: document IDLESTARTUP and .Idle.py. ........ r70400 | georg.brandl | 2009-03-15 16:59:37 -0500 (Sun, 15 Mar 2009) | 3 lines Fix markup in re docs and give a mail address in regex howto, so that the recommendation to send suggestions to the author can be followed. ........ r70405 | georg.brandl | 2009-03-15 17:11:07 -0500 (Sun, 15 Mar 2009) | 7 lines Move the previously local import of threading to module level. This is cleaner and avoids lockups in obscure cases where a Queue is instantiated while the import lock is already held by another thread. OKed by Tim Peters. ........ r70406 | hirokazu.yamamoto | 2009-03-15 17:43:14 -0500 (Sun, 15 Mar 2009) | 1 line Added skip for old MSVC. ........ r70418 | georg.brandl | 2009-03-16 14:42:03 -0500 (Mon, 16 Mar 2009) | 1 line Add token markup. ........ r70438 | benjamin.peterson | 2009-03-17 15:29:51 -0500 (Tue, 17 Mar 2009) | 1 line I thought this was begging for an example ........ r70464 | benjamin.peterson | 2009-03-18 15:58:09 -0500 (Wed, 18 Mar 2009) | 1 line a much better example ........ r70468 | benjamin.peterson | 2009-03-18 22:04:31 -0500 (Wed, 18 Mar 2009) | 1 line close files after comparing them ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/c-api/typeobj.rst python/branches/py3k/Doc/howto/regex.rst python/branches/py3k/Doc/library/contextlib.rst python/branches/py3k/Doc/library/functions.rst python/branches/py3k/Doc/library/idle.rst python/branches/py3k/Doc/library/re.rst python/branches/py3k/Doc/library/string.rst python/branches/py3k/Doc/library/xml.dom.rst python/branches/py3k/Doc/reference/datamodel.rst python/branches/py3k/Lib/distutils/tests/test_msvc9compiler.py python/branches/py3k/Lib/filecmp.py python/branches/py3k/Modules/_codecsmodule.c python/branches/py3k/Objects/tupleobject.c python/branches/py3k/Objects/typeobject.c Modified: python/branches/py3k/Doc/c-api/typeobj.rst ============================================================================== --- python/branches/py3k/Doc/c-api/typeobj.rst (original) +++ python/branches/py3k/Doc/c-api/typeobj.rst Sat Mar 21 18:31:58 2009 @@ -1052,6 +1052,7 @@ binaryfunc nb_inplace_add; binaryfunc nb_inplace_subtract; binaryfunc nb_inplace_multiply; + binaryfunc nb_inplace_divide; binaryfunc nb_inplace_remainder; ternaryfunc nb_inplace_power; binaryfunc nb_inplace_lshift; Modified: python/branches/py3k/Doc/howto/regex.rst ============================================================================== --- python/branches/py3k/Doc/howto/regex.rst (original) +++ python/branches/py3k/Doc/howto/regex.rst Sat Mar 21 18:31:58 2009 @@ -4,7 +4,7 @@ Regular Expression HOWTO **************************** -:Author: A.M. Kuchling +:Author: A.M. Kuchling :Release: 0.05 .. TODO: Modified: python/branches/py3k/Doc/library/contextlib.rst ============================================================================== --- python/branches/py3k/Doc/library/contextlib.rst (original) +++ python/branches/py3k/Doc/library/contextlib.rst Sat Mar 21 18:31:58 2009 @@ -61,14 +61,15 @@ from contextlib import nested - with nested(A, B, C) as (X, Y, Z): + with nested(A(), B(), C()) as (X, Y, Z): do_something() is equivalent to this:: - with A as X: - with B as Y: - with C as Z: + m1, m2, m3 = A(), B(), C() + with m1 as X: + with m2 as Y: + with m3 as Z: do_something() Note that if the :meth:`__exit__` method of one of the nested context managers Modified: python/branches/py3k/Doc/library/functions.rst ============================================================================== --- python/branches/py3k/Doc/library/functions.rst (original) +++ python/branches/py3k/Doc/library/functions.rst Sat Mar 21 18:31:58 2009 @@ -561,6 +561,14 @@ its :meth:`__next__` method; if the value returned is equal to *sentinel*, :exc:`StopIteration` will be raised, otherwise the value will be returned. + One useful application of the second form of :func:`iter` is to read lines of + a file until a certain line is reached. The following example reads a file + until ``"STOP"`` is reached: :: + + with open("mydata.txt") as fp: + for line in iter(fp.readline, "STOP"): + process_line(line) + .. function:: len(s) Modified: python/branches/py3k/Doc/library/idle.rst ============================================================================== --- python/branches/py3k/Doc/library/idle.rst (original) +++ python/branches/py3k/Doc/library/idle.rst Sat Mar 21 18:31:58 2009 @@ -253,6 +253,24 @@ black +Startup +------- + +Upon startup with the ``-s`` option, IDLE will execute the file referenced by +the environment variables :envvar:`IDLESTARTUP` or :envvar:`PYTHONSTARTUP`. +Idle first checks for ``IDLESTARTUP``; if ``IDLESTARTUP`` is present the file +referenced is run. If ``IDLESTARTUP`` is not present, Idle checks for +``PYTHONSTARTUP``. Files referenced by these environment variables are +convenient places to store functions that are used frequently from the Idle +shell, or for executing import statements to import common modules. + +In addition, ``Tk`` also loads a startup file if it is present. Note that the +Tk file is loaded unconditionally. This additional file is ``.Idle.py`` and is +looked for in the user's home directory. Statements in this file will be +executed in the Tk namespace, so this file is not useful for importing functions +to be used from Idle's Python shell. + + Command line usage ^^^^^^^^^^^^^^^^^^ Modified: python/branches/py3k/Doc/library/re.rst ============================================================================== --- python/branches/py3k/Doc/library/re.rst (original) +++ python/branches/py3k/Doc/library/re.rst Sat Mar 21 18:31:58 2009 @@ -1127,7 +1127,7 @@ string)`` or ``re.search(pattern, string)``. :func:`match` has an optional second parameter that gives an index in the string -where the search is to start: +where the search is to start:: >>> pattern = re.compile("o") >>> pattern.match("dog") # No match as "o" is not at the start of "dog." Modified: python/branches/py3k/Doc/library/string.rst ============================================================================== --- python/branches/py3k/Doc/library/string.rst (original) +++ python/branches/py3k/Doc/library/string.rst Sat Mar 21 18:31:58 2009 @@ -196,7 +196,7 @@ .. productionlist:: sf replacement_field: "{" `field_name` ["!" `conversion`] [":" `format_spec`] "}" - field_name: (`identifier` | `integer`) ("." `attribute_name` | "[" element_index "]")* + field_name: (`identifier` | `integer`) ("." `attribute_name` | "[" `element_index` "]")* attribute_name: `identifier` element_index: `integer` conversion: "r" | "s" | "a" Modified: python/branches/py3k/Doc/library/xml.dom.rst ============================================================================== --- python/branches/py3k/Doc/library/xml.dom.rst (original) +++ python/branches/py3k/Doc/library/xml.dom.rst Sat Mar 21 18:31:58 2009 @@ -600,7 +600,7 @@ Same as equivalent method in the :class:`Document` class. -.. method:: Element.getElementsByTagNameNS(tagName) +.. method:: Element.getElementsByTagNameNS(namespaceURI, localName) Same as equivalent method in the :class:`Document` class. Modified: python/branches/py3k/Doc/reference/datamodel.rst ============================================================================== --- python/branches/py3k/Doc/reference/datamodel.rst (original) +++ python/branches/py3k/Doc/reference/datamodel.rst Sat Mar 21 18:31:58 2009 @@ -1251,11 +1251,12 @@ .. index:: single: __len__() (mapping object method) - Called to implement truth value testing, and the built-in operation ``bool()``; - should return ``False`` or ``True``. When this method is not defined, - :meth:`__len__` is called, if it is defined (see below) and ``True`` is returned - when the length is not zero. If a class defines neither :meth:`__len__` nor - :meth:`__bool__`, all its instances are considered true. + Called to implement truth value testing and the built-in operation + ``bool()``; should return ``False`` or ``True``, or their integer equivalents + ``0`` or ``1``. When this method is not defined, :meth:`__len__` is called, + if it is defined, and the object is considered true if its result is nonzero. + If a class defines neither :meth:`__len__` nor :meth:`__bool__`, all its + instances are considered true. .. _attribute-access: Modified: python/branches/py3k/Lib/distutils/tests/test_msvc9compiler.py ============================================================================== --- python/branches/py3k/Lib/distutils/tests/test_msvc9compiler.py (original) +++ python/branches/py3k/Lib/distutils/tests/test_msvc9compiler.py Sat Mar 21 18:31:58 2009 @@ -34,6 +34,10 @@ if sys.platform != 'win32': # this test is only for win32 return + from distutils.msvccompiler import get_build_version + if get_build_version() < 8.0: + # this test is only for MSVC8.0 or above + return from distutils.msvc9compiler import Reg self.assertRaises(KeyError, Reg.get_value, 'xxx', 'xxx') Modified: python/branches/py3k/Lib/filecmp.py ============================================================================== --- python/branches/py3k/Lib/filecmp.py (original) +++ python/branches/py3k/Lib/filecmp.py Sat Mar 21 18:31:58 2009 @@ -11,6 +11,7 @@ import os import stat +import contextlib from itertools import filterfalse __all__ = ["cmp","dircmp","cmpfiles"] @@ -62,15 +63,14 @@ def _do_cmp(f1, f2): bufsize = BUFSIZE - fp1 = open(f1, 'rb') - fp2 = open(f2, 'rb') - while True: - b1 = fp1.read(bufsize) - b2 = fp2.read(bufsize) - if b1 != b2: - return False - if not b1: - return True + with contextlib.nested(open(f1, 'rb'), open(f2, 'rb')) as (fp1, fp2): + while True: + b1 = fp1.read(bufsize) + b2 = fp2.read(bufsize) + if b1 != b2: + return False + if not b1: + return True # Directory comparison class. # Modified: python/branches/py3k/Modules/_codecsmodule.c ============================================================================== --- python/branches/py3k/Modules/_codecsmodule.c (original) +++ python/branches/py3k/Modules/_codecsmodule.c Sat Mar 21 18:31:58 2009 @@ -61,7 +61,7 @@ "lookup(encoding) -> CodecInfo\n\ \n\ Looks up a codec tuple in the Python codec registry and returns\n\ -a tuple of function (or a CodecInfo object)."); +a CodecInfo object."); static PyObject *codec_lookup(PyObject *self, PyObject *args) Modified: python/branches/py3k/Objects/tupleobject.c ============================================================================== --- python/branches/py3k/Objects/tupleobject.c (original) +++ python/branches/py3k/Objects/tupleobject.c Sat Mar 21 18:31:58 2009 @@ -458,7 +458,7 @@ else if (cmp < 0) return NULL; } - PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in list"); + PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in tuple"); return NULL; } Modified: python/branches/py3k/Objects/typeobject.c ============================================================================== --- python/branches/py3k/Objects/typeobject.c (original) +++ python/branches/py3k/Objects/typeobject.c Sat Mar 21 18:31:58 2009 @@ -4785,7 +4785,7 @@ PyObject *func, *args; static PyObject *bool_str, *len_str; int result = -1; - int from_len = 0; + int using_len = 0; func = lookup_maybe(self, "__bool__", &bool_str); if (func == NULL) { @@ -4794,14 +4794,14 @@ func = lookup_maybe(self, "__len__", &len_str); if (func == NULL) return PyErr_Occurred() ? -1 : 1; - from_len = 1; - } + using_len = 1; + } args = PyTuple_New(0); if (args != NULL) { PyObject *temp = PyObject_Call(func, args, NULL); Py_DECREF(args); if (temp != NULL) { - if (from_len) { + if (using_len) { /* enforced by slot_nb_len */ result = PyObject_IsTrue(temp); } @@ -4810,9 +4810,11 @@ } else { PyErr_Format(PyExc_TypeError, - "__bool__ should return " - "bool, returned %s", - Py_TYPE(temp)->tp_name); + "%s should return " + "bool or int, returned %s", + (using_len ? "__len__" + : "__bool__"), + Py_TYPE(temp)->tp_name); result = -1; } Py_DECREF(temp); From python-checkins at python.org Sat Mar 21 18:36:10 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 21 Mar 2009 18:36:10 +0100 (CET) Subject: [Python-checkins] r70508 - python/branches/py3k/Lib/queue.py Message-ID: <20090321173610.859241E4002@bag.python.org> Author: benjamin.peterson Date: Sat Mar 21 18:36:10 2009 New Revision: 70508 Log: port the queue change r70405 Modified: python/branches/py3k/Lib/queue.py Modified: python/branches/py3k/Lib/queue.py ============================================================================== --- python/branches/py3k/Lib/queue.py (original) +++ python/branches/py3k/Lib/queue.py Sat Mar 21 18:36:10 2009 @@ -1,6 +1,10 @@ """A multi-producer, multi-consumer queue.""" from time import time as _time +try: + import threading as _threading +except ImportError: + import dummy_threading as _threading from collections import deque import heapq @@ -20,26 +24,22 @@ If maxsize is <= 0, the queue size is infinite. """ def __init__(self, maxsize=0): - try: - import threading - except ImportError: - import dummy_threading as threading self.maxsize = maxsize self._init(maxsize) # mutex must be held whenever the queue is mutating. All methods # that acquire mutex must release it before returning. mutex # is shared between the three conditions, so acquiring and # releasing the conditions also acquires and releases mutex. - self.mutex = threading.Lock() + self.mutex = _threading.Lock() # Notify not_empty whenever an item is added to the queue; a # thread waiting to get is notified then. - self.not_empty = threading.Condition(self.mutex) + self.not_empty = _threading.Condition(self.mutex) # Notify not_full whenever an item is removed from the queue; # a thread waiting to put is notified then. - self.not_full = threading.Condition(self.mutex) + self.not_full = _threading.Condition(self.mutex) # Notify all_tasks_done whenever the number of unfinished tasks # drops to zero; thread waiting to join() is notified to resume - self.all_tasks_done = threading.Condition(self.mutex) + self.all_tasks_done = _threading.Condition(self.mutex) self.unfinished_tasks = 0 def task_done(self): From python-checkins at python.org Sat Mar 21 18:44:11 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 21 Mar 2009 18:44:11 +0100 (CET) Subject: [Python-checkins] r70509 - in python/branches/release30-maint: Doc/c-api/typeobj.rst Doc/howto/regex.rst Doc/library/contextlib.rst Doc/library/functions.rst Doc/library/idle.rst Doc/library/re.rst Doc/library/string.rst Doc/library/xml.dom.rst Doc/reference/datamodel.rst Lib/filecmp.py Lib/queue.py Modules/_codecsmodule.c Objects/tupleobject.c Objects/typeobject.c Message-ID: <20090321174411.7483B1E4002@bag.python.org> Author: benjamin.peterson Date: Sat Mar 21 18:44:10 2009 New Revision: 70509 Log: Merged revisions 70507-70508 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70507 | benjamin.peterson | 2009-03-21 12:31:58 -0500 (Sat, 21 Mar 2009) | 75 lines Merged revisions 70342,70385-70387,70389-70390,70392-70393,70395,70400,70405-70406,70418,70438,70464,70468 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70342 | georg.brandl | 2009-03-13 14:03:58 -0500 (Fri, 13 Mar 2009) | 1 line #5486: typos. ........ r70385 | benjamin.peterson | 2009-03-15 09:38:55 -0500 (Sun, 15 Mar 2009) | 1 line fix tuple.index() error message #5495 ........ r70386 | georg.brandl | 2009-03-15 16:32:06 -0500 (Sun, 15 Mar 2009) | 1 line #5496: fix docstring of lookup(). ........ r70387 | georg.brandl | 2009-03-15 16:37:16 -0500 (Sun, 15 Mar 2009) | 1 line #5493: clarify __nonzero__ docs. ........ r70389 | georg.brandl | 2009-03-15 16:43:38 -0500 (Sun, 15 Mar 2009) | 1 line Fix a small nit in the error message if bool() falls back on __len__ and it returns the wrong type: it would tell the user that __nonzero__ should return bool or int. ........ r70390 | georg.brandl | 2009-03-15 16:44:43 -0500 (Sun, 15 Mar 2009) | 1 line #5491: clarify nested() semantics. ........ r70392 | georg.brandl | 2009-03-15 16:46:00 -0500 (Sun, 15 Mar 2009) | 1 line #5488: add missing struct member. ........ r70393 | georg.brandl | 2009-03-15 16:47:42 -0500 (Sun, 15 Mar 2009) | 1 line #5478: fix copy-paste oversight in function signature. ........ r70395 | georg.brandl | 2009-03-15 16:51:48 -0500 (Sun, 15 Mar 2009) | 1 line #5276: document IDLESTARTUP and .Idle.py. ........ r70400 | georg.brandl | 2009-03-15 16:59:37 -0500 (Sun, 15 Mar 2009) | 3 lines Fix markup in re docs and give a mail address in regex howto, so that the recommendation to send suggestions to the author can be followed. ........ r70405 | georg.brandl | 2009-03-15 17:11:07 -0500 (Sun, 15 Mar 2009) | 7 lines Move the previously local import of threading to module level. This is cleaner and avoids lockups in obscure cases where a Queue is instantiated while the import lock is already held by another thread. OKed by Tim Peters. ........ r70406 | hirokazu.yamamoto | 2009-03-15 17:43:14 -0500 (Sun, 15 Mar 2009) | 1 line Added skip for old MSVC. ........ r70418 | georg.brandl | 2009-03-16 14:42:03 -0500 (Mon, 16 Mar 2009) | 1 line Add token markup. ........ r70438 | benjamin.peterson | 2009-03-17 15:29:51 -0500 (Tue, 17 Mar 2009) | 1 line I thought this was begging for an example ........ r70464 | benjamin.peterson | 2009-03-18 15:58:09 -0500 (Wed, 18 Mar 2009) | 1 line a much better example ........ r70468 | benjamin.peterson | 2009-03-18 22:04:31 -0500 (Wed, 18 Mar 2009) | 1 line close files after comparing them ........ ................ r70508 | benjamin.peterson | 2009-03-21 12:36:10 -0500 (Sat, 21 Mar 2009) | 1 line port the queue change r70405 ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Doc/c-api/typeobj.rst python/branches/release30-maint/Doc/howto/regex.rst python/branches/release30-maint/Doc/library/contextlib.rst python/branches/release30-maint/Doc/library/functions.rst python/branches/release30-maint/Doc/library/idle.rst python/branches/release30-maint/Doc/library/re.rst python/branches/release30-maint/Doc/library/string.rst python/branches/release30-maint/Doc/library/xml.dom.rst python/branches/release30-maint/Doc/reference/datamodel.rst python/branches/release30-maint/Lib/filecmp.py python/branches/release30-maint/Lib/queue.py python/branches/release30-maint/Modules/_codecsmodule.c python/branches/release30-maint/Objects/tupleobject.c python/branches/release30-maint/Objects/typeobject.c Modified: python/branches/release30-maint/Doc/c-api/typeobj.rst ============================================================================== --- python/branches/release30-maint/Doc/c-api/typeobj.rst (original) +++ python/branches/release30-maint/Doc/c-api/typeobj.rst Sat Mar 21 18:44:10 2009 @@ -1052,6 +1052,7 @@ binaryfunc nb_inplace_add; binaryfunc nb_inplace_subtract; binaryfunc nb_inplace_multiply; + binaryfunc nb_inplace_divide; binaryfunc nb_inplace_remainder; ternaryfunc nb_inplace_power; binaryfunc nb_inplace_lshift; Modified: python/branches/release30-maint/Doc/howto/regex.rst ============================================================================== --- python/branches/release30-maint/Doc/howto/regex.rst (original) +++ python/branches/release30-maint/Doc/howto/regex.rst Sat Mar 21 18:44:10 2009 @@ -4,7 +4,7 @@ Regular Expression HOWTO **************************** -:Author: A.M. Kuchling +:Author: A.M. Kuchling :Release: 0.05 .. TODO: Modified: python/branches/release30-maint/Doc/library/contextlib.rst ============================================================================== --- python/branches/release30-maint/Doc/library/contextlib.rst (original) +++ python/branches/release30-maint/Doc/library/contextlib.rst Sat Mar 21 18:44:10 2009 @@ -61,14 +61,15 @@ from contextlib import nested - with nested(A, B, C) as (X, Y, Z): + with nested(A(), B(), C()) as (X, Y, Z): do_something() is equivalent to this:: - with A as X: - with B as Y: - with C as Z: + m1, m2, m3 = A(), B(), C() + with m1 as X: + with m2 as Y: + with m3 as Z: do_something() Note that if the :meth:`__exit__` method of one of the nested context managers Modified: python/branches/release30-maint/Doc/library/functions.rst ============================================================================== --- python/branches/release30-maint/Doc/library/functions.rst (original) +++ python/branches/release30-maint/Doc/library/functions.rst Sat Mar 21 18:44:10 2009 @@ -560,6 +560,14 @@ its :meth:`__next__` method; if the value returned is equal to *sentinel*, :exc:`StopIteration` will be raised, otherwise the value will be returned. + One useful application of the second form of :func:`iter` is to read lines of + a file until a certain line is reached. The following example reads a file + until ``"STOP"`` is reached: :: + + with open("mydata.txt") as fp: + for line in iter(fp.readline, "STOP"): + process_line(line) + .. function:: len(s) Modified: python/branches/release30-maint/Doc/library/idle.rst ============================================================================== --- python/branches/release30-maint/Doc/library/idle.rst (original) +++ python/branches/release30-maint/Doc/library/idle.rst Sat Mar 21 18:44:10 2009 @@ -253,6 +253,24 @@ black +Startup +------- + +Upon startup with the ``-s`` option, IDLE will execute the file referenced by +the environment variables :envvar:`IDLESTARTUP` or :envvar:`PYTHONSTARTUP`. +Idle first checks for ``IDLESTARTUP``; if ``IDLESTARTUP`` is present the file +referenced is run. If ``IDLESTARTUP`` is not present, Idle checks for +``PYTHONSTARTUP``. Files referenced by these environment variables are +convenient places to store functions that are used frequently from the Idle +shell, or for executing import statements to import common modules. + +In addition, ``Tk`` also loads a startup file if it is present. Note that the +Tk file is loaded unconditionally. This additional file is ``.Idle.py`` and is +looked for in the user's home directory. Statements in this file will be +executed in the Tk namespace, so this file is not useful for importing functions +to be used from Idle's Python shell. + + Command line usage ^^^^^^^^^^^^^^^^^^ Modified: python/branches/release30-maint/Doc/library/re.rst ============================================================================== --- python/branches/release30-maint/Doc/library/re.rst (original) +++ python/branches/release30-maint/Doc/library/re.rst Sat Mar 21 18:44:10 2009 @@ -1114,7 +1114,7 @@ string)`` or ``re.search(pattern, string)``. :func:`match` has an optional second parameter that gives an index in the string -where the search is to start: +where the search is to start:: >>> pattern = re.compile("o") >>> pattern.match("dog") # No match as "o" is not at the start of "dog." Modified: python/branches/release30-maint/Doc/library/string.rst ============================================================================== --- python/branches/release30-maint/Doc/library/string.rst (original) +++ python/branches/release30-maint/Doc/library/string.rst Sat Mar 21 18:44:10 2009 @@ -196,7 +196,7 @@ .. productionlist:: sf replacement_field: "{" `field_name` ["!" `conversion`] [":" `format_spec`] "}" - field_name: (`identifier` | `integer`) ("." `attribute_name` | "[" element_index "]")* + field_name: (`identifier` | `integer`) ("." `attribute_name` | "[" `element_index` "]")* attribute_name: `identifier` element_index: `integer` conversion: "r" | "s" | "a" Modified: python/branches/release30-maint/Doc/library/xml.dom.rst ============================================================================== --- python/branches/release30-maint/Doc/library/xml.dom.rst (original) +++ python/branches/release30-maint/Doc/library/xml.dom.rst Sat Mar 21 18:44:10 2009 @@ -600,7 +600,7 @@ Same as equivalent method in the :class:`Document` class. -.. method:: Element.getElementsByTagNameNS(tagName) +.. method:: Element.getElementsByTagNameNS(namespaceURI, localName) Same as equivalent method in the :class:`Document` class. Modified: python/branches/release30-maint/Doc/reference/datamodel.rst ============================================================================== --- python/branches/release30-maint/Doc/reference/datamodel.rst (original) +++ python/branches/release30-maint/Doc/reference/datamodel.rst Sat Mar 21 18:44:10 2009 @@ -1248,11 +1248,12 @@ .. index:: single: __len__() (mapping object method) - Called to implement truth value testing, and the built-in operation ``bool()``; - should return ``False`` or ``True``. When this method is not defined, - :meth:`__len__` is called, if it is defined (see below) and ``True`` is returned - when the length is not zero. If a class defines neither :meth:`__len__` nor - :meth:`__bool__`, all its instances are considered true. + Called to implement truth value testing and the built-in operation + ``bool()``; should return ``False`` or ``True``, or their integer equivalents + ``0`` or ``1``. When this method is not defined, :meth:`__len__` is called, + if it is defined, and the object is considered true if its result is nonzero. + If a class defines neither :meth:`__len__` nor :meth:`__bool__`, all its + instances are considered true. .. _attribute-access: Modified: python/branches/release30-maint/Lib/filecmp.py ============================================================================== --- python/branches/release30-maint/Lib/filecmp.py (original) +++ python/branches/release30-maint/Lib/filecmp.py Sat Mar 21 18:44:10 2009 @@ -11,6 +11,7 @@ import os import stat +import contextlib from itertools import filterfalse __all__ = ["cmp","dircmp","cmpfiles"] @@ -62,15 +63,14 @@ def _do_cmp(f1, f2): bufsize = BUFSIZE - fp1 = open(f1, 'rb') - fp2 = open(f2, 'rb') - while True: - b1 = fp1.read(bufsize) - b2 = fp2.read(bufsize) - if b1 != b2: - return False - if not b1: - return True + with contextlib.nested(open(f1, 'rb'), open(f2, 'rb')) as (fp1, fp2): + while True: + b1 = fp1.read(bufsize) + b2 = fp2.read(bufsize) + if b1 != b2: + return False + if not b1: + return True # Directory comparison class. # Modified: python/branches/release30-maint/Lib/queue.py ============================================================================== --- python/branches/release30-maint/Lib/queue.py (original) +++ python/branches/release30-maint/Lib/queue.py Sat Mar 21 18:44:10 2009 @@ -1,6 +1,10 @@ """A multi-producer, multi-consumer queue.""" from time import time as _time +try: + import threading as _threading +except ImportError: + import dummy_threading as _threading from collections import deque import heapq @@ -20,26 +24,22 @@ If maxsize is <= 0, the queue size is infinite. """ def __init__(self, maxsize=0): - try: - import threading - except ImportError: - import dummy_threading as threading self.maxsize = maxsize self._init(maxsize) # mutex must be held whenever the queue is mutating. All methods # that acquire mutex must release it before returning. mutex # is shared between the three conditions, so acquiring and # releasing the conditions also acquires and releases mutex. - self.mutex = threading.Lock() + self.mutex = _threading.Lock() # Notify not_empty whenever an item is added to the queue; a # thread waiting to get is notified then. - self.not_empty = threading.Condition(self.mutex) + self.not_empty = _threading.Condition(self.mutex) # Notify not_full whenever an item is removed from the queue; # a thread waiting to put is notified then. - self.not_full = threading.Condition(self.mutex) + self.not_full = _threading.Condition(self.mutex) # Notify all_tasks_done whenever the number of unfinished tasks # drops to zero; thread waiting to join() is notified to resume - self.all_tasks_done = threading.Condition(self.mutex) + self.all_tasks_done = _threading.Condition(self.mutex) self.unfinished_tasks = 0 def task_done(self): Modified: python/branches/release30-maint/Modules/_codecsmodule.c ============================================================================== --- python/branches/release30-maint/Modules/_codecsmodule.c (original) +++ python/branches/release30-maint/Modules/_codecsmodule.c Sat Mar 21 18:44:10 2009 @@ -61,7 +61,7 @@ "lookup(encoding) -> CodecInfo\n\ \n\ Looks up a codec tuple in the Python codec registry and returns\n\ -a tuple of function (or a CodecInfo object)."); +a CodecInfo object."); static PyObject *codec_lookup(PyObject *self, PyObject *args) Modified: python/branches/release30-maint/Objects/tupleobject.c ============================================================================== --- python/branches/release30-maint/Objects/tupleobject.c (original) +++ python/branches/release30-maint/Objects/tupleobject.c Sat Mar 21 18:44:10 2009 @@ -458,7 +458,7 @@ else if (cmp < 0) return NULL; } - PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in list"); + PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in tuple"); return NULL; } Modified: python/branches/release30-maint/Objects/typeobject.c ============================================================================== --- python/branches/release30-maint/Objects/typeobject.c (original) +++ python/branches/release30-maint/Objects/typeobject.c Sat Mar 21 18:44:10 2009 @@ -4785,7 +4785,7 @@ PyObject *func, *args; static PyObject *bool_str, *len_str; int result = -1; - int from_len = 0; + int using_len = 0; func = lookup_maybe(self, "__bool__", &bool_str); if (func == NULL) { @@ -4794,14 +4794,14 @@ func = lookup_maybe(self, "__len__", &len_str); if (func == NULL) return PyErr_Occurred() ? -1 : 1; - from_len = 1; - } + using_len = 1; + } args = PyTuple_New(0); if (args != NULL) { PyObject *temp = PyObject_Call(func, args, NULL); Py_DECREF(args); if (temp != NULL) { - if (from_len) { + if (using_len) { /* enforced by slot_nb_len */ result = PyObject_IsTrue(temp); } @@ -4810,9 +4810,11 @@ } else { PyErr_Format(PyExc_TypeError, - "__bool__ should return " - "bool, returned %s", - Py_TYPE(temp)->tp_name); + "%s should return " + "bool or int, returned %s", + (using_len ? "__len__" + : "__bool__"), + Py_TYPE(temp)->tp_name); result = -1; } Py_DECREF(temp); From python-checkins at python.org Sat Mar 21 18:50:00 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 21 Mar 2009 18:50:00 +0100 (CET) Subject: [Python-checkins] r70510 - python/branches/py3k Message-ID: <20090321175000.1B0751E4002@bag.python.org> Author: benjamin.peterson Date: Sat Mar 21 18:49:59 2009 New Revision: 70510 Log: Blocked revisions 70463 via svnmerge ........ r70463 | benjamin.peterson | 2009-03-18 15:52:15 -0500 (Wed, 18 Mar 2009) | 1 line fix strange errors when setting attributes on tracebacks #4034 ........ Modified: python/branches/py3k/ (props changed) From buildbot at python.org Sat Mar 21 19:09:28 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Mar 2009 18:09:28 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090321180928.C520C1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/499 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Sat Mar 21 19:35:56 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 21 Mar 2009 18:35:56 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.0 Message-ID: <20090321183556.89F441E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.0/builds/217 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_asynchat make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sat Mar 21 19:56:40 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sat, 21 Mar 2009 19:56:40 +0100 (CET) Subject: [Python-checkins] r70511 - tracker/instances/meta/html/page.html Message-ID: <20090321185640.8B0F91E4002@bag.python.org> Author: martin.v.loewis Date: Sat Mar 21 19:56:39 2009 New Revision: 70511 Log: Don't put query parameters into the submit button. Modified: tracker/instances/meta/html/page.html Modified: tracker/instances/meta/html/page.html ============================================================================== --- tracker/instances/meta/html/page.html (original) +++ tracker/instances/meta/html/page.html Sat Mar 21 19:56:39 2009 @@ -39,7 +39,7 @@ - + From python-checkins at python.org Sat Mar 21 20:22:29 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sat, 21 Mar 2009 20:22:29 +0100 (CET) Subject: [Python-checkins] r70512 - tracker/instances/python-dev/schema.py Message-ID: <20090321192229.9B2CF1E4002@bag.python.org> Author: martin.v.loewis Date: Sat Mar 21 20:22:28 2009 New Revision: 70512 Log: Issue #252: allow editing of organization again. Modified: tracker/instances/python-dev/schema.py Modified: tracker/instances/python-dev/schema.py ============================================================================== --- tracker/instances/python-dev/schema.py (original) +++ tracker/instances/python-dev/schema.py Sat Mar 21 20:22:28 2009 @@ -298,7 +298,7 @@ description="User is allowed to edit their own user details", properties=('username', 'password', 'address', 'realname', - 'phone', 'organization', + 'phone', 'organisation', 'alternate_addresses', 'queries', 'timezone')) # Note: 'roles' excluded - users should not be able to edit their own roles. From python-checkins at python.org Sat Mar 21 20:22:52 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sat, 21 Mar 2009 20:22:52 +0100 (CET) Subject: [Python-checkins] r70513 - tracker/instances/jython/schema.py Message-ID: <20090321192252.0270D1E4002@bag.python.org> Author: martin.v.loewis Date: Sat Mar 21 20:22:51 2009 New Revision: 70513 Log: Issue #252: allow editing of organization again. Modified: tracker/instances/jython/schema.py Modified: tracker/instances/jython/schema.py ============================================================================== --- tracker/instances/jython/schema.py (original) +++ tracker/instances/jython/schema.py Sat Mar 21 20:22:51 2009 @@ -274,7 +274,7 @@ description="User is allowed to edit their own user details", properties=('username', 'password', 'address', 'realname', - 'phone', 'organization', + 'phone', 'organisation', 'alternate_addresses', 'queries', 'timezone')) # Note: 'roles' excluded - users should not be able to edit their own roles. From python-checkins at python.org Sat Mar 21 20:31:34 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sat, 21 Mar 2009 20:31:34 +0100 (CET) Subject: [Python-checkins] r70514 - tracker/instances/python-dev/html/page.html Message-ID: <20090321193134.B89BA1E4002@bag.python.org> Author: martin.v.loewis Date: Sat Mar 21 20:31:33 2009 New Revision: 70514 Log: Issue #224: Add radio button to search box for authenticated users. Modified: tracker/instances/python-dev/html/page.html Modified: tracker/instances/python-dev/html/page.html ============================================================================== --- tracker/instances/python-dev/html/page.html (original) +++ tracker/instances/python-dev/html/page.html Sat Mar 21 20:31:33 2009 @@ -1,6 +1,6 @@ - + title goes here @@ -23,6 +23,7 @@ columns string:id,activity,title,creator,status; columns_showall string:id,activity,title,creator,assignee,status,type; status_notresolved string:-1,1,3; +status_all string:-1,1,2,3; ">

        @@ -42,10 +43,23 @@ - - + + + + + + + + + + + From python-checkins at python.org Sat Mar 21 20:34:45 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sat, 21 Mar 2009 20:34:45 +0100 (CET) Subject: [Python-checkins] r70515 - in tracker/instances/python-dev/html: issue.index.html issue.item.html issue.search.html Message-ID: <20090321193445.B52511E4002@bag.python.org> Author: martin.v.loewis Date: Sat Mar 21 20:34:44 2009 New Revision: 70515 Log: Issue #251: Allow searching for message and nosy counts. Modified: tracker/instances/python-dev/html/issue.index.html tracker/instances/python-dev/html/issue.item.html tracker/instances/python-dev/html/issue.search.html Modified: tracker/instances/python-dev/html/issue.index.html ============================================================================== --- tracker/instances/python-dev/html/issue.index.html (original) +++ tracker/instances/python-dev/html/issue.index.html Sat Mar 21 20:34:44 2009 @@ -40,6 +40,7 @@ Depends On Type Msgs + Nosy     +   Modified: tracker/instances/python-dev/html/issue.item.html ============================================================================== --- tracker/instances/python-dev/html/issue.item.html (original) +++ tracker/instances/python-dev/html/issue.item.html Sat Mar 21 20:34:44 2009 @@ -135,7 +135,8 @@ tal:replace="structure python:db.user.classhelp('username,realname,address', property='nosy')" /> - + + @@ -226,7 +227,9 @@ - + + + + + + + + + + + + + + + + From python-checkins at python.org Sat Mar 21 22:23:42 2009 From: python-checkins at python.org (martin.v.loewis) Date: Sat, 21 Mar 2009 22:23:42 +0100 (CET) Subject: [Python-checkins] r70516 - tracker/instances/python-dev/html/issue.item.html Message-ID: <20090321212342.7E3901E4002@bag.python.org> Author: martin.v.loewis Date: Sat Mar 21 22:23:42 2009 New Revision: 70516 Log: Issue #251: Don't try to print nosy_count for new issues. Modified: tracker/instances/python-dev/html/issue.item.html Modified: tracker/instances/python-dev/html/issue.item.html ============================================================================== --- tracker/instances/python-dev/html/issue.item.html (original) +++ tracker/instances/python-dev/html/issue.item.html Sat Mar 21 22:23:42 2009 @@ -136,7 +136,7 @@ From g.brandl at gmx.net Sun Mar 22 09:49:09 2009 From: g.brandl at gmx.net (Georg Brandl) Date: Sun, 22 Mar 2009 08:49:09 +0000 Subject: [Python-checkins] r70495 - in python/branches/py3k: Doc/glossary.rst Doc/library/sys.rst Doc/reference/simple_stmts.rst Lib/importlib/NOTES In-Reply-To: <20090321031116.A59951E4002@bag.python.org> References: <20090321031116.A59951E4002@bag.python.org> Message-ID: brett.cannon schrieb: > Author: brett.cannon > Date: Sat Mar 21 04:11:16 2009 > New Revision: 70495 > > Log: > Document import's semantics for the language reference. This includes filling > in missing details for the sys module. Many thanks for this! 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 Sun Mar 22 10:01:47 2009 From: python-checkins at python.org (georg.brandl) Date: Sun, 22 Mar 2009 10:01:47 +0100 (CET) Subject: [Python-checkins] r70517 - peps/trunk/pep-0381.txt Message-ID: <20090322090147.521F31E4002@bag.python.org> Author: georg.brandl Date: Sun Mar 22 10:01:46 2009 New Revision: 70517 Log: Fix number and edit PEP a bit for clarity. Modified: peps/trunk/pep-0381.txt Modified: peps/trunk/pep-0381.txt ============================================================================== --- peps/trunk/pep-0381.txt (original) +++ peps/trunk/pep-0381.txt Sun Mar 22 10:01:46 2009 @@ -1,4 +1,4 @@ -PEP: 376 +PEP: 381 Title: Mirroring infrastructure for PyPI Version: $Revision$ Last-Modified: $Date$ @@ -15,38 +15,38 @@ This PEP describes a mirroring infrastructure for PyPI. + Rationale ========= -PyPI is hosting over 4000 projects and is used on a daily basis -by people to build applications. Especially systems like `easy_install` +PyPI is hosting over 4000 projects and is used on a daily basis by +people to build applications. Especially systems like `easy_install` and `zc.buildout` make intensive usage of PyPI. For people making intensive use of PyPI, it can act as a single point -of failure. People have started to set up some mirrors, both private and -public. Those mirrors are active mirrors, which means that they are -browsing PyPI to get synced. +of failure. People have started to set up some mirrors, both private +and public. Those mirrors are active mirrors, which means that they +are browsing PyPI to get synced. In order to make the system more reliable, this PEP describes: -- the mirror listing and registering at PyPI -- the pages a public mirror should maintain. - these pages will be used by PyPI, in order to get - hit counts and the last modified date. +- the mirror listing and registering at PyPI +- the pages a public mirror should maintain. These pages will be used + by PyPI, in order to get hit counts and the last modified date. - how a mirror should synchronize with PyPI - how a client can implement a fail-over mechanism - a contact form for Package maintainers + Mirror listing and registering ============================== -A new text page will be added at `http://pypi.python.org/mirrors` -that can be browsed like the simple index. This page gives a list of -the mirrors through a list of links. - -These links are the URL of the simple index of each mirror. -The page will look like this:: +A new text page will be added at http://pypi.python.org/mirrors that +can be browsed like the simple index. This page gives a list of the +mirrors through a list of links. +These links are the URL of the simple index of each mirror. The page +will look like this:: # PyPI mirrors # @@ -73,15 +73,16 @@ http://example.com/pypi,index,last-modified,local-stats,stats,mirrors http://example2.com/pypi,index,last-modified,local-stats,stats,mirrors -When a mirror is proposed on the mailing list, it is manually -added in the mirror list in the PyPI application after it -has been checked to be compliant with the mirroring rules. - -The mirror list page is a simple text page that can be browsed -by any tool that wants to get a list of registered mirrors. -Other package indexes that are not mirrors of PyPI are not added in the -mirror list in PyPI. Although they can provide themselve the -same mirroring list mechanism for their own mirrors. +When a mirror is proposed on the mailing list, it is manually added in +the mirror list in the PyPI application after it has been checked to +be compliant with the mirroring rules. + +The mirror list page is a simple text page that can be browsed by any +tool that wants to get a list of registered mirrors. Other package +indexes that are not mirrors of PyPI are not added in the mirror list +in PyPI, although they can provide themselve the same mirroring list +mechanism for their own mirrors. + Special pages a mirror needs to provide ======================================= @@ -96,35 +97,36 @@ Last modified date :::::::::::::::::: -CPAN uses a freshness date system where the mirror last synchronisation -date is made available. +CPAN uses a freshness date system where the mirror's last +synchronisation date is made available. -For PyPI, each mirror needs to maintain an url with a simple text content +For PyPI, each mirror needs to maintain a URL with simple text content that represents the last synchronisation date the mirror maintains. -The date is provided in GMT time, using the ISO 8601 format -(see http://en.wikipedia.org/wiki/ISO_8601) +The date is provided in GMT time, using the ISO 8601 format (see +http://en.wikipedia.org/wiki/ISO_8601). -Each mirror will be responsible to maintain its last modified date. +Each mirror will be responsible to maintain its last modified date. -Conventionaly, this page should be reachable at: `/last-modified`. +Conventionally, this page should be reachable at: `/last-modified`. Local statistics :::::::::::::::: -Each mirror is responsible to count all the downloads -that where done on it. This is used by PyPI to sum up all -downloads, to be able to display the grand total. - -These statistics are in csv-like form, with a header at the first -line. It needs to obey `PEP 305 `_ -Basically, it should be readable by Python `csv` module. +Each mirror is responsible to count all the downloads that where done +via it. This is used by PyPI to sum up all downloads, to be able to +display the grand total. + +These statistics are in CSV-like form, with a header in the first +line. It needs to obey PEP 305 [#pep305]_. Basically, it should be +readable by Python's `csv` module. The fields in this file are: - package: the distutils id of the package. - filename: the filename that has been downloaded. -- useragent: the User-Agent of the client that has downloaded the package. +- useragent: the User-Agent of the client that has downloaded the + package. - count: the number of downloads. The content will look like this:: @@ -133,9 +135,10 @@ zc.buildout,zc.buildout-1.6.0.tgz,MyAgent,142 ... -The counting starts the day the mirror is launched, and there is one file per -day, compressed using the `bzip2` format. Each file is named after the -day. For example `2008-11-06.bz2` is the file for the 6th of November 2008. +The counting starts the day the mirror is launched, and there is one +file per day, compressed using the `bzip2` format. Each file is named +like the day. For example `2008-11-06.bz2` is the file for the 6th of +November 2008. They are then provided in a folder called `days`. For example: @@ -143,21 +146,21 @@ - /local-stats/days/2008-11-07.bz2 - /local-stats/days/2008-11-08.bz2 -Conventionally the name should be `local-stats` but it can be any name -provided when the mirror is registered. +Conventionally the name should be `local-stats`, but it can be any +name provided when the mirror is registered. Statistics page ::::::::::::::: -PyPI and each mirror are responsible to provide the grand total -page at `/stats`. This page is calculated daily by PyPI, -by reading all mirrors local stats and suming them. +PyPI and each mirror are responsible to provide the grand total page +at `/stats`. This page is calculated daily by PyPI, by reading all +mirrors' local stats and summing them. -Therefore the mirrors should not try to rebuild this stat page but simply -get PyPI's one during each synchronization. +Therefore the mirrors should not try to rebuild this stat page but +simply get the one on PyPI during each synchronization. -It has the same structure than `local-stats` but also provides -counts for months. +It has the same structure as `local-stats` but also provides counts +for months. Examples: @@ -167,42 +170,42 @@ - /stats/months/2008-11.bz2 - /stats/months/2008-10.bz2 -Conventionally the name should be `stats` but it can be any name +Conventionally the name should be `stats`, but it can be any name provided when the mirror is registered. Mirrors listing page :::::::::::::::::::: -Like `/stats`, each mirror should get and provide a copy of the `/mirrors` -page. +Like `/stats`, each mirror should get and provide a copy of the +`/mirrors` page. -Conventionally the name should be `mirrors` but it can be any name +Conventionally the name should be `mirrors`, but it can be any name provided when the mirror is registered. + How a mirror should synchronize with PyPI ========================================= -A mirroring protocol calls `Simple Index` was described -and implemented by Martin v. Loewis and Jim Fulton, based on -how `easy_install` works. This section synthesizes it -and give a few relevant links, plus a small part about -`User-Agent`. +A mirroring protocol called `Simple Index` was described and +implemented by Martin v. Loewis and Jim Fulton, based on how +`easy_install` works. This section synthesizes it and gives a few +relevant links, plus a small part about `User-Agent`. The mirroring protocol :::::::::::::::::::::: XXX Need to describe the protocol here. -The `zc.pypimirror `_ package -provides an application that respects this protocol to browse PyPI. +The zc.pypimirror package [#zcpkg]_ provides an application that +respects this protocol to browse PyPI. User-agent request header ::::::::::::::::::::::::: -In order to be able to differentiate actions taken by clients -over PyPI, a specific user agent name should be provided by all -mirroring softwares. +In order to be able to differentiate actions taken by clients over +PyPI, a specific user agent name should be provided by all mirroring +softwares. This is also true for all clients like: @@ -216,9 +219,8 @@ How a client can use PyPI and its mirrors ::::::::::::::::::::::::::::::::::::::::: -Clients that are browsing PyPI should be able to use -alternative mirrors, by reading the `/mirrors` page -at PyPI. +Clients that are browsing PyPI should be able to use alternative +mirrors, by reading the `/mirrors` page at PyPI. The clients so far that could use this mechanism: @@ -229,20 +231,18 @@ Fail-over mechanism ::::::::::::::::::: -Clients that are browsing PyPI should be able to use -a fail-over mechanism when PyPI or the used mirror -is not responding. - -This can be done by parsing the `/mirrors` page of PyPI -or the one located on any PyPI mirror. - -It is up to the client to decide wich mirror should -be used. Maybe by looking at its geographical location and -its responsivness. - -This PEP does not describe how this fail-over -mechanism should work, but it is strongly encouraged -that the clients try to use the nearest mirror. +Clients that are browsing PyPI should be able to use a fail-over +mechanism when PyPI or the used mirror is not responding. + +This can be done by parsing the `/mirrors` page of PyPI or the one +located on any PyPI mirror. + +It is up to the client to decide wich mirror should be used, maybe by +looking at its geographical location and its responsivness. + +This PEP does not describe how this fail-over mechanism should work, +but it is strongly encouraged that the clients try to use the nearest +mirror. The clients so far that could use this mechanism: @@ -253,44 +253,51 @@ Extra package indexes ::::::::::::::::::::: -It is obvious that some package will not be uploaded -to PyPI. Wether because they are private or wether because -the project maintainer runs his own server where people -might get the project package. Although, it is strongly -encouraged that a public package index follows PyPI -and Distutils protocols. - -In other words, the `register` and `upload` command -should be compatible with any package index server out -there. +It is obvious that some packages will not be uploaded to PyPI, whether +because they are private or whether because the project maintainer +runs his own server where people might get the project package. +However, it is strongly encouraged that a public package index follows +PyPI and Distutils protocols. + +In other words, the `register` and `upload` command should be +compatible with any package index server out there. -Softwares that are compatible with PyPI and Distutils so -far: +Softwares that are compatible with PyPI and Distutils so far: - `PloneSoftwareCenter `_ wich is used to run plone.org products section. - `EggBasket `_ -**An extra package index is not a mirror or PyPI but can have itself -some mirrors** +**An extra package index is not a mirror of PyPI, but can have some +mirrors itself.** Merging several indexes ::::::::::::::::::::::: -When a client needs to get some packages from several -distinct indexes, it should be able to use each one of them -as a potential source of packages. Different indexes -should be defined as a sorted list for the client to -look for a package. +When a client needs to get some packages from several distinct +indexes, it should be able to use each one of them as a potential +source of packages. Different indexes should be defined as a sorted +list for the client to look for a package. -Each independant index can of course provide a list of -its mirrors, if the `/mirrors` page is available. +Each independant index can of course provide a list of its mirrors, if +the `/mirrors` page is available. That permits all combinations at client level, for a reliable packaging system with all levels of privacy. It is up the client to deal with the merging. + +References +========== + +.. [#pep305] + http://www.python.org/dev/peps/pep-0305/#id19 + +.. [#zcpkg] + http://pypi.python.org/pypi/z3c.pypimirror + + Copyright ========= From python-checkins at python.org Sun Mar 22 14:08:22 2009 From: python-checkins at python.org (matthias.klose) Date: Sun, 22 Mar 2009 14:08:22 +0100 (CET) Subject: [Python-checkins] r70518 - python/trunk/Misc/python.man Message-ID: <20090322130822.5842F1E4002@bag.python.org> Author: matthias.klose Date: Sun Mar 22 14:08:22 2009 New Revision: 70518 Log: - Fix comment macro in python.man Modified: python/trunk/Misc/python.man Modified: python/trunk/Misc/python.man ============================================================================== --- python/trunk/Misc/python.man (original) +++ python/trunk/Misc/python.man Sun Mar 22 14:08:22 2009 @@ -1,7 +1,7 @@ .TH PYTHON "1" "$Date$" -./" To view this file while editing, run it through groff: -./" groff -Tascii -man python.man | less +.\" To view this file while editing, run it through groff: +.\" groff -Tascii -man python.man | less .SH NAME python \- an interpreted, interactive, object-oriented programming language From python-checkins at python.org Sun Mar 22 14:13:24 2009 From: python-checkins at python.org (matthias.klose) Date: Sun, 22 Mar 2009 14:13:24 +0100 (CET) Subject: [Python-checkins] r70519 - in python/branches/release26-maint: Misc/python.man Message-ID: <20090322131324.6BA011E4002@bag.python.org> Author: matthias.klose Date: Sun Mar 22 14:13:23 2009 New Revision: 70519 Log: Merged revisions 70518 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70518 | matthias.klose | 2009-03-22 14:08:22 +0100 (So, 22 M?r 2009) | 2 lines - Fix comment macro in python.man Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Misc/python.man Modified: python/branches/release26-maint/Misc/python.man ============================================================================== --- python/branches/release26-maint/Misc/python.man (original) +++ python/branches/release26-maint/Misc/python.man Sun Mar 22 14:13:23 2009 @@ -1,7 +1,7 @@ .TH PYTHON "1" "$Date$" -./" To view this file while editing, run it through groff: -./" groff -Tascii -man python.man | less +.\" To view this file while editing, run it through groff: +.\" groff -Tascii -man python.man | less .SH NAME python \- an interpreted, interactive, object-oriented programming language From buildbot at python.org Sun Mar 22 15:12:53 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 22 Mar 2009 14:12:53 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090322141253.4DDCA1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/185 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: matthias.klose BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From brett at python.org Sun Mar 22 18:08:31 2009 From: brett at python.org (Brett Cannon) Date: Sun, 22 Mar 2009 10:08:31 -0700 Subject: [Python-checkins] r70495 - in python/branches/py3k: Doc/glossary.rst Doc/library/sys.rst Doc/reference/simple_stmts.rst Lib/importlib/NOTES In-Reply-To: References: <20090321031116.A59951E4002@bag.python.org> Message-ID: On Sun, Mar 22, 2009 at 01:49, Georg Brandl wrote: > brett.cannon schrieb: > > Author: brett.cannon > > Date: Sat Mar 21 04:11:16 2009 > > New Revision: 70495 > > > > Log: > > Document import's semantics for the language reference. This includes > filling > > in missing details for the sys module. > > Many thanks for this! Welcome! I just hope it's all coherent. -Brett -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Sun Mar 22 18:22:36 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 22 Mar 2009 18:22:36 +0100 (CET) Subject: [Python-checkins] r70520 - python/branches/py3k/Doc/library/itertools.rst Message-ID: <20090322172236.435671E4017@bag.python.org> Author: benjamin.peterson Date: Sun Mar 22 18:22:36 2009 New Revision: 70520 Log: fix incorrect merge Modified: python/branches/py3k/Doc/library/itertools.rst Modified: python/branches/py3k/Doc/library/itertools.rst ============================================================================== --- python/branches/py3k/Doc/library/itertools.rst (original) +++ python/branches/py3k/Doc/library/itertools.rst Sun Mar 22 18:22:36 2009 @@ -683,26 +683,26 @@ s = list(iterable) return chain.from_iterable(combinations(s, r) for r in range(len(s)+1)) - def unique_everseen(iterable, key=None): - "List unique elements, preserving order. Remember all elements ever seen." - # unique_everseen('AAAABBBCCDAABBB') --> A B C D - # unique_everseen('ABBCcAD', str.lower) --> A B C D - seen = set() - seen_add = seen.add - if key is None: - for element in iterable: - if element not in seen: - seen_add(element) - yield element - else: - for element in iterable: - k = key(element) - if k not in seen: - seen_add(k) - yield element + def unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in iterable: + if element not in seen: + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element - def unique_justseen(iterable, key=None): - "List unique elements, preserving order. Remember only the element just seen." - # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B - # unique_justseen('ABBCcAD', str.lower) --> A B C A D - return map(next, imap(itemgetter(1), groupby(iterable, key))) + def unique_justseen(iterable, key=None): + "List unique elements, preserving order. Remember only the element just seen." + # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B + # unique_justseen('ABBCcAD', str.lower) --> A B C A D + return map(next, map(itemgetter(1), groupby(iterable, key))) From python-checkins at python.org Sun Mar 22 18:45:11 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 22 Mar 2009 18:45:11 +0100 (CET) Subject: [Python-checkins] r70521 - in python/trunk: Lib/urllib.py Misc/NEWS Message-ID: <20090322174511.926411E4002@bag.python.org> Author: benjamin.peterson Date: Sun Mar 22 18:45:11 2009 New Revision: 70521 Log: close the file even if an exception occurs #5536 Modified: python/trunk/Lib/urllib.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/urllib.py ============================================================================== --- python/trunk/Lib/urllib.py (original) +++ python/trunk/Lib/urllib.py Sun Mar 22 18:45:11 2009 @@ -233,41 +233,45 @@ except IOError, msg: pass fp = self.open(url, data) - headers = fp.info() - if filename: - tfp = open(filename, 'wb') - else: - import tempfile - garbage, path = splittype(url) - garbage, path = splithost(path or "") - path, garbage = splitquery(path or "") - path, garbage = splitattr(path or "") - suffix = os.path.splitext(path)[1] - (fd, filename) = tempfile.mkstemp(suffix) - self.__tempfiles.append(filename) - tfp = os.fdopen(fd, 'wb') - result = filename, headers - if self.tempcache is not None: - self.tempcache[url] = result - bs = 1024*8 - size = -1 - read = 0 - blocknum = 0 - if reporthook: - if "content-length" in headers: - size = int(headers["Content-Length"]) - reporthook(blocknum, bs, size) - while 1: - block = fp.read(bs) - if block == "": - break - read += len(block) - tfp.write(block) - blocknum += 1 - if reporthook: - reporthook(blocknum, bs, size) - fp.close() - tfp.close() + try: + headers = fp.info() + if filename: + tfp = open(filename, 'wb') + else: + import tempfile + garbage, path = splittype(url) + garbage, path = splithost(path or "") + path, garbage = splitquery(path or "") + path, garbage = splitattr(path or "") + suffix = os.path.splitext(path)[1] + (fd, filename) = tempfile.mkstemp(suffix) + self.__tempfiles.append(filename) + tfp = os.fdopen(fd, 'wb') + try: + result = filename, headers + if self.tempcache is not None: + self.tempcache[url] = result + bs = 1024*8 + size = -1 + read = 0 + blocknum = 0 + if reporthook: + if "content-length" in headers: + size = int(headers["Content-Length"]) + reporthook(blocknum, bs, size) + while 1: + block = fp.read(bs) + if block == "": + break + read += len(block) + tfp.write(block) + blocknum += 1 + if reporthook: + reporthook(blocknum, bs, size) + finally: + tfp.close() + finally: + fp.close() del fp del tfp Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sun Mar 22 18:45:11 2009 @@ -188,6 +188,9 @@ Library ------- +- Issue #5536: urllib.urlretrieve makes sure to close the file it's writing to + even if an exception occurs. + - Issue #5381: Added object_pairs_hook to the json module. This allows OrderedDicts to be built by the decoder. From python-checkins at python.org Sun Mar 22 18:49:21 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 22 Mar 2009 18:49:21 +0100 (CET) Subject: [Python-checkins] r70522 - in python/branches/release26-maint: Lib/urllib.py Misc/NEWS Message-ID: <20090322174921.D94D11E4002@bag.python.org> Author: benjamin.peterson Date: Sun Mar 22 18:49:21 2009 New Revision: 70522 Log: Merged revisions 70521 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70521 | benjamin.peterson | 2009-03-22 12:45:11 -0500 (Sun, 22 Mar 2009) | 1 line close the file even if an exception occurs #5536 ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/urllib.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/urllib.py ============================================================================== --- python/branches/release26-maint/Lib/urllib.py (original) +++ python/branches/release26-maint/Lib/urllib.py Sun Mar 22 18:49:21 2009 @@ -233,41 +233,45 @@ except IOError, msg: pass fp = self.open(url, data) - headers = fp.info() - if filename: - tfp = open(filename, 'wb') - else: - import tempfile - garbage, path = splittype(url) - garbage, path = splithost(path or "") - path, garbage = splitquery(path or "") - path, garbage = splitattr(path or "") - suffix = os.path.splitext(path)[1] - (fd, filename) = tempfile.mkstemp(suffix) - self.__tempfiles.append(filename) - tfp = os.fdopen(fd, 'wb') - result = filename, headers - if self.tempcache is not None: - self.tempcache[url] = result - bs = 1024*8 - size = -1 - read = 0 - blocknum = 0 - if reporthook: - if "content-length" in headers: - size = int(headers["Content-Length"]) - reporthook(blocknum, bs, size) - while 1: - block = fp.read(bs) - if block == "": - break - read += len(block) - tfp.write(block) - blocknum += 1 - if reporthook: - reporthook(blocknum, bs, size) - fp.close() - tfp.close() + try: + headers = fp.info() + if filename: + tfp = open(filename, 'wb') + else: + import tempfile + garbage, path = splittype(url) + garbage, path = splithost(path or "") + path, garbage = splitquery(path or "") + path, garbage = splitattr(path or "") + suffix = os.path.splitext(path)[1] + (fd, filename) = tempfile.mkstemp(suffix) + self.__tempfiles.append(filename) + tfp = os.fdopen(fd, 'wb') + try: + result = filename, headers + if self.tempcache is not None: + self.tempcache[url] = result + bs = 1024*8 + size = -1 + read = 0 + blocknum = 0 + if reporthook: + if "content-length" in headers: + size = int(headers["Content-Length"]) + reporthook(blocknum, bs, size) + while 1: + block = fp.read(bs) + if block == "": + break + read += len(block) + tfp.write(block) + blocknum += 1 + if reporthook: + reporthook(blocknum, bs, size) + finally: + tfp.close() + finally: + fp.close() del fp del tfp Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Sun Mar 22 18:49:21 2009 @@ -92,6 +92,9 @@ Library ------- +- Issue #5536: urllib.urlretrieve makes sure to close the file it's writing to + even if an exception occurs. + - Fix Decimal.__format__ bug that swapped the meanings of the '<' and '>' alignment characters. From python-checkins at python.org Sun Mar 22 21:09:34 2009 From: python-checkins at python.org (lars.gustaebel) Date: Sun, 22 Mar 2009 21:09:34 +0100 (CET) Subject: [Python-checkins] r70523 - in python/trunk: Lib/tarfile.py Lib/test/test_tarfile.py Misc/NEWS Message-ID: <20090322200934.198EB1E4002@bag.python.org> Author: lars.gustaebel Date: Sun Mar 22 21:09:33 2009 New Revision: 70523 Log: Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop forever on incomplete input. That caused tarfile.open() to hang when used with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or partial bzip2 compressed data. Modified: python/trunk/Lib/tarfile.py python/trunk/Lib/test/test_tarfile.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/tarfile.py ============================================================================== --- python/trunk/Lib/tarfile.py (original) +++ python/trunk/Lib/tarfile.py Sun Mar 22 21:09:33 2009 @@ -662,12 +662,11 @@ b = [self.buf] x = len(self.buf) while x < size: - try: - raw = self.fileobj.read(self.blocksize) - data = self.bz2obj.decompress(raw) - b.append(data) - except EOFError: + raw = self.fileobj.read(self.blocksize) + if not raw: break + data = self.bz2obj.decompress(raw) + b.append(data) x += len(data) self.buf = "".join(b) Modified: python/trunk/Lib/test/test_tarfile.py ============================================================================== --- python/trunk/Lib/test/test_tarfile.py (original) +++ python/trunk/Lib/test/test_tarfile.py Sun Mar 22 21:09:33 2009 @@ -1140,6 +1140,30 @@ class Bz2StreamWriteTest(StreamWriteTest): mode = "w|bz2" +class Bz2PartialReadTest(unittest.TestCase): + # Issue5068: The _BZ2Proxy.read() method loops forever + # on an empty or partial bzipped file. + + def _test_partial_input(self, mode): + class MyStringIO(StringIO.StringIO): + hit_eof = False + def read(self, n): + if self.hit_eof: + raise AssertionError("infinite loop detected in tarfile.open()") + self.hit_eof = self.pos == self.len + return StringIO.StringIO.read(self, n) + + data = bz2.compress(tarfile.TarInfo("foo").tobuf()) + for x in range(len(data) + 1): + tarfile.open(fileobj=MyStringIO(data[:x]), mode=mode) + + def test_partial_input(self): + self._test_partial_input("r") + + def test_partial_input_bz2(self): + self._test_partial_input("r:bz2") + + def test_main(): if not os.path.exists(TEMPDIR): os.mkdir(TEMPDIR) @@ -1196,6 +1220,7 @@ Bz2StreamReadTest, Bz2WriteTest, Bz2StreamWriteTest, + Bz2PartialReadTest, ] try: Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sun Mar 22 21:09:33 2009 @@ -188,6 +188,11 @@ Library ------- +- Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop + forever on incomplete input. That caused tarfile.open() to hang when used + with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or + partial bzip2 compressed data. + - Issue #5536: urllib.urlretrieve makes sure to close the file it's writing to even if an exception occurs. From python-checkins at python.org Sun Mar 22 21:22:39 2009 From: python-checkins at python.org (lars.gustaebel) Date: Sun, 22 Mar 2009 21:22:39 +0100 (CET) Subject: [Python-checkins] r70524 - in python/branches/release26-maint: Lib/tarfile.py Lib/test/test_tarfile.py Misc/NEWS Message-ID: <20090322202239.1B6761E4002@bag.python.org> Author: lars.gustaebel Date: Sun Mar 22 21:22:29 2009 New Revision: 70524 Log: Merged revisions 70523 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70523 | lars.gustaebel | 2009-03-22 21:09:33 +0100 (Sun, 22 Mar 2009) | 5 lines Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop forever on incomplete input. That caused tarfile.open() to hang when used with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or partial bzip2 compressed data. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/tarfile.py python/branches/release26-maint/Lib/test/test_tarfile.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/tarfile.py ============================================================================== --- python/branches/release26-maint/Lib/tarfile.py (original) +++ python/branches/release26-maint/Lib/tarfile.py Sun Mar 22 21:22:29 2009 @@ -662,12 +662,11 @@ b = [self.buf] x = len(self.buf) while x < size: - try: - raw = self.fileobj.read(self.blocksize) - data = self.bz2obj.decompress(raw) - b.append(data) - except EOFError: + raw = self.fileobj.read(self.blocksize) + if not raw: break + data = self.bz2obj.decompress(raw) + b.append(data) x += len(data) self.buf = "".join(b) Modified: python/branches/release26-maint/Lib/test/test_tarfile.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_tarfile.py (original) +++ python/branches/release26-maint/Lib/test/test_tarfile.py Sun Mar 22 21:22:29 2009 @@ -1140,6 +1140,30 @@ class Bz2StreamWriteTest(StreamWriteTest): mode = "w|bz2" +class Bz2PartialReadTest(unittest.TestCase): + # Issue5068: The _BZ2Proxy.read() method loops forever + # on an empty or partial bzipped file. + + def _test_partial_input(self, mode): + class MyStringIO(StringIO.StringIO): + hit_eof = False + def read(self, n): + if self.hit_eof: + raise AssertionError("infinite loop detected in tarfile.open()") + self.hit_eof = self.pos == self.len + return StringIO.StringIO.read(self, n) + + data = bz2.compress(tarfile.TarInfo("foo").tobuf()) + for x in range(len(data) + 1): + tarfile.open(fileobj=MyStringIO(data[:x]), mode=mode) + + def test_partial_input(self): + self._test_partial_input("r") + + def test_partial_input_bz2(self): + self._test_partial_input("r:bz2") + + def test_main(): if not os.path.exists(TEMPDIR): os.mkdir(TEMPDIR) @@ -1196,6 +1220,7 @@ Bz2StreamReadTest, Bz2WriteTest, Bz2StreamWriteTest, + Bz2PartialReadTest, ] try: Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Sun Mar 22 21:22:29 2009 @@ -92,6 +92,11 @@ Library ------- +- Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop + forever on incomplete input. That caused tarfile.open() to hang when used + with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or + partial bzip2 compressed data. + - Issue #5536: urllib.urlretrieve makes sure to close the file it's writing to even if an exception occurs. From python-checkins at python.org Sun Mar 22 21:34:29 2009 From: python-checkins at python.org (lars.gustaebel) Date: Sun, 22 Mar 2009 21:34:29 +0100 (CET) Subject: [Python-checkins] r70525 - in python/branches/py3k: Lib/tarfile.py Lib/test/test_tarfile.py Misc/NEWS Message-ID: <20090322203429.B2ADA1E4002@bag.python.org> Author: lars.gustaebel Date: Sun Mar 22 21:34:29 2009 New Revision: 70525 Log: Merged revisions 70523 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70523 | lars.gustaebel | 2009-03-22 21:09:33 +0100 (Sun, 22 Mar 2009) | 5 lines Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop forever on incomplete input. That caused tarfile.open() to hang when used with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or partial bzip2 compressed data. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/tarfile.py python/branches/py3k/Lib/test/test_tarfile.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/tarfile.py ============================================================================== --- python/branches/py3k/Lib/tarfile.py (original) +++ python/branches/py3k/Lib/tarfile.py Sun Mar 22 21:34:29 2009 @@ -639,12 +639,11 @@ def read(self, size): x = len(self.buf) while x < size: - try: - raw = self.fileobj.read(self.blocksize) - data = self.bz2obj.decompress(raw) - self.buf += data - except EOFError: + raw = self.fileobj.read(self.blocksize) + if not raw: break + data = self.bz2obj.decompress(raw) + self.buf += data x += len(data) buf = self.buf[:size] Modified: python/branches/py3k/Lib/test/test_tarfile.py ============================================================================== --- python/branches/py3k/Lib/test/test_tarfile.py (original) +++ python/branches/py3k/Lib/test/test_tarfile.py Sun Mar 22 21:34:29 2009 @@ -1121,6 +1121,30 @@ class Bz2StreamWriteTest(StreamWriteTest): mode = "w|bz2" +class Bz2PartialReadTest(unittest.TestCase): + # Issue5068: The _BZ2Proxy.read() method loops forever + # on an empty or partial bzipped file. + + def _test_partial_input(self, mode): + class MyBytesIO(io.BytesIO): + hit_eof = False + def read(self, n): + if self.hit_eof: + raise AssertionError("infinite loop detected in tarfile.open()") + self.hit_eof = self.tell() == len(self.getvalue()) + return super(MyBytesIO, self).read(n) + + data = bz2.compress(tarfile.TarInfo("foo").tobuf()) + for x in range(len(data) + 1): + tarfile.open(fileobj=MyBytesIO(data[:x]), mode=mode) + + def test_partial_input(self): + self._test_partial_input("r") + + def test_partial_input_bz2(self): + self._test_partial_input("r:bz2") + + def test_main(): if not os.path.exists(TEMPDIR): os.mkdir(TEMPDIR) @@ -1178,6 +1202,7 @@ Bz2StreamReadTest, Bz2WriteTest, Bz2StreamWriteTest, + Bz2PartialReadTest, ] try: Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Mar 22 21:34:29 2009 @@ -32,6 +32,11 @@ Library ------- +- Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop + forever on incomplete input. That caused tarfile.open() to hang when used + with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or + partial bzip2 compressed data. + - Issue #2110: Add support for thousands separator and 'n' type specifier to Decimal.__format__ From python-checkins at python.org Sun Mar 22 21:39:39 2009 From: python-checkins at python.org (lars.gustaebel) Date: Sun, 22 Mar 2009 21:39:39 +0100 (CET) Subject: [Python-checkins] r70526 - in python/branches/release30-maint: Lib/tarfile.py Lib/test/test_tarfile.py Misc/NEWS Message-ID: <20090322203939.34AA41E4002@bag.python.org> Author: lars.gustaebel Date: Sun Mar 22 21:39:38 2009 New Revision: 70526 Log: Merged revisions 70525 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70525 | lars.gustaebel | 2009-03-22 21:34:29 +0100 (Sun, 22 Mar 2009) | 12 lines Merged revisions 70523 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70523 | lars.gustaebel | 2009-03-22 21:09:33 +0100 (Sun, 22 Mar 2009) | 5 lines Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop forever on incomplete input. That caused tarfile.open() to hang when used with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or partial bzip2 compressed data. ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/tarfile.py python/branches/release30-maint/Lib/test/test_tarfile.py python/branches/release30-maint/Misc/NEWS Modified: python/branches/release30-maint/Lib/tarfile.py ============================================================================== --- python/branches/release30-maint/Lib/tarfile.py (original) +++ python/branches/release30-maint/Lib/tarfile.py Sun Mar 22 21:39:38 2009 @@ -639,12 +639,11 @@ def read(self, size): x = len(self.buf) while x < size: - try: - raw = self.fileobj.read(self.blocksize) - data = self.bz2obj.decompress(raw) - self.buf += data - except EOFError: + raw = self.fileobj.read(self.blocksize) + if not raw: break + data = self.bz2obj.decompress(raw) + self.buf += data x += len(data) buf = self.buf[:size] Modified: python/branches/release30-maint/Lib/test/test_tarfile.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_tarfile.py (original) +++ python/branches/release30-maint/Lib/test/test_tarfile.py Sun Mar 22 21:39:38 2009 @@ -1121,6 +1121,30 @@ class Bz2StreamWriteTest(StreamWriteTest): mode = "w|bz2" +class Bz2PartialReadTest(unittest.TestCase): + # Issue5068: The _BZ2Proxy.read() method loops forever + # on an empty or partial bzipped file. + + def _test_partial_input(self, mode): + class MyBytesIO(io.BytesIO): + hit_eof = False + def read(self, n): + if self.hit_eof: + raise AssertionError("infinite loop detected in tarfile.open()") + self.hit_eof = self.tell() == len(self.getvalue()) + return super(MyBytesIO, self).read(n) + + data = bz2.compress(tarfile.TarInfo("foo").tobuf()) + for x in range(len(data) + 1): + tarfile.open(fileobj=MyBytesIO(data[:x]), mode=mode) + + def test_partial_input(self): + self._test_partial_input("r") + + def test_partial_input_bz2(self): + self._test_partial_input("r:bz2") + + def test_main(): if not os.path.exists(TEMPDIR): os.mkdir(TEMPDIR) @@ -1178,6 +1202,7 @@ Bz2StreamReadTest, Bz2WriteTest, Bz2StreamWriteTest, + Bz2PartialReadTest, ] try: Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Sun Mar 22 21:39:38 2009 @@ -24,6 +24,11 @@ Library ------- +- Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop + forever on incomplete input. That caused tarfile.open() to hang when used + with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or + partial bzip2 compressed data. + - Fix Decimal.__format__ bug that swapped the meanings of the '<' and '>' alignment characters. From python-checkins at python.org Sun Mar 22 21:48:05 2009 From: python-checkins at python.org (lars.gustaebel) Date: Sun, 22 Mar 2009 21:48:05 +0100 (CET) Subject: [Python-checkins] r70527 - in python/branches/release25-maint: Lib/tarfile.py Lib/test/test_tarfile.py Misc/NEWS Message-ID: <20090322204805.6BE271E4002@bag.python.org> Author: lars.gustaebel Date: Sun Mar 22 21:48:03 2009 New Revision: 70527 Log: Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop forever on incomplete input. That caused tarfile.open() to hang when used with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or partial bzip2 compressed data. (backported from r70523) Modified: python/branches/release25-maint/Lib/tarfile.py python/branches/release25-maint/Lib/test/test_tarfile.py python/branches/release25-maint/Misc/NEWS Modified: python/branches/release25-maint/Lib/tarfile.py ============================================================================== --- python/branches/release25-maint/Lib/tarfile.py (original) +++ python/branches/release25-maint/Lib/tarfile.py Sun Mar 22 21:48:03 2009 @@ -594,12 +594,11 @@ b = [self.buf] x = len(self.buf) while x < size: - try: - raw = self.fileobj.read(self.blocksize) - data = self.bz2obj.decompress(raw) - b.append(data) - except EOFError: + raw = self.fileobj.read(self.blocksize) + if not raw: break + data = self.bz2obj.decompress(raw) + b.append(data) x += len(data) self.buf = "".join(b) 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 Sun Mar 22 21:48:03 2009 @@ -751,6 +751,29 @@ class ReadFileobjTestBzip2(ReadFileobjTest): comp = "bz2" + class PartialReadTestBzip2(unittest.TestCase): + # Issue5068: The _BZ2Proxy.read() method loops forever + # on an empty or partial bzipped file. + + def _test_partial_input(self, mode): + class MyStringIO(StringIO.StringIO): + hit_eof = False + def read(self, n): + if self.hit_eof: + raise AssertionError("infinite loop detected in tarfile.open()") + self.hit_eof = self.pos == self.len + return StringIO.StringIO.read(self, n) + + data = bz2.compress(tarfile.TarInfo("foo").tobuf()) + for x in range(len(data) + 1): + tarfile.open(fileobj=MyStringIO(data[:x]), mode=mode) + + def test_partial_input(self): + self._test_partial_input("r") + + def test_partial_input_bz2(self): + self._test_partial_input("r:bz2") + # If importing gzip failed, discard the Gzip TestCases. if not gzip: del ReadTestGzip @@ -811,7 +834,7 @@ WriteTestBzip2, WriteStreamTestBzip2, ReadDetectTestBzip2, ReadDetectFileobjTestBzip2, ReadAsteriskTestBzip2, ReadStreamAsteriskTestBzip2, - ReadFileobjTestBzip2 + ReadFileobjTestBzip2, PartialReadTestBzip2 ]) try: test_support.run_unittest(*tests) Modified: python/branches/release25-maint/Misc/NEWS ============================================================================== --- python/branches/release25-maint/Misc/NEWS (original) +++ python/branches/release25-maint/Misc/NEWS Sun Mar 22 21:48:03 2009 @@ -4,6 +4,20 @@ (editors: check NEWS.help for information about editing NEWS using ReST.) +What's New in Python 2.5.5? +=========================== + +*Release date: XX-XXX-20XX* + +Library +------- + +- Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop + forever on incomplete input. That caused tarfile.open() to hang when used + with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or + partial bzip2 compressed data. + + What's New in Python 2.5.4? =========================== From buildbot at python.org Sun Mar 22 22:08:04 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 22 Mar 2009 21:08:04 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090322210804.9DE6C1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/749 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: lars.gustaebel BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From ncoghlan at gmail.com Sun Mar 22 22:12:57 2009 From: ncoghlan at gmail.com (Nick Coghlan) Date: Mon, 23 Mar 2009 07:12:57 +1000 Subject: [Python-checkins] r70495 - in python/branches/py3k: Doc/glossary.rst Doc/library/sys.rst Doc/reference/simple_stmts.rst Lib/importlib/NOTES In-Reply-To: References: <20090321031116.A59951E4002@bag.python.org> Message-ID: <49C6A9D9.8010605@gmail.com> Brett Cannon wrote: > Welcome! I just hope it's all coherent. I haven't read all of it yet, but the part I skimmed over made sense :) Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- From buildbot at python.org Sun Mar 22 22:23:34 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 22 Mar 2009 21:23:34 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 2.6 Message-ID: <20090322212334.C30921E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%202.6/builds/193 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: The web-page 'force build' button was pressed by 'Nick': idk Build Source Stamp: [branch idk] idk Blamelist: BUILD FAILED: failed svn sincerely, -The Buildbot From python-checkins at python.org Sun Mar 22 22:29:49 2009 From: python-checkins at python.org (lars.gustaebel) Date: Sun, 22 Mar 2009 22:29:49 +0100 (CET) Subject: [Python-checkins] r70528 - python/branches/release26-maint/Lib/tarfile.py Message-ID: <20090322212949.126751E4002@bag.python.org> Author: lars.gustaebel Date: Sun Mar 22 22:29:48 2009 New Revision: 70528 Log: Avoid EOFError being passed to the caller (restoring the old behavior). Modified: python/branches/release26-maint/Lib/tarfile.py Modified: python/branches/release26-maint/Lib/tarfile.py ============================================================================== --- python/branches/release26-maint/Lib/tarfile.py (original) +++ python/branches/release26-maint/Lib/tarfile.py Sun Mar 22 22:29:48 2009 @@ -665,7 +665,10 @@ raw = self.fileobj.read(self.blocksize) if not raw: break - data = self.bz2obj.decompress(raw) + try: + data = self.bz2obj.decompress(raw) + except EOFError: + break b.append(data) x += len(data) self.buf = "".join(b) From python-checkins at python.org Sun Mar 22 22:32:31 2009 From: python-checkins at python.org (lars.gustaebel) Date: Sun, 22 Mar 2009 22:32:31 +0100 (CET) Subject: [Python-checkins] r70529 - python/branches/release30-maint/Lib/tarfile.py Message-ID: <20090322213231.3C9491E4002@bag.python.org> Author: lars.gustaebel Date: Sun Mar 22 22:32:31 2009 New Revision: 70529 Log: Avoid EOFError being passed to the caller (restoring the old behavior). Modified: python/branches/release30-maint/Lib/tarfile.py Modified: python/branches/release30-maint/Lib/tarfile.py ============================================================================== --- python/branches/release30-maint/Lib/tarfile.py (original) +++ python/branches/release30-maint/Lib/tarfile.py Sun Mar 22 22:32:31 2009 @@ -642,7 +642,10 @@ raw = self.fileobj.read(self.blocksize) if not raw: break - data = self.bz2obj.decompress(raw) + try: + data = self.bz2obj.decompress(raw) + except EOFError: + break self.buf += data x += len(data) From python-checkins at python.org Sun Mar 22 22:34:05 2009 From: python-checkins at python.org (lars.gustaebel) Date: Sun, 22 Mar 2009 22:34:05 +0100 (CET) Subject: [Python-checkins] r70530 - python/branches/release25-maint/Lib/tarfile.py Message-ID: <20090322213405.EFC971E4002@bag.python.org> Author: lars.gustaebel Date: Sun Mar 22 22:34:05 2009 New Revision: 70530 Log: Avoid EOFError being passed to the caller (restoring the old behavior). Modified: python/branches/release25-maint/Lib/tarfile.py Modified: python/branches/release25-maint/Lib/tarfile.py ============================================================================== --- python/branches/release25-maint/Lib/tarfile.py (original) +++ python/branches/release25-maint/Lib/tarfile.py Sun Mar 22 22:34:05 2009 @@ -597,7 +597,10 @@ raw = self.fileobj.read(self.blocksize) if not raw: break - data = self.bz2obj.decompress(raw) + try: + data = self.bz2obj.decompress(raw) + except EOFError: + break b.append(data) x += len(data) self.buf = "".join(b) From buildbot at python.org Sun Mar 22 22:34:40 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 22 Mar 2009 21:34:40 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090322213440.6E5751E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/187 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: lars.gustaebel BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_asynchat make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sun Mar 22 23:24:59 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 22 Mar 2009 23:24:59 +0100 (CET) Subject: [Python-checkins] r70531 - python/trunk/Lib/test/test_cpickle.py Message-ID: <20090322222459.12C321E4002@bag.python.org> Author: benjamin.peterson Date: Sun Mar 22 23:24:58 2009 New Revision: 70531 Log: AttributeError can be thrown during recursion errors Modified: python/trunk/Lib/test/test_cpickle.py Modified: python/trunk/Lib/test/test_cpickle.py ============================================================================== --- python/trunk/Lib/test/test_cpickle.py (original) +++ python/trunk/Lib/test/test_cpickle.py Sun Mar 22 23:24:58 2009 @@ -102,7 +102,7 @@ for n in nodes: n.connections = list(nodes) n.connections.remove(n) - self.assertRaises(RuntimeError, cPickle.dumps, n) + self.assertRaises((AttributeError, RuntimeError), cPickle.dumps, n) def test_issue3179(self): # Safe test, because I broke this case when fixing the From buildbot at python.org Sun Mar 22 23:25:54 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 22 Mar 2009 22:25:54 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090322222555.BB76A1E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/222 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: lars.gustaebel BUILD FAILED: failed test Excerpt from the test logfile: 3 tests failed: test_distutils test_posix test_subprocess ====================================================================== FAIL: test_get_python_inc (distutils.tests.test_sysconfig.SysconfigTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/distutils/tests/test_sysconfig.py", line 45, in test_get_python_inc self.assert_(os.path.isdir(inc_dir), inc_dir) AssertionError: /home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/Include ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_subprocess.py", line 115, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From buildbot at python.org Sun Mar 22 23:32:39 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 22 Mar 2009 22:32:39 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.0 Message-ID: <20090322223240.ABC2C1E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.0/builds/198 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: lars.gustaebel BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_doctest test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 00:58:49 2009 From: python-checkins at python.org (matthias.klose) Date: Mon, 23 Mar 2009 00:58:49 +0100 (CET) Subject: [Python-checkins] r70532 - python/branches/py3k/Modules/Setup.dist Message-ID: <20090322235849.0D35A1E4002@bag.python.org> Author: matthias.klose Date: Mon Mar 23 00:58:48 2009 New Revision: 70532 Log: - Modules/Setup.dist: Readd the _functools extension, lost in the io-c merge. Modified: python/branches/py3k/Modules/Setup.dist Modified: python/branches/py3k/Modules/Setup.dist ============================================================================== --- python/branches/py3k/Modules/Setup.dist (original) +++ python/branches/py3k/Modules/Setup.dist Mon Mar 23 00:58:48 2009 @@ -164,6 +164,7 @@ #_collections _collectionsmodule.c # Container types #itertools itertoolsmodule.c # Functions creating iterators for efficient looping #atexit atexitmodule.c # Register functions to be run at interpreter-shutdown +#_functools _functoolsmodule.c # Tools for working with functions and callable objects #_elementtree -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI _elementtree.c # elementtree accelerator #_pickle _pickle.c # pickle accelerator #datetime datetimemodule.c # date/time type From python-checkins at python.org Mon Mar 23 01:08:10 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 23 Mar 2009 01:08:10 +0100 (CET) Subject: [Python-checkins] r70533 - python/trunk/Lib/collections.py Message-ID: <20090323000810.2989A1E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 23 01:08:09 2009 New Revision: 70533 Log: Add more comments. Improve variable names. Make links clearer by using a Link object instead of a list. Use proxy links to avoid circular references. Modified: python/trunk/Lib/collections.py Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Mon Mar 23 01:08:09 2009 @@ -10,6 +10,7 @@ from keyword import iskeyword as _iskeyword import sys as _sys import heapq as _heapq +from weakref import proxy from itertools import repeat as _repeat, chain as _chain, starmap as _starmap, \ ifilter as _ifilter, imap as _imap, izip as _izip @@ -17,68 +18,79 @@ ### OrderedDict ################################################################################ +class _Link(object): + __slots__ = 'prev', 'next', 'key', '__weakref__' + class OrderedDict(dict, MutableMapping): 'Dictionary that remembers insertion order' - # The inherited dict maps keys to values. - # The internal self.__map dictionary maps keys to links in a doubly linked list. - # The doubly linked list starts and ends with a sentinel element. - # The sentinel element never gets deleted. It simplifies the algorithm. - # Setting a new item causes a new link to append to the doubly linked list. - # Deleting an item uses self.__map to find the link, which is then removed. - # Iteration follows the linked list in order. - # Reverse iteration follows the links backwards. + # An inherited dict maps keys to values. # The inherited dict provides __getitem__, __len__, __contains__, and get. # The remaining methods are order-aware. - # Big-Oh running times for all methods are the same as for regular dictionaries. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # The prev/next links are weakref proxies (to prevent circular references). + # Individual links are kept alive by the hard reference in self.__map. + # Those hard references disappear when a key is deleted from an OrderedDict. def __init__(self, *args, **kwds): if len(args) > 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) try: - self.__end + self.__root except AttributeError: self.clear() self.update(*args, **kwds) def clear(self): - self.__end = end = [] - end += [None, end, end] # sentinel node for doubly linked list - self.__map = {} # key --> [key, prev, next] + self.__root = root = _Link() # sentinel node for the doubly linked list + root.prev = root.next = root + self.__map = {} dict.clear(self) def __setitem__(self, key, value): + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. if key not in self: - end = self.__end - curr = end[1] - curr[2] = end[1] = self.__map[key] = [key, curr, end] + self.__map[key] = link = _Link() + root = self.__root + last = root.prev + link.prev, link.next, link.key = last, root, key + last.next = root.prev = proxy(link) dict.__setitem__(self, key, value) def __delitem__(self, key): + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. dict.__delitem__(self, key) - key, prev, next = self.__map.pop(key) - prev[2] = next - next[1] = prev + link = self.__map.pop(key) + link.prev.next = link.next + link.next.prev = link.prev def __iter__(self): - end = self.__end - curr = end[2] # start at first link - while curr is not end: - yield curr[0] # yield KEY for each link - curr = curr[2] # goto next link + # Traverse the linked list in order. + root = self.__root + curr = root.next + while curr is not root: + yield curr.key + curr = curr.next def __reversed__(self): - end = self.__end - curr = end[1] # start at last link - while curr is not end: - yield curr[0] # yield KEY for each link - curr = curr[1] # goto prev link + # Traverse the linked list in reverse order. + root = self.__root + curr = root.prev + while curr is not root: + yield curr.key + curr = curr.prev def __reduce__(self): items = [[k, self[k]] for k in self] - tmp = self.__map, self.__end - del self.__map, self.__end + tmp = self.__map, self.__root + del self.__map, self.__root inst_dict = vars(self).copy() - self.__map, self.__end = tmp + self.__map, self.__root = tmp if inst_dict: return (self.__class__, (items,), inst_dict) return self.__class__, (items,) From buildbot at python.org Mon Mar 23 01:55:56 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 00:55:56 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.0 Message-ID: <20090323005556.E93991E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.0/builds/219 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: lars.gustaebel BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 03:38:01 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Mar 2009 03:38:01 +0100 (CET) Subject: [Python-checkins] r70534 - in python/branches/py3k/Doc/library: functions.rst io.rst Message-ID: <20090323023801.CAD771E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 23 03:38:01 2009 New Revision: 70534 Log: fix docs about open's return value #5539 (how annoying to have the same docs in two places) (three if you count the docstring...) Modified: python/branches/py3k/Doc/library/functions.rst python/branches/py3k/Doc/library/io.rst Modified: python/branches/py3k/Doc/library/functions.rst ============================================================================== --- python/branches/py3k/Doc/library/functions.rst (original) +++ python/branches/py3k/Doc/library/functions.rst Mon Mar 23 03:38:01 2009 @@ -749,9 +749,22 @@ the other legal values, any ``'\n'`` characters written are translated to the given string. - If *closefd* is ``False``, the underlying file descriptor will be kept open - when the file is closed. This does not work when a file name is given and - must be ``True`` in that case. + If *closefd* is ``False`` and a file descriptor rather than a filename was + given, the underlying file descriptor will be kept open when the file is + closed. If a filename is given *closefd* has no effect and must be ``True`` + (the default). + + The type of file object returned by the :func:`open` function depends on the + mode. When :func:`open` is used to open a file in a text mode (``'w'``, + ``'r'``, ``'wt'``, ``'rt'``, etc.), it returns a subclass of + :class:`io.TextIOBase` (specifically :class:`io.TextIOWrapper`). When used + to open a file in a binary mode with buffering, the returned class is a + subclass of :class:`io.BufferedIOBase`. The exact class varies: in read + binary mode, it returns a :class:`io.BufferedReader`; in write binary and + append binary modes, it returns a :class:`io.BufferedWriter`, and in + read/write mode, it returns a :class:`io.BufferedRandom`. When buffering is + disabled, the raw stream, a subclass of :class:`io.RawIOBase`, + :class:`io.FileIO`, is returned. .. index:: single: line-buffered I/O @@ -763,8 +776,8 @@ module: sys See also the file handling modules, such as, :mod:`fileinput`, :mod:`io` - (where :func:`open()` is declared), :mod:`os`, :mod:`os.path`, - :mod:`tempfile`, and :mod:`shutil`. + (where :func:`open` is declared), :mod:`os`, :mod:`os.path`, :mod:`tempfile`, + and :mod:`shutil`. .. XXX works for bytes too, but should it? Modified: python/branches/py3k/Doc/library/io.rst ============================================================================== --- python/branches/py3k/Doc/library/io.rst (original) +++ python/branches/py3k/Doc/library/io.rst Mon Mar 23 03:38:01 2009 @@ -134,19 +134,21 @@ the other legal values, any ``'\n'`` characters written are translated to the given string. - If *closefd* is ``False`` and a file descriptor rather than a - filename was given, the underlying file descriptor will be kept open - when the file is closed. If a filename is given *closefd* has no - effect but must be ``True`` (the default). - - The type of file object returned by the :func:`open` function depends - on the mode. When :func:`open` is used to open a file in a text mode - (``'w'``, ``'r'``, ``'wt'``, ``'rt'``, etc.), it returns a - :class:`TextIOWrapper`. When used to open a file in a binary mode, - the returned class varies: in read binary mode, it returns a - :class:`BufferedReader`; in write binary and append binary modes, it - returns a :class:`BufferedWriter`, and in read/write mode, it returns - a :class:`BufferedRandom`. + If *closefd* is ``False`` and a file descriptor rather than a filename was + given, the underlying file descriptor will be kept open when the file is + closed. If a filename is given *closefd* has no effect and must be ``True`` + (the default). + + The type of file object returned by the :func:`open` function depends on the + mode. When :func:`open` is used to open a file in a text mode (``'w'``, + ``'r'``, ``'wt'``, ``'rt'``, etc.), it returns a subclass of + :class:`TextIOBase` (specifically :class:`TextIOWrapper`). When used to open + a file in a binary mode with buffering, the returned class is a subclass of + :class:`BufferedIOBase`. The exact class varies: in read binary mode, it + returns a :class:`BufferedReader`; in write binary and append binary modes, + it returns a :class:`BufferedWriter`, and in read/write mode, it returns a + :class:`BufferedRandom`. When buffering is disabled, the raw stream, a + subclass of :class:`RawIOBase`, :class:`FileIO`, is returned. It is also possible to use a string or bytearray as a file for both reading and writing. For strings :class:`StringIO` can be used like a file opened in From buildbot at python.org Mon Mar 23 03:43:34 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 02:43:34 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090323024334.6BB2F1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/433 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: matthias.klose BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_pipes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 03:44:58 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Mar 2009 03:44:58 +0100 (CET) Subject: [Python-checkins] r70535 - in python/branches/py3k/Doc/library: functions.rst io.rst Message-ID: <20090323024458.EC7AE1E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 23 03:44:58 2009 New Revision: 70535 Log: sync open() docs more Modified: python/branches/py3k/Doc/library/functions.rst python/branches/py3k/Doc/library/io.rst Modified: python/branches/py3k/Doc/library/functions.rst ============================================================================== --- python/branches/py3k/Doc/library/functions.rst (original) +++ python/branches/py3k/Doc/library/functions.rst Mon Mar 23 03:44:58 2009 @@ -666,7 +666,8 @@ .. function:: open(file[, mode='r'[, buffering=None[, encoding=None[, errors=None[, newline=None[, closefd=True]]]]]]) - Open a file. If the file cannot be opened, :exc:`IOError` is raised. + Open *file* and return a corresponding stream. If the file cannot be opened, + an :exc:`IOError` is raised. *file* is either a string or bytes object giving the name (and the path if the file isn't in the current working directory) of the file to be opened or @@ -679,14 +680,9 @@ Other common values are ``'w'`` for writing (truncating the file if it already exists), and ``'a'`` for appending (which on *some* Unix systems, means that *all* writes append to the end of the file regardless of the - current seek position). - - In text mode, if *encoding* is not specified the encoding used is the same as - returned by :func:`locale.getpreferredencoding`, if the :mod:`locale` module - is available, else ASCII. For reading and writing raw bytes, use binary mode - and leave *encoding* unspecified. - - The available modes are: + current seek position). In text mode, if *encoding* is not specified the + encoding used is platform dependent. (For reading and writing raw bytes use + binary mode and leave *encoding* unspecified.) The available modes are: ========= =============================================================== Character Meaning @@ -697,39 +693,44 @@ ``'b'`` binary mode ``'t'`` text mode (default) ``'+'`` open a disk file for updating (reading and writing) - ``'U'`` universal newline mode (for backwards compatibility; unneeded - for new code) + ``'U'`` universal newline mode (for backwards compatibility; should + not be used in new code) ========= =============================================================== The default mode is ``'rt'`` (open for reading text). For binary random access, the mode ``'w+b'`` opens and truncates the file to 0 bytes, while ``'r+b'`` opens the file without truncation. - Python distinguishes between files opened in binary and text modes, even - when the underlying operating system doesn't. Files opened in binary - mode (appending ``'b'`` to the *mode* argument) return contents as - ``bytes`` objects without any decoding. In text mode (the default, or when - ``'t'`` is appended to the *mode* argument) the contents of - the file are returned as strings, the bytes having been first decoded - using a platform-dependent encoding or using the specified *encoding* - if given. + Python distinguishes between files opened in binary and text modes, even when + the underlying operating system doesn't. Files opened in binary mode + (including ``'b'`` in the *mode* argument) return contents as ``bytes`` + objects without any decoding. In text mode (the default, or when ``'t'`` is + included in the *mode* argument), the contents of the file are returned as + strings, the bytes having been first decoded using a platform-dependent + encoding or using the specified *encoding* if given. *buffering* is an optional integer used to set the buffering policy. By - default full buffering is on. Pass 0 to switch buffering off (only allowed in - binary mode), 1 to set line buffering, and an integer > 1 for full buffering. + default full buffering is on. Pass 0 to switch buffering off (only allowed + in binary mode), 1 to set line buffering, and an integer > 1 for full + buffering. *encoding* is the name of the encoding used to decode or encode the file. This should only be used in text mode. The default encoding is platform - dependent, but any encoding supported by Python can be passed. See the - :mod:`codecs` module for the list of supported encodings. - - *errors* is an optional string that specifies how encoding errors are to be - handled---this argument should not be used in binary mode. Pass ``'strict'`` - to raise a :exc:`ValueError` exception if there is an encoding error (the - default of ``None`` has the same effect), or pass ``'ignore'`` to ignore - errors. (Note that ignoring encoding errors can lead to data loss.) See the - documentation for :func:`codecs.register` for a list of the permitted - encoding error strings. + dependent (whatever :func:`locale.getpreferredencoding` returns), but any + encoding supported by Python can be used. See the :mod:`codecs` module for + the list of supported encodings. + + *errors* is an optional string that specifies how encoding and decoding + errors are to be handled--this cannot be used in binary mode. Pass + ``'strict'`` to raise a :exc:`ValueError` exception if there is an encoding + error (the default of ``None`` has the same effect), or pass ``'ignore'`` to + ignore errors. (Note that ignoring encoding errors can lead to data loss.) + ``'replace'`` causes a replacement marker (such as ``'?'``) to be inserted + where there is malformed data. When writing, ``'xmlcharrefreplace'`` + (replace with the appropriate XML character reference) or + ``'backslashreplace'`` (replace with backslashed escape sequences) can be + used. Any other error handling name that has been registered with + :func:`codecs.register_error` is also valid. *newline* controls how universal newlines works (it only applies to text mode). It can be ``None``, ``''``, ``'\n'``, ``'\r'``, and ``'\r\n'``. It Modified: python/branches/py3k/Doc/library/io.rst ============================================================================== --- python/branches/py3k/Doc/library/io.rst (original) +++ python/branches/py3k/Doc/library/io.rst Mon Mar 23 03:44:58 2009 @@ -52,14 +52,14 @@ .. function:: open(file[, mode[, buffering[, encoding[, errors[, newline[, closefd=True]]]]]]) - Open *file* and return a stream. If the file cannot be opened, an - :exc:`IOError` is raised. + Open *file* and return a corresponding stream. If the file cannot be opened, + an :exc:`IOError` is raised. - *file* is either a string giving the name (and the path if the file isn't in - the current working directory) of the file to be opened or a file - descriptor of the file to be opened. (If a file descriptor is given, - for example, from :func:`os.fdopen`, it is closed when the returned - I/O object is closed, unless *closefd* is set to ``False``.) + *file* is either a string or bytes object giving the name (and the path if + the file isn't in the current working directory) of the file to be opened or + an integer file descriptor of the file to be wrapped. (If a file descriptor + is given, it is closed when the returned I/O object is closed, unless + *closefd* is set to ``False``.) *mode* is an optional string that specifies the mode in which the file is opened. It defaults to ``'r'`` which means open for reading in text mode. @@ -102,19 +102,21 @@ *encoding* is the name of the encoding used to decode or encode the file. This should only be used in text mode. The default encoding is platform - dependent, but any encoding supported by Python can be used. See the - :mod:`codecs` module for the list of supported encodings. + dependent (whatever :func:`locale.getpreferredencoding` returns), but any + encoding supported by Python can be used. See the :mod:`codecs` module for + the list of supported encodings. *errors* is an optional string that specifies how encoding and decoding - errors are to be handled. Pass ``'strict'`` to raise a :exc:`ValueError` - exception if there is an encoding error (the default of ``None`` has the same - effect), or pass ``'ignore'`` to ignore errors. (Note that ignoring encoding - errors can lead to data loss.) ``'replace'`` causes a replacement marker - (such as ``'?'``) to be inserted where there is malformed data. When - writing, ``'xmlcharrefreplace'`` (replace with the appropriate XML character - reference) or ``'backslashreplace'`` (replace with backslashed escape - sequences) can be used. Any other error handling name that has been - registered with :func:`codecs.register_error` is also valid. + errors are to be handled--this cannot be used in binary mode. Pass + ``'strict'`` to raise a :exc:`ValueError` exception if there is an encoding + error (the default of ``None`` has the same effect), or pass ``'ignore'`` to + ignore errors. (Note that ignoring encoding errors can lead to data loss.) + ``'replace'`` causes a replacement marker (such as ``'?'``) to be inserted + where there is malformed data. When writing, ``'xmlcharrefreplace'`` + (replace with the appropriate XML character reference) or + ``'backslashreplace'`` (replace with backslashed escape sequences) can be + used. Any other error handling name that has been registered with + :func:`codecs.register_error` is also valid. *newline* controls how universal newlines works (it only applies to text mode). It can be ``None``, ``''``, ``'\n'``, ``'\r'``, and ``'\r\n'``. It From python-checkins at python.org Mon Mar 23 03:49:52 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Mar 2009 03:49:52 +0100 (CET) Subject: [Python-checkins] r70536 - python/branches/py3k/Doc/whatsnew/3.0.rst Message-ID: <20090323024952.6D5111E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 23 03:49:51 2009 New Revision: 70536 Log: more about the file type's death #5513 Modified: python/branches/py3k/Doc/whatsnew/3.0.rst Modified: python/branches/py3k/Doc/whatsnew/3.0.rst ============================================================================== --- python/branches/py3k/Doc/whatsnew/3.0.rst (original) +++ python/branches/py3k/Doc/whatsnew/3.0.rst Mon Mar 23 03:49:51 2009 @@ -813,7 +813,8 @@ * Removed :func:`execfile`. Instead of ``execfile(fn)`` use ``exec(open(fn).read())``. -* Removed :class:`file`. Use :func:`open`. +* Removed the :class:`file` type. Use :func:`open`. There are now several + different kinds of streams that open can return in the :mod:`io` module. * Removed :func:`reduce`. Use :func:`functools.reduce` if you really need it; however, 99 percent of the time an explicit :keyword:`for` From python-checkins at python.org Mon Mar 23 03:54:05 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Mar 2009 03:54:05 +0100 (CET) Subject: [Python-checkins] r70537 - in python/branches/release30-maint: Doc/whatsnew/3.0.rst Message-ID: <20090323025405.8C3C91E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 23 03:54:05 2009 New Revision: 70537 Log: Merged revisions 70536 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70536 | benjamin.peterson | 2009-03-22 21:49:51 -0500 (Sun, 22 Mar 2009) | 1 line more about the file type's death #5513 ........ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Doc/whatsnew/3.0.rst Modified: python/branches/release30-maint/Doc/whatsnew/3.0.rst ============================================================================== --- python/branches/release30-maint/Doc/whatsnew/3.0.rst (original) +++ python/branches/release30-maint/Doc/whatsnew/3.0.rst Mon Mar 23 03:54:05 2009 @@ -813,7 +813,8 @@ * Removed :func:`execfile`. Instead of ``execfile(fn)`` use ``exec(open(fn).read())``. -* Removed :class:`file`. Use :func:`open`. +* Removed the :class:`file` type. Use :func:`open`. There are now several + different kinds of streams that open can return in the :mod:`io` module. * Removed :func:`reduce`. Use :func:`functools.reduce` if you really need it; however, 99 percent of the time an explicit :keyword:`for` From buildbot at python.org Mon Mar 23 05:06:12 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 04:06:12 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090323040612.618E01E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/224 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 3 tests failed: test_distutils test_posix test_subprocess ====================================================================== FAIL: test_get_python_inc (distutils.tests.test_sysconfig.SysconfigTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/distutils/tests/test_sysconfig.py", line 45, in test_get_python_inc self.assert_(os.path.isdir(inc_dir), inc_dir) AssertionError: /home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/Include ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_subprocess.py", line 115, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 05:42:19 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 23 Mar 2009 05:42:19 +0100 (CET) Subject: [Python-checkins] r70538 - python/trunk/Lib/collections.py Message-ID: <20090323044219.50F161E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 23 05:42:18 2009 New Revision: 70538 Log: Move initialization of root link to __init__. Modified: python/trunk/Lib/collections.py Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Mon Mar 23 05:42:18 2009 @@ -41,11 +41,12 @@ try: self.__root except AttributeError: + self.__root = _Link() # sentinel node for the doubly linked list self.clear() self.update(*args, **kwds) def clear(self): - self.__root = root = _Link() # sentinel node for the doubly linked list + root = self.__root root.prev = root.next = root self.__map = {} dict.clear(self) From buildbot at python.org Mon Mar 23 05:51:34 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 04:51:34 +0000 Subject: [Python-checkins] buildbot failure in OS X x86 trunk Message-ID: <20090323045135.828D31E4002@bag.python.org> The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/258 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Abort trap sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 06:19:21 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 23 Mar 2009 06:19:21 +0100 (CET) Subject: [Python-checkins] r70539 - python/branches/py3k/Lib/collections.py Message-ID: <20090323051921.A813F1E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 23 06:19:21 2009 New Revision: 70539 Log: Forward port r70533 and r70538. Modified: python/branches/py3k/Lib/collections.py Modified: python/branches/py3k/Lib/collections.py ============================================================================== --- python/branches/py3k/Lib/collections.py (original) +++ python/branches/py3k/Lib/collections.py Mon Mar 23 06:19:21 2009 @@ -11,74 +11,87 @@ from keyword import iskeyword as _iskeyword import sys as _sys import heapq as _heapq +from weakref import proxy from itertools import repeat as _repeat, chain as _chain, starmap as _starmap ################################################################################ ### OrderedDict ################################################################################ +class _Link(object): + __slots__ = 'prev', 'next', 'key', '__weakref__' + class OrderedDict(dict, MutableMapping): 'Dictionary that remembers insertion order' - # The inherited dict maps keys to values. - # The internal self.__map dictionary maps keys to links in a doubly linked list. - # The doubly linked list starts and ends with a sentinel element. - # The sentinel element never gets deleted. It simplifies the algorithm. - # Setting a new item causes a new link to append to the doubly linked list. - # Deleting an item uses self.__map to find the link, which is then removed. - # Iteration follows the linked list in order. - # Reverse iteration follows the links backwards. + # An inherited dict maps keys to values. # The inherited dict provides __getitem__, __len__, __contains__, and get. # The remaining methods are order-aware. - # Big-Oh running times for all methods are the same as for regular dictionaries. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # The prev/next links are weakref proxies (to prevent circular references). + # Individual links are kept alive by the hard reference in self.__map. + # Those hard references disappear when a key is deleted from an OrderedDict. def __init__(self, *args, **kwds): if len(args) > 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) try: - self.__end + self.__root except AttributeError: + self.__root = _Link() # sentinel node for the doubly linked list self.clear() self.update(*args, **kwds) def clear(self): - self.__end = end = [] - end += [None, end, end] # sentinel node for doubly linked list - self.__map = {} # key --> [key, prev, next] + root = self.__root + root.prev = root.next = root + self.__map = {} dict.clear(self) def __setitem__(self, key, value): + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. if key not in self: - end = self.__end - curr = end[1] - curr[2] = end[1] = self.__map[key] = [key, curr, end] + self.__map[key] = link = _Link() + root = self.__root + last = root.prev + link.prev, link.next, link.key = last, root, key + last.next = root.prev = proxy(link) dict.__setitem__(self, key, value) def __delitem__(self, key): + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. dict.__delitem__(self, key) - key, prev, next = self.__map.pop(key) - prev[2] = next - next[1] = prev + link = self.__map.pop(key) + link.prev.next = link.next + link.next.prev = link.prev def __iter__(self): - end = self.__end - curr = end[2] # start at first link - while curr is not end: - yield curr[0] # yield KEY for each link - curr = curr[2] # goto next link + # Traverse the linked list in order. + root = self.__root + curr = root.next + while curr is not root: + yield curr.key + curr = curr.next def __reversed__(self): - end = self.__end - curr = end[1] # start at last link - while curr is not end: - yield curr[0] # yield KEY for each link - curr = curr[1] # goto prev link + # Traverse the linked list in reverse order. + root = self.__root + curr = root.prev + while curr is not root: + yield curr.key + curr = curr.prev def __reduce__(self): items = [[k, self[k]] for k in self] - tmp = self.__map, self.__end - del self.__map, self.__end + tmp = self.__map, self.__root + del self.__map, self.__root inst_dict = vars(self).copy() - self.__map, self.__end = tmp + self.__map, self.__root = tmp if inst_dict: return (self.__class__, (items,), inst_dict) return self.__class__, (items,) From buildbot at python.org Mon Mar 23 06:43:26 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 05:43:26 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090323054326.5FF661E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/443 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_ssl make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 07:46:56 2009 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 23 Mar 2009 07:46:56 +0100 (CET) Subject: [Python-checkins] r70540 - tracker/roundup-src/roundup/cgi/templating.py Message-ID: <20090323064656.B46641E4036@bag.python.org> Author: martin.v.loewis Date: Mon Mar 23 07:46:56 2009 New Revision: 70540 Log: Validate property names for sorting. Modified: tracker/roundup-src/roundup/cgi/templating.py Modified: tracker/roundup-src/roundup/cgi/templating.py ============================================================================== --- tracker/roundup-src/roundup/cgi/templating.py (original) +++ tracker/roundup-src/roundup/cgi/templating.py Mon Mar 23 07:46:56 2009 @@ -2332,13 +2332,18 @@ dirs.append(self.form.getfirst(dirkey)) if fields: # only try other special char if nothing found break + cls = self.client.db.getclass(self.classname) for f, d in map(None, fields, dirs): if f.startswith('-'): - var.append(('-', f[1:])) + dir, name = '-', f[1:] elif d: - var.append(('-', f)) + dir, name = '-', f else: - var.append(('+', f)) + dir, name = '+', f + if cls.get_transitive_prop(name) is None: + self.client.error_message.append("Unknown property "+name) + else: + var.append((dir, name)) def _post_init(self): """ Set attributes based on self.form From buildbot at python.org Mon Mar 23 07:47:52 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 06:47:52 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090323064752.884A71E405D@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/479 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 08:13:42 2009 From: python-checkins at python.org (martin.v.loewis) Date: Mon, 23 Mar 2009 08:13:42 +0100 (CET) Subject: [Python-checkins] r70541 - tracker/roundup-src/roundup/cgi/templating.py Message-ID: <20090323071342.C15891E4002@bag.python.org> Author: martin.v.loewis Date: Mon Mar 23 08:13:42 2009 New Revision: 70541 Log: Fix previous checkin: only check properties if a classname was given. Modified: tracker/roundup-src/roundup/cgi/templating.py Modified: tracker/roundup-src/roundup/cgi/templating.py ============================================================================== --- tracker/roundup-src/roundup/cgi/templating.py (original) +++ tracker/roundup-src/roundup/cgi/templating.py Mon Mar 23 08:13:42 2009 @@ -2332,7 +2332,9 @@ dirs.append(self.form.getfirst(dirkey)) if fields: # only try other special char if nothing found break - cls = self.client.db.getclass(self.classname) + cls = None + if self.classname: + cls = self.client.db.getclass(self.classname) for f, d in map(None, fields, dirs): if f.startswith('-'): dir, name = '-', f[1:] @@ -2340,7 +2342,7 @@ dir, name = '-', f else: dir, name = '+', f - if cls.get_transitive_prop(name) is None: + if cls and cls.get_transitive_prop(name) is None: self.client.error_message.append("Unknown property "+name) else: var.append((dir, name)) From buildbot at python.org Mon Mar 23 18:45:39 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 17:45:39 +0000 Subject: [Python-checkins] buildbot failure in x86 FreeBSD trunk Message-ID: <20090323174540.114491E401A@bag.python.org> The Buildbot has detected a new failure of x86 FreeBSD trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20FreeBSD%20trunk/builds/1987 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: bolen-freebsd Build Reason: The web-page 'rebuild' button was pressed by '': Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Mon Mar 23 18:53:30 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 17:53:30 +0000 Subject: [Python-checkins] buildbot failure in x86 OpenBSD trunk Message-ID: <20090323175330.39FC41E4002@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%20OpenBSD%20trunk/builds/733 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: cortesi Build Reason: The web-page 'rebuild' button was pressed by '': Build Source Stamp: [branch trunk] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 19:25:13 2009 From: python-checkins at python.org (mark.dickinson) Date: Mon, 23 Mar 2009 19:25:13 +0100 (CET) Subject: [Python-checkins] r70542 - in python/trunk: Misc/NEWS Objects/longobject.c Message-ID: <20090323182513.E4F6D1E4002@bag.python.org> Author: mark.dickinson Date: Mon Mar 23 19:25:13 2009 New Revision: 70542 Log: Issue #5512: speed up the long division algorithm for Python longs. The basic algorithm remains the same; the most significant speedups come from the following three changes: (1) normalize by shifting instead of multiplying and dividing (2) the old algorithm usually did an unnecessary extra iteration of the outer loop; remove this. As a special case, this means that long divisions with a single-digit result run twice as fast as before. (3) make inner loop much tighter. Various benchmarks show speedups of between 50% and 150% for long integer divisions and modulo operations. Modified: python/trunk/Misc/NEWS python/trunk/Objects/longobject.c Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Mon Mar 23 19:25:13 2009 @@ -12,6 +12,10 @@ Core and Builtins ----------------- +- Issue #5512: Rewrite PyLong long division algorithm (x_divrem) to + improve its performance. Long divisions and remainder operations + are now between 50% and 150% faster. + - Issue #4258: Make it possible to use base 2**30 instead of base 2**15 for the internal representation of integers, for performance reasons. Base 2**30 is enabled by default on 64-bit machines. Add Modified: python/trunk/Objects/longobject.c ============================================================================== --- python/trunk/Objects/longobject.c (original) +++ python/trunk/Objects/longobject.c Mon Mar 23 19:25:13 2009 @@ -1074,6 +1074,26 @@ return Py_NotImplemented; \ } +/* bits_in_digit(d) returns the unique integer k such that 2**(k-1) <= d < + 2**k if d is nonzero, else 0. */ + +static const unsigned char BitLengthTable[32] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +}; + +static int +bits_in_digit(digit d) +{ + int d_bits = 0; + while (d >= 32) { + d_bits += 6; + d >>= 6; + } + d_bits += (int)BitLengthTable[d]; + return d_bits; +} + /* x[0:m] and y[0:n] are digit vectors, LSD first, m >= n required. x[0:n] * is modified in place, by adding y to it. Carries are propagated as far as * x[m-1], and the remaining carry (0 or 1) is returned. @@ -1126,25 +1146,41 @@ return borrow; } -/* Multiply by a single digit, ignoring the sign. */ +/* Shift digit vector a[0:m] d bits left, with 0 <= d < PyLong_SHIFT. Put + * result in z[0:m], and return the d bits shifted out of the top. + */ +static digit +v_lshift(digit *z, digit *a, Py_ssize_t m, int d) +{ + Py_ssize_t i; + digit carry = 0; + + assert(0 <= d && d < PyLong_SHIFT); + for (i=0; i < m; i++) { + twodigits acc = (twodigits)a[i] << d | carry; + z[i] = (digit)acc & PyLong_MASK; + carry = (digit)(acc >> PyLong_SHIFT); + } + return carry; +} -static PyLongObject * -mul1(PyLongObject *a, digit n) +/* Shift digit vector a[0:m] d bits right, with 0 <= d < PyLong_SHIFT. Put + * result in z[0:m], and return the d bits shifted out of the bottom. + */ +static digit +v_rshift(digit *z, digit *a, Py_ssize_t m, int d) { - Py_ssize_t size_a = ABS(Py_SIZE(a)); - PyLongObject *z = _PyLong_New(size_a+1); - twodigits carry = 0; Py_ssize_t i; + digit carry = 0; + digit mask = ((digit)1 << d) - 1U; - if (z == NULL) - return NULL; - for (i = 0; i < size_a; ++i) { - carry += (twodigits)a->ob_digit[i] * n; - z->ob_digit[i] = (digit) (carry & PyLong_MASK); - carry >>= PyLong_SHIFT; + assert(0 <= d && d < PyLong_SHIFT); + for (i=m; i-- > 0;) { + twodigits acc = (twodigits)carry << PyLong_SHIFT | a[i]; + carry = (digit)acc & mask; + z[i] = (digit)(acc >> d); } - z->ob_digit[i] = (digit) carry; - return long_normalize(z); + return carry; } /* Divide long pin, w/ size digits, by non-zero digit n, storing quotient @@ -1808,104 +1844,131 @@ return 0; } -/* Unsigned long division with remainder -- the algorithm */ +/* Unsigned long division with remainder -- the algorithm. The arguments v1 + and w1 should satisfy 2 <= ABS(Py_SIZE(w1)) <= ABS(Py_SIZE(v1)). */ static PyLongObject * x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem) { - Py_ssize_t size_v = ABS(Py_SIZE(v1)), size_w = ABS(Py_SIZE(w1)); - digit d = (digit) ((twodigits)PyLong_BASE / (w1->ob_digit[size_w-1] + 1)); - PyLongObject *v = mul1(v1, d); - PyLongObject *w = mul1(w1, d); - PyLongObject *a; - Py_ssize_t j, k; - - if (v == NULL || w == NULL) { - Py_XDECREF(v); - Py_XDECREF(w); + PyLongObject *v, *w, *a; + Py_ssize_t i, k, size_v, size_w; + int d; + digit wm1, wm2, carry, q, r, vtop, *v0, *vk, *w0, *ak; + twodigits vv; + sdigit zhi; + stwodigits z; + + /* We follow Knuth [The Art of Computer Programming, Vol. 2 (3rd + edn.), section 4.3.1, Algorithm D], except that we don't explicitly + handle the special case when the initial estimate q for a quotient + digit is >= PyLong_BASE: the max value for q is PyLong_BASE+1, and + that won't overflow a digit. */ + + /* allocate space; w will also be used to hold the final remainder */ + size_v = ABS(Py_SIZE(v1)); + size_w = ABS(Py_SIZE(w1)); + assert(size_v >= size_w && size_w >= 2); /* Assert checks by div() */ + v = _PyLong_New(size_v+1); + if (v == NULL) { + *prem = NULL; + return NULL; + } + w = _PyLong_New(size_w); + if (w == NULL) { + Py_DECREF(v); + *prem = NULL; return NULL; } - assert(size_v >= size_w && size_w > 1); /* Assert checks by div() */ - assert(Py_REFCNT(v) == 1); /* Since v will be used as accumulator! */ - assert(size_w == ABS(Py_SIZE(w))); /* That's how d was calculated */ + /* normalize: shift w1 left so that its top digit is >= PyLong_BASE/2. + shift v1 left by the same amount. Results go into w and v. */ + d = PyLong_SHIFT - bits_in_digit(w1->ob_digit[size_w-1]); + carry = v_lshift(w->ob_digit, w1->ob_digit, size_w, d); + assert(carry == 0); + carry = v_lshift(v->ob_digit, v1->ob_digit, size_v, d); + if (carry != 0 || v->ob_digit[size_v-1] >= w->ob_digit[size_w-1]) { + v->ob_digit[size_v] = carry; + size_v++; + } - size_v = ABS(Py_SIZE(v)); + /* Now v->ob_digit[size_v-1] < w->ob_digit[size_w-1], so quotient has + at most (and usually exactly) k = size_v - size_w digits. */ k = size_v - size_w; - a = _PyLong_New(k + 1); - - for (j = size_v; a != NULL && k >= 0; --j, --k) { - digit vj = (j >= size_v) ? 0 : v->ob_digit[j]; - twodigits q; - stwodigits carry = 0; - Py_ssize_t i; + assert(k >= 0); + a = _PyLong_New(k); + if (a == NULL) { + Py_DECREF(w); + Py_DECREF(v); + *prem = NULL; + return NULL; + } + v0 = v->ob_digit; + w0 = w->ob_digit; + wm1 = w0[size_w-1]; + wm2 = w0[size_w-2]; + for (vk = v0+k, ak = a->ob_digit + k; vk-- > v0;) { + /* inner loop: divide vk[0:size_w+1] by w0[0:size_w], giving + single-digit quotient q, remainder in vk[0:size_w]. */ SIGCHECK({ Py_DECREF(a); - a = NULL; - break; + Py_DECREF(w); + Py_DECREF(v); + *prem = NULL; + return NULL; }) - if (vj == w->ob_digit[size_w-1]) - q = PyLong_MASK; - else - q = (((twodigits)vj << PyLong_SHIFT) + v->ob_digit[j-1]) / - w->ob_digit[size_w-1]; - while (w->ob_digit[size_w-2]*q > - (( - ((twodigits)vj << PyLong_SHIFT) - + v->ob_digit[j-1] - - q*w->ob_digit[size_w-1] - ) << PyLong_SHIFT) - + v->ob_digit[j-2]) + /* estimate quotient digit q; may overestimate by 1 (rare) */ + vtop = vk[size_w]; + assert(vtop <= wm1); + vv = ((twodigits)vtop << PyLong_SHIFT) | vk[size_w-1]; + q = (digit)(vv / wm1); + r = (digit)(vv - (twodigits)wm1 * q); /* r = vv % wm1 */ + while ((twodigits)wm2 * q > (((twodigits)r << PyLong_SHIFT) + | vk[size_w-2])) { --q; - - for (i = 0; i < size_w && i+k < size_v; ++i) { - twodigits z = w->ob_digit[i] * q; - digit zz = (digit) (z >> PyLong_SHIFT); - carry += v->ob_digit[i+k] - z - + ((twodigits)zz << PyLong_SHIFT); - v->ob_digit[i+k] = (digit)(carry & PyLong_MASK); - carry = Py_ARITHMETIC_RIGHT_SHIFT(PyLong_BASE_TWODIGITS_TYPE, - carry, PyLong_SHIFT); - carry -= zz; - } - - if (i+k < size_v) { - carry += v->ob_digit[i+k]; - v->ob_digit[i+k] = 0; + r += wm1; + if (r >= PyLong_BASE) + break; } + assert(q <= PyLong_BASE); - if (carry == 0) - a->ob_digit[k] = (digit) q; - else { - assert(carry == -1); - a->ob_digit[k] = (digit) q-1; + /* subtract q*w0[0:size_w] from vk[0:size_w+1] */ + zhi = 0; + for (i = 0; i < size_w; ++i) { + /* invariants: -PyLong_BASE <= -q <= zhi <= 0; + -PyLong_BASE * q <= z < PyLong_BASE */ + z = (sdigit)vk[i] + zhi - + (stwodigits)q * (stwodigits)w0[i]; + vk[i] = (digit)z & PyLong_MASK; + zhi = (sdigit)Py_ARITHMETIC_RIGHT_SHIFT(stwodigits, + z, PyLong_SHIFT); + } + + /* add w back if q was too large (this branch taken rarely) */ + assert((sdigit)vtop + zhi == -1 || (sdigit)vtop + zhi == 0); + if ((sdigit)vtop + zhi < 0) { carry = 0; - for (i = 0; i < size_w && i+k < size_v; ++i) { - carry += v->ob_digit[i+k] + w->ob_digit[i]; - v->ob_digit[i+k] = (digit)(carry & PyLong_MASK); - carry = Py_ARITHMETIC_RIGHT_SHIFT( - PyLong_BASE_TWODIGITS_TYPE, - carry, PyLong_SHIFT); + for (i = 0; i < size_w; ++i) { + carry += vk[i] + w0[i]; + vk[i] = carry & PyLong_MASK; + carry >>= PyLong_SHIFT; } + --q; } - } /* for j, k */ - if (a == NULL) - *prem = NULL; - else { - a = long_normalize(a); - *prem = divrem1(v, d, &d); - /* d receives the (unused) remainder */ - if (*prem == NULL) { - Py_DECREF(a); - a = NULL; - } + /* store quotient digit */ + assert(q < PyLong_BASE); + *--ak = q; } + + /* unshift remainder; we reuse w to store the result */ + carry = v_rshift(w0, v0, size_w, d); + assert(carry==0); Py_DECREF(v); - Py_DECREF(w); - return a; + + *prem = long_normalize(w); + return long_normalize(a); } /* Methods */ @@ -3438,11 +3501,6 @@ return PyInt_FromSsize_t(res); } -static const unsigned char BitLengthTable[32] = { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 -}; - static PyObject * long_bit_length(PyLongObject *v) { From python-checkins at python.org Mon Mar 23 19:26:07 2009 From: python-checkins at python.org (mark.dickinson) Date: Mon, 23 Mar 2009 19:26:07 +0100 (CET) Subject: [Python-checkins] r70543 - python/branches/release26-maint Message-ID: <20090323182607.2DD8F1E4002@bag.python.org> Author: mark.dickinson Date: Mon Mar 23 19:26:07 2009 New Revision: 70543 Log: Blocked revisions 70542 via svnmerge ........ r70542 | mark.dickinson | 2009-03-23 18:25:13 +0000 (Mon, 23 Mar 2009) | 14 lines Issue #5512: speed up the long division algorithm for Python longs. The basic algorithm remains the same; the most significant speedups come from the following three changes: (1) normalize by shifting instead of multiplying and dividing (2) the old algorithm usually did an unnecessary extra iteration of the outer loop; remove this. As a special case, this means that long divisions with a single-digit result run twice as fast as before. (3) make inner loop much tighter. Various benchmarks show speedups of between 50% and 150% for long integer divisions and modulo operations. ........ Modified: python/branches/release26-maint/ (props changed) From buildbot at python.org Mon Mar 23 19:26:45 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 18:26:45 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu trunk Message-ID: <20090323182645.8B0A81E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%20trunk/builds/1135 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: The web-page 'rebuild' button was pressed by '': Build Source Stamp: [branch trunk] HEAD Blamelist: antoine.pitrou,benjamin.peterson,bob.ippolito,hirokazu.yamamoto,lars.gustaebel,mark.dickinson,matthias.klose,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/threading.py", line 477, in run self.__target(*self.__args, **self.__kwargs) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/bsddb/test/test_thread.py", line 306, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/bsddb/dbutils.py", line 68, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30994, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') 1 test failed: test_shelve ====================================================================== ERROR: test_update (test.test_shelve.TestAsciiFileShelve) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/mapping_tests.py", line 182, in test_update d = self._empty_mapping() File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_shelve.py", line 108, in _empty_mapping x= shelve.open(self.fn+str(self.counter), **self._args) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/shelve.py", line 234, in open return DbfilenameShelf(filename, flag, protocol, writeback) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/shelve.py", line 218, in __init__ Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/anydbm.py", line 83, in open return mod.open(file, flag, mode) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/dbhash.py", line 19, in open return bsddb.hashopen(file, flag, mode) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/bsddb/__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test_write (test.test_shelve.TestAsciiFileShelve) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/mapping_tests.py", line 107, in test_write d = self._full_mapping(self.reference) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/mapping_tests.py", line 24, in _full_mapping x = self._empty_mapping() File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_shelve.py", line 108, in _empty_mapping x= shelve.open(self.fn+str(self.counter), **self._args) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/shelve.py", line 234, in open return DbfilenameShelf(filename, flag, protocol, writeback) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/shelve.py", line 218, in __init__ Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/anydbm.py", line 83, in open return mod.open(file, flag, mode) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/dbhash.py", line 19, in open return bsddb.hashopen(file, flag, mode) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/bsddb/__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test_update (test.test_shelve.TestBinaryFileShelve) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/mapping_tests.py", line 182, in test_update d = self._empty_mapping() File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_shelve.py", line 108, in _empty_mapping x= shelve.open(self.fn+str(self.counter), **self._args) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/shelve.py", line 234, in open return DbfilenameShelf(filename, flag, protocol, writeback) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/shelve.py", line 218, in __init__ Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/anydbm.py", line 83, in open return mod.open(file, flag, mode) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/dbhash.py", line 19, in open return bsddb.hashopen(file, flag, mode) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/bsddb/__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test_write (test.test_shelve.TestBinaryFileShelve) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/mapping_tests.py", line 107, in test_write d = self._full_mapping(self.reference) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/mapping_tests.py", line 24, in _full_mapping x = self._empty_mapping() File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_shelve.py", line 108, in _empty_mapping x= shelve.open(self.fn+str(self.counter), **self._args) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/shelve.py", line 234, in open return DbfilenameShelf(filename, flag, protocol, writeback) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/shelve.py", line 218, in __init__ Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/anydbm.py", line 83, in open return mod.open(file, flag, mode) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/dbhash.py", line 19, in open return bsddb.hashopen(file, flag, mode) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/bsddb/__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test_update (test.test_shelve.TestProto2FileShelve) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/mapping_tests.py", line 182, in test_update d = self._empty_mapping() File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_shelve.py", line 108, in _empty_mapping x= shelve.open(self.fn+str(self.counter), **self._args) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/shelve.py", line 234, in open return DbfilenameShelf(filename, flag, protocol, writeback) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/shelve.py", line 218, in __init__ Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/anydbm.py", line 83, in open return mod.open(file, flag, mode) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/dbhash.py", line 19, in open return bsddb.hashopen(file, flag, mode) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/bsddb/__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test_write (test.test_shelve.TestProto2FileShelve) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/mapping_tests.py", line 107, in test_write d = self._full_mapping(self.reference) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/mapping_tests.py", line 24, in _full_mapping x = self._empty_mapping() File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_shelve.py", line 108, in _empty_mapping x= shelve.open(self.fn+str(self.counter), **self._args) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/shelve.py", line 234, in open return DbfilenameShelf(filename, flag, protocol, writeback) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/shelve.py", line 218, in __init__ Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/anydbm.py", line 83, in open return mod.open(file, flag, mode) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/dbhash.py", line 19, in open return bsddb.hashopen(file, flag, mode) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/bsddb/__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 19:26:59 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 23 Mar 2009 19:26:59 +0100 (CET) Subject: [Python-checkins] r70544 - python/trunk/Lib/collections.py Message-ID: <20090323182659.EF5E01E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 23 19:26:59 2009 New Revision: 70544 Log: Make imported name private and wrap long-line. Modified: python/trunk/Lib/collections.py Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Mon Mar 23 19:26:59 2009 @@ -10,7 +10,7 @@ from keyword import iskeyword as _iskeyword import sys as _sys import heapq as _heapq -from weakref import proxy +from weakref import proxy as _proxy from itertools import repeat as _repeat, chain as _chain, starmap as _starmap, \ ifilter as _ifilter, imap as _imap, izip as _izip @@ -59,7 +59,7 @@ root = self.__root last = root.prev link.prev, link.next, link.key = last, root, key - last.next = root.prev = proxy(link) + last.next = root.prev = _proxy(link) dict.__setitem__(self, key, value) def __delitem__(self, key): @@ -131,7 +131,8 @@ def __eq__(self, other): if isinstance(other, OrderedDict): - return len(self)==len(other) and all(_imap(_eq, self.items(), other.items())) + return len(self)==len(other) and \ + all(_imap(_eq, self.iteritems(), other.iteritems())) return dict.__eq__(self, other) From python-checkins at python.org Mon Mar 23 19:29:11 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 23 Mar 2009 19:29:11 +0100 (CET) Subject: [Python-checkins] r70545 - python/branches/py3k/Lib/collections.py Message-ID: <20090323182911.570CA1E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 23 19:29:11 2009 New Revision: 70545 Log: Make imported name private and wrap long-line. Modified: python/branches/py3k/Lib/collections.py Modified: python/branches/py3k/Lib/collections.py ============================================================================== --- python/branches/py3k/Lib/collections.py (original) +++ python/branches/py3k/Lib/collections.py Mon Mar 23 19:29:11 2009 @@ -11,7 +11,7 @@ from keyword import iskeyword as _iskeyword import sys as _sys import heapq as _heapq -from weakref import proxy +from weakref import proxy as _proxy from itertools import repeat as _repeat, chain as _chain, starmap as _starmap ################################################################################ @@ -59,7 +59,7 @@ root = self.__root last = root.prev link.prev, link.next, link.key = last, root, key - last.next = root.prev = proxy(link) + last.next = root.prev = _proxy(link) dict.__setitem__(self, key, value) def __delitem__(self, key): @@ -127,7 +127,8 @@ def __eq__(self, other): if isinstance(other, OrderedDict): - return len(self)==len(other) and all(p==q for p, q in zip(self.items(), other.items())) + return len(self)==len(other) and \ + all(p==q for p, q in zip(self.items(), other.items())) return dict.__eq__(self, other) From buildbot at python.org Mon Mar 23 19:31:32 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 18:31:32 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 2.6 Message-ID: <20090323183132.40CE01E4043@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%202.6/builds/183 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Mon Mar 23 19:32:24 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 18:32:24 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu trunk Message-ID: <20090323183224.808CD1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%20trunk/builds/1137 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: mark.dickinson,raymond.hettinger BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Mon Mar 23 19:33:57 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 18:33:57 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 2.6 Message-ID: <20090323183357.776031E4039@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%202.6/builds/195 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Mon Mar 23 19:34:35 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 18:34:35 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090323183435.572681E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/435 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Mon Mar 23 19:37:12 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 18:37:12 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090323183712.B573E1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/539 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed svn sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 19:41:46 2009 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 23 Mar 2009 19:41:46 +0100 (CET) Subject: [Python-checkins] r70546 - in python/trunk: Doc/library/gc.rst Include/dictobject.h Include/objimpl.h Include/tupleobject.h Lib/test/test_dict.py Lib/test/test_gc.py Lib/test/test_tuple.py Misc/NEWS Modules/gcmodule.c Objects/dictobject.c Objects/tupleobject.c Message-ID: <20090323184146.3CC0D1E4002@bag.python.org> Author: antoine.pitrou Date: Mon Mar 23 19:41:45 2009 New Revision: 70546 Log: Issue #4688: Add a heuristic so that tuples and dicts containing only untrackable objects are not tracked by the garbage collector. This can reduce the size of collections and therefore the garbage collection overhead on long-running programs, depending on their particular use of datatypes. (trivia: this makes the "binary_trees" benchmark from the Computer Language Shootout 40% faster) Modified: python/trunk/Doc/library/gc.rst python/trunk/Include/dictobject.h python/trunk/Include/objimpl.h python/trunk/Include/tupleobject.h python/trunk/Lib/test/test_dict.py python/trunk/Lib/test/test_gc.py python/trunk/Lib/test/test_tuple.py python/trunk/Misc/NEWS python/trunk/Modules/gcmodule.c python/trunk/Objects/dictobject.c python/trunk/Objects/tupleobject.c Modified: python/trunk/Doc/library/gc.rst ============================================================================== --- python/trunk/Doc/library/gc.rst (original) +++ python/trunk/Doc/library/gc.rst Mon Mar 23 19:41:45 2009 @@ -140,6 +140,31 @@ .. versionadded:: 2.3 +.. function:: is_tracked(obj) + + Returns True if the object is currently tracked by the garbage collector, + False otherwise. As a general rule, instances of atomic types aren't + tracked and instances of non-atomic types (containers, user-defined + objects...) are. However, some type-specific optimizations can be present + in order to suppress the garbage collector footprint of simple instances + (e.g. dicts containing only atomic keys and values):: + + >>> gc.is_tracked(0) + False + >>> gc.is_tracked("a") + False + >>> gc.is_tracked([]) + True + >>> gc.is_tracked({}) + False + >>> gc.is_tracked({"a": 1}) + False + >>> gc.is_tracked({"a": []}) + True + + .. versionadded:: 2.7 + + The following variable is provided for read-only access (you can mutate its value but should not rebind it): Modified: python/trunk/Include/dictobject.h ============================================================================== --- python/trunk/Include/dictobject.h (original) +++ python/trunk/Include/dictobject.h Mon Mar 23 19:41:45 2009 @@ -111,6 +111,7 @@ PyAPI_FUNC(int) PyDict_Contains(PyObject *mp, PyObject *key); PyAPI_FUNC(int) _PyDict_Contains(PyObject *mp, PyObject *key, long hash); PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused); +PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp); /* PyDict_Update(mp, other) is equivalent to PyDict_Merge(mp, other, 1). */ PyAPI_FUNC(int) PyDict_Update(PyObject *mp, PyObject *other); Modified: python/trunk/Include/objimpl.h ============================================================================== --- python/trunk/Include/objimpl.h (original) +++ python/trunk/Include/objimpl.h Mon Mar 23 19:41:45 2009 @@ -285,6 +285,17 @@ g->gc.gc_next = NULL; \ } while (0); +/* True if the object is currently tracked by the GC. */ +#define _PyObject_GC_IS_TRACKED(o) \ + ((_Py_AS_GC(o))->gc.gc_refs != _PyGC_REFS_UNTRACKED) + +/* True if the object may be tracked by the GC in the future, or already is. + This can be useful to implement some optimizations. */ +#define _PyObject_GC_MAY_BE_TRACKED(obj) \ + (PyObject_IS_GC(obj) && \ + (!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj))) + + PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t); PyAPI_FUNC(PyObject *) _PyObject_GC_New(PyTypeObject *); PyAPI_FUNC(PyVarObject *) _PyObject_GC_NewVar(PyTypeObject *, Py_ssize_t); Modified: python/trunk/Include/tupleobject.h ============================================================================== --- python/trunk/Include/tupleobject.h (original) +++ python/trunk/Include/tupleobject.h Mon Mar 23 19:41:45 2009 @@ -44,6 +44,7 @@ PyAPI_FUNC(PyObject *) PyTuple_GetSlice(PyObject *, Py_ssize_t, Py_ssize_t); PyAPI_FUNC(int) _PyTuple_Resize(PyObject **, Py_ssize_t); PyAPI_FUNC(PyObject *) PyTuple_Pack(Py_ssize_t, ...); +PyAPI_FUNC(void) _PyTuple_MaybeUntrack(PyObject *); /* Macro, trading safety for speed */ #define PyTuple_GET_ITEM(op, i) (((PyTupleObject *)(op))->ob_item[i]) Modified: python/trunk/Lib/test/test_dict.py ============================================================================== --- python/trunk/Lib/test/test_dict.py (original) +++ python/trunk/Lib/test/test_dict.py Mon Mar 23 19:41:45 2009 @@ -569,6 +569,104 @@ gc.collect() self.assert_(ref() is None, "Cycle was not collected") + def _not_tracked(self, t): + # Nested containers can take several collections to untrack + gc.collect() + gc.collect() + self.assertFalse(gc.is_tracked(t), t) + + def _tracked(self, t): + self.assertTrue(gc.is_tracked(t), t) + gc.collect() + gc.collect() + self.assertTrue(gc.is_tracked(t), t) + + def test_track_literals(self): + # Test GC-optimization of dict literals + x, y, z, w = 1.5, "a", (1, None), [] + + self._not_tracked({}) + self._not_tracked({x:(), y:x, z:1}) + self._not_tracked({1: "a", "b": 2}) + self._not_tracked({1: 2, (None, True, False, ()): int}) + self._not_tracked({1: object()}) + + # Dicts with mutable elements are always tracked, even if those + # elements are not tracked right now. + self._tracked({1: []}) + self._tracked({1: ([],)}) + self._tracked({1: {}}) + self._tracked({1: set()}) + + def test_track_dynamic(self): + # Test GC-optimization of dynamically-created dicts + class MyObject(object): + pass + x, y, z, w, o = 1.5, "a", (1, object()), [], MyObject() + + d = dict() + self._not_tracked(d) + d[1] = "a" + self._not_tracked(d) + d[y] = 2 + self._not_tracked(d) + d[z] = 3 + self._not_tracked(d) + self._not_tracked(d.copy()) + d[4] = w + self._tracked(d) + self._tracked(d.copy()) + d[4] = None + self._not_tracked(d) + self._not_tracked(d.copy()) + + # dd isn't tracked right now, but it may mutate and therefore d + # which contains it must be tracked. + d = dict() + dd = dict() + d[1] = dd + self._not_tracked(dd) + self._tracked(d) + dd[1] = d + self._tracked(dd) + + d = dict.fromkeys([x, y, z]) + self._not_tracked(d) + dd = dict() + dd.update(d) + self._not_tracked(dd) + d = dict.fromkeys([x, y, z, o]) + self._tracked(d) + dd = dict() + dd.update(d) + self._tracked(dd) + + d = dict(x=x, y=y, z=z) + self._not_tracked(d) + d = dict(x=x, y=y, z=z, w=w) + self._tracked(d) + d = dict() + d.update(x=x, y=y, z=z) + self._not_tracked(d) + d.update(w=w) + self._tracked(d) + + d = dict([(x, y), (z, 1)]) + self._not_tracked(d) + d = dict([(x, y), (z, w)]) + self._tracked(d) + d = dict() + d.update([(x, y), (z, 1)]) + self._not_tracked(d) + d.update([(x, y), (z, w)]) + self._tracked(d) + + def test_track_subtypes(self): + # Dict subtypes are always tracked + class MyDict(dict): + pass + self._tracked(MyDict()) + from test import mapping_tests Modified: python/trunk/Lib/test/test_gc.py ============================================================================== --- python/trunk/Lib/test/test_gc.py (original) +++ python/trunk/Lib/test/test_gc.py Mon Mar 23 19:41:45 2009 @@ -415,6 +415,37 @@ self.assertEqual(gc.get_referents(1, 'a', 4j), []) + def test_is_tracked(self): + # Atomic built-in types are not tracked, user-defined objects and + # mutable containers are. + # NOTE: types with special optimizations (e.g. tuple) have tests + # in their own test files instead. + self.assertFalse(gc.is_tracked(None)) + self.assertFalse(gc.is_tracked(1)) + self.assertFalse(gc.is_tracked(1.0)) + self.assertFalse(gc.is_tracked(1.0 + 5.0j)) + self.assertFalse(gc.is_tracked(True)) + self.assertFalse(gc.is_tracked(False)) + self.assertFalse(gc.is_tracked("a")) + self.assertFalse(gc.is_tracked(u"a")) + self.assertFalse(gc.is_tracked(bytearray("a"))) + self.assertFalse(gc.is_tracked(type)) + self.assertFalse(gc.is_tracked(int)) + self.assertFalse(gc.is_tracked(object)) + self.assertFalse(gc.is_tracked(object())) + + class OldStyle: + pass + class NewStyle(object): + pass + self.assertTrue(gc.is_tracked(gc)) + self.assertTrue(gc.is_tracked(OldStyle)) + self.assertTrue(gc.is_tracked(OldStyle())) + self.assertTrue(gc.is_tracked(NewStyle)) + self.assertTrue(gc.is_tracked(NewStyle())) + self.assertTrue(gc.is_tracked([])) + self.assertTrue(gc.is_tracked(set())) + def test_bug1055820b(self): # Corresponds to temp2b.py in the bug report. Modified: python/trunk/Lib/test/test_tuple.py ============================================================================== --- python/trunk/Lib/test/test_tuple.py (original) +++ python/trunk/Lib/test/test_tuple.py Mon Mar 23 19:41:45 2009 @@ -1,5 +1,7 @@ from test import test_support, seq_tests +import gc + class TupleTest(seq_tests.CommonTest): type2test = tuple @@ -82,6 +84,69 @@ self.assertEqual(repr(a0), "()") self.assertEqual(repr(a2), "(0, 1, 2)") + def _not_tracked(self, t): + # Nested tuples can take several collections to untrack + gc.collect() + gc.collect() + self.assertFalse(gc.is_tracked(t), t) + + def _tracked(self, t): + self.assertTrue(gc.is_tracked(t), t) + gc.collect() + gc.collect() + self.assertTrue(gc.is_tracked(t), t) + + def test_track_literals(self): + # Test GC-optimization of tuple literals + x, y, z = 1.5, "a", [] + + self._not_tracked(()) + self._not_tracked((1,)) + self._not_tracked((1, 2)) + self._not_tracked((1, 2, "a")) + self._not_tracked((1, 2, (None, True, False, ()), int)) + self._not_tracked((object(),)) + self._not_tracked(((1, x), y, (2, 3))) + + # Tuples with mutable elements are always tracked, even if those + # elements are not tracked right now. + self._tracked(([],)) + self._tracked(([1],)) + self._tracked(({},)) + self._tracked((set(),)) + self._tracked((x, y, z)) + + def check_track_dynamic(self, tp, always_track): + x, y, z = 1.5, "a", [] + + check = self._tracked if always_track else self._not_tracked + check(tp()) + check(tp([])) + check(tp(set())) + check(tp([1, x, y])) + check(tp(obj for obj in [1, x, y])) + check(tp(set([1, x, y]))) + check(tp(tuple([obj]) for obj in [1, x, y])) + check(tuple(tp([obj]) for obj in [1, x, y])) + + self._tracked(tp([z])) + self._tracked(tp([[x, y]])) + self._tracked(tp([{x: y}])) + self._tracked(tp(obj for obj in [x, y, z])) + self._tracked(tp(tuple([obj]) for obj in [x, y, z])) + self._tracked(tuple(tp([obj]) for obj in [x, y, z])) + + def test_track_dynamic(self): + # Test GC-optimization of dynamically constructed tuples. + self.check_track_dynamic(tuple, False) + + def test_track_subtypes(self): + # Tuple subtypes must always be tracked + class MyTuple(tuple): + pass + self.check_track_dynamic(MyTuple, True) + + def test_main(): test_support.run_unittest(TupleTest) Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Mon Mar 23 19:41:45 2009 @@ -12,6 +12,11 @@ Core and Builtins ----------------- +- Issue #4688: Add a heuristic so that tuples and dicts containing only + untrackable objects are not tracked by the garbage collector. This can + reduce the size of collections and therefore the garbage collection overhead + on long-running programs, depending on their particular use of datatypes. + - Issue #5512: Rewrite PyLong long division algorithm (x_divrem) to improve its performance. Long divisions and remainder operations are now between 50% and 150% faster. Modified: python/trunk/Modules/gcmodule.c ============================================================================== --- python/trunk/Modules/gcmodule.c (original) +++ python/trunk/Modules/gcmodule.c Mon Mar 23 19:41:45 2009 @@ -432,7 +432,13 @@ (void) traverse(op, (visitproc)visit_reachable, (void *)young); - next = gc->gc.gc_next; + next = gc->gc.gc_next; + if (PyTuple_CheckExact(op)) { + _PyTuple_MaybeUntrack(op); + } + else if (PyDict_CheckExact(op)) { + _PyDict_MaybeUntrack(op); + } } else { /* This *may* be unreachable. To make progress, @@ -1264,6 +1270,26 @@ return result; } +PyDoc_STRVAR(gc_is_tracked__doc__, +"is_tracked(obj) -> bool\n" +"\n" +"Returns true if the object is tracked by the garbage collector.\n" +"Simple atomic objects will return false.\n" +); + +static PyObject * +gc_is_tracked(PyObject *self, PyObject *obj) +{ + PyObject *result; + + if (PyObject_IS_GC(obj) && IS_TRACKED(obj)) + result = Py_True; + else + result = Py_False; + Py_INCREF(result); + return result; +} + PyDoc_STRVAR(gc__doc__, "This module provides access to the garbage collector for reference cycles.\n" @@ -1278,6 +1304,7 @@ "set_threshold() -- Set the collection thresholds.\n" "get_threshold() -- Return the current the collection thresholds.\n" "get_objects() -- Return a list of all objects tracked by the collector.\n" +"is_tracked() -- Returns true if a given object is tracked.\n" "get_referrers() -- Return the list of objects that refer to an object.\n" "get_referents() -- Return the list of objects that an object refers to.\n"); @@ -1293,6 +1320,7 @@ {"collect", (PyCFunction)gc_collect, METH_VARARGS | METH_KEYWORDS, gc_collect__doc__}, {"get_objects", gc_get_objects,METH_NOARGS, gc_get_objects__doc__}, + {"is_tracked", gc_is_tracked, METH_O, gc_is_tracked__doc__}, {"get_referrers", gc_get_referrers, METH_VARARGS, gc_get_referrers__doc__}, {"get_referents", gc_get_referents, METH_VARARGS, Modified: python/trunk/Objects/dictobject.c ============================================================================== --- python/trunk/Objects/dictobject.c (original) +++ python/trunk/Objects/dictobject.c Mon Mar 23 19:41:45 2009 @@ -180,6 +180,24 @@ } #endif +/* Debug statistic to count GC tracking of dicts */ +#ifdef SHOW_TRACK_COUNT +static Py_ssize_t count_untracked = 0; +static Py_ssize_t count_tracked = 0; + +static void +show_track(void) +{ + fprintf(stderr, "Dicts created: %" PY_FORMAT_SIZE_T "d\n", + count_tracked + count_untracked); + fprintf(stderr, "Dicts tracked by the GC: %" PY_FORMAT_SIZE_T + "d\n", count_tracked); + fprintf(stderr, "%.2f%% dict tracking rate\n\n", + (100.0*count_tracked/(count_untracked+count_tracked))); +} +#endif + + /* Initialization macros. There are two ways to create a dict: PyDict_New() is the main C API function, and the tp_new slot maps to dict_new(). In the latter case we @@ -233,6 +251,9 @@ #ifdef SHOW_ALLOC_COUNT Py_AtExit(show_alloc); #endif +#ifdef SHOW_TRACK_COUNT + Py_AtExit(show_track); +#endif } if (numfree) { mp = free_list[--numfree]; @@ -262,10 +283,12 @@ #endif } mp->ma_lookup = lookdict_string; +#ifdef SHOW_TRACK_COUNT + count_untracked++; +#endif #ifdef SHOW_CONVERSION_COUNTS ++created; #endif - _PyObject_GC_TRACK(mp); return (PyObject *)mp; } @@ -433,6 +456,52 @@ return 0; } +#ifdef SHOW_TRACK_COUNT +#define INCREASE_TRACK_COUNT \ + (count_tracked++, count_untracked--); +#define DECREASE_TRACK_COUNT \ + (count_tracked--, count_untracked++); +#else +#define INCREASE_TRACK_COUNT +#define DECREASE_TRACK_COUNT +#endif + +#define MAINTAIN_TRACKING(mp, key, value) \ + do { \ + if (!_PyObject_GC_IS_TRACKED(mp)) { \ + if (_PyObject_GC_MAY_BE_TRACKED(key) || \ + _PyObject_GC_MAY_BE_TRACKED(value)) { \ + _PyObject_GC_TRACK(mp); \ + INCREASE_TRACK_COUNT \ + } \ + } \ + } while(0) + +void +_PyDict_MaybeUntrack(PyObject *op) +{ + PyDictObject *mp; + PyObject *value; + Py_ssize_t mask, i; + PyDictEntry *ep; + + if (!PyDict_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op)) + return; + + mp = (PyDictObject *) op; + ep = mp->ma_table; + mask = mp->ma_mask; + for (i = 0; i <= mask; i++) { + if ((value = ep[i].me_value) == NULL) + continue; + if (_PyObject_GC_MAY_BE_TRACKED(value) || + _PyObject_GC_MAY_BE_TRACKED(ep[i].me_key)) + return; + } + _PyObject_GC_UNTRACK(op); +} + + /* Internal routine to insert a new item into the table. Used both by the internal resize routine and by the public insert routine. @@ -453,6 +522,7 @@ Py_DECREF(value); return -1; } + MAINTAIN_TRACKING(mp, key, value); if (ep->me_value != NULL) { old_value = ep->me_value; ep->me_value = value; @@ -492,6 +562,7 @@ PyDictEntry *ep0 = mp->ma_table; register PyDictEntry *ep; + MAINTAIN_TRACKING(mp, key, value); i = hash & mask; ep = &ep0[i]; for (perturb = hash; ep->me_key != NULL; perturb >>= PERTURB_SHIFT) { @@ -2202,9 +2273,18 @@ assert(d->ma_table == NULL && d->ma_fill == 0 && d->ma_used == 0); INIT_NONZERO_DICT_SLOTS(d); d->ma_lookup = lookdict_string; + /* The object has been implicitely tracked by tp_alloc */ + if (type == &PyDict_Type) + _PyObject_GC_UNTRACK(d); #ifdef SHOW_CONVERSION_COUNTS ++created; #endif +#ifdef SHOW_TRACK_COUNT + if (_PyObject_GC_IS_TRACKED(d)) + count_tracked++; + else + count_untracked++; +#endif } return self; } Modified: python/trunk/Objects/tupleobject.c ============================================================================== --- python/trunk/Objects/tupleobject.c (original) +++ python/trunk/Objects/tupleobject.c Mon Mar 23 19:41:45 2009 @@ -23,11 +23,36 @@ Py_ssize_t tuple_zero_allocs; #endif +/* Debug statistic to count GC tracking of tuples. + Please note that tuples are only untracked when considered by the GC, and + many of them will be dead before. Therefore, a tracking rate close to 100% + does not necessarily prove that the heuristic is inefficient. +*/ +#ifdef SHOW_TRACK_COUNT +static Py_ssize_t count_untracked = 0; +static Py_ssize_t count_tracked = 0; + +static void +show_track(void) +{ + fprintf(stderr, "Tuples created: %" PY_FORMAT_SIZE_T "d\n", + count_tracked + count_untracked); + fprintf(stderr, "Tuples tracked by the GC: %" PY_FORMAT_SIZE_T + "d\n", count_tracked); + fprintf(stderr, "%.2f%% tuple tracking rate\n\n", + (100.0*count_tracked/(count_untracked+count_tracked))); +} +#endif + + PyObject * PyTuple_New(register Py_ssize_t size) { register PyTupleObject *op; Py_ssize_t i; +#ifdef SHOW_TRACK_COUNT + count_tracked++; +#endif if (size < 0) { PyErr_BadInternalCall(); return NULL; @@ -131,6 +156,32 @@ return 0; } +void +_PyTuple_MaybeUntrack(PyObject *op) +{ + PyTupleObject *t; + Py_ssize_t i, n; + + if (!PyTuple_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op)) + return; + t = (PyTupleObject *) op; + n = Py_SIZE(t); + for (i = 0; i < n; i++) { + PyObject *elt = PyTuple_GET_ITEM(t, i); + /* Tuple with NULL elements aren't + fully constructed, don't untrack + them yet. */ + if (!elt || + _PyObject_GC_MAY_BE_TRACKED(elt)) + return; + } +#ifdef SHOW_TRACK_COUNT + count_tracked--; + count_untracked++; +#endif + _PyObject_GC_UNTRACK(op); +} + PyObject * PyTuple_Pack(Py_ssize_t n, ...) { @@ -880,6 +931,9 @@ (void)PyTuple_ClearFreeList(); #endif +#ifdef SHOW_TRACK_COUNT + show_track(); +#endif } /*********************** Tuple Iterator **************************/ From python-checkins at python.org Mon Mar 23 19:44:57 2009 From: python-checkins at python.org (mark.dickinson) Date: Mon, 23 Mar 2009 19:44:57 +0100 (CET) Subject: [Python-checkins] r70547 - in python/branches/py3k: Misc/NEWS Objects/longobject.c Message-ID: <20090323184457.EFB9B1E4002@bag.python.org> Author: mark.dickinson Date: Mon Mar 23 19:44:57 2009 New Revision: 70547 Log: Merged revisions 70542 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70542 | mark.dickinson | 2009-03-23 18:25:13 +0000 (Mon, 23 Mar 2009) | 14 lines Issue #5512: speed up the long division algorithm for Python longs. The basic algorithm remains the same; the most significant speedups come from the following three changes: (1) normalize by shifting instead of multiplying and dividing (2) the old algorithm usually did an unnecessary extra iteration of the outer loop; remove this. As a special case, this means that long divisions with a single-digit result run twice as fast as before. (3) make inner loop much tighter. Various benchmarks show speedups of between 50% and 150% for long integer divisions and modulo operations. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/longobject.c Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Mon Mar 23 19:44:57 2009 @@ -12,6 +12,10 @@ Core and Builtins ----------------- +- Issue #5512: Rewrite PyLong long division algorithm (x_divrem) to + improve its performance. Long divisions and remainder operations + are now between 50% and 150% faster. + - Issue #4258: Make it possible to use base 2**30 instead of base 2**15 for the internal representation of integers, for performance reasons. Base 2**30 is enabled by default on 64-bit machines. Add Modified: python/branches/py3k/Objects/longobject.c ============================================================================== --- python/branches/py3k/Objects/longobject.c (original) +++ python/branches/py3k/Objects/longobject.c Mon Mar 23 19:44:57 2009 @@ -1363,6 +1363,26 @@ return Py_NotImplemented; \ } +/* bits_in_digit(d) returns the unique integer k such that 2**(k-1) <= d < + 2**k if d is nonzero, else 0. */ + +static const unsigned char BitLengthTable[32] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +}; + +static int +bits_in_digit(digit d) +{ + int d_bits = 0; + while (d >= 32) { + d_bits += 6; + d >>= 6; + } + d_bits += (int)BitLengthTable[d]; + return d_bits; +} + /* x[0:m] and y[0:n] are digit vectors, LSD first, m >= n required. x[0:n] * is modified in place, by adding y to it. Carries are propagated as far as * x[m-1], and the remaining carry (0 or 1) is returned. @@ -1415,25 +1435,41 @@ return borrow; } -/* Multiply by a single digit, ignoring the sign. */ +/* Shift digit vector a[0:m] d bits left, with 0 <= d < PyLong_SHIFT. Put + * result in z[0:m], and return the d bits shifted out of the top. + */ +static digit +v_lshift(digit *z, digit *a, Py_ssize_t m, int d) +{ + Py_ssize_t i; + digit carry = 0; + + assert(0 <= d && d < PyLong_SHIFT); + for (i=0; i < m; i++) { + twodigits acc = (twodigits)a[i] << d | carry; + z[i] = (digit)acc & PyLong_MASK; + carry = (digit)(acc >> PyLong_SHIFT); + } + return carry; +} -static PyLongObject * -mul1(PyLongObject *a, digit n) +/* Shift digit vector a[0:m] d bits right, with 0 <= d < PyLong_SHIFT. Put + * result in z[0:m], and return the d bits shifted out of the bottom. + */ +static digit +v_rshift(digit *z, digit *a, Py_ssize_t m, int d) { - Py_ssize_t size_a = ABS(Py_SIZE(a)); - PyLongObject *z = _PyLong_New(size_a+1); - twodigits carry = 0; Py_ssize_t i; + digit carry = 0; + digit mask = ((digit)1 << d) - 1U; - if (z == NULL) - return NULL; - for (i = 0; i < size_a; ++i) { - carry += (twodigits)a->ob_digit[i] * n; - z->ob_digit[i] = (digit) (carry & PyLong_MASK); - carry >>= PyLong_SHIFT; + assert(0 <= d && d < PyLong_SHIFT); + for (i=m; i-- > 0;) { + twodigits acc = (twodigits)carry << PyLong_SHIFT | a[i]; + carry = (digit)acc & mask; + z[i] = (digit)(acc >> d); } - z->ob_digit[i] = (digit) carry; - return long_normalize(z); + return carry; } /* Divide long pin, w/ size digits, by non-zero digit n, storing quotient @@ -2089,104 +2125,131 @@ return 0; } -/* Unsigned long division with remainder -- the algorithm */ +/* Unsigned long division with remainder -- the algorithm. The arguments v1 + and w1 should satisfy 2 <= ABS(Py_SIZE(w1)) <= ABS(Py_SIZE(v1)). */ static PyLongObject * x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem) { - Py_ssize_t size_v = ABS(Py_SIZE(v1)), size_w = ABS(Py_SIZE(w1)); - digit d = (digit) ((twodigits)PyLong_BASE / (w1->ob_digit[size_w-1] + 1)); - PyLongObject *v = mul1(v1, d); - PyLongObject *w = mul1(w1, d); - PyLongObject *a; - Py_ssize_t j, k; - - if (v == NULL || w == NULL) { - Py_XDECREF(v); - Py_XDECREF(w); + PyLongObject *v, *w, *a; + Py_ssize_t i, k, size_v, size_w; + int d; + digit wm1, wm2, carry, q, r, vtop, *v0, *vk, *w0, *ak; + twodigits vv; + sdigit zhi; + stwodigits z; + + /* We follow Knuth [The Art of Computer Programming, Vol. 2 (3rd + edn.), section 4.3.1, Algorithm D], except that we don't explicitly + handle the special case when the initial estimate q for a quotient + digit is >= PyLong_BASE: the max value for q is PyLong_BASE+1, and + that won't overflow a digit. */ + + /* allocate space; w will also be used to hold the final remainder */ + size_v = ABS(Py_SIZE(v1)); + size_w = ABS(Py_SIZE(w1)); + assert(size_v >= size_w && size_w >= 2); /* Assert checks by div() */ + v = _PyLong_New(size_v+1); + if (v == NULL) { + *prem = NULL; + return NULL; + } + w = _PyLong_New(size_w); + if (w == NULL) { + Py_DECREF(v); + *prem = NULL; return NULL; } - assert(size_v >= size_w && size_w > 1); /* Assert checks by div() */ - assert(Py_REFCNT(v) == 1); /* Since v will be used as accumulator! */ - assert(size_w == ABS(Py_SIZE(w))); /* That's how d was calculated */ + /* normalize: shift w1 left so that its top digit is >= PyLong_BASE/2. + shift v1 left by the same amount. Results go into w and v. */ + d = PyLong_SHIFT - bits_in_digit(w1->ob_digit[size_w-1]); + carry = v_lshift(w->ob_digit, w1->ob_digit, size_w, d); + assert(carry == 0); + carry = v_lshift(v->ob_digit, v1->ob_digit, size_v, d); + if (carry != 0 || v->ob_digit[size_v-1] >= w->ob_digit[size_w-1]) { + v->ob_digit[size_v] = carry; + size_v++; + } - size_v = ABS(Py_SIZE(v)); + /* Now v->ob_digit[size_v-1] < w->ob_digit[size_w-1], so quotient has + at most (and usually exactly) k = size_v - size_w digits. */ k = size_v - size_w; - a = _PyLong_New(k + 1); - - for (j = size_v; a != NULL && k >= 0; --j, --k) { - digit vj = (j >= size_v) ? 0 : v->ob_digit[j]; - twodigits q; - stwodigits carry = 0; - Py_ssize_t i; + assert(k >= 0); + a = _PyLong_New(k); + if (a == NULL) { + Py_DECREF(w); + Py_DECREF(v); + *prem = NULL; + return NULL; + } + v0 = v->ob_digit; + w0 = w->ob_digit; + wm1 = w0[size_w-1]; + wm2 = w0[size_w-2]; + for (vk = v0+k, ak = a->ob_digit + k; vk-- > v0;) { + /* inner loop: divide vk[0:size_w+1] by w0[0:size_w], giving + single-digit quotient q, remainder in vk[0:size_w]. */ SIGCHECK({ Py_DECREF(a); - a = NULL; - break; + Py_DECREF(w); + Py_DECREF(v); + *prem = NULL; + return NULL; }) - if (vj == w->ob_digit[size_w-1]) - q = PyLong_MASK; - else - q = (((twodigits)vj << PyLong_SHIFT) + v->ob_digit[j-1]) / - w->ob_digit[size_w-1]; - while (w->ob_digit[size_w-2]*q > - (( - ((twodigits)vj << PyLong_SHIFT) - + v->ob_digit[j-1] - - q*w->ob_digit[size_w-1] - ) << PyLong_SHIFT) - + v->ob_digit[j-2]) + /* estimate quotient digit q; may overestimate by 1 (rare) */ + vtop = vk[size_w]; + assert(vtop <= wm1); + vv = ((twodigits)vtop << PyLong_SHIFT) | vk[size_w-1]; + q = (digit)(vv / wm1); + r = (digit)(vv - (twodigits)wm1 * q); /* r = vv % wm1 */ + while ((twodigits)wm2 * q > (((twodigits)r << PyLong_SHIFT) + | vk[size_w-2])) { --q; - - for (i = 0; i < size_w && i+k < size_v; ++i) { - twodigits z = w->ob_digit[i] * q; - digit zz = (digit) (z >> PyLong_SHIFT); - carry += v->ob_digit[i+k] - z - + ((twodigits)zz << PyLong_SHIFT); - v->ob_digit[i+k] = (digit)(carry & PyLong_MASK); - carry = Py_ARITHMETIC_RIGHT_SHIFT(stwodigits, - carry, PyLong_SHIFT); - carry -= zz; - } - - if (i+k < size_v) { - carry += v->ob_digit[i+k]; - v->ob_digit[i+k] = 0; + r += wm1; + if (r >= PyLong_BASE) + break; } + assert(q <= PyLong_BASE); - if (carry == 0) - a->ob_digit[k] = (digit) q; - else { - assert(carry == -1); - a->ob_digit[k] = (digit) q-1; + /* subtract q*w0[0:size_w] from vk[0:size_w+1] */ + zhi = 0; + for (i = 0; i < size_w; ++i) { + /* invariants: -PyLong_BASE <= -q <= zhi <= 0; + -PyLong_BASE * q <= z < PyLong_BASE */ + z = (sdigit)vk[i] + zhi - + (stwodigits)q * (stwodigits)w0[i]; + vk[i] = (digit)z & PyLong_MASK; + zhi = (sdigit)Py_ARITHMETIC_RIGHT_SHIFT(stwodigits, + z, PyLong_SHIFT); + } + + /* add w back if q was too large (this branch taken rarely) */ + assert((sdigit)vtop + zhi == -1 || (sdigit)vtop + zhi == 0); + if ((sdigit)vtop + zhi < 0) { carry = 0; - for (i = 0; i < size_w && i+k < size_v; ++i) { - carry += v->ob_digit[i+k] + w->ob_digit[i]; - v->ob_digit[i+k] = (digit)(carry & PyLong_MASK); - carry = Py_ARITHMETIC_RIGHT_SHIFT( - stwodigits, - carry, PyLong_SHIFT); + for (i = 0; i < size_w; ++i) { + carry += vk[i] + w0[i]; + vk[i] = carry & PyLong_MASK; + carry >>= PyLong_SHIFT; } + --q; } - } /* for j, k */ - if (a == NULL) - *prem = NULL; - else { - a = long_normalize(a); - *prem = divrem1(v, d, &d); - /* d receives the (unused) remainder */ - if (*prem == NULL) { - Py_DECREF(a); - a = NULL; - } + /* store quotient digit */ + assert(q < PyLong_BASE); + *--ak = q; } + + /* unshift remainder; we reuse w to store the result */ + carry = v_rshift(w0, v0, size_w, d); + assert(carry==0); Py_DECREF(v); - Py_DECREF(w); - return a; + + *prem = long_normalize(w); + return long_normalize(a); } /* Methods */ @@ -3793,11 +3856,6 @@ return PyLong_FromSsize_t(res); } -static const unsigned char BitLengthTable[32] = { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 -}; - static PyObject * long_bit_length(PyLongObject *v) { From python-checkins at python.org Mon Mar 23 19:46:40 2009 From: python-checkins at python.org (mark.dickinson) Date: Mon, 23 Mar 2009 19:46:40 +0100 (CET) Subject: [Python-checkins] r70548 - python/branches/release30-maint Message-ID: <20090323184640.CFC0B1E4002@bag.python.org> Author: mark.dickinson Date: Mon Mar 23 19:46:40 2009 New Revision: 70548 Log: Blocked revisions 70547 via svnmerge ................ r70547 | mark.dickinson | 2009-03-23 18:44:57 +0000 (Mon, 23 Mar 2009) | 21 lines Merged revisions 70542 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70542 | mark.dickinson | 2009-03-23 18:25:13 +0000 (Mon, 23 Mar 2009) | 14 lines Issue #5512: speed up the long division algorithm for Python longs. The basic algorithm remains the same; the most significant speedups come from the following three changes: (1) normalize by shifting instead of multiplying and dividing (2) the old algorithm usually did an unnecessary extra iteration of the outer loop; remove this. As a special case, this means that long divisions with a single-digit result run twice as fast as before. (3) make inner loop much tighter. Various benchmarks show speedups of between 50% and 150% for long integer divisions and modulo operations. ........ ................ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Mon Mar 23 19:52:05 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 18:52:05 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.0 Message-ID: <20090323185205.793F81E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.0/builds/224 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed svn sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 19:52:06 2009 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 23 Mar 2009 19:52:06 +0100 (CET) Subject: [Python-checkins] r70549 - in python/branches/py3k: Doc/library/gc.rst Include/dictobject.h Include/objimpl.h Include/tupleobject.h Lib/test/test_dict.py Lib/test/test_gc.py Lib/test/test_tuple.py Misc/NEWS Modules/gcmodule.c Objects/dictobject.c Objects/tupleobject.c Message-ID: <20090323185206.781641E4002@bag.python.org> Author: antoine.pitrou Date: Mon Mar 23 19:52:06 2009 New Revision: 70549 Log: Merged revisions 70546 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70546 | antoine.pitrou | 2009-03-23 19:41:45 +0100 (lun., 23 mars 2009) | 9 lines Issue #4688: Add a heuristic so that tuples and dicts containing only untrackable objects are not tracked by the garbage collector. This can reduce the size of collections and therefore the garbage collection overhead on long-running programs, depending on their particular use of datatypes. (trivia: this makes the "binary_trees" benchmark from the Computer Language Shootout 40% faster) ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/gc.rst python/branches/py3k/Include/dictobject.h python/branches/py3k/Include/objimpl.h python/branches/py3k/Include/tupleobject.h python/branches/py3k/Lib/test/test_dict.py python/branches/py3k/Lib/test/test_gc.py python/branches/py3k/Lib/test/test_tuple.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/gcmodule.c python/branches/py3k/Objects/dictobject.c python/branches/py3k/Objects/tupleobject.c Modified: python/branches/py3k/Doc/library/gc.rst ============================================================================== --- python/branches/py3k/Doc/library/gc.rst (original) +++ python/branches/py3k/Doc/library/gc.rst Mon Mar 23 19:52:06 2009 @@ -129,6 +129,31 @@ from an argument, that integer object may or may not appear in the result list. +.. function:: is_tracked(obj) + + Returns True if the object is currently tracked by the garbage collector, + False otherwise. As a general rule, instances of atomic types aren't + tracked and instances of non-atomic types (containers, user-defined + objects...) are. However, some type-specific optimizations can be present + in order to suppress the garbage collector footprint of simple instances + (e.g. dicts containing only atomic keys and values):: + + >>> gc.is_tracked(0) + False + >>> gc.is_tracked("a") + False + >>> gc.is_tracked([]) + True + >>> gc.is_tracked({}) + False + >>> gc.is_tracked({"a": 1}) + False + >>> gc.is_tracked({"a": []}) + True + + .. versionadded:: 2.7 + + The following variable is provided for read-only access (you can mutate its value but should not rebind it): Modified: python/branches/py3k/Include/dictobject.h ============================================================================== --- python/branches/py3k/Include/dictobject.h (original) +++ python/branches/py3k/Include/dictobject.h Mon Mar 23 19:52:06 2009 @@ -125,6 +125,7 @@ PyAPI_FUNC(int) PyDict_Contains(PyObject *mp, PyObject *key); PyAPI_FUNC(int) _PyDict_Contains(PyObject *mp, PyObject *key, long hash); PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused); +PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp); /* PyDict_Update(mp, other) is equivalent to PyDict_Merge(mp, other, 1). */ PyAPI_FUNC(int) PyDict_Update(PyObject *mp, PyObject *other); Modified: python/branches/py3k/Include/objimpl.h ============================================================================== --- python/branches/py3k/Include/objimpl.h (original) +++ python/branches/py3k/Include/objimpl.h Mon Mar 23 19:52:06 2009 @@ -282,6 +282,17 @@ g->gc.gc_next = NULL; \ } while (0); +/* True if the object is currently tracked by the GC. */ +#define _PyObject_GC_IS_TRACKED(o) \ + ((_Py_AS_GC(o))->gc.gc_refs != _PyGC_REFS_UNTRACKED) + +/* True if the object may be tracked by the GC in the future, or already is. + This can be useful to implement some optimizations. */ +#define _PyObject_GC_MAY_BE_TRACKED(obj) \ + (PyObject_IS_GC(obj) && \ + (!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj))) + + PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t); PyAPI_FUNC(PyObject *) _PyObject_GC_New(PyTypeObject *); PyAPI_FUNC(PyVarObject *) _PyObject_GC_NewVar(PyTypeObject *, Py_ssize_t); Modified: python/branches/py3k/Include/tupleobject.h ============================================================================== --- python/branches/py3k/Include/tupleobject.h (original) +++ python/branches/py3k/Include/tupleobject.h Mon Mar 23 19:52:06 2009 @@ -45,6 +45,7 @@ PyAPI_FUNC(PyObject *) PyTuple_GetSlice(PyObject *, Py_ssize_t, Py_ssize_t); PyAPI_FUNC(int) _PyTuple_Resize(PyObject **, Py_ssize_t); PyAPI_FUNC(PyObject *) PyTuple_Pack(Py_ssize_t, ...); +PyAPI_FUNC(void) _PyTuple_MaybeUntrack(PyObject *); /* Macro, trading safety for speed */ #define PyTuple_GET_ITEM(op, i) (((PyTupleObject *)(op))->ob_item[i]) Modified: python/branches/py3k/Lib/test/test_dict.py ============================================================================== --- python/branches/py3k/Lib/test/test_dict.py (original) +++ python/branches/py3k/Lib/test/test_dict.py Mon Mar 23 19:52:06 2009 @@ -665,6 +665,104 @@ gc.collect() self.assert_(ref() is None, "Cycle was not collected") + def _not_tracked(self, t): + # Nested containers can take several collections to untrack + gc.collect() + gc.collect() + self.assertFalse(gc.is_tracked(t), t) + + def _tracked(self, t): + self.assertTrue(gc.is_tracked(t), t) + gc.collect() + gc.collect() + self.assertTrue(gc.is_tracked(t), t) + + def test_track_literals(self): + # Test GC-optimization of dict literals + x, y, z, w = 1.5, "a", (1, None), [] + + self._not_tracked({}) + self._not_tracked({x:(), y:x, z:1}) + self._not_tracked({1: "a", "b": 2}) + self._not_tracked({1: 2, (None, True, False, ()): int}) + self._not_tracked({1: object()}) + + # Dicts with mutable elements are always tracked, even if those + # elements are not tracked right now. + self._tracked({1: []}) + self._tracked({1: ([],)}) + self._tracked({1: {}}) + self._tracked({1: set()}) + + def test_track_dynamic(self): + # Test GC-optimization of dynamically-created dicts + class MyObject(object): + pass + x, y, z, w, o = 1.5, "a", (1, object()), [], MyObject() + + d = dict() + self._not_tracked(d) + d[1] = "a" + self._not_tracked(d) + d[y] = 2 + self._not_tracked(d) + d[z] = 3 + self._not_tracked(d) + self._not_tracked(d.copy()) + d[4] = w + self._tracked(d) + self._tracked(d.copy()) + d[4] = None + self._not_tracked(d) + self._not_tracked(d.copy()) + + # dd isn't tracked right now, but it may mutate and therefore d + # which contains it must be tracked. + d = dict() + dd = dict() + d[1] = dd + self._not_tracked(dd) + self._tracked(d) + dd[1] = d + self._tracked(dd) + + d = dict.fromkeys([x, y, z]) + self._not_tracked(d) + dd = dict() + dd.update(d) + self._not_tracked(dd) + d = dict.fromkeys([x, y, z, o]) + self._tracked(d) + dd = dict() + dd.update(d) + self._tracked(dd) + + d = dict(x=x, y=y, z=z) + self._not_tracked(d) + d = dict(x=x, y=y, z=z, w=w) + self._tracked(d) + d = dict() + d.update(x=x, y=y, z=z) + self._not_tracked(d) + d.update(w=w) + self._tracked(d) + + d = dict([(x, y), (z, 1)]) + self._not_tracked(d) + d = dict([(x, y), (z, w)]) + self._tracked(d) + d = dict() + d.update([(x, y), (z, 1)]) + self._not_tracked(d) + d.update([(x, y), (z, w)]) + self._tracked(d) + + def test_track_subtypes(self): + # Dict subtypes are always tracked + class MyDict(dict): + pass + self._tracked(MyDict()) + from test import mapping_tests Modified: python/branches/py3k/Lib/test/test_gc.py ============================================================================== --- python/branches/py3k/Lib/test/test_gc.py (original) +++ python/branches/py3k/Lib/test/test_gc.py Mon Mar 23 19:52:06 2009 @@ -415,6 +415,33 @@ self.assertEqual(gc.get_referents(1, 'a', 4j), []) + def test_is_tracked(self): + # Atomic built-in types are not tracked, user-defined objects and + # mutable containers are. + # NOTE: types with special optimizations (e.g. tuple) have tests + # in their own test files instead. + self.assertFalse(gc.is_tracked(None)) + self.assertFalse(gc.is_tracked(1)) + self.assertFalse(gc.is_tracked(1.0)) + self.assertFalse(gc.is_tracked(1.0 + 5.0j)) + self.assertFalse(gc.is_tracked(True)) + self.assertFalse(gc.is_tracked(False)) + self.assertFalse(gc.is_tracked(b"a")) + self.assertFalse(gc.is_tracked("a")) + self.assertFalse(gc.is_tracked(bytearray(b"a"))) + self.assertFalse(gc.is_tracked(type)) + self.assertFalse(gc.is_tracked(int)) + self.assertFalse(gc.is_tracked(object)) + self.assertFalse(gc.is_tracked(object())) + + class UserClass: + pass + self.assertTrue(gc.is_tracked(gc)) + self.assertTrue(gc.is_tracked(UserClass)) + self.assertTrue(gc.is_tracked(UserClass())) + self.assertTrue(gc.is_tracked([])) + self.assertTrue(gc.is_tracked(set())) + def test_bug1055820b(self): # Corresponds to temp2b.py in the bug report. Modified: python/branches/py3k/Lib/test/test_tuple.py ============================================================================== --- python/branches/py3k/Lib/test/test_tuple.py (original) +++ python/branches/py3k/Lib/test/test_tuple.py Mon Mar 23 19:52:06 2009 @@ -1,5 +1,7 @@ from test import support, seq_tests +import gc + class TupleTest(seq_tests.CommonTest): type2test = tuple @@ -82,6 +84,69 @@ self.assertEqual(repr(a0), "()") self.assertEqual(repr(a2), "(0, 1, 2)") + def _not_tracked(self, t): + # Nested tuples can take several collections to untrack + gc.collect() + gc.collect() + self.assertFalse(gc.is_tracked(t), t) + + def _tracked(self, t): + self.assertTrue(gc.is_tracked(t), t) + gc.collect() + gc.collect() + self.assertTrue(gc.is_tracked(t), t) + + def test_track_literals(self): + # Test GC-optimization of tuple literals + x, y, z = 1.5, "a", [] + + self._not_tracked(()) + self._not_tracked((1,)) + self._not_tracked((1, 2)) + self._not_tracked((1, 2, "a")) + self._not_tracked((1, 2, (None, True, False, ()), int)) + self._not_tracked((object(),)) + self._not_tracked(((1, x), y, (2, 3))) + + # Tuples with mutable elements are always tracked, even if those + # elements are not tracked right now. + self._tracked(([],)) + self._tracked(([1],)) + self._tracked(({},)) + self._tracked((set(),)) + self._tracked((x, y, z)) + + def check_track_dynamic(self, tp, always_track): + x, y, z = 1.5, "a", [] + + check = self._tracked if always_track else self._not_tracked + check(tp()) + check(tp([])) + check(tp(set())) + check(tp([1, x, y])) + check(tp(obj for obj in [1, x, y])) + check(tp(set([1, x, y]))) + check(tp(tuple([obj]) for obj in [1, x, y])) + check(tuple(tp([obj]) for obj in [1, x, y])) + + self._tracked(tp([z])) + self._tracked(tp([[x, y]])) + self._tracked(tp([{x: y}])) + self._tracked(tp(obj for obj in [x, y, z])) + self._tracked(tp(tuple([obj]) for obj in [x, y, z])) + self._tracked(tuple(tp([obj]) for obj in [x, y, z])) + + def test_track_dynamic(self): + # Test GC-optimization of dynamically constructed tuples. + self.check_track_dynamic(tuple, False) + + def test_track_subtypes(self): + # Tuple subtypes must always be tracked + class MyTuple(tuple): + pass + self.check_track_dynamic(MyTuple, True) + + def test_main(): support.run_unittest(TupleTest) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Mon Mar 23 19:52:06 2009 @@ -12,6 +12,11 @@ Core and Builtins ----------------- +- Issue #4688: Add a heuristic so that tuples and dicts containing only + untrackable objects are not tracked by the garbage collector. This can + reduce the size of collections and therefore the garbage collection overhead + on long-running programs, depending on their particular use of datatypes. + - Issue #5512: Rewrite PyLong long division algorithm (x_divrem) to improve its performance. Long divisions and remainder operations are now between 50% and 150% faster. Modified: python/branches/py3k/Modules/gcmodule.c ============================================================================== --- python/branches/py3k/Modules/gcmodule.c (original) +++ python/branches/py3k/Modules/gcmodule.c Mon Mar 23 19:52:06 2009 @@ -433,7 +433,13 @@ (void) traverse(op, (visitproc)visit_reachable, (void *)young); - next = gc->gc.gc_next; + next = gc->gc.gc_next; + if (PyTuple_CheckExact(op)) { + _PyTuple_MaybeUntrack(op); + } + else if (PyDict_CheckExact(op)) { + _PyDict_MaybeUntrack(op); + } } else { /* This *may* be unreachable. To make progress, @@ -1229,6 +1235,26 @@ return result; } +PyDoc_STRVAR(gc_is_tracked__doc__, +"is_tracked(obj) -> bool\n" +"\n" +"Returns true if the object is tracked by the garbage collector.\n" +"Simple atomic objects will return false.\n" +); + +static PyObject * +gc_is_tracked(PyObject *self, PyObject *obj) +{ + PyObject *result; + + if (PyObject_IS_GC(obj) && IS_TRACKED(obj)) + result = Py_True; + else + result = Py_False; + Py_INCREF(result); + return result; +} + PyDoc_STRVAR(gc__doc__, "This module provides access to the garbage collector for reference cycles.\n" @@ -1243,6 +1269,7 @@ "set_threshold() -- Set the collection thresholds.\n" "get_threshold() -- Return the current the collection thresholds.\n" "get_objects() -- Return a list of all objects tracked by the collector.\n" +"is_tracked() -- Returns true if a given object is tracked.\n" "get_referrers() -- Return the list of objects that refer to an object.\n" "get_referents() -- Return the list of objects that an object refers to.\n"); @@ -1258,6 +1285,7 @@ {"collect", (PyCFunction)gc_collect, METH_VARARGS | METH_KEYWORDS, gc_collect__doc__}, {"get_objects", gc_get_objects,METH_NOARGS, gc_get_objects__doc__}, + {"is_tracked", gc_is_tracked, METH_O, gc_is_tracked__doc__}, {"get_referrers", gc_get_referrers, METH_VARARGS, gc_get_referrers__doc__}, {"get_referents", gc_get_referents, METH_VARARGS, Modified: python/branches/py3k/Objects/dictobject.c ============================================================================== --- python/branches/py3k/Objects/dictobject.c (original) +++ python/branches/py3k/Objects/dictobject.c Mon Mar 23 19:52:06 2009 @@ -181,6 +181,24 @@ } #endif +/* Debug statistic to count GC tracking of dicts */ +#ifdef SHOW_TRACK_COUNT +static Py_ssize_t count_untracked = 0; +static Py_ssize_t count_tracked = 0; + +static void +show_track(void) +{ + fprintf(stderr, "Dicts created: %" PY_FORMAT_SIZE_T "d\n", + count_tracked + count_untracked); + fprintf(stderr, "Dicts tracked by the GC: %" PY_FORMAT_SIZE_T + "d\n", count_tracked); + fprintf(stderr, "%.2f%% dict tracking rate\n\n", + (100.0*count_tracked/(count_untracked+count_tracked))); +} +#endif + + /* Initialization macros. There are two ways to create a dict: PyDict_New() is the main C API function, and the tp_new slot maps to dict_new(). In the latter case we @@ -234,6 +252,9 @@ #ifdef SHOW_ALLOC_COUNT Py_AtExit(show_alloc); #endif +#ifdef SHOW_TRACK_COUNT + Py_AtExit(show_track); +#endif } if (numfree) { mp = free_list[--numfree]; @@ -263,10 +284,12 @@ #endif } mp->ma_lookup = lookdict_unicode; +#ifdef SHOW_TRACK_COUNT + count_untracked++; +#endif #ifdef SHOW_CONVERSION_COUNTS ++created; #endif - _PyObject_GC_TRACK(mp); return (PyObject *)mp; } @@ -435,6 +458,52 @@ return 0; } +#ifdef SHOW_TRACK_COUNT +#define INCREASE_TRACK_COUNT \ + (count_tracked++, count_untracked--); +#define DECREASE_TRACK_COUNT \ + (count_tracked--, count_untracked++); +#else +#define INCREASE_TRACK_COUNT +#define DECREASE_TRACK_COUNT +#endif + +#define MAINTAIN_TRACKING(mp, key, value) \ + do { \ + if (!_PyObject_GC_IS_TRACKED(mp)) { \ + if (_PyObject_GC_MAY_BE_TRACKED(key) || \ + _PyObject_GC_MAY_BE_TRACKED(value)) { \ + _PyObject_GC_TRACK(mp); \ + INCREASE_TRACK_COUNT \ + } \ + } \ + } while(0) + +void +_PyDict_MaybeUntrack(PyObject *op) +{ + PyDictObject *mp; + PyObject *value; + Py_ssize_t mask, i; + PyDictEntry *ep; + + if (!PyDict_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op)) + return; + + mp = (PyDictObject *) op; + ep = mp->ma_table; + mask = mp->ma_mask; + for (i = 0; i <= mask; i++) { + if ((value = ep[i].me_value) == NULL) + continue; + if (_PyObject_GC_MAY_BE_TRACKED(value) || + _PyObject_GC_MAY_BE_TRACKED(ep[i].me_key)) + return; + } + _PyObject_GC_UNTRACK(op); +} + + /* Internal routine to insert a new item into the table. Used both by the internal resize routine and by the public insert routine. @@ -455,6 +524,7 @@ Py_DECREF(value); return -1; } + MAINTAIN_TRACKING(mp, key, value); if (ep->me_value != NULL) { old_value = ep->me_value; ep->me_value = value; @@ -494,6 +564,7 @@ PyDictEntry *ep0 = mp->ma_table; register PyDictEntry *ep; + MAINTAIN_TRACKING(mp, key, value); i = hash & mask; ep = &ep0[i]; for (perturb = hash; ep->me_key != NULL; perturb >>= PERTURB_SHIFT) { @@ -1993,9 +2064,18 @@ assert(d->ma_table == NULL && d->ma_fill == 0 && d->ma_used == 0); INIT_NONZERO_DICT_SLOTS(d); d->ma_lookup = lookdict_unicode; + /* The object has been implicitely tracked by tp_alloc */ + if (type == &PyDict_Type) + _PyObject_GC_UNTRACK(d); #ifdef SHOW_CONVERSION_COUNTS ++created; #endif +#ifdef SHOW_TRACK_COUNT + if (_PyObject_GC_IS_TRACKED(d)) + count_tracked++; + else + count_untracked++; +#endif } return self; } Modified: python/branches/py3k/Objects/tupleobject.c ============================================================================== --- python/branches/py3k/Objects/tupleobject.c (original) +++ python/branches/py3k/Objects/tupleobject.c Mon Mar 23 19:52:06 2009 @@ -23,11 +23,36 @@ Py_ssize_t tuple_zero_allocs; #endif +/* Debug statistic to count GC tracking of tuples. + Please note that tuples are only untracked when considered by the GC, and + many of them will be dead before. Therefore, a tracking rate close to 100% + does not necessarily prove that the heuristic is inefficient. +*/ +#ifdef SHOW_TRACK_COUNT +static Py_ssize_t count_untracked = 0; +static Py_ssize_t count_tracked = 0; + +static void +show_track(void) +{ + fprintf(stderr, "Tuples created: %" PY_FORMAT_SIZE_T "d\n", + count_tracked + count_untracked); + fprintf(stderr, "Tuples tracked by the GC: %" PY_FORMAT_SIZE_T + "d\n", count_tracked); + fprintf(stderr, "%.2f%% tuple tracking rate\n\n", + (100.0*count_tracked/(count_untracked+count_tracked))); +} +#endif + + PyObject * PyTuple_New(register Py_ssize_t size) { register PyTupleObject *op; Py_ssize_t i; +#ifdef SHOW_TRACK_COUNT + count_tracked++; +#endif if (size < 0) { PyErr_BadInternalCall(); return NULL; @@ -131,6 +156,32 @@ return 0; } +void +_PyTuple_MaybeUntrack(PyObject *op) +{ + PyTupleObject *t; + Py_ssize_t i, n; + + if (!PyTuple_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op)) + return; + t = (PyTupleObject *) op; + n = Py_SIZE(t); + for (i = 0; i < n; i++) { + PyObject *elt = PyTuple_GET_ITEM(t, i); + /* Tuple with NULL elements aren't + fully constructed, don't untrack + them yet. */ + if (!elt || + _PyObject_GC_MAY_BE_TRACKED(elt)) + return; + } +#ifdef SHOW_TRACK_COUNT + count_tracked--; + count_untracked++; +#endif + _PyObject_GC_UNTRACK(op); +} + PyObject * PyTuple_Pack(Py_ssize_t n, ...) { @@ -855,6 +906,9 @@ (void)PyTuple_ClearFreeList(); #endif +#ifdef SHOW_TRACK_COUNT + show_track(); +#endif } /*********************** Tuple Iterator **************************/ From buildbot at python.org Mon Mar 23 19:54:40 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 18:54:40 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.0 Message-ID: <20090323185440.606161E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.0/builds/249 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Mon Mar 23 20:05:31 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 19:05:31 +0000 Subject: [Python-checkins] buildbot failure in x86 OpenBSD trunk Message-ID: <20090323190531.C17861E4002@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%20OpenBSD%20trunk/builds/736 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: cortesi Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: mark.dickinson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 20:17:01 2009 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 23 Mar 2009 20:17:01 +0100 (CET) Subject: [Python-checkins] r70550 - in python/trunk/Objects: dictobject.c tupleobject.c Message-ID: <20090323191701.1D01E1E4002@bag.python.org> Author: antoine.pitrou Date: Mon Mar 23 20:17:00 2009 New Revision: 70550 Log: The tracking statistics were actually too pessimistic Modified: python/trunk/Objects/dictobject.c python/trunk/Objects/tupleobject.c Modified: python/trunk/Objects/dictobject.c ============================================================================== --- python/trunk/Objects/dictobject.c (original) +++ python/trunk/Objects/dictobject.c Mon Mar 23 20:17:00 2009 @@ -498,6 +498,7 @@ _PyObject_GC_MAY_BE_TRACKED(ep[i].me_key)) return; } + DECREASE_TRACK_COUNT _PyObject_GC_UNTRACK(op); } Modified: python/trunk/Objects/tupleobject.c ============================================================================== --- python/trunk/Objects/tupleobject.c (original) +++ python/trunk/Objects/tupleobject.c Mon Mar 23 20:17:00 2009 @@ -50,9 +50,6 @@ { register PyTupleObject *op; Py_ssize_t i; -#ifdef SHOW_TRACK_COUNT - count_tracked++; -#endif if (size < 0) { PyErr_BadInternalCall(); return NULL; @@ -104,6 +101,9 @@ Py_INCREF(op); /* extra INCREF so that this is never freed */ } #endif +#ifdef SHOW_TRACK_COUNT + count_tracked++; +#endif _PyObject_GC_TRACK(op); return (PyObject *) op; } From python-checkins at python.org Mon Mar 23 20:19:56 2009 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 23 Mar 2009 20:19:56 +0100 (CET) Subject: [Python-checkins] r70551 - in python/branches/py3k: Objects/dictobject.c Objects/tupleobject.c Message-ID: <20090323191956.108EE1E4002@bag.python.org> Author: antoine.pitrou Date: Mon Mar 23 20:19:54 2009 New Revision: 70551 Log: Merged revisions 70550 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70550 | antoine.pitrou | 2009-03-23 20:17:00 +0100 (lun., 23 mars 2009) | 3 lines The tracking statistics were actually too pessimistic ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Objects/dictobject.c python/branches/py3k/Objects/tupleobject.c Modified: python/branches/py3k/Objects/dictobject.c ============================================================================== --- python/branches/py3k/Objects/dictobject.c (original) +++ python/branches/py3k/Objects/dictobject.c Mon Mar 23 20:19:54 2009 @@ -500,6 +500,7 @@ _PyObject_GC_MAY_BE_TRACKED(ep[i].me_key)) return; } + DECREASE_TRACK_COUNT _PyObject_GC_UNTRACK(op); } Modified: python/branches/py3k/Objects/tupleobject.c ============================================================================== --- python/branches/py3k/Objects/tupleobject.c (original) +++ python/branches/py3k/Objects/tupleobject.c Mon Mar 23 20:19:54 2009 @@ -50,9 +50,6 @@ { register PyTupleObject *op; Py_ssize_t i; -#ifdef SHOW_TRACK_COUNT - count_tracked++; -#endif if (size < 0) { PyErr_BadInternalCall(); return NULL; @@ -104,6 +101,9 @@ Py_INCREF(op); /* extra INCREF so that this is never freed */ } #endif +#ifdef SHOW_TRACK_COUNT + count_tracked++; +#endif _PyObject_GC_TRACK(op); return (PyObject *) op; } From buildbot at python.org Mon Mar 23 21:08:03 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 20:08:03 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090323200804.0406C1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/504 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Mon Mar 23 21:33:06 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 20:33:06 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo trunk Message-ID: <20090323203306.DA2831E4002@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%20gentoo%20trunk/builds/4761 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 21:47:59 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Mar 2009 21:47:59 +0100 (CET) Subject: [Python-checkins] r70552 - python/trunk/Lib/traceback.py Message-ID: <20090323204759.8ABC41E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 23 21:47:59 2009 New Revision: 70552 Log: fix very old names for exception terms #5543 Modified: python/trunk/Lib/traceback.py Modified: python/trunk/Lib/traceback.py ============================================================================== --- python/trunk/Lib/traceback.py (original) +++ python/trunk/Lib/traceback.py Mon Mar 23 21:47:59 2009 @@ -149,7 +149,7 @@ """Format the exception part of a traceback. The arguments are the exception type and value such as given by - sys.last_type and sys.last_value. The return value is a list of + sys.exc_info()[0] and sys.exc_info()[1]. The return value is a list of strings, each ending in a newline. Normally, the list contains a single string; however, for @@ -239,12 +239,12 @@ def print_last(limit=None, file=None): - """This is a shorthand for 'print_exception(sys.last_type, - sys.last_value, sys.last_traceback, limit, file)'.""" + """ + This is a shorthand for 'print_exception(*sys.exc_info(), limit, file)'. + """ if file is None: file = sys.stderr - print_exception(sys.last_type, sys.last_value, sys.last_traceback, - limit, file) + print_exception(*(sys.exc_info() + (limit, file))) def print_stack(f=None, limit=None, file=None): From python-checkins at python.org Mon Mar 23 22:23:31 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Mar 2009 22:23:31 +0100 (CET) Subject: [Python-checkins] r70553 - python/trunk/Lib/traceback.py Message-ID: <20090323212331.21B4C1E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 23 22:23:30 2009 New Revision: 70553 Log: revert r70552; wrong fix Modified: python/trunk/Lib/traceback.py Modified: python/trunk/Lib/traceback.py ============================================================================== --- python/trunk/Lib/traceback.py (original) +++ python/trunk/Lib/traceback.py Mon Mar 23 22:23:30 2009 @@ -149,7 +149,7 @@ """Format the exception part of a traceback. The arguments are the exception type and value such as given by - sys.exc_info()[0] and sys.exc_info()[1]. The return value is a list of + sys.last_type and sys.last_value. The return value is a list of strings, each ending in a newline. Normally, the list contains a single string; however, for @@ -239,12 +239,12 @@ def print_last(limit=None, file=None): - """ - This is a shorthand for 'print_exception(*sys.exc_info(), limit, file)'. - """ + """This is a shorthand for 'print_exception(sys.last_type, + sys.last_value, sys.last_traceback, limit, file)'.""" if file is None: file = sys.stderr - print_exception(*(sys.exc_info() + (limit, file))) + print_exception(sys.last_type, sys.last_value, sys.last_traceback, + limit, file) def print_stack(f=None, limit=None, file=None): From python-checkins at python.org Mon Mar 23 22:25:16 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Mar 2009 22:25:16 +0100 (CET) Subject: [Python-checkins] r70554 - python/trunk/Lib/traceback.py Message-ID: <20090323212516.AA8831E4020@bag.python.org> Author: benjamin.peterson Date: Mon Mar 23 22:25:15 2009 New Revision: 70554 Log: complain when there's no last exception Modified: python/trunk/Lib/traceback.py Modified: python/trunk/Lib/traceback.py ============================================================================== --- python/trunk/Lib/traceback.py (original) +++ python/trunk/Lib/traceback.py Mon Mar 23 22:25:15 2009 @@ -241,6 +241,8 @@ def print_last(limit=None, file=None): """This is a shorthand for 'print_exception(sys.last_type, sys.last_value, sys.last_traceback, limit, file)'.""" + if not hasattr(sys, "last_type"): + raise ValueError("no last exception") if file is None: file = sys.stderr print_exception(sys.last_type, sys.last_value, sys.last_traceback, From python-checkins at python.org Mon Mar 23 22:50:22 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Mar 2009 22:50:22 +0100 (CET) Subject: [Python-checkins] r70555 - in python/trunk: Doc/library/unittest.rst Lib/test/test_unittest.py Lib/unittest.py Misc/NEWS Message-ID: <20090323215022.469C01E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 23 22:50:21 2009 New Revision: 70555 Log: implement test skipping and expected failures patch by myself #1034053 Modified: python/trunk/Doc/library/unittest.rst python/trunk/Lib/test/test_unittest.py python/trunk/Lib/unittest.py python/trunk/Misc/NEWS Modified: python/trunk/Doc/library/unittest.rst ============================================================================== --- python/trunk/Doc/library/unittest.rst (original) +++ python/trunk/Doc/library/unittest.rst Mon Mar 23 22:50:21 2009 @@ -11,6 +11,9 @@ .. versionadded:: 2.1 +.. versionchanged:: 2.7 + + Added :ref:`skipping and expected failures `. The Python unit testing framework, sometimes referred to as "PyUnit," is a Python language version of JUnit, by Kent Beck and Erich Gamma. JUnit is, in @@ -60,7 +63,8 @@ Test suites are implemented by the :class:`TestSuite` class. This class allows individual tests and test suites to be aggregated; when the suite is executed, -all tests added directly to the suite and in "child" test suites are run. +all tests added directly to the suite and in "child" test suites are run. A +:class:`ClassTestSuite` contains the test cases of a class. A test runner is an object that provides a single method, :meth:`run`, which accepts a :class:`TestCase` or :class:`TestSuite` object as a parameter, and @@ -408,6 +412,78 @@ make future test refactorings infinitely easier. +.. _unittest-skipping: + +Skipping tests and expected failures +------------------------------------ + +Unittest supports skipping individual test methods and even whole classes of +tests. In addition, it supports marking a test as a "expected failure," a test +that is broken and will fail, but shouldn't be counted as a failure on a +:class:`TestResult`. + +Skipping a test is simply a matter of using the :func:`skip` :term:`decorator` +or one of its conditional variants. + +Basic skipping looks like this: :: + + class MyTestCase(unittest.TestCase): + + @unittest.skip("demonstrating skipping") + def test_nothing(self): + self.fail("shouldn't happen") + +This is the output of running the example above in verbose mode: :: + + test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping' + + ---------------------------------------------------------------------- + Ran 1 test in 0.072s + +Classes can be skipped just like methods: :: + + @skip("showing class skipping") + class MySkippedTestCase(unittest.TestCase): + def test_not_run(self): + pass + +Expected failures use the :func:`expectedFailure` decorator. :: + + class ExpectedFailureTestCase(unittest.TestCase): + @unittest.expectedFailure + def test_fail(self): + self.assertEqual(1, 0, "broken") + +It's easy to roll your own skipping decorators by making a decorator that calls +:func:`skip` on the test when it wants it to be skipped. This decorator skips +the test unless the passed object has a certain attribute: :: + + def skipUnlessHasattr(obj, attr): + if hasattr(obj, attr): + return lambda func: func + return unittest.skip("{0!r} doesn't have {1!r}".format(obj, attr)) + +The following decorators implement test skipping and expected failures: + +.. function:: skip(reason) + + Unconditionally skip the decorated test. *reason* should describe why the + test is being skipped. + +.. function:: skipIf(condition, reason) + + Skip the decorated test if *condition* is true. + +.. function:: skipUnless(condition, reason) + + Skip the decoratored test unless *condition* is true. + +.. function:: expectedFailure + + Mark the test as an expected failure. If the test fails when run, the test + is not counted as a failure. + + .. _unittest-contents: Classes and functions @@ -459,6 +535,13 @@ test suites that will be used to build the suite initially. Additional methods are provided to add test cases and suites to the collection later on. +.. class:: ClassTestSuite(tests, collected_from) + + This subclass of :class:`TestSuite` repesents an aggregation of individuals + tests from one :class:`TestCase` class. *tests* is an iterable of + :class:`TestCase` instances created from the class. *collected_from* is the + class they came from. + .. class:: TestLoader() @@ -553,6 +636,11 @@ The same effect may be had by simply calling the :class:`TestCase` instance. +.. method:: TestCase.skip(reason) + + Skips the current test. See :ref:`unittest-skipping`. + + .. method:: TestCase.debug() Run the test without collecting the result. This allows exceptions raised by @@ -690,10 +778,11 @@ TestSuite Objects ----------------- -:class:`TestSuite` objects behave much like :class:`TestCase` objects, except -they do not actually implement a test. Instead, they are used to aggregate -tests into groups of tests that should be run together. Some additional methods -are available to add tests to :class:`TestSuite` instances: +:class:`TestSuite` (including :class:`ClassTestSuite`) objects behave much like +:class:`TestCase` objects, except they do not actually implement a test. +Instead, they are used to aggregate tests into groups of tests that should be +run together. Some additional methods are available to add tests to +:class:`TestSuite` instances: .. method:: TestSuite.addTest(test) @@ -846,6 +935,34 @@ The default implementation does nothing. +.. method:: TestResult.addSkip(test, reason) + + Called when the test case *test* is skipped. *reason* is the reason the test + gave for skipping. + + The default implementation appends a tuple ``(test, reason)`` to the + instance's ``skipped`` attribute. + + +.. method:: TestResult.addExpectedFailure(test, err) + + Called when the test case *test* fails, but was marked with the + :func:`expectedFailure` decorator. + + The default implementation appends a tuple ``(test, formatted_err)`` to the + instance's ``expected_failures`` attribute, where *formatted_err* is a + formatted traceback derived from *err*. + + +.. method:: TestResult.addUnexpectedSuccess(test) + + Called when the test case *test* was marked with the :func:`expectedFailure` + decorator, but succeeded. + + The default implementation appends the test to the instance's + ``unexpected_successes`` attribute. + + .. _testloader-objects: TestLoader Objects @@ -946,3 +1063,9 @@ This affects all the :meth:`loadTestsFrom\*` methods. + +.. attribute:: TestLoader.classSuiteClass + + Callable object that constructs a test suite for the tests cases from one + class. The default value is :class:`ClassTestSuite`. + Modified: python/trunk/Lib/test/test_unittest.py ============================================================================== --- python/trunk/Lib/test/test_unittest.py (original) +++ python/trunk/Lib/test/test_unittest.py Mon Mar 23 22:50:21 2009 @@ -31,10 +31,27 @@ self._events.append('addFailure') super(LoggingResult, self).addFailure(*args) + def addSuccess(self, *args): + self._events.append('addSuccess') + super(LoggingResult, self).addSuccess(*args) + def addError(self, *args): self._events.append('addError') super(LoggingResult, self).addError(*args) + def addSkip(self, *args): + self._events.append('addSkip') + super(LoggingResult, self).addSkip(*args) + + def addExpectedFailure(self, *args): + self._events.append('addExpectedFailure') + super(LoggingResult, self).addExpectedFailure(*args) + + def addUnexpectedSuccess(self, *args): + self._events.append('addUnexpectedSuccess') + super(LoggingResult, self).addUnexpectedSuccess(*args) + + class TestEquality(object): # Check for a valid __eq__ implementation def test_eq(self): @@ -72,6 +89,13 @@ self.fail("Problem hashing %s and %s: %s" % (obj_1, obj_2, e)) +# List subclass we can add attributes to. +class MyClassSuite(list): + + def __init__(self, tests, klass): + super(MyClassSuite, self).__init__(tests) + + ################################################################ ### /Support code @@ -1223,7 +1247,7 @@ tests = [Foo('test_1'), Foo('test_2')] loader = unittest.TestLoader() - loader.suiteClass = list + loader.classSuiteClass = MyClassSuite self.assertEqual(loader.loadTestsFromTestCase(Foo), tests) # It is implicit in the documentation for TestLoader.suiteClass that @@ -1236,7 +1260,7 @@ def foo_bar(self): pass m.Foo = Foo - tests = [[Foo('test_1'), Foo('test_2')]] + tests = [unittest.ClassTestSuite([Foo('test_1'), Foo('test_2')], Foo)] loader = unittest.TestLoader() loader.suiteClass = list @@ -1255,7 +1279,7 @@ tests = [Foo('test_1'), Foo('test_2')] loader = unittest.TestLoader() - loader.suiteClass = list + loader.classSuiteClass = MyClassSuite self.assertEqual(loader.loadTestsFromName('Foo', m), tests) # It is implicit in the documentation for TestLoader.suiteClass that @@ -1268,7 +1292,7 @@ def foo_bar(self): pass m.Foo = Foo - tests = [[Foo('test_1'), Foo('test_2')]] + tests = [unittest.ClassTestSuite([Foo('test_1'), Foo('test_2')], Foo)] loader = unittest.TestLoader() loader.suiteClass = list @@ -2261,9 +2285,103 @@ # Make run() find a result object on its own Foo('test').run() - expected = ['startTest', 'test', 'stopTest'] + expected = ['startTest', 'test', 'addSuccess', 'stopTest'] self.assertEqual(events, expected) + +class Test_TestSkipping(TestCase): + + def test_skipping(self): + class Foo(unittest.TestCase): + def test_skip_me(self): + self.skip("skip") + events = [] + result = LoggingResult(events) + test = Foo("test_skip_me") + test.run(result) + self.assertEqual(events, ['startTest', 'addSkip', 'stopTest']) + self.assertEqual(result.skipped, [(test, "skip")]) + + # Try letting setUp skip the test now. + class Foo(unittest.TestCase): + def setUp(self): + self.skip("testing") + def test_nothing(self): pass + events = [] + result = LoggingResult(events) + test = Foo("test_nothing") + test.run(result) + self.assertEqual(events, ['startTest', 'addSkip', 'stopTest']) + self.assertEqual(result.skipped, [(test, "testing")]) + self.assertEqual(result.testsRun, 1) + + def test_skipping_decorators(self): + op_table = ((unittest.skipUnless, False, True), + (unittest.skipIf, True, False)) + for deco, do_skip, dont_skip in op_table: + class Foo(unittest.TestCase): + @deco(do_skip, "testing") + def test_skip(self): pass + + @deco(dont_skip, "testing") + def test_dont_skip(self): pass + test_do_skip = Foo("test_skip") + test_dont_skip = Foo("test_dont_skip") + suite = unittest.ClassTestSuite([test_do_skip, test_dont_skip], Foo) + events = [] + result = LoggingResult(events) + suite.run(result) + self.assertEqual(len(result.skipped), 1) + expected = ['startTest', 'addSkip', 'stopTest', + 'startTest', 'addSuccess', 'stopTest'] + self.assertEqual(events, expected) + self.assertEqual(result.testsRun, 2) + self.assertEqual(result.skipped, [(test_do_skip, "testing")]) + self.assertTrue(result.wasSuccessful()) + + def test_skip_class(self): + @unittest.skip("testing") + class Foo(unittest.TestCase): + def test_1(self): + record.append(1) + record = [] + result = unittest.TestResult() + suite = unittest.ClassTestSuite([Foo("test_1")], Foo) + suite.run(result) + self.assertEqual(result.skipped, [(suite, "testing")]) + self.assertEqual(record, []) + + def test_expected_failure(self): + class Foo(unittest.TestCase): + @unittest.expectedFailure + def test_die(self): + self.fail("help me!") + events = [] + result = LoggingResult(events) + test = Foo("test_die") + test.run(result) + self.assertEqual(events, + ['startTest', 'addExpectedFailure', 'stopTest']) + self.assertEqual(result.expected_failures[0][0], test) + self.assertTrue(result.wasSuccessful()) + + def test_unexpected_success(self): + class Foo(unittest.TestCase): + @unittest.expectedFailure + def test_die(self): + pass + events = [] + result = LoggingResult(events) + test = Foo("test_die") + test.run(result) + self.assertEqual(events, + ['startTest', 'addUnexpectedSuccess', 'stopTest']) + self.assertFalse(result.failures) + self.assertEqual(result.unexpected_successes, [test]) + self.assertTrue(result.wasSuccessful()) + + + class Test_Assertions(TestCase): def test_AlmostEqual(self): self.failUnlessAlmostEqual(1.00000001, 1.0) @@ -2328,7 +2446,7 @@ def test_main(): test_support.run_unittest(Test_TestCase, Test_TestLoader, Test_TestSuite, Test_TestResult, Test_FunctionTestCase, - Test_Assertions) + Test_TestSkipping, Test_Assertions) if __name__ == "__main__": test_main() Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Mon Mar 23 22:50:21 2009 @@ -53,6 +53,7 @@ import traceback import os import types +import functools ############################################################################## # Exported classes and functions @@ -84,6 +85,79 @@ def _strclass(cls): return "%s.%s" % (cls.__module__, cls.__name__) + +class SkipTest(Exception): + """ + Raise this exception in a test to skip it. + + Usually you can use TestResult.skip() or one of the skipping decorators + instead of raising this directly. + """ + pass + +class _ExpectedFailure(Exception): + """ + Raise this when a test is expected to fail. + + This is an implementation detail. + """ + + def __init__(self, exc_info): + super(_ExpectedFailure, self).__init__() + self.exc_info = exc_info + +class _UnexpectedSuccess(Exception): + """ + The test was supposed to fail, but it didn't! + """ + pass + +def _id(obj): + return obj + +def skip(reason): + """ + Unconditionally skip a test. + """ + def decorator(test_item): + if isinstance(test_item, type) and issubclass(test_item, TestCase): + test_item.__unittest_skip__ = True + test_item.__unittest_skip_why__ = reason + return test_item + @functools.wraps(test_item) + def skip_wrapper(*args, **kwargs): + raise SkipTest(reason) + return skip_wrapper + return decorator + +def skipIf(condition, reason): + """ + Skip a test if the condition is true. + """ + if condition: + return skip(reason) + return _id + +def skipUnless(condition, reason): + """ + Skip a test unless the condition is true. + """ + if not condition: + return skip(reason) + return _id + + +def expectedFailure(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + try: + func(*args, **kwargs) + except Exception: + raise _ExpectedFailure(sys.exc_info()) + raise _UnexpectedSuccess + return wrapper + + __unittest = 1 class TestResult(object): @@ -101,6 +175,9 @@ self.failures = [] self.errors = [] self.testsRun = 0 + self.skipped = [] + self.expected_failures = [] + self.unexpected_successes = [] self.shouldStop = False def startTest(self, test): @@ -126,6 +203,19 @@ "Called when a test has completed successfully" pass + def addSkip(self, test, reason): + """Called when a test is skipped.""" + self.skipped.append((test, reason)) + + def addExpectedFailure(self, test, err): + """Called when an expected failure/error occured.""" + self.expected_failures.append( + (test, self._exc_info_to_string(err, test))) + + def addUnexpectedSuccess(self, test): + """Called when a test was expected to fail, but succeed.""" + self.unexpected_successes.append(test) + def wasSuccessful(self): "Tells whether or not this result was a success" return len(self.failures) == len(self.errors) == 0 @@ -274,25 +364,36 @@ try: try: self.setUp() + except SkipTest as e: + result.addSkip(self, str(e)) + return except Exception: result.addError(self, self._exc_info()) return - ok = False + success = False try: testMethod() - ok = True except self.failureException: result.addFailure(self, self._exc_info()) + except _ExpectedFailure as e: + result.addExpectedFailure(self, e.exc_info) + except _UnexpectedSuccess: + result.addUnexpectedSuccess(self) + except SkipTest as e: + result.addSkip(self, str(e)) except Exception: result.addError(self, self._exc_info()) + else: + success = True try: self.tearDown() except Exception: result.addError(self, self._exc_info()) - ok = False - if ok: result.addSuccess(self) + success = False + if success: + result.addSuccess(self) finally: result.stopTest(self) @@ -312,6 +413,10 @@ """ return sys.exc_info() + def skip(self, reason): + """Skip this test.""" + raise SkipTest(reason) + def fail(self, msg=None): """Fail immediately, with the given message.""" raise self.failureException(msg) @@ -419,8 +524,8 @@ __str__ = __repr__ def __eq__(self, other): - if type(self) is not type(other): - return False + if not isinstance(other, self.__class__): + return NotImplemented return self._tests == other._tests def __ne__(self, other): @@ -469,6 +574,37 @@ for test in self._tests: test.debug() +class ClassTestSuite(TestSuite): + """ + Suite of tests derived from a single TestCase class. + """ + + def __init__(self, tests, class_collected_from): + super(ClassTestSuite, self).__init__(tests) + self.collected_from = class_collected_from + + def id(self): + module = getattr(self.collected_from, "__module__", None) + if module is not None: + return "{0}.{1}".format(module, self.collected_from.__name__) + return self.collected_from.__name__ + + def run(self, result): + if getattr(self.collected_from, "__unittest_skip__", False): + # ClassTestSuite result pretends to be a TestCase enough to be + # reported. + result.startTest(self) + try: + result.addSkip(self, self.collected_from.__unittest_skip_why__) + finally: + result.stopTest(self) + else: + result = super(ClassTestSuite, self).run(result) + return result + + shortDescription = id + + class FunctionTestCase(TestCase): """A test case that wraps a test function. @@ -540,6 +676,7 @@ testMethodPrefix = 'test' sortTestMethodsUsing = cmp suiteClass = TestSuite + classSuiteClass = ClassTestSuite def loadTestsFromTestCase(self, testCaseClass): """Return a suite of all tests cases contained in testCaseClass""" @@ -548,7 +685,9 @@ testCaseNames = self.getTestCaseNames(testCaseClass) if not testCaseNames and hasattr(testCaseClass, 'runTest'): testCaseNames = ['runTest'] - return self.suiteClass(map(testCaseClass, testCaseNames)) + suite = self.classSuiteClass(map(testCaseClass, testCaseNames), + testCaseClass) + return suite def loadTestsFromModule(self, module): """Return a suite of all tests cases contained in the given module""" @@ -719,6 +858,30 @@ self.stream.write('F') self.stream.flush() + def addSkip(self, test, reason): + TestResult.addSkip(self, test, reason) + if self.showAll: + self.stream.writeln("skipped {0!r}".format(reason)) + elif self.dots: + self.stream.write("s") + self.stream.flush() + + def addExpectedFailure(self, test, err): + TestResult.addExpectedFailure(self, test, err) + if self.showAll: + self.stream.writeln("expected failure") + elif self.dots: + self.stream.write(".") + self.stream.flush() + + def addUnexpectedSuccess(self, test): + TestResult.addUnexpectedSuccess(self, test) + if self.showAll: + self.stream.writeln("unexpected success") + elif self.dots: + self.stream.write(".") + self.stream.flush() + def printErrors(self): if self.dots or self.showAll: self.stream.writeln() @@ -760,17 +923,28 @@ self.stream.writeln("Ran %d test%s in %.3fs" % (run, run != 1 and "s" or "", timeTaken)) self.stream.writeln() + results = map(len, (result.expected_failures, + result.unexpected_successes, + result.skipped)) + expected_fails, unexpected_successes, skipped = results + infos = [] if not result.wasSuccessful(): - self.stream.write("FAILED (") + self.stream.write("FAILED") failed, errored = map(len, (result.failures, result.errors)) if failed: - self.stream.write("failures=%d" % failed) + infos.append("failures=%d" % failed) if errored: - if failed: self.stream.write(", ") - self.stream.write("errors=%d" % errored) - self.stream.writeln(")") + infos.append("errors=%d" % errored) else: - self.stream.writeln("OK") + self.stream.write("OK") + if skipped: + infos.append("skipped=%d" % skipped) + if expected_fails: + infos.append("expected failures=%d" % expected_fails) + if unexpected_successes: + infos.append("unexpected successes=%d" % unexpected_successes) + if infos: + self.stream.writeln(" (%s)" % (", ".join(infos),)) return result @@ -824,9 +998,9 @@ def parseArgs(self, argv): import getopt + long_opts = ['help','verbose','quiet'] try: - options, args = getopt.getopt(argv[1:], 'hHvq', - ['help','verbose','quiet']) + options, args = getopt.getopt(argv[1:], 'hHvq', long_opts) for opt, value in options: if opt in ('-h','-H','--help'): self.usageExit() Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Mon Mar 23 22:50:21 2009 @@ -197,6 +197,8 @@ Library ------- +- Issue #1034053: unittest now supports skipping tests and expected failures. + - Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop forever on incomplete input. That caused tarfile.open() to hang when used with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or From python-checkins at python.org Mon Mar 23 22:52:09 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Mar 2009 22:52:09 +0100 (CET) Subject: [Python-checkins] r70556 - python/branches/py3k/Doc/c-api/dict.rst Message-ID: <20090323215209.646D31E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 23 22:52:09 2009 New Revision: 70556 Log: PyString_FromString -> PyUnicode_FromString Modified: python/branches/py3k/Doc/c-api/dict.rst Modified: python/branches/py3k/Doc/c-api/dict.rst ============================================================================== --- python/branches/py3k/Doc/c-api/dict.rst (original) +++ python/branches/py3k/Doc/c-api/dict.rst Mon Mar 23 22:52:09 2009 @@ -73,11 +73,12 @@ .. cfunction:: int PyDict_SetItemString(PyObject *p, const char *key, PyObject *val) - .. index:: single: PyString_FromString() + .. index:: single: PyUnicode_FromString() - Insert *value* into the dictionary *p* using *key* as a key. *key* should be a - :ctype:`char\*`. The key object is created using ``PyString_FromString(key)``. - Return ``0`` on success or ``-1`` on failure. + Insert *value* into the dictionary *p* using *key* as a key. *key* should be + a :ctype:`char\*`. The key object is created using + :cfunc:`PyUnicode_FromString(key)`. Return ``0`` on success or ``-1`` on + failure. .. cfunction:: int PyDict_DelItem(PyObject *p, PyObject *key) From buildbot at python.org Mon Mar 23 23:22:39 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 23 Mar 2009 22:22:39 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090323222239.491041E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/755 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_threadedtempfile make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 23 23:25:03 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Mar 2009 23:25:03 +0100 (CET) Subject: [Python-checkins] r70557 - in python/branches/py3k: Doc/library/unittest.rst Lib/test/test_unittest.py Lib/unittest.py Message-ID: <20090323222503.E36D01E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 23 23:25:03 2009 New Revision: 70557 Log: Merged revisions 70555 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70555 | benjamin.peterson | 2009-03-23 16:50:21 -0500 (Mon, 23 Mar 2009) | 4 lines implement test skipping and expected failures patch by myself #1034053 ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/unittest.rst python/branches/py3k/Lib/test/test_unittest.py python/branches/py3k/Lib/unittest.py Modified: python/branches/py3k/Doc/library/unittest.rst ============================================================================== --- python/branches/py3k/Doc/library/unittest.rst (original) +++ python/branches/py3k/Doc/library/unittest.rst Mon Mar 23 23:25:03 2009 @@ -10,6 +10,10 @@ .. sectionauthor:: Raymond Hettinger +.. versionchanged:: 3.1 + + Added :ref:`skipping and expected failures `. + The Python unit testing framework, sometimes referred to as "PyUnit," is a Python language version of JUnit, by Kent Beck and Erich Gamma. JUnit is, in turn, a Java version of Kent's Smalltalk testing framework. Each is the de @@ -58,7 +62,8 @@ Test suites are implemented by the :class:`TestSuite` class. This class allows individual tests and test suites to be aggregated; when the suite is executed, -all tests added directly to the suite and in "child" test suites are run. +all tests added directly to the suite and in "child" test suites are run. A +:class:`ClassTestSuite` contains the test cases of a class. A test runner is an object that provides a single method, :meth:`run`, which accepts a :class:`TestCase` or :class:`TestSuite` object as a parameter, and @@ -407,6 +412,78 @@ make future test refactorings infinitely easier. +.. _unittest-skipping: + +Skipping tests and expected failures +------------------------------------ + +Unittest supports skipping individual test methods and even whole classes of +tests. In addition, it supports marking a test as a "expected failure," a test +that is broken and will fail, but shouldn't be counted as a failure on a +:class:`TestResult`. + +Skipping a test is simply a matter of using the :func:`skip` :term:`decorator` +or one of its conditional variants. + +Basic skipping looks like this: :: + + class MyTestCase(unittest.TestCase): + + @unittest.skip("demonstrating skipping") + def test_nothing(self): + self.fail("shouldn't happen") + +This is the output of running the example above in verbose mode: :: + + test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping' + + ---------------------------------------------------------------------- + Ran 1 test in 0.072s + +Classes can be skipped just like methods: :: + + @skip("showing class skipping") + class MySkippedTestCase(unittest.TestCase): + def test_not_run(self): + pass + +Expected failures use the :func:`expectedFailure` decorator. :: + + class ExpectedFailureTestCase(unittest.TestCase): + @unittest.expectedFailure + def test_fail(self): + self.assertEqual(1, 0, "broken") + +It's easy to roll your own skipping decorators by making a decorator that calls +:func:`skip` on the test when it wants it to be skipped. This decorator skips +the test unless the passed object has a certain attribute: :: + + def skipUnlessHasattr(obj, attr): + if hasattr(obj, attr): + return lambda func: func + return unittest.skip("{0!r} doesn't have {1!r}".format(obj, attr)) + +The following decorators implement test skipping and expected failures: + +.. function:: skip(reason) + + Unconditionally skip the decorated test. *reason* should describe why the + test is being skipped. + +.. function:: skipIf(condition, reason) + + Skip the decorated test if *condition* is true. + +.. function:: skipUnless(condition, reason) + + Skip the decoratored test unless *condition* is true. + +.. function:: expectedFailure + + Mark the test as an expected failure. If the test fails when run, the test + is not counted as a failure. + + .. _unittest-contents: Classes and functions @@ -458,6 +535,13 @@ test suites that will be used to build the suite initially. Additional methods are provided to add test cases and suites to the collection later on. +.. class:: ClassTestSuite(tests, collected_from) + + This subclass of :class:`TestSuite` repesents an aggregation of individuals + tests from one :class:`TestCase` class. *tests* is an iterable of + :class:`TestCase` instances created from the class. *collected_from* is the + class they came from. + .. class:: TestLoader() @@ -550,6 +634,11 @@ The same effect may be had by simply calling the :class:`TestCase` instance. +.. method:: TestCase.skip(reason) + + Skips the current test. See :ref:`unittest-skipping`. + + .. method:: TestCase.debug() Run the test without collecting the result. This allows exceptions raised by @@ -685,10 +774,11 @@ TestSuite Objects ----------------- -:class:`TestSuite` objects behave much like :class:`TestCase` objects, except -they do not actually implement a test. Instead, they are used to aggregate -tests into groups of tests that should be run together. Some additional methods -are available to add tests to :class:`TestSuite` instances: +:class:`TestSuite` (including :class:`ClassTestSuite`) objects behave much like +:class:`TestCase` objects, except they do not actually implement a test. +Instead, they are used to aggregate tests into groups of tests that should be +run together. Some additional methods are available to add tests to +:class:`TestSuite` instances: .. method:: TestSuite.addTest(test) @@ -835,6 +925,34 @@ The default implementation does nothing. +.. method:: TestResult.addSkip(test, reason) + + Called when the test case *test* is skipped. *reason* is the reason the test + gave for skipping. + + The default implementation appends a tuple ``(test, reason)`` to the + instance's ``skipped`` attribute. + + +.. method:: TestResult.addExpectedFailure(test, err) + + Called when the test case *test* fails, but was marked with the + :func:`expectedFailure` decorator. + + The default implementation appends a tuple ``(test, formatted_err)`` to the + instance's ``expected_failures`` attribute, where *formatted_err* is a + formatted traceback derived from *err*. + + +.. method:: TestResult.addUnexpectedSuccess(test) + + Called when the test case *test* was marked with the :func:`expectedFailure` + decorator, but succeeded. + + The default implementation appends the test to the instance's + ``unexpected_successes`` attribute. + + .. _testloader-objects: TestLoader Objects @@ -939,3 +1057,9 @@ This affects all the :meth:`loadTestsFrom\*` methods. + +.. attribute:: TestLoader.classSuiteClass + + Callable object that constructs a test suite for the tests cases from one + class. The default value is :class:`ClassTestSuite`. + Modified: python/branches/py3k/Lib/test/test_unittest.py ============================================================================== --- python/branches/py3k/Lib/test/test_unittest.py (original) +++ python/branches/py3k/Lib/test/test_unittest.py Mon Mar 23 23:25:03 2009 @@ -31,10 +31,27 @@ self._events.append('addFailure') super().addFailure(*args) + def addSuccess(self, *args): + self._events.append('addSuccess') + super(LoggingResult, self).addSuccess(*args) + def addError(self, *args): self._events.append('addError') super().addError(*args) + def addSkip(self, *args): + self._events.append('addSkip') + super(LoggingResult, self).addSkip(*args) + + def addExpectedFailure(self, *args): + self._events.append('addExpectedFailure') + super(LoggingResult, self).addExpectedFailure(*args) + + def addUnexpectedSuccess(self, *args): + self._events.append('addUnexpectedSuccess') + super(LoggingResult, self).addUnexpectedSuccess(*args) + + class TestEquality(object): # Check for a valid __eq__ implementation def test_eq(self): @@ -72,6 +89,13 @@ self.fail("Problem hashing %s and %s: %s" % (obj_1, obj_2, e)) +# List subclass we can add attributes to. +class MyClassSuite(list): + + def __init__(self, tests, klass): + super(MyClassSuite, self).__init__(tests) + + ################################################################ ### /Support code @@ -1233,7 +1257,7 @@ tests = [Foo('test_1'), Foo('test_2')] loader = unittest.TestLoader() - loader.suiteClass = list + loader.classSuiteClass = MyClassSuite self.assertEqual(loader.loadTestsFromTestCase(Foo), tests) # It is implicit in the documentation for TestLoader.suiteClass that @@ -1246,7 +1270,7 @@ def foo_bar(self): pass m.Foo = Foo - tests = [[Foo('test_1'), Foo('test_2')]] + tests = [unittest.ClassTestSuite([Foo('test_1'), Foo('test_2')], Foo)] loader = unittest.TestLoader() loader.suiteClass = list @@ -1265,7 +1289,7 @@ tests = [Foo('test_1'), Foo('test_2')] loader = unittest.TestLoader() - loader.suiteClass = list + loader.classSuiteClass = MyClassSuite self.assertEqual(loader.loadTestsFromName('Foo', m), tests) # It is implicit in the documentation for TestLoader.suiteClass that @@ -1278,7 +1302,7 @@ def foo_bar(self): pass m.Foo = Foo - tests = [[Foo('test_1'), Foo('test_2')]] + tests = [unittest.ClassTestSuite([Foo('test_1'), Foo('test_2')], Foo)] loader = unittest.TestLoader() loader.suiteClass = list @@ -2271,9 +2295,103 @@ # Make run() find a result object on its own Foo('test').run() - expected = ['startTest', 'test', 'stopTest'] + expected = ['startTest', 'test', 'addSuccess', 'stopTest'] self.assertEqual(events, expected) + +class Test_TestSkipping(TestCase): + + def test_skipping(self): + class Foo(unittest.TestCase): + def test_skip_me(self): + self.skip("skip") + events = [] + result = LoggingResult(events) + test = Foo("test_skip_me") + test.run(result) + self.assertEqual(events, ['startTest', 'addSkip', 'stopTest']) + self.assertEqual(result.skipped, [(test, "skip")]) + + # Try letting setUp skip the test now. + class Foo(unittest.TestCase): + def setUp(self): + self.skip("testing") + def test_nothing(self): pass + events = [] + result = LoggingResult(events) + test = Foo("test_nothing") + test.run(result) + self.assertEqual(events, ['startTest', 'addSkip', 'stopTest']) + self.assertEqual(result.skipped, [(test, "testing")]) + self.assertEqual(result.testsRun, 1) + + def test_skipping_decorators(self): + op_table = ((unittest.skipUnless, False, True), + (unittest.skipIf, True, False)) + for deco, do_skip, dont_skip in op_table: + class Foo(unittest.TestCase): + @deco(do_skip, "testing") + def test_skip(self): pass + + @deco(dont_skip, "testing") + def test_dont_skip(self): pass + test_do_skip = Foo("test_skip") + test_dont_skip = Foo("test_dont_skip") + suite = unittest.ClassTestSuite([test_do_skip, test_dont_skip], Foo) + events = [] + result = LoggingResult(events) + suite.run(result) + self.assertEqual(len(result.skipped), 1) + expected = ['startTest', 'addSkip', 'stopTest', + 'startTest', 'addSuccess', 'stopTest'] + self.assertEqual(events, expected) + self.assertEqual(result.testsRun, 2) + self.assertEqual(result.skipped, [(test_do_skip, "testing")]) + self.assertTrue(result.wasSuccessful()) + + def test_skip_class(self): + @unittest.skip("testing") + class Foo(unittest.TestCase): + def test_1(self): + record.append(1) + record = [] + result = unittest.TestResult() + suite = unittest.ClassTestSuite([Foo("test_1")], Foo) + suite.run(result) + self.assertEqual(result.skipped, [(suite, "testing")]) + self.assertEqual(record, []) + + def test_expected_failure(self): + class Foo(unittest.TestCase): + @unittest.expectedFailure + def test_die(self): + self.fail("help me!") + events = [] + result = LoggingResult(events) + test = Foo("test_die") + test.run(result) + self.assertEqual(events, + ['startTest', 'addExpectedFailure', 'stopTest']) + self.assertEqual(result.expected_failures[0][0], test) + self.assertTrue(result.wasSuccessful()) + + def test_unexpected_success(self): + class Foo(unittest.TestCase): + @unittest.expectedFailure + def test_die(self): + pass + events = [] + result = LoggingResult(events) + test = Foo("test_die") + test.run(result) + self.assertEqual(events, + ['startTest', 'addUnexpectedSuccess', 'stopTest']) + self.assertFalse(result.failures) + self.assertEqual(result.unexpected_successes, [test]) + self.assertTrue(result.wasSuccessful()) + + + class Test_Assertions(TestCase): def test_AlmostEqual(self): self.failUnlessAlmostEqual(1.00000001, 1.0) @@ -2338,7 +2456,7 @@ def test_main(): support.run_unittest(Test_TestCase, Test_TestLoader, Test_TestSuite, Test_TestResult, Test_FunctionTestCase, - Test_Assertions) + Test_TestSkipping, Test_Assertions) if __name__ == "__main__": test_main() Modified: python/branches/py3k/Lib/unittest.py ============================================================================== --- python/branches/py3k/Lib/unittest.py (original) +++ python/branches/py3k/Lib/unittest.py Mon Mar 23 23:25:03 2009 @@ -53,6 +53,7 @@ import traceback import os import types +import functools ############################################################################## # Exported classes and functions @@ -71,6 +72,79 @@ def _strclass(cls): return "%s.%s" % (cls.__module__, cls.__name__) + +class SkipTest(Exception): + """ + Raise this exception in a test to skip it. + + Usually you can use TestResult.skip() or one of the skipping decorators + instead of raising this directly. + """ + pass + +class _ExpectedFailure(Exception): + """ + Raise this when a test is expected to fail. + + This is an implementation detail. + """ + + def __init__(self, exc_info): + super(_ExpectedFailure, self).__init__() + self.exc_info = exc_info + +class _UnexpectedSuccess(Exception): + """ + The test was supposed to fail, but it didn't! + """ + pass + +def _id(obj): + return obj + +def skip(reason): + """ + Unconditionally skip a test. + """ + def decorator(test_item): + if isinstance(test_item, type) and issubclass(test_item, TestCase): + test_item.__unittest_skip__ = True + test_item.__unittest_skip_why__ = reason + return test_item + @functools.wraps(test_item) + def skip_wrapper(*args, **kwargs): + raise SkipTest(reason) + return skip_wrapper + return decorator + +def skipIf(condition, reason): + """ + Skip a test if the condition is true. + """ + if condition: + return skip(reason) + return _id + +def skipUnless(condition, reason): + """ + Skip a test unless the condition is true. + """ + if not condition: + return skip(reason) + return _id + + +def expectedFailure(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + try: + func(*args, **kwargs) + except Exception: + raise _ExpectedFailure(sys.exc_info()) + raise _UnexpectedSuccess + return wrapper + + __unittest = 1 class TestResult(object): @@ -88,6 +162,9 @@ self.failures = [] self.errors = [] self.testsRun = 0 + self.skipped = [] + self.expected_failures = [] + self.unexpected_successes = [] self.shouldStop = False def startTest(self, test): @@ -113,6 +190,19 @@ "Called when a test has completed successfully" pass + def addSkip(self, test, reason): + """Called when a test is skipped.""" + self.skipped.append((test, reason)) + + def addExpectedFailure(self, test, err): + """Called when an expected failure/error occured.""" + self.expected_failures.append( + (test, self._exc_info_to_string(err, test))) + + def addUnexpectedSuccess(self, test): + """Called when a test was expected to fail, but succeed.""" + self.unexpected_successes.append(test) + def wasSuccessful(self): "Tells whether or not this result was a success" return len(self.failures) == len(self.errors) == 0 @@ -273,25 +363,36 @@ try: try: self.setUp() + except SkipTest as e: + result.addSkip(self, str(e)) + return except Exception: result.addError(self, self._exc_info()) return - ok = False + success = False try: testMethod() - ok = True except self.failureException: result.addFailure(self, self._exc_info()) + except _ExpectedFailure as e: + result.addExpectedFailure(self, e.exc_info) + except _UnexpectedSuccess: + result.addUnexpectedSuccess(self) + except SkipTest as e: + result.addSkip(self, str(e)) except Exception: result.addError(self, self._exc_info()) + else: + success = True try: self.tearDown() except Exception: result.addError(self, self._exc_info()) - ok = False - if ok: result.addSuccess(self) + success = False + if success: + result.addSuccess(self) finally: result.stopTest(self) @@ -311,6 +412,10 @@ """ return sys.exc_info() + def skip(self, reason): + """Skip this test.""" + raise SkipTest(reason) + def fail(self, msg=None): """Fail immediately, with the given message.""" raise self.failureException(msg) @@ -418,8 +523,8 @@ __str__ = __repr__ def __eq__(self, other): - if type(self) is not type(other): - return False + if not isinstance(other, self.__class__): + return NotImplemented return self._tests == other._tests def __ne__(self, other): @@ -464,6 +569,37 @@ for test in self._tests: test.debug() +class ClassTestSuite(TestSuite): + """ + Suite of tests derived from a single TestCase class. + """ + + def __init__(self, tests, class_collected_from): + super(ClassTestSuite, self).__init__(tests) + self.collected_from = class_collected_from + + def id(self): + module = getattr(self.collected_from, "__module__", None) + if module is not None: + return "{0}.{1}".format(module, self.collected_from.__name__) + return self.collected_from.__name__ + + def run(self, result): + if getattr(self.collected_from, "__unittest_skip__", False): + # ClassTestSuite result pretends to be a TestCase enough to be + # reported. + result.startTest(self) + try: + result.addSkip(self, self.collected_from.__unittest_skip_why__) + finally: + result.stopTest(self) + else: + result = super(ClassTestSuite, self).run(result) + return result + + shortDescription = id + + class FunctionTestCase(TestCase): """A test case that wraps a test function. @@ -550,6 +686,7 @@ testMethodPrefix = 'test' sortTestMethodsUsing = staticmethod(three_way_cmp) suiteClass = TestSuite + classSuiteClass = ClassTestSuite def loadTestsFromTestCase(self, testCaseClass): """Return a suite of all tests cases contained in testCaseClass""" @@ -559,7 +696,9 @@ testCaseNames = self.getTestCaseNames(testCaseClass) if not testCaseNames and hasattr(testCaseClass, 'runTest'): testCaseNames = ['runTest'] - return self.suiteClass(map(testCaseClass, testCaseNames)) + suite = self.classSuiteClass(map(testCaseClass, testCaseNames), + testCaseClass) + return suite def loadTestsFromModule(self, module): """Return a suite of all tests cases contained in the given module""" @@ -739,6 +878,30 @@ self.stream.write('F') self.stream.flush() + def addSkip(self, test, reason): + TestResult.addSkip(self, test, reason) + if self.showAll: + self.stream.writeln("skipped {0!r}".format(reason)) + elif self.dots: + self.stream.write("s") + self.stream.flush() + + def addExpectedFailure(self, test, err): + TestResult.addExpectedFailure(self, test, err) + if self.showAll: + self.stream.writeln("expected failure") + elif self.dots: + self.stream.write(".") + self.stream.flush() + + def addUnexpectedSuccess(self, test): + TestResult.addUnexpectedSuccess(self, test) + if self.showAll: + self.stream.writeln("unexpected success") + elif self.dots: + self.stream.write(".") + self.stream.flush() + def printErrors(self): if self.dots or self.showAll: self.stream.writeln() @@ -780,17 +943,28 @@ self.stream.writeln("Ran %d test%s in %.3fs" % (run, run != 1 and "s" or "", timeTaken)) self.stream.writeln() + results = map(len, (result.expected_failures, + result.unexpected_successes, + result.skipped)) + expected_fails, unexpected_successes, skipped = results + infos = [] if not result.wasSuccessful(): - self.stream.write("FAILED (") + self.stream.write("FAILED") failed, errored = len(result.failures), len(result.errors) if failed: - self.stream.write("failures=%d" % failed) + infos.append("failures=%d" % failed) if errored: - if failed: self.stream.write(", ") - self.stream.write("errors=%d" % errored) - self.stream.writeln(")") + infos.append("errors=%d" % errored) else: - self.stream.writeln("OK") + self.stream.write("OK") + if skipped: + infos.append("skipped=%d" % skipped) + if expected_fails: + infos.append("expected failures=%d" % expected_fails) + if unexpected_successes: + infos.append("unexpected successes=%d" % unexpected_successes) + if infos: + self.stream.writeln(" (%s)" % (", ".join(infos),)) return result @@ -844,9 +1018,9 @@ def parseArgs(self, argv): import getopt + long_opts = ['help','verbose','quiet'] try: - options, args = getopt.getopt(argv[1:], 'hHvq', - ['help','verbose','quiet']) + options, args = getopt.getopt(argv[1:], 'hHvq', long_opts) for opt, value in options: if opt in ('-h','-H','--help'): self.usageExit() From python-checkins at python.org Mon Mar 23 23:29:46 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 23 Mar 2009 23:29:46 +0100 (CET) Subject: [Python-checkins] r70558 - in python/trunk: Doc/library/unittest.rst Lib/test/test_unittest.py Lib/unittest.py Message-ID: <20090323222946.2385C1E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 23 23:29:45 2009 New Revision: 70558 Log: comply with the evilJavaNamingScheme for attribute names It seems my love of PEP 8 overrode the need for consistentcy Modified: python/trunk/Doc/library/unittest.rst python/trunk/Lib/test/test_unittest.py python/trunk/Lib/unittest.py Modified: python/trunk/Doc/library/unittest.rst ============================================================================== --- python/trunk/Doc/library/unittest.rst (original) +++ python/trunk/Doc/library/unittest.rst Mon Mar 23 23:29:45 2009 @@ -950,7 +950,7 @@ :func:`expectedFailure` decorator. The default implementation appends a tuple ``(test, formatted_err)`` to the - instance's ``expected_failures`` attribute, where *formatted_err* is a + instance's ``expectedFailures`` attribute, where *formatted_err* is a formatted traceback derived from *err*. @@ -960,7 +960,7 @@ decorator, but succeeded. The default implementation appends the test to the instance's - ``unexpected_successes`` attribute. + ``unexpectedSuccesses`` attribute. .. _testloader-objects: Modified: python/trunk/Lib/test/test_unittest.py ============================================================================== --- python/trunk/Lib/test/test_unittest.py (original) +++ python/trunk/Lib/test/test_unittest.py Mon Mar 23 23:29:45 2009 @@ -2362,7 +2362,7 @@ test.run(result) self.assertEqual(events, ['startTest', 'addExpectedFailure', 'stopTest']) - self.assertEqual(result.expected_failures[0][0], test) + self.assertEqual(result.expectedFailures[0][0], test) self.assertTrue(result.wasSuccessful()) def test_unexpected_success(self): @@ -2377,7 +2377,7 @@ self.assertEqual(events, ['startTest', 'addUnexpectedSuccess', 'stopTest']) self.assertFalse(result.failures) - self.assertEqual(result.unexpected_successes, [test]) + self.assertEqual(result.unexpectedSuccesses, [test]) self.assertTrue(result.wasSuccessful()) Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Mon Mar 23 23:29:45 2009 @@ -176,8 +176,8 @@ self.errors = [] self.testsRun = 0 self.skipped = [] - self.expected_failures = [] - self.unexpected_successes = [] + self.expectedFailures = [] + self.unexpectedSuccesses = [] self.shouldStop = False def startTest(self, test): @@ -209,12 +209,12 @@ def addExpectedFailure(self, test, err): """Called when an expected failure/error occured.""" - self.expected_failures.append( + self.expectedFailures.append( (test, self._exc_info_to_string(err, test))) def addUnexpectedSuccess(self, test): """Called when a test was expected to fail, but succeed.""" - self.unexpected_successes.append(test) + self.unexpectedSuccesses.append(test) def wasSuccessful(self): "Tells whether or not this result was a success" @@ -923,10 +923,10 @@ self.stream.writeln("Ran %d test%s in %.3fs" % (run, run != 1 and "s" or "", timeTaken)) self.stream.writeln() - results = map(len, (result.expected_failures, - result.unexpected_successes, + results = map(len, (result.expectedFailures, + result.unexpectedSuccesses, result.skipped)) - expected_fails, unexpected_successes, skipped = results + expectedFails, unexpectedSuccesses, skipped = results infos = [] if not result.wasSuccessful(): self.stream.write("FAILED") From python-checkins at python.org Mon Mar 23 23:42:28 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 23 Mar 2009 23:42:28 +0100 (CET) Subject: [Python-checkins] r70559 - python/branches/py3k/Doc/library/itertools.rst Message-ID: <20090323224228.4BEF81E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 23 23:42:28 2009 New Revision: 70559 Log: For some reason rst docs like an initial 3 space indent. Modified: python/branches/py3k/Doc/library/itertools.rst Modified: python/branches/py3k/Doc/library/itertools.rst ============================================================================== --- python/branches/py3k/Doc/library/itertools.rst (original) +++ python/branches/py3k/Doc/library/itertools.rst Mon Mar 23 23:42:28 2009 @@ -683,26 +683,26 @@ s = list(iterable) return chain.from_iterable(combinations(s, r) for r in range(len(s)+1)) - def unique_everseen(iterable, key=None): - "List unique elements, preserving order. Remember all elements ever seen." - # unique_everseen('AAAABBBCCDAABBB') --> A B C D - # unique_everseen('ABBCcAD', str.lower) --> A B C D - seen = set() - seen_add = seen.add - if key is None: - for element in iterable: - if element not in seen: - seen_add(element) - yield element - else: - for element in iterable: - k = key(element) - if k not in seen: - seen_add(k) - yield element + def unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in iterable: + if element not in seen: + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element - def unique_justseen(iterable, key=None): - "List unique elements, preserving order. Remember only the element just seen." - # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B - # unique_justseen('ABBCcAD', str.lower) --> A B C A D - return map(next, map(itemgetter(1), groupby(iterable, key))) + def unique_justseen(iterable, key=None): + "List unique elements, preserving order. Remember only the element just seen." + # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B + # unique_justseen('ABBCcAD', str.lower) --> A B C A D + return map(next, map(itemgetter(1), groupby(iterable, key))) From python-checkins at python.org Mon Mar 23 23:43:36 2009 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 23 Mar 2009 23:43:36 +0100 (CET) Subject: [Python-checkins] r70560 - python/branches/release30-maint/Doc/library/itertools.rst Message-ID: <20090323224336.A691F1E4002@bag.python.org> Author: raymond.hettinger Date: Mon Mar 23 23:43:36 2009 New Revision: 70560 Log: Fix an incorrect merge. Modified: python/branches/release30-maint/Doc/library/itertools.rst Modified: python/branches/release30-maint/Doc/library/itertools.rst ============================================================================== --- python/branches/release30-maint/Doc/library/itertools.rst (original) +++ python/branches/release30-maint/Doc/library/itertools.rst Mon Mar 23 23:43:36 2009 @@ -659,4 +659,4 @@ "List unique elements, preserving order. Remember only the element just seen." # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B # unique_justseen('ABBCcAD', str.lower) --> A B C A D - return map(next, imap(itemgetter(1), groupby(iterable, key))) + return map(next, map(itemgetter(1), groupby(iterable, key))) From python-checkins at python.org Tue Mar 24 00:10:15 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 00:10:15 +0100 (CET) Subject: [Python-checkins] r70561 - python/trunk/Doc/library/unittest.rst Message-ID: <20090323231015.63AE81E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 00:10:14 2009 New Revision: 70561 Log: refactor unittest docs Modified: python/trunk/Doc/library/unittest.rst Modified: python/trunk/Doc/library/unittest.rst ============================================================================== --- python/trunk/Doc/library/unittest.rst (original) +++ python/trunk/Doc/library/unittest.rst Tue Mar 24 00:10:14 2009 @@ -11,9 +11,9 @@ .. versionadded:: 2.1 -.. versionchanged:: 2.7 - Added :ref:`skipping and expected failures `. +.. versionchanged:: 2.7 + Added test :ref:`skipping and expected failures `. The Python unit testing framework, sometimes referred to as "PyUnit," is a Python language version of JUnit, by Kent Beck and Erich Gamma. JUnit is, in @@ -52,27 +52,28 @@ :class:`TestCase` and :class:`FunctionTestCase` classes; the former should be used when creating new tests, and the latter can be used when integrating existing test code with a :mod:`unittest`\ -driven framework. When building test -fixtures using :class:`TestCase`, the :meth:`setUp` and :meth:`tearDown` methods -can be overridden to provide initialization and cleanup for the fixture. With -:class:`FunctionTestCase`, existing functions can be passed to the constructor -for these purposes. When the test is run, the fixture initialization is run -first; if it succeeds, the cleanup method is run after the test has been -executed, regardless of the outcome of the test. Each instance of the -:class:`TestCase` will only be used to run a single test method, so a new -fixture is created for each test. +fixtures using :class:`TestCase`, the :meth:`~TestCase.setUp` and +:meth:`~TestCase.tearDown` methods can be overridden to provide initialization +and cleanup for the fixture. With :class:`FunctionTestCase`, existing functions +can be passed to the constructor for these purposes. When the test is run, the +fixture initialization is run first; if it succeeds, the cleanup method is run +after the test has been executed, regardless of the outcome of the test. Each +instance of the :class:`TestCase` will only be used to run a single test method, +so a new fixture is created for each test. Test suites are implemented by the :class:`TestSuite` class. This class allows individual tests and test suites to be aggregated; when the suite is executed, all tests added directly to the suite and in "child" test suites are run. A :class:`ClassTestSuite` contains the test cases of a class. -A test runner is an object that provides a single method, :meth:`run`, which -accepts a :class:`TestCase` or :class:`TestSuite` object as a parameter, and -returns a result object. The class :class:`TestResult` is provided for use as -the result object. :mod:`unittest` provides the :class:`TextTestRunner` as an -example test runner which reports test results on the standard error stream by -default. Alternate runners can be implemented for other environments (such as -graphical environments) without any need to derive from a specific class. +A test runner is an object that provides a single method, +:meth:`~TestRunner.run`, which accepts a :class:`TestCase` or :class:`TestSuite` +object as a parameter, and returns a result object. The class +:class:`TestResult` is provided for use as the result object. :mod:`unittest` +provides the :class:`TextTestRunner` as an example test runner which reports +test results on the standard error stream by default. Alternate runners can be +implemented for other environments (such as graphical environments) without any +need to derive from a specific class. .. seealso:: @@ -104,17 +105,17 @@ def setUp(self): self.seq = range(10) - def testshuffle(self): + def test_shuffle(self): # make sure the shuffled sequence does not lose any elements random.shuffle(self.seq) self.seq.sort() self.assertEqual(self.seq, range(10)) - def testchoice(self): + def test_choice(self): element = random.choice(self.seq) self.assert_(element in self.seq) - def testsample(self): + def test_sample(self): self.assertRaises(ValueError, random.sample, self.seq, 20) for element in random.sample(self.seq, 5): self.assert_(element in self.seq) @@ -122,21 +123,22 @@ if __name__ == '__main__': unittest.main() -A testcase is created by subclassing :class:`unittest.TestCase`. The three +A testcase is created by subclassing :class:`unittest.TestCase`. The three individual tests are defined with methods whose names start with the letters ``test``. This naming convention informs the test runner about which methods represent tests. -The crux of each test is a call to :meth:`assertEqual` to check for an expected -result; :meth:`assert_` to verify a condition; or :meth:`assertRaises` to verify -that an expected exception gets raised. These methods are used instead of the -:keyword:`assert` statement so the test runner can accumulate all test results -and produce a report. - -When a :meth:`setUp` method is defined, the test runner will run that method -prior to each test. Likewise, if a :meth:`tearDown` method is defined, the test -runner will invoke that method after each test. In the example, :meth:`setUp` -was used to create a fresh sequence for each test. +The crux of each test is a call to :meth:`~TestCase.assertEqual` to check for an +expected result; :meth:`~TestCase.assert_` to verify a condition; or +:meth:`~TestCase.assertRaises` to verify that an expected exception gets raised. +These methods are used instead of the :keyword:`assert` statement so the test +runner can accumulate all test results and produce a report. + +When a :meth:`~TestCase.setUp` method is defined, the test runner will run that +method prior to each test. Likewise, if a :meth:`~TestCase.tearDown` method is +defined, the test runner will invoke that method after each test. In the +example, :meth:`~TestCase.setUp` was used to create a fresh sequence for each +test. The final block shows a simple way to run the tests. :func:`unittest.main` provides a command line interface to the test script. When run from the command @@ -191,8 +193,8 @@ contained, such that it can be run either in isolation or in arbitrary combination with any number of other test cases. -The simplest :class:`TestCase` subclass will simply override the :meth:`runTest` -method in order to perform specific testing code:: +The simplest :class:`TestCase` subclass will simply override the +:meth:`~TestCase.runTest` method in order to perform specific testing code:: import unittest @@ -221,8 +223,8 @@ subclasses would mean unsightly duplication. Luckily, we can factor out such set-up code by implementing a method called -:meth:`setUp`, which the testing framework will automatically call for us when -we run the test:: +:meth:`~TestCase.setUp`, which the testing framework will automatically call for +us when we run the test:: import unittest @@ -241,12 +243,12 @@ self.failUnless(self.widget.size() == (100,150), 'wrong size after resize') -If the :meth:`setUp` method raises an exception while the test is running, the -framework will consider the test to have suffered an error, and the -:meth:`runTest` method will not be executed. +If the :meth:`~TestCase.setUp` method raises an exception while the test is +running, the framework will consider the test to have suffered an error, and the +:meth:`~TestCase.runTest` method will not be executed. -Similarly, we can provide a :meth:`tearDown` method that tidies up after the -:meth:`runTest` method has been run:: +Similarly, we can provide a :meth:`~TestCase.tearDown` method that tidies up +after the :meth:`~TestCase.runTest` method has been run:: import unittest @@ -258,8 +260,8 @@ self.widget.dispose() self.widget = None -If :meth:`setUp` succeeded, the :meth:`tearDown` method will be run whether -:meth:`runTest` succeeded or not. +If :meth:`~TestCase.setUp` succeeded, the :meth:`~TestCase.tearDown` method will +be run whether :meth:`~TestCase.runTest` succeeded or not. Such a working environment for the testing code is called a :dfn:`fixture`. @@ -288,11 +290,12 @@ self.failUnless(self.widget.size() == (100,150), 'wrong size after resize') -Here we have not provided a :meth:`runTest` method, but have instead provided -two different test methods. Class instances will now each run one of the -:meth:`test\*` methods, with ``self.widget`` created and destroyed separately -for each instance. When creating an instance we must specify the test method it -is to run. We do this by passing the method name in the constructor:: +Here we have not provided a :meth:`~TestCase.runTest` method, but have instead +provided two different test methods. Class instances will now each run one of +the :meth:`test\*` methods, with ``self.widget`` created and destroyed +separately for each instance. When creating an instance we must specify the +test method it is to run. We do this by passing the method name in the +constructor:: defaultSizeTestCase = WidgetTestCase('testDefaultSize') resizeTestCase = WidgetTestCase('testResize') @@ -411,6 +414,11 @@ recommended. Taking the time to set up proper :class:`TestCase` subclasses will make future test refactorings infinitely easier. +In some cases, the existing tests may have been written using the :mod:`doctest` +module. If so, :mod:`doctest` provides a :class:`DocTestSuite` class that can +automatically build :class:`unittest.TestSuite` instances from the existing +:mod:`doctest`\ -based tests. + .. _unittest-skipping: @@ -489,6 +497,13 @@ Classes and functions --------------------- +This section describes in depth the API of :mod:`unittest`. + + +.. _testcase-objects: + +Test cases +~~~~~~~~~~ .. class:: TestCase([methodName]) @@ -512,560 +527,569 @@ Here, we create two instances of :class:`WidgetTestCase`, each of which runs a single test. - *methodName* defaults to ``'runTest'``. + *methodName* defaults to :meth:`runTest`. + :class:`TestCase` instances provide three groups of methods: one group used + to run the test, another used by the test implementation to check conditions + and report failures, and some inquiry methods allowing information about the + test itself to be gathered. -.. class:: FunctionTestCase(testFunc[, setUp[, tearDown[, description]]]) + Methods in the first group (running the test) are: - This class implements the portion of the :class:`TestCase` interface which - allows the test runner to drive the test, but does not provide the methods which - test code can use to check and report errors. This is used to create test cases - using legacy test code, allowing it to be integrated into a :mod:`unittest`\ - -based test framework. + .. method:: setUp() -.. class:: TestSuite([tests]) + Method called to prepare the test fixture. This is called immediately + before calling the test method; any exception raised by this method will + be considered an error rather than a test failure. The default + implementation does nothing. - This class represents an aggregation of individual tests cases and test suites. - The class presents the interface needed by the test runner to allow it to be run - as any other test case. Running a :class:`TestSuite` instance is the same as - iterating over the suite, running each test individually. - 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. Additional methods - are provided to add test cases and suites to the collection later on. + .. method:: tearDown() -.. class:: ClassTestSuite(tests, collected_from) + Method called immediately after the test method has been called and the + result recorded. This is called even if the test method raised an + exception, so the implementation in subclasses may need to be particularly + careful about checking internal state. Any exception raised by this + method will be considered an error rather than a test failure. This + method will only be called if the :meth:`setUp` succeeds, regardless of + the outcome of the test method. The default implementation does nothing. - This subclass of :class:`TestSuite` repesents an aggregation of individuals - tests from one :class:`TestCase` class. *tests* is an iterable of - :class:`TestCase` instances created from the class. *collected_from* is the - class they came from. + .. method:: run([result]) -.. class:: TestLoader() + Run the test, collecting the result into the test result object passed as + *result*. If *result* is omitted or :const:`None`, a temporary result + object is created (by calling the :meth:`defaultTestCase` method) and + used; this result object is not returned to :meth:`run`'s caller. - This class is responsible for loading tests according to various criteria and - returning them wrapped in a :class:`TestSuite`. It can load all tests within a - given module or :class:`TestCase` subclass. + The same effect may be had by simply calling the :class:`TestCase` + instance. -.. class:: TestResult() + .. method:: skip(reason) - This class is used to compile information about which tests have succeeded and - which have failed. + Skips the current test. See :ref:`unittest-skipping` for more + information. -.. data:: defaultTestLoader + .. method:: debug() - Instance of the :class:`TestLoader` class intended to be shared. If no - customization of the :class:`TestLoader` is needed, this instance can be used - instead of repeatedly creating new instances. + Run the test without collecting the result. This allows exceptions raised + by the test to be propagated to the caller, and can be used to support + running tests under a debugger. + The test code can use any of the following methods to check for and report + failures. -.. class:: TextTestRunner([stream[, descriptions[, verbosity]]]) - A basic test runner implementation which prints results on standard error. It - has a few configurable parameters, but is essentially very simple. Graphical - applications which run test suites should provide alternate implementations. + .. method:: assert_(expr[, msg]) + failUnless(expr[, msg]) + assertTrue(expr[, msg]) + Signal a test failure if *expr* is false; the explanation for the error + will be *msg* if given, otherwise it will be :const:`None`. -.. function:: main([module[, defaultTest[, argv[, testRunner[, 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 test script:: + .. method:: assertEqual(first, second[, msg]) + failUnlessEqual(first, second[, msg]) - if __name__ == '__main__': - unittest.main() + Test that *first* and *second* are equal. If the values do not compare + equal, the test will fail with the explanation given by *msg*, or + :const:`None`. Note that using :meth:`failUnlessEqual` improves upon + doing the comparison as the first parameter to :meth:`failUnless`: the + default value for *msg* can be computed to include representations of both + *first* and *second*. - The *testRunner* argument can either be a test runner class or an already - created instance of it. -In some cases, the existing tests may have been written using the :mod:`doctest` -module. If so, that module provides a :class:`DocTestSuite` class that can -automatically build :class:`unittest.TestSuite` instances from the existing -:mod:`doctest`\ -based tests. + .. method:: assertNotEqual(first, second[, msg]) + failIfEqual(first, second[, msg]) -.. versionadded:: 2.3 + Test that *first* and *second* are not equal. If the values do compare + equal, the test will fail with the explanation given by *msg*, or + :const:`None`. Note that using :meth:`failIfEqual` improves upon doing + the comparison as the first parameter to :meth:`failUnless` is that the + default value for *msg* can be computed to include representations of both + *first* and *second*. -.. _testcase-objects: + .. method:: assertAlmostEqual(first, second[, places[, msg]]) + failUnlessAlmostEqual(first, second[, places[, msg]]) -TestCase Objects ----------------- + Test that *first* and *second* are approximately equal by computing the + difference, rounding to the given number of decimal *places* (default 7), + and comparing to zero. -Each :class:`TestCase` instance represents a single test, but each concrete -subclass may be used to define multiple tests --- the concrete class represents -a single test fixture. The fixture is created and cleaned up for each test -case. + Note that comparing a given number of decimal places is not the same as + comparing a given number of significant digits. If the values do not + compare equal, the test will fail with the explanation given by *msg*, or + :const:`None`. -:class:`TestCase` instances provide three groups of methods: one group used to -run the test, another used by the test implementation to check conditions and -report failures, and some inquiry methods allowing information about the test -itself to be gathered. -Methods in the first group (running the test) are: + .. method:: assertNotAlmostEqual(first, second[, places[, msg]]) + failIfAlmostEqual(first, second[, places[, msg]]) + Test that *first* and *second* are not approximately equal by computing + the difference, rounding to the given number of decimal *places* (default + 7), and comparing to zero. -.. method:: TestCase.setUp() + Note that comparing a given number of decimal places is not the same as + comparing a given number of significant digits. If the values do not + compare equal, the test will fail with the explanation given by *msg*, or + :const:`None`. - Method called to prepare the test fixture. This is called immediately before - calling the test method; any exception raised by this method will be considered - an error rather than a test failure. The default implementation does nothing. + .. method:: assertRaises(exception[, callable, ...]) + failUnlessRaises(exception[, callable, ...]) -.. method:: TestCase.tearDown() + Test that an exception is raised when *callable* is called with any + positional or keyword arguments that are also passed to + :meth:`assertRaises`. The test passes if *exception* is raised, is an + error if another exception is raised, or fails if no exception is raised. + To catch any of a group of exceptions, a tuple containing the exception + classes may be passed as *exception*. - Method called immediately after the test method has been called and the result - recorded. This is called even if the test method raised an exception, so the - implementation in subclasses may need to be particularly careful about checking - internal state. Any exception raised by this method will be considered an error - rather than a test failure. This method will only be called if the - :meth:`setUp` succeeds, regardless of the outcome of the test method. The - default implementation does nothing. + .. versionchanged:: 2.7 + If *callable* is omitted or None, returns a context manager so that the + code under test can be written inline rather than as a function:: -.. method:: TestCase.run([result]) + with self.failUnlessRaises(some_error_class): + do_something() - Run the test, collecting the result into the test result object passed as - *result*. If *result* is omitted or :const:`None`, a temporary result object is - created (by calling the :meth:`defaultTestCase` method) and used; this result - object is not returned to :meth:`run`'s caller. + .. method:: failIf(expr[, msg]) + assertFalse(expr[, msg]) - The same effect may be had by simply calling the :class:`TestCase` instance. + The inverse of the :meth:`failUnless` method is the :meth:`failIf` method. + This signals a test failure if *expr* is true, with *msg* or :const:`None` + for the error message. -.. method:: TestCase.skip(reason) + .. method:: fail([msg]) - Skips the current test. See :ref:`unittest-skipping`. + Signals a test failure unconditionally, with *msg* or :const:`None` for + the error message. -.. method:: TestCase.debug() + .. attribute:: failureException - Run the test without collecting the result. This allows exceptions raised by - the test to be propagated to the caller, and can be used to support running - tests under a debugger. + 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 + :exc:`AssertionError`. -The test code can use any of the following methods to check for and report -failures. + Testing frameworks can use the following methods to collect information on + the test: -.. method:: TestCase.assert_(expr[, msg]) - TestCase.failUnless(expr[, msg]) - TestCase.assertTrue(expr[, msg]) + .. method:: countTestCases() - Signal a test failure if *expr* is false; the explanation for the error will be - *msg* if given, otherwise it will be :const:`None`. + Return the number of tests represented by this test object. For + :class:`TestCase` instances, this will always be ``1``. -.. method:: TestCase.assertEqual(first, second[, msg]) - TestCase.failUnlessEqual(first, second[, msg]) + .. method:: defaultTestResult() - Test that *first* and *second* are equal. If the values do not compare equal, - the test will fail with the explanation given by *msg*, or :const:`None`. Note - that using :meth:`failUnlessEqual` improves upon doing the comparison as the - first parameter to :meth:`failUnless`: the default value for *msg* can be - computed to include representations of both *first* and *second*. + Return an instance of the test result class that should be used for this + test case class (if no other result instance is provided to the + :meth:`run` method). + For :class:`TestCase` instances, this will always be an instance of + :class:`TestResult`; subclasses of :class:`TestCase` should override this + as necessary. -.. method:: TestCase.assertNotEqual(first, second[, msg]) - TestCase.failIfEqual(first, second[, msg]) - Test that *first* and *second* are not equal. If the values do compare equal, - the test will fail with the explanation given by *msg*, or :const:`None`. Note - that using :meth:`failIfEqual` improves upon doing the comparison as the first - parameter to :meth:`failUnless` is that the default value for *msg* can be - computed to include representations of both *first* and *second*. + .. method:: id() + Return a string identifying the specific test case. This is usually the + full name of the test method, including the module and class name. -.. method:: TestCase.assertAlmostEqual(first, second[, places[, msg]]) - TestCase.failUnlessAlmostEqual(first, second[, places[, msg]]) - Test that *first* and *second* are approximately equal by computing the - difference, rounding to the given number of decimal *places* (default 7), - and comparing to zero. - Note that comparing a given number of decimal places is not the same as - comparing a given number of significant digits. If the values do not compare - equal, the test will fail with the explanation given by *msg*, or :const:`None`. + .. method:: shortDescription() + Returns a one-line description of the test, or :const:`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 + :const:`None`. -.. method:: TestCase.assertNotAlmostEqual(first, second[, places[, msg]]) - TestCase.failIfAlmostEqual(first, second[, places[, msg]]) - Test that *first* and *second* are not approximately equal by computing the - difference, rounding to the given number of decimal *places* (default 7), - and comparing to zero. - Note that comparing a given number of decimal places is not the same as - comparing a given number of significant digits. If the values do not compare - equal, the test will fail with the explanation given by *msg*, or :const:`None`. +.. class:: FunctionTestCase(testFunc[, setUp[, tearDown[, description]]]) + This class implements the portion of the :class:`TestCase` interface which + allows the test runner to drive the test, but does not provide the methods which + test code can use to check and report errors. This is used to create test cases + using legacy test code, allowing it to be integrated into a :mod:`unittest`\ + -based test framework. -.. method:: TestCase.assertRaises(exception[, callable, ...]) - TestCase.failUnlessRaises(exception[, callable, ...]) - Test that an exception is raised when *callable* is called with any positional - or keyword arguments that are also passed to :meth:`assertRaises`. The test - passes if *exception* is raised, is an error if another exception is raised, or - fails if no exception is raised. To catch any of a group of exceptions, a tuple - containing the exception classes may be passed as *exception*. +.. _testsuite-objects: - .. versionchanged:: 2.7 +Grouping tests +~~~~~~~~~~~~~~ - If *callable* is omitted or None, returns a context manager so that the code - under test can be written inline rather than as a function:: +.. class:: TestSuite([tests]) - with self.failUnlessRaises(some_error_class): - do_something() + This class represents an aggregation of individual tests cases and test suites. + The class presents the interface needed by the test runner to allow it to be run + as any other test case. Running a :class:`TestSuite` instance is the same as + iterating over the suite, running each test individually. -.. method:: TestCase.failIf(expr[, msg]) - TestCase.assertFalse(expr[, msg]) + 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. Additional methods + are provided to add test cases and suites to the collection later on. - The inverse of the :meth:`failUnless` method is the :meth:`failIf` method. This - signals a test failure if *expr* is true, with *msg* or :const:`None` for the - error message. + :class:`TestSuite` (including :class:`ClassTestSuite`) objects behave much + like :class:`TestCase` objects, except they do not actually implement a test. + Instead, they are used to aggregate tests into groups of tests that should be + run together. Some additional methods are available to add tests to + :class:`TestSuite` instances: -.. method:: TestCase.fail([msg]) + .. method:: TestSuite.addTest(test) - Signals a test failure unconditionally, with *msg* or :const:`None` for the - error message. + Add a :class:`TestCase` or :class:`TestSuite` to the suite. -.. attribute:: TestCase.failureException + .. method:: TestSuite.addTests(tests) - This class attribute gives the exception raised by the :meth:`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 - :exc:`AssertionError`. + Add all the tests from an iterable of :class:`TestCase` and :class:`TestSuite` + instances to this test suite. -Testing frameworks can use the following methods to collect information on the -test: + This is equivalent to iterating over *tests*, calling :meth:`addTest` for each + element. + :class:`TestSuite` shares the following methods with :class:`TestCase`: -.. method:: TestCase.countTestCases() - Return the number of tests represented by this test object. For - :class:`TestCase` instances, this will always be ``1``. + .. method:: run(result) + Run the tests associated with this suite, collecting the result into the + test result object passed as *result*. Note that unlike + :meth:`TestCase.run`, :meth:`TestSuite.run` requires the result object to + be passed in. -.. method:: TestCase.defaultTestResult() - Return an instance of the test result class that should be used for this test - case class (if no other result instance is provided to the :meth:`run` method). + .. method:: debug() - For :class:`TestCase` instances, this will always be an instance of - :class:`TestResult`; subclasses of :class:`TestCase` should override this as - necessary. + Run the tests associated with this suite without collecting the + result. This allows exceptions raised by the test to be propagated to the + caller and can be used to support running tests under a debugger. -.. method:: TestCase.id() + .. method:: countTestCases() - Return a string identifying the specific test case. This is usually the full - name of the test method, including the module and class name. + Return the number of tests represented by this test object, including all + individual tests and sub-suites. + In the typical usage of a :class:`TestSuite` object, the :meth:`run` method + is invoked by a :class:`TestRunner` rather than by the end-user test harness. -.. method:: TestCase.shortDescription() - Returns a one-line description of the test, or :const:`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 :const:`None`. +.. class:: ClassTestSuite(tests, collected_from) + This subclass of :class:`TestSuite` repesents an aggregation of individuals + tests from one :class:`TestCase` class. *tests* is an iterable of + :class:`TestCase` instances created from the class. *collected_from* is the + class they came from. -.. _testsuite-objects: -TestSuite Objects ------------------ +Loading and running tests +~~~~~~~~~~~~~~~~~~~~~~~~~ -:class:`TestSuite` (including :class:`ClassTestSuite`) objects behave much like -:class:`TestCase` objects, except they do not actually implement a test. -Instead, they are used to aggregate tests into groups of tests that should be -run together. Some additional methods are available to add tests to -:class:`TestSuite` instances: +.. class:: TestLoader() + The :class:`TestLoader` class is used to create test suites from classes and + modules. Normally, there is no need to create an instance of this class; the + :mod:`unittest` module provides an instance that can be shared as + ``unittest.defaultTestLoader``. Using a subclass or instance, however, allows + customization of some configurable properties. -.. method:: TestSuite.addTest(test) + :class:`TestLoader` objects have the following methods: - Add a :class:`TestCase` or :class:`TestSuite` to the suite. + .. method:: loadTestsFromTestCase(testCaseClass) -.. method:: TestSuite.addTests(tests) + Return a suite of all tests cases contained in the :class:`TestCase`\ -derived + :class:`testCaseClass`. - Add all the tests from an iterable of :class:`TestCase` and :class:`TestSuite` - instances to this test suite. - This is equivalent to iterating over *tests*, calling :meth:`addTest` for each - element. + .. method:: loadTestsFromModule(module) -:class:`TestSuite` shares the following methods with :class:`TestCase`: + Return a suite of all tests cases contained in the given module. This + method searches *module* for classes derived from :class:`TestCase` and + creates an instance of the class for each test method defined for the + class. + .. warning:: -.. method:: TestSuite.run(result) + While using a hierarchy of :class:`TestCase`\ -derived classes can be + convenient in sharing fixtures and helper functions, defining test + methods on base classes that are not intended to be instantiated + directly does not play well with this method. Doing so, however, can + be useful when the fixtures are different and defined in subclasses. - Run the tests associated with this suite, collecting the result into the test - result object passed as *result*. Note that unlike :meth:`TestCase.run`, - :meth:`TestSuite.run` requires the result object to be passed in. + .. method:: loadTestsFromName(name[, module]) -.. method:: TestSuite.debug() + Return a suite of all tests cases given a string specifier. - Run the tests associated with this suite without collecting the result. This - allows exceptions raised by the test to be propagated to the caller and can be - used to support running tests under a debugger. + The specifier *name* is a "dotted name" that may resolve either to a + module, a test case class, a test method within a test case class, a + :class:`TestSuite` instance, or a callable object which returns a + :class:`TestCase` or :class:`TestSuite` instance. These checks are + applied in the order listed here; that is, a method on a possible test + case class will be picked up as "a test method within a test case class", + rather than "a callable object". + For example, if you have a module :mod:`SampleTests` containing a + :class:`TestCase`\ -derived class :class:`SampleTestCase` with three test + methods (:meth:`test_one`, :meth:`test_two`, and :meth:`test_three`), the + specifier ``'SampleTests.SampleTestCase'`` would cause this method to return a + suite which will run all three test methods. Using the specifier + ``'SampleTests.SampleTestCase.test_two'`` would cause it to return a test suite + which will run only the :meth:`test_two` test method. The specifier can refer + to modules and packages which have not been imported; they will be imported as a + side-effect. -.. method:: TestSuite.countTestCases() + The method optionally resolves *name* relative to the given *module*. - Return the number of tests represented by this test object, including all - individual tests and sub-suites. -In the typical usage of a :class:`TestSuite` object, the :meth:`run` method is -invoked by a :class:`TestRunner` rather than by the end-user test harness. + .. method:: loadTestsFromNames(names[, module]) + Similar to :meth:`loadTestsFromName`, but takes a sequence of names rather + than a single name. The return value is a test suite which supports all + the tests defined for each name. -.. _testresult-objects: -TestResult Objects ------------------- + .. method:: getTestCaseNames(testCaseClass) -A :class:`TestResult` object stores the results of a set of tests. The -:class:`TestCase` and :class:`TestSuite` classes ensure that results are -properly recorded; test authors do not need to worry about recording the outcome -of tests. + Return a sorted sequence of method names found within *testCaseClass*; + this should be a subclass of :class:`TestCase`. -Testing frameworks built on top of :mod:`unittest` may want access to the -:class:`TestResult` object generated by running a set of tests for reporting -purposes; a :class:`TestResult` instance is returned by the -:meth:`TestRunner.run` method for this purpose. + The following attributes of a :class:`TestLoader` can be configured either by + subclassing or assignment on an instance: -:class:`TestResult` instances have the following attributes that will be of -interest when inspecting the results of running a set of tests: + .. attribute:: testMethodPrefix -.. attribute:: TestResult.errors + String giving the prefix of method names which will be interpreted as test + methods. The default value is ``'test'``. - A list containing 2-tuples of :class:`TestCase` instances and strings holding - formatted tracebacks. Each tuple represents a test which raised an unexpected - exception. + This affects :meth:`getTestCaseNames` and all the :meth:`loadTestsFrom\*` + methods. - .. versionchanged:: 2.2 - Contains formatted tracebacks instead of :func:`sys.exc_info` results. + .. attribute:: sortTestMethodsUsing -.. attribute:: TestResult.failures + Function to be used to compare method names when sorting them in + :meth:`getTestCaseNames` and all the :meth:`loadTestsFrom\*` methods. The + default value is the built-in :func:`cmp` function; the attribute can also + be set to :const:`None` to disable the sort. - A list containing 2-tuples of :class:`TestCase` instances and strings holding - formatted tracebacks. Each tuple represents a test where a failure was - explicitly signalled using the :meth:`TestCase.fail\*` or - :meth:`TestCase.assert\*` methods. - .. versionchanged:: 2.2 - Contains formatted tracebacks instead of :func:`sys.exc_info` results. + .. attribute:: suiteClass + Callable object that constructs a test suite from a list of tests. No + methods on the resulting object are needed. The default value is the + :class:`TestSuite` class. -.. attribute:: TestResult.testsRun + This affects all the :meth:`loadTestsFrom\*` methods. - The total number of tests run so far. + .. attribute:: classSuiteClass -.. method:: TestResult.wasSuccessful() + Callable object that constructs a test suite for the tests cases from one + class. The default value is :class:`ClassTestSuite`. - Returns :const:`True` if all tests run so far have passed, otherwise returns - :const:`False`. +.. class:: TestResult -.. method:: TestResult.stop() + This class is used to compile information about which tests have succeeded + and which have failed. - This method can be called to signal that the set of tests being run should be - aborted by setting the :class:`TestResult`'s ``shouldStop`` attribute to - :const:`True`. :class:`TestRunner` objects should respect this flag and return - without running any additional tests. + A :class:`TestResult` object stores the results of a set of tests. The + :class:`TestCase` and :class:`TestSuite` classes ensure that results are + properly recorded; test authors do not need to worry about recording the + outcome of tests. - For example, this feature is used by the :class:`TextTestRunner` class to stop - the test framework when the user signals an interrupt from the keyboard. - Interactive tools which provide :class:`TestRunner` implementations can use this - in a similar manner. + Testing frameworks built on top of :mod:`unittest` may want access to the + :class:`TestResult` object generated by running a set of tests for reporting + purposes; a :class:`TestResult` instance is returned by the + :meth:`TestRunner.run` method for this purpose. -The following methods of the :class:`TestResult` class are used to maintain the -internal data structures, and may be extended in subclasses to support -additional reporting requirements. This is particularly useful in building -tools which support interactive reporting while tests are being run. + :class:`TestResult` instances have the following attributes that will be of + interest when inspecting the results of running a set of tests: -.. method:: TestResult.startTest(test) + .. attribute:: errors - Called when the test case *test* is about to be run. + A list containing 2-tuples of :class:`TestCase` instances and strings + holding formatted tracebacks. Each tuple represents a test which raised an + unexpected exception. - The default implementation simply increments the instance's ``testsRun`` - counter. + .. versionchanged:: 2.2 + Contains formatted tracebacks instead of :func:`sys.exc_info` results. -.. method:: TestResult.stopTest(test) - Called after the test case *test* has been executed, regardless of the outcome. + .. attribute:: failures - The default implementation does nothing. + A list containing 2-tuples of :class:`TestCase` instances and strings + holding formatted tracebacks. Each tuple represents a test where a failure + was explicitly signalled using the :meth:`TestCase.fail\*` or + :meth:`TestCase.assert\*` methods. + .. versionchanged:: 2.2 -.. method:: TestResult.addError(test, err) + Contains formatted tracebacks instead of :func:`sys.exc_info` results. - Called when the test case *test* raises an unexpected exception *err* is a tuple - of the form returned by :func:`sys.exc_info`: ``(type, value, traceback)``. + .. attribute:: skipped - The default implementation appends a tuple ``(test, formatted_err)`` to the - instance's ``errors`` attribute, where *formatted_err* is a formatted - traceback derived from *err*. + A list containing 2-tuples of :class:`TestCase` instances and strings + holding the reason for skipping the test. + .. versionadded:: 2.7 -.. method:: TestResult.addFailure(test, err) + .. attribute:: expectedFailures - Called when the test case *test* signals a failure. *err* is a tuple of the form - returned by :func:`sys.exc_info`: ``(type, value, traceback)``. + A list contaning 2-tuples of :class:`TestCase` instances and strings + holding formatted tracebacks. Each tuple represents a expected failures + of the test case. - The default implementation appends a tuple ``(test, formatted_err)`` to the - instance's ``failures`` attribute, where *formatted_err* is a formatted - traceback derived from *err*. + .. attribute:: unexpectedSuccesses + A list containing :class:`TestCase` instances that were marked as expected + failures, but succeeded. -.. method:: TestResult.addSuccess(test) + .. attribute:: shouldStop - Called when the test case *test* succeeds. + Set to ``True`` when the execution of tests should stop by :meth:`stop`. - The default implementation does nothing. + .. attribute:: testsRun -.. method:: TestResult.addSkip(test, reason) + The total number of tests run so far. - Called when the test case *test* is skipped. *reason* is the reason the test - gave for skipping. - The default implementation appends a tuple ``(test, reason)`` to the - instance's ``skipped`` attribute. + .. method:: wasSuccessful() + Return :const:`True` if all tests run so far have passed, otherwise returns + :const:`False`. -.. method:: TestResult.addExpectedFailure(test, err) - Called when the test case *test* fails, but was marked with the - :func:`expectedFailure` decorator. + .. method:: stop() - The default implementation appends a tuple ``(test, formatted_err)`` to the - instance's ``expectedFailures`` attribute, where *formatted_err* is a - formatted traceback derived from *err*. + This method can be called to signal that the set of tests being run should + be aborted by setting the :attr:`shouldStop` attribute to :const:`True`. + :class:`TestRunner` objects should respect this flag and return without + running any additional tests. + For example, this feature is used by the :class:`TextTestRunner` class to + stop the test framework when the user signals an interrupt from the + keyboard. Interactive tools which provide :class:`TestRunner` + implementations can use this in a similar manner. -.. method:: TestResult.addUnexpectedSuccess(test) + The following methods of the :class:`TestResult` class are used to maintain + the internal data structures, and may be extended in subclasses to support + additional reporting requirements. This is particularly useful in building + tools which support interactive reporting while tests are being run. - Called when the test case *test* was marked with the :func:`expectedFailure` - decorator, but succeeded. - The default implementation appends the test to the instance's - ``unexpectedSuccesses`` attribute. + .. method:: startTest(test) + Called when the test case *test* is about to be run. -.. _testloader-objects: + The default implementation simply increments the instance's :attr:`testsRun` + counter. -TestLoader Objects ------------------- -The :class:`TestLoader` class is used to create test suites from classes and -modules. Normally, there is no need to create an instance of this class; the -:mod:`unittest` module provides an instance that can be shared as -``unittest.defaultTestLoader``. Using a subclass or instance, however, allows -customization of some configurable properties. + .. method:: stopTest(test) -:class:`TestLoader` objects have the following methods: + Called after the test case *test* has been executed, regardless of the + outcome. + The default implementation does nothing. -.. method:: TestLoader.loadTestsFromTestCase(testCaseClass) - Return a suite of all tests cases contained in the :class:`TestCase`\ -derived - :class:`testCaseClass`. + .. method:: addError(test, err) + Called when the test case *test* raises an unexpected exception *err* is a + tuple of the form returned by :func:`sys.exc_info`: ``(type, value, + traceback)``. -.. method:: TestLoader.loadTestsFromModule(module) + The default implementation appends a tuple ``(test, formatted_err)`` to + the instance's :attr:`errors` attribute, where *formatted_err* is a + formatted traceback derived from *err*. - Return a suite of all tests cases contained in the given module. This method - searches *module* for classes derived from :class:`TestCase` and creates an - instance of the class for each test method defined for the class. - .. warning:: + .. method:: addFailure(test, err) - While using a hierarchy of :class:`TestCase`\ -derived classes can be convenient - in sharing fixtures and helper functions, defining test methods on base classes - that are not intended to be instantiated directly does not play well with this - method. Doing so, however, can be useful when the fixtures are different and - defined in subclasses. + Called when the test case *test* signals a failure. *err* is a tuple of the form + returned by :func:`sys.exc_info`: ``(type, value, traceback)``. + The default implementation appends a tuple ``(test, formatted_err)`` to + the instance's :attr:`failures` attribute, where *formatted_err* is a + formatted traceback derived from *err*. -.. method:: TestLoader.loadTestsFromName(name[, module]) - Return a suite of all tests cases given a string specifier. + .. method:: addSuccess(test) - The specifier *name* is a "dotted name" that may resolve either to a module, a - test case class, a test method within a test case class, a :class:`TestSuite` - instance, or a callable object which returns a :class:`TestCase` or - :class:`TestSuite` instance. These checks are applied in the order listed here; - that is, a method on a possible test case class will be picked up as "a test - method within a test case class", rather than "a callable object". + Called when the test case *test* succeeds. - For example, if you have a module :mod:`SampleTests` containing a - :class:`TestCase`\ -derived class :class:`SampleTestCase` with three test - methods (:meth:`test_one`, :meth:`test_two`, and :meth:`test_three`), the - specifier ``'SampleTests.SampleTestCase'`` would cause this method to return a - suite which will run all three test methods. Using the specifier - ``'SampleTests.SampleTestCase.test_two'`` would cause it to return a test suite - which will run only the :meth:`test_two` test method. The specifier can refer - to modules and packages which have not been imported; they will be imported as a - side-effect. + The default implementation does nothing. - The method optionally resolves *name* relative to the given *module*. + .. method:: addSkip(test, reason) -.. method:: TestLoader.loadTestsFromNames(names[, module]) + Called when the test case *test* is skipped. *reason* is the reason the + test gave for skipping. - Similar to :meth:`loadTestsFromName`, but takes a sequence of names rather than - a single name. The return value is a test suite which supports all the tests - defined for each name. + The default implementation appends a tuple ``(test, reason)`` to the + instance's :attr:`skipped` attribute. -.. method:: TestLoader.getTestCaseNames(testCaseClass) + .. method:: addExpectedFailure(test, err) - Return a sorted sequence of method names found within *testCaseClass*; this - should be a subclass of :class:`TestCase`. + Called when the test case *test* fails, but was marked with the + :func:`expectedFailure` decorator. -The following attributes of a :class:`TestLoader` can be configured either by -subclassing or assignment on an instance: + The default implementation appends a tuple ``(test, formatted_err)`` to + the instance's :attr:`expectedFailures` attribute, where *formatted_err* + is a formatted traceback derived from *err*. -.. attribute:: TestLoader.testMethodPrefix + .. method:: addUnexpectedSuccess(test) - String giving the prefix of method names which will be interpreted as test - methods. The default value is ``'test'``. + Called when the test case *test* was marked with the + :func:`expectedFailure` decorator, but succeeded. - This affects :meth:`getTestCaseNames` and all the :meth:`loadTestsFrom\*` - methods. + The default implementation appends the test to the instance's + :attr:`unexpectedSuccesses` attribute. -.. attribute:: TestLoader.sortTestMethodsUsing +.. data:: defaultTestLoader - Function to be used to compare method names when sorting them in - :meth:`getTestCaseNames` and all the :meth:`loadTestsFrom\*` methods. The - default value is the built-in :func:`cmp` function; the attribute can also be - set to :const:`None` to disable the sort. + Instance of the :class:`TestLoader` class intended to be shared. If no + customization of the :class:`TestLoader` is needed, this instance can be used + instead of repeatedly creating new instances. -.. attribute:: TestLoader.suiteClass +.. class:: TextTestRunner([stream[, descriptions[, verbosity]]]) - Callable object that constructs a test suite from a list of tests. No methods on - the resulting object are needed. The default value is the :class:`TestSuite` - class. + A basic test runner implementation which prints results on standard error. It + has a few configurable parameters, but is essentially very simple. Graphical + applications which run test suites should provide alternate implementations. - This affects all the :meth:`loadTestsFrom\*` methods. +.. function:: main([module[, defaultTest[, argv[, testRunner[, testLoader]]]]]) -.. attribute:: TestLoader.classSuiteClass + 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 test script:: - Callable object that constructs a test suite for the tests cases from one - class. The default value is :class:`ClassTestSuite`. + if __name__ == '__main__': + unittest.main() + The *testRunner* argument can either be a test runner class or an already + created instance of it. From python-checkins at python.org Tue Mar 24 00:13:36 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 00:13:36 +0100 (CET) Subject: [Python-checkins] r70562 - python/trunk/Doc/library/unittest.rst Message-ID: <20090323231336.34F181E400C@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 00:13:36 2009 New Revision: 70562 Log: forgot to document that setUp can be skipped (silly me...) Modified: python/trunk/Doc/library/unittest.rst Modified: python/trunk/Doc/library/unittest.rst ============================================================================== --- python/trunk/Doc/library/unittest.rst (original) +++ python/trunk/Doc/library/unittest.rst Tue Mar 24 00:13:36 2009 @@ -455,6 +455,9 @@ def test_not_run(self): pass +:meth:`TestCase.setUp` can also skip the test. This is useful when a resource +that needs to be set up is not available. + Expected failures use the :func:`expectedFailure` decorator. :: class ExpectedFailureTestCase(unittest.TestCase): @@ -569,8 +572,8 @@ .. method:: skip(reason) - Skips the current test. See :ref:`unittest-skipping` for more - information. + Calling this during the a test method or :meth:`setUp` skips the current + test. See :ref:`unittest-skipping` for more information. .. method:: debug() From python-checkins at python.org Tue Mar 24 00:19:03 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 00:19:03 +0100 (CET) Subject: [Python-checkins] r70563 - python/trunk/Lib/unittest.py Message-ID: <20090323231903.A48F71E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 00:19:03 2009 New Revision: 70563 Log: update from CVS Modified: python/trunk/Lib/unittest.py (contents, props changed) Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Tue Mar 24 00:19:03 2009 @@ -46,7 +46,7 @@ __author__ = "Steve Purcell" __email__ = "stephen_purcell at yahoo dot com" -__version__ = "#Revision: 1.63 $"[11:-2] +__version__ = "$Id$" import time import sys From martin at v.loewis.de Tue Mar 24 00:27:55 2009 From: martin at v.loewis.de (=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=) Date: Tue, 24 Mar 2009 00:27:55 +0100 Subject: [Python-checkins] r70563 - python/trunk/Lib/unittest.py In-Reply-To: <20090323231903.A48F71E4002@bag.python.org> References: <20090323231903.A48F71E4002@bag.python.org> Message-ID: <49C81AFB.1000906@v.loewis.de> > update from CVS > -__version__ = "#Revision: 1.63 $"[11:-2] > +__version__ = "$Id$" Do we need to preserve __version__ at all? (and likewise, __author__ and __email__, as variables?) If so, I think it should continue be Revision, and it should continue to slice the actual number out of the string, for compatibility with existing code. Regards, Martin From brett at python.org Tue Mar 24 00:50:44 2009 From: brett at python.org (Brett Cannon) Date: Mon, 23 Mar 2009 16:50:44 -0700 Subject: [Python-checkins] r70563 - python/trunk/Lib/unittest.py In-Reply-To: <49C81AFB.1000906@v.loewis.de> References: <20090323231903.A48F71E4002@bag.python.org> <49C81AFB.1000906@v.loewis.de> Message-ID: On Mon, Mar 23, 2009 at 16:27, "Martin v. L?wis" wrote: > > update from CVS > > -__version__ = "#Revision: 1.63 $"[11:-2] > > +__version__ = "$Id$" > > Do we need to preserve __version__ at all? (and likewise, > __author__ and __email__, as variables?) > > If so, I think it should continue be Revision, and it > should continue to slice the actual number out of the > string, for compatibility with existing code. I say get rid of that metadata. It really serves no great purpose since unittest is not distributed separately anymore. -Brett -------------- next part -------------- An HTML attachment was scrubbed... URL: From buildbot at python.org Tue Mar 24 01:06:04 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 00:06:04 +0000 Subject: [Python-checkins] buildbot failure in x86 FreeBSD trunk Message-ID: <20090324000604.DB46F1E4002@bag.python.org> The Buildbot has detected a new failure of x86 FreeBSD trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20FreeBSD%20trunk/builds/1990 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: bolen-freebsd Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: antoine.pitrou,benjamin.peterson,mark.dickinson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 24 01:17:11 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 24 Mar 2009 01:17:11 +0100 (CET) Subject: [Python-checkins] r70564 - python/trunk/Doc/library/unittest.rst Message-ID: <20090324001711.9B27B1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 24 01:17:11 2009 New Revision: 70564 Log: Add links to related resources. Modified: python/trunk/Doc/library/unittest.rst Modified: python/trunk/Doc/library/unittest.rst ============================================================================== --- python/trunk/Doc/library/unittest.rst (original) +++ python/trunk/Doc/library/unittest.rst Tue Mar 24 01:17:11 2009 @@ -85,6 +85,12 @@ Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. + `Nose `_ and `py.test `_ + Third-party unittest frameworks with a lighter-weight syntax + for writing tests. For example, ``assert func(10) == 42``. + + `python-mock `_ and `minimock `_ + Tools for creating mock test objects (objects simulating external resources). .. _unittest-minimal-example: From python-checkins at python.org Tue Mar 24 01:21:36 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 24 Mar 2009 01:21:36 +0100 (CET) Subject: [Python-checkins] r70565 - python/branches/release26-maint/Doc/library/unittest.rst Message-ID: <20090324002136.2DC721E403C@bag.python.org> Author: raymond.hettinger Date: Tue Mar 24 01:21:36 2009 New Revision: 70565 Log: Add links to related resources. Modified: python/branches/release26-maint/Doc/library/unittest.rst Modified: python/branches/release26-maint/Doc/library/unittest.rst ============================================================================== --- python/branches/release26-maint/Doc/library/unittest.rst (original) +++ python/branches/release26-maint/Doc/library/unittest.rst Tue Mar 24 01:21:36 2009 @@ -80,6 +80,12 @@ Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. + `Nose `_ and `py.test `_ + Third-party unittest frameworks with a lighter-weight syntax + for writing tests. For example, ``assert func(10) == 42``. + + `python-mock `_ and `minimock `_ + Tools for creating mock test objects (objects simulating external resources). .. _unittest-minimal-example: From python-checkins at python.org Tue Mar 24 01:22:53 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 24 Mar 2009 01:22:53 +0100 (CET) Subject: [Python-checkins] r70566 - python/branches/py3k/Doc/library/unittest.rst Message-ID: <20090324002253.4746C1E4002@bag.python.org> Author: raymond.hettinger Date: Tue Mar 24 01:22:53 2009 New Revision: 70566 Log: Add links to related resources. Modified: python/branches/py3k/Doc/library/unittest.rst Modified: python/branches/py3k/Doc/library/unittest.rst ============================================================================== --- python/branches/py3k/Doc/library/unittest.rst (original) +++ python/branches/py3k/Doc/library/unittest.rst Tue Mar 24 01:22:53 2009 @@ -83,6 +83,12 @@ Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. + `Nose `_ and `py.test `_ + Third-party unittest frameworks with a lighter-weight syntax + for writing tests. For example, ``assert func(10) == 42``. + + `python-mock `_ and `minimock `_ + Tools for creating mock test objects (objects simulating external resources). .. _unittest-minimal-example: From python-checkins at python.org Tue Mar 24 01:23:08 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 24 Mar 2009 01:23:08 +0100 (CET) Subject: [Python-checkins] r70567 - python/branches/release30-maint/Doc/library/unittest.rst Message-ID: <20090324002308.66DB61E400C@bag.python.org> Author: raymond.hettinger Date: Tue Mar 24 01:23:08 2009 New Revision: 70567 Log: Add links to related resources. Modified: python/branches/release30-maint/Doc/library/unittest.rst Modified: python/branches/release30-maint/Doc/library/unittest.rst ============================================================================== --- python/branches/release30-maint/Doc/library/unittest.rst (original) +++ python/branches/release30-maint/Doc/library/unittest.rst Tue Mar 24 01:23:08 2009 @@ -78,6 +78,12 @@ Kent Beck's original paper on testing frameworks using the pattern shared by :mod:`unittest`. + `Nose `_ and `py.test `_ + Third-party unittest frameworks with a lighter-weight syntax + for writing tests. For example, ``assert func(10) == 42``. + + `python-mock `_ and `minimock `_ + Tools for creating mock test objects (objects simulating external resources). .. _unittest-minimal-example: From python-checkins at python.org Tue Mar 24 01:35:20 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 01:35:20 +0100 (CET) Subject: [Python-checkins] r70568 - python/trunk/Lib/unittest.py Message-ID: <20090324003520.D87091E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 01:35:20 2009 New Revision: 70568 Log: some cleanup and modernization Modified: python/trunk/Lib/unittest.py Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Tue Mar 24 01:35:20 2009 @@ -251,12 +251,16 @@ (_strclass(self.__class__), self.testsRun, len(self.errors), len(self.failures)) + class AssertRaisesContext(object): + def __init__(self, expected, test_case): self.expected = expected self.failureException = test_case.failureException + def __enter__(self): pass + def __exit__(self, exc_type, exc_value, traceback): if exc_type is None: try: @@ -270,6 +274,7 @@ # Let unexpected exceptions skip through return False + class TestCase(object): """A class whose instances are single test cases. @@ -303,13 +308,13 @@ method when executed. Raises a ValueError if the instance does not have a method with the specified name. """ + self._testMethodName = methodName try: - self._testMethodName = methodName testMethod = getattr(self, methodName) - self._testMethodDoc = testMethod.__doc__ except AttributeError: raise ValueError("no such test method in %s: %s" % \ (self.__class__, methodName)) + self._testMethodDoc = testMethod.__doc__ def setUp(self): "Hook method for setting up the test fixture before exercising it." @@ -340,7 +345,7 @@ def __eq__(self, other): if type(self) is not type(other): - return False + return NotImplemented return self._testMethodName == other._testMethodName @@ -358,7 +363,8 @@ (_strclass(self.__class__), self._testMethodName) def run(self, result=None): - if result is None: result = self.defaultTestResult() + if result is None: + result = self.defaultTestResult() result.startTest(self) testMethod = getattr(self, self._testMethodName) try: @@ -423,11 +429,13 @@ def failIf(self, expr, msg=None): "Fail the test if the expression is true." - if expr: raise self.failureException(msg) + if expr: + raise self.failureException(msg) def failUnless(self, expr, msg=None): """Fail the test unless the expression is true.""" - if not expr: raise self.failureException(msg) + if not expr: + raise self.failureException(msg) def failUnlessRaises(self, excClass, callableObj=None, *args, **kwargs): """Fail unless an exception of class excClass is thrown @@ -521,8 +529,6 @@ def __repr__(self): return "<%s tests=%s>" % (_strclass(self.__class__), self._tests) - __str__ = __repr__ - def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented @@ -547,8 +553,7 @@ # sanity checks if not hasattr(test, '__call__'): raise TypeError("the test to add must be callable") - if (isinstance(test, (type, types.ClassType)) and - issubclass(test, (TestCase, TestSuite))): + if isinstance(test, type) and issubclass(test, (TestCase, TestSuite)): raise TypeError("TestCases and TestSuites must be instantiated " "before passing them to addTest()") self._tests.append(test) @@ -571,7 +576,8 @@ def debug(self): """Run the tests without collecting errors in a TestResult""" - for test in self._tests: test.debug() + for test in self._tests: + test.debug() class ClassTestSuite(TestSuite): @@ -614,9 +620,8 @@ always be called if the set-up ('setUp') function ran successfully. """ - def __init__(self, testFunc, setUp=None, tearDown=None, - description=None): - TestCase.__init__(self) + def __init__(self, testFunc, setUp=None, tearDown=None, description=None): + super(FunctionTestCase, self).__init__() self.__setUpFunc = setUp self.__tearDownFunc = tearDown self.__testFunc = testFunc @@ -637,8 +642,8 @@ return self.__testFunc.__name__ def __eq__(self, other): - if type(self) is not type(other): - return False + if not isinstance(other, self.__class__): + return NotImplemented return self.__setUpFunc == other.__setUpFunc and \ self.__tearDownFunc == other.__tearDownFunc and \ @@ -670,8 +675,9 @@ ############################################################################## class TestLoader(object): - """This class is responsible for loading tests according to various - criteria and returning them wrapped in a TestSuite + """ + This class is responsible for loading tests according to various criteria + and returning them wrapped in a TestSuite """ testMethodPrefix = 'test' sortTestMethodsUsing = cmp @@ -681,7 +687,8 @@ def loadTestsFromTestCase(self, testCaseClass): """Return a suite of all tests cases contained in testCaseClass""" if issubclass(testCaseClass, TestSuite): - raise TypeError("Test cases should not be derived from TestSuite. Maybe you meant to derive from TestCase?") + raise TypeError("Test cases should not be derived from TestSuite." \ + " Maybe you meant to derive from TestCase?") testCaseNames = self.getTestCaseNames(testCaseClass) if not testCaseNames and hasattr(testCaseClass, 'runTest'): testCaseNames = ['runTest'] @@ -694,8 +701,7 @@ tests = [] for name in dir(module): obj = getattr(module, name) - if (isinstance(obj, (type, types.ClassType)) and - issubclass(obj, TestCase)): + if isinstance(obj, type) and issubclass(obj, TestCase): tests.append(self.loadTestsFromTestCase(obj)) return self.suiteClass(tests) @@ -717,7 +723,8 @@ break except ImportError: del parts_copy[-1] - if not parts_copy: raise + if not parts_copy: + raise parts = parts[1:] obj = module for part in parts: @@ -725,11 +732,10 @@ if isinstance(obj, types.ModuleType): return self.loadTestsFromModule(obj) - elif (isinstance(obj, (type, types.ClassType)) and - issubclass(obj, TestCase)): + elif isinstance(obj, type) and issubclass(obj, TestCase): return self.loadTestsFromTestCase(obj) elif (isinstance(obj, types.UnboundMethodType) and - isinstance(parent, (type, types.ClassType)) and + isinstance(parent, type) and issubclass(parent, TestCase)): return TestSuite([parent(obj.__name__)]) elif isinstance(obj, TestSuite): @@ -756,8 +762,10 @@ def getTestCaseNames(self, testCaseClass): """Return a sorted sequence of method names found within testCaseClass """ - def isTestMethod(attrname, testCaseClass=testCaseClass, prefix=self.testMethodPrefix): - return attrname.startswith(prefix) and hasattr(getattr(testCaseClass, attrname), '__call__') + def isTestMethod(attrname, testCaseClass=testCaseClass, + prefix=self.testMethodPrefix): + return attrname.startswith(prefix) and \ + hasattr(getattr(testCaseClass, attrname), '__call__') testFnNames = filter(isTestMethod, dir(testCaseClass)) if self.sortTestMethodsUsing: testFnNames.sort(key=_CmpToKey(self.sortTestMethodsUsing)) @@ -815,7 +823,7 @@ separator2 = '-' * 70 def __init__(self, stream, descriptions, verbosity): - TestResult.__init__(self) + super(_TextTestResult, self).__init__() self.stream = stream self.showAll = verbosity > 1 self.dots = verbosity == 1 @@ -828,14 +836,14 @@ return str(test) def startTest(self, test): - TestResult.startTest(self, test) + super(_TextTestResult, self).startTest(test) if self.showAll: self.stream.write(self.getDescription(test)) self.stream.write(" ... ") self.stream.flush() def addSuccess(self, test): - TestResult.addSuccess(self, test) + super(_TextTestResult, self).addSuccess(test) if self.showAll: self.stream.writeln("ok") elif self.dots: @@ -843,7 +851,7 @@ self.stream.flush() def addError(self, test, err): - TestResult.addError(self, test, err) + super(_TextTestResult, self).addError(test, err) if self.showAll: self.stream.writeln("ERROR") elif self.dots: @@ -851,7 +859,7 @@ self.stream.flush() def addFailure(self, test, err): - TestResult.addFailure(self, test, err) + super(_TextTestResult, self).addFailure(test, err) if self.showAll: self.stream.writeln("FAIL") elif self.dots: @@ -859,7 +867,7 @@ self.stream.flush() def addSkip(self, test, reason): - TestResult.addSkip(self, test, reason) + super(_TextTestResult, self).addSkip(test, reason) if self.showAll: self.stream.writeln("skipped {0!r}".format(reason)) elif self.dots: @@ -867,7 +875,7 @@ self.stream.flush() def addExpectedFailure(self, test, err): - TestResult.addExpectedFailure(self, test, err) + super(_TextTestResult, self).addExpectedFailure(test, err) if self.showAll: self.stream.writeln("expected failure") elif self.dots: @@ -875,7 +883,7 @@ self.stream.flush() def addUnexpectedSuccess(self, test): - TestResult.addUnexpectedSuccess(self, test) + super(_TextTestResult, self).addUnexpectedSuccess(test) if self.showAll: self.stream.writeln("unexpected success") elif self.dots: @@ -936,13 +944,13 @@ if errored: infos.append("errors=%d" % errored) else: - self.stream.write("OK") + self.stream.writeln("OK") if skipped: infos.append("skipped=%d" % skipped) - if expected_fails: - infos.append("expected failures=%d" % expected_fails) - if unexpected_successes: - infos.append("unexpected successes=%d" % unexpected_successes) + if expectedFails: + infos.append("expected failures=%d" % expectedFails) + if unexpectedSuccesses: + infos.append("unexpected successes=%d" % unexpectedSuccesses) if infos: self.stream.writeln(" (%s)" % (", ".join(infos),)) return result @@ -992,7 +1000,8 @@ self.runTests() def usageExit(self, msg=None): - if msg: print msg + if msg: + print msg print self.USAGE % self.__dict__ sys.exit(2) From python-checkins at python.org Tue Mar 24 01:36:16 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 01:36:16 +0100 (CET) Subject: [Python-checkins] r70569 - python/trunk/Lib/unittest.py Message-ID: <20090324003616.E1E621E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 01:36:16 2009 New Revision: 70569 Log: remove special metadata Modified: python/trunk/Lib/unittest.py (contents, props changed) Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Tue Mar 24 01:36:16 2009 @@ -44,10 +44,6 @@ SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ''' -__author__ = "Steve Purcell" -__email__ = "stephen_purcell at yahoo dot com" -__version__ = "$Id$" - import time import sys import traceback From python-checkins at python.org Tue Mar 24 01:37:12 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 01:37:12 +0100 (CET) Subject: [Python-checkins] r70570 - python/trunk/Lib/unittest.py Message-ID: <20090324003712.88B5D1E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 01:37:12 2009 New Revision: 70570 Log: update docstring Modified: python/trunk/Lib/unittest.py Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Tue Mar 24 01:37:12 2009 @@ -25,9 +25,10 @@ Further information is available in the bundled documentation, and from - http://docs.python.org/lib/module-unittest.html + http://docs.python.org/library/unittest.html Copyright (c) 1999-2003 Steve Purcell +Copyright (c) 2003-2009 Python Software Foundation This module is free software, and you may redistribute it and/or modify it under the same terms as Python itself, so long as this copyright message and disclaimer are retained in their original form. From python-checkins at python.org Tue Mar 24 01:39:24 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 01:39:24 +0100 (CET) Subject: [Python-checkins] r70571 - python/trunk/Lib/unittest.py Message-ID: <20090324003924.B44DB1E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 01:39:24 2009 New Revision: 70571 Log: add new skipping things to __all__ Modified: python/trunk/Lib/unittest.py Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Tue Mar 24 01:39:24 2009 @@ -55,8 +55,10 @@ ############################################################################## # Exported classes and functions ############################################################################## -__all__ = ['TestResult', 'TestCase', 'TestSuite', 'TextTestRunner', - 'TestLoader', 'FunctionTestCase', 'main', 'defaultTestLoader'] +__all__ = ['TestResult', 'TestCase', 'TestSuite', 'ClassTestSuite', + 'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main', + 'defaultTestLoader', 'SkipException', 'skip', 'skipIf', 'skipUnless', + 'expectedFailure'] # Expose obsolete functions for backwards compatibility __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases']) From python-checkins at python.org Tue Mar 24 01:56:33 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 01:56:33 +0100 (CET) Subject: [Python-checkins] r70572 - in python/branches/py3k: Doc/library/unittest.rst Lib/test/test_unittest.py Lib/unittest.py Message-ID: <20090324005633.05B4A1E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 01:56:30 2009 New Revision: 70572 Log: Merged revisions 70558,70561-70563,70568-70571 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70558 | benjamin.peterson | 2009-03-23 17:29:45 -0500 (Mon, 23 Mar 2009) | 4 lines comply with the evilJavaNamingScheme for attribute names It seems my love of PEP 8 overrode the need for consistentcy ........ r70561 | benjamin.peterson | 2009-03-23 18:10:14 -0500 (Mon, 23 Mar 2009) | 1 line refactor unittest docs ........ r70562 | benjamin.peterson | 2009-03-23 18:13:36 -0500 (Mon, 23 Mar 2009) | 1 line forgot to document that setUp can be skipped (silly me...) ........ r70563 | benjamin.peterson | 2009-03-23 18:19:03 -0500 (Mon, 23 Mar 2009) | 1 line update from CVS ........ r70568 | benjamin.peterson | 2009-03-23 19:35:20 -0500 (Mon, 23 Mar 2009) | 1 line some cleanup and modernization ........ r70569 | benjamin.peterson | 2009-03-23 19:36:16 -0500 (Mon, 23 Mar 2009) | 1 line remove special metadata ........ r70570 | benjamin.peterson | 2009-03-23 19:37:12 -0500 (Mon, 23 Mar 2009) | 1 line update docstring ........ r70571 | benjamin.peterson | 2009-03-23 19:39:24 -0500 (Mon, 23 Mar 2009) | 1 line add new skipping things to __all__ ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/unittest.rst python/branches/py3k/Lib/test/test_unittest.py python/branches/py3k/Lib/unittest.py (contents, props changed) Modified: python/branches/py3k/Doc/library/unittest.rst ============================================================================== --- python/branches/py3k/Doc/library/unittest.rst (original) +++ python/branches/py3k/Doc/library/unittest.rst Tue Mar 24 01:56:30 2009 @@ -11,8 +11,7 @@ .. versionchanged:: 3.1 - - Added :ref:`skipping and expected failures `. + Added test :ref:`skipping and expected failures `. The Python unit testing framework, sometimes referred to as "PyUnit," is a Python language version of JUnit, by Kent Beck and Erich Gamma. JUnit is, in @@ -51,27 +50,28 @@ :class:`TestCase` and :class:`FunctionTestCase` classes; the former should be used when creating new tests, and the latter can be used when integrating existing test code with a :mod:`unittest`\ -driven framework. When building test -fixtures using :class:`TestCase`, the :meth:`setUp` and :meth:`tearDown` methods -can be overridden to provide initialization and cleanup for the fixture. With -:class:`FunctionTestCase`, existing functions can be passed to the constructor -for these purposes. When the test is run, the fixture initialization is run -first; if it succeeds, the cleanup method is run after the test has been -executed, regardless of the outcome of the test. Each instance of the -:class:`TestCase` will only be used to run a single test method, so a new -fixture is created for each test. +fixtures using :class:`TestCase`, the :meth:`~TestCase.setUp` and +:meth:`~TestCase.tearDown` methods can be overridden to provide initialization +and cleanup for the fixture. With :class:`FunctionTestCase`, existing functions +can be passed to the constructor for these purposes. When the test is run, the +fixture initialization is run first; if it succeeds, the cleanup method is run +after the test has been executed, regardless of the outcome of the test. Each +instance of the :class:`TestCase` will only be used to run a single test method, +so a new fixture is created for each test. Test suites are implemented by the :class:`TestSuite` class. This class allows individual tests and test suites to be aggregated; when the suite is executed, all tests added directly to the suite and in "child" test suites are run. A :class:`ClassTestSuite` contains the test cases of a class. -A test runner is an object that provides a single method, :meth:`run`, which -accepts a :class:`TestCase` or :class:`TestSuite` object as a parameter, and -returns a result object. The class :class:`TestResult` is provided for use as -the result object. :mod:`unittest` provides the :class:`TextTestRunner` as an -example test runner which reports test results on the standard error stream by -default. Alternate runners can be implemented for other environments (such as -graphical environments) without any need to derive from a specific class. +A test runner is an object that provides a single method, +:meth:`~TestRunner.run`, which accepts a :class:`TestCase` or :class:`TestSuite` +object as a parameter, and returns a result object. The class +:class:`TestResult` is provided for use as the result object. :mod:`unittest` +provides the :class:`TextTestRunner` as an example test runner which reports +test results on the standard error stream by default. Alternate runners can be +implemented for other environments (such as graphical environments) without any +need to derive from a specific class. .. seealso:: @@ -109,17 +109,17 @@ def setUp(self): self.seq = range(10) - def testshuffle(self): + def test_shuffle(self): # make sure the shuffled sequence does not lose any elements random.shuffle(self.seq) self.seq.sort() self.assertEqual(self.seq, range(10)) - def testchoice(self): + def test_choice(self): element = random.choice(self.seq) self.assert_(element in self.seq) - def testsample(self): + def test_sample(self): self.assertRaises(ValueError, random.sample, self.seq, 20) for element in random.sample(self.seq, 5): self.assert_(element in self.seq) @@ -127,21 +127,22 @@ if __name__ == '__main__': unittest.main() -A testcase is created by subclassing :class:`unittest.TestCase`. The three +A testcase is created by subclassing :class:`unittest.TestCase`. The three individual tests are defined with methods whose names start with the letters ``test``. This naming convention informs the test runner about which methods represent tests. -The crux of each test is a call to :meth:`assertEqual` to check for an expected -result; :meth:`assert_` to verify a condition; or :meth:`assertRaises` to verify -that an expected exception gets raised. These methods are used instead of the -:keyword:`assert` statement so the test runner can accumulate all test results -and produce a report. - -When a :meth:`setUp` method is defined, the test runner will run that method -prior to each test. Likewise, if a :meth:`tearDown` method is defined, the test -runner will invoke that method after each test. In the example, :meth:`setUp` -was used to create a fresh sequence for each test. +The crux of each test is a call to :meth:`~TestCase.assertEqual` to check for an +expected result; :meth:`~TestCase.assert_` to verify a condition; or +:meth:`~TestCase.assertRaises` to verify that an expected exception gets raised. +These methods are used instead of the :keyword:`assert` statement so the test +runner can accumulate all test results and produce a report. + +When a :meth:`~TestCase.setUp` method is defined, the test runner will run that +method prior to each test. Likewise, if a :meth:`~TestCase.tearDown` method is +defined, the test runner will invoke that method after each test. In the +example, :meth:`~TestCase.setUp` was used to create a fresh sequence for each +test. The final block shows a simple way to run the tests. :func:`unittest.main` provides a command line interface to the test script. When run from the command @@ -196,8 +197,8 @@ contained, such that it can be run either in isolation or in arbitrary combination with any number of other test cases. -The simplest :class:`TestCase` subclass will simply override the :meth:`runTest` -method in order to perform specific testing code:: +The simplest :class:`TestCase` subclass will simply override the +:meth:`~TestCase.runTest` method in order to perform specific testing code:: import unittest @@ -226,8 +227,8 @@ subclasses would mean unsightly duplication. Luckily, we can factor out such set-up code by implementing a method called -:meth:`setUp`, which the testing framework will automatically call for us when -we run the test:: +:meth:`~TestCase.setUp`, which the testing framework will automatically call for +us when we run the test:: import unittest @@ -246,12 +247,12 @@ self.failUnless(self.widget.size() == (100,150), 'wrong size after resize') -If the :meth:`setUp` method raises an exception while the test is running, the -framework will consider the test to have suffered an error, and the -:meth:`runTest` method will not be executed. +If the :meth:`~TestCase.setUp` method raises an exception while the test is +running, the framework will consider the test to have suffered an error, and the +:meth:`~TestCase.runTest` method will not be executed. -Similarly, we can provide a :meth:`tearDown` method that tidies up after the -:meth:`runTest` method has been run:: +Similarly, we can provide a :meth:`~TestCase.tearDown` method that tidies up +after the :meth:`~TestCase.runTest` method has been run:: import unittest @@ -263,8 +264,8 @@ self.widget.dispose() self.widget = None -If :meth:`setUp` succeeded, the :meth:`tearDown` method will be run whether -:meth:`runTest` succeeded or not. +If :meth:`~TestCase.setUp` succeeded, the :meth:`~TestCase.tearDown` method will +be run whether :meth:`~TestCase.runTest` succeeded or not. Such a working environment for the testing code is called a :dfn:`fixture`. @@ -293,11 +294,12 @@ self.failUnless(self.widget.size() == (100,150), 'wrong size after resize') -Here we have not provided a :meth:`runTest` method, but have instead provided -two different test methods. Class instances will now each run one of the -:meth:`test\*` methods, with ``self.widget`` created and destroyed separately -for each instance. When creating an instance we must specify the test method it -is to run. We do this by passing the method name in the constructor:: +Here we have not provided a :meth:`~TestCase.runTest` method, but have instead +provided two different test methods. Class instances will now each run one of +the :meth:`test\*` methods, with ``self.widget`` created and destroyed +separately for each instance. When creating an instance we must specify the +test method it is to run. We do this by passing the method name in the +constructor:: defaultSizeTestCase = WidgetTestCase('testDefaultSize') resizeTestCase = WidgetTestCase('testResize') @@ -417,6 +419,11 @@ recommended. Taking the time to set up proper :class:`TestCase` subclasses will make future test refactorings infinitely easier. +In some cases, the existing tests may have been written using the :mod:`doctest` +module. If so, :mod:`doctest` provides a :class:`DocTestSuite` class that can +automatically build :class:`unittest.TestSuite` instances from the existing +:mod:`doctest`\ -based tests. + .. _unittest-skipping: @@ -453,6 +460,9 @@ def test_not_run(self): pass +:meth:`TestCase.setUp` can also skip the test. This is useful when a resource +that needs to be set up is not available. + Expected failures use the :func:`expectedFailure` decorator. :: class ExpectedFailureTestCase(unittest.TestCase): @@ -495,6 +505,13 @@ Classes and functions --------------------- +This section describes in depth the API of :mod:`unittest`. + + +.. _testcase-objects: + +Test cases +~~~~~~~~~~ .. class:: TestCase([methodName]) @@ -518,554 +535,567 @@ Here, we create two instances of :class:`WidgetTestCase`, each of which runs a single test. - *methodName* defaults to ``'runTest'``. + *methodName* defaults to :meth:`runTest`. + :class:`TestCase` instances provide three groups of methods: one group used + to run the test, another used by the test implementation to check conditions + and report failures, and some inquiry methods allowing information about the + test itself to be gathered. -.. class:: FunctionTestCase(testFunc[, setUp[, tearDown[, description]]]) + Methods in the first group (running the test) are: - This class implements the portion of the :class:`TestCase` interface which - allows the test runner to drive the test, but does not provide the methods which - test code can use to check and report errors. This is used to create test cases - using legacy test code, allowing it to be integrated into a :mod:`unittest`\ - -based test framework. + .. method:: setUp() -.. class:: TestSuite([tests]) + Method called to prepare the test fixture. This is called immediately + before calling the test method; any exception raised by this method will + be considered an error rather than a test failure. The default + implementation does nothing. - This class represents an aggregation of individual tests cases and test suites. - The class presents the interface needed by the test runner to allow it to be run - as any other test case. Running a :class:`TestSuite` instance is the same as - iterating over the suite, running each test individually. - 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. Additional methods - are provided to add test cases and suites to the collection later on. + .. method:: tearDown() -.. class:: ClassTestSuite(tests, collected_from) + Method called immediately after the test method has been called and the + result recorded. This is called even if the test method raised an + exception, so the implementation in subclasses may need to be particularly + careful about checking internal state. Any exception raised by this + method will be considered an error rather than a test failure. This + method will only be called if the :meth:`setUp` succeeds, regardless of + the outcome of the test method. The default implementation does nothing. - This subclass of :class:`TestSuite` repesents an aggregation of individuals - tests from one :class:`TestCase` class. *tests* is an iterable of - :class:`TestCase` instances created from the class. *collected_from* is the - class they came from. + .. method:: run([result]) -.. class:: TestLoader() + Run the test, collecting the result into the test result object passed as + *result*. If *result* is omitted or :const:`None`, a temporary result + object is created (by calling the :meth:`defaultTestCase` method) and + used; this result object is not returned to :meth:`run`'s caller. - This class is responsible for loading tests according to various criteria and - returning them wrapped in a :class:`TestSuite`. It can load all tests within a - given module or :class:`TestCase` subclass. + The same effect may be had by simply calling the :class:`TestCase` + instance. -.. class:: TestResult() + .. method:: skip(reason) - This class is used to compile information about which tests have succeeded and - which have failed. + Calling this during the a test method or :meth:`setUp` skips the current + test. See :ref:`unittest-skipping` for more information. -.. data:: defaultTestLoader + .. method:: debug() - Instance of the :class:`TestLoader` class intended to be shared. If no - customization of the :class:`TestLoader` is needed, this instance can be used - instead of repeatedly creating new instances. + Run the test without collecting the result. This allows exceptions raised + by the test to be propagated to the caller, and can be used to support + running tests under a debugger. + The test code can use any of the following methods to check for and report + failures. -.. class:: TextTestRunner([stream[, descriptions[, verbosity]]]) - A basic test runner implementation which prints results on standard error. It - has a few configurable parameters, but is essentially very simple. Graphical - applications which run test suites should provide alternate implementations. + .. method:: assert_(expr[, msg]) + failUnless(expr[, msg]) + assertTrue(expr[, msg]) + Signal a test failure if *expr* is false; the explanation for the error + will be *msg* if given, otherwise it will be :const:`None`. -.. function:: main([module[, defaultTest[, argv[, testRunner[, 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 test script:: + .. method:: assertEqual(first, second[, msg]) + failUnlessEqual(first, second[, msg]) - if __name__ == '__main__': - unittest.main() + Test that *first* and *second* are equal. If the values do not compare + equal, the test will fail with the explanation given by *msg*, or + :const:`None`. Note that using :meth:`failUnlessEqual` improves upon + doing the comparison as the first parameter to :meth:`failUnless`: the + default value for *msg* can be computed to include representations of both + *first* and *second*. - The *testRunner* argument can either be a test runner class or an already - created instance of it. -In some cases, the existing tests may have been written using the :mod:`doctest` -module. If so, that module provides a :class:`DocTestSuite` class that can -automatically build :class:`unittest.TestSuite` instances from the existing -:mod:`doctest`\ -based tests. + .. method:: assertNotEqual(first, second[, msg]) + failIfEqual(first, second[, msg]) + Test that *first* and *second* are not equal. If the values do compare + equal, the test will fail with the explanation given by *msg*, or + :const:`None`. Note that using :meth:`failIfEqual` improves upon doing + the comparison as the first parameter to :meth:`failUnless` is that the + default value for *msg* can be computed to include representations of both + *first* and *second*. -.. _testcase-objects: + .. method:: assertAlmostEqual(first, second[, places[, msg]]) + failUnlessAlmostEqual(first, second[, places[, msg]]) -TestCase Objects ----------------- + Test that *first* and *second* are approximately equal by computing the + difference, rounding to the given number of decimal *places* (default 7), + and comparing to zero. -Each :class:`TestCase` instance represents a single test, but each concrete -subclass may be used to define multiple tests --- the concrete class represents -a single test fixture. The fixture is created and cleaned up for each test -case. + Note that comparing a given number of decimal places is not the same as + comparing a given number of significant digits. If the values do not + compare equal, the test will fail with the explanation given by *msg*, or + :const:`None`. -:class:`TestCase` instances provide three groups of methods: one group used to -run the test, another used by the test implementation to check conditions and -report failures, and some inquiry methods allowing information about the test -itself to be gathered. -Methods in the first group (running the test) are: + .. method:: assertNotAlmostEqual(first, second[, places[, msg]]) + failIfAlmostEqual(first, second[, places[, msg]]) + Test that *first* and *second* are not approximately equal by computing + the difference, rounding to the given number of decimal *places* (default + 7), and comparing to zero. -.. method:: TestCase.setUp() + Note that comparing a given number of decimal places is not the same as + comparing a given number of significant digits. If the values do not + compare equal, the test will fail with the explanation given by *msg*, or + :const:`None`. - Method called to prepare the test fixture. This is called immediately before - calling the test method; any exception raised by this method will be considered - an error rather than a test failure. The default implementation does nothing. + .. method:: assertRaises(exception[, callable, ...]) + failUnlessRaises(exception[, callable, ...]) -.. method:: TestCase.tearDown() + Test that an exception is raised when *callable* is called with any + positional or keyword arguments that are also passed to + :meth:`assertRaises`. The test passes if *exception* is raised, is an + error if another exception is raised, or fails if no exception is raised. + To catch any of a group of exceptions, a tuple containing the exception + classes may be passed as *exception*. - Method called immediately after the test method has been called and the result - recorded. This is called even if the test method raised an exception, so the - implementation in subclasses may need to be particularly careful about checking - internal state. Any exception raised by this method will be considered an error - rather than a test failure. This method will only be called if the - :meth:`setUp` succeeds, regardless of the outcome of the test method. The - default implementation does nothing. + .. versionchanged:: 2.7 + If *callable* is omitted or None, returns a context manager so that the + code under test can be written inline rather than as a function:: -.. method:: TestCase.run([result]) + with self.failUnlessRaises(some_error_class): + do_something() - Run the test, collecting the result into the test result object passed as - *result*. If *result* is omitted or :const:`None`, a temporary result object is - created (by calling the :meth:`defaultTestCase` method) and used; this result - object is not returned to :meth:`run`'s caller. + .. method:: failIf(expr[, msg]) + assertFalse(expr[, msg]) - The same effect may be had by simply calling the :class:`TestCase` instance. + The inverse of the :meth:`failUnless` method is the :meth:`failIf` method. + This signals a test failure if *expr* is true, with *msg* or :const:`None` + for the error message. -.. method:: TestCase.skip(reason) + .. method:: fail([msg]) - Skips the current test. See :ref:`unittest-skipping`. + Signals a test failure unconditionally, with *msg* or :const:`None` for + the error message. -.. method:: TestCase.debug() + .. attribute:: failureException - Run the test without collecting the result. This allows exceptions raised by - the test to be propagated to the caller, and can be used to support running - tests under a debugger. + 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 + :exc:`AssertionError`. -The test code can use any of the following methods to check for and report -failures. + Testing frameworks can use the following methods to collect information on + the test: -.. method:: TestCase.assert_(expr[, msg]) - TestCase.failUnless(expr[, msg]) - TestCase.assertTrue(expr[, msg]) + .. method:: countTestCases() - Signal a test failure if *expr* is false; the explanation for the error will be - *msg* if given, otherwise it will be :const:`None`. + Return the number of tests represented by this test object. For + :class:`TestCase` instances, this will always be ``1``. -.. method:: TestCase.assertEqual(first, second[, msg]) - TestCase.failUnlessEqual(first, second[, msg]) + .. method:: defaultTestResult() - Test that *first* and *second* are equal. If the values do not compare equal, - the test will fail with the explanation given by *msg*, or :const:`None`. Note - that using :meth:`failUnlessEqual` improves upon doing the comparison as the - first parameter to :meth:`failUnless`: the default value for *msg* can be - computed to include representations of both *first* and *second*. + Return an instance of the test result class that should be used for this + test case class (if no other result instance is provided to the + :meth:`run` method). + For :class:`TestCase` instances, this will always be an instance of + :class:`TestResult`; subclasses of :class:`TestCase` should override this + as necessary. -.. method:: TestCase.assertNotEqual(first, second[, msg]) - TestCase.failIfEqual(first, second[, msg]) - Test that *first* and *second* are not equal. If the values do compare equal, - the test will fail with the explanation given by *msg*, or :const:`None`. Note - that using :meth:`failIfEqual` improves upon doing the comparison as the first - parameter to :meth:`failUnless` is that the default value for *msg* can be - computed to include representations of both *first* and *second*. + .. method:: id() + Return a string identifying the specific test case. This is usually the + full name of the test method, including the module and class name. -.. method:: TestCase.assertAlmostEqual(first, second[, places[, msg]]) - TestCase.failUnlessAlmostEqual(first, second[, places[, msg]]) - Test that *first* and *second* are approximately equal by computing the - difference, rounding to the given number of decimal *places* (default 7), - and comparing to zero. - Note that comparing a given number of decimal places is not the same as - comparing a given number of significant digits. If the values do not compare - equal, the test will fail with the explanation given by *msg*, or :const:`None`. + .. method:: shortDescription() + Returns a one-line description of the test, or :const:`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 + :const:`None`. -.. method:: TestCase.assertNotAlmostEqual(first, second[, places[, msg]]) - TestCase.failIfAlmostEqual(first, second[, places[, msg]]) - Test that *first* and *second* are not approximately equal by computing the - difference, rounding to the given number of decimal *places* (default 7), - and comparing to zero. - Note that comparing a given number of decimal places is not the same as - comparing a given number of significant digits. If the values do not compare - equal, the test will fail with the explanation given by *msg*, or :const:`None`. +.. class:: FunctionTestCase(testFunc[, setUp[, tearDown[, description]]]) + This class implements the portion of the :class:`TestCase` interface which + allows the test runner to drive the test, but does not provide the methods which + test code can use to check and report errors. This is used to create test cases + using legacy test code, allowing it to be integrated into a :mod:`unittest`\ + -based test framework. -.. method:: TestCase.assertRaises(exception[, callable, ...]) - TestCase.failUnlessRaises(exception[, callable, ...]) - Test that an exception is raised when *callable* is called with any positional - or keyword arguments that are also passed to :meth:`assertRaises`. The test - passes if *exception* is raised, is an error if another exception is raised, or - fails if no exception is raised. To catch any of a group of exceptions, a tuple - containing the exception classes may be passed as *exception*. +.. _testsuite-objects: - If *callable* is omitted or None, returns a context manager so that the code - under test can be written inline rather than as a function:: - with self.failUnlessRaises(some_error_class): - do_something() +Grouping tests +~~~~~~~~~~~~~~ -.. method:: TestCase.failIf(expr[, msg]) - TestCase.assertFalse(expr[, msg]) +.. class:: TestSuite([tests]) - The inverse of the :meth:`failUnless` method is the :meth:`failIf` method. This - signals a test failure if *expr* is true, with *msg* or :const:`None` for the - error message. + This class represents an aggregation of individual tests cases and test suites. + The class presents the interface needed by the test runner to allow it to be run + as any other test case. Running a :class:`TestSuite` instance is the same as + iterating over the suite, running each test individually. + 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. Additional methods + are provided to add test cases and suites to the collection later on. -.. method:: TestCase.fail([msg]) + :class:`TestSuite` (including :class:`ClassTestSuite`) objects behave much + like :class:`TestCase` objects, except they do not actually implement a test. + Instead, they are used to aggregate tests into groups of tests that should be + run together. Some additional methods are available to add tests to + :class:`TestSuite` instances: - Signals a test failure unconditionally, with *msg* or :const:`None` for the - error message. + .. method:: TestSuite.addTest(test) -.. attribute:: TestCase.failureException + Add a :class:`TestCase` or :class:`TestSuite` to the suite. - This class attribute gives the exception raised by the :meth:`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 - :exc:`AssertionError`. -Testing frameworks can use the following methods to collect information on the -test: + .. method:: TestSuite.addTests(tests) + Add all the tests from an iterable of :class:`TestCase` and :class:`TestSuite` + instances to this test suite. -.. method:: TestCase.countTestCases() + This is equivalent to iterating over *tests*, calling :meth:`addTest` for each + element. - Return the number of tests represented by this test object. For - :class:`TestCase` instances, this will always be ``1``. + :class:`TestSuite` shares the following methods with :class:`TestCase`: -.. method:: TestCase.defaultTestResult() + .. method:: run(result) - Return an instance of the test result class that should be used for this test - case class (if no other result instance is provided to the :meth:`run` method). + Run the tests associated with this suite, collecting the result into the + test result object passed as *result*. Note that unlike + :meth:`TestCase.run`, :meth:`TestSuite.run` requires the result object to + be passed in. - For :class:`TestCase` instances, this will always be an instance of - :class:`TestResult`; subclasses of :class:`TestCase` should override this as - necessary. + .. method:: debug() -.. method:: TestCase.id() + Run the tests associated with this suite without collecting the + result. This allows exceptions raised by the test to be propagated to the + caller and can be used to support running tests under a debugger. - Return a string identifying the specific test case. This is usually the full - name of the test method, including the module and class name. + .. method:: countTestCases() -.. method:: TestCase.shortDescription() + Return the number of tests represented by this test object, including all + individual tests and sub-suites. - Returns a one-line description of the test, or :const:`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 :const:`None`. + In the typical usage of a :class:`TestSuite` object, the :meth:`run` method + is invoked by a :class:`TestRunner` rather than by the end-user test harness. -.. _testsuite-objects: +.. class:: ClassTestSuite(tests, collected_from) + + This subclass of :class:`TestSuite` repesents an aggregation of individuals + tests from one :class:`TestCase` class. *tests* is an iterable of + :class:`TestCase` instances created from the class. *collected_from* is the + class they came from. -TestSuite Objects ------------------ -:class:`TestSuite` (including :class:`ClassTestSuite`) objects behave much like -:class:`TestCase` objects, except they do not actually implement a test. -Instead, they are used to aggregate tests into groups of tests that should be -run together. Some additional methods are available to add tests to -:class:`TestSuite` instances: +Loading and running tests +~~~~~~~~~~~~~~~~~~~~~~~~~ +.. class:: TestLoader() -.. method:: TestSuite.addTest(test) + The :class:`TestLoader` class is used to create test suites from classes and + modules. Normally, there is no need to create an instance of this class; the + :mod:`unittest` module provides an instance that can be shared as + ``unittest.defaultTestLoader``. Using a subclass or instance, however, allows + customization of some configurable properties. - Add a :class:`TestCase` or :class:`TestSuite` to the suite. + :class:`TestLoader` objects have the following methods: -.. method:: TestSuite.addTests(tests) + .. method:: loadTestsFromTestCase(testCaseClass) - Add all the tests from an iterable of :class:`TestCase` and :class:`TestSuite` - instances to this test suite. + Return a suite of all tests cases contained in the :class:`TestCase`\ -derived + :class:`testCaseClass`. - This is equivalent to iterating over *tests*, calling :meth:`addTest` for each - element. -:class:`TestSuite` shares the following methods with :class:`TestCase`: + .. method:: loadTestsFromModule(module) + Return a suite of all tests cases contained in the given module. This + method searches *module* for classes derived from :class:`TestCase` and + creates an instance of the class for each test method defined for the + class. -.. method:: TestSuite.run(result) + .. warning:: - Run the tests associated with this suite, collecting the result into the test - result object passed as *result*. Note that unlike :meth:`TestCase.run`, - :meth:`TestSuite.run` requires the result object to be passed in. + While using a hierarchy of :class:`TestCase`\ -derived classes can be + convenient in sharing fixtures and helper functions, defining test + methods on base classes that are not intended to be instantiated + directly does not play well with this method. Doing so, however, can + be useful when the fixtures are different and defined in subclasses. -.. method:: TestSuite.debug() + .. method:: loadTestsFromName(name[, module]) - Run the tests associated with this suite without collecting the result. This - allows exceptions raised by the test to be propagated to the caller and can be - used to support running tests under a debugger. + Return a suite of all tests cases given a string specifier. + The specifier *name* is a "dotted name" that may resolve either to a + module, a test case class, a test method within a test case class, a + :class:`TestSuite` instance, or a callable object which returns a + :class:`TestCase` or :class:`TestSuite` instance. These checks are + applied in the order listed here; that is, a method on a possible test + case class will be picked up as "a test method within a test case class", + rather than "a callable object". -.. method:: TestSuite.countTestCases() + For example, if you have a module :mod:`SampleTests` containing a + :class:`TestCase`\ -derived class :class:`SampleTestCase` with three test + methods (:meth:`test_one`, :meth:`test_two`, and :meth:`test_three`), the + specifier ``'SampleTests.SampleTestCase'`` would cause this method to return a + suite which will run all three test methods. Using the specifier + ``'SampleTests.SampleTestCase.test_two'`` would cause it to return a test suite + which will run only the :meth:`test_two` test method. The specifier can refer + to modules and packages which have not been imported; they will be imported as a + side-effect. - Return the number of tests represented by this test object, including all - individual tests and sub-suites. + The method optionally resolves *name* relative to the given *module*. -In the typical usage of a :class:`TestSuite` object, the :meth:`run` method is -invoked by a :class:`TestRunner` rather than by the end-user test harness. + .. method:: loadTestsFromNames(names[, module]) -.. _testresult-objects: + Similar to :meth:`loadTestsFromName`, but takes a sequence of names rather + than a single name. The return value is a test suite which supports all + the tests defined for each name. -TestResult Objects ------------------- -A :class:`TestResult` object stores the results of a set of tests. The -:class:`TestCase` and :class:`TestSuite` classes ensure that results are -properly recorded; test authors do not need to worry about recording the outcome -of tests. + .. method:: getTestCaseNames(testCaseClass) -Testing frameworks built on top of :mod:`unittest` may want access to the -:class:`TestResult` object generated by running a set of tests for reporting -purposes; a :class:`TestResult` instance is returned by the -:meth:`TestRunner.run` method for this purpose. + Return a sorted sequence of method names found within *testCaseClass*; + this should be a subclass of :class:`TestCase`. -:class:`TestResult` instances have the following attributes that will be of -interest when inspecting the results of running a set of tests: + The following attributes of a :class:`TestLoader` can be configured either by + subclassing or assignment on an instance: -.. attribute:: TestResult.errors + .. attribute:: testMethodPrefix - A list containing 2-tuples of :class:`TestCase` instances and strings holding - formatted tracebacks. Each tuple represents a test which raised an unexpected - exception. + String giving the prefix of method names which will be interpreted as test + methods. The default value is ``'test'``. + This affects :meth:`getTestCaseNames` and all the :meth:`loadTestsFrom\*` + methods. -.. attribute:: TestResult.failures - A list containing 2-tuples of :class:`TestCase` instances and strings holding - formatted tracebacks. Each tuple represents a test where a failure was - explicitly signalled using the :meth:`TestCase.fail\*` or - :meth:`TestCase.assert\*` methods. + .. attribute:: sortTestMethodsUsing + Function to be used to compare method names when sorting them in + :meth:`getTestCaseNames` and all the :meth:`loadTestsFrom\*` methods. -.. attribute:: TestResult.testsRun - The total number of tests run so far. + .. attribute:: suiteClass + Callable object that constructs a test suite from a list of tests. No + methods on the resulting object are needed. The default value is the + :class:`TestSuite` class. -.. method:: TestResult.wasSuccessful() + This affects all the :meth:`loadTestsFrom\*` methods. - Returns :const:`True` if all tests run so far have passed, otherwise returns - :const:`False`. + .. attribute:: classSuiteClass -.. method:: TestResult.stop() + Callable object that constructs a test suite for the tests cases from one + class. The default value is :class:`ClassTestSuite`. - This method can be called to signal that the set of tests being run should be - aborted by setting the :class:`TestResult`'s ``shouldStop`` attribute to - :const:`True`. :class:`TestRunner` objects should respect this flag and return - without running any additional tests. - For example, this feature is used by the :class:`TextTestRunner` class to stop - the test framework when the user signals an interrupt from the keyboard. - Interactive tools which provide :class:`TestRunner` implementations can use this - in a similar manner. +.. class:: TestResult -The following methods of the :class:`TestResult` class are used to maintain the -internal data structures, and may be extended in subclasses to support -additional reporting requirements. This is particularly useful in building -tools which support interactive reporting while tests are being run. + This class is used to compile information about which tests have succeeded + and which have failed. + A :class:`TestResult` object stores the results of a set of tests. The + :class:`TestCase` and :class:`TestSuite` classes ensure that results are + properly recorded; test authors do not need to worry about recording the + outcome of tests. -.. method:: TestResult.startTest(test) + Testing frameworks built on top of :mod:`unittest` may want access to the + :class:`TestResult` object generated by running a set of tests for reporting + purposes; a :class:`TestResult` instance is returned by the + :meth:`TestRunner.run` method for this purpose. - Called when the test case *test* is about to be run. + :class:`TestResult` instances have the following attributes that will be of + interest when inspecting the results of running a set of tests: - The default implementation simply increments the instance's ``testsRun`` - counter. + .. attribute:: errors -.. method:: TestResult.stopTest(test) + A list containing 2-tuples of :class:`TestCase` instances and strings + holding formatted tracebacks. Each tuple represents a test which raised an + unexpected exception. - Called after the test case *test* has been executed, regardless of the outcome. + .. versionchanged:: 2.2 - The default implementation does nothing. + Contains formatted tracebacks instead of :func:`sys.exc_info` results. -.. method:: TestResult.addError(test, err) + .. attribute:: failures - Called when the test case *test* raises an unexpected exception *err* is a tuple - of the form returned by :func:`sys.exc_info`: ``(type, value, traceback)``. + A list containing 2-tuples of :class:`TestCase` instances and strings + holding formatted tracebacks. Each tuple represents a test where a failure + was explicitly signalled using the :meth:`TestCase.fail\*` or + :meth:`TestCase.assert\*` methods. - The default implementation appends a tuple ``(test, formatted_err)`` to the - instance's ``errors`` attribute, where *formatted_err* is a formatted - traceback derived from *err*. + .. versionchanged:: 2.2 + Contains formatted tracebacks instead of :func:`sys.exc_info` results. -.. method:: TestResult.addFailure(test, err) + .. attribute:: skipped - Called when the test case *test* signals a failure. *err* is a tuple of the form - returned by :func:`sys.exc_info`: ``(type, value, traceback)``. + A list containing 2-tuples of :class:`TestCase` instances and strings + holding the reason for skipping the test. - The default implementation appends a tuple ``(test, formatted_err)`` to the - instance's ``failures`` attribute, where *formatted_err* is a formatted - traceback derived from *err*. + .. versionadded:: 2.7 + .. attribute:: expectedFailures -.. method:: TestResult.addSuccess(test) + A list contaning 2-tuples of :class:`TestCase` instances and strings + holding formatted tracebacks. Each tuple represents a expected failures + of the test case. - Called when the test case *test* succeeds. + .. attribute:: unexpectedSuccesses - The default implementation does nothing. + A list containing :class:`TestCase` instances that were marked as expected + failures, but succeeded. + .. attribute:: shouldStop -.. method:: TestResult.addSkip(test, reason) + Set to ``True`` when the execution of tests should stop by :meth:`stop`. - Called when the test case *test* is skipped. *reason* is the reason the test - gave for skipping. - The default implementation appends a tuple ``(test, reason)`` to the - instance's ``skipped`` attribute. + .. attribute:: testsRun + The total number of tests run so far. -.. method:: TestResult.addExpectedFailure(test, err) - Called when the test case *test* fails, but was marked with the - :func:`expectedFailure` decorator. + .. method:: wasSuccessful() - The default implementation appends a tuple ``(test, formatted_err)`` to the - instance's ``expected_failures`` attribute, where *formatted_err* is a - formatted traceback derived from *err*. + Return :const:`True` if all tests run so far have passed, otherwise returns + :const:`False`. -.. method:: TestResult.addUnexpectedSuccess(test) + .. method:: stop() - Called when the test case *test* was marked with the :func:`expectedFailure` - decorator, but succeeded. + This method can be called to signal that the set of tests being run should + be aborted by setting the :attr:`shouldStop` attribute to :const:`True`. + :class:`TestRunner` objects should respect this flag and return without + running any additional tests. - The default implementation appends the test to the instance's - ``unexpected_successes`` attribute. + For example, this feature is used by the :class:`TextTestRunner` class to + stop the test framework when the user signals an interrupt from the + keyboard. Interactive tools which provide :class:`TestRunner` + implementations can use this in a similar manner. + The following methods of the :class:`TestResult` class are used to maintain + the internal data structures, and may be extended in subclasses to support + additional reporting requirements. This is particularly useful in building + tools which support interactive reporting while tests are being run. -.. _testloader-objects: -TestLoader Objects ------------------- + .. method:: startTest(test) -The :class:`TestLoader` class is used to create test suites from classes and -modules. Normally, there is no need to create an instance of this class; the -:mod:`unittest` module provides an instance that can be shared as -``unittest.defaultTestLoader``. Using a subclass or instance, however, allows -customization of some configurable properties. + Called when the test case *test* is about to be run. -:class:`TestLoader` objects have the following methods: + The default implementation simply increments the instance's :attr:`testsRun` + counter. -.. method:: TestLoader.loadTestsFromTestCase(testCaseClass) + .. method:: stopTest(test) - Return a suite of all tests cases contained in the :class:`TestCase`\ -derived - :class:`testCaseClass`. + Called after the test case *test* has been executed, regardless of the + outcome. + The default implementation does nothing. -.. method:: TestLoader.loadTestsFromModule(module) - Return a suite of all tests cases contained in the given module. This method - searches *module* for classes derived from :class:`TestCase` and creates an - instance of the class for each test method defined for the class. + .. method:: addError(test, err) - .. warning:: + Called when the test case *test* raises an unexpected exception *err* is a + tuple of the form returned by :func:`sys.exc_info`: ``(type, value, + traceback)``. - While using a hierarchy of :class:`TestCase`\ -derived classes can be convenient - in sharing fixtures and helper functions, defining test methods on base classes - that are not intended to be instantiated directly does not play well with this - method. Doing so, however, can be useful when the fixtures are different and - defined in subclasses. + The default implementation appends a tuple ``(test, formatted_err)`` to + the instance's :attr:`errors` attribute, where *formatted_err* is a + formatted traceback derived from *err*. -.. method:: TestLoader.loadTestsFromName(name[, module]) + .. method:: addFailure(test, err) - Return a suite of all tests cases given a string specifier. + Called when the test case *test* signals a failure. *err* is a tuple of the form + returned by :func:`sys.exc_info`: ``(type, value, traceback)``. - The specifier *name* is a "dotted name" that may resolve either to a module, a - test case class, a test method within a test case class, a :class:`TestSuite` - instance, or a callable object which returns a :class:`TestCase` or - :class:`TestSuite` instance. These checks are applied in the order listed here; - that is, a method on a possible test case class will be picked up as "a test - method within a test case class", rather than "a callable object". + The default implementation appends a tuple ``(test, formatted_err)`` to + the instance's :attr:`failures` attribute, where *formatted_err* is a + formatted traceback derived from *err*. - For example, if you have a module :mod:`SampleTests` containing a - :class:`TestCase`\ -derived class :class:`SampleTestCase` with three test - methods (:meth:`test_one`, :meth:`test_two`, and :meth:`test_three`), the - specifier ``'SampleTests.SampleTestCase'`` would cause this method to return a - suite which will run all three test methods. Using the specifier - ``'SampleTests.SampleTestCase.test_two'`` would cause it to return a test suite - which will run only the :meth:`test_two` test method. The specifier can refer - to modules and packages which have not been imported; they will be imported as a - side-effect. - The method optionally resolves *name* relative to the given *module*. + .. method:: addSuccess(test) + Called when the test case *test* succeeds. -.. method:: TestLoader.loadTestsFromNames(names[, module]) + The default implementation does nothing. - Similar to :meth:`loadTestsFromName`, but takes a sequence of names rather than - a single name. The return value is a test suite which supports all the tests - defined for each name. + .. method:: addSkip(test, reason) -.. method:: TestLoader.getTestCaseNames(testCaseClass) + Called when the test case *test* is skipped. *reason* is the reason the + test gave for skipping. - Return a sorted sequence of method names found within *testCaseClass*; this - should be a subclass of :class:`TestCase`. + The default implementation appends a tuple ``(test, reason)`` to the + instance's :attr:`skipped` attribute. -The following attributes of a :class:`TestLoader` can be configured either by -subclassing or assignment on an instance: + .. method:: addExpectedFailure(test, err) -.. attribute:: TestLoader.testMethodPrefix + Called when the test case *test* fails, but was marked with the + :func:`expectedFailure` decorator. - String giving the prefix of method names which will be interpreted as test - methods. The default value is ``'test'``. + The default implementation appends a tuple ``(test, formatted_err)`` to + the instance's :attr:`expectedFailures` attribute, where *formatted_err* + is a formatted traceback derived from *err*. - This affects :meth:`getTestCaseNames` and all the :meth:`loadTestsFrom\*` - methods. + .. method:: addUnexpectedSuccess(test) -.. attribute:: TestLoader.sortTestMethodsUsing + Called when the test case *test* was marked with the + :func:`expectedFailure` decorator, but succeeded. - Function to be used to compare method names when sorting them in - :meth:`getTestCaseNames` and all the :meth:`loadTestsFrom\*` - methods. This should be a function that takes two arguments - ``self`` and ``other``, and returns ``-1`` if ``self`` precedes - ``other`` in the desired ordering, ``1`` if ``other`` precedes - ``self``, and ``0`` if ``self`` and ``other`` are equal. The - default ordering is the built-in ordering for strings. This - attribute can also be set to :const:`None` to disable the sort. + The default implementation appends the test to the instance's + :attr:`unexpectedSuccesses` attribute. -.. attribute:: TestLoader.suiteClass +.. data:: defaultTestLoader - Callable object that constructs a test suite from a list of tests. No methods on - the resulting object are needed. The default value is the :class:`TestSuite` - class. + Instance of the :class:`TestLoader` class intended to be shared. If no + customization of the :class:`TestLoader` is needed, this instance can be used + instead of repeatedly creating new instances. - This affects all the :meth:`loadTestsFrom\*` methods. +.. class:: TextTestRunner([stream[, descriptions[, verbosity]]]) -.. attribute:: TestLoader.classSuiteClass + A basic test runner implementation which prints results on standard error. It + has a few configurable parameters, but is essentially very simple. Graphical + applications which run test suites should provide alternate implementations. - Callable object that constructs a test suite for the tests cases from one - class. The default value is :class:`ClassTestSuite`. +.. function:: main([module[, defaultTest[, argv[, testRunner[, 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 test script:: + + if __name__ == '__main__': + unittest.main() + + The *testRunner* argument can either be a test runner class or an already + created instance of it. Modified: python/branches/py3k/Lib/test/test_unittest.py ============================================================================== --- python/branches/py3k/Lib/test/test_unittest.py (original) +++ python/branches/py3k/Lib/test/test_unittest.py Tue Mar 24 01:56:30 2009 @@ -2372,7 +2372,7 @@ test.run(result) self.assertEqual(events, ['startTest', 'addExpectedFailure', 'stopTest']) - self.assertEqual(result.expected_failures[0][0], test) + self.assertEqual(result.expectedFailures[0][0], test) self.assertTrue(result.wasSuccessful()) def test_unexpected_success(self): @@ -2387,7 +2387,7 @@ self.assertEqual(events, ['startTest', 'addUnexpectedSuccess', 'stopTest']) self.assertFalse(result.failures) - self.assertEqual(result.unexpected_successes, [test]) + self.assertEqual(result.unexpectedSuccesses, [test]) self.assertTrue(result.wasSuccessful()) Modified: python/branches/py3k/Lib/unittest.py ============================================================================== --- python/branches/py3k/Lib/unittest.py (original) +++ python/branches/py3k/Lib/unittest.py Tue Mar 24 01:56:30 2009 @@ -25,9 +25,10 @@ Further information is available in the bundled documentation, and from - http://docs.python.org/lib/module-unittest.html + http://docs.python.org/library/unittest.html Copyright (c) 1999-2003 Steve Purcell +Copyright (c) 2003-2009 Python Software Foundation This module is free software, and you may redistribute it and/or modify it under the same terms as Python itself, so long as this copyright message and disclaimer are retained in their original form. @@ -44,10 +45,6 @@ SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ''' -__author__ = "Steve Purcell" -__email__ = "stephen_purcell at yahoo dot com" -__version__ = "#Revision: 1.63 $"[11:-2] - import time import sys import traceback @@ -58,8 +55,10 @@ ############################################################################## # Exported classes and functions ############################################################################## -__all__ = ['TestResult', 'TestCase', 'TestSuite', 'TextTestRunner', - 'TestLoader', 'FunctionTestCase', 'main', 'defaultTestLoader'] +__all__ = ['TestResult', 'TestCase', 'TestSuite', 'ClassTestSuite', + 'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main', + 'defaultTestLoader', 'SkipException', 'skip', 'skipIf', 'skipUnless', + 'expectedFailure'] # Expose obsolete functions for backwards compatibility __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases']) @@ -163,8 +162,8 @@ self.errors = [] self.testsRun = 0 self.skipped = [] - self.expected_failures = [] - self.unexpected_successes = [] + self.expectedFailures = [] + self.unexpectedSuccesses = [] self.shouldStop = False def startTest(self, test): @@ -196,12 +195,12 @@ def addExpectedFailure(self, test, err): """Called when an expected failure/error occured.""" - self.expected_failures.append( + self.expectedFailures.append( (test, self._exc_info_to_string(err, test))) def addUnexpectedSuccess(self, test): """Called when a test was expected to fail, but succeed.""" - self.unexpected_successes.append(test) + self.unexpectedSuccesses.append(test) def wasSuccessful(self): "Tells whether or not this result was a success" @@ -239,7 +238,10 @@ (_strclass(self.__class__), self.testsRun, len(self.errors), len(self.failures)) + class AssertRaisesContext(object): + + def __init__(self, expected, test_case, callable_obj=None): self.expected = expected self.failureException = test_case.failureException @@ -250,8 +252,10 @@ self.obj_name = str(callable_obj) else: self.obj_name = None + def __enter__(self): pass + def __exit__(self, exc_type, exc_value, traceback): if exc_type is None: try: @@ -269,6 +273,7 @@ # Let unexpected exceptions skip through return False + class TestCase(object): """A class whose instances are single test cases. @@ -302,13 +307,13 @@ method when executed. Raises a ValueError if the instance does not have a method with the specified name. """ + self._testMethodName = methodName try: - self._testMethodName = methodName testMethod = getattr(self, methodName) - self._testMethodDoc = testMethod.__doc__ except AttributeError: raise ValueError("no such test method in %s: %s" % \ (self.__class__, methodName)) + self._testMethodDoc = testMethod.__doc__ def setUp(self): "Hook method for setting up the test fixture before exercising it." @@ -339,7 +344,7 @@ def __eq__(self, other): if type(self) is not type(other): - return False + return NotImplemented return self._testMethodName == other._testMethodName @@ -357,7 +362,8 @@ (_strclass(self.__class__), self._testMethodName) def run(self, result=None): - if result is None: result = self.defaultTestResult() + if result is None: + result = self.defaultTestResult() result.startTest(self) testMethod = getattr(self, self._testMethodName) try: @@ -422,11 +428,13 @@ def failIf(self, expr, msg=None): "Fail the test if the expression is true." - if expr: raise self.failureException(msg) + if expr: + raise self.failureException(msg) def failUnless(self, expr, msg=None): """Fail the test unless the expression is true.""" - if not expr: raise self.failureException(msg) + if not expr: + raise self.failureException(msg) def failUnlessRaises(self, excClass, callableObj=None, *args, **kwargs): """Fail unless an exception of class excClass is thrown @@ -520,8 +528,6 @@ def __repr__(self): return "<%s tests=%s>" % (_strclass(self.__class__), self._tests) - __str__ = __repr__ - def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented @@ -566,7 +572,8 @@ def debug(self): """Run the tests without collecting errors in a TestResult""" - for test in self._tests: test.debug() + for test in self._tests: + test.debug() class ClassTestSuite(TestSuite): @@ -609,9 +616,8 @@ always be called if the set-up ('setUp') function ran successfully. """ - def __init__(self, testFunc, setUp=None, tearDown=None, - description=None): - TestCase.__init__(self) + def __init__(self, testFunc, setUp=None, tearDown=None, description=None): + super(FunctionTestCase, self).__init__() self.__setUpFunc = setUp self.__tearDownFunc = tearDown self.__testFunc = testFunc @@ -632,8 +638,8 @@ return self.__testFunc.__name__ def __eq__(self, other): - if type(self) is not type(other): - return False + if not isinstance(other, self.__class__): + return NotImplemented return self.__setUpFunc == other.__setUpFunc and \ self.__tearDownFunc == other.__tearDownFunc and \ @@ -680,8 +686,9 @@ return (x > y) - (x < y) class TestLoader(object): - """This class is responsible for loading tests according to various - criteria and returning them wrapped in a TestSuite + """ + This class is responsible for loading tests according to various criteria + and returning them wrapped in a TestSuite """ testMethodPrefix = 'test' sortTestMethodsUsing = staticmethod(three_way_cmp) @@ -691,8 +698,8 @@ def loadTestsFromTestCase(self, testCaseClass): """Return a suite of all tests cases contained in testCaseClass""" if issubclass(testCaseClass, TestSuite): - raise TypeError("Test cases should not be derived from TestSuite." - "Maybe you meant to derive from TestCase?") + raise TypeError("Test cases should not be derived from TestSuite." \ + " Maybe you meant to derive from TestCase?") testCaseNames = self.getTestCaseNames(testCaseClass) if not testCaseNames and hasattr(testCaseClass, 'runTest'): testCaseNames = ['runTest'] @@ -727,7 +734,8 @@ break except ImportError: del parts_copy[-1] - if not parts_copy: raise + if not parts_copy: + raise parts = parts[1:] obj = module for part in parts: @@ -772,8 +780,8 @@ """ def isTestMethod(attrname, testCaseClass=testCaseClass, prefix=self.testMethodPrefix): - return attrname.startswith(prefix) \ - and hasattr(getattr(testCaseClass, attrname), '__call__') + return attrname.startswith(prefix) and \ + hasattr(getattr(testCaseClass, attrname), '__call__') testFnNames = list(filter(isTestMethod, dir(testCaseClass))) if self.sortTestMethodsUsing: testFnNames.sort(key=CmpToKey(self.sortTestMethodsUsing)) @@ -835,7 +843,7 @@ separator2 = '-' * 70 def __init__(self, stream, descriptions, verbosity): - TestResult.__init__(self) + super(_TextTestResult, self).__init__() self.stream = stream self.showAll = verbosity > 1 self.dots = verbosity == 1 @@ -848,14 +856,14 @@ return str(test) def startTest(self, test): - TestResult.startTest(self, test) + super(_TextTestResult, self).startTest(test) if self.showAll: self.stream.write(self.getDescription(test)) self.stream.write(" ... ") self.stream.flush() def addSuccess(self, test): - TestResult.addSuccess(self, test) + super(_TextTestResult, self).addSuccess(test) if self.showAll: self.stream.writeln("ok") elif self.dots: @@ -863,7 +871,7 @@ self.stream.flush() def addError(self, test, err): - TestResult.addError(self, test, err) + super(_TextTestResult, self).addError(test, err) if self.showAll: self.stream.writeln("ERROR") elif self.dots: @@ -871,7 +879,7 @@ self.stream.flush() def addFailure(self, test, err): - TestResult.addFailure(self, test, err) + super(_TextTestResult, self).addFailure(test, err) if self.showAll: self.stream.writeln("FAIL") elif self.dots: @@ -879,7 +887,7 @@ self.stream.flush() def addSkip(self, test, reason): - TestResult.addSkip(self, test, reason) + super(_TextTestResult, self).addSkip(test, reason) if self.showAll: self.stream.writeln("skipped {0!r}".format(reason)) elif self.dots: @@ -887,7 +895,7 @@ self.stream.flush() def addExpectedFailure(self, test, err): - TestResult.addExpectedFailure(self, test, err) + super(_TextTestResult, self).addExpectedFailure(test, err) if self.showAll: self.stream.writeln("expected failure") elif self.dots: @@ -895,7 +903,7 @@ self.stream.flush() def addUnexpectedSuccess(self, test): - TestResult.addUnexpectedSuccess(self, test) + super(_TextTestResult, self).addUnexpectedSuccess(test) if self.showAll: self.stream.writeln("unexpected success") elif self.dots: @@ -943,10 +951,10 @@ self.stream.writeln("Ran %d test%s in %.3fs" % (run, run != 1 and "s" or "", timeTaken)) self.stream.writeln() - results = map(len, (result.expected_failures, - result.unexpected_successes, + results = map(len, (result.expectedFailures, + result.unexpectedSuccesses, result.skipped)) - expected_fails, unexpected_successes, skipped = results + expectedFails, unexpectedSuccesses, skipped = results infos = [] if not result.wasSuccessful(): self.stream.write("FAILED") @@ -956,13 +964,13 @@ if errored: infos.append("errors=%d" % errored) else: - self.stream.write("OK") + self.stream.writeln("OK") if skipped: infos.append("skipped=%d" % skipped) - if expected_fails: - infos.append("expected failures=%d" % expected_fails) - if unexpected_successes: - infos.append("unexpected successes=%d" % unexpected_successes) + if expectedFails: + infos.append("expected failures=%d" % expectedFails) + if unexpectedSuccesses: + infos.append("unexpected successes=%d" % unexpectedSuccesses) if infos: self.stream.writeln(" (%s)" % (", ".join(infos),)) return result @@ -1012,7 +1020,8 @@ self.runTests() def usageExit(self, msg=None): - if msg: print(msg) + if msg: + print(msg) print(self.USAGE % self.__dict__) sys.exit(2) From python-checkins at python.org Tue Mar 24 02:00:11 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 02:00:11 +0100 (CET) Subject: [Python-checkins] r70573 - python/branches/py3k/Doc/library/unittest.rst Message-ID: <20090324010011.9F3531E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 02:00:11 2009 New Revision: 70573 Log: fix some versionchanged and versionadded directives Modified: python/branches/py3k/Doc/library/unittest.rst Modified: python/branches/py3k/Doc/library/unittest.rst ============================================================================== --- python/branches/py3k/Doc/library/unittest.rst (original) +++ python/branches/py3k/Doc/library/unittest.rst Tue Mar 24 02:00:11 2009 @@ -620,6 +620,7 @@ default value for *msg* can be computed to include representations of both *first* and *second*. + .. method:: assertAlmostEqual(first, second[, places[, msg]]) failUnlessAlmostEqual(first, second[, places[, msg]]) @@ -656,7 +657,7 @@ To catch any of a group of exceptions, a tuple containing the exception classes may be passed as *exception*. - .. versionchanged:: 2.7 + .. versionchanged:: 3.1 If *callable* is omitted or None, returns a context manager so that the code under test can be written inline rather than as a function:: @@ -732,7 +733,6 @@ .. _testsuite-objects: - Grouping tests ~~~~~~~~~~~~~~ @@ -934,10 +934,6 @@ holding formatted tracebacks. Each tuple represents a test which raised an unexpected exception. - .. versionchanged:: 2.2 - - Contains formatted tracebacks instead of :func:`sys.exc_info` results. - .. attribute:: failures @@ -946,16 +942,12 @@ was explicitly signalled using the :meth:`TestCase.fail\*` or :meth:`TestCase.assert\*` methods. - .. versionchanged:: 2.2 - - Contains formatted tracebacks instead of :func:`sys.exc_info` results. - .. attribute:: skipped A list containing 2-tuples of :class:`TestCase` instances and strings holding the reason for skipping the test. - .. versionadded:: 2.7 + .. versionadded:: 3.1 .. attribute:: expectedFailures From buildbot at python.org Tue Mar 24 02:03:18 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 01:03:18 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo trunk Message-ID: <20090324010318.5C4861E401E@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%20gentoo%20trunk/builds/4767 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test___all__ ====================================================================== ERROR: test_all (test.test___all__.AllTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/test/test___all__.py", line 155, in test_all self.check_all("unittest") File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/test/test___all__.py", line 24, in check_all exec "from %s import *" % modname in names File "", line 1, in AttributeError: 'module' object has no attribute 'SkipException' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 24 02:07:32 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 01:07:32 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo trunk Message-ID: <20090324010732.8D3D61E4002@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%20gentoo%20trunk/builds/1990 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed 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 522, in __bootstrap_inner self.run() File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/threading.py", line 477, in run self.__target(*self.__args, **self.__kwargs) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/bsddb/test/test_thread.py", line 306, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/bsddb/dbutils.py", line 68, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') 1 test failed: test___all__ ====================================================================== ERROR: test_all (test.test___all__.AllTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test___all__.py", line 155, in test_all self.check_all("unittest") File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test___all__.py", line 24, in check_all exec "from %s import *" % modname in names File "", line 1, in AttributeError: 'module' object has no attribute 'SkipException' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 24 02:10:44 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 01:10:44 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090324011044.7FFB61E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/759 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test___all__ test_asynchat ====================================================================== ERROR: test_all (test.test___all__.AllTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test___all__.py", line 155, in test_all self.check_all("unittest") File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test___all__.py", line 24, in check_all exec "from %s import *" % modname in names File "", line 1, in AttributeError: 'module' object has no attribute 'SkipException' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 24 02:11:37 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 02:11:37 +0100 (CET) Subject: [Python-checkins] r70574 - python/trunk/Lib/unittest.py Message-ID: <20090324011137.D2B1A1E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 02:11:37 2009 New Revision: 70574 Log: fix typo Modified: python/trunk/Lib/unittest.py Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Tue Mar 24 02:11:37 2009 @@ -57,7 +57,7 @@ ############################################################################## __all__ = ['TestResult', 'TestCase', 'TestSuite', 'ClassTestSuite', 'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main', - 'defaultTestLoader', 'SkipException', 'skip', 'skipIf', 'skipUnless', + 'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless', 'expectedFailure'] # Expose obsolete functions for backwards compatibility From buildbot at python.org Tue Mar 24 02:13:16 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 01:13:16 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090324011316.8353E1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/544 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test___all__ ====================================================================== ERROR: test_all (test.test___all__.AllTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/test/test___all__.py", line 136, in test_all self.check_all("unittest") File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/test/test___all__.py", line 23, in check_all exec("from %s import *" % modname, names) File "", line 1, in AttributeError: 'module' object has no attribute 'SkipException' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 24 02:25:36 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 01:25:36 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090324012536.BBE161E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/447 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test___all__ ====================================================================== ERROR: test_all (test.test___all__.AllTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test___all__.py", line 136, in test_all self.check_all("unittest") File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test___all__.py", line 23, in check_all exec("from %s import *" % modname, names) File "", line 1, in AttributeError: 'module' object has no attribute 'SkipException' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 24 02:33:26 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 01:33:26 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090324013326.CD1BE1E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/483 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test___all__ ====================================================================== ERROR: test_all (test.test___all__.AllTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ppc/build/Lib/test/test___all__.py", line 136, in test_all self.check_all("unittest") File "/home/pybot/buildarea/3.x.klose-debian-ppc/build/Lib/test/test___all__.py", line 23, in check_all exec("from %s import *" % modname, names) File "", line 1, in AttributeError: 'module' object has no attribute 'SkipException' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 24 02:33:55 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 02:33:55 +0100 (CET) Subject: [Python-checkins] r70575 - in python/branches/py3k: Lib/unittest.py Message-ID: <20090324013355.EE3911E400C@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 02:33:55 2009 New Revision: 70575 Log: Merged revisions 70574 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70574 | benjamin.peterson | 2009-03-23 20:11:37 -0500 (Mon, 23 Mar 2009) | 1 line fix typo ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/unittest.py Modified: python/branches/py3k/Lib/unittest.py ============================================================================== --- python/branches/py3k/Lib/unittest.py (original) +++ python/branches/py3k/Lib/unittest.py Tue Mar 24 02:33:55 2009 @@ -57,7 +57,7 @@ ############################################################################## __all__ = ['TestResult', 'TestCase', 'TestSuite', 'ClassTestSuite', 'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main', - 'defaultTestLoader', 'SkipException', 'skip', 'skipIf', 'skipUnless', + 'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless', 'expectedFailure'] # Expose obsolete functions for backwards compatibility From buildbot at python.org Tue Mar 24 02:35:23 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 01:35:23 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090324013523.865241E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/507 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test___all__ ====================================================================== ERROR: test_all (test.test___all__.AllTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildbot/buildarea/3.x.heller-x86-osx5/build/Lib/test/test___all__.py", line 136, in test_all self.check_all("unittest") File "/Users/buildbot/buildarea/3.x.heller-x86-osx5/build/Lib/test/test___all__.py", line 23, in check_all exec("from %s import *" % modname, names) File "", line 1, in AttributeError: 'module' object has no attribute 'SkipException' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 24 02:36:17 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 02:36:17 +0100 (CET) Subject: [Python-checkins] r70576 - in python/branches/release30-maint/Doc/c-api: allocation.rst module.rst Message-ID: <20090324013617.CEF061E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 02:36:17 2009 New Revision: 70576 Log: backport new c module docs Modified: python/branches/release30-maint/Doc/c-api/allocation.rst python/branches/release30-maint/Doc/c-api/module.rst Modified: python/branches/release30-maint/Doc/c-api/allocation.rst ============================================================================== --- python/branches/release30-maint/Doc/c-api/allocation.rst (original) +++ python/branches/release30-maint/Doc/c-api/allocation.rst Tue Mar 24 02:36:17 2009 @@ -54,40 +54,15 @@ accessed after this call as the memory is no longer a valid Python object. -.. cfunction:: PyObject* Py_InitModule(char *name, PyMethodDef *methods) - - Create a new module object based on a name and table of functions, returning - the new module object; the *methods* argument can be *NULL* if no methods are - to be defined for the module. - - -.. cfunction:: PyObject* Py_InitModule3(char *name, PyMethodDef *methods, char *doc) - - Create a new module object based on a name and table of functions, returning - the new module object. The *methods* argument can be *NULL* if no methods - are to be defined for the module. If *doc* is non-*NULL*, it will be used to - define the docstring for the module. - - -.. cfunction:: PyObject* Py_InitModule4(char *name, PyMethodDef *methods, char *doc, PyObject *self, int apiver) - - Create a new module object based on a name and table of functions, returning - the new module object. The *methods* argument can be *NULL* if no methods - are to be defined for the module. If *doc* is non-*NULL*, it will be used to - define the docstring for the module. If *self* is non-*NULL*, it will passed - to the functions of the module as their (otherwise *NULL*) first parameter. - (This was added as an experimental feature, and there are no known uses in - the current version of Python.) For *apiver*, the only value which should be - passed is defined by the constant :const:`PYTHON_API_VERSION`. - - .. note:: - - Most uses of this function should probably be using the :cfunc:`Py_InitModule3` - instead; only use this if you are sure you need it. - - .. cvar:: PyObject _Py_NoneStruct Object which is visible in Python as ``None``. This should only be accessed using the :cmacro:`Py_None` macro, which evaluates to a pointer to this object. + + +.. seealso:: + + :cfunc:`PyModule_Create` + To allocate and create extension modules. + Modified: python/branches/release30-maint/Doc/c-api/module.rst ============================================================================== --- python/branches/release30-maint/Doc/c-api/module.rst (original) +++ python/branches/release30-maint/Doc/c-api/module.rst Tue Mar 24 02:36:17 2009 @@ -73,6 +73,101 @@ raise :exc:`SystemError` and return *NULL*. +.. cfunction:: void* PyModule_GetState(PyObject *module) + + Return the "state" of the module, that is, a pointer to the block of memory + allocated at module creation time, or *NULL*. See + :cmember:`PyModuleDef.m_size`. + + +.. cfunction:: PyModuleDef* PyModule_GetDef(PyObject *module) + + Return a pointer to the :ctype:`PyModuleDef` struct from which the module was + created, or *NULL* if the module wasn't created with + :cfunc:`PyModule_Create`. + + +Initializing C modules +^^^^^^^^^^^^^^^^^^^^^^ + +These functions are usually used in the module initialization function. + +.. cfunction:: PyObject* PyModule_Create(PyModuleDef *module) + + Create a new module object, given the definition in *module*. This behaves + like :cfunc:`PyModule_Create2` with *module_api_version* set to + :const:`PYTHON_API_VERSION`. + + +.. cfunction:: PyObject* PyModule_Create2(PyModuleDef *module, int module_api_version) + + Create a new module object, given the definition in *module*, assuming the + API version *module_api_version*. If that version does not match the version + of the running interpreter, a :exc:`RuntimeWarning` is emitted. + + .. note:: + + Most uses of this function should be using :cfunc:`PyModule_Create` + instead; only use this if you are sure you need it. + + +.. ctype:: PyModuleDef + + This struct holds all information that is needed to create a module object. + There is usually only one static variable of that type for each module, which + is statically initialized and then passed to :cfunc:`PyModule_Create` in the + module initialization function. + + .. cmember:: PyModuleDef_Base m_base + + Always initialize this member to :const:`PyModuleDef_HEAD_INIT`. + + .. cmember:: char* m_name + + Name for the new module. + + .. cmember:: char* m_doc + + Docstring for the module; usually a docstring variable created with + :cfunc:`PyDoc_STRVAR` is used. + + .. cmember:: Py_ssize_t m_size + + If the module object needs additional memory, this should be set to the + number of bytes to allocate; a pointer to the block of memory can be + retrieved with :cfunc:`PyModule_GetState`. If no memory is needed, set + this to ``-1``. + + This memory should be used, rather than static globals, to hold per-module + state, since it is then safe for use in multiple sub-interpreters. It is + freed when the module object is deallocated, after the :cmember:`m_free` + function has been called, if present. + + .. cmember:: PyMethodDef* m_methods + + A pointer to a table of module-level functions, described by + :ctype:`PyMethodDef` values. Can be *NULL* if no functions are present. + + .. cmember:: inquiry m_reload + + Currently unused, should be *NULL*. + + .. cmember:: traverseproc m_traverse + + A traversal function to call during GC traversal of the module object, or + *NULL* if not needed. + + .. cmember:: inquiry m_clear + + A clear function to call during GC clearing of the module object, or + *NULL* if not needed. + + .. cmember:: freefunc m_free + + A function to call during deallocation of the module object, or *NULL* if + not needed. + + .. cfunction:: int PyModule_AddObject(PyObject *module, const char *name, PyObject *value) Add an object to *module* as *name*. This is a convenience function which can @@ -105,4 +200,3 @@ .. cfunction:: int PyModule_AddStringMacro(PyObject *module, macro) Add a string constant to *module*. - From python-checkins at python.org Tue Mar 24 02:40:39 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 02:40:39 +0100 (CET) Subject: [Python-checkins] r70577 - python/branches/py3k/Doc/extending/extending.rst Message-ID: <20090324014039.DF0C21E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 02:40:39 2009 New Revision: 70577 Log: fix function name Modified: python/branches/py3k/Doc/extending/extending.rst Modified: python/branches/py3k/Doc/extending/extending.rst ============================================================================== --- python/branches/py3k/Doc/extending/extending.rst (original) +++ python/branches/py3k/Doc/extending/extending.rst Tue Mar 24 02:40:39 2009 @@ -1262,7 +1262,7 @@ :cfunc:`import_spam` in its initialization function:: PyMODINIT_FUNC - initclient(void) + PyInit_client(void) { PyObject *m; From buildbot at python.org Tue Mar 24 02:51:13 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 01:51:13 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090324015114.3D4A41E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/440 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test___all__ ====================================================================== ERROR: test_all (test.test___all__.AllTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test___all__.py", line 136, in test_all self.check_all("unittest") File "/home/pybot/buildarea/3.x.klose-debian-ia64/build/Lib/test/test___all__.py", line 23, in check_all exec("from %s import *" % modname, names) File "", line 1, in AttributeError: 'module' object has no attribute 'SkipException' make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 24 04:24:56 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 04:24:56 +0100 (CET) Subject: [Python-checkins] r70578 - python/trunk/Lib/test/test_support.py Message-ID: <20090324032456.AC8511E4002@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 04:24:56 2009 New Revision: 70578 Log: this is better written using assertRaises Modified: python/trunk/Lib/test/test_support.py Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Tue Mar 24 04:24:56 2009 @@ -370,12 +370,8 @@ unlink(TESTFN) def check_syntax_error(testcase, statement): - try: - compile(statement, '', 'exec') - except SyntaxError: - pass - else: - testcase.fail('Missing SyntaxError: "%s"' % statement) + testcase.assertRaises(SyntaxError, compile, statement, + '', 'exec') def open_urlresource(url): import urllib, urlparse From python-checkins at python.org Tue Mar 24 14:21:53 2009 From: python-checkins at python.org (kristjan.jonsson) Date: Tue, 24 Mar 2009 14:21:53 +0100 (CET) Subject: [Python-checkins] r70579 - python/branches/py3k/Modules/_fileio.c Message-ID: <20090324132153.A9C441E402D@bag.python.org> Author: kristjan.jonsson Date: Tue Mar 24 14:21:53 2009 New Revision: 70579 Log: http://bugs.python.org/issue5544 Someone may have closed the file descriptor, with something like f = open('test.test', 'w') os.close(f.fileno()) f.close() Protect against this by checking fd on windows before closing. Modified: python/branches/py3k/Modules/_fileio.c Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Tue Mar 24 14:21:53 2009 @@ -77,11 +77,15 @@ if (self->fd >= 0) { int fd = self->fd; self->fd = -1; - Py_BEGIN_ALLOW_THREADS - err = close(fd); - if (err < 0) - save_errno = errno; - Py_END_ALLOW_THREADS + /* fd is accessible and someone else may have closed it */ + if (_PyVerify_fd(fd)) { + Py_BEGIN_ALLOW_THREADS + err = close(fd); + if (err < 0) + save_errno = errno; + Py_END_ALLOW_THREADS + } else + save_errno = errno; } if (err < 0) { errno = save_errno; From buildbot at python.org Tue Mar 24 14:43:17 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 13:43:17 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo 3.x Message-ID: <20090324134317.B659D1E4002@bag.python.org> The Buildbot has detected a new failure of x86 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20gentoo%203.x/builds/550 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,kristjan.jonsson BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Unknown signal 32 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 24 14:51:36 2009 From: python-checkins at python.org (kristjan.jonsson) Date: Tue, 24 Mar 2009 14:51:36 +0100 (CET) Subject: [Python-checkins] r70580 - python/branches/py3k/Modules/_fileio.c Message-ID: <20090324135136.C34C61E4018@bag.python.org> Author: kristjan.jonsson Date: Tue Mar 24 14:51:36 2009 New Revision: 70580 Log: http://bugs.python.org/issue5544 Fix to the last checkin, correctly raise an exception on failure. Modified: python/branches/py3k/Modules/_fileio.c Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Tue Mar 24 14:51:36 2009 @@ -84,8 +84,10 @@ if (err < 0) save_errno = errno; Py_END_ALLOW_THREADS - } else - save_errno = errno; + } else { + save_errno = errno; + err = -1; + } } if (err < 0) { errno = save_errno; From python-checkins at python.org Tue Mar 24 15:15:49 2009 From: python-checkins at python.org (kristjan.jonsson) Date: Tue, 24 Mar 2009 15:15:49 +0100 (CET) Subject: [Python-checkins] r70581 - python/branches/py3k/Modules/posixmodule.c Message-ID: <20090324141549.5FD851E4002@bag.python.org> Author: kristjan.jonsson Date: Tue Mar 24 15:15:49 2009 New Revision: 70581 Log: http://bugs.python.org/issue5552 Return None rather than raise an exception if os.device_error is given an invalid file descriptor. Modified: python/branches/py3k/Modules/posixmodule.c Modified: python/branches/py3k/Modules/posixmodule.c ============================================================================== --- python/branches/py3k/Modules/posixmodule.c (original) +++ python/branches/py3k/Modules/posixmodule.c Tue Mar 24 15:15:49 2009 @@ -6830,9 +6830,7 @@ int fd; if (!PyArg_ParseTuple(args, "i:device_encoding", &fd)) return NULL; - if (!_PyVerify_fd(fd)) - return posix_error(); - if (!isatty(fd)) { + if (!_PyVerify_fd(fd) || !isatty(fd)) { Py_INCREF(Py_None); return Py_None; } From buildbot at python.org Tue Mar 24 15:37:22 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 14:37:22 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090324143723.0E3F91E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/547 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: kristjan.jonsson BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Tue Mar 24 15:39:48 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 14:39:48 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090324143949.B983B1E403B@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/451 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: kristjan.jonsson BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_pipes test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 24 15:50:44 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 14:50:44 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090324145045.109601E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/510 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: kristjan.jonsson BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 24 16:27:43 2009 From: python-checkins at python.org (kristjan.jonsson) Date: Tue, 24 Mar 2009 16:27:43 +0100 (CET) Subject: [Python-checkins] r70582 - in python/branches/py3k: Lib/test/test_fileio.py Modules/_fileio.c Message-ID: <20090324152743.7D3781E401B@bag.python.org> Author: kristjan.jonsson Date: Tue Mar 24 16:27:42 2009 New Revision: 70582 Log: http://bugs.python.org/issue5544 Guard _fileio.c against other malicious os.close(f.fileno()) attempts. Add tests to test_fileio.py to verify behaviour. Modified: python/branches/py3k/Lib/test/test_fileio.py python/branches/py3k/Modules/_fileio.c Modified: python/branches/py3k/Lib/test/test_fileio.py ============================================================================== --- python/branches/py3k/Lib/test/test_fileio.py (original) +++ python/branches/py3k/Lib/test/test_fileio.py Tue Mar 24 16:27:42 2009 @@ -6,6 +6,7 @@ import unittest from array import array from weakref import proxy +from functools import wraps from test.support import (TESTFN, findfile, check_warnings, run_unittest, make_bad_fd) @@ -114,20 +115,106 @@ else: self.fail("Should have raised IOError") - def testErrnoOnClose(self): - # Test that the IOError's `errno` attribute is correctly set when - # close() fails. Here we first close the file descriptor ourselves so - # that close() fails with EBADF ('Bad file descriptor'). - f = self.f - os.close(f.fileno()) - self.f = None + #A set of functions testing that we get expected behaviour if someone has + #manually closed the internal file descriptor. First, a decorator: + def ClosedFD(func): + @wraps(func) + def wrapper(self): + #forcibly close the fd before invoking the problem function + f = self.f + os.close(f.fileno()) + try: + func(self, f) + finally: + try: + self.f.close() + except IOError: + pass + return wrapper + + def ClosedFDRaises(func): + @wraps(func) + def wrapper(self): + #forcibly close the fd before invoking the problem function + f = self.f + os.close(f.fileno()) + try: + func(self, f) + except IOError as e: + self.assertEqual(e.errno, errno.EBADF) + else: + self.fail("Should have raised IOError") + finally: + try: + self.f.close() + except IOError: + pass + return wrapper + + @ClosedFDRaises + def testErrnoOnClose(self, f): + f.close() + + @ClosedFDRaises + def testErrnoOnClosedWrite(self, f): + f.write('a') + + @ClosedFDRaises + def testErrnoOnClosedSeek(self, f): + f.seek(0) + + @ClosedFDRaises + def testErrnoOnClosedTell(self, f): + f.tell() + + @ClosedFDRaises + def testErrnoOnClosedTruncate(self, f): + f.truncate(0) + + @ClosedFD + def testErrnoOnClosedSeekable(self, f): + f.seekable() + + @ClosedFD + def testErrnoOnClosedReadable(self, f): + f.readable() + + @ClosedFD + def testErrnoOnClosedWritable(self, f): + f.writable() + + @ClosedFD + def testErrnoOnClosedFileno(self, f): + f.fileno() + + @ClosedFD + def testErrnoOnClosedIsatty(self, f): + self.assertEqual(f.isatty(), False) + + def ReopenForRead(self): try: - f.close() - except IOError as e: - self.assertEqual(e.errno, errno.EBADF) - else: - self.fail("Should have raised IOError") + self.f.close() + except IOError: + pass + self.f = _FileIO(TESTFN, 'r') + os.close(self.f.fileno()) + return self.f + @ClosedFDRaises + def testErrnoOnClosedRead(self, f): + f = self.ReopenForRead() + f.read(1) + + @ClosedFDRaises + def testErrnoOnClosedReadall(self, f): + f = self.ReopenForRead() + f.readall() + + @ClosedFDRaises + def testErrnoOnClosedReadinto(self, f): + f = self.ReopenForRead() + a = array('b', b'x'*10) + f.readinto(a) class OtherFileTests(unittest.TestCase): Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Tue Mar 24 16:27:42 2009 @@ -475,10 +475,13 @@ if (!PyArg_ParseTuple(args, "w*", &pbuf)) return NULL; - Py_BEGIN_ALLOW_THREADS - errno = 0; - n = read(self->fd, pbuf.buf, pbuf.len); - Py_END_ALLOW_THREADS + if (_PyVerify_fd(self->fd)) { + Py_BEGIN_ALLOW_THREADS + errno = 0; + n = read(self->fd, pbuf.buf, pbuf.len); + Py_END_ALLOW_THREADS + } else + n = -1; PyBuffer_Release(&pbuf); if (n < 0) { if (errno == EAGAIN) @@ -522,6 +525,9 @@ Py_ssize_t total = 0; int n; + if (!_PyVerify_fd(self->fd)) + return PyErr_SetFromErrno(PyExc_IOError); + result = PyBytes_FromStringAndSize(NULL, SMALLCHUNK); if (result == NULL) return NULL; @@ -596,10 +602,13 @@ return NULL; ptr = PyBytes_AS_STRING(bytes); - Py_BEGIN_ALLOW_THREADS - errno = 0; - n = read(self->fd, ptr, size); - Py_END_ALLOW_THREADS + if (_PyVerify_fd(self->fd)) { + Py_BEGIN_ALLOW_THREADS + errno = 0; + n = read(self->fd, ptr, size); + Py_END_ALLOW_THREADS + } else + n = -1; if (n < 0) { if (errno == EAGAIN) @@ -632,10 +641,13 @@ if (!PyArg_ParseTuple(args, "s*", &pbuf)) return NULL; - Py_BEGIN_ALLOW_THREADS - errno = 0; - n = write(self->fd, pbuf.buf, pbuf.len); - Py_END_ALLOW_THREADS + if (_PyVerify_fd(self->fd)) { + Py_BEGIN_ALLOW_THREADS + errno = 0; + n = write(self->fd, pbuf.buf, pbuf.len); + Py_END_ALLOW_THREADS + } else + n = -1; PyBuffer_Release(&pbuf); @@ -688,13 +700,16 @@ return NULL; } - Py_BEGIN_ALLOW_THREADS + if (_PyVerify_fd(fd)) { + Py_BEGIN_ALLOW_THREADS #if defined(MS_WIN64) || defined(MS_WINDOWS) - res = _lseeki64(fd, pos, whence); + res = _lseeki64(fd, pos, whence); #else - res = lseek(fd, pos, whence); + res = lseek(fd, pos, whence); #endif - Py_END_ALLOW_THREADS + Py_END_ALLOW_THREADS + } else + res = -1; if (res < 0) return PyErr_SetFromErrno(PyExc_IOError); @@ -757,13 +772,15 @@ /* Move to the position to be truncated. */ posobj = portable_lseek(fd, posobj, 0); } + if (posobj == NULL) + return NULL; #if defined(HAVE_LARGEFILE_SUPPORT) pos = PyLong_AsLongLong(posobj); #else pos = PyLong_AsLong(posobj); #endif - if (PyErr_Occurred()) + if (pos == -1 && PyErr_Occurred()) return NULL; #ifdef MS_WINDOWS From buildbot at python.org Tue Mar 24 16:44:03 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 15:44:03 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090324154403.DD8FD1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/549 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: kristjan.jonsson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_pipes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 24 21:59:51 2009 From: python-checkins at python.org (christian.heimes) Date: Tue, 24 Mar 2009 21:59:51 +0100 (CET) Subject: [Python-checkins] r70583 - python/branches/multiprocessing-autoconf Message-ID: <20090324205951.7CB671E4035@bag.python.org> Author: christian.heimes Date: Tue Mar 24 21:59:51 2009 New Revision: 70583 Log: Created branch to work on autoconf for multiprocessing Added: python/branches/multiprocessing-autoconf/ - copied from r70582, /python/trunk/ From python-checkins at python.org Tue Mar 24 22:11:11 2009 From: python-checkins at python.org (christian.heimes) Date: Tue, 24 Mar 2009 22:11:11 +0100 (CET) Subject: [Python-checkins] r70584 - in python/branches/multiprocessing-autoconf: Lib/test/test_multiprocessing.py configure configure.in pyconfig.h.in setup.py Message-ID: <20090324211111.4DBCD1E4002@bag.python.org> Author: christian.heimes Date: Tue Mar 24 22:11:10 2009 New Revision: 70584 Log: Replaced hard coded values with autoconf rules. Modified: python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py python/branches/multiprocessing-autoconf/configure python/branches/multiprocessing-autoconf/configure.in python/branches/multiprocessing-autoconf/pyconfig.h.in python/branches/multiprocessing-autoconf/setup.py Modified: python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py (original) +++ python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py Tue Mar 24 22:11:10 2009 @@ -1801,6 +1801,58 @@ multiprocessing.connection.answer_challenge, _FakeConnection(), b'abc') + def test_macros(self): + platform = sys.platform + if platform == "win32": + macros = dict( + ) + elif platform == 'darwin': # Mac OSX + macros = dict( + HAVE_SEM_OPEN=1, + HAVE_SEM_TIMEDWAIT=0, + HAVE_FD_TRANSFER=1, + HAVE_BROKEN_SEM_GETVALUE=1 + ) + elif platform == 'cygwin': # Cygwin + macros = dict( + HAVE_SEM_OPEN=1, + HAVE_SEM_TIMEDWAIT=1, + HAVE_FD_TRANSFER=0, + HAVE_BROKEN_SEM_UNLINK=1 + ) + elif platform in ('freebsd4', 'freebsd5', 'freebsd6', 'freebsd7', 'freebsd8'): + # FreeBSD's P1003.1b semaphore support is very experimental + # and has many known problems. (as of June 2008) + macros = dict( # FreeBSD + HAVE_SEM_OPEN=0, + HAVE_SEM_TIMEDWAIT=0, + HAVE_FD_TRANSFER=1, + ) + elif platform.startswith('openbsd'): + macros = dict( # OpenBSD + HAVE_SEM_OPEN=0, # Not implemented + HAVE_SEM_TIMEDWAIT=0, + HAVE_FD_TRANSFER=1, + ) + else: # Linux and other unices + macros = dict( + HAVE_SEM_OPEN=1, + HAVE_SEM_TIMEDWAIT=1, + HAVE_FD_TRANSFER=1 + ) + flags = ['HAVE_SEM_OPEN', 'HAVE_BROKEN_SEM_GETVALUE', + 'HAVE_FD_TRANSFER', 'HAVE_BROKEN_SEM_UNLINK', + 'HAVE_SEM_TIMEDWAIT'] + + for name in flags: + mp_flag = _multiprocessing.flags.get(name, 0) + plat_flag = macros.get(name, 0) + self.assertEqual(mp_flag, plat_flag, + "%s: expected %i, got %i" % + (name, mp_flag, plat_flag) + ) + + testcases_other = [OtherTest, TestInvalidHandle] # Modified: python/branches/multiprocessing-autoconf/configure ============================================================================== --- python/branches/multiprocessing-autoconf/configure (original) +++ python/branches/multiprocessing-autoconf/configure Tue Mar 24 22:11:10 2009 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 68312 . +# From configure.in Revision: 70479 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 2.7. # @@ -25187,6 +25187,224 @@ fi +### +# multiprocessing specific tests + +cat >>confdefs.h <<\_ACEOF +#define HAVE_BROKEN_SEM_UNLINK 0 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_BROKEN_SEM_GETVALUE 0 +_ACEOF + + +{ echo "$as_me:$LINENO: checking for sem_open" >&5 +echo $ECHO_N "checking for sem_open... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +void *x=sem_open + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SEM_OPEN 1 +_ACEOF + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >>confdefs.h <<\_ACEOF +#define HAVE_SEM_OPEN 0 +_ACEOF + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ echo "$as_me:$LINENO: checking for sem_timedwait" >&5 +echo $ECHO_N "checking for sem_timedwait... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +void *x=sem_timedwait + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SEM_TIMEDWAIT 1 +_ACEOF + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >>confdefs.h <<\_ACEOF +#define HAVE_SEM_TIMEDWAIT 0 +_ACEOF + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ echo "$as_me:$LINENO: checking for sendmsg (fd transfer)" >&5 +echo $ECHO_N "checking for sendmsg (fd transfer)... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +void *x; size_t s; struct msghdr msg; struct cmsghdr *cmsg; + x=sendmsg; + s = CMSG_SPACE(CMSG_LEN(sizeof(int))); + cmsg = CMSG_FIRSTHDR(&msg); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FD_TRANSFER 1 +_ACEOF + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >>confdefs.h <<\_ACEOF +#define HAVE_FD_TRANSFER 0. +_ACEOF + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +case $ac_sys_system/$ac_sys_release in + FreeBSD/4.*|FreeBSD/5.*|FreeBSD/6.*|FreeBSD/7.*|FreeBSD/8.*) + # FreeBSD's P1003.1b semaphore support is very experimental + # and has many known problems. (as of June 2008) + cat >>confdefs.h <<\_ACEOF +#define HAVE_SEM_OPEN 0 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define HAVE_SEM_TIMEDWAIT 0 +_ACEOF + + ;; +esac + +case $ac_sys_system in + CYGWIN*) + cat >>confdefs.h <<\_ACEOF +#define HAVE_BROKEN_SEM_UNLINK 1 +_ACEOF + + ;; + Darwin*) + cat >>confdefs.h <<\_ACEOF +#define HAVE_BROKEN_SEM_GETVALUE 1 +_ACEOF + + ;; +esac + +# end of multiprocessing +### + for h in `(cd $srcdir;echo Python/thread_*.h)` Modified: python/branches/multiprocessing-autoconf/configure.in ============================================================================== --- python/branches/multiprocessing-autoconf/configure.in (original) +++ python/branches/multiprocessing-autoconf/configure.in Tue Mar 24 22:11:10 2009 @@ -3766,6 +3766,61 @@ #endif ]) +### +# multiprocessing specific tests +AC_DEFINE(HAVE_BROKEN_SEM_UNLINK, 0, Define if 'sem_unlink' is broken on your platform) +AC_DEFINE(HAVE_BROKEN_SEM_GETVALUE, 0, Define if 'sem_getvalue' is broken on your platform) + +AC_MSG_CHECKING(for sem_open) +AC_TRY_COMPILE([#include ], void *x=sem_open, + AC_DEFINE(HAVE_SEM_OPEN, 1, Define if you have the 'sem_open' function.) + AC_MSG_RESULT(yes), + AC_DEFINE(HAVE_SEM_OPEN, 0) + AC_MSG_RESULT(no) +) + +AC_MSG_CHECKING(for sem_timedwait) +AC_TRY_COMPILE([#include ], void *x=sem_timedwait, + AC_DEFINE(HAVE_SEM_TIMEDWAIT, 1, Define if you have the 'sem_timedwait' function.) + AC_MSG_RESULT(yes), + AC_DEFINE(HAVE_SEM_TIMEDWAIT, 0) + AC_MSG_RESULT(no) +) + +AC_MSG_CHECKING(for sendmsg (fd transfer)) +AC_TRY_COMPILE([#include ], + void *x; size_t s; struct msghdr msg; struct cmsghdr *cmsg; + x=sendmsg; + s = CMSG_SPACE(CMSG_LEN(sizeof(int))); + cmsg = CMSG_FIRSTHDR(&msg); + , + AC_DEFINE(HAVE_FD_TRANSFER, 1, Define if you have the 'sendmsg' function for fd transfer.) + AC_MSG_RESULT(yes), + AC_DEFINE(HAVE_FD_TRANSFER, 0.) + AC_MSG_RESULT(no) +) + +case $ac_sys_system/$ac_sys_release in + FreeBSD/4.*|FreeBSD/5.*|FreeBSD/6.*|FreeBSD/7.*|FreeBSD/8.*) + # FreeBSD's P1003.1b semaphore support is very experimental + # and has many known problems. (as of June 2008) + AC_DEFINE(HAVE_SEM_OPEN, 0) + AC_DEFINE(HAVE_SEM_TIMEDWAIT, 0) + ;; +esac + +case $ac_sys_system in + CYGWIN*) + AC_DEFINE(HAVE_BROKEN_SEM_UNLINK, 1) + ;; + Darwin*) + AC_DEFINE(HAVE_BROKEN_SEM_GETVALUE, 1) + ;; +esac + +# end of multiprocessing +### + AC_SUBST(THREADHEADERS) for h in `(cd $srcdir;echo Python/thread_*.h)` Modified: python/branches/multiprocessing-autoconf/pyconfig.h.in ============================================================================== --- python/branches/multiprocessing-autoconf/pyconfig.h.in (original) +++ python/branches/multiprocessing-autoconf/pyconfig.h.in Tue Mar 24 22:11:10 2009 @@ -73,6 +73,12 @@ /* Define if pthread_sigmask() does not work on your system. */ #undef HAVE_BROKEN_PTHREAD_SIGMASK +/* Define if 'sem_getvalue' is broken on your platform */ +#undef HAVE_BROKEN_SEM_GETVALUE + +/* Define if 'sem_unlink' is broken on your platform */ +#undef HAVE_BROKEN_SEM_UNLINK + /* Define this if you have the type _Bool. */ #undef HAVE_C99_BOOL @@ -186,6 +192,9 @@ /* Define if you have the 'fdatasync' function. */ #undef HAVE_FDATASYNC +/* Define if you have the 'sendmsg' function for fd transfer. */ +#undef HAVE_FD_TRANSFER + /* Define to 1 if you have the `finite' function. */ #undef HAVE_FINITE @@ -504,6 +513,12 @@ /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT +/* Define if you have the 'sem_open' function. */ +#undef HAVE_SEM_OPEN + +/* Define if you have the 'sem_timedwait' function. */ +#undef HAVE_SEM_TIMEDWAIT + /* Define to 1 if you have the `setegid' function. */ #undef HAVE_SETEGID Modified: python/branches/multiprocessing-autoconf/setup.py ============================================================================== --- python/branches/multiprocessing-autoconf/setup.py (original) +++ python/branches/multiprocessing-autoconf/setup.py Tue Mar 24 22:11:10 2009 @@ -1240,55 +1240,11 @@ self.detect_ctypes(inc_dirs, lib_dirs) # Richard Oudkerk's multiprocessing module - if platform == 'win32': # Windows - macros = dict() - libraries = ['ws2_32'] - - elif platform == 'darwin': # Mac OSX - macros = dict( - HAVE_SEM_OPEN=1, - HAVE_SEM_TIMEDWAIT=0, - HAVE_FD_TRANSFER=1, - HAVE_BROKEN_SEM_GETVALUE=1 - ) - libraries = [] - - elif platform == 'cygwin': # Cygwin - macros = dict( - HAVE_SEM_OPEN=1, - HAVE_SEM_TIMEDWAIT=1, - HAVE_FD_TRANSFER=0, - HAVE_BROKEN_SEM_UNLINK=1 - ) - libraries = [] - - elif platform in ('freebsd4', 'freebsd5', 'freebsd6', 'freebsd7', 'freebsd8'): - # FreeBSD's P1003.1b semaphore support is very experimental - # and has many known problems. (as of June 2008) - macros = dict( # FreeBSD - HAVE_SEM_OPEN=0, - HAVE_SEM_TIMEDWAIT=0, - HAVE_FD_TRANSFER=1, - ) - libraries = [] - - elif platform.startswith('openbsd'): - macros = dict( # OpenBSD - HAVE_SEM_OPEN=0, # Not implemented - HAVE_SEM_TIMEDWAIT=0, - HAVE_FD_TRANSFER=1, - ) - libraries = [] - - else: # Linux and other unices - macros = dict( - HAVE_SEM_OPEN=1, - HAVE_SEM_TIMEDWAIT=1, - HAVE_FD_TRANSFER=1 - ) - libraries = ['rt'] + macros = {} + libraries = [] # some platforms may require 'rt' if platform == 'win32': + libraries = ['ws2_32'] multiprocessing_srcs = [ '_multiprocessing/multiprocessing.c', '_multiprocessing/semaphore.c', '_multiprocessing/pipe_connection.c', @@ -1301,7 +1257,7 @@ '_multiprocessing/socket_connection.c' ] - if macros.get('HAVE_SEM_OPEN', False): + if sysconfig.get_config_var("HAVE_SEM_OPEN"): multiprocessing_srcs.append('_multiprocessing/semaphore.c') if sysconfig.get_config_var('WITH_THREAD'): From nnorwitz at gmail.com Tue Mar 24 23:11:43 2009 From: nnorwitz at gmail.com (Neal Norwitz) Date: Tue, 24 Mar 2009 17:11:43 -0500 Subject: [Python-checkins] Python Regression Test Failures refleak (1) Message-ID: <20090324221143.GA14414@python.psfb.org> More important issues: ---------------------- test_softspace leaked [0, 0, -84] references, sum=-84 Less important issues: ---------------------- test_asynchat leaked [-125, 0, 131] references, sum=6 test_cmd_line leaked [25, -25, 0] references, sum=0 test_file leaked [0, 0, 69] references, sum=69 test_fileinput leaked [-69, 0, 0] references, sum=-69 test_smtplib leaked [0, -6, -82] references, sum=-88 test_socketserver leaked [0, 0, 84] references, sum=84 test_sys leaked [21, -21, 0] references, sum=0 test_urllib2_localnet leaked [3, 3, 3] references, sum=9 From buildbot at python.org Tue Mar 24 23:16:52 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 22:16:52 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090324221653.1EE381E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/762 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: The web-page 'force build' button was pressed by 'christian.heimes': test of new autoconf code Build Source Stamp: [branch branches/multiprocessing-autoconf] HEAD Blamelist: BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 24 23:23:38 2009 From: python-checkins at python.org (christian.heimes) Date: Tue, 24 Mar 2009 23:23:38 +0100 (CET) Subject: [Python-checkins] r70585 - python/branches/multiprocessing-autoconf/configure.in Message-ID: <20090324222338.18B941E4002@bag.python.org> Author: christian.heimes Date: Tue Mar 24 23:23:37 2009 New Revision: 70585 Log: Somehow a period got into my code ... Modified: python/branches/multiprocessing-autoconf/configure.in Modified: python/branches/multiprocessing-autoconf/configure.in ============================================================================== --- python/branches/multiprocessing-autoconf/configure.in (original) +++ python/branches/multiprocessing-autoconf/configure.in Tue Mar 24 23:23:37 2009 @@ -3796,7 +3796,7 @@ , AC_DEFINE(HAVE_FD_TRANSFER, 1, Define if you have the 'sendmsg' function for fd transfer.) AC_MSG_RESULT(yes), - AC_DEFINE(HAVE_FD_TRANSFER, 0.) + AC_DEFINE(HAVE_FD_TRANSFER, 0) AC_MSG_RESULT(no) ) From python-checkins at python.org Tue Mar 24 23:24:40 2009 From: python-checkins at python.org (christian.heimes) Date: Tue, 24 Mar 2009 23:24:40 +0100 (CET) Subject: [Python-checkins] r70586 - python/branches/multiprocessing-autoconf/configure Message-ID: <20090324222440.1EFA81E4002@bag.python.org> Author: christian.heimes Date: Tue Mar 24 23:24:39 2009 New Revision: 70586 Log: Autoreconf run Modified: python/branches/multiprocessing-autoconf/configure Modified: python/branches/multiprocessing-autoconf/configure ============================================================================== --- python/branches/multiprocessing-autoconf/configure (original) +++ python/branches/multiprocessing-autoconf/configure Tue Mar 24 23:24:39 2009 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 70479 . +# From configure.in Revision: 70585 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 2.7. # @@ -25362,7 +25362,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 cat >>confdefs.h <<\_ACEOF -#define HAVE_FD_TRANSFER 0. +#define HAVE_FD_TRANSFER 0 _ACEOF { echo "$as_me:$LINENO: result: no" >&5 From python-checkins at python.org Tue Mar 24 23:30:15 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 23:30:15 +0100 (CET) Subject: [Python-checkins] r70587 - in python/branches/py3k/Lib: linecache.py tokenize.py Message-ID: <20090324223015.455081E400C@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 23:30:15 2009 New Revision: 70587 Log: reuse tokenize.detect_encoding in linecache instead of a custom solution patch by Victor Stinner #4016 Modified: python/branches/py3k/Lib/linecache.py python/branches/py3k/Lib/tokenize.py Modified: python/branches/py3k/Lib/linecache.py ============================================================================== --- python/branches/py3k/Lib/linecache.py (original) +++ python/branches/py3k/Lib/linecache.py Tue Mar 24 23:30:15 2009 @@ -7,7 +7,7 @@ import sys import os -import re +import tokenize __all__ = ["getline", "clearcache", "checkcache"] @@ -120,27 +120,11 @@ pass else: # No luck -## print '*** Cannot stat', filename, ':', msg return [] -## print("Refreshing cache for %s..." % fullname) - try: - fp = open(fullname, 'rU') + with open(fullname, 'rb') as fp: + coding, line = tokenize.detect_encoding(fp.readline) + with open(fullname, 'r', encoding=coding) as fp: lines = fp.readlines() - fp.close() - except Exception as msg: -## print '*** Cannot open', fullname, ':', msg - return [] - coding = "utf-8" - for line in lines[:2]: - m = re.search(r"coding[:=]\s*([-\w.]+)", line) - if m: - coding = m.group(1) - break - try: - lines = [line if isinstance(line, str) else str(line, coding) - for line in lines] - except: - pass # Hope for the best size, mtime = stat.st_size, stat.st_mtime cache[filename] = size, mtime, lines, fullname return lines Modified: python/branches/py3k/Lib/tokenize.py ============================================================================== --- python/branches/py3k/Lib/tokenize.py (original) +++ python/branches/py3k/Lib/tokenize.py Tue Mar 24 23:30:15 2009 @@ -27,7 +27,6 @@ import re, string, sys from token import * from codecs import lookup, BOM_UTF8 -from itertools import chain, repeat cookie_re = re.compile("coding[:=]\s*([-\w.]+)") import token @@ -327,13 +326,15 @@ which tells you which encoding was used to decode the bytes stream. """ encoding, consumed = detect_encoding(readline) - def readline_generator(): + def readline_generator(consumed): + for line in consumed: + yield line while True: try: yield readline() except StopIteration: return - chained = chain(consumed, readline_generator()) + chained = readline_generator(consumed) return _tokenize(chained.__next__, encoding) From python-checkins at python.org Tue Mar 24 23:56:33 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 24 Mar 2009 23:56:33 +0100 (CET) Subject: [Python-checkins] r70588 - python/trunk/Lib/unittest.py Message-ID: <20090324225633.293C51E400C@bag.python.org> Author: benjamin.peterson Date: Tue Mar 24 23:56:32 2009 New Revision: 70588 Log: fix newline issue in test summary Modified: python/trunk/Lib/unittest.py Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Tue Mar 24 23:56:32 2009 @@ -943,7 +943,7 @@ if errored: infos.append("errors=%d" % errored) else: - self.stream.writeln("OK") + self.stream.write("OK") if skipped: infos.append("skipped=%d" % skipped) if expectedFails: @@ -952,6 +952,8 @@ infos.append("unexpected successes=%d" % unexpectedSuccesses) if infos: self.stream.writeln(" (%s)" % (", ".join(infos),)) + else: + self.stream.write("\n") return result From python-checkins at python.org Wed Mar 25 00:07:08 2009 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 25 Mar 2009 00:07:08 +0100 (CET) Subject: [Python-checkins] r70589 - python/trunk/Lib/unittest.py Message-ID: <20090324230708.4BAD11E4002@bag.python.org> Author: benjamin.peterson Date: Wed Mar 25 00:07:07 2009 New Revision: 70589 Log: another style nit Modified: python/trunk/Lib/unittest.py Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Wed Mar 25 00:07:07 2009 @@ -809,7 +809,8 @@ return getattr(self.stream,attr) def writeln(self, arg=None): - if arg: self.write(arg) + if arg: + self.write(arg) self.write('\n') # text-mode streams translate to \r\n if needed From buildbot at python.org Wed Mar 25 00:26:06 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 24 Mar 2009 23:26:06 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo trunk Message-ID: <20090324232606.C325B1E4002@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%20gentoo%20trunk/builds/4771 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Killed sincerely, -The Buildbot From buildbot at python.org Wed Mar 25 01:37:39 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Mar 2009 00:37:39 +0000 Subject: [Python-checkins] buildbot failure in x86 XP-4 trunk Message-ID: <20090325003739.DA5D41E4002@bag.python.org> The Buildbot has detected a new failure of x86 XP-4 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20XP-4%20trunk/builds/1982 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: bolen-windows Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From python-checkins at python.org Wed Mar 25 01:52:11 2009 From: python-checkins at python.org (skip.montanaro) Date: Wed, 25 Mar 2009 01:52:11 +0100 (CET) Subject: [Python-checkins] r70590 - python/trunk/Doc/library/csv.rst Message-ID: <20090325005211.A7EDA1E4002@bag.python.org> Author: skip.montanaro Date: Wed Mar 25 01:52:11 2009 New Revision: 70590 Log: clarify the type of data returned Modified: python/trunk/Doc/library/csv.rst Modified: python/trunk/Doc/library/csv.rst ============================================================================== --- python/trunk/Doc/library/csv.rst (original) +++ python/trunk/Doc/library/csv.rst Wed Mar 25 01:52:11 2009 @@ -72,8 +72,8 @@ dialect. For full details about the dialect and formatting parameters, see section :ref:`csv-fmt-params`. - All data read are returned as strings. No automatic data type conversion is - performed. + Each row read from the csv file is returned as a list of strings. No + automatic data type conversion is performed. A short usage example:: From python-checkins at python.org Wed Mar 25 01:52:18 2009 From: python-checkins at python.org (skip.montanaro) Date: Wed, 25 Mar 2009 01:52:18 +0100 (CET) Subject: [Python-checkins] r70591 - python/branches/py3k/Doc/library/csv.rst Message-ID: <20090325005218.DE0211E4002@bag.python.org> Author: skip.montanaro Date: Wed Mar 25 01:52:18 2009 New Revision: 70591 Log: clarify the type of data returned Modified: python/branches/py3k/Doc/library/csv.rst Modified: python/branches/py3k/Doc/library/csv.rst ============================================================================== --- python/branches/py3k/Doc/library/csv.rst (original) +++ python/branches/py3k/Doc/library/csv.rst Wed Mar 25 01:52:18 2009 @@ -70,8 +70,8 @@ dialect. For full details about the dialect and formatting parameters, see section :ref:`csv-fmt-params`. - All data read are returned as strings. No automatic data type conversion is - performed. + Each row read from the csv file is returned as a list of strings. No + automatic data type conversion is performed. The parser is quite strict with respect to multi-line quoted fields. Previously, if a line ended within a quoted field without a terminating newline character, a From python-checkins at python.org Wed Mar 25 02:21:17 2009 From: python-checkins at python.org (christian.heimes) Date: Wed, 25 Mar 2009 02:21:17 +0100 (CET) Subject: [Python-checkins] r70592 - in python/branches/multiprocessing-autoconf: Lib/test/test_multiprocessing.py configure configure.in Message-ID: <20090325012117.BF29D1E401E@bag.python.org> Author: christian.heimes Date: Wed Mar 25 02:21:17 2009 New Revision: 70592 Log: Added more debugging code to see why the tests aren't working on *BSD Modified: python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py python/branches/multiprocessing-autoconf/configure python/branches/multiprocessing-autoconf/configure.in Modified: python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py (original) +++ python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py Wed Mar 25 02:21:17 2009 @@ -1801,7 +1801,7 @@ multiprocessing.connection.answer_challenge, _FakeConnection(), b'abc') - def test_macros(self): + def test_000macros(self): platform = sys.platform if platform == "win32": macros = dict( @@ -1881,10 +1881,10 @@ ManagerMixin.pool = ManagerMixin.manager.Pool(4) testcases = ( + testcases_other + sorted(testcases_processes.values(), key=lambda tc:tc.__name__) + sorted(testcases_threads.values(), key=lambda tc:tc.__name__) + sorted(testcases_manager.values(), key=lambda tc:tc.__name__) + - testcases_other ) loadTestsFromTestCase = unittest.defaultTestLoader.loadTestsFromTestCase Modified: python/branches/multiprocessing-autoconf/configure ============================================================================== --- python/branches/multiprocessing-autoconf/configure (original) +++ python/branches/multiprocessing-autoconf/configure Wed Mar 25 02:21:17 2009 @@ -25384,6 +25384,8 @@ #define HAVE_SEM_TIMEDWAIT 0 _ACEOF + { echo "$as_me:$LINENO: disable sem_open and sem_timedwait on *BSD" >&5 +echo "$as_me: disable sem_open and sem_timedwait on *BSD" >&6;} ;; esac @@ -25393,12 +25395,16 @@ #define HAVE_BROKEN_SEM_UNLINK 1 _ACEOF + { echo "$as_me:$LINENO: Cygwin has broken sem_unlink" >&5 +echo "$as_me: Cygwin has broken sem_unlink" >&6;} ;; Darwin*) cat >>confdefs.h <<\_ACEOF #define HAVE_BROKEN_SEM_GETVALUE 1 _ACEOF + { echo "$as_me:$LINENO: Darwin has broken sem_getvalue" >&5 +echo "$as_me: Darwin has broken sem_getvalue" >&6;} ;; esac Modified: python/branches/multiprocessing-autoconf/configure.in ============================================================================== --- python/branches/multiprocessing-autoconf/configure.in (original) +++ python/branches/multiprocessing-autoconf/configure.in Wed Mar 25 02:21:17 2009 @@ -3805,16 +3805,19 @@ # FreeBSD's P1003.1b semaphore support is very experimental # and has many known problems. (as of June 2008) AC_DEFINE(HAVE_SEM_OPEN, 0) - AC_DEFINE(HAVE_SEM_TIMEDWAIT, 0) + AC_DEFINE(HAVE_SEM_TIMEDWAIT, 0) + AC_MSG_NOTICE([disable sem_open and sem_timedwait on *BSD]) ;; esac case $ac_sys_system in CYGWIN*) AC_DEFINE(HAVE_BROKEN_SEM_UNLINK, 1) + AC_MSG_NOTICE([Cygwin has broken sem_unlink]) ;; Darwin*) AC_DEFINE(HAVE_BROKEN_SEM_GETVALUE, 1) + AC_MSG_NOTICE([Darwin has broken sem_getvalue]) ;; esac From buildbot at python.org Wed Mar 25 03:15:41 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Mar 2009 02:15:41 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090325021541.5C0101E403B@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/767 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: The web-page 'force build' button was pressed by 'christian.heimes': test of new autoconf code, third try Build Source Stamp: [branch branches/multiprocessing-autoconf] HEAD Blamelist: BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_compiler test_multiprocessing ====================================================================== ERROR: testCompileLibrary (test.test_compiler.CompilerTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_compiler.py", line 53, in testCompileLibrary compiler.compile(buf, basename, "exec") File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/compiler/pycodegen.py", line 65, in compile gen.compile() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/compiler/pycodegen.py", line 112, in compile tree = self._get_tree() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/compiler/pycodegen.py", line 78, in _get_tree tree = parse(self.source, self.mode) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/compiler/transformer.py", line 51, in parse return Transformer().parsesuite(buf) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/compiler/transformer.py", line 128, in parsesuite return self.transform(parser.suite(text)) SyntaxError: invalid syntax (line 1888) Traceback (most recent call last): File "./Lib/test/regrtest.py", line 551, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_multiprocessing.py", line 1888 ) ^ SyntaxError: invalid syntax [691007 refs] make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Wed Mar 25 08:24:17 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Mar 2009 07:24:17 +0000 Subject: [Python-checkins] buildbot failure in OS X x86 trunk Message-ID: <20090325072417.54FB01E4002@bag.python.org> The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/260 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: The web-page 'rebuild' button was pressed by '': Build Source Stamp: [branch trunk] HEAD Blamelist: antoine.pitrou,benjamin.peterson,bob.ippolito,hirokazu.yamamoto,lars.gustaebel,mark.dickinson,matthias.klose,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_zipimport_support make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Wed Mar 25 08:51:58 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Mar 2009 07:51:58 +0000 Subject: [Python-checkins] buildbot failure in OS X x86 trunk Message-ID: <20090325075158.6C57D1E4002@bag.python.org> The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/262 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: The web-page 'force build' button was pressed by 'christian.heimes': test of new autoconf code, third try Build Source Stamp: [branch branches/multiprocessing-autoconf] HEAD Blamelist: BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_compiler test_multiprocessing ====================================================================== ERROR: testCompileLibrary (test.test_compiler.CompilerTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/test/test_compiler.py", line 53, in testCompileLibrary compiler.compile(buf, basename, "exec") File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/compiler/pycodegen.py", line 65, in compile gen.compile() File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/compiler/pycodegen.py", line 112, in compile tree = self._get_tree() File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/compiler/pycodegen.py", line 78, in _get_tree tree = parse(self.source, self.mode) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/compiler/transformer.py", line 51, in parse return Transformer().parsesuite(buf) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/compiler/transformer.py", line 128, in parsesuite return self.transform(parser.suite(text)) SyntaxError: invalid syntax (line 1888) Traceback (most recent call last): File "./Lib/test/regrtest.py", line 551, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/test/test_multiprocessing.py", line 1888 ) ^ SyntaxError: invalid syntax [708214 refs] make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Mar 25 11:59:04 2009 From: python-checkins at python.org (christian.heimes) Date: Wed, 25 Mar 2009 11:59:04 +0100 (CET) Subject: [Python-checkins] r70593 - python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py Message-ID: <20090325105904.E262B1E4002@bag.python.org> Author: christian.heimes Date: Wed Mar 25 11:59:04 2009 New Revision: 70593 Log: No more coding after 2am for me Modified: python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py Modified: python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py (original) +++ python/branches/multiprocessing-autoconf/Lib/test/test_multiprocessing.py Wed Mar 25 11:59:04 2009 @@ -1884,7 +1884,7 @@ testcases_other + sorted(testcases_processes.values(), key=lambda tc:tc.__name__) + sorted(testcases_threads.values(), key=lambda tc:tc.__name__) + - sorted(testcases_manager.values(), key=lambda tc:tc.__name__) + + sorted(testcases_manager.values(), key=lambda tc:tc.__name__) ) loadTestsFromTestCase = unittest.defaultTestLoader.loadTestsFromTestCase From buildbot at python.org Wed Mar 25 12:57:06 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Mar 2009 11:57:06 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090325115707.6DC351E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/226 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: The web-page 'force build' button was pressed by 'christian.heimes': another test of mp autoconf Build Source Stamp: [branch branches/multiprocessing-autoconf] HEAD Blamelist: BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 270, in test_getcwd_long_pathnames shutil.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 27, in tearDown os.unlink(test_support.TESTFN) OSError: [Errno 2] No such file or directory: '@test' sincerely, -The Buildbot From python-checkins at python.org Wed Mar 25 20:44:59 2009 From: python-checkins at python.org (marc-andre.lemburg) Date: Wed, 25 Mar 2009 20:44:59 +0100 (CET) Subject: [Python-checkins] r70594 - in python/trunk/Lib: platform.py test/test_platform.py Message-ID: <20090325194459.3C2561E4002@bag.python.org> Author: marc-andre.lemburg Date: Wed Mar 25 20:44:58 2009 New Revision: 70594 Log: Remove the sys.version_info shortcut, since they cause the APIs to return different information than the _sys_version() output used in previous Python versions. This also fixes issue5561: platform.python_version_tuple returns tuple of ints, should be strings Added more tests for the various platform functions. Modified: python/trunk/Lib/platform.py python/trunk/Lib/test/test_platform.py Modified: python/trunk/Lib/platform.py ============================================================================== --- python/trunk/Lib/platform.py (original) +++ python/trunk/Lib/platform.py Wed Mar 25 20:44:58 2009 @@ -1278,10 +1278,10 @@ def _sys_version(sys_version=None): """ Returns a parsed version of Python's sys.version as tuple - (name, version, branch, revision, buildno, builddate, compiler) - referring to the Python implementation name, version, branch, - revision, build number, build date/time as string and the compiler - identification string. + (name, version, branch, revision, buildno, builddate, compiler) + referring to the Python implementation name, version, branch, + revision, build number, build date/time as string and the compiler + identification string. Note that unlike the Python sys.version, the returned value for the Python version will always include the patchlevel (it @@ -1383,8 +1383,6 @@ will always include the patchlevel (it defaults to 0). """ - if hasattr(sys, 'version_info'): - return '%i.%i.%i' % sys.version_info[:3] return _sys_version()[1] def python_version_tuple(): @@ -1396,8 +1394,6 @@ will always include the patchlevel (it defaults to 0). """ - if hasattr(sys, 'version_info'): - return sys.version_info[:3] return tuple(string.split(_sys_version()[1], '.')) def python_branch(): Modified: python/trunk/Lib/test/test_platform.py ============================================================================== --- python/trunk/Lib/test/test_platform.py (original) +++ python/trunk/Lib/test/test_platform.py Wed Mar 25 20:44:58 2009 @@ -25,39 +25,48 @@ finally: os.remove(link) - def test_machine(self): - res = platform.machine() - - def test_node(self): - res = platform.node() - def test_platform(self): for aliased in (False, True): for terse in (False, True): res = platform.platform(aliased, terse) - def test_processor(self): - res = platform.processor() + def test_system(self): + res = platform.system() - def test_python_build(self): - res = platform.python_build() + def test_node(self): + res = platform.node() - def test_python_compiler(self): - res = platform.python_compiler() + def test_release(self): + res = platform.release() def test_version(self): - res1 = platform.version() - res2 = platform.version_tuple() + res = platform.version() + + def test_machine(self): + res = platform.machine() + + def test_processor(self): + res = platform.processor() + + def test_python_implementation(self): + res = platform.python_implementation() + + def test_python_version(self): + res1 = platform.python_version() + res2 = platform.python_version_tuple() self.assertEqual(res1, ".".join(res2)) - def test_release(self): - res = platform.release() + def test_python_branch(self): + res = platform.python_branch() - def test_system(self): - res = platform.system() + def test_python_revision(self): + res = platform.python_revision() - def test_version(self): - res = platform.version() + def test_python_build(self): + res = platform.python_build() + + def test_python_compiler(self): + res = platform.python_compiler() def test_system_alias(self): res = platform.system_alias( From python-checkins at python.org Wed Mar 25 20:45:33 2009 From: python-checkins at python.org (marc-andre.lemburg) Date: Wed, 25 Mar 2009 20:45:33 +0100 (CET) Subject: [Python-checkins] r70595 - python/trunk/Misc/NEWS Message-ID: <20090325194533.683241E4002@bag.python.org> Author: marc-andre.lemburg Date: Wed Mar 25 20:45:33 2009 New Revision: 70595 Log: News item for the platform.py fix (r70594). Modified: python/trunk/Misc/NEWS Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Wed Mar 25 20:45:33 2009 @@ -197,6 +197,10 @@ Library ------- +- Issue #5561: Removed the sys.version_info shortcuts from platform's + python_version() and python_version_tuple() since they produced different + output compared to previous Python versions. + - Issue #1034053: unittest now supports skipping tests and expected failures. - Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop From python-checkins at python.org Wed Mar 25 20:52:04 2009 From: python-checkins at python.org (marc-andre.lemburg) Date: Wed, 25 Mar 2009 20:52:04 +0100 (CET) Subject: [Python-checkins] r70596 - in python/branches/release26-maint: Lib/platform.py Lib/test/test_platform.py Misc/NEWS Message-ID: <20090325195204.5F1921E4002@bag.python.org> Author: marc-andre.lemburg Date: Wed Mar 25 20:52:04 2009 New Revision: 70596 Log: Merged revisions 70594-70595 via svnmerge from svn+pythonssh://pythondev at svn.python.org/python/trunk ........ r70594 | marc-andre.lemburg | 2009-03-25 20:44:58 +0100 (Wed, 25 Mar 2009) | 9 lines Remove the sys.version_info shortcut, since they cause the APIs to return different information than the _sys_version() output used in previous Python versions. This also fixes issue5561: platform.python_version_tuple returns tuple of ints, should be strings Added more tests for the various platform functions. ........ r70595 | marc-andre.lemburg | 2009-03-25 20:45:33 +0100 (Wed, 25 Mar 2009) | 3 lines News item for the platform.py fix (r70594). ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/platform.py python/branches/release26-maint/Lib/test/test_platform.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/platform.py ============================================================================== --- python/branches/release26-maint/Lib/platform.py (original) +++ python/branches/release26-maint/Lib/platform.py Wed Mar 25 20:52:04 2009 @@ -1296,10 +1296,10 @@ def _sys_version(sys_version=None): """ Returns a parsed version of Python's sys.version as tuple - (name, version, branch, revision, buildno, builddate, compiler) - referring to the Python implementation name, version, branch, - revision, build number, build date/time as string and the compiler - identification string. + (name, version, branch, revision, buildno, builddate, compiler) + referring to the Python implementation name, version, branch, + revision, build number, build date/time as string and the compiler + identification string. Note that unlike the Python sys.version, the returned value for the Python version will always include the patchlevel (it @@ -1416,8 +1416,6 @@ will always include the patchlevel (it defaults to 0). """ - if hasattr(sys, 'version_info'): - return '%i.%i.%i' % sys.version_info[:3] return _sys_version()[1] def python_version_tuple(): @@ -1429,8 +1427,6 @@ will always include the patchlevel (it defaults to 0). """ - if hasattr(sys, 'version_info'): - return sys.version_info[:3] return tuple(string.split(_sys_version()[1], '.')) def python_branch(): Modified: python/branches/release26-maint/Lib/test/test_platform.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_platform.py (original) +++ python/branches/release26-maint/Lib/test/test_platform.py Wed Mar 25 20:52:04 2009 @@ -25,39 +25,48 @@ finally: os.remove(link) - def test_machine(self): - res = platform.machine() - - def test_node(self): - res = platform.node() - def test_platform(self): for aliased in (False, True): for terse in (False, True): res = platform.platform(aliased, terse) - def test_processor(self): - res = platform.processor() + def test_system(self): + res = platform.system() - def test_python_build(self): - res = platform.python_build() + def test_node(self): + res = platform.node() - def test_python_compiler(self): - res = platform.python_compiler() + def test_release(self): + res = platform.release() def test_version(self): - res1 = platform.version() - res2 = platform.version_tuple() + res = platform.version() + + def test_machine(self): + res = platform.machine() + + def test_processor(self): + res = platform.processor() + + def test_python_implementation(self): + res = platform.python_implementation() + + def test_python_version(self): + res1 = platform.python_version() + res2 = platform.python_version_tuple() self.assertEqual(res1, ".".join(res2)) - def test_release(self): - res = platform.release() + def test_python_branch(self): + res = platform.python_branch() - def test_system(self): - res = platform.system() + def test_python_revision(self): + res = platform.python_revision() - def test_version(self): - res = platform.version() + def test_python_build(self): + res = platform.python_build() + + def test_python_compiler(self): + res = platform.python_compiler() def test_system_alias(self): res = platform.system_alias( Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Wed Mar 25 20:52:04 2009 @@ -92,6 +92,10 @@ Library ------- +- Issue #5561: Removed the sys.version_info shortcuts from platform's + python_version() and python_version_tuple() since they produced different + output compared to previous Python versions. + - Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop forever on incomplete input. That caused tarfile.open() to hang when used with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or From buildbot at python.org Wed Mar 25 21:37:09 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Mar 2009 20:37:09 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu trunk Message-ID: <20090325203709.DE6BB1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%20trunk/builds/1149 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: marc-andre.lemburg,skip.montanaro BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_ssl.py", line 278, in run elif not self.wrap_conn(): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_ssl.py", line 241, in wrap_conn str(self.sock.getpeername()) + ":\n") File "", line 1, in getpeername error: [Errno 9] Bad file descriptor 1 test failed: test_ssl make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Wed Mar 25 22:17:23 2009 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 25 Mar 2009 22:17:23 +0100 (CET) Subject: [Python-checkins] r70597 - sandbox/trunk/2to3/HACKING Message-ID: <20090325211723.33F781E4002@bag.python.org> Author: benjamin.peterson Date: Wed Mar 25 22:17:22 2009 New Revision: 70597 Log: I thought of another idea Modified: sandbox/trunk/2to3/HACKING Modified: sandbox/trunk/2to3/HACKING ============================================================================== --- sandbox/trunk/2to3/HACKING (original) +++ sandbox/trunk/2to3/HACKING Wed Mar 25 22:17:22 2009 @@ -43,3 +43,7 @@ * Remove the need to explicitly assign a node's parent attribute. This could be gone with a magic children list. + + * Import statements are complicated and a pain to handle, and there are many + fixers that manipulate them. It would be nice to have a little API for + manipulating imports in fixers. From python-checkins at python.org Wed Mar 25 22:24:04 2009 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 25 Mar 2009 22:24:04 +0100 (CET) Subject: [Python-checkins] r70598 - python/trunk/Lib/unittest.py Message-ID: <20090325212404.52B331E4012@bag.python.org> Author: benjamin.peterson Date: Wed Mar 25 22:24:04 2009 New Revision: 70598 Log: add shorthands for expected failures and unexpected success Modified: python/trunk/Lib/unittest.py Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Wed Mar 25 22:24:04 2009 @@ -879,7 +879,7 @@ if self.showAll: self.stream.writeln("expected failure") elif self.dots: - self.stream.write(".") + self.stream.write("x") self.stream.flush() def addUnexpectedSuccess(self, test): @@ -887,7 +887,7 @@ if self.showAll: self.stream.writeln("unexpected success") elif self.dots: - self.stream.write(".") + self.stream.write("u") self.stream.flush() def printErrors(self): From buildbot at python.org Wed Mar 25 22:37:30 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Mar 2009 21:37:30 +0000 Subject: [Python-checkins] buildbot failure in x86 XP-4 trunk Message-ID: <20090325213731.1B60F1E4002@bag.python.org> The Buildbot has detected a new failure of x86 XP-4 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20XP-4%20trunk/builds/1984 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: bolen-windows Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: marc-andre.lemburg,skip.montanaro BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 ====================================================================== FAIL: test01_basic_replication (bsddb.test.test_replication.DBBaseReplication) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\trunk.bolen-windows\build\lib\bsddb\test\test_replication.py", line 315, in test01_basic_replication self.assertTrue(time.time() The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/264 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Abort trap sincerely, -The Buildbot From python-checkins at python.org Wed Mar 25 22:42:51 2009 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 25 Mar 2009 22:42:51 +0100 (CET) Subject: [Python-checkins] r70599 - python/trunk/Lib/test/test_support.py Message-ID: <20090325214251.CBEEF1E4002@bag.python.org> Author: benjamin.peterson Date: Wed Mar 25 22:42:51 2009 New Revision: 70599 Log: this can be slightly less ugly Modified: python/trunk/Lib/test/test_support.py Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Wed Mar 25 22:42:51 2009 @@ -123,7 +123,7 @@ possibility of False being returned occurs when regrtest.py is executing.""" # see if the caller's module is __main__ - if so, treat as if # the resource was set - if sys._getframe().f_back.f_globals.get("__name__") == "__main__": + if sys._getframe(1).f_globals.get("__name__") == "__main__": return if not is_resource_enabled(resource): if msg is None: From python-checkins at python.org Wed Mar 25 22:50:44 2009 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 25 Mar 2009 22:50:44 +0100 (CET) Subject: [Python-checkins] r70600 - python/branches/py3k/Doc/reference/simple_stmts.rst Message-ID: <20090325215044.08BE01E4002@bag.python.org> Author: benjamin.peterson Date: Wed Mar 25 22:50:43 2009 New Revision: 70600 Log: wild card import is only allowed at the module level Modified: python/branches/py3k/Doc/reference/simple_stmts.rst Modified: python/branches/py3k/Doc/reference/simple_stmts.rst ============================================================================== --- python/branches/py3k/Doc/reference/simple_stmts.rst (original) +++ python/branches/py3k/Doc/reference/simple_stmts.rst Wed Mar 25 22:50:43 2009 @@ -794,10 +794,10 @@ accidentally exporting items that are not part of the API (such as library modules which were imported and used within the module). -The :keyword:`from` form with ``*`` may only occur in a module scope. If the -wild card form of import --- ``import *`` --- is used in a function and the -function contains or is a nested block with free variables, the compiler will -raise a :exc:`SyntaxError`. +The :keyword:`from` form with ``*`` may only occur in a module scope. The wild +card form of import --- ``import *`` --- is only allowed at the module level. +Attempting to use it in class for function definitions will raise a +:exc:`SyntaxError`. .. index:: single: relative; import From python-checkins at python.org Wed Mar 25 23:41:32 2009 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 25 Mar 2009 23:41:32 +0100 (CET) Subject: [Python-checkins] r70601 - python/trunk/Lib/collections.py Message-ID: <20090325224132.A7F521E4002@bag.python.org> Author: raymond.hettinger Date: Wed Mar 25 23:41:32 2009 New Revision: 70601 Log: Separate initialization from clearing. Modified: python/trunk/Lib/collections.py Modified: python/trunk/Lib/collections.py ============================================================================== --- python/trunk/Lib/collections.py (original) +++ python/trunk/Lib/collections.py Wed Mar 25 23:41:32 2009 @@ -41,14 +41,15 @@ try: self.__root except AttributeError: - self.__root = _Link() # sentinel node for the doubly linked list - self.clear() + self.__root = root = _Link() # sentinel node for the doubly linked list + root.prev = root.next = root + self.__map = {} self.update(*args, **kwds) def clear(self): root = self.__root root.prev = root.next = root - self.__map = {} + self.__map.clear() dict.clear(self) def __setitem__(self, key, value): From python-checkins at python.org Wed Mar 25 23:45:23 2009 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 25 Mar 2009 23:45:23 +0100 (CET) Subject: [Python-checkins] r70602 - python/branches/py3k/Lib/collections.py Message-ID: <20090325224523.115E81E400C@bag.python.org> Author: raymond.hettinger Date: Wed Mar 25 23:45:22 2009 New Revision: 70602 Log: Separate initialization from clearing. Modified: python/branches/py3k/Lib/collections.py Modified: python/branches/py3k/Lib/collections.py ============================================================================== --- python/branches/py3k/Lib/collections.py (original) +++ python/branches/py3k/Lib/collections.py Wed Mar 25 23:45:22 2009 @@ -41,14 +41,15 @@ try: self.__root except AttributeError: - self.__root = _Link() # sentinel node for the doubly linked list - self.clear() + self.__root = root = _Link() # sentinel node for the doubly linked list + root.prev = root.next = root + self.__map = {} self.update(*args, **kwds) def clear(self): root = self.__root root.prev = root.next = root - self.__map = {} + self.__map.clear() dict.clear(self) def __setitem__(self, key, value): From buildbot at python.org Thu Mar 26 00:02:36 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Mar 2009 23:02:36 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu trunk Message-ID: <20090325230236.A151B1E400C@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%20trunk/builds/1151 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/threading.py", line 477, in run self.__target(*self.__args, **self.__kwargs) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/bsddb/test/test_thread.py", line 306, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/bsddb/dbutils.py", line 68, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30994, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') 1 test failed: test_userstring ====================================================================== ERROR: test___contains__ (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 945, in test___contains__ self.checkequal(True, '', '__contains__', '') # vereq('' in '', True) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_capitalize (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 93, in test_capitalize self.checkequal(' hello ', ' hello ', 'capitalize') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_center (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 530, in test_center self.checkequal(' abc ', 'abc', 'center', 10) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_count (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 102, in test_count self.checkequal(3, 'aaa', 'count', 'a') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_delitem (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 63, in test_delitem s = self.type2test("foo") TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_delslice (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 85, in test_delslice s = self.type2test("foobar") TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_encoding_decoding (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 1194, in test_encoding_decoding self.checkequal(data, 'hello world', 'encode', encoding) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_endswith (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 896, in test_endswith self.checkequal(True, 'hello', 'endswith', 'lo') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_expandtabs (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 287, in test_expandtabs self.checkequal('abc\rab def\ng hi', 'abc\rab\tdef\ng\thi', 'expandtabs') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_extended_getslice (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 989, in test_extended_getslice slice(start, stop, step)) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_extended_set_del_slice (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 99, in test_extended_set_del_slice s = self.type2test(orig) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_find (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 162, in test_find self.checkequal(0, 'abcdefghiabc', 'find', 'abc') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_floatformatting (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 1100, in test_floatformatting self.checkcall(format, "__mod__", value) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 42, in checkcall object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_formatting (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 1043, in test_formatting self.checkequal('+hello+', '+%s+', '__mod__', 'hello') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_iadd (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 120, in test_iadd s = self.type2test("foo") TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_immutable (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 114, in test_immutable s = self.type2test("foobar") TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_imul (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 129, in test_imul s = self.type2test("foo") TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_index (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 234, in test_index self.checkequal(0, 'abcdefghiabc', 'index', '') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_inplace_rewrites (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 1104, in test_inplace_rewrites self.checkequal('a', 'A', 'lower') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_isalnum (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 811, in test_isalnum self.checkequal(False, '', 'isalnum') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_isalpha (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 801, in test_isalpha self.checkequal(False, '', 'isalpha') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_isdigit (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 822, in test_isdigit self.checkequal(False, '', 'isdigit') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_islower (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 756, in test_islower self.checkequal(False, '', 'islower') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_isspace (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 790, in test_isspace self.checkequal(False, '', 'isspace') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_istitle (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 776, in test_istitle self.checkequal(False, '', 'istitle') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_isupper (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 766, in test_isupper self.checkequal(False, '', 'isupper') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_join (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 1007, in test_join self.checkequal('a b c d', ' ', 'join', ['a', 'b', 'c', 'd']) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_ljust (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 514, in test_ljust self.checkequal('abc ', 'abc', 'ljust', 10) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_lower (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 277, in test_lower self.checkequal('hello', 'HeLLo', 'lower') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_mul (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 992, in test_mul self.checkequal('', 'abc', '__mul__', -1) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_partition (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 1124, in test_partition 'this is the partition method', 'partition', 'ti') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 39, in fixtype return tuple([self.fixtype(x) for x in obj]) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_replace (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 546, in test_replace EQ("", "", "replace", "", "") File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_rfind (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 214, in test_rfind self.checkequal(9, 'abcdefghiabc', 'rfind', 'abc') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_rindex (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 255, in test_rindex self.checkequal(12, 'abcdefghiabc', 'rindex', '') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_rjust (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 522, in test_rjust self.checkequal(' abc', 'abc', 'rjust', 10) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_rpartition (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 1142, in test_rpartition 'this is the rpartition method', 'rpartition', 'ti') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 39, in fixtype return tuple([self.fixtype(x) for x in obj]) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_rsplit (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 391, in test_rsplit 'this is the rsplit function', 'rsplit') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 37, in fixtype return [self.fixtype(x) for x in obj] File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_setitem (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 54, in test_setitem s = self.type2test("foo") TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_setslice (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 74, in test_setslice s = self.type2test("foo") TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_slice (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 967, in test_slice self.checkequal('abc', 'abc', '__getslice__', 0, 1000) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_split (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 304, in test_split 'this is the split function', 'split') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 37, in fixtype return [self.fixtype(x) for x in obj] File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_splitlines (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 840, in test_splitlines self.checkequal(['abc', 'def', '', 'ghi'], "abc\ndef\n\rghi", 'splitlines') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 37, in fixtype return [self.fixtype(x) for x in obj] File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_startswith (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 851, in test_startswith self.checkequal(True, 'hello', 'startswith', 'he') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_strip (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 480, in test_strip self.checkequal('hello', ' hello ', 'strip') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_subscript (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 956, in test_subscript self.checkequal(u'a', 'abc', '__getitem__', 0) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 24, in checkequal object = self.fixtype(object) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_swapcase (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 538, in test_swapcase self.checkequal('hEllO CoMPuTErS', 'HeLLo cOmpUteRs', 'swapcase') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_title (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 831, in test_title self.checkequal(' Hello ', ' hello ', 'title') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_translate (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 1170, in test_translate self.checkequal('xyzxyz', 'xyzabcdef', 'translate', table, 'def') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_upper (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 282, in test_upper self.checkequal('HELLO', 'HeLLo', 'upper') File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert ====================================================================== ERROR: test_zfill (test.test_userstring.MutableStringTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 732, in test_zfill self.checkequal('123', '123', 'zfill', 2) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_userstring.py", line 23, in checkequal result = self.fixtype(result) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/string_tests.py", line 35, in fixtype return self.__class__.type2test(obj) TypeError: Can't instantiate abstract class MutableString with abstract methods insert make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Mar 26 00:31:22 2009 From: python-checkins at python.org (brett.cannon) Date: Thu, 26 Mar 2009 00:31:22 +0100 (CET) Subject: [Python-checkins] r70603 - python/branches/py3k/Lib/weakref.py Message-ID: <20090325233122.902A31E4002@bag.python.org> Author: brett.cannon Date: Thu Mar 26 00:31:22 2009 New Revision: 70603 Log: Fix a circular import dependency. Modified: python/branches/py3k/Lib/weakref.py Modified: python/branches/py3k/Lib/weakref.py ============================================================================== --- python/branches/py3k/Lib/weakref.py (original) +++ python/branches/py3k/Lib/weakref.py Thu Mar 26 00:31:22 2009 @@ -9,8 +9,6 @@ # they are called this instead of "ref" to avoid name collisions with # the module-global ref() function imported from _weakref. -import collections - from _weakref import ( getweakrefcount, getweakrefs, @@ -22,6 +20,8 @@ from _weakrefset import WeakSet +import collections # Import after _weakref to avoid circular import. + ProxyTypes = (ProxyType, CallableProxyType) __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs", From buildbot at python.org Thu Mar 26 00:55:26 2009 From: buildbot at python.org (buildbot at python.org) Date: Wed, 25 Mar 2009 23:55:26 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090325235527.18AD91E4016@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/514 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,raymond.hettinger,skip.montanaro BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_sys test_wsgiref make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Thu Mar 26 01:22:20 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 00:22:20 +0000 Subject: [Python-checkins] buildbot failure in x86 XP-4 2.6 Message-ID: <20090326002220.C71B31E4002@bag.python.org> The Buildbot has detected a new failure of x86 XP-4 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20XP-4%202.6/builds/157 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: bolen-windows Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: marc-andre.lemburg,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 ====================================================================== ERROR: test01_badpointer (bsddb.test.test_misc.MiscTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\test\test_misc.py", line 21, in test01_badpointer dbs = dbshelve.open(self.filename) File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\dbshelve.py", line 106, in open d.open(filename, dbname, filetype, flags, mode) File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\dbshelve.py", line 171, in open self.db.open(*args, **kwargs) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test03_repr_closed_db (bsddb.test.test_misc.MiscTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\test\test_misc.py", line 37, in test03_repr_closed_db db = hashopen(self.filename) File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test04_repr_db (bsddb.test.test_misc.MiscTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\test\test_misc.py", line 43, in test04_repr_db db = hashopen(self.filename) File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test05_double_free_make_key_dbt (bsddb.test.test_misc.MiscTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\test\test_misc.py", line 65, in test05_double_free_make_key_dbt db.DB_CREATE | db.DB_THREAD) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test06_key_with_null_bytes (bsddb.test.test_misc.MiscTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\test\test_misc.py", line 77, in test06_key_with_null_bytes db1.open(self.filename, None, db.DB_HASH, db.DB_CREATE) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test07_DB_set_flags_persists (bsddb.test.test_misc.MiscTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\test\test_misc.py", line 101, in test07_DB_set_flags_persists db1.open(self.filename, db.DB_HASH, db.DB_CREATE) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test01_basic_replication (bsddb.test.test_replication.DBReplicationManager) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\test\test_replication.py", line 170, in test01_basic_replication mode=0666, txn=txn) DBNoSuchFileError: (2, 'No such file or directory -- connection closed: Successful return: 0') ====================================================================== ERROR: test01_basic_replication (bsddb.test.test_replication.DBReplicationManager) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\test\test_replication.py", line 58, in tearDown if self.dbClient : DBError: (0, 'DB object has been closed') ====================================================================== FAIL: test01_basic_replication (bsddb.test.test_replication.DBBaseReplication) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\2.6.bolen-windows\build\lib\bsddb\test\test_replication.py", line 315, in test01_basic_replication self.assertTrue(time.time() The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/448 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_zipfile make: *** [buildbottest] Error 1 sincerely, -The Buildbot From nnorwitz at gmail.com Thu Mar 26 11:13:31 2009 From: nnorwitz at gmail.com (Neal Norwitz) Date: Thu, 26 Mar 2009 05:13:31 -0500 Subject: [Python-checkins] Python Regression Test Failures refleak (1) Message-ID: <20090326101331.GA13704@python.psfb.org> More important issues: ---------------------- test_softspace leaked [0, 0, -80] references, sum=-80 Less important issues: ---------------------- test_cmd_line leaked [0, 0, -25] references, sum=-25 test_file leaked [-80, 0, 0] references, sum=-80 test_smtplib leaked [0, -14, 14] references, sum=0 test_socketserver leaked [0, 0, 80] references, sum=80 test_threadsignals leaked [0, 8, 0] references, sum=8 test_urllib2_localnet leaked [3, 3, 3] references, sum=9 From python-checkins at python.org Thu Mar 26 15:49:36 2009 From: python-checkins at python.org (jeremy.hylton) Date: Thu, 26 Mar 2009 15:49:36 +0100 (CET) Subject: [Python-checkins] r70604 - python/branches/py3k/Lib/urllib/parse.py Message-ID: <20090326144936.218BB1E4002@bag.python.org> Author: jeremy.hylton Date: Thu Mar 26 15:49:26 2009 New Revision: 70604 Log: Whitespace normalization. Modified: python/branches/py3k/Lib/urllib/parse.py Modified: python/branches/py3k/Lib/urllib/parse.py ============================================================================== --- python/branches/py3k/Lib/urllib/parse.py (original) +++ python/branches/py3k/Lib/urllib/parse.py Thu Mar 26 15:49:26 2009 @@ -504,7 +504,7 @@ _safe_quoters[cachekey] = quoter return ''.join(map(quoter.__getitem__, bs)) -def urlencode(query,doseq=0): +def urlencode(query, doseq=0): """Encode a sequence of two-element tuples or dictionary into a URL query string. If any values in the query arg are sequences and doseq is true, each @@ -515,7 +515,7 @@ input. """ - if hasattr(query,"items"): + if hasattr(query, "items"): # mapping objects query = query.items() else: @@ -531,8 +531,9 @@ # allowed empty dicts that type of behavior probably should be # preserved for consistency except TypeError: - ty,va,tb = sys.exc_info() - raise TypeError("not a valid non-string sequence or mapping object").with_traceback(tb) + ty, va, tb = sys.exc_info() + raise TypeError("not a valid non-string sequence " + "or mapping object").with_traceback(tb) l = [] if not doseq: @@ -551,7 +552,7 @@ # is there a reasonable way to convert to ASCII? # encode generates a string, but "replace" or "ignore" # lose information and "strict" can raise UnicodeError - v = quote_plus(v.encode("ASCII","replace")) + v = quote_plus(v.encode("ASCII", "replace")) l.append(k + '=' + v) else: try: From buildbot at python.org Thu Mar 26 16:06:29 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 15:06:29 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090326150629.C0E911E4040@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/553 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_pipes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Thu Mar 26 16:12:43 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 15:12:43 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090326151243.7C2591E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/456 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Mar 26 17:32:23 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 17:32:23 +0100 (CET) Subject: [Python-checkins] r70605 - python/trunk/Lib/unittest.py Message-ID: <20090326163223.796381E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 17:32:23 2009 New Revision: 70605 Log: remove uneeded function Modified: python/trunk/Lib/unittest.py Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Thu Mar 26 17:32:23 2009 @@ -373,14 +373,14 @@ result.addSkip(self, str(e)) return except Exception: - result.addError(self, self._exc_info()) + result.addError(self, sys.exc_info()) return success = False try: testMethod() except self.failureException: - result.addFailure(self, self._exc_info()) + result.addFailure(self, sys.exc_info()) except _ExpectedFailure as e: result.addExpectedFailure(self, e.exc_info) except _UnexpectedSuccess: @@ -388,14 +388,14 @@ except SkipTest as e: result.addSkip(self, str(e)) except Exception: - result.addError(self, self._exc_info()) + result.addError(self, sys.exc_info()) else: success = True try: self.tearDown() except Exception: - result.addError(self, self._exc_info()) + result.addError(self, sys.exc_info()) success = False if success: result.addSuccess(self) @@ -411,13 +411,6 @@ getattr(self, self._testMethodName)() self.tearDown() - def _exc_info(self): - """Return a version of sys.exc_info() with the traceback frame - minimised; usually the top level of the traceback frame is not - needed. - """ - return sys.exc_info() - def skip(self, reason): """Skip this test.""" raise SkipTest(reason) From python-checkins at python.org Thu Mar 26 17:55:08 2009 From: python-checkins at python.org (jeremy.hylton) Date: Thu, 26 Mar 2009 17:55:08 +0100 (CET) Subject: [Python-checkins] r70606 - python/branches/py3k/Lib/urllib/parse.py Message-ID: <20090326165508.7E0331E4022@bag.python.org> Author: jeremy.hylton Date: Thu Mar 26 17:55:08 2009 New Revision: 70606 Log: Simplify a few complicated expressions. Modified: python/branches/py3k/Lib/urllib/parse.py Modified: python/branches/py3k/Lib/urllib/parse.py ============================================================================== --- python/branches/py3k/Lib/urllib/parse.py (original) +++ python/branches/py3k/Lib/urllib/parse.py Thu Mar 26 17:55:08 2009 @@ -479,12 +479,17 @@ HTML form values. Plus signs in the original string are escaped unless they are included in safe. It also does not have safe default to '/'. """ - # Check if ' ' in string, where string may either be a str or bytes - if ' ' in string if isinstance(string, str) else b' ' in string: - string = quote(string, - safe + ' ' if isinstance(safe, str) else safe + b' ') - return string.replace(' ', '+') - return quote(string, safe, encoding, errors) + # Check if ' ' in string, where string may either be a str or bytes. If + # there are no spaces, the regular quote will produce the right answer. + if ((isinstance(string, str) and ' ' not in string) or + (isinstance(string, bytes) and b' ' not in string)): + return quote(string, safe, encoding, errors) + if isinstance(safe, str): + space = ' ' + else: + space = b' ' + string = quote(string, safe + space) + return string.replace(' ', '+') def quote_from_bytes(bs, safe='/'): """Like quote(), but accepts a bytes object rather than a str, and does @@ -502,7 +507,7 @@ except KeyError: quoter = Quoter(safe) _safe_quoters[cachekey] = quoter - return ''.join(map(quoter.__getitem__, bs)) + return ''.join([quoter[char] for char in bs]) def urlencode(query, doseq=0): """Encode a sequence of two-element tuples or dictionary into a URL query string. From python-checkins at python.org Thu Mar 26 17:56:59 2009 From: python-checkins at python.org (jeremy.hylton) Date: Thu, 26 Mar 2009 17:56:59 +0100 (CET) Subject: [Python-checkins] r70607 - python/branches/py3k/Lib/urllib/parse.py Message-ID: <20090326165659.D69621E4002@bag.python.org> Author: jeremy.hylton Date: Thu Mar 26 17:56:59 2009 New Revision: 70607 Log: urlencode: Remove dead code branch created by automated conversion from 2.x. Clean up a few comments. Modified: python/branches/py3k/Lib/urllib/parse.py Modified: python/branches/py3k/Lib/urllib/parse.py ============================================================================== --- python/branches/py3k/Lib/urllib/parse.py (original) +++ python/branches/py3k/Lib/urllib/parse.py Thu Mar 26 17:56:59 2009 @@ -521,18 +521,17 @@ """ if hasattr(query, "items"): - # mapping objects query = query.items() else: - # it's a bother at times that strings and string-like objects are - # sequences... + # It's a bother at times that strings and string-like objects are + # sequences. try: # non-sequence items should not work with len() # non-empty strings will fail this if len(query) and not isinstance(query[0], tuple): raise TypeError - # zero-length sequences of all types will get here and succeed, - # but that's a minor nit - since the original implementation + # Zero-length sequences of all types will get here and succeed, + # but that's a minor nit. Since the original implementation # allowed empty dicts that type of behavior probably should be # preserved for consistency except TypeError: @@ -542,7 +541,6 @@ l = [] if not doseq: - # preserve old behavior for k, v in query: k = quote_plus(str(k)) v = quote_plus(str(v)) @@ -553,15 +551,9 @@ if isinstance(v, str): v = quote_plus(v) l.append(k + '=' + v) - elif isinstance(v, str): - # is there a reasonable way to convert to ASCII? - # encode generates a string, but "replace" or "ignore" - # lose information and "strict" can raise UnicodeError - v = quote_plus(v.encode("ASCII", "replace")) - l.append(k + '=' + v) else: try: - # is this a sufficient test for sequence-ness? + # Is this a sufficient test for sequence-ness? x = len(v) except TypeError: # not a sequence From python-checkins at python.org Thu Mar 26 17:57:30 2009 From: python-checkins at python.org (jeremy.hylton) Date: Thu, 26 Mar 2009 17:57:30 +0100 (CET) Subject: [Python-checkins] r70608 - python/branches/py3k/Lib/test/test_urllib.py Message-ID: <20090326165730.C09C31E4002@bag.python.org> Author: jeremy.hylton Date: Thu Mar 26 17:57:30 2009 New Revision: 70608 Log: Add a few more tests for urllib.parse.urlencode. Fix some long lines. Modified: python/branches/py3k/Lib/test/test_urllib.py Modified: python/branches/py3k/Lib/test/test_urllib.py ============================================================================== --- python/branches/py3k/Lib/test/test_urllib.py (original) +++ python/branches/py3k/Lib/test/test_urllib.py Thu Mar 26 17:57:30 2009 @@ -379,7 +379,8 @@ result = urllib.parse.quote(quote_by_default, safe=quote_by_default) self.assertEqual(quote_by_default, result, "using quote(): %r != %r" % (quote_by_default, result)) - result = urllib.parse.quote_plus(quote_by_default, safe=quote_by_default) + result = urllib.parse.quote_plus(quote_by_default, + safe=quote_by_default) self.assertEqual(quote_by_default, result, "using quote_plus(): %r != %r" % (quote_by_default, result)) @@ -411,7 +412,8 @@ for char in should_quote: result = urllib.parse.quote(char) self.assertEqual(hexescape(char), result, - "using quote(): %s should be escaped to %s, not %s" % + "using quote(): " + "%s should be escaped to %s, not %s" % (char, hexescape(char), result)) result = urllib.parse.quote_plus(char) self.assertEqual(hexescape(char), result, @@ -770,6 +772,21 @@ self.assertEqual(result.count('&'), 2, "Expected 2 '&'s, got %s" % result.count('&')) + def test_empty_sequence(self): + self.assertEqual("", urllib.parse.urlencode({})) + self.assertEqual("", urllib.parse.urlencode([])) + + def test_nonstring_values(self): + self.assertEqual("a=1", urllib.parse.urlencode({"a": 1})) + self.assertEqual("a=None", urllib.parse.urlencode({"a": None})) + + def test_nonstring_seq_values(self): + self.assertEqual("a=1&a=2", urllib.parse.urlencode({"a": [1, 2]}, True)) + self.assertEqual("a=None&a=a", + urllib.parse.urlencode({"a": [None, "a"]}, True)) + self.assertEqual("a=a&a=b", + urllib.parse.urlencode({"a": {"a": 1, "b": 1}}, True)) + class Pathname_Tests(unittest.TestCase): """Test pathname2url() and url2pathname()""" From python-checkins at python.org Thu Mar 26 18:10:29 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 18:10:29 +0100 (CET) Subject: [Python-checkins] r70609 - in python/branches/py3k: Lib/_pyio.py Lib/test/test_io.py Misc/NEWS Modules/_bufferedio.c Message-ID: <20090326171029.D855D1E4020@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 18:10:29 2009 New Revision: 70609 Log: officially deprecated max_buffer_size Modified: python/branches/py3k/Lib/_pyio.py python/branches/py3k/Lib/test/test_io.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_bufferedio.c Modified: python/branches/py3k/Lib/_pyio.py ============================================================================== --- python/branches/py3k/Lib/_pyio.py (original) +++ python/branches/py3k/Lib/_pyio.py Thu Mar 26 18:10:29 2009 @@ -5,6 +5,7 @@ import os import abc import codecs +import warnings # Import _thread instead of threading to reduce startup cost try: from _thread import allocate_lock as Lock @@ -960,16 +961,20 @@ The constructor creates a BufferedWriter for the given writeable raw stream. If the buffer_size is not given, it defaults to - DEFAULT_BUFFER_SIZE. If max_buffer_size is omitted, it defaults to - twice the buffer size. + DEFAULT_BUFFER_SIZE. """ + _warning_stack_offset = 2 + def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): raw._checkWritable() _BufferedIOMixin.__init__(self, raw) if buffer_size <= 0: raise ValueError("invalid buffer size") + if max_buffer_size is not None: + warnings.warn("max_buffer_size is deprecated", DeprecationWarning, + self._warning_stack_offset) self.buffer_size = buffer_size self._write_buf = bytearray() self._write_lock = Lock() @@ -1055,8 +1060,7 @@ reader and writer are RawIOBase objects that are readable and writeable respectively. If the buffer_size is omitted it defaults to - DEFAULT_BUFFER_SIZE. The max_buffer_size (for the buffered writer) - defaults to twice the buffer size. + DEFAULT_BUFFER_SIZE. """ # XXX The usefulness of this (compared to having two separate IO @@ -1068,10 +1072,12 @@ The arguments are two RawIO instances. """ + if max_buffer_size is not None: + warnings.warn("max_buffer_size is deprecated", DeprecationWarning, 2) reader._checkReadable() writer._checkWritable() self.reader = BufferedReader(reader, buffer_size) - self.writer = BufferedWriter(writer, buffer_size, max_buffer_size) + self.writer = BufferedWriter(writer, buffer_size) def read(self, n=None): if n is None: @@ -1117,10 +1123,11 @@ The constructor creates a reader and writer for a seekable stream, raw, given in the first argument. If the buffer_size is omitted it - defaults to DEFAULT_BUFFER_SIZE. The max_buffer_size (for the buffered - writer) defaults to twice the buffer size. + defaults to DEFAULT_BUFFER_SIZE. """ + _warning_stack_offset = 3 + def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): raw._checkSeekable() Modified: python/branches/py3k/Lib/test/test_io.py ============================================================================== --- python/branches/py3k/Lib/test/test_io.py (original) +++ python/branches/py3k/Lib/test/test_io.py Thu Mar 26 18:10:29 2009 @@ -26,6 +26,7 @@ import threading import random import unittest +import warnings import weakref import gc import abc @@ -861,7 +862,7 @@ def test_write_non_blocking(self): raw = self.MockNonBlockWriterIO() - bufio = self.tp(raw, 8, 8) + bufio = self.tp(raw, 8) self.assertEquals(bufio.write(b"abcd"), 4) self.assertEquals(bufio.write(b"efghi"), 5) @@ -979,6 +980,17 @@ self.assertRaises(IOError, bufio.tell) self.assertRaises(IOError, bufio.write, b"abcdef") + def test_max_buffer_size_deprecation(self): + with support.check_warnings() as w: + warnings.simplefilter("always", DeprecationWarning) + self.tp(self.MockRawIO(), 8, 12) + self.assertEqual(len(w.warnings), 1) + warning = w.warnings[0] + self.assertTrue(warning.category is DeprecationWarning) + self.assertEqual(str(warning.message), + "max_buffer_size is deprecated") + + class CBufferedWriterTest(BufferedWriterTest): tp = io.BufferedWriter @@ -1029,6 +1041,16 @@ pair = self.tp(r, w) self.assertFalse(pair.closed) + def test_max_buffer_size_deprecation(self): + with support.check_warnings() as w: + warnings.simplefilter("always", DeprecationWarning) + self.tp(self.MockRawIO(), self.MockRawIO(), 8, 12) + self.assertEqual(len(w.warnings), 1) + warning = w.warnings[0] + self.assertTrue(warning.category is DeprecationWarning) + self.assertEqual(str(warning.message), + "max_buffer_size is deprecated") + # XXX More Tests class CBufferedRWPairTest(BufferedRWPairTest): @@ -1048,7 +1070,7 @@ def test_read_and_write(self): raw = self.MockRawIO((b"asdf", b"ghjk")) - rw = self.tp(raw, 8, 12) + rw = self.tp(raw, 8) self.assertEqual(b"as", rw.read(2)) rw.write(b"ddd") Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Mar 26 18:10:29 2009 @@ -41,6 +41,9 @@ Library ------- +- The max_buffer_size arguments of io.BufferedWriter, io.BufferedRWPair, and + io.BufferedRandom have been deprecated for removal in Python 3.2. + - Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop forever on incomplete input. That caused tarfile.open() to hang when used with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or Modified: python/branches/py3k/Modules/_bufferedio.c ============================================================================== --- python/branches/py3k/Modules/_bufferedio.c (original) +++ python/branches/py3k/Modules/_bufferedio.c Thu Mar 26 18:10:29 2009 @@ -1415,6 +1415,16 @@ }; + +static int +complain_about_max_buffer_size(void) +{ + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "max_buffer_size is deprecated", 1) < 0) + return 0; + return 1; +} + /* * class BufferedWriter */ @@ -1439,7 +1449,7 @@ /* TODO: properly deprecate max_buffer_size */ char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL}; Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - Py_ssize_t max_buffer_size = -1; + Py_ssize_t max_buffer_size = -234; PyObject *raw; self->ok = 0; @@ -1449,6 +1459,9 @@ return -1; } + if (max_buffer_size != -234 && !complain_about_max_buffer_size()) + return -1; + if (_PyIOBase_checkWritable(raw, Py_True) == NULL) return -1; @@ -1767,8 +1780,7 @@ "\n" "reader and writer are RawIOBase objects that are readable and\n" "writeable respectively. If the buffer_size is omitted it defaults to\n" - "DEFAULT_BUFFER_SIZE. The max_buffer_size (for the buffered writer)\n" - "defaults to twice the buffer size.\n" + "DEFAULT_BUFFER_SIZE.\n" ); /* XXX The usefulness of this (compared to having two separate IO objects) is @@ -1789,13 +1801,16 @@ { PyObject *reader, *writer; Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - Py_ssize_t max_buffer_size = -1; + Py_ssize_t max_buffer_size = -234; if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer, &buffer_size, &max_buffer_size)) { return -1; } + if (max_buffer_size != -234 && !complain_about_max_buffer_size()) + return -1; + if (_PyIOBase_checkReadable(reader, Py_True) == NULL) return -1; if (_PyIOBase_checkWritable(writer, Py_True) == NULL) @@ -1812,7 +1827,7 @@ if (self->reader == NULL) return -1; - args = Py_BuildValue("(nn)", buffer_size, max_buffer_size); + args = Py_BuildValue("(n)", buffer_size); if (args == NULL) { Py_CLEAR(self->reader); return -1; @@ -2016,7 +2031,7 @@ { char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL}; Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - Py_ssize_t max_buffer_size = -1; + Py_ssize_t max_buffer_size = -234; PyObject *raw; self->ok = 0; @@ -2026,6 +2041,9 @@ return -1; } + if (max_buffer_size != -234 && !complain_about_max_buffer_size()) + return -1; + if (_PyIOBase_checkSeekable(raw, Py_True) == NULL) return -1; if (_PyIOBase_checkReadable(raw, Py_True) == NULL) From python-checkins at python.org Thu Mar 26 18:15:46 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 18:15:46 +0100 (CET) Subject: [Python-checkins] r70610 - in python/branches/py3k: Lib/test/test_unicode.py Misc/NEWS Objects/unicodetype_db.h Tools/unicode/makeunicodedata.py Message-ID: <20090326171546.C641A1E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 18:15:46 2009 New Revision: 70610 Log: fix isprintable() on space characters #5126 Modified: python/branches/py3k/Lib/test/test_unicode.py python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/unicodetype_db.h python/branches/py3k/Tools/unicode/makeunicodedata.py Modified: python/branches/py3k/Lib/test/test_unicode.py ============================================================================== --- python/branches/py3k/Lib/test/test_unicode.py (original) +++ python/branches/py3k/Lib/test/test_unicode.py Thu Mar 26 18:15:46 2009 @@ -424,6 +424,7 @@ def test_isprintable(self): self.assertTrue("".isprintable()) + self.assertTrue(" ".isprintable()) self.assertTrue("abcdefg".isprintable()) self.assertFalse("abcdefg\n".isprintable()) # some defined Unicode character Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Mar 26 18:15:46 2009 @@ -12,6 +12,8 @@ Core and Builtins ----------------- +- Issue #5126: str.isprintable() returned False for space characters. + - Issue #4688: Add a heuristic so that tuples and dicts containing only untrackable objects are not tracked by the garbage collector. This can reduce the size of collections and therefore the garbage collection overhead Modified: python/branches/py3k/Objects/unicodetype_db.h ============================================================================== --- python/branches/py3k/Objects/unicodetype_db.h (original) +++ python/branches/py3k/Objects/unicodetype_db.h Thu Mar 26 18:15:46 2009 @@ -6,6 +6,7 @@ {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 32}, {0, 0, 0, 0, 0, 48}, + {0, 0, 0, 0, 0, 1056}, {0, 0, 0, 0, 0, 1024}, {0, 0, 0, 0, 0, 1542}, {0, 0, 0, 1, 1, 1542}, @@ -380,117 +381,116 @@ static unsigned char index2[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 3, 3, 3, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, 4, 4, 4, 4, 4, 4, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 4, 4, 4, 4, 16, 4, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 4, 4, - 4, 4, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 18, 4, 4, - 1, 4, 4, 4, 4, 19, 20, 4, 21, 4, 16, 4, 22, 18, 4, 4, 4, 4, 4, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 4, 15, 15, 15, 15, 15, 15, 15, 18, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 4, - 17, 17, 17, 17, 17, 17, 17, 23, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 26, 27, 24, 25, 24, 25, 24, 25, 18, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 18, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 28, 24, 25, 24, 25, 24, 25, 29, 30, 31, 24, 25, 24, 25, 32, 24, - 25, 33, 33, 24, 25, 18, 34, 35, 36, 24, 25, 33, 37, 38, 39, 40, 24, 25, - 41, 18, 39, 42, 43, 44, 24, 25, 24, 25, 24, 25, 45, 24, 25, 45, 18, 18, - 24, 25, 45, 24, 25, 46, 46, 24, 25, 24, 25, 47, 24, 25, 18, 48, 24, 25, - 18, 49, 48, 48, 48, 48, 50, 51, 52, 50, 51, 52, 50, 51, 52, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 53, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 18, 50, 51, 52, - 24, 25, 54, 55, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 56, 18, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 18, 18, 18, 18, 18, 18, 57, 24, - 25, 58, 59, 18, 18, 24, 25, 60, 61, 62, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 63, 64, 18, 65, 66, 18, 67, 67, 18, 68, 18, 69, 18, 18, 18, 18, - 67, 18, 18, 70, 18, 18, 18, 18, 71, 72, 18, 73, 18, 18, 18, 72, 18, 74, - 75, 18, 18, 76, 18, 18, 18, 18, 18, 18, 18, 77, 18, 18, 78, 18, 18, 78, - 18, 18, 18, 18, 78, 79, 80, 80, 81, 18, 18, 18, 18, 18, 82, 18, 48, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 4, 4, 4, 4, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 48, 48, 48, - 48, 48, 4, 4, 4, 4, 4, 4, 4, 48, 4, 48, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 83, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 1, 1, 1, 1, 3, 3, 3, 2, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 24, 25, 24, 25, 48, 4, 24, 25, 0, 0, 84, - 43, 43, 43, 4, 0, 0, 0, 0, 0, 4, 4, 85, 16, 86, 86, 86, 0, 87, 0, 88, 88, - 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 89, 90, 90, 90, 18, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 91, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 92, 93, 93, 94, 95, 96, 97, 97, 97, 98, 99, 100, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 101, 102, 103, 18, 104, 105, 4, 24, 25, 106, 24, - 25, 18, 56, 56, 56, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 102, - 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, - 102, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 4, - 16, 16, 16, 16, 16, 4, 4, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 108, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 109, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 0, 0, 48, 4, 4, 4, 4, 4, 4, 0, 111, 111, 111, 111, 111, 111, + 16, 16, 16, 16, 5, 5, 5, 5, 17, 5, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 5, 5, + 5, 5, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 19, 5, 5, + 1, 5, 5, 5, 5, 20, 21, 5, 22, 5, 17, 5, 23, 19, 5, 5, 5, 5, 5, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 5, 16, 16, 16, 16, 16, 16, 16, 19, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 5, + 18, 18, 18, 18, 18, 18, 18, 24, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 27, 28, 25, 26, 25, 26, 25, 26, 19, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 19, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 29, 25, 26, 25, 26, 25, 26, 30, 31, 32, 25, 26, 25, 26, 33, 25, + 26, 34, 34, 25, 26, 19, 35, 36, 37, 25, 26, 34, 38, 39, 40, 41, 25, 26, + 42, 19, 40, 43, 44, 45, 25, 26, 25, 26, 25, 26, 46, 25, 26, 46, 19, 19, + 25, 26, 46, 25, 26, 47, 47, 25, 26, 25, 26, 48, 25, 26, 19, 49, 25, 26, + 19, 50, 49, 49, 49, 49, 51, 52, 53, 51, 52, 53, 51, 52, 53, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 54, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 19, 51, 52, 53, + 25, 26, 55, 56, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 57, 19, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 19, 19, 19, 19, 19, 19, 58, 25, + 26, 59, 60, 19, 19, 25, 26, 61, 62, 63, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 64, 65, 19, 66, 67, 19, 68, 68, 19, 69, 19, 70, 19, 19, 19, 19, + 68, 19, 19, 71, 19, 19, 19, 19, 72, 73, 19, 74, 19, 19, 19, 73, 19, 75, + 76, 19, 19, 77, 19, 19, 19, 19, 19, 19, 19, 78, 19, 19, 79, 19, 19, 79, + 19, 19, 19, 19, 79, 80, 81, 81, 82, 19, 19, 19, 19, 19, 83, 19, 49, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, + 49, 49, 5, 5, 5, 5, 5, 5, 5, 49, 5, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 84, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 25, 26, 25, 26, 49, 5, 25, 26, 0, 0, 85, + 44, 44, 44, 5, 0, 0, 0, 0, 0, 5, 5, 86, 17, 87, 87, 87, 0, 88, 0, 89, 89, + 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 90, 91, 91, 91, 19, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 92, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 93, 94, 94, 95, 96, 97, 98, 98, 98, 99, 100, 101, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 102, 103, 104, 19, 105, 106, 5, 25, 26, 107, 25, + 26, 19, 57, 57, 57, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 103, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, + 103, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 5, + 17, 17, 17, 17, 17, 5, 5, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 109, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 110, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, - 111, 111, 111, 111, 18, 0, 4, 4, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 4, 16, 4, 16, 16, 4, 16, 16, 4, 16, 0, 0, 0, 0, 0, 0, 0, - 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 48, 48, 48, 4, 4, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 0, 0, 4, 4, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, - 4, 4, 4, 48, 48, 16, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 48, 16, 16, - 16, 16, 16, 16, 16, 1, 4, 16, 16, 16, 16, 16, 16, 48, 48, 16, 16, 4, 16, - 16, 16, 16, 48, 48, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48, 48, 48, 4, 4, - 48, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, 48, 16, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 48, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 48, 48, 4, 4, 4, 4, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 111, 111, 0, 0, 49, 5, 5, 5, 5, 5, 5, 0, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 19, 0, 5, 5, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 5, 17, 5, 17, 17, 5, 17, 17, 5, 17, 0, 0, 0, 0, 0, 0, 0, + 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 0, 0, 5, 5, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, + 5, 5, 5, 49, 49, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 49, 17, 17, + 17, 17, 17, 17, 17, 1, 5, 17, 17, 17, 17, 17, 17, 49, 49, 17, 17, 5, 17, + 17, 17, 17, 49, 49, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, 5, 5, + 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 1, 49, 17, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 49, 49, 5, 5, 5, 5, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -500,604 +500,605 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 16, 48, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 48, 16, 16, 16, 16, 0, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 4, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 4, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 0, - 16, 16, 16, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 0, 0, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 0, 0, 0, 48, 48, 48, - 48, 0, 0, 16, 48, 16, 16, 16, 16, 16, 16, 16, 0, 0, 16, 16, 0, 0, 16, 16, - 16, 48, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 48, 48, 0, 48, 48, 48, - 16, 16, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48, 48, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 16, 16, 16, 0, 48, 48, 48, 48, 48, 48, 0, - 0, 0, 0, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, - 48, 48, 0, 48, 48, 0, 48, 48, 0, 0, 16, 0, 16, 16, 16, 16, 16, 0, 0, 0, - 0, 16, 16, 0, 0, 16, 16, 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 48, 48, - 48, 48, 0, 48, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 16, 16, 48, 48, 48, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, - 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 0, 48, 48, 48, 48, 48, 0, 0, 16, - 48, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 0, 16, 16, 16, 0, 0, - 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 16, 16, 0, 0, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 16, 16, 16, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 0, - 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 0, 48, 48, - 48, 48, 48, 0, 0, 16, 48, 16, 16, 16, 16, 16, 16, 16, 0, 0, 16, 16, 0, 0, - 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 48, 48, 0, 48, - 48, 48, 16, 16, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 48, 0, 48, 48, 48, 48, 48, 48, - 0, 0, 0, 48, 48, 48, 0, 48, 48, 48, 48, 0, 0, 0, 48, 48, 0, 48, 0, 48, - 48, 0, 0, 0, 48, 48, 0, 0, 0, 48, 48, 48, 0, 0, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 16, 16, 16, 16, 16, 0, 0, 0, 16, - 16, 16, 0, 16, 16, 16, 16, 0, 0, 48, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 16, 16, 16, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 0, 0, 0, 48, 16, 16, 16, 16, - 16, 16, 16, 0, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 16, - 16, 0, 48, 48, 0, 0, 0, 0, 0, 0, 48, 48, 16, 16, 0, 0, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 16, - 16, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 0, - 0, 16, 48, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 0, 16, 16, 16, 16, - 0, 0, 0, 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 48, 0, 48, 48, 16, 16, - 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 16, 16, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, - 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 48, 16, 16, 16, 16, 16, 16, 16, 0, - 16, 16, 16, 0, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, - 0, 0, 0, 0, 48, 48, 16, 16, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, - 4, 4, 4, 4, 4, 0, 0, 0, 4, 48, 48, 48, 48, 48, 48, 0, 0, 16, 16, 0, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, - 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, - 0, 0, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 16, 0, 0, 0, 0, 16, 16, 16, - 16, 16, 16, 0, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 48, 112, 16, - 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 4, 48, 48, 48, 48, 48, 48, 48, 16, - 16, 16, 16, 16, 16, 16, 16, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, 4, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 48, 0, 0, 48, 48, 0, - 48, 0, 0, 48, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, - 48, 48, 0, 48, 48, 48, 0, 48, 0, 48, 0, 0, 48, 48, 0, 48, 48, 48, 48, 16, - 48, 112, 16, 16, 16, 16, 16, 16, 0, 16, 16, 48, 0, 0, 48, 48, 48, 48, 48, - 0, 48, 0, 16, 16, 16, 16, 16, 16, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 4, 4, 4, 4, 4, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, - 4, 16, 4, 16, 4, 4, 4, 4, 16, 16, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, - 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 4, 16, 16, 48, 48, 48, 48, 0, 0, 0, 0, 16, 16, 16, 16, 16, - 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 0, 4, 4, 4, 4, 4, 4, 4, 4, 16, 4, 4, 4, 4, 4, 4, 0, 4, 4, - 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 48, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 4, 4, 4, 4, 4, 4, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 48, 48, 48, - 48, 16, 16, 16, 48, 16, 16, 16, 48, 48, 16, 16, 16, 16, 16, 16, 16, 48, - 48, 48, 16, 16, 16, 16, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 48, 16, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 0, 0, 0, 0, 4, 4, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 4, 48, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, - 48, 0, 48, 0, 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, - 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, - 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 0, 48, 48, 48, - 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 0, 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 0, 0, 0, 0, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 4, 4, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 4, 0, 0, 0, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 4, 4, 4, 123, 123, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 16, - 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 4, 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 0, 16, 16, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 1, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, - 4, 48, 4, 4, 4, 4, 48, 16, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, - 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 2, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 48, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 4, 0, 0, 0, 4, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 48, 48, 48, 48, 48, 48, 48, 16, 16, - 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 0, 0, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, 0, 0, 4, 4, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 16, - 16, 16, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 0, 0, 0, 48, 48, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 0, 0, 0, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 0, - 48, 48, 48, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 48, 124, 18, 18, 18, - 125, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 18, 18, 18, 18, 18, 126, 18, 18, 127, 18, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, - 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 0, 0, 129, 129, 129, - 129, 129, 129, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, - 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, - 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 0, - 0, 129, 129, 129, 129, 129, 129, 0, 0, 18, 128, 18, 128, 18, 128, 18, - 128, 0, 129, 0, 129, 0, 129, 0, 129, 128, 128, 128, 128, 128, 128, 128, - 128, 129, 129, 129, 129, 129, 129, 129, 129, 130, 130, 131, 131, 131, - 131, 132, 132, 133, 133, 134, 134, 135, 135, 0, 0, 128, 128, 128, 128, - 128, 128, 128, 128, 136, 136, 136, 136, 136, 136, 136, 136, 128, 128, - 128, 128, 128, 128, 128, 128, 136, 136, 136, 136, 136, 136, 136, 136, - 128, 128, 128, 128, 128, 128, 128, 128, 136, 136, 136, 136, 136, 136, - 136, 136, 128, 128, 18, 137, 18, 0, 18, 18, 129, 129, 138, 138, 139, 4, - 140, 4, 4, 4, 18, 137, 18, 0, 18, 18, 141, 141, 141, 141, 139, 4, 4, 4, - 128, 128, 18, 18, 0, 0, 18, 18, 129, 129, 142, 142, 0, 4, 4, 4, 128, 128, - 18, 18, 18, 103, 18, 18, 129, 129, 143, 143, 106, 4, 4, 4, 0, 0, 18, 137, - 18, 0, 18, 18, 144, 144, 145, 145, 139, 4, 4, 0, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 1, 1, 1, 1, 1, 2, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, 1, 1, 1, 1, 0, 0, 0, - 0, 0, 1, 1, 1, 1, 1, 1, 146, 18, 0, 0, 147, 148, 149, 150, 151, 152, 4, - 4, 4, 4, 4, 18, 146, 22, 19, 20, 147, 148, 149, 150, 151, 152, 4, 4, 4, - 4, 4, 0, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, 4, 4, 16, 4, 4, 4, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 4, 97, 4, 4, 4, 4, 97, 4, 4, 18, 97, 97, 97, 18, 18, 97, - 97, 97, 18, 4, 97, 4, 4, 123, 97, 97, 97, 97, 97, 4, 4, 4, 4, 4, 4, 97, - 4, 153, 4, 97, 4, 154, 155, 97, 97, 123, 18, 97, 97, 156, 97, 18, 48, 48, - 48, 48, 18, 4, 4, 18, 18, 97, 97, 4, 4, 4, 4, 4, 97, 18, 18, 18, 18, 4, - 4, 4, 4, 157, 4, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 158, - 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, - 158, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 123, 123, 123, 24, 25, 123, 123, 123, 123, 0, 0, 0, 0, 0, - 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 22, 19, 20, 147, 148, 149, 150, 151, 152, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 22, 19, 20, 147, 148, 149, 150, 151, 152, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 22, 19, 20, 147, 148, 149, 150, 151, 152, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, - 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, - 160, 160, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 17, 49, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 49, 17, 17, 17, 17, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 5, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 5, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 0, + 17, 17, 17, 0, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, 0, 0, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 0, 0, 0, 49, 49, 49, + 49, 0, 0, 17, 49, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 0, 0, 17, 17, + 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 49, 49, 0, 49, 49, 49, + 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, 49, 49, 49, 49, 49, 49, 0, + 0, 0, 0, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, + 49, 49, 0, 49, 49, 0, 49, 49, 0, 0, 17, 0, 17, 17, 17, 17, 17, 0, 0, 0, + 0, 17, 17, 0, 0, 17, 17, 17, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 49, 49, + 49, 49, 0, 49, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 17, 17, 49, 49, 49, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, + 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, 49, 49, 49, 49, 49, 0, 0, 17, + 49, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 0, 17, 17, 17, 0, 0, + 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 17, 17, 0, 0, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 17, 17, 0, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, + 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, 49, 49, + 49, 49, 49, 0, 0, 17, 49, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 0, 0, + 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 49, 49, 0, 49, + 49, 49, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 49, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 49, 0, 49, 49, 49, 49, 49, 49, + 0, 0, 0, 49, 49, 49, 0, 49, 49, 49, 49, 0, 0, 0, 49, 49, 0, 49, 0, 49, + 49, 0, 0, 0, 49, 49, 0, 0, 0, 49, 49, 49, 0, 0, 0, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 17, 17, 17, 17, 17, 0, 0, 0, 17, + 17, 17, 0, 17, 17, 17, 17, 0, 0, 49, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 0, 0, 0, 49, 17, 17, 17, + 17, 17, 17, 17, 0, 17, 17, 17, 0, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 0, 49, 49, 0, 0, 0, 0, 0, 0, 49, 49, 17, 17, 0, 0, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 17, 17, 0, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, + 49, 49, 0, 0, 17, 49, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 0, 17, + 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 49, 0, 49, + 49, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 5, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 0, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 49, 17, 17, 17, 17, 17, + 17, 17, 0, 17, 17, 17, 0, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, + 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 49, 49, 49, 49, 49, 49, 0, 0, 17, + 17, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 0, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 17, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 0, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, + 49, 113, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 5, 49, 49, 49, 49, 49, + 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 0, 49, 0, 0, + 49, 49, 0, 49, 0, 0, 49, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 0, 49, 49, 49, + 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, 0, 49, 0, 0, 49, 49, 0, 49, 49, 49, + 49, 17, 49, 113, 17, 17, 17, 17, 17, 17, 0, 17, 17, 49, 0, 0, 49, 49, 49, + 49, 49, 0, 49, 0, 17, 17, 17, 17, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 0, 0, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 5, 5, 5, 5, + 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 17, 5, 17, 5, 17, 5, 5, 5, 5, 17, 17, 49, 49, 49, 49, 49, 49, 49, 49, + 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 5, 17, 17, 49, 49, 49, 49, 0, 0, 0, 0, 17, 17, + 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 0, 5, 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, + 5, 0, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, + 49, 49, 49, 49, 17, 17, 17, 49, 17, 17, 17, 49, 49, 17, 17, 17, 17, 17, + 17, 17, 49, 49, 49, 17, 17, 17, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 17, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 5, 5, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 5, 49, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 49, + 49, 49, 49, 49, 0, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, + 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 0, + 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 49, 49, 49, 49, 49, 49, 49, 49, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 0, 0, + 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 5, 5, 5, 124, 124, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, + 49, 49, 49, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 0, 17, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 1, 1, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 5, 5, 5, 49, 5, 5, 5, 5, 49, 17, 0, 0, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, + 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, 2, 0, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, + 0, 0, 5, 0, 0, 0, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 49, 49, 49, + 49, 49, 49, 17, 17, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, + 17, 17, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 0, 17, 17, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 49, 49, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 0, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 0, 0, 0, 49, 49, 49, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 49, 125, + 19, 19, 19, 126, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 19, 19, 19, 19, 19, 127, 19, 19, 128, 19, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 129, 129, 129, 129, 129, 129, 129, 129, 130, 130, + 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, 129, 129, 0, 0, 130, + 130, 130, 130, 130, 130, 0, 0, 129, 129, 129, 129, 129, 129, 129, 129, + 130, 130, 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, 129, 129, + 129, 129, 130, 130, 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, + 129, 129, 0, 0, 130, 130, 130, 130, 130, 130, 0, 0, 19, 129, 19, 129, 19, + 129, 19, 129, 0, 130, 0, 130, 0, 130, 0, 130, 129, 129, 129, 129, 129, + 129, 129, 129, 130, 130, 130, 130, 130, 130, 130, 130, 131, 131, 132, + 132, 132, 132, 133, 133, 134, 134, 135, 135, 136, 136, 0, 0, 129, 129, + 129, 129, 129, 129, 129, 129, 137, 137, 137, 137, 137, 137, 137, 137, + 129, 129, 129, 129, 129, 129, 129, 129, 137, 137, 137, 137, 137, 137, + 137, 137, 129, 129, 129, 129, 129, 129, 129, 129, 137, 137, 137, 137, + 137, 137, 137, 137, 129, 129, 19, 138, 19, 0, 19, 19, 130, 130, 139, 139, + 140, 5, 141, 5, 5, 5, 19, 138, 19, 0, 19, 19, 142, 142, 142, 142, 140, 5, + 5, 5, 129, 129, 19, 19, 0, 0, 19, 19, 130, 130, 143, 143, 0, 5, 5, 5, + 129, 129, 19, 19, 19, 104, 19, 19, 130, 130, 144, 144, 107, 5, 5, 5, 0, + 0, 19, 138, 19, 0, 19, 19, 145, 145, 146, 146, 140, 5, 5, 0, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 1, 1, 1, 1, 1, 2, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 147, 19, 0, 0, 148, 149, 150, 151, + 152, 153, 5, 5, 5, 5, 5, 19, 147, 23, 20, 21, 148, 149, 150, 151, 152, + 153, 5, 5, 5, 5, 5, 0, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 17, 5, + 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 98, 5, 5, 5, 5, 98, 5, 5, 19, 98, 98, + 98, 19, 19, 98, 98, 98, 19, 5, 98, 5, 5, 124, 98, 98, 98, 98, 98, 5, 5, + 5, 5, 5, 5, 98, 5, 154, 5, 98, 5, 155, 156, 98, 98, 124, 19, 98, 98, 157, + 98, 19, 49, 49, 49, 49, 19, 5, 5, 19, 19, 98, 98, 5, 5, 5, 5, 5, 98, 19, + 19, 19, 19, 5, 5, 5, 5, 158, 5, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 124, 124, 124, 25, 26, 124, 124, 124, 124, 0, 0, + 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 23, 20, 21, 148, 149, 150, 151, 152, 153, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 23, 20, 21, 148, 149, 150, 151, 152, 153, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 23, 20, 21, 148, 149, 150, 151, 152, 153, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, - 146, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 22, 19, 20, 147, 148, 149, 150, 151, - 152, 4, 146, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, - 4, 0, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 0, 4, 0, 4, 4, 4, 4, 0, 0, 0, 4, 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 22, 19, 20, 147, - 148, 149, 150, 151, 152, 4, 22, 19, 20, 147, 148, 149, 150, 151, 152, 4, - 22, 19, 20, 147, 148, 149, 150, 151, 152, 4, 4, 0, 0, 0, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, - 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 161, 161, 161, 161, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 147, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 23, 20, 21, 148, 149, 150, + 151, 152, 153, 5, 147, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 0, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 0, 5, 0, 5, 5, 5, 5, 0, 0, 0, 5, 0, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 23, 20, + 21, 148, 149, 150, 151, 152, 153, 5, 23, 20, 21, 148, 149, 150, 151, 152, + 153, 5, 23, 20, 21, 148, 149, 150, 151, 152, 153, 5, 5, 0, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 5, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 0, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, - 111, 111, 111, 111, 111, 111, 111, 0, 24, 25, 162, 163, 164, 165, 166, - 24, 25, 24, 25, 24, 25, 167, 168, 169, 0, 18, 24, 25, 18, 24, 25, 18, 18, - 18, 18, 18, 18, 48, 0, 0, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 18, 4, 4, - 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, - 4, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, - 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, - 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, - 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, - 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, - 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, - 48, 48, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 84, 4, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 0, 0, 0, 0, 2, 4, 4, 4, 4, 48, 48, 123, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 16, 16, 16, 16, 16, 16, 4, 48, 48, 48, 48, 48, 4, 4, - 123, 123, 123, 48, 48, 4, 4, 4, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 16, 16, 4, 4, 48, 48, 48, 4, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 48, 48, 48, - 48, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 4, 4, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 0, 0, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 48, 16, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 16, 16, 4, 48, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 4, 4, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 18, 18, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 48, 18, 18, 18, - 18, 18, 18, 18, 18, 24, 25, 24, 25, 171, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 48, 4, 4, 24, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, - 48, 48, 48, 48, 48, 16, 48, 48, 48, 16, 48, 48, 48, 48, 16, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 16, 16, 16, 16, 16, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 48, 48, 48, 16, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 0, 0, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 0, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 0, 25, 26, 163, 164, 165, 166, + 167, 25, 26, 25, 26, 25, 26, 168, 169, 170, 0, 19, 25, 26, 19, 25, 26, + 19, 19, 19, 19, 19, 19, 49, 0, 0, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 19, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, + 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, + 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, + 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, + 49, 49, 49, 49, 49, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 85, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 2, 5, 5, 5, 5, 49, 49, 124, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 17, 17, 17, 17, 17, 17, 5, 49, 49, 49, + 49, 49, 5, 5, 124, 124, 124, 49, 49, 5, 5, 5, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 17, 17, 5, 5, 49, 49, 49, 5, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, + 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 5, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 0, 0, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 49, 17, 5, 5, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 17, 5, 49, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 19, 19, 25, 26, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 49, + 19, 19, 19, 19, 19, 19, 19, 19, 25, 26, 25, 26, 172, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 49, 5, 5, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 49, 49, 49, 49, 49, 49, 49, 17, 49, 49, 49, 17, 49, 49, 49, 49, 17, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 17, + 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 17, 49, 49, 49, 49, 49, 49, + 49, 49, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 5, 5, 5, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1107,371 +1108,372 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 48, 16, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 0, 48, 0, 48, 48, 0, 48, 48, - 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 84, 84, 84, 84, 84, 84, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 84, 84, 4, 4, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 16, - 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 16, 16, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, - 16, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 0, 4, 4, 4, 4, 0, 0, 0, 0, 84, 48, 84, 48, 84, 0, 84, 48, 84, 48, 84, 48, - 84, 48, 84, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 0, 0, 1, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, 4, 4, 4, 4, 4, 4, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 4, 4, 4, 4, 16, 4, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 112, 112, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 0, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 48, - 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 48, 0, 0, 0, 4, - 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 4, 4, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, - 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, - 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, - 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 123, 48, 48, 48, 48, 48, 48, 48, 48, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 4, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 4, 123, 123, 123, 123, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, + 19, 0, 0, 0, 0, 0, 49, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 0, + 49, 0, 49, 49, 0, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 85, 85, 85, 85, 85, 85, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 85, 85, 5, 5, 0, 0, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 17, 17, 17, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 0, 0, 0, 0, 85, 49, 85, 49, 85, 0, + 85, 49, 85, 49, 85, 49, 85, 49, 85, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 1, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, + 5, 5, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 5, 5, 5, 5, 17, 5, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 113, 113, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 49, 49, 49, 49, 49, + 49, 0, 0, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 0, 0, 49, + 49, 49, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 5, 5, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, + 0, 0, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 0, 0, 48, 0, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 0, 0, 0, 48, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 5, 5, 5, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 124, 49, 49, 49, 49, 49, 49, 49, 49, 124, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 5, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 5, 124, 124, 124, 124, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, + 49, 0, 0, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, 0, 0, 49, + 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 4, 4, 4, 4, 0, 0, 0, 0, 0, 4, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, - 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 5, 5, 5, 5, 0, 0, 0, 0, 0, 5, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 48, 16, 16, 16, 0, 16, 16, 0, 0, 0, 0, 0, 16, 16, 16, 16, 48, - 48, 48, 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, - 0, 16, 16, 16, 0, 0, 0, 0, 16, 22, 19, 20, 147, 4, 4, 4, 4, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 17, 17, 17, 0, 17, 17, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 0, 0, 0, 0, 17, 17, 17, 0, 0, 0, 0, 17, 23, 20, 21, 148, 5, + 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 16, 16, 16, 16, 16, 4, 4, 4, 16, 16, 16, 16, 16, 16, 1, 1, 1, - 1, 1, 1, 1, 1, 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, 16, 16, 16, 16, 16, - 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, 17, 17, 5, 5, 5, 17, 17, 17, 17, + 17, 17, 1, 1, 1, 1, 1, 1, 1, 1, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 17, + 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, 17, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, + 17, 17, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, 18, 18, - 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 97, 0, 97, 97, 0, 0, 97, 0, 0, 97, 97, 0, 0, 97, 97, 97, 97, 0, 97, 97, - 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, 0, 18, 0, 18, 18, 18, 18, 18, 18, - 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 97, 97, 0, 97, 97, 97, 97, 0, - 0, 97, 97, 97, 97, 97, 97, 97, 97, 0, 97, 97, 97, 97, 97, 97, 97, 0, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 97, 97, 0, 97, 97, 97, 97, 0, 97, 97, 97, 97, - 97, 0, 97, 0, 0, 0, 97, 97, 97, 97, 97, 97, 97, 0, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 4, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 4, 18, 18, 18, 18, 18, 18, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 4, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 4, 18, 18, 18, 18, - 18, 18, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 4, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 4, - 18, 18, 18, 18, 18, 18, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 4, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 4, 18, 18, 18, 18, 18, 18, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 4, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 4, 18, 18, 18, 18, 18, 18, 97, 18, 0, 0, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 98, 0, 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 0, 98, 98, 98, + 98, 0, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 0, 19, 0, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, 0, + 98, 98, 98, 98, 0, 0, 98, 98, 98, 98, 98, 98, 98, 98, 0, 98, 98, 98, 98, + 98, 98, 98, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, 0, 98, 98, 98, + 98, 0, 98, 98, 98, 98, 98, 0, 98, 0, 0, 0, 98, 98, 98, 98, 98, 98, 98, 0, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 5, 19, 19, 19, + 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 5, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 5, 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 5, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 5, 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 5, 19, 19, 19, 19, 19, 19, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 5, 19, 19, 19, 19, 19, + 19, 98, 19, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1481,6 +1483,6 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, }; Modified: python/branches/py3k/Tools/unicode/makeunicodedata.py ============================================================================== --- python/branches/py3k/Tools/unicode/makeunicodedata.py (original) +++ python/branches/py3k/Tools/unicode/makeunicodedata.py Thu Mar 26 18:15:46 2009 @@ -375,7 +375,7 @@ flags |= TITLE_MASK if category == "Lu": flags |= UPPER_MASK - if char == " " or category[0] not in ("C", "Z"): + if char == ord(" ") or category[0] not in ("C", "Z"): flags |= PRINTABLE_MASK if "XID_Start" in properties: flags |= XID_START_MASK From python-checkins at python.org Thu Mar 26 19:35:37 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 19:35:37 +0100 (CET) Subject: [Python-checkins] r70611 - in python/trunk/Lib: platform.py test/test_platform.py Message-ID: <20090326183537.A0F2D1E4013@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 19:35:37 2009 New Revision: 70611 Log: add much better tests for python version information parsing Modified: python/trunk/Lib/platform.py python/trunk/Lib/test/test_platform.py Modified: python/trunk/Lib/platform.py ============================================================================== --- python/trunk/Lib/platform.py (original) +++ python/trunk/Lib/platform.py Thu Mar 26 19:35:37 2009 @@ -1264,9 +1264,6 @@ '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*' '\[([^\]]+)\]?') -_jython_sys_version_parser = re.compile( - r'([\d\.]+)') - _ironpython_sys_version_parser = re.compile( r'IronPython\s*' '([\d\.]+)' @@ -1322,12 +1319,12 @@ elif sys.platform[:4] == 'java': # Jython name = 'Jython' - match = _jython_sys_version_parser.match(sys_version) + match = _sys_version_parser.match(sys_version) if match is None: raise ValueError( 'failed to parse Jython sys.version: %s' % repr(sys_version)) - version, = match.groups() + version, buildno, builddate, buildtime, _ = match.groups() branch = '' revision = '' compiler = sys.platform Modified: python/trunk/Lib/test/test_platform.py ============================================================================== --- python/trunk/Lib/test/test_platform.py (original) +++ python/trunk/Lib/test/test_platform.py Thu Mar 26 19:35:37 2009 @@ -48,25 +48,52 @@ def test_processor(self): res = platform.processor() - def test_python_implementation(self): - res = platform.python_implementation() - - def test_python_version(self): - res1 = platform.python_version() - res2 = platform.python_version_tuple() - self.assertEqual(res1, ".".join(res2)) - - def test_python_branch(self): - res = platform.python_branch() - - def test_python_revision(self): - res = platform.python_revision() - - def test_python_build(self): - res = platform.python_build() - - def test_python_compiler(self): - res = platform.python_compiler() + def setUp(self): + self.save_version = sys.version + self.save_subversion = sys.subversion + self.save_platform = sys.platform + + def tearDown(self): + sys.version = self.save_version + sys.subversion = self.save_subversion + sys.platform = self.save_platform + + def test_python_info(self): + # Tests for python_implementation(), python_version(), python_branch(), + # python_revision(), python_build(), and python_compiler(). + sys_versions = { + ("2.6.1 (r261:67515, Dec 6 2008, 15:26:00) \n[GCC 4.0.1 (Apple Computer, Inc. build 5370)]", + ('CPython', 'tags/r261', '67515'), self.save_platform) + : + ("CPython", "2.6.1", "tags/r261", "67515", + ('r261:67515', 'Dec 6 2008 15:26:00'), + 'GCC 4.0.1 (Apple Computer, Inc. build 5370)'), + ("IronPython 2.0 (2.0.0.0) on .NET 2.0.50727.3053", None, "cli") + : + ("IronPython", "2.0.0", "", "", ("", ""), + ".NET 2.0.50727.3053"), + ("2.5 (trunk:6107, Mar 26 2009, 13:02:18) \n[Java HotSpot(TM) Client VM (\"Apple Computer, Inc.\")]", + None, "java1.5.0_16") + : + ("Jython", "2.5.0", "", "", ("", ""), + "java1.5.0_16"), + } + for (version_tag, subversion, sys_platform), info in \ + sys_versions.iteritems(): + sys.version = version_tag + if subversion is None: + if hasattr(sys, "subversion"): + del sys.subversion + else: + sys.subversion = subversion + if sys_platform is not None: + sys.platform = sys_platform + self.assertEqual(platform.python_implementation(), info[0]) + self.assertEqual(platform.python_version(), info[1]) + self.assertEqual(platform.python_branch(), info[2]) + self.assertEqual(platform.python_revision(), info[3]) + self.assertEqual(platform.python_build(), info[4]) + self.assertEqual(platform.python_compiler(), info[5]) def test_system_alias(self): res = platform.system_alias( From buildbot at python.org Thu Mar 26 19:48:19 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 18:48:19 +0000 Subject: [Python-checkins] buildbot failure in x86 XP-4 trunk Message-ID: <20090326184820.1F46D1E4002@bag.python.org> The Buildbot has detected a new failure of x86 XP-4 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20XP-4%20trunk/builds/1987 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: bolen-windows Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\trunk.bolen-windows\build\lib\threading.py", line 522, in __bootstrap_inner File "E:\cygwin\home\db3l\buildarea\trunk.bolen-windows\build\lib\threading.py", line 477, in run File "", line 7, in killer : 'NoneType' object is not callable 1 test failed: test_bsddb3 ====================================================================== FAIL: test01_basic_replication (bsddb.test.test_replication.DBBaseReplication) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\trunk.bolen-windows\build\lib\bsddb\test\test_replication.py", line 315, in test01_basic_replication self.assertTrue(time.time() The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/268 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Abort trap sincerely, -The Buildbot From python-checkins at python.org Thu Mar 26 19:55:48 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 19:55:48 +0100 (CET) Subject: [Python-checkins] r70612 - in python/trunk/Lib: platform.py test/test_platform.py Message-ID: <20090326185548.A69201E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 19:55:48 2009 New Revision: 70612 Log: more and more implementations now support sys.subversion Modified: python/trunk/Lib/platform.py python/trunk/Lib/test/test_platform.py Modified: python/trunk/Lib/platform.py ============================================================================== --- python/trunk/Lib/platform.py (original) +++ python/trunk/Lib/platform.py Thu Mar 26 19:55:48 2009 @@ -1311,8 +1311,6 @@ 'failed to parse IronPython sys.version: %s' % repr(sys_version)) version, alt_version, compiler = match.groups() - branch = '' - revision = '' buildno = '' builddate = '' @@ -1325,11 +1323,7 @@ 'failed to parse Jython sys.version: %s' % repr(sys_version)) version, buildno, builddate, buildtime, _ = match.groups() - branch = '' - revision = '' compiler = sys.platform - buildno = '' - builddate = '' else: # CPython @@ -1340,15 +1334,16 @@ repr(sys_version)) version, buildno, builddate, buildtime, compiler = \ match.groups() - if hasattr(sys, 'subversion'): - # sys.subversion was added in Python 2.5 - name, branch, revision = sys.subversion - else: - name = 'CPython' - branch = '' - revision = '' + name = 'CPython' builddate = builddate + ' ' + buildtime + if hasattr(sys, 'subversion'): + # sys.subversion was added in Python 2.5 + _, branch, revision = sys.subversion + else: + branch = '' + revision = '' + # Add the patchlevel version if missing l = string.split(version, '.') if len(l) == 2: Modified: python/trunk/Lib/test/test_platform.py ============================================================================== --- python/trunk/Lib/test/test_platform.py (original) +++ python/trunk/Lib/test/test_platform.py Thu Mar 26 19:55:48 2009 @@ -73,10 +73,10 @@ ("IronPython", "2.0.0", "", "", ("", ""), ".NET 2.0.50727.3053"), ("2.5 (trunk:6107, Mar 26 2009, 13:02:18) \n[Java HotSpot(TM) Client VM (\"Apple Computer, Inc.\")]", - None, "java1.5.0_16") + ('Jython', 'trunk', '6107'), "java1.5.0_16") : - ("Jython", "2.5.0", "", "", ("", ""), - "java1.5.0_16"), + ("Jython", "2.5.0", "trunk", "6107", + ('trunk:6107', 'Mar 26 2009'), "java1.5.0_16"), } for (version_tag, subversion, sys_platform), info in \ sys_versions.iteritems(): From python-checkins at python.org Thu Mar 26 19:58:30 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 19:58:30 +0100 (CET) Subject: [Python-checkins] r70613 - python/trunk/Lib/test/test_platform.py Message-ID: <20090326185830.8A7D01E4039@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 19:58:30 2009 New Revision: 70613 Log: roll old test in with new one Modified: python/trunk/Lib/test/test_platform.py Modified: python/trunk/Lib/test/test_platform.py ============================================================================== --- python/trunk/Lib/test/test_platform.py (original) +++ python/trunk/Lib/test/test_platform.py Thu Mar 26 19:58:30 2009 @@ -58,7 +58,23 @@ sys.subversion = self.save_subversion sys.platform = self.save_platform - def test_python_info(self): + def test_sys_version(self): + # Old test. + for input, output in ( + ('2.4.3 (#1, Jun 21 2006, 13:54:21) \n[GCC 3.3.4 (pre 3.3.5 20040809)]', + ('CPython', '2.4.3', '', '', '1', 'Jun 21 2006 13:54:21', 'GCC 3.3.4 (pre 3.3.5 20040809)')), + ('IronPython 1.0.60816 on .NET 2.0.50727.42', + ('IronPython', '1.0.60816', '', '', '', '', '.NET 2.0.50727.42')), + ('IronPython 1.0 (1.0.61005.1977) on .NET 2.0.50727.42', + ('IronPython', '1.0.0', '', '', '', '', '.NET 2.0.50727.42')), + ): + # branch and revision are not "parsed", but fetched + # from sys.subversion. Ignore them + (name, version, branch, revision, buildno, builddate, compiler) \ + = platform._sys_version(input) + self.assertEqual( + (name, version, '', '', buildno, builddate, compiler), output) + # Tests for python_implementation(), python_version(), python_branch(), # python_revision(), python_build(), and python_compiler(). sys_versions = { @@ -174,23 +190,6 @@ ): self.assertEqual(platform._parse_release_file(input), output) - def test_sys_version(self): - - platform._sys_version_cache.clear() - for input, output in ( - ('2.4.3 (#1, Jun 21 2006, 13:54:21) \n[GCC 3.3.4 (pre 3.3.5 20040809)]', - ('CPython', '2.4.3', '', '', '1', 'Jun 21 2006 13:54:21', 'GCC 3.3.4 (pre 3.3.5 20040809)')), - ('IronPython 1.0.60816 on .NET 2.0.50727.42', - ('IronPython', '1.0.60816', '', '', '', '', '.NET 2.0.50727.42')), - ('IronPython 1.0 (1.0.61005.1977) on .NET 2.0.50727.42', - ('IronPython', '1.0.0', '', '', '', '', '.NET 2.0.50727.42')), - ): - # branch and revision are not "parsed", but fetched - # from sys.subversion. Ignore them - (name, version, branch, revision, buildno, builddate, compiler) \ - = platform._sys_version(input) - self.assertEqual( - (name, version, '', '', buildno, builddate, compiler), output) def test_main(): test_support.run_unittest( From python-checkins at python.org Thu Mar 26 20:09:21 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 20:09:21 +0100 (CET) Subject: [Python-checkins] r70614 - in python/trunk/Lib: platform.py test/test_platform.py Message-ID: <20090326190921.7ABE61E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 20:09:21 2009 New Revision: 70614 Log: add support for PyPy Modified: python/trunk/Lib/platform.py python/trunk/Lib/test/test_platform.py Modified: python/trunk/Lib/platform.py ============================================================================== --- python/trunk/Lib/platform.py (original) +++ python/trunk/Lib/platform.py Thu Mar 26 20:09:21 2009 @@ -1270,6 +1270,11 @@ '(?: \(([\d\.]+)\))?' ' on (.NET [\d\.]+)') +_pypy_sys_version_parser = re.compile( + r'([\w.+]+)\s*' + '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*' + '\[PyPy [^\]]+\]?') + _sys_version_cache = {} def _sys_version(sys_version=None): @@ -1325,6 +1330,16 @@ version, buildno, builddate, buildtime, _ = match.groups() compiler = sys.platform + elif "PyPy" in sys_version: + # PyPy + name = "PyPy" + match = _pypy_sys_version_parser.match(sys_version) + if match is None: + raise ValueError("failed to parse PyPy sys.version: %s" % + repr(sys_version)) + version, buildno, builddate, buildtime = match.groups() + compiler = "" + else: # CPython match = _sys_version_parser.match(sys_version) Modified: python/trunk/Lib/test/test_platform.py ============================================================================== --- python/trunk/Lib/test/test_platform.py (original) +++ python/trunk/Lib/test/test_platform.py Thu Mar 26 20:09:21 2009 @@ -93,6 +93,11 @@ : ("Jython", "2.5.0", "trunk", "6107", ('trunk:6107', 'Mar 26 2009'), "java1.5.0_16"), + ("2.5.2 (63378, Mar 26 2009, 18:03:29)\n[PyPy 1.0.0]", + ('PyPy', 'trunk', '63378'), self.save_platform) + : + ("PyPy", "2.5.2", "trunk", "63378", ('63378', 'Mar 26 2009'), + "") } for (version_tag, subversion, sys_platform), info in \ sys_versions.iteritems(): From buildbot at python.org Thu Mar 26 20:32:25 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 19:32:25 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090326193225.7BF5E1E4024@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/775 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_asynchat make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Mar 26 20:58:19 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 20:58:19 +0100 (CET) Subject: [Python-checkins] r70615 - python/trunk/Lib/test/test_support.py Message-ID: <20090326195819.0384C1E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 20:58:18 2009 New Revision: 70615 Log: add some useful utilities for skipping tests with unittest's new skipping ability most significantly apply a modified portion of the patch from #4242 with patches for skipping implementation details Modified: python/trunk/Lib/test/test_support.py Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Thu Mar 26 20:58:18 2009 @@ -8,6 +8,7 @@ import socket import sys import os +import platform import shutil import warnings import unittest @@ -23,7 +24,8 @@ "captured_stdout", "TransientResource", "transient_internet", "run_with_locale", "set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner", "run_unittest", "run_doctest", "threading_setup", - "threading_cleanup", "reap_children"] + "threading_cleanup", "reap_children", "cpython_only", + "check_impl_detail"] class Error(Exception): """Base class for regression test exceptions.""" @@ -531,6 +533,21 @@ def captured_stdout(): return captured_output("stdout") +def gc_collect(): + """Force as many objects as possible to be collected. + + In non-CPython implementations of Python, this is needed because timely + deallocation is not guaranteed by the garbage collector. (Even in CPython + this can be the case in case of reference cycles.) This means that __del__ + methods may be called later than expected and weakrefs may remain alive for + longer than expected. This function tries its best to force all garbage + objects to disappear. + """ + import gc + gc.collect() + gc.collect() + gc.collect() + #======================================================================= # Decorator for running a function in a different locale, correctly resetting @@ -682,6 +699,55 @@ test(result) return result +def _id(obj): + return obj + +def requires_resource(resource): + if resource_is_enabled(resource): + return _id + else: + return unittest.skip("resource {0!r} is not enabled".format(resource)) + +def cpython_only(test): + """ + Decorator for tests only applicable on CPython. + """ + return impl_detail(cpython=True)(test) + +def impl_detail(msg=None, **guards): + if check_impl_detail(): + return _id + if msg is None: + guardnames, default = _parse_guards(guards) + if default: + msg = "implementation detail not available on {0}" + else: + msg = "implementation detail specific to {0}" + guardnames = sorted(guardnames.keys()) + msg = msg.format(' or '.join(guardnames)) + return unittest.skip(msg) + +def _parse_guards(guards): + # Returns a tuple ({platform_name: run_me}, default_value) + if not guards: + return ({'cpython': True}, False) + is_true = guards.values()[0] + assert guards.values() == [is_true] * len(guards) # all True or all False + return (guards, not is_true) + +# Use the following check to guard CPython's implementation-specific tests -- +# or to run them only on the implementation(s) guarded by the arguments. +def check_impl_detail(**guards): + """This function returns True or False depending on the host platform. + Examples: + if check_impl_detail(): # only on CPython (default) + if check_impl_detail(jython=True): # only on Jython + if check_impl_detail(cpython=False): # everywhere except on CPython + """ + guards, default = _parse_guards(guards) + return guards.get(platform.python_implementation().lower(), default) + + def _run_suite(suite): """Run tests from a unittest.TestSuite-derived class.""" From python-checkins at python.org Thu Mar 26 21:05:50 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 21:05:50 +0100 (CET) Subject: [Python-checkins] r70616 - in python/trunk: Doc/library/unittest.rst Lib/test/test_unittest.py Lib/unittest.py Message-ID: <20090326200550.B00ED1E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 21:05:50 2009 New Revision: 70616 Log: rename TestCase.skip() to skipTest() because it causes annoying problems with trial #5571 Modified: python/trunk/Doc/library/unittest.rst python/trunk/Lib/test/test_unittest.py python/trunk/Lib/unittest.py Modified: python/trunk/Doc/library/unittest.rst ============================================================================== --- python/trunk/Doc/library/unittest.rst (original) +++ python/trunk/Doc/library/unittest.rst Thu Mar 26 21:05:50 2009 @@ -576,7 +576,7 @@ instance. - .. method:: skip(reason) + .. method:: skipTest(reason) Calling this during the a test method or :meth:`setUp` skips the current test. See :ref:`unittest-skipping` for more information. Modified: python/trunk/Lib/test/test_unittest.py ============================================================================== --- python/trunk/Lib/test/test_unittest.py (original) +++ python/trunk/Lib/test/test_unittest.py Thu Mar 26 21:05:50 2009 @@ -2294,7 +2294,7 @@ def test_skipping(self): class Foo(unittest.TestCase): def test_skip_me(self): - self.skip("skip") + self.skipTest("skip") events = [] result = LoggingResult(events) test = Foo("test_skip_me") @@ -2305,7 +2305,7 @@ # Try letting setUp skip the test now. class Foo(unittest.TestCase): def setUp(self): - self.skip("testing") + self.skipTest("testing") def test_nothing(self): pass events = [] result = LoggingResult(events) Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Thu Mar 26 21:05:50 2009 @@ -411,7 +411,7 @@ getattr(self, self._testMethodName)() self.tearDown() - def skip(self, reason): + def skipTest(self, reason): """Skip this test.""" raise SkipTest(reason) From python-checkins at python.org Thu Mar 26 21:17:27 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 21:17:27 +0100 (CET) Subject: [Python-checkins] r70617 - python/trunk/Lib/test/test_descr.py Message-ID: <20090326201727.BBCEC1E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 21:17:27 2009 New Revision: 70617 Log: apply the second part of #4242's patch; classify all the implementation details in test_descr Modified: python/trunk/Lib/test/test_descr.py Modified: python/trunk/Lib/test/test_descr.py ============================================================================== --- python/trunk/Lib/test/test_descr.py (original) +++ python/trunk/Lib/test/test_descr.py Thu Mar 26 21:17:27 2009 @@ -75,8 +75,9 @@ # Find method in parent class while meth not in t.__dict__: t = t.__bases__[0] - - self.assertEqual(m, t.__dict__[meth]) + # in some implementations (e.g. PyPy), 'm' can be a regular unbound + # method object; the getattr() below obtains its underlying function. + self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) self.assertEqual(m(a), res) bm = getattr(a, meth) self.assertEqual(bm(), res) @@ -95,7 +96,9 @@ m = getattr(t, meth) while meth not in t.__dict__: t = t.__bases__[0] - self.assertEqual(m, t.__dict__[meth]) + # in some implementations (e.g. PyPy), 'm' can be a regular unbound + # method object; the getattr() below obtains its underlying function. + self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) self.assertEqual(m(a, b), res) bm = getattr(a, meth) self.assertEqual(bm(b), res) @@ -107,7 +110,9 @@ m = getattr(t, meth) while meth not in t.__dict__: t = t.__bases__[0] - self.assertEqual(m, t.__dict__[meth]) + # in some implementations (e.g. PyPy), 'm' can be a regular unbound + # method object; the getattr() below obtains its underlying function. + self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) self.assertEqual(m(a, b, c), res) bm = getattr(a, meth) self.assertEqual(bm(b, c), res) @@ -120,7 +125,9 @@ m = getattr(t, meth) while meth not in t.__dict__: t = t.__bases__[0] - self.assertEqual(m, t.__dict__[meth]) + # in some implementations (e.g. PyPy), 'm' can be a regular unbound + # method object; the getattr() below obtains its underlying function. + self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) d['a'] = deepcopy(a) m(d['a'], b) self.assertEqual(d['a'], res) @@ -137,7 +144,9 @@ m = getattr(t, meth) while meth not in t.__dict__: t = t.__bases__[0] - self.assertEqual(m, t.__dict__[meth]) + # in some implementations (e.g. PyPy), 'm' can be a regular unbound + # method object; the getattr() below obtains its underlying function. + self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) d['a'] = deepcopy(a) m(d['a'], b, c) self.assertEqual(d['a'], res) @@ -154,7 +163,9 @@ while meth not in t.__dict__: t = t.__bases__[0] m = getattr(t, meth) - self.assertEqual(m, t.__dict__[meth]) + # in some implementations (e.g. PyPy), 'm' can be a regular unbound + # method object; the getattr() below obtains its underlying function. + self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) dictionary['a'] = deepcopy(a) m(dictionary['a'], b, c, d) self.assertEqual(dictionary['a'], res) @@ -182,7 +193,10 @@ def test_dicts(self): # Testing dict operations... - self.binop_test({1:2}, {2:1}, -1, "cmp(a,b)", "__cmp__") + if hasattr(dict, '__cmp__'): # PyPy has only rich comparison on dicts + self.binop_test({1:2}, {2:1}, -1, "cmp(a,b)", "__cmp__") + else: + self.binop_test({1:2}, {2:1}, True, "a < b", "__lt__") self.binop_test({1:2,3:4}, 1, 1, "b in a", "__contains__") self.binop_test({1:2,3:4}, 2, 0, "b in a", "__contains__") self.binop_test({1:2,3:4}, 1, 2, "a[b]", "__getitem__") @@ -293,6 +307,7 @@ self.assertEqual(repr(a), "234.5") self.assertEqual(a.prec, 12) + @test_support.impl_detail("the module 'xxsubtype' is internal") def test_spam_lists(self): # Testing spamlist operations... import copy, xxsubtype as spam @@ -336,6 +351,7 @@ a.setstate(42) self.assertEqual(a.getstate(), 42) + @test_support.impl_detail("the module 'xxsubtype' is internal") def test_spam_dicts(self): # Testing spamdict operations... import copy, xxsubtype as spam @@ -891,8 +907,11 @@ try: callable(*args) except exc, msg: - if not str(msg).startswith(expected): - self.fail("Message %r, expected %r" % (str(msg), expected)) + # the exact msg is generally considered an impl detail + if test_support.check_impl_detail(): + if not str(msg).startswith(expected): + self.fail("Message %r, expected %r" % + (str(msg), expected)) else: self.fail("Expected %s" % exc) @@ -1085,6 +1104,7 @@ x.c = Counted() self.assertEqual(Counted.counter, 3) del x + test_support.gc_collect() self.assertEqual(Counted.counter, 0) class D(C): pass @@ -1093,6 +1113,7 @@ x.z = Counted() self.assertEqual(Counted.counter, 2) del x + test_support.gc_collect() self.assertEqual(Counted.counter, 0) class E(D): __slots__ = ['e'] @@ -1102,6 +1123,7 @@ x.e = Counted() self.assertEqual(Counted.counter, 3) del x + test_support.gc_collect() self.assertEqual(Counted.counter, 0) # Test cyclical leaks [SF bug 519621] @@ -1112,22 +1134,23 @@ s.a = [Counted(), s] self.assertEqual(Counted.counter, 1) s = None - import gc - gc.collect() + test_support.gc_collect() self.assertEqual(Counted.counter, 0) # Test lookup leaks [SF bug 572567] import sys,gc - class G(object): - def __cmp__(self, other): - return 0 - __hash__ = None # Silence Py3k warning - g = G() - orig_objects = len(gc.get_objects()) - for i in xrange(10): - g==g - new_objects = len(gc.get_objects()) - self.assertEqual(orig_objects, new_objects) + if hasattr(gc, 'get_objects'): + class G(object): + def __cmp__(self, other): + return 0 + __hash__ = None # Silence Py3k warning + g = G() + orig_objects = len(gc.get_objects()) + for i in xrange(10): + g==g + new_objects = len(gc.get_objects()) + self.assertEqual(orig_objects, new_objects) + class H(object): __slots__ = ['a', 'b'] def __init__(self): @@ -1382,6 +1405,7 @@ else: self.fail("classmethod shouldn't accept keyword args") + @test_support.impl_detail("the module 'xxsubtype' is internal") def test_classmethods_in_c(self): # Testing C-based class methods... import xxsubtype as spam @@ -1413,6 +1437,7 @@ self.assertEqual(d.foo(1), (d, 1)) self.assertEqual(D.foo(d, 1), (d, 1)) + @test_support.impl_detail("the module 'xxsubtype' is internal") def test_staticmethods_in_c(self): # Testing C-based static methods... import xxsubtype as spam @@ -1529,6 +1554,14 @@ class __metaclass__(type): def mro(self): return [self, dict, object] + # In CPython, the class creation above already raises + # TypeError, as a protection against the fact that + # instances of X would segfault it. In other Python + # implementations it would be ok to let the class X + # be created, but instead get a clean TypeError on the + # __setitem__ below. + x = object.__new__(X) + x[5] = 6 except TypeError: pass else: @@ -1766,6 +1799,10 @@ # Safety test for __cmp__ def unsafecmp(a, b): + if not hasattr(a, '__cmp__'): + return # some types don't have a __cmp__ any more (so the + # test doesn't make sense any more), or maybe they + # never had a __cmp__ at all, e.g. in PyPy try: a.__class__.__cmp__(a, b) except TypeError: @@ -1781,7 +1818,8 @@ unsafecmp(1, 1L) unsafecmp(1L, 1) - def test_recursions(self): + @test_support.impl_detail("custom logic for printing to real file objects") + def test_recursions_1(self): # Testing recursion checks ... class Letter(str): def __new__(cls, letter): @@ -1806,6 +1844,7 @@ finally: sys.stdout = test_stdout + def test_recursions_2(self): # Bug #1202533. class A(object): pass @@ -1826,6 +1865,7 @@ r = weakref.ref(c) self.assertEqual(r(), c) del c + test_support.gc_collect() self.assertEqual(r(), None) del r class NoWeak(object): @@ -1843,6 +1883,7 @@ r = weakref.ref(yes) self.assertEqual(r(), yes) del yes + test_support.gc_collect() self.assertEqual(r(), None) del r @@ -2179,7 +2220,10 @@ # Two essentially featureless objects, just inheriting stuff from # object. - self.assertEqual(dir(None), dir(Ellipsis)) + self.assertEqual(dir(NotImplemented), dir(Ellipsis)) + if test_support.check_impl_detail(): + # None differs in PyPy: it has a __nonzero__ + self.assertEqual(dir(None), dir(Ellipsis)) # Nasty test case for proxied objects class Wrapper(object): @@ -2893,7 +2937,7 @@ self.fail("shouldn't allow %r.__class__ = %r" % (x, C)) try: delattr(x, "__class__") - except TypeError: + except (TypeError, AttributeError): pass else: self.fail("shouldn't allow del %r.__class__" % x) @@ -3027,6 +3071,16 @@ mod.__dict__["spam"] = "eggs" # Exception's __dict__ can be replaced, but not deleted + # (at least not any more than regular exception's __dict__ can + # be deleted; on CPython it is not the case, whereas on PyPy they + # can, just like any other new-style instance's __dict__.) + def can_delete_dict(e): + try: + del e.__dict__ + except (TypeError, AttributeError): + return False + else: + return True class Exception1(Exception, Base): pass class Exception2(Base, Exception): @@ -3035,12 +3089,7 @@ e = ExceptionType() e.__dict__ = {"a": 1} self.assertEqual(e.a, 1) - try: - del e.__dict__ - except (TypeError, AttributeError): - pass - else: - self.fail("%r's __dict__ can be deleted" % e) + self.assertEqual(can_delete_dict(e), can_delete_dict(ValueError())) def test_pickles(self): # Testing pickling and copying new-style classes and objects... @@ -3339,7 +3388,7 @@ class B(A): pass del B - gc.collect() + test_support.gc_collect() A.__setitem__ = lambda *a: None # crash def test_buffer_inheritance(self): @@ -3431,6 +3480,7 @@ c = C() self.assertEqual(log, []) del c + test_support.gc_collect() self.assertEqual(log, [1]) class D(object): pass @@ -3526,7 +3576,7 @@ self.assertEqual(hasattr(m, "__name__"), 0) self.assertEqual(hasattr(m, "__file__"), 0) self.assertEqual(hasattr(m, "foo"), 0) - self.assertEqual(m.__dict__, None) + self.assertFalse(m.__dict__) # None or {} are both reasonable answers m.foo = 1 self.assertEqual(m.__dict__, {"foo": 1}) @@ -3661,17 +3711,23 @@ c = C() c.attr = 42 - # The most interesting thing here is whether this blows up, due to flawed - # GC tracking logic in typeobject.c's call_finalizer() (a 2.2.1 bug). + # The most interesting thing here is whether this blows up, due to + # flawed GC tracking logic in typeobject.c's call_finalizer() (a 2.2.1 + # bug). del c # If that didn't blow up, it's also interesting to see whether clearing - # the last container slot works: that will attempt to delete c again, - # which will cause c to get appended back to the container again "during" - # the del. - del C.container[-1] + # the last container slot works: that will attempt to delete c again, + # which will cause c to get appended back to the container again + # "during" the del. (On non-CPython implementations, however, __del__ + # is typically not called again.) + test_support.gc_collect() self.assertEqual(len(C.container), 1) - self.assertEqual(C.container[-1].attr, 42) + del C.container[-1] + if test_support.check_impl_detail(): + test_support.gc_collect() + self.assertEqual(len(C.container), 1) + self.assertEqual(C.container[-1].attr, 42) # Make c mortal again, so that the test framework with -l doesn't report # it as a leak. @@ -3697,7 +3753,8 @@ pass class C(A,B) : __slots__=() - self.assertEqual(C.__basicsize__, B.__basicsize__) + if test_support.check_impl_detail(): + self.assertEqual(C.__basicsize__, B.__basicsize__) self.assert_(hasattr(C, '__dict__')) self.assert_(hasattr(C, '__weakref__')) C().x = 2 @@ -3780,7 +3837,7 @@ try: del D.__bases__ - except TypeError: + except (TypeError, AttributeError): pass else: self.fail("shouldn't be able to delete .__bases__") @@ -3981,6 +4038,7 @@ self.assertEqual(E() // C(), "C.__floordiv__") self.assertEqual(C() // E(), "C.__floordiv__") # This one would fail + @test_support.impl_detail("testing an internal kind of method object") def test_meth_class_get(self): # Testing __get__ method of METH_CLASS C methods... # Full coverage of descrobject.c::classmethod_get() @@ -4166,7 +4224,7 @@ self.assertEqual(c.attr, 1) # this makes a crash more likely: - import gc; gc.collect() + test_support.gc_collect() self.assertEqual(hasattr(c, 'attr'), False) def test_init(self): @@ -4191,8 +4249,14 @@ self.assert_(l.__add__ != [5].__add__) self.assert_(l.__add__ != l.__mul__) self.assert_(l.__add__.__name__ == '__add__') - self.assert_(l.__add__.__self__ is l) - self.assert_(l.__add__.__objclass__ is list) + if hasattr(l.__add__, '__self__'): + # CPython + self.assert_(l.__add__.__self__ is l) + self.assert_(l.__add__.__objclass__ is list) + else: + # Python implementations where [].__add__ is a normal bound method + self.assert_(l.__add__.im_self is l) + self.assert_(l.__add__.im_class is list) self.assertEqual(l.__add__.__doc__, list.__add__.__doc__) try: hash(l.__add__) From python-checkins at python.org Thu Mar 26 21:48:27 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 21:48:27 +0100 (CET) Subject: [Python-checkins] r70618 - in python/trunk/Lib/test: regrtest.py test__locale.py test_commands.py test_curses.py test_decimal.py test_dl.py test_epoll.py test_fork1.py test_gl.py test_ioctl.py test_kqueue.py test_largefile.py test_linuxaudiodev.py test_locale.py test_macostools.py test_mhlib.py test_minidom.py test_multiprocessing.py test_nis.py test_openpty.py test_ossaudiodev.py test_pep277.py test_pipes.py test_poll.py test_popen2.py test_posix.py test_pty.py test_py3kwarn.py test_signal.py test_site.py test_socketserver.py test_sqlite.py test_ssl.py test_sunaudiodev.py test_support.py test_tempfile.py test_threaded_import.py test_threadsignals.py test_tk.py test_ttk_guionly.py test_unicode_file.py test_univnewlines.py test_wait3.py test_wait4.py Message-ID: <20090326204827.8FF5A1E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 21:48:25 2009 New Revision: 70618 Log: remove test_support.TestSkipped and just use unittest.SkipTest Modified: python/trunk/Lib/test/regrtest.py python/trunk/Lib/test/test__locale.py python/trunk/Lib/test/test_commands.py python/trunk/Lib/test/test_curses.py python/trunk/Lib/test/test_decimal.py python/trunk/Lib/test/test_dl.py python/trunk/Lib/test/test_epoll.py python/trunk/Lib/test/test_fork1.py python/trunk/Lib/test/test_gl.py python/trunk/Lib/test/test_ioctl.py python/trunk/Lib/test/test_kqueue.py python/trunk/Lib/test/test_largefile.py python/trunk/Lib/test/test_linuxaudiodev.py python/trunk/Lib/test/test_locale.py python/trunk/Lib/test/test_macostools.py python/trunk/Lib/test/test_mhlib.py python/trunk/Lib/test/test_minidom.py python/trunk/Lib/test/test_multiprocessing.py python/trunk/Lib/test/test_nis.py python/trunk/Lib/test/test_openpty.py python/trunk/Lib/test/test_ossaudiodev.py python/trunk/Lib/test/test_pep277.py python/trunk/Lib/test/test_pipes.py python/trunk/Lib/test/test_poll.py python/trunk/Lib/test/test_popen2.py python/trunk/Lib/test/test_posix.py python/trunk/Lib/test/test_pty.py python/trunk/Lib/test/test_py3kwarn.py python/trunk/Lib/test/test_signal.py python/trunk/Lib/test/test_site.py python/trunk/Lib/test/test_socketserver.py python/trunk/Lib/test/test_sqlite.py python/trunk/Lib/test/test_ssl.py python/trunk/Lib/test/test_sunaudiodev.py python/trunk/Lib/test/test_support.py python/trunk/Lib/test/test_tempfile.py python/trunk/Lib/test/test_threaded_import.py python/trunk/Lib/test/test_threadsignals.py python/trunk/Lib/test/test_tk.py python/trunk/Lib/test/test_ttk_guionly.py python/trunk/Lib/test/test_unicode_file.py python/trunk/Lib/test/test_univnewlines.py python/trunk/Lib/test/test_wait3.py python/trunk/Lib/test/test_wait4.py Modified: python/trunk/Lib/test/regrtest.py ============================================================================== --- python/trunk/Lib/test/regrtest.py (original) +++ python/trunk/Lib/test/regrtest.py Thu Mar 26 21:48:25 2009 @@ -132,6 +132,7 @@ import time import traceback import warnings +import unittest # I see no other way to suppress these warnings; # putting them in test_grammar.py has no effect: @@ -567,7 +568,7 @@ print test, "skipped --", msg sys.stdout.flush() return -2 - except (ImportError, test_support.TestSkipped), msg: + except (ImportError, unittest.SkipTest), msg: if not quiet: print test, "skipped --", msg sys.stdout.flush() Modified: python/trunk/Lib/test/test__locale.py ============================================================================== --- python/trunk/Lib/test/test__locale.py (original) +++ python/trunk/Lib/test/test__locale.py Thu Mar 26 21:48:25 2009 @@ -1,4 +1,4 @@ -from test.test_support import verbose, TestSkipped, run_unittest +from test.test_support import verbose, SkipTest, run_unittest from _locale import (setlocale, LC_NUMERIC, RADIXCHAR, THOUSEP, nl_langinfo, localeconv, Error) import unittest @@ -7,7 +7,7 @@ if uname()[0] == "Darwin": maj, min, mic = [int(part) for part in uname()[2].split(".")] if (maj, min, mic) < (8, 0, 0): - raise TestSkipped("locale support broken for OS X < 10.4") + raise SkipTest("locale support broken for OS X < 10.4") candidate_locales = ['es_UY', 'fr_FR', 'fi_FI', 'es_CO', 'pt_PT', 'it_IT', 'et_EE', 'es_PY', 'no_NO', 'nl_NL', 'lv_LV', 'el_GR', 'be_BY', 'fr_BE', Modified: python/trunk/Lib/test/test_commands.py ============================================================================== --- python/trunk/Lib/test/test_commands.py (original) +++ python/trunk/Lib/test/test_commands.py Thu Mar 26 21:48:25 2009 @@ -9,7 +9,7 @@ warnings.filterwarnings('ignore', r".*commands.getstatus.. is deprecated", DeprecationWarning) -from test.test_support import TestSkipped, run_unittest, reap_children +from test.test_support import SkipTest, run_unittest, reap_children from commands import * # The module says: @@ -19,7 +19,7 @@ # I'll take the comment as given, and skip this suite. if os.name != 'posix': - raise TestSkipped('Not posix; skipping test_commands') + raise SkipTest('Not posix; skipping test_commands') class CommandTests(unittest.TestCase): Modified: python/trunk/Lib/test/test_curses.py ============================================================================== --- python/trunk/Lib/test/test_curses.py (original) +++ python/trunk/Lib/test/test_curses.py Thu Mar 26 21:48:25 2009 @@ -16,16 +16,16 @@ # 'curses' resource be given on the regrtest command line using the -u # option. If not available, nothing after this line will be executed. -from test.test_support import requires, TestSkipped +from test.test_support import requires, SkipTest requires('curses') # XXX: if newterm was supported we could use it instead of initscr and not exit term = os.environ.get('TERM') if not term or term == 'unknown': - raise TestSkipped, "$TERM=%r, calling initscr() may cause exit" % term + raise SkipTest, "$TERM=%r, calling initscr() may cause exit" % term if sys.platform == "cygwin": - raise TestSkipped("cygwin's curses mostly just hangs") + raise SkipTest("cygwin's curses mostly just hangs") def window_funcs(stdscr): "Test the methods of windows" Modified: python/trunk/Lib/test/test_decimal.py ============================================================================== --- python/trunk/Lib/test/test_decimal.py (original) +++ python/trunk/Lib/test/test_decimal.py Thu Mar 26 21:48:25 2009 @@ -31,7 +31,7 @@ import unittest from decimal import * import numbers -from test.test_support import (TestSkipped, run_unittest, run_doctest, +from test.test_support import (SkipTest, run_unittest, run_doctest, is_resource_enabled) import random try: @@ -194,7 +194,7 @@ def eval_file(self, file): global skip_expected if skip_expected: - raise TestSkipped + raise SkipTest return for line in open(file).xreadlines(): line = line.replace('\r\n', '').replace('\n', '') Modified: python/trunk/Lib/test/test_dl.py ============================================================================== --- python/trunk/Lib/test/test_dl.py (original) +++ python/trunk/Lib/test/test_dl.py Thu Mar 26 21:48:25 2009 @@ -2,7 +2,7 @@ """Test dlmodule.c Roger E. Masse revised strategy by Barry Warsaw """ -from test.test_support import verbose,TestSkipped, import_module +from test.test_support import verbose,SkipTest, import_module dl = import_module('dl', deprecated=True) sharedlibs = [ @@ -31,7 +31,7 @@ print 'worked!' break else: - raise TestSkipped, 'Could not open any shared libraries' + raise SkipTest, 'Could not open any shared libraries' if __name__ == '__main__': Modified: python/trunk/Lib/test/test_epoll.py ============================================================================== --- python/trunk/Lib/test/test_epoll.py (original) +++ python/trunk/Lib/test/test_epoll.py Thu Mar 26 21:48:25 2009 @@ -31,13 +31,13 @@ from test import test_support if not hasattr(select, "epoll"): - raise test_support.TestSkipped("test works only on Linux 2.6") + raise unittest.SkipTest("test works only on Linux 2.6") try: select.epoll() except IOError, e: if e.errno == errno.ENOSYS: - raise test_support.TestSkipped("kernel doesn't support epoll()") + raise unittest.SkipTest("kernel doesn't support epoll()") class TestEPoll(unittest.TestCase): Modified: python/trunk/Lib/test/test_fork1.py ============================================================================== --- python/trunk/Lib/test/test_fork1.py (original) +++ python/trunk/Lib/test/test_fork1.py Thu Mar 26 21:48:25 2009 @@ -4,12 +4,12 @@ import os import time from test.fork_wait import ForkWait -from test.test_support import TestSkipped, run_unittest, reap_children +from test.test_support import SkipTest, run_unittest, reap_children try: os.fork except AttributeError: - raise TestSkipped, "os.fork not defined -- skipping test_fork1" + raise SkipTest, "os.fork not defined -- skipping test_fork1" class ForkTest(ForkWait): def wait_impl(self, cpid): Modified: python/trunk/Lib/test/test_gl.py ============================================================================== --- python/trunk/Lib/test/test_gl.py (original) +++ python/trunk/Lib/test/test_gl.py Thu Mar 26 21:48:25 2009 @@ -3,7 +3,7 @@ taken mostly from the documentation. Roger E. Masse """ -from test.test_support import verbose, TestSkipped +from test.test_support import verbose, SkipTest import gl, GL, time glattrs = ['RGBcolor', 'RGBcursor', 'RGBmode', 'RGBrange', 'RGBwritemask', @@ -87,7 +87,7 @@ try: display = os.environ['DISPLAY'] except: - raise TestSkipped, "No $DISPLAY -- skipping gl test" + raise SkipTest, "No $DISPLAY -- skipping gl test" # touch all the attributes of gl without doing anything if verbose: Modified: python/trunk/Lib/test/test_ioctl.py ============================================================================== --- python/trunk/Lib/test/test_ioctl.py (original) +++ python/trunk/Lib/test/test_ioctl.py Thu Mar 26 21:48:25 2009 @@ -1,18 +1,18 @@ import unittest -from test.test_support import TestSkipped, run_unittest +from test.test_support import SkipTest, run_unittest import os, struct try: import fcntl, termios except ImportError: - raise TestSkipped("No fcntl or termios module") + raise SkipTest("No fcntl or termios module") if not hasattr(termios,'TIOCGPGRP'): - raise TestSkipped("termios module doesn't have TIOCGPGRP") + raise SkipTest("termios module doesn't have TIOCGPGRP") try: tty = open("/dev/tty", "r") tty.close() except IOError: - raise TestSkipped("Unable to open /dev/tty") + raise SkipTest("Unable to open /dev/tty") try: import pty @@ -41,7 +41,7 @@ def test_ioctl_signed_unsigned_code_param(self): if not pty: - raise TestSkipped('pty module required') + raise SkipTest('pty module required') mfd, sfd = pty.openpty() try: if termios.TIOCSWINSZ < 0: Modified: python/trunk/Lib/test/test_kqueue.py ============================================================================== --- python/trunk/Lib/test/test_kqueue.py (original) +++ python/trunk/Lib/test/test_kqueue.py Thu Mar 26 21:48:25 2009 @@ -10,7 +10,7 @@ from test import test_support if not hasattr(select, "kqueue"): - raise test_support.TestSkipped("test works only on BSD") + raise unittest.SkipTest("test works only on BSD") class TestKQueue(unittest.TestCase): def test_create_queue(self): Modified: python/trunk/Lib/test/test_largefile.py ============================================================================== --- python/trunk/Lib/test/test_largefile.py (original) +++ python/trunk/Lib/test/test_largefile.py Thu Mar 26 21:48:25 2009 @@ -6,7 +6,7 @@ import sys import unittest from test.test_support import run_unittest, TESTFN, verbose, requires, \ - TestSkipped, unlink + SkipTest, unlink try: import signal @@ -104,7 +104,7 @@ # this is already decided before start running the test suite # but we do it anyway for extra protection if not hasattr(f, 'truncate'): - raise TestSkipped, "open().truncate() not available on this system" + raise SkipTest, "open().truncate() not available on this system" f.seek(0, 2) # else we've lost track of the true size self.assertEqual(f.tell(), size+1) @@ -155,7 +155,7 @@ except (IOError, OverflowError): f.close() unlink(TESTFN) - raise TestSkipped, "filesystem does not have largefile support" + raise SkipTest, "filesystem does not have largefile support" else: f.close() suite = unittest.TestSuite() Modified: python/trunk/Lib/test/test_linuxaudiodev.py ============================================================================== --- python/trunk/Lib/test/test_linuxaudiodev.py (original) +++ python/trunk/Lib/test/test_linuxaudiodev.py Thu Mar 26 21:48:25 2009 @@ -1,7 +1,7 @@ from test import test_support test_support.requires('audio') -from test.test_support import findfile, TestSkipped, run_unittest +from test.test_support import findfile, SkipTest, run_unittest import errno linuxaudiodev = test_support.import_module('linuxaudiodev', deprecated=True) @@ -89,7 +89,7 @@ dsp = linuxaudiodev.open('w') except linuxaudiodev.error, msg: if msg.args[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): - raise TestSkipped(msg) + raise SkipTest(msg) raise dsp.close() run_unittest(LinuxAudioDevTests) Modified: python/trunk/Lib/test/test_locale.py ============================================================================== --- python/trunk/Lib/test/test_locale.py (original) +++ python/trunk/Lib/test/test_locale.py Thu Mar 26 21:48:25 2009 @@ -1,4 +1,4 @@ -from test.test_support import run_unittest, verbose, TestSkipped +from test.test_support import run_unittest, verbose, SkipTest import unittest import locale import sys @@ -10,7 +10,7 @@ def get_enUS_locale(): global enUS_locale if sys.platform == 'darwin': - raise TestSkipped("Locale support on MacOSX is minimal") + raise SkipTest("Locale support on MacOSX is minimal") if sys.platform.startswith("win"): tlocs = ("En", "English") else: @@ -23,7 +23,7 @@ continue break else: - raise TestSkipped( + raise SkipTest( "Test locale not supported (tried %s)" % (', '.join(tlocs))) enUS_locale = tloc locale.setlocale(locale.LC_NUMERIC, oldlocale) @@ -355,10 +355,10 @@ TestCNumberFormatting, TestFrFRNumberFormatting, ] - # TestSkipped can't be raised inside unittests, handle it manually instead + # SkipTest can't be raised inside unittests, handle it manually instead try: get_enUS_locale() - except TestSkipped as e: + except SkipTest as e: if verbose: print "Some tests will be disabled: %s" % e else: Modified: python/trunk/Lib/test/test_macostools.py ============================================================================== --- python/trunk/Lib/test/test_macostools.py (original) +++ python/trunk/Lib/test/test_macostools.py Thu Mar 26 21:48:25 2009 @@ -93,7 +93,7 @@ def test_main(): # Skip on wide unicode if len(u'\0'.encode('unicode-internal')) == 4: - raise test_support.TestSkipped("test_macostools is broken in USC4") + raise unittest.SkipTest("test_macostools is broken in USC4") test_support.run_unittest(TestMacostools) Modified: python/trunk/Lib/test/test_mhlib.py ============================================================================== --- python/trunk/Lib/test/test_mhlib.py (original) +++ python/trunk/Lib/test/test_mhlib.py Thu Mar 26 21:48:25 2009 @@ -7,7 +7,7 @@ ### mhlib. It should. import unittest -from test.test_support import run_unittest, TESTFN, TestSkipped, import_module +from test.test_support import run_unittest, TESTFN, SkipTest, import_module import os, StringIO import sys mhlib = import_module('mhlib', deprecated=True) @@ -21,7 +21,7 @@ # link counts, and that causes test_listfolders() here to get back # an empty list from its call of listallfolders(). # The other tests here pass on Windows. - raise TestSkipped("skipped on %s -- " % sys.platform + + raise SkipTest("skipped on %s -- " % sys.platform + "too many Unix assumptions") _mhroot = TESTFN+"_MH" Modified: python/trunk/Lib/test/test_minidom.py ============================================================================== --- python/trunk/Lib/test/test_minidom.py (original) +++ python/trunk/Lib/test/test_minidom.py Thu Mar 26 21:48:25 2009 @@ -4,7 +4,7 @@ import sys import pickle from StringIO import StringIO -from test.test_support import verbose, run_unittest, TestSkipped +from test.test_support import verbose, run_unittest, SkipTest import unittest import xml.dom Modified: python/trunk/Lib/test/test_multiprocessing.py ============================================================================== --- python/trunk/Lib/test/test_multiprocessing.py (original) +++ python/trunk/Lib/test/test_multiprocessing.py Thu Mar 26 21:48:25 2009 @@ -23,8 +23,8 @@ try: import multiprocessing.synchronize except ImportError, e: - from test.test_support import TestSkipped - raise TestSkipped(e) + from test.test_support import SkipTest + raise SkipTest(e) import multiprocessing.dummy import multiprocessing.connection @@ -1812,8 +1812,8 @@ try: lock = multiprocessing.RLock() except OSError: - from test.test_support import TestSkipped - raise TestSkipped("OSError raises on RLock creation, see issue 3111!") + from test.test_support import SkipTest + raise SkipTest("OSError raises on RLock creation, see issue 3111!") if run is None: from test.test_support import run_unittest as run Modified: python/trunk/Lib/test/test_nis.py ============================================================================== --- python/trunk/Lib/test/test_nis.py (original) +++ python/trunk/Lib/test/test_nis.py Thu Mar 26 21:48:25 2009 @@ -10,7 +10,7 @@ # NIS is probably not active, so this test isn't useful if test_support.verbose: print "Test Skipped:", msg - # Can't raise TestSkipped as regrtest only recognizes the exception + # Can't raise SkipTest as regrtest only recognizes the exception # import time. return try: Modified: python/trunk/Lib/test/test_openpty.py ============================================================================== --- python/trunk/Lib/test/test_openpty.py (original) +++ python/trunk/Lib/test/test_openpty.py Thu Mar 26 21:48:25 2009 @@ -1,10 +1,10 @@ # Test to see if openpty works. (But don't worry if it isn't available.) import os, unittest -from test.test_support import run_unittest, TestSkipped +from test.test_support import run_unittest, SkipTest if not hasattr(os, "openpty"): - raise TestSkipped, "No openpty() available." + raise SkipTest, "No openpty() available." class OpenptyTest(unittest.TestCase): Modified: python/trunk/Lib/test/test_ossaudiodev.py ============================================================================== --- python/trunk/Lib/test/test_ossaudiodev.py (original) +++ python/trunk/Lib/test/test_ossaudiodev.py Thu Mar 26 21:48:25 2009 @@ -1,7 +1,7 @@ from test import test_support test_support.requires('audio') -from test.test_support import findfile, TestSkipped +from test.test_support import findfile, SkipTest import errno import ossaudiodev @@ -45,7 +45,7 @@ dsp = ossaudiodev.open('w') except IOError, msg: if msg[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): - raise TestSkipped(msg) + raise SkipTest(msg) raise # at least check that these methods can be invoked @@ -162,7 +162,7 @@ dsp = ossaudiodev.open('w') except (ossaudiodev.error, IOError), msg: if msg[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): - raise TestSkipped(msg) + raise SkipTest(msg) raise dsp.close() test_support.run_unittest(__name__) Modified: python/trunk/Lib/test/test_pep277.py ============================================================================== --- python/trunk/Lib/test/test_pep277.py (original) +++ python/trunk/Lib/test/test_pep277.py Thu Mar 26 21:48:25 2009 @@ -3,7 +3,7 @@ import sys, os, unittest from test import test_support if not os.path.supports_unicode_filenames: - raise test_support.TestSkipped, "test works only on NT+" + raise unittest.SkipTest, "test works only on NT+" filenames = [ 'abc', Modified: python/trunk/Lib/test/test_pipes.py ============================================================================== --- python/trunk/Lib/test/test_pipes.py (original) +++ python/trunk/Lib/test/test_pipes.py Thu Mar 26 21:48:25 2009 @@ -2,10 +2,10 @@ import os import string import unittest -from test.test_support import TESTFN, run_unittest, unlink, TestSkipped +from test.test_support import TESTFN, run_unittest, unlink, SkipTest if os.name != 'posix': - raise TestSkipped('pipes module only works on posix') + raise SkipTest('pipes module only works on posix') TESTFN2 = TESTFN + "2" Modified: python/trunk/Lib/test/test_poll.py ============================================================================== --- python/trunk/Lib/test/test_poll.py (original) +++ python/trunk/Lib/test/test_poll.py Thu Mar 26 21:48:25 2009 @@ -1,12 +1,12 @@ # Test case for the os.poll() function import os, select, random, unittest -from test.test_support import TestSkipped, TESTFN, run_unittest +from test.test_support import SkipTest, TESTFN, run_unittest try: select.poll except AttributeError: - raise TestSkipped, "select.poll not defined -- skipping test_poll" + raise SkipTest, "select.poll not defined -- skipping test_poll" def find_ready_matching(ready, flag): Modified: python/trunk/Lib/test/test_popen2.py ============================================================================== --- python/trunk/Lib/test/test_popen2.py (original) +++ python/trunk/Lib/test/test_popen2.py Thu Mar 26 21:48:25 2009 @@ -12,13 +12,13 @@ import unittest import popen2 -from test.test_support import TestSkipped, run_unittest, reap_children +from test.test_support import SkipTest, 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) + raise SkipTest("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 Modified: python/trunk/Lib/test/test_posix.py ============================================================================== --- python/trunk/Lib/test/test_posix.py (original) +++ python/trunk/Lib/test/test_posix.py Thu Mar 26 21:48:25 2009 @@ -5,7 +5,7 @@ try: import posix except ImportError: - raise test_support.TestSkipped, "posix is not available" + raise unittest.SkipTest, "posix is not available" import time import os @@ -242,10 +242,10 @@ os.mkdir(base_path) os.chdir(base_path) except: -# Just returning nothing instead of the TestSkipped exception, +# Just returning nothing instead of the SkipTest exception, # because the test results in Error in that case. # Is that ok? -# raise test_support.TestSkipped, "cannot create directory for testing" +# raise unittest.SkipTest, "cannot create directory for testing" return try: @@ -253,7 +253,7 @@ try: os.mkdir(dirname) except: - raise test_support.TestSkipped, "mkdir cannot create directory sufficiently deep for getcwd test" + raise unittest.SkipTest, "mkdir cannot create directory sufficiently deep for getcwd test" os.chdir(dirname) try: Modified: python/trunk/Lib/test/test_pty.py ============================================================================== --- python/trunk/Lib/test/test_pty.py (original) +++ python/trunk/Lib/test/test_pty.py Thu Mar 26 21:48:25 2009 @@ -4,7 +4,7 @@ import os import sys import signal -from test.test_support import verbose, TestSkipped, run_unittest +from test.test_support import verbose, SkipTest, run_unittest import unittest TEST_STRING_1 = "I wish to buy a fish license.\n" @@ -69,7 +69,7 @@ debug("Got slave_fd '%d'" % slave_fd) except OSError: # " An optional feature could not be imported " ... ? - raise TestSkipped, "Pseudo-terminals (seemingly) not functional." + raise SkipTest, "Pseudo-terminals (seemingly) not functional." self.assertTrue(os.isatty(slave_fd), 'slave_fd is not a tty') Modified: python/trunk/Lib/test/test_py3kwarn.py ============================================================================== --- python/trunk/Lib/test/test_py3kwarn.py (original) +++ python/trunk/Lib/test/test_py3kwarn.py Thu Mar 26 21:48:25 2009 @@ -1,13 +1,13 @@ import unittest import sys from test.test_support import (check_warnings, CleanImport, - TestSkipped, run_unittest) + SkipTest, run_unittest) import warnings from contextlib import nested if not sys.py3kwarning: - raise TestSkipped('%s must be run with the -3 flag' % __name__) + raise SkipTest('%s must be run with the -3 flag' % __name__) def reset_module_registry(module): try: Modified: python/trunk/Lib/test/test_signal.py ============================================================================== --- python/trunk/Lib/test/test_signal.py (original) +++ python/trunk/Lib/test/test_signal.py Thu Mar 26 21:48:25 2009 @@ -10,7 +10,7 @@ import sys, os, time, errno if sys.platform[:3] in ('win', 'os2') or sys.platform == 'riscos': - raise test_support.TestSkipped("Can't test signal on %s" % \ + raise unittest.SkipTest("Can't test signal on %s" % \ sys.platform) Modified: python/trunk/Lib/test/test_site.py ============================================================================== --- python/trunk/Lib/test/test_site.py (original) +++ python/trunk/Lib/test/test_site.py Thu Mar 26 21:48:25 2009 @@ -5,7 +5,7 @@ """ import unittest -from test.test_support import TestSkipped, run_unittest, TESTFN +from test.test_support import SkipTest, run_unittest, TESTFN import __builtin__ import os import sys @@ -17,7 +17,7 @@ if "site" in sys.modules: import site else: - raise TestSkipped("importation of site.py suppressed") + raise SkipTest("importation of site.py suppressed") if not os.path.isdir(site.USER_SITE): # need to add user site directory for tests Modified: python/trunk/Lib/test/test_socketserver.py ============================================================================== --- python/trunk/Lib/test/test_socketserver.py (original) +++ python/trunk/Lib/test/test_socketserver.py Thu Mar 26 21:48:25 2009 @@ -16,7 +16,7 @@ import SocketServer import test.test_support -from test.test_support import reap_children, verbose, TestSkipped +from test.test_support import reap_children, verbose, SkipTest from test.test_support import TESTFN as TEST_FILE test.test_support.requires("network") @@ -247,7 +247,7 @@ def test_main(): if imp.lock_held(): # If the import lock is held, the threads will hang - raise TestSkipped("can't run when import lock is held") + raise SkipTest("can't run when import lock is held") test.test_support.run_unittest(SocketServerTest) Modified: python/trunk/Lib/test/test_sqlite.py ============================================================================== --- python/trunk/Lib/test/test_sqlite.py (original) +++ python/trunk/Lib/test/test_sqlite.py Thu Mar 26 21:48:25 2009 @@ -1,9 +1,9 @@ -from test.test_support import run_unittest, TestSkipped +from test.test_support import run_unittest, SkipTest try: import _sqlite3 except ImportError: - raise TestSkipped('no sqlite available') + raise SkipTest('no sqlite available') from sqlite3.test import (dbapi, types, userfunctions, py25tests, factory, transactions, hooks, regression, dump) Modified: python/trunk/Lib/test/test_ssl.py ============================================================================== --- python/trunk/Lib/test/test_ssl.py (original) +++ python/trunk/Lib/test/test_ssl.py Thu Mar 26 21:48:25 2009 @@ -1167,7 +1167,7 @@ def test_main(verbose=False): if skip_expected: - raise test_support.TestSkipped("No SSL support") + raise unittest.SkipTest("No SSL support") global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, Modified: python/trunk/Lib/test/test_sunaudiodev.py ============================================================================== --- python/trunk/Lib/test/test_sunaudiodev.py (original) +++ python/trunk/Lib/test/test_sunaudiodev.py Thu Mar 26 21:48:25 2009 @@ -1,4 +1,4 @@ -from test.test_support import findfile, TestFailed, TestSkipped, import_module +from test.test_support import findfile, TestFailed, SkipTest, import_module sunaudiodev = import_module('sunaudiodev', deprecated=True) import os @@ -8,7 +8,7 @@ audiodev = "/dev/audio" if not os.path.exists(audiodev): - raise TestSkipped("no audio device found!") + raise SkipTest("no audio device found!") def play_sound_file(path): fp = open(path, 'r') Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Thu Mar 26 21:48:25 2009 @@ -13,7 +13,7 @@ import warnings import unittest -__all__ = ["Error", "TestFailed", "TestSkipped", "ResourceDenied", "import_module", +__all__ = ["Error", "TestFailed", "ResourceDenied", "import_module", "verbose", "use_resources", "max_memuse", "record_original_stdout", "get_original_stdout", "unload", "unlink", "rmtree", "forget", "is_resource_enabled", "requires", "find_unused_port", "bind_port", @@ -33,17 +33,7 @@ class TestFailed(Error): """Test failed.""" -class TestSkipped(Error): - """Test skipped. - - This can be raised to indicate that a test was deliberatly - skipped, but not because a feature wasn't available. For - example, if some resource can't be used, such as the network - appears to be unavailable, this should be raised instead of - TestFailed. - """ - -class ResourceDenied(TestSkipped): +class ResourceDenied(SkipTest): """Test skipped because it requested a disallowed resource. This is raised when a test calls requires() for a resource that @@ -52,7 +42,7 @@ """ def import_module(name, deprecated=False): - """Import the module to be tested, raising TestSkipped if it is not + """Import the module to be tested, raising SkipTest if it is not available.""" with warnings.catch_warnings(): if deprecated: @@ -61,7 +51,7 @@ try: module = __import__(name, level=0) except ImportError: - raise TestSkipped("No module named " + name) + raise SkipTest("No module named " + name) else: return module Modified: python/trunk/Lib/test/test_tempfile.py ============================================================================== --- python/trunk/Lib/test/test_tempfile.py (original) +++ python/trunk/Lib/test/test_tempfile.py Thu Mar 26 21:48:25 2009 @@ -259,7 +259,7 @@ def test_file_mode(self): # _mkstemp_inner creates files with the proper mode if not has_stat: - return # ugh, can't use TestSkipped. + return # ugh, can't use SkipTest. file = self.do_create() mode = stat.S_IMODE(os.stat(file.name).st_mode) @@ -274,7 +274,7 @@ def test_noinherit(self): # _mkstemp_inner file handles are not inherited by child processes if not has_spawnl: - return # ugh, can't use TestSkipped. + return # ugh, can't use SkipTest. if test_support.verbose: v="v" @@ -312,7 +312,7 @@ def test_textmode(self): # _mkstemp_inner can create files in text mode if not has_textmode: - return # ugh, can't use TestSkipped. + return # ugh, can't use SkipTest. self.do_create(bin=0).write("blat\n") # XXX should test that the file really is a text file @@ -476,7 +476,7 @@ def test_mode(self): # mkdtemp creates directories with the proper mode if not has_stat: - return # ugh, can't use TestSkipped. + return # ugh, can't use SkipTest. dir = self.do_create() try: Modified: python/trunk/Lib/test/test_threaded_import.py ============================================================================== --- python/trunk/Lib/test/test_threaded_import.py (original) +++ python/trunk/Lib/test/test_threaded_import.py Thu Mar 26 21:48:25 2009 @@ -6,7 +6,7 @@ # randrange, and then Python hangs. import thread -from test.test_support import verbose, TestSkipped, TestFailed +from test.test_support import verbose, SkipTest, TestFailed critical_section = thread.allocate_lock() done = thread.allocate_lock() @@ -56,7 +56,7 @@ import imp if imp.lock_held(): # This triggers on, e.g., from test import autotest. - raise TestSkipped("can't run when import lock is held") + raise SkipTest("can't run when import lock is held") done.acquire() for N in (20, 50) * 3: Modified: python/trunk/Lib/test/test_threadsignals.py ============================================================================== --- python/trunk/Lib/test/test_threadsignals.py (original) +++ python/trunk/Lib/test/test_threadsignals.py Thu Mar 26 21:48:25 2009 @@ -5,10 +5,10 @@ import signal import os import sys -from test.test_support import run_unittest, TestSkipped +from test.test_support import run_unittest, SkipTest if sys.platform[:3] in ('win', 'os2') or sys.platform=='riscos': - raise TestSkipped, "Can't test signal on %s" % sys.platform + raise SkipTest, "Can't test signal on %s" % sys.platform process_pid = os.getpid() signalled_all=thread.allocate_lock() Modified: python/trunk/Lib/test/test_tk.py ============================================================================== --- python/trunk/Lib/test/test_tk.py (original) +++ python/trunk/Lib/test/test_tk.py Thu Mar 26 21:48:25 2009 @@ -7,7 +7,7 @@ Tkinter.Button() except Tkinter.TclError, msg: # assuming tk is not available - raise test_support.TestSkipped("tk not available: %s" % msg) + raise unittest.SkipTest("tk not available: %s" % msg) this_dir = os.path.dirname(os.path.abspath(__file__)) lib_tk_test = os.path.abspath(os.path.join(this_dir, os.path.pardir, Modified: python/trunk/Lib/test/test_ttk_guionly.py ============================================================================== --- python/trunk/Lib/test/test_ttk_guionly.py (original) +++ python/trunk/Lib/test/test_ttk_guionly.py Thu Mar 26 21:48:25 2009 @@ -8,7 +8,7 @@ ttk.Button() except TclError, msg: # assuming ttk is not available - raise test_support.TestSkipped("ttk not available: %s" % msg) + raise unittest.SkipTest("ttk not available: %s" % msg) this_dir = os.path.dirname(os.path.abspath(__file__)) lib_tk_test = os.path.abspath(os.path.join(this_dir, os.path.pardir, 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 Thu Mar 26 21:48:25 2009 @@ -5,14 +5,14 @@ import unicodedata import unittest -from test.test_support import run_unittest, TestSkipped, TESTFN_UNICODE +from test.test_support import run_unittest, SkipTest, TESTFN_UNICODE from test.test_support import TESTFN_ENCODING, TESTFN_UNICODE_UNENCODEABLE try: TESTFN_ENCODED = TESTFN_UNICODE.encode(TESTFN_ENCODING) except (UnicodeError, TypeError): # Either the file system encoding is None, or the file name # cannot be encoded in the file system encoding. - raise TestSkipped("No Unicode filesystem semantics on this platform.") + raise SkipTest("No Unicode filesystem semantics on this platform.") if TESTFN_ENCODED.decode(TESTFN_ENCODING) != TESTFN_UNICODE: # The file system encoding does not support Latin-1 @@ -26,10 +26,10 @@ # MBCS will not report the error properly raise UnicodeError, "mbcs encoding problem" except (UnicodeError, TypeError): - raise TestSkipped("Cannot find a suiteable filename.") + raise SkipTest("Cannot find a suiteable filename.") if TESTFN_ENCODED.decode(TESTFN_ENCODING) != TESTFN_UNICODE: - raise TestSkipped("Cannot find a suitable filename.") + raise SkipTest("Cannot find a suitable filename.") def remove_if_exists(filename): if os.path.exists(filename): Modified: python/trunk/Lib/test/test_univnewlines.py ============================================================================== --- python/trunk/Lib/test/test_univnewlines.py (original) +++ python/trunk/Lib/test/test_univnewlines.py Thu Mar 26 21:48:25 2009 @@ -5,7 +5,7 @@ from test import test_support if not hasattr(sys.stdin, 'newlines'): - raise test_support.TestSkipped, \ + raise unittest.SkipTest, \ "This Python does not have universal newline support" FATX = 'x' * (2**14) Modified: python/trunk/Lib/test/test_wait3.py ============================================================================== --- python/trunk/Lib/test/test_wait3.py (original) +++ python/trunk/Lib/test/test_wait3.py Thu Mar 26 21:48:25 2009 @@ -4,17 +4,17 @@ import os import time from test.fork_wait import ForkWait -from test.test_support import TestSkipped, run_unittest, reap_children +from test.test_support import SkipTest, run_unittest, reap_children try: os.fork except AttributeError: - raise TestSkipped, "os.fork not defined -- skipping test_wait3" + raise SkipTest, "os.fork not defined -- skipping test_wait3" try: os.wait3 except AttributeError: - raise TestSkipped, "os.wait3 not defined -- skipping test_wait3" + raise SkipTest, "os.wait3 not defined -- skipping test_wait3" class Wait3Test(ForkWait): def wait_impl(self, cpid): Modified: python/trunk/Lib/test/test_wait4.py ============================================================================== --- python/trunk/Lib/test/test_wait4.py (original) +++ python/trunk/Lib/test/test_wait4.py Thu Mar 26 21:48:25 2009 @@ -4,17 +4,17 @@ import os import time from test.fork_wait import ForkWait -from test.test_support import TestSkipped, run_unittest, reap_children +from test.test_support import SkipTest, run_unittest, reap_children try: os.fork except AttributeError: - raise TestSkipped, "os.fork not defined -- skipping test_wait4" + raise SkipTest, "os.fork not defined -- skipping test_wait4" try: os.wait4 except AttributeError: - raise TestSkipped, "os.wait4 not defined -- skipping test_wait4" + raise SkipTest, "os.wait4 not defined -- skipping test_wait4" class Wait4Test(ForkWait): def wait_impl(self, cpid): From python-checkins at python.org Thu Mar 26 21:49:40 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 21:49:40 +0100 (CET) Subject: [Python-checkins] r70619 - python/trunk/Lib/test/test_support.py Message-ID: <20090326204940.E02351E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 21:49:40 2009 New Revision: 70619 Log: fix naming Modified: python/trunk/Lib/test/test_support.py Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Thu Mar 26 21:49:40 2009 @@ -33,7 +33,7 @@ class TestFailed(Error): """Test failed.""" -class ResourceDenied(SkipTest): +class ResourceDenied(unittest.SkipTest): """Test skipped because it requested a disallowed resource. This is raised when a test calls requires() for a resource that From ncoghlan at gmail.com Thu Mar 26 22:08:58 2009 From: ncoghlan at gmail.com (Nick Coghlan) Date: Fri, 27 Mar 2009 07:08:58 +1000 Subject: [Python-checkins] r70615 - python/trunk/Lib/test/test_support.py In-Reply-To: <20090326195819.0384C1E4002@bag.python.org> References: <20090326195819.0384C1E4002@bag.python.org> Message-ID: <49CBEEEA.80909@gmail.com> benjamin.peterson wrote: > Modified: python/trunk/Lib/test/test_support.py > ============================================================================== > --- python/trunk/Lib/test/test_support.py (original) > +++ python/trunk/Lib/test/test_support.py Thu Mar 26 20:58:18 2009 > +def impl_detail(msg=None, **guards): > + if check_impl_detail(): > + return _id You want to pass "guards" down to check_impl_detail() here. Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- From python-checkins at python.org Thu Mar 26 22:10:31 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 22:10:31 +0100 (CET) Subject: [Python-checkins] r70620 - in python/trunk/Lib/test: test__locale.py test_commands.py test_curses.py test_decimal.py test_dl.py test_fork1.py test_gl.py test_ioctl.py test_largefile.py test_linuxaudiodev.py test_locale.py test_mhlib.py test_minidom.py test_multiprocessing.py test_openpty.py test_ossaudiodev.py test_pipes.py test_poll.py test_popen2.py test_pty.py test_py3kwarn.py test_site.py test_socketserver.py test_sqlite.py test_sunaudiodev.py test_support.py test_threaded_import.py test_threadsignals.py test_unicode_file.py test_wait3.py test_wait4.py Message-ID: <20090326211031.573F41E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 22:10:30 2009 New Revision: 70620 Log: fix incorrect auto-translation of TestSkipped -> unittest.SkipTest Modified: python/trunk/Lib/test/test__locale.py python/trunk/Lib/test/test_commands.py python/trunk/Lib/test/test_curses.py python/trunk/Lib/test/test_decimal.py python/trunk/Lib/test/test_dl.py python/trunk/Lib/test/test_fork1.py python/trunk/Lib/test/test_gl.py python/trunk/Lib/test/test_ioctl.py python/trunk/Lib/test/test_largefile.py python/trunk/Lib/test/test_linuxaudiodev.py python/trunk/Lib/test/test_locale.py python/trunk/Lib/test/test_mhlib.py python/trunk/Lib/test/test_minidom.py python/trunk/Lib/test/test_multiprocessing.py python/trunk/Lib/test/test_openpty.py python/trunk/Lib/test/test_ossaudiodev.py python/trunk/Lib/test/test_pipes.py python/trunk/Lib/test/test_poll.py python/trunk/Lib/test/test_popen2.py python/trunk/Lib/test/test_pty.py python/trunk/Lib/test/test_py3kwarn.py python/trunk/Lib/test/test_site.py python/trunk/Lib/test/test_socketserver.py python/trunk/Lib/test/test_sqlite.py python/trunk/Lib/test/test_sunaudiodev.py python/trunk/Lib/test/test_support.py python/trunk/Lib/test/test_threaded_import.py python/trunk/Lib/test/test_threadsignals.py python/trunk/Lib/test/test_unicode_file.py python/trunk/Lib/test/test_wait3.py python/trunk/Lib/test/test_wait4.py Modified: python/trunk/Lib/test/test__locale.py ============================================================================== --- python/trunk/Lib/test/test__locale.py (original) +++ python/trunk/Lib/test/test__locale.py Thu Mar 26 22:10:30 2009 @@ -1,4 +1,4 @@ -from test.test_support import verbose, SkipTest, run_unittest +from test.test_support import verbose, run_unittest from _locale import (setlocale, LC_NUMERIC, RADIXCHAR, THOUSEP, nl_langinfo, localeconv, Error) import unittest @@ -7,7 +7,7 @@ if uname()[0] == "Darwin": maj, min, mic = [int(part) for part in uname()[2].split(".")] if (maj, min, mic) < (8, 0, 0): - raise SkipTest("locale support broken for OS X < 10.4") + raise unittest.SkipTest("locale support broken for OS X < 10.4") candidate_locales = ['es_UY', 'fr_FR', 'fi_FI', 'es_CO', 'pt_PT', 'it_IT', 'et_EE', 'es_PY', 'no_NO', 'nl_NL', 'lv_LV', 'el_GR', 'be_BY', 'fr_BE', Modified: python/trunk/Lib/test/test_commands.py ============================================================================== --- python/trunk/Lib/test/test_commands.py (original) +++ python/trunk/Lib/test/test_commands.py Thu Mar 26 22:10:30 2009 @@ -9,7 +9,7 @@ warnings.filterwarnings('ignore', r".*commands.getstatus.. is deprecated", DeprecationWarning) -from test.test_support import SkipTest, run_unittest, reap_children +from test.test_support import run_unittest, reap_children from commands import * # The module says: @@ -19,7 +19,7 @@ # I'll take the comment as given, and skip this suite. if os.name != 'posix': - raise SkipTest('Not posix; skipping test_commands') + raise unittest.SkipTest('Not posix; skipping test_commands') class CommandTests(unittest.TestCase): Modified: python/trunk/Lib/test/test_curses.py ============================================================================== --- python/trunk/Lib/test/test_curses.py (original) +++ python/trunk/Lib/test/test_curses.py Thu Mar 26 22:10:30 2009 @@ -16,16 +16,16 @@ # 'curses' resource be given on the regrtest command line using the -u # option. If not available, nothing after this line will be executed. -from test.test_support import requires, SkipTest +from test.test_support import requires requires('curses') # XXX: if newterm was supported we could use it instead of initscr and not exit term = os.environ.get('TERM') if not term or term == 'unknown': - raise SkipTest, "$TERM=%r, calling initscr() may cause exit" % term + raise unittest.SkipTest, "$TERM=%r, calling initscr() may cause exit" % term if sys.platform == "cygwin": - raise SkipTest("cygwin's curses mostly just hangs") + raise unittest.SkipTest("cygwin's curses mostly just hangs") def window_funcs(stdscr): "Test the methods of windows" Modified: python/trunk/Lib/test/test_decimal.py ============================================================================== --- python/trunk/Lib/test/test_decimal.py (original) +++ python/trunk/Lib/test/test_decimal.py Thu Mar 26 22:10:30 2009 @@ -31,8 +31,7 @@ import unittest from decimal import * import numbers -from test.test_support import (SkipTest, run_unittest, run_doctest, - is_resource_enabled) +from test.test_support import (run_unittest, run_doctest, is_resource_enabled) import random try: import threading @@ -194,7 +193,7 @@ def eval_file(self, file): global skip_expected if skip_expected: - raise SkipTest + raise unittest.SkipTest return for line in open(file).xreadlines(): line = line.replace('\r\n', '').replace('\n', '') Modified: python/trunk/Lib/test/test_dl.py ============================================================================== --- python/trunk/Lib/test/test_dl.py (original) +++ python/trunk/Lib/test/test_dl.py Thu Mar 26 22:10:30 2009 @@ -2,7 +2,7 @@ """Test dlmodule.c Roger E. Masse revised strategy by Barry Warsaw """ -from test.test_support import verbose,SkipTest, import_module +from test.test_support import verbose, import_module dl = import_module('dl', deprecated=True) sharedlibs = [ @@ -31,7 +31,7 @@ print 'worked!' break else: - raise SkipTest, 'Could not open any shared libraries' + raise unittest.SkipTest, 'Could not open any shared libraries' if __name__ == '__main__': Modified: python/trunk/Lib/test/test_fork1.py ============================================================================== --- python/trunk/Lib/test/test_fork1.py (original) +++ python/trunk/Lib/test/test_fork1.py Thu Mar 26 22:10:30 2009 @@ -4,12 +4,12 @@ import os import time from test.fork_wait import ForkWait -from test.test_support import SkipTest, run_unittest, reap_children +from test.test_support import run_unittest, reap_children try: os.fork except AttributeError: - raise SkipTest, "os.fork not defined -- skipping test_fork1" + raise unittest.SkipTest, "os.fork not defined -- skipping test_fork1" class ForkTest(ForkWait): def wait_impl(self, cpid): Modified: python/trunk/Lib/test/test_gl.py ============================================================================== --- python/trunk/Lib/test/test_gl.py (original) +++ python/trunk/Lib/test/test_gl.py Thu Mar 26 22:10:30 2009 @@ -3,7 +3,7 @@ taken mostly from the documentation. Roger E. Masse """ -from test.test_support import verbose, SkipTest +from test.test_support import verbose import gl, GL, time glattrs = ['RGBcolor', 'RGBcursor', 'RGBmode', 'RGBrange', 'RGBwritemask', @@ -87,7 +87,7 @@ try: display = os.environ['DISPLAY'] except: - raise SkipTest, "No $DISPLAY -- skipping gl test" + raise unittest.SkipTest, "No $DISPLAY -- skipping gl test" # touch all the attributes of gl without doing anything if verbose: Modified: python/trunk/Lib/test/test_ioctl.py ============================================================================== --- python/trunk/Lib/test/test_ioctl.py (original) +++ python/trunk/Lib/test/test_ioctl.py Thu Mar 26 22:10:30 2009 @@ -1,18 +1,18 @@ import unittest -from test.test_support import SkipTest, run_unittest +from test.test_support import run_unittest import os, struct try: import fcntl, termios except ImportError: - raise SkipTest("No fcntl or termios module") + raise unittest.SkipTest("No fcntl or termios module") if not hasattr(termios,'TIOCGPGRP'): - raise SkipTest("termios module doesn't have TIOCGPGRP") + raise unittest.SkipTest("termios module doesn't have TIOCGPGRP") try: tty = open("/dev/tty", "r") tty.close() except IOError: - raise SkipTest("Unable to open /dev/tty") + raise unittest.SkipTest("Unable to open /dev/tty") try: import pty @@ -41,7 +41,7 @@ def test_ioctl_signed_unsigned_code_param(self): if not pty: - raise SkipTest('pty module required') + raise unittest.SkipTest('pty module required') mfd, sfd = pty.openpty() try: if termios.TIOCSWINSZ < 0: Modified: python/trunk/Lib/test/test_largefile.py ============================================================================== --- python/trunk/Lib/test/test_largefile.py (original) +++ python/trunk/Lib/test/test_largefile.py Thu Mar 26 22:10:30 2009 @@ -6,7 +6,7 @@ import sys import unittest from test.test_support import run_unittest, TESTFN, verbose, requires, \ - SkipTest, unlink + unlink try: import signal @@ -104,7 +104,7 @@ # this is already decided before start running the test suite # but we do it anyway for extra protection if not hasattr(f, 'truncate'): - raise SkipTest, "open().truncate() not available on this system" + raise unittest.SkipTest, "open().truncate() not available on this system" f.seek(0, 2) # else we've lost track of the true size self.assertEqual(f.tell(), size+1) @@ -155,7 +155,7 @@ except (IOError, OverflowError): f.close() unlink(TESTFN) - raise SkipTest, "filesystem does not have largefile support" + raise unittest.SkipTest, "filesystem does not have largefile support" else: f.close() suite = unittest.TestSuite() Modified: python/trunk/Lib/test/test_linuxaudiodev.py ============================================================================== --- python/trunk/Lib/test/test_linuxaudiodev.py (original) +++ python/trunk/Lib/test/test_linuxaudiodev.py Thu Mar 26 22:10:30 2009 @@ -1,7 +1,7 @@ from test import test_support test_support.requires('audio') -from test.test_support import findfile, SkipTest, run_unittest +from test.test_support import findfile, run_unittest import errno linuxaudiodev = test_support.import_module('linuxaudiodev', deprecated=True) @@ -89,7 +89,7 @@ dsp = linuxaudiodev.open('w') except linuxaudiodev.error, msg: if msg.args[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): - raise SkipTest(msg) + raise unittest.SkipTest(msg) raise dsp.close() run_unittest(LinuxAudioDevTests) Modified: python/trunk/Lib/test/test_locale.py ============================================================================== --- python/trunk/Lib/test/test_locale.py (original) +++ python/trunk/Lib/test/test_locale.py Thu Mar 26 22:10:30 2009 @@ -1,4 +1,4 @@ -from test.test_support import run_unittest, verbose, SkipTest +from test.test_support import run_unittest, verbose import unittest import locale import sys @@ -10,7 +10,7 @@ def get_enUS_locale(): global enUS_locale if sys.platform == 'darwin': - raise SkipTest("Locale support on MacOSX is minimal") + raise unittest.SkipTest("Locale support on MacOSX is minimal") if sys.platform.startswith("win"): tlocs = ("En", "English") else: @@ -23,7 +23,7 @@ continue break else: - raise SkipTest( + raise unittest.SkipTest( "Test locale not supported (tried %s)" % (', '.join(tlocs))) enUS_locale = tloc locale.setlocale(locale.LC_NUMERIC, oldlocale) Modified: python/trunk/Lib/test/test_mhlib.py ============================================================================== --- python/trunk/Lib/test/test_mhlib.py (original) +++ python/trunk/Lib/test/test_mhlib.py Thu Mar 26 22:10:30 2009 @@ -7,7 +7,7 @@ ### mhlib. It should. import unittest -from test.test_support import run_unittest, TESTFN, SkipTest, import_module +from test.test_support import run_unittest, TESTFN, import_module import os, StringIO import sys mhlib = import_module('mhlib', deprecated=True) @@ -21,8 +21,8 @@ # link counts, and that causes test_listfolders() here to get back # an empty list from its call of listallfolders(). # The other tests here pass on Windows. - raise SkipTest("skipped on %s -- " % sys.platform + - "too many Unix assumptions") + raise unittest.SkipTest("skipped on %s -- " % sys.platform + + "too many Unix assumptions") _mhroot = TESTFN+"_MH" _mhpath = os.path.join(_mhroot, "MH") Modified: python/trunk/Lib/test/test_minidom.py ============================================================================== --- python/trunk/Lib/test/test_minidom.py (original) +++ python/trunk/Lib/test/test_minidom.py Thu Mar 26 22:10:30 2009 @@ -4,7 +4,7 @@ import sys import pickle from StringIO import StringIO -from test.test_support import verbose, run_unittest, SkipTest +from test.test_support import verbose, run_unittest import unittest import xml.dom Modified: python/trunk/Lib/test/test_multiprocessing.py ============================================================================== --- python/trunk/Lib/test/test_multiprocessing.py (original) +++ python/trunk/Lib/test/test_multiprocessing.py Thu Mar 26 22:10:30 2009 @@ -23,8 +23,7 @@ try: import multiprocessing.synchronize except ImportError, e: - from test.test_support import SkipTest - raise SkipTest(e) + raise unittest.SkipTest(e) import multiprocessing.dummy import multiprocessing.connection @@ -1813,7 +1812,7 @@ lock = multiprocessing.RLock() except OSError: from test.test_support import SkipTest - raise SkipTest("OSError raises on RLock creation, see issue 3111!") + raise unittest.SkipTest("OSError raises on RLock creation, see issue 3111!") if run is None: from test.test_support import run_unittest as run Modified: python/trunk/Lib/test/test_openpty.py ============================================================================== --- python/trunk/Lib/test/test_openpty.py (original) +++ python/trunk/Lib/test/test_openpty.py Thu Mar 26 22:10:30 2009 @@ -1,10 +1,10 @@ # Test to see if openpty works. (But don't worry if it isn't available.) import os, unittest -from test.test_support import run_unittest, SkipTest +from test.test_support import run_unittest if not hasattr(os, "openpty"): - raise SkipTest, "No openpty() available." + raise unittest.SkipTest, "No openpty() available." class OpenptyTest(unittest.TestCase): Modified: python/trunk/Lib/test/test_ossaudiodev.py ============================================================================== --- python/trunk/Lib/test/test_ossaudiodev.py (original) +++ python/trunk/Lib/test/test_ossaudiodev.py Thu Mar 26 22:10:30 2009 @@ -1,7 +1,7 @@ from test import test_support test_support.requires('audio') -from test.test_support import findfile, SkipTest +from test.test_support import findfile import errno import ossaudiodev @@ -45,7 +45,7 @@ dsp = ossaudiodev.open('w') except IOError, msg: if msg[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): - raise SkipTest(msg) + raise unittest.SkipTest(msg) raise # at least check that these methods can be invoked @@ -162,7 +162,7 @@ dsp = ossaudiodev.open('w') except (ossaudiodev.error, IOError), msg: if msg[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): - raise SkipTest(msg) + raise unittest.SkipTest(msg) raise dsp.close() test_support.run_unittest(__name__) Modified: python/trunk/Lib/test/test_pipes.py ============================================================================== --- python/trunk/Lib/test/test_pipes.py (original) +++ python/trunk/Lib/test/test_pipes.py Thu Mar 26 22:10:30 2009 @@ -2,10 +2,10 @@ import os import string import unittest -from test.test_support import TESTFN, run_unittest, unlink, SkipTest +from test.test_support import TESTFN, run_unittest, unlink if os.name != 'posix': - raise SkipTest('pipes module only works on posix') + raise unittest.SkipTest('pipes module only works on posix') TESTFN2 = TESTFN + "2" Modified: python/trunk/Lib/test/test_poll.py ============================================================================== --- python/trunk/Lib/test/test_poll.py (original) +++ python/trunk/Lib/test/test_poll.py Thu Mar 26 22:10:30 2009 @@ -1,12 +1,12 @@ # Test case for the os.poll() function import os, select, random, unittest -from test.test_support import SkipTest, TESTFN, run_unittest +from test.test_support import TESTFN, run_unittest try: select.poll except AttributeError: - raise SkipTest, "select.poll not defined -- skipping test_poll" + raise unittest.SkipTest, "select.poll not defined -- skipping test_poll" def find_ready_matching(ready, flag): Modified: python/trunk/Lib/test/test_popen2.py ============================================================================== --- python/trunk/Lib/test/test_popen2.py (original) +++ python/trunk/Lib/test/test_popen2.py Thu Mar 26 22:10:30 2009 @@ -12,13 +12,13 @@ import unittest import popen2 -from test.test_support import SkipTest, run_unittest, reap_children +from test.test_support import 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 SkipTest("popen2() doesn't work on " + sys.platform) + raise unittest.SkipTest("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 Modified: python/trunk/Lib/test/test_pty.py ============================================================================== --- python/trunk/Lib/test/test_pty.py (original) +++ python/trunk/Lib/test/test_pty.py Thu Mar 26 22:10:30 2009 @@ -4,7 +4,7 @@ import os import sys import signal -from test.test_support import verbose, SkipTest, run_unittest +from test.test_support import verbose, run_unittest import unittest TEST_STRING_1 = "I wish to buy a fish license.\n" @@ -69,7 +69,7 @@ debug("Got slave_fd '%d'" % slave_fd) except OSError: # " An optional feature could not be imported " ... ? - raise SkipTest, "Pseudo-terminals (seemingly) not functional." + raise unittest.SkipTest, "Pseudo-terminals (seemingly) not functional." self.assertTrue(os.isatty(slave_fd), 'slave_fd is not a tty') Modified: python/trunk/Lib/test/test_py3kwarn.py ============================================================================== --- python/trunk/Lib/test/test_py3kwarn.py (original) +++ python/trunk/Lib/test/test_py3kwarn.py Thu Mar 26 22:10:30 2009 @@ -1,13 +1,12 @@ import unittest import sys -from test.test_support import (check_warnings, CleanImport, - SkipTest, run_unittest) +from test.test_support import check_warnings, CleanImport, run_unittest import warnings from contextlib import nested if not sys.py3kwarning: - raise SkipTest('%s must be run with the -3 flag' % __name__) + raise unittest.SkipTest('%s must be run with the -3 flag' % __name__) def reset_module_registry(module): try: Modified: python/trunk/Lib/test/test_site.py ============================================================================== --- python/trunk/Lib/test/test_site.py (original) +++ python/trunk/Lib/test/test_site.py Thu Mar 26 22:10:30 2009 @@ -5,7 +5,7 @@ """ import unittest -from test.test_support import SkipTest, run_unittest, TESTFN +from test.test_support import run_unittest, TESTFN import __builtin__ import os import sys @@ -17,7 +17,7 @@ if "site" in sys.modules: import site else: - raise SkipTest("importation of site.py suppressed") + raise unittest.SkipTest("importation of site.py suppressed") if not os.path.isdir(site.USER_SITE): # need to add user site directory for tests Modified: python/trunk/Lib/test/test_socketserver.py ============================================================================== --- python/trunk/Lib/test/test_socketserver.py (original) +++ python/trunk/Lib/test/test_socketserver.py Thu Mar 26 22:10:30 2009 @@ -16,7 +16,7 @@ import SocketServer import test.test_support -from test.test_support import reap_children, verbose, SkipTest +from test.test_support import reap_children, verbose from test.test_support import TESTFN as TEST_FILE test.test_support.requires("network") @@ -247,7 +247,7 @@ def test_main(): if imp.lock_held(): # If the import lock is held, the threads will hang - raise SkipTest("can't run when import lock is held") + raise unittest.SkipTest("can't run when import lock is held") test.test_support.run_unittest(SocketServerTest) Modified: python/trunk/Lib/test/test_sqlite.py ============================================================================== --- python/trunk/Lib/test/test_sqlite.py (original) +++ python/trunk/Lib/test/test_sqlite.py Thu Mar 26 22:10:30 2009 @@ -1,9 +1,10 @@ -from test.test_support import run_unittest, SkipTest +import unittest +from test.test_support import run_unittest try: import _sqlite3 except ImportError: - raise SkipTest('no sqlite available') + raise unittest.SkipTest('no sqlite available') from sqlite3.test import (dbapi, types, userfunctions, py25tests, factory, transactions, hooks, regression, dump) Modified: python/trunk/Lib/test/test_sunaudiodev.py ============================================================================== --- python/trunk/Lib/test/test_sunaudiodev.py (original) +++ python/trunk/Lib/test/test_sunaudiodev.py Thu Mar 26 22:10:30 2009 @@ -1,4 +1,5 @@ -from test.test_support import findfile, TestFailed, SkipTest, import_module +from test.test_support import findfile, TestFailed, import_module +import unittest sunaudiodev = import_module('sunaudiodev', deprecated=True) import os @@ -8,7 +9,7 @@ audiodev = "/dev/audio" if not os.path.exists(audiodev): - raise SkipTest("no audio device found!") + raise unittest.SkipTest("no audio device found!") def play_sound_file(path): fp = open(path, 'r') Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Thu Mar 26 22:10:30 2009 @@ -51,7 +51,7 @@ try: module = __import__(name, level=0) except ImportError: - raise SkipTest("No module named " + name) + raise unittest.SkipTest("No module named " + name) else: return module Modified: python/trunk/Lib/test/test_threaded_import.py ============================================================================== --- python/trunk/Lib/test/test_threaded_import.py (original) +++ python/trunk/Lib/test/test_threaded_import.py Thu Mar 26 22:10:30 2009 @@ -6,7 +6,7 @@ # randrange, and then Python hangs. import thread -from test.test_support import verbose, SkipTest, TestFailed +from test.test_support import verbose, TestFailed critical_section = thread.allocate_lock() done = thread.allocate_lock() @@ -56,7 +56,7 @@ import imp if imp.lock_held(): # This triggers on, e.g., from test import autotest. - raise SkipTest("can't run when import lock is held") + raise unittest.SkipTest("can't run when import lock is held") done.acquire() for N in (20, 50) * 3: Modified: python/trunk/Lib/test/test_threadsignals.py ============================================================================== --- python/trunk/Lib/test/test_threadsignals.py (original) +++ python/trunk/Lib/test/test_threadsignals.py Thu Mar 26 22:10:30 2009 @@ -5,10 +5,10 @@ import signal import os import sys -from test.test_support import run_unittest, SkipTest +from test.test_support import run_unittest if sys.platform[:3] in ('win', 'os2') or sys.platform=='riscos': - raise SkipTest, "Can't test signal on %s" % sys.platform + raise unittest.SkipTest, "Can't test signal on %s" % sys.platform process_pid = os.getpid() signalled_all=thread.allocate_lock() 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 Thu Mar 26 22:10:30 2009 @@ -5,14 +5,14 @@ import unicodedata import unittest -from test.test_support import run_unittest, SkipTest, TESTFN_UNICODE +from test.test_support import run_unittest, TESTFN_UNICODE from test.test_support import TESTFN_ENCODING, TESTFN_UNICODE_UNENCODEABLE try: TESTFN_ENCODED = TESTFN_UNICODE.encode(TESTFN_ENCODING) except (UnicodeError, TypeError): # Either the file system encoding is None, or the file name # cannot be encoded in the file system encoding. - raise SkipTest("No Unicode filesystem semantics on this platform.") + raise unittest.SkipTest("No Unicode filesystem semantics on this platform.") if TESTFN_ENCODED.decode(TESTFN_ENCODING) != TESTFN_UNICODE: # The file system encoding does not support Latin-1 @@ -26,10 +26,10 @@ # MBCS will not report the error properly raise UnicodeError, "mbcs encoding problem" except (UnicodeError, TypeError): - raise SkipTest("Cannot find a suiteable filename.") + raise unittest.SkipTest("Cannot find a suiteable filename.") if TESTFN_ENCODED.decode(TESTFN_ENCODING) != TESTFN_UNICODE: - raise SkipTest("Cannot find a suitable filename.") + raise unittest.SkipTest("Cannot find a suitable filename.") def remove_if_exists(filename): if os.path.exists(filename): Modified: python/trunk/Lib/test/test_wait3.py ============================================================================== --- python/trunk/Lib/test/test_wait3.py (original) +++ python/trunk/Lib/test/test_wait3.py Thu Mar 26 22:10:30 2009 @@ -3,18 +3,19 @@ import os import time +import unittest from test.fork_wait import ForkWait -from test.test_support import SkipTest, run_unittest, reap_children +from test.test_support import run_unittest, reap_children try: os.fork except AttributeError: - raise SkipTest, "os.fork not defined -- skipping test_wait3" + raise unittest.SkipTest, "os.fork not defined -- skipping test_wait3" try: os.wait3 except AttributeError: - raise SkipTest, "os.wait3 not defined -- skipping test_wait3" + raise unittest.SkipTest, "os.wait3 not defined -- skipping test_wait3" class Wait3Test(ForkWait): def wait_impl(self, cpid): Modified: python/trunk/Lib/test/test_wait4.py ============================================================================== --- python/trunk/Lib/test/test_wait4.py (original) +++ python/trunk/Lib/test/test_wait4.py Thu Mar 26 22:10:30 2009 @@ -4,17 +4,17 @@ import os import time from test.fork_wait import ForkWait -from test.test_support import SkipTest, run_unittest, reap_children +from test.test_support import run_unittest, reap_children try: os.fork except AttributeError: - raise SkipTest, "os.fork not defined -- skipping test_wait4" + raise unittest.SkipTest, "os.fork not defined -- skipping test_wait4" try: os.wait4 except AttributeError: - raise SkipTest, "os.wait4 not defined -- skipping test_wait4" + raise unittest.SkipTest, "os.wait4 not defined -- skipping test_wait4" class Wait4Test(ForkWait): def wait_impl(self, cpid): From python-checkins at python.org Thu Mar 26 22:11:17 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 22:11:17 +0100 (CET) Subject: [Python-checkins] r70621 - python/trunk/Lib/test/test_support.py Message-ID: <20090326211117.1EFD81E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 22:11:16 2009 New Revision: 70621 Log: must pass argument to get expected behavior ;) Modified: python/trunk/Lib/test/test_support.py Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Thu Mar 26 22:11:16 2009 @@ -705,7 +705,7 @@ return impl_detail(cpython=True)(test) def impl_detail(msg=None, **guards): - if check_impl_detail(): + if check_impl_detail(guards): return _id if msg is None: guardnames, default = _parse_guards(guards) From benjamin at python.org Thu Mar 26 22:11:24 2009 From: benjamin at python.org (Benjamin Peterson) Date: Thu, 26 Mar 2009 16:11:24 -0500 Subject: [Python-checkins] r70615 - python/trunk/Lib/test/test_support.py In-Reply-To: <49CBEEEA.80909@gmail.com> References: <20090326195819.0384C1E4002@bag.python.org> <49CBEEEA.80909@gmail.com> Message-ID: <1afaf6160903261411pccb895fw1db0ab91c01f2480@mail.gmail.com> 2009/3/26 Nick Coghlan : > benjamin.peterson wrote: >> Modified: python/trunk/Lib/test/test_support.py >> ============================================================================== >> --- python/trunk/Lib/test/test_support.py ? ? (original) >> +++ python/trunk/Lib/test/test_support.py ? ? Thu Mar 26 20:58:18 2009 > >> +def impl_detail(msg=None, **guards): >> + ? ?if check_impl_detail(): >> + ? ? ? ?return _id > > You want to pass "guards" down to check_impl_detail() here. Nice catch! Thanks. -- Regards, Benjamin From buildbot at python.org Thu Mar 26 22:14:36 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 21:14:36 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu trunk Message-ID: <20090326211437.35A131E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%20trunk/builds/1004 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 5 tests failed: test_al test_bsddb185 test_imgfile test_tk test_ttk_guionly Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/pybot/buildarea/trunk.klose-ubuntu-i386/build/Lib/test/test_al.py", line 6, in al = import_module('al', deprecated=True) File "/home/pybot/buildarea/trunk.klose-ubuntu-i386/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/pybot/buildarea/trunk.klose-ubuntu-i386/build/Lib/test/test_bsddb185.py", line 9, in bsddb185 = import_module('bsddb185', deprecated=True) File "/home/pybot/buildarea/trunk.klose-ubuntu-i386/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/pybot/buildarea/trunk.klose-ubuntu-i386/build/Lib/test/test_imgfile.py", line 9, in imgfile = import_module('imgfile', deprecated=True) File "/home/pybot/buildarea/trunk.klose-ubuntu-i386/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/pybot/buildarea/trunk.klose-ubuntu-i386/build/Lib/test/test_tk.py", line 10, in raise unittest.SkipTest("tk not available: %s" % msg) NameError: name 'unittest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/pybot/buildarea/trunk.klose-ubuntu-i386/build/Lib/test/test_ttk_guionly.py", line 11, in raise unittest.SkipTest("ttk not available: %s" % msg) NameError: name 'unittest' is not defined make: *** [buildbottest] Error 1 sincerely, -The Buildbot From nnorwitz at gmail.com Thu Mar 26 22:16:05 2009 From: nnorwitz at gmail.com (Neal Norwitz) Date: Thu, 26 Mar 2009 16:16:05 -0500 Subject: [Python-checkins] Python Regression Test Failures basics (4) Message-ID: <20090326211605.GA28405@python.psfb.org> 309 tests OK. 4 tests failed: test_al test_bsddb185 test_imgfile test_tarfile 54 tests skipped: test__locale test_aepack test_applesingle test_bsddb3 test_cd test_cl test_commands test_curses test_decimal test_dl test_email_codecs test_epoll test_fork1 test_gl test_ioctl test_kqueue test_largefile test_lib2to3 test_linuxaudiodev test_locale test_macos test_macostools test_mhlib test_minidom test_multiprocessing test_openpty test_ossaudiodev test_pep277 test_pipes test_poll test_popen2 test_pty test_py3kwarn test_scriptpackages test_site test_socketserver test_sqlite test_startfile test_sunaudiodev test_tcl test_threaded_import test_threadsignals test_timeout test_tk test_ttk_guionly test_ttk_textonly test_unicode_file test_urllib2net test_urllibnet test_wait3 test_wait4 test_winreg test_winsound test_zipfile64 26 skips unexpected on linux2: test_wait4 test_pipes test_wait3 test_pty test_locale test_multiprocessing test_ttk_textonly test_email_codecs test_threadsignals test_minidom test_decimal test_poll test_epoll test_site test_popen2 test_lib2to3 test_ttk_guionly test_mhlib test_openpty test_commands test_threaded_import test_fork1 test__locale test_tk test_ioctl test_socketserver test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_SimpleHTTPServer test_StringIO test___all__ test___future__ test__locale test__locale skipped -- cannot import name SkipTest test_abc test_abstract_numbers test_aepack test_aepack skipped -- No module named aepack test_al test test_al crashed -- : global name 'SkipTest' is not defined test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat test_asyncore 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 test_bsddb185 crashed -- : global name 'SkipTest' is not defined test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_buffer test_bufio test_bytes test_bz2 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 test_cmd_line test_cmd_line_script 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_commands skipped -- cannot import name SkipTest test_compare test_compile test_compileall test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle Exception RuntimeError: 'maximum recursion depth exceeded while calling a Python object' in ignored test_cprofile test_crypt test_csv test_ctypes test_curses test_curses skipped -- cannot import name SkipTest test_datetime test_dbm test_decimal test_decimal skipped -- cannot import name SkipTest test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils test_dl test_dl skipped -- cannot import name SkipTest test_docxmlrpc test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_codecs skipped -- cannot import name TestSkipped test_email_renamed test_enumerate test_eof test_epoll test_epoll skipped -- kernel doesn't support epoll() test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_fileio test_float test_fnmatch test_fork1 test_fork1 skipped -- cannot import name SkipTest test_format test_fpformat test_fractions test_frozen test_ftplib test_funcattrs test_functools test_future test_future3 test_future4 test_future5 test_future_builtins test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- cannot import name SkipTest test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_httpservers [13179 refs] [13179 refs] [23375 refs] test_imageop test_imaplib test_imgfile test test_imgfile crashed -- : global name 'SkipTest' is not defined test_imp test_import test_importhooks test_importlib test_index test_inspect test_int test_int_literal test_io test_ioctl test_ioctl skipped -- cannot import name SkipTest test_isinstance test_iter test_iterlen test_itertools test_json test_kqueue test_kqueue skipped -- test works only on BSD test_largefile test_largefile skipped -- cannot import name SkipTest test_lib2to3 test_lib2to3 skipped -- No module named myfixes test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_locale skipped -- cannot import name SkipTest test_logging test_long test_long_future test_longexp test_macos test_macos skipped -- No module named MacOS test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_memoryio test_mhlib test_mhlib skipped -- cannot import name SkipTest test_mimetools test_mimetypes test_minidom test_minidom skipped -- cannot import name SkipTest test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_multiprocessing test_multiprocessing skipped -- cannot import name SkipTest test_mutants test_mutex test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_openpty skipped -- cannot import name SkipTest test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser Expecting 's_push: parser stack overflow' in next line s_push: parser stack overflow 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_pipes test_pipes skipped -- cannot import name SkipTest test_pkg test_pkgimport test_pkgutil test_platform [14834 refs] [14834 refs] test_plistlib test_poll test_poll skipped -- cannot import name SkipTest test_popen [13184 refs] [13184 refs] [13184 refs] test_popen2 test_popen2 skipped -- cannot import name SkipTest test_poplib test_posix test_posixpath test_pow test_pprint test_print test_profile test_profilehooks test_property test_pstats test_pty test_pty skipped -- cannot import name SkipTest test_pwd test_py3kwarn test_py3kwarn skipped -- cannot import name SkipTest test_pyclbr test_pydoc [18903 refs] test_pyexpat test_queue test_quopri [15704 refs] [15704 refs] test_random test_re test_repr test_resource test_rfc822 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_site skipped -- cannot import name SkipTest test_slice test_smtplib test_socket test_socketserver test_socketserver skipped -- cannot import name SkipTest test_softspace test_sort test_sqlite test_sqlite skipped -- cannot import name SkipTest test_ssl 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 [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [15079 refs] [13394 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] . [13179 refs] [13179 refs] this bit of output is from a test of stdout in a different process ... [13179 refs] [13179 refs] [13394 refs] test_sunaudiodev test_sunaudiodev skipped -- cannot import name SkipTest test_sundry /tmp/python-test/local/lib/python2.7/test/test_sundry.py:66: DeprecationWarning: The posixfile module is deprecated; fcntl.lockf() provides better locking import posixfile test_symtable test_syntax test_sys [13179 refs] [13179 refs] [13408 refs] [13202 refs] test_tarfile test test_tarfile crashed -- : [Errno 13] Permission denied: '/tmp/test_tarfile_tmp/testtar.tar.gz' test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [13182 refs] test_textwrap test_thread test_threaded_import test_threaded_import skipped -- cannot import name SkipTest test_threadedtempfile test_threading [16675 refs] [18865 refs] [17842 refs] [17842 refs] [17842 refs] [17842 refs] test_threading_local test_threadsignals test_threadsignals skipped -- cannot import name SkipTest test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tk test_tk skipped -- No module named _tkinter test_tokenize test_trace test_traceback test_transformer test_ttk_guionly test_ttk_guionly skipped -- No module named _tkinter test_ttk_textonly test_ttk_textonly skipped -- No module named runtktests test_tuple test_typechecks test_ucn test_unary test_undocumented_details test_unicode test_unicode_file test_unicode_file skipped -- cannot import name SkipTest test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2_localnet 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_wait3 skipped -- cannot import name SkipTest test_wait4 test_wait4 skipped -- cannot import name SkipTest 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_zipimport_support test_zlib 309 tests OK. 4 tests failed: test_al test_bsddb185 test_imgfile test_tarfile 54 tests skipped: test__locale test_aepack test_applesingle test_bsddb3 test_cd test_cl test_commands test_curses test_decimal test_dl test_email_codecs test_epoll test_fork1 test_gl test_ioctl test_kqueue test_largefile test_lib2to3 test_linuxaudiodev test_locale test_macos test_macostools test_mhlib test_minidom test_multiprocessing test_openpty test_ossaudiodev test_pep277 test_pipes test_poll test_popen2 test_pty test_py3kwarn test_scriptpackages test_site test_socketserver test_sqlite test_startfile test_sunaudiodev test_tcl test_threaded_import test_threadsignals test_timeout test_tk test_ttk_guionly test_ttk_textonly test_unicode_file test_urllib2net test_urllibnet test_wait3 test_wait4 test_winreg test_winsound test_zipfile64 26 skips unexpected on linux2: test_wait4 test_pipes test_wait3 test_pty test_locale test_multiprocessing test_ttk_textonly test_email_codecs test_threadsignals test_minidom test_decimal test_poll test_epoll test_site test_popen2 test_lib2to3 test_ttk_guionly test_mhlib test_openpty test_commands test_threaded_import test_fork1 test__locale test_tk test_ioctl test_socketserver [639624 refs] From buildbot at python.org Thu Mar 26 22:16:26 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 21:16:26 +0000 Subject: [Python-checkins] buildbot failure in OS X x86 trunk Message-ID: <20090326211626.7B7E51E4012@bag.python.org> The Buildbot has detected a new failure of OS X x86 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%20trunk/builds/273 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/threading.py", line 477, in run self.__target(*self.__args, **self.__kwargs) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/bsddb/test/test_thread.py", line 306, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/bsddb/dbutils.py", line 68, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') 5 tests failed: test_al test_bsddb185 test_bz2 test_imgfile test_ttk_guionly Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/test/test_al.py", line 6, in al = import_module('al', deprecated=True) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/test/test_bsddb185.py", line 9, in bsddb185 = import_module('bsddb185', deprecated=True) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/test/test_imgfile.py", line 9, in imgfile = import_module('imgfile', deprecated=True) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/Users/buildbot/buildarea/trunk.noller-osx86/build/Lib/test/test_ttk_guionly.py", line 11, in raise unittest.SkipTest("ttk not available: %s" % msg) NameError: name 'unittest' is not defined make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Thu Mar 26 22:16:40 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 21:16:40 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo trunk Message-ID: <20090326211640.C62411E4031@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%20gentoo%20trunk/builds/2005 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed 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 522, in __bootstrap_inner self.run() File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/threading.py", line 477, in run self.__target(*self.__args, **self.__kwargs) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/bsddb/test/test_thread.py", line 306, in readerThread rec = dbutils.DeadlockWrap(c.next, max_retries=10) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/bsddb/dbutils.py", line 68, in DeadlockWrap return function(*_args, **_kwargs) DBLockDeadlockError: (-30995, 'DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock') 6 tests failed: test_al test_bsddb185 test_imageop test_imgfile test_tk test_ttk_guionly Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_al.py", line 6, in al = import_module('al', deprecated=True) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_bsddb185.py", line 9, in bsddb185 = import_module('bsddb185', deprecated=True) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_imageop.py", line 10, in imageop = import_module('imageop', deprecated=True) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_imgfile.py", line 9, in imgfile = import_module('imgfile', deprecated=True) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_tk.py", line 10, in raise unittest.SkipTest("tk not available: %s" % msg) NameError: name 'unittest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_ttk_guionly.py", line 11, in raise unittest.SkipTest("ttk not available: %s" % msg) NameError: name 'unittest' is not defined make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Thu Mar 26 22:20:49 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 21:20:49 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo trunk Message-ID: <20090326212049.8015B1E402C@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%20gentoo%20trunk/builds/4782 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 3 tests failed: test_al test_bsddb185 test_imgfile Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/test/test_al.py", line 6, in al = import_module('al', deprecated=True) File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/test/test_bsddb185.py", line 9, in bsddb185 = import_module('bsddb185', deprecated=True) File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/test/test_imgfile.py", line 9, in imgfile = import_module('imgfile', deprecated=True) File "/home/buildslave/python-trunk/trunk.norwitz-x86/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined make: *** [buildbottest] Error 1 sincerely, -The Buildbot From nnorwitz at gmail.com Thu Mar 26 22:26:42 2009 From: nnorwitz at gmail.com (Neal Norwitz) Date: Thu, 26 Mar 2009 16:26:42 -0500 Subject: [Python-checkins] Python Regression Test Failures opt (3) Message-ID: <20090326212642.GA11214@python.psfb.org> 310 tests OK. 3 tests failed: test_al test_bsddb185 test_imgfile 54 tests skipped: test__locale test_aepack test_applesingle test_bsddb3 test_cd test_cl test_commands test_curses test_decimal test_dl test_email_codecs test_epoll test_fork1 test_gl test_ioctl test_kqueue test_largefile test_lib2to3 test_linuxaudiodev test_locale test_macos test_macostools test_mhlib test_minidom test_multiprocessing test_openpty test_ossaudiodev test_pep277 test_pipes test_poll test_popen2 test_pty test_py3kwarn test_scriptpackages test_site test_socketserver test_sqlite test_startfile test_sunaudiodev test_tcl test_threaded_import test_threadsignals test_timeout test_tk test_ttk_guionly test_ttk_textonly test_unicode_file test_urllib2net test_urllibnet test_wait3 test_wait4 test_winreg test_winsound test_zipfile64 26 skips unexpected on linux2: test_wait4 test_pipes test_wait3 test_pty test_locale test_multiprocessing test_ttk_textonly test_email_codecs test_threadsignals test_minidom test_decimal test_poll test_epoll test_site test_popen2 test_lib2to3 test_ttk_guionly test_mhlib test_openpty test_commands test_threaded_import test_fork1 test__locale test_tk test_ioctl test_socketserver test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_SimpleHTTPServer test_StringIO test___all__ test___future__ test__locale test__locale skipped -- cannot import name SkipTest test_abc test_abstract_numbers test_aepack test_aepack skipped -- No module named aepack test_al test test_al crashed -- : global name 'SkipTest' is not defined test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat test_asyncore 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 test_bsddb185 crashed -- : global name 'SkipTest' is not defined test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_buffer test_bufio test_bytes test_bz2 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 test_cmd_line test_cmd_line_script 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_commands skipped -- cannot import name SkipTest test_compare test_compile test_compileall test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle Exception RuntimeError: 'maximum recursion depth exceeded while calling a Python object' in ignored test_cprofile test_crypt test_csv test_ctypes test_curses test_curses skipped -- cannot import name SkipTest test_datetime test_dbm test_decimal test_decimal skipped -- cannot import name SkipTest test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils [17359 refs] [17359 refs] test_dl test_dl skipped -- cannot import name SkipTest test_docxmlrpc test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_codecs skipped -- cannot import name TestSkipped test_email_renamed test_enumerate test_eof test_epoll test_epoll skipped -- kernel doesn't support epoll() test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_fileio test_float test_fnmatch test_fork1 test_fork1 skipped -- cannot import name SkipTest test_format test_fpformat test_fractions test_frozen test_ftplib test_funcattrs test_functools test_future test_future3 test_future4 test_future5 test_future_builtins test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- cannot import name SkipTest test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_httpservers [13179 refs] [13179 refs] [23375 refs] test_imageop test_imaplib test_imgfile test test_imgfile crashed -- : global name 'SkipTest' is not defined test_imp test_import test_importhooks test_importlib test_index test_inspect test_int test_int_literal test_io test_ioctl test_ioctl skipped -- cannot import name SkipTest test_isinstance test_iter test_iterlen test_itertools test_json test_kqueue test_kqueue skipped -- test works only on BSD test_largefile test_largefile skipped -- cannot import name SkipTest test_lib2to3 test_lib2to3 skipped -- No module named myfixes test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_locale skipped -- cannot import name SkipTest test_logging test_long test_long_future test_longexp test_macos test_macos skipped -- No module named MacOS test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_memoryio test_mhlib test_mhlib skipped -- cannot import name SkipTest test_mimetools test_mimetypes test_minidom test_minidom skipped -- cannot import name SkipTest test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_multiprocessing test_multiprocessing skipped -- cannot import name SkipTest test_mutants test_mutex test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_openpty skipped -- cannot import name SkipTest test_operator test_optparse test_os test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser Expecting 's_push: parser stack overflow' in next line s_push: parser stack overflow 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_pipes test_pipes skipped -- cannot import name SkipTest test_pkg test_pkgimport test_pkgutil test_platform [14834 refs] [14834 refs] test_plistlib test_poll test_poll skipped -- cannot import name SkipTest test_popen [13184 refs] [13184 refs] [13184 refs] test_popen2 test_popen2 skipped -- cannot import name SkipTest test_poplib test_posix test_posixpath test_pow test_pprint test_print test_profile test_profilehooks test_property test_pstats test_pty test_pty skipped -- cannot import name SkipTest test_pwd test_py3kwarn test_py3kwarn skipped -- cannot import name SkipTest test_pyclbr test_pydoc [18903 refs] test_pyexpat test_queue test_quopri [15704 refs] [15704 refs] test_random test_re test_repr test_resource test_rfc822 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_site skipped -- cannot import name SkipTest test_slice test_smtplib test_socket test_socketserver test_socketserver skipped -- cannot import name SkipTest test_softspace test_sort test_sqlite test_sqlite skipped -- cannot import name SkipTest test_ssl 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 [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [15079 refs] [13394 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] . [13179 refs] [13179 refs] this bit of output is from a test of stdout in a different process ... [13179 refs] [13179 refs] [13394 refs] test_sunaudiodev test_sunaudiodev skipped -- cannot import name SkipTest test_sundry /tmp/python-test/local/lib/python2.7/test/test_sundry.py:66: DeprecationWarning: The posixfile module is deprecated; fcntl.lockf() provides better locking import posixfile test_symtable test_syntax test_sys [13179 refs] [13179 refs] [13408 refs] [13202 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [13182 refs] test_textwrap test_thread test_threaded_import test_threaded_import skipped -- cannot import name SkipTest test_threadedtempfile test_threading [16675 refs] [18026 refs] [17842 refs] [17842 refs] [17842 refs] [17842 refs] test_threading_local test_threadsignals test_threadsignals skipped -- cannot import name SkipTest test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tk test_tk skipped -- No module named _tkinter test_tokenize test_trace test_traceback test_transformer test_ttk_guionly test_ttk_guionly skipped -- No module named _tkinter test_ttk_textonly test_ttk_textonly skipped -- No module named runtktests test_tuple test_typechecks test_ucn test_unary test_undocumented_details test_unicode test_unicode_file test_unicode_file skipped -- cannot import name SkipTest test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2_localnet 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_wait3 skipped -- cannot import name SkipTest test_wait4 test_wait4 skipped -- cannot import name SkipTest 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_zipimport_support test_zlib 310 tests OK. 3 tests failed: test_al test_bsddb185 test_imgfile 54 tests skipped: test__locale test_aepack test_applesingle test_bsddb3 test_cd test_cl test_commands test_curses test_decimal test_dl test_email_codecs test_epoll test_fork1 test_gl test_ioctl test_kqueue test_largefile test_lib2to3 test_linuxaudiodev test_locale test_macos test_macostools test_mhlib test_minidom test_multiprocessing test_openpty test_ossaudiodev test_pep277 test_pipes test_poll test_popen2 test_pty test_py3kwarn test_scriptpackages test_site test_socketserver test_sqlite test_startfile test_sunaudiodev test_tcl test_threaded_import test_threadsignals test_timeout test_tk test_ttk_guionly test_ttk_textonly test_unicode_file test_urllib2net test_urllibnet test_wait3 test_wait4 test_winreg test_winsound test_zipfile64 26 skips unexpected on linux2: test_wait4 test_pipes test_wait3 test_pty test_locale test_multiprocessing test_ttk_textonly test_email_codecs test_threadsignals test_minidom test_decimal test_poll test_epoll test_site test_popen2 test_lib2to3 test_ttk_guionly test_mhlib test_openpty test_commands test_threaded_import test_fork1 test__locale test_tk test_ioctl test_socketserver [638950 refs] From ncoghlan at gmail.com Thu Mar 26 22:28:37 2009 From: ncoghlan at gmail.com (Nick Coghlan) Date: Fri, 27 Mar 2009 07:28:37 +1000 Subject: [Python-checkins] r70621 - python/trunk/Lib/test/test_support.py In-Reply-To: <20090326211117.1EFD81E4002@bag.python.org> References: <20090326211117.1EFD81E4002@bag.python.org> Message-ID: <49CBF385.40204@gmail.com> benjamin.peterson wrote: > Author: benjamin.peterson > Date: Thu Mar 26 22:11:16 2009 > New Revision: 70621 > > Log: > must pass argument to get expected behavior ;) > > Modified: > python/trunk/Lib/test/test_support.py > > Modified: python/trunk/Lib/test/test_support.py > ============================================================================== > --- python/trunk/Lib/test/test_support.py (original) > +++ python/trunk/Lib/test/test_support.py Thu Mar 26 22:11:16 2009 > @@ -705,7 +705,7 @@ > return impl_detail(cpython=True)(test) > > def impl_detail(msg=None, **guards): > - if check_impl_detail(): > + if check_impl_detail(guards): That either needs to be "**guards", or the signature of check_impl_detail needs to change to accept *args as well as **kwds (i.e. similar to the dict constructor). Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- From python-checkins at python.org Thu Mar 26 22:29:57 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 22:29:57 +0100 (CET) Subject: [Python-checkins] r70622 - python/branches/py3k Message-ID: <20090326212957.F1F871E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 22:29:57 2009 New Revision: 70622 Log: Blocked revisions 70531,70533,70538,70544,70552-70553,70564,70601 via svnmerge ........ r70531 | benjamin.peterson | 2009-03-22 17:24:58 -0500 (Sun, 22 Mar 2009) | 1 line AttributeError can be thrown during recursion errors ........ r70533 | raymond.hettinger | 2009-03-22 19:08:09 -0500 (Sun, 22 Mar 2009) | 6 lines Add more comments. Improve variable names. Make links clearer by using a Link object instead of a list. Use proxy links to avoid circular references. ........ r70538 | raymond.hettinger | 2009-03-22 23:42:18 -0500 (Sun, 22 Mar 2009) | 1 line Move initialization of root link to __init__. ........ r70544 | raymond.hettinger | 2009-03-23 13:26:59 -0500 (Mon, 23 Mar 2009) | 1 line Make imported name private and wrap long-line. ........ r70552 | benjamin.peterson | 2009-03-23 15:47:59 -0500 (Mon, 23 Mar 2009) | 1 line fix very old names for exception terms #5543 ........ r70553 | benjamin.peterson | 2009-03-23 16:23:30 -0500 (Mon, 23 Mar 2009) | 1 line revert r70552; wrong fix ........ r70564 | raymond.hettinger | 2009-03-23 19:17:11 -0500 (Mon, 23 Mar 2009) | 1 line Add links to related resources. ........ r70601 | raymond.hettinger | 2009-03-25 17:41:32 -0500 (Wed, 25 Mar 2009) | 1 line Separate initialization from clearing. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Thu Mar 26 22:30:11 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 22:30:11 +0100 (CET) Subject: [Python-checkins] r70623 - python/trunk/Lib/test/test_ttk_guionly.py Message-ID: <20090326213011.573831E4028@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 22:30:10 2009 New Revision: 70623 Log: add missing import Modified: python/trunk/Lib/test/test_ttk_guionly.py Modified: python/trunk/Lib/test/test_ttk_guionly.py ============================================================================== --- python/trunk/Lib/test/test_ttk_guionly.py (original) +++ python/trunk/Lib/test/test_ttk_guionly.py Thu Mar 26 22:30:10 2009 @@ -1,6 +1,7 @@ import os import sys import ttk +import unittest from _tkinter import TclError from test import test_support From python-checkins at python.org Thu Mar 26 22:30:54 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 22:30:54 +0100 (CET) Subject: [Python-checkins] r70624 - python/trunk/Lib/test/test_support.py Message-ID: <20090326213054.970891E403B@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 22:30:54 2009 New Revision: 70624 Log: ** is required here Modified: python/trunk/Lib/test/test_support.py Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Thu Mar 26 22:30:54 2009 @@ -705,7 +705,7 @@ return impl_detail(cpython=True)(test) def impl_detail(msg=None, **guards): - if check_impl_detail(guards): + if check_impl_detail(**guards): return _id if msg is None: guardnames, default = _parse_guards(guards) From python-checkins at python.org Thu Mar 26 22:34:21 2009 From: python-checkins at python.org (jeremy.hylton) Date: Thu, 26 Mar 2009 22:34:21 +0100 (CET) Subject: [Python-checkins] r70625 - in python/branches/py3k/Lib: test/test_urllib_response.py urllib/response.py Message-ID: <20090326213421.4343F1E4053@bag.python.org> Author: jeremy.hylton Date: Thu Mar 26 22:34:20 2009 New Revision: 70625 Log: Add __enter__ and __exit__ methods to addbase() so that it supports with. This change also adds a minimal unittest of urllib.response.addbase. More are needed, but not to cover the small change being made here. Addresses http://bugs.python.org/issue5418 Added: python/branches/py3k/Lib/test/test_urllib_response.py Modified: python/branches/py3k/Lib/urllib/response.py Added: python/branches/py3k/Lib/test/test_urllib_response.py ============================================================================== --- (empty file) +++ python/branches/py3k/Lib/test/test_urllib_response.py Thu Mar 26 22:34:20 2009 @@ -0,0 +1,42 @@ +"""Unit tests for code in urllib.response.""" + +import test.support +import urllib.response +import unittest + +class TestFile(object): + + def __init__(self): + self.closed = False + + def read(self, bytes): + pass + + def readline(self): + pass + + def close(self): + self.closed = True + +class Testaddbase(unittest.TestCase): + + # TODO(jhylton): Write tests for other functionality of addbase() + + def setUp(self): + self.fp = TestFile() + self.addbase = urllib.response.addbase(self.fp) + + def test_with(self): + def f(): + with self.addbase as spam: + pass + self.assertFalse(self.fp.closed) + f() + self.assertTrue(self.fp.closed) + self.assertRaises(ValueError, f) + +def test_main(): + test.support.run_unittest(Testaddbase) + +if __name__ == '__main__': + test_main() Modified: python/branches/py3k/Lib/urllib/response.py ============================================================================== --- python/branches/py3k/Lib/urllib/response.py (original) +++ python/branches/py3k/Lib/urllib/response.py Thu Mar 26 22:34:20 2009 @@ -40,6 +40,14 @@ if self.fp: self.fp.close() self.fp = None + def __enter__(self): + if self.fp is None: + raise ValueError("I/O operation on closed file") + return self + + def __exit__(self, type, value, traceback): + self.close() + class addclosehook(addbase): """Class to add a close hook to an open file.""" From python-checkins at python.org Thu Mar 26 22:40:34 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 22:40:34 +0100 (CET) Subject: [Python-checkins] r70626 - python/trunk/Lib/email/test/test_email_codecs.py Message-ID: <20090326214034.CE40D1E401A@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 22:40:29 2009 New Revision: 70626 Log: update email tests to use SkipTest Modified: python/trunk/Lib/email/test/test_email_codecs.py Modified: python/trunk/Lib/email/test/test_email_codecs.py ============================================================================== --- python/trunk/Lib/email/test/test_email_codecs.py (original) +++ python/trunk/Lib/email/test/test_email_codecs.py Thu Mar 26 22:40:29 2009 @@ -3,7 +3,7 @@ # email package unit tests for (optional) Asian codecs import unittest -from test.test_support import TestSkipped, run_unittest +from test.test_support import run_unittest from email.test.test_email import TestEmailBase from email.Charset import Charset @@ -15,7 +15,7 @@ try: unicode('foo', 'euc-jp') except LookupError: - raise TestSkipped + raise unittest.SkipTest From buildbot at python.org Thu Mar 26 22:43:55 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 21:43:55 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu trunk Message-ID: <20090326214355.F2DDC1E4017@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%20trunk/builds/1157 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 6 tests failed: test_al test_bsddb185 test_imageop test_imgfile test_tk test_ttk_guionly Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_al.py", line 6, in al = import_module('al', deprecated=True) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_bsddb185.py", line 9, in bsddb185 = import_module('bsddb185', deprecated=True) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_imageop.py", line 10, in imageop = import_module('imageop', deprecated=True) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_imgfile.py", line 9, in imgfile = import_module('imgfile', deprecated=True) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_support.py", line 54, in import_module raise SkipTest("No module named " + name) NameError: global name 'SkipTest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_tk.py", line 10, in raise unittest.SkipTest("tk not available: %s" % msg) NameError: name 'unittest' is not defined Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_ttk_guionly.py", line 11, in raise unittest.SkipTest("ttk not available: %s" % msg) NameError: name 'unittest' is not defined make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Mar 26 22:44:44 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 22:44:44 +0100 (CET) Subject: [Python-checkins] r70627 - python/trunk/Lib/test/test_locale.py Message-ID: <20090326214444.22DBD1E4017@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 22:44:43 2009 New Revision: 70627 Log: fix another name Modified: python/trunk/Lib/test/test_locale.py Modified: python/trunk/Lib/test/test_locale.py ============================================================================== --- python/trunk/Lib/test/test_locale.py (original) +++ python/trunk/Lib/test/test_locale.py Thu Mar 26 22:44:43 2009 @@ -358,7 +358,7 @@ # SkipTest can't be raised inside unittests, handle it manually instead try: get_enUS_locale() - except SkipTest as e: + except unittest.SkipTest as e: if verbose: print "Some tests will be disabled: %s" % e else: From python-checkins at python.org Thu Mar 26 22:49:58 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 22:49:58 +0100 (CET) Subject: [Python-checkins] r70628 - in python/branches/py3k: Lib/platform.py Lib/test/test_platform.py Lib/urllib/request.py Misc/python.man Message-ID: <20090326214958.E80D41E40AC@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 22:49:58 2009 New Revision: 70628 Log: Merged revisions 70518,70521,70590,70594-70595 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70518 | matthias.klose | 2009-03-22 08:08:22 -0500 (Sun, 22 Mar 2009) | 2 lines - Fix comment macro in python.man ........ r70521 | benjamin.peterson | 2009-03-22 12:45:11 -0500 (Sun, 22 Mar 2009) | 1 line close the file even if an exception occurs #5536 ........ r70590 | skip.montanaro | 2009-03-24 19:52:11 -0500 (Tue, 24 Mar 2009) | 1 line clarify the type of data returned ........ r70594 | marc-andre.lemburg | 2009-03-25 14:44:58 -0500 (Wed, 25 Mar 2009) | 9 lines Remove the sys.version_info shortcut, since they cause the APIs to return different information than the _sys_version() output used in previous Python versions. This also fixes issue5561: platform.python_version_tuple returns tuple of ints, should be strings Added more tests for the various platform functions. ........ r70595 | marc-andre.lemburg | 2009-03-25 14:45:33 -0500 (Wed, 25 Mar 2009) | 3 lines News item for the platform.py fix (r70594). ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/platform.py python/branches/py3k/Lib/test/test_platform.py python/branches/py3k/Lib/urllib/request.py python/branches/py3k/Misc/python.man Modified: python/branches/py3k/Lib/platform.py ============================================================================== --- python/branches/py3k/Lib/platform.py (original) +++ python/branches/py3k/Lib/platform.py Thu Mar 26 22:49:58 2009 @@ -1254,10 +1254,10 @@ def _sys_version(sys_version=None): """ Returns a parsed version of Python's sys.version as tuple - (name, version, branch, revision, buildno, builddate, compiler) - referring to the Python implementation name, version, branch, - revision, build number, build date/time as string and the compiler - identification string. + (name, version, branch, revision, buildno, builddate, compiler) + referring to the Python implementation name, version, branch, + revision, build number, build date/time as string and the compiler + identification string. Note that unlike the Python sys.version, the returned value for the Python version will always include the patchlevel (it @@ -1359,8 +1359,6 @@ will always include the patchlevel (it defaults to 0). """ - if hasattr(sys, 'version_info'): - return '%i.%i.%i' % sys.version_info[:3] return _sys_version()[1] def python_version_tuple(): @@ -1372,8 +1370,6 @@ will always include the patchlevel (it defaults to 0). """ - if hasattr(sys, 'version_info'): - return sys.version_info[:3] return tuple(_sys_version()[1].split('.')) def python_branch(): Modified: python/branches/py3k/Lib/test/test_platform.py ============================================================================== --- python/branches/py3k/Lib/test/test_platform.py (original) +++ python/branches/py3k/Lib/test/test_platform.py Thu Mar 26 22:49:58 2009 @@ -25,39 +25,48 @@ finally: os.remove(link) - def test_machine(self): - res = platform.machine() - - def test_node(self): - res = platform.node() - def test_platform(self): for aliased in (False, True): for terse in (False, True): res = platform.platform(aliased, terse) - def test_processor(self): - res = platform.processor() + def test_system(self): + res = platform.system() - def test_python_build(self): - res = platform.python_build() + def test_node(self): + res = platform.node() - def test_python_compiler(self): - res = platform.python_compiler() + def test_release(self): + res = platform.release() def test_version(self): - res1 = platform.version() - res2 = platform.version_tuple() + res = platform.version() + + def test_machine(self): + res = platform.machine() + + def test_processor(self): + res = platform.processor() + + def test_python_implementation(self): + res = platform.python_implementation() + + def test_python_version(self): + res1 = platform.python_version() + res2 = platform.python_version_tuple() self.assertEqual(res1, ".".join(res2)) - def test_release(self): - res = platform.release() + def test_python_branch(self): + res = platform.python_branch() - def test_system(self): - res = platform.system() + def test_python_revision(self): + res = platform.python_revision() - def test_version(self): - res = platform.version() + def test_python_build(self): + res = platform.python_build() + + def test_python_compiler(self): + res = platform.python_compiler() def test_system_alias(self): res = platform.system_alias( Modified: python/branches/py3k/Lib/urllib/request.py ============================================================================== --- python/branches/py3k/Lib/urllib/request.py (original) +++ python/branches/py3k/Lib/urllib/request.py Thu Mar 26 22:49:58 2009 @@ -1474,41 +1474,45 @@ except IOError as msg: pass fp = self.open(url, data) - headers = fp.info() - if filename: - tfp = open(filename, 'wb') - else: - import tempfile - garbage, path = splittype(url) - garbage, path = splithost(path or "") - path, garbage = splitquery(path or "") - path, garbage = splitattr(path or "") - suffix = os.path.splitext(path)[1] - (fd, filename) = tempfile.mkstemp(suffix) - self.__tempfiles.append(filename) - tfp = os.fdopen(fd, 'wb') - result = filename, headers - if self.tempcache is not None: - self.tempcache[url] = result - bs = 1024*8 - size = -1 - read = 0 - blocknum = 0 - if reporthook: - if "content-length" in headers: - size = int(headers["Content-Length"]) - reporthook(blocknum, bs, size) - while 1: - block = fp.read(bs) - if not block: - break - read += len(block) - tfp.write(block) - blocknum += 1 - if reporthook: - reporthook(blocknum, bs, size) - fp.close() - tfp.close() + try: + headers = fp.info() + if filename: + tfp = open(filename, 'wb') + else: + import tempfile + garbage, path = splittype(url) + garbage, path = splithost(path or "") + path, garbage = splitquery(path or "") + path, garbage = splitattr(path or "") + suffix = os.path.splitext(path)[1] + (fd, filename) = tempfile.mkstemp(suffix) + self.__tempfiles.append(filename) + tfp = os.fdopen(fd, 'wb') + try: + result = filename, headers + if self.tempcache is not None: + self.tempcache[url] = result + bs = 1024*8 + size = -1 + read = 0 + blocknum = 0 + if reporthook: + if "content-length" in headers: + size = int(headers["Content-Length"]) + reporthook(blocknum, bs, size) + while 1: + block = fp.read(bs) + if not block: + break + read += len(block) + tfp.write(block) + blocknum += 1 + if reporthook: + reporthook(blocknum, bs, size) + finally: + tfp.close() + finally: + fp.close() del fp del tfp Modified: python/branches/py3k/Misc/python.man ============================================================================== --- python/branches/py3k/Misc/python.man (original) +++ python/branches/py3k/Misc/python.man Thu Mar 26 22:49:58 2009 @@ -1,7 +1,7 @@ .TH PYTHON "1" "$Date$" -./" To view this file while editing, run it through groff: -./" groff -Tascii -man python.man | less +.\" To view this file while editing, run it through groff: +.\" groff -Tascii -man python.man | less .SH NAME python \- an interpreted, interactive, object-oriented programming language From python-checkins at python.org Thu Mar 26 22:51:18 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 22:51:18 +0100 (CET) Subject: [Python-checkins] r70629 - in python/branches/release30-maint: Lib/test/test_unicode.py Misc/NEWS Objects/unicodetype_db.h Tools/unicode/makeunicodedata.py Message-ID: <20090326215118.E9A741E4019@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 22:51:18 2009 New Revision: 70629 Log: Merged revisions 70610 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70610 | benjamin.peterson | 2009-03-26 12:15:46 -0500 (Thu, 26 Mar 2009) | 1 line fix isprintable() on space characters #5126 ........ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/test/test_unicode.py python/branches/release30-maint/Misc/NEWS python/branches/release30-maint/Objects/unicodetype_db.h python/branches/release30-maint/Tools/unicode/makeunicodedata.py Modified: python/branches/release30-maint/Lib/test/test_unicode.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_unicode.py (original) +++ python/branches/release30-maint/Lib/test/test_unicode.py Thu Mar 26 22:51:18 2009 @@ -424,6 +424,7 @@ def test_isprintable(self): self.assertTrue("".isprintable()) + self.assertTrue(" ".isprintable()) self.assertTrue("abcdefg".isprintable()) self.assertFalse("abcdefg\n".isprintable()) # some defined Unicode character Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Thu Mar 26 22:51:18 2009 @@ -15,6 +15,8 @@ - Issue #5392: when a very low recursion limit was set, the interpreter would abort with a fatal error after the recursion limit was hit twice. +- Issue #5126: str.isprintable() returned False for space characters. + - Issue #5247: Improve error message when unknown format codes are used when using str.format() with str, int, and float arguments. Modified: python/branches/release30-maint/Objects/unicodetype_db.h ============================================================================== --- python/branches/release30-maint/Objects/unicodetype_db.h (original) +++ python/branches/release30-maint/Objects/unicodetype_db.h Thu Mar 26 22:51:18 2009 @@ -6,6 +6,7 @@ {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 32}, {0, 0, 0, 0, 0, 48}, + {0, 0, 0, 0, 0, 1056}, {0, 0, 0, 0, 0, 1024}, {0, 0, 0, 0, 0, 1542}, {0, 0, 0, 1, 1, 1542}, @@ -380,117 +381,116 @@ static unsigned char index2[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 3, 3, 3, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, 4, 4, 4, 4, 4, 4, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 4, 4, 4, 4, 16, 4, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 4, 4, - 4, 4, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 18, 4, 4, - 1, 4, 4, 4, 4, 19, 20, 4, 21, 4, 16, 4, 22, 18, 4, 4, 4, 4, 4, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 4, 15, 15, 15, 15, 15, 15, 15, 18, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 4, - 17, 17, 17, 17, 17, 17, 17, 23, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 26, 27, 24, 25, 24, 25, 24, 25, 18, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 18, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 28, 24, 25, 24, 25, 24, 25, 29, 30, 31, 24, 25, 24, 25, 32, 24, - 25, 33, 33, 24, 25, 18, 34, 35, 36, 24, 25, 33, 37, 38, 39, 40, 24, 25, - 41, 18, 39, 42, 43, 44, 24, 25, 24, 25, 24, 25, 45, 24, 25, 45, 18, 18, - 24, 25, 45, 24, 25, 46, 46, 24, 25, 24, 25, 47, 24, 25, 18, 48, 24, 25, - 18, 49, 48, 48, 48, 48, 50, 51, 52, 50, 51, 52, 50, 51, 52, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 53, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 18, 50, 51, 52, - 24, 25, 54, 55, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 56, 18, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 18, 18, 18, 18, 18, 18, 57, 24, - 25, 58, 59, 18, 18, 24, 25, 60, 61, 62, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 63, 64, 18, 65, 66, 18, 67, 67, 18, 68, 18, 69, 18, 18, 18, 18, - 67, 18, 18, 70, 18, 18, 18, 18, 71, 72, 18, 73, 18, 18, 18, 72, 18, 74, - 75, 18, 18, 76, 18, 18, 18, 18, 18, 18, 18, 77, 18, 18, 78, 18, 18, 78, - 18, 18, 18, 18, 78, 79, 80, 80, 81, 18, 18, 18, 18, 18, 82, 18, 48, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 4, 4, 4, 4, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 48, 48, 48, - 48, 48, 4, 4, 4, 4, 4, 4, 4, 48, 4, 48, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 83, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 1, 1, 1, 1, 3, 3, 3, 2, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 24, 25, 24, 25, 48, 4, 24, 25, 0, 0, 84, - 43, 43, 43, 4, 0, 0, 0, 0, 0, 4, 4, 85, 16, 86, 86, 86, 0, 87, 0, 88, 88, - 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 89, 90, 90, 90, 18, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 91, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 92, 93, 93, 94, 95, 96, 97, 97, 97, 98, 99, 100, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 101, 102, 103, 18, 104, 105, 4, 24, 25, 106, 24, - 25, 18, 56, 56, 56, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 102, - 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, - 102, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 4, - 16, 16, 16, 16, 16, 4, 4, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 108, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 109, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 0, 0, 48, 4, 4, 4, 4, 4, 4, 0, 111, 111, 111, 111, 111, 111, + 16, 16, 16, 16, 5, 5, 5, 5, 17, 5, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 5, 5, + 5, 5, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 19, 5, 5, + 1, 5, 5, 5, 5, 20, 21, 5, 22, 5, 17, 5, 23, 19, 5, 5, 5, 5, 5, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 5, 16, 16, 16, 16, 16, 16, 16, 19, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 5, + 18, 18, 18, 18, 18, 18, 18, 24, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 27, 28, 25, 26, 25, 26, 25, 26, 19, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 19, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 29, 25, 26, 25, 26, 25, 26, 30, 31, 32, 25, 26, 25, 26, 33, 25, + 26, 34, 34, 25, 26, 19, 35, 36, 37, 25, 26, 34, 38, 39, 40, 41, 25, 26, + 42, 19, 40, 43, 44, 45, 25, 26, 25, 26, 25, 26, 46, 25, 26, 46, 19, 19, + 25, 26, 46, 25, 26, 47, 47, 25, 26, 25, 26, 48, 25, 26, 19, 49, 25, 26, + 19, 50, 49, 49, 49, 49, 51, 52, 53, 51, 52, 53, 51, 52, 53, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 54, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 19, 51, 52, 53, + 25, 26, 55, 56, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 57, 19, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 19, 19, 19, 19, 19, 19, 58, 25, + 26, 59, 60, 19, 19, 25, 26, 61, 62, 63, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 64, 65, 19, 66, 67, 19, 68, 68, 19, 69, 19, 70, 19, 19, 19, 19, + 68, 19, 19, 71, 19, 19, 19, 19, 72, 73, 19, 74, 19, 19, 19, 73, 19, 75, + 76, 19, 19, 77, 19, 19, 19, 19, 19, 19, 19, 78, 19, 19, 79, 19, 19, 79, + 19, 19, 19, 19, 79, 80, 81, 81, 82, 19, 19, 19, 19, 19, 83, 19, 49, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, + 49, 49, 5, 5, 5, 5, 5, 5, 5, 49, 5, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 84, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 25, 26, 25, 26, 49, 5, 25, 26, 0, 0, 85, + 44, 44, 44, 5, 0, 0, 0, 0, 0, 5, 5, 86, 17, 87, 87, 87, 0, 88, 0, 89, 89, + 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 90, 91, 91, 91, 19, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 92, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 93, 94, 94, 95, 96, 97, 98, 98, 98, 99, 100, 101, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 102, 103, 104, 19, 105, 106, 5, 25, 26, 107, 25, + 26, 19, 57, 57, 57, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 103, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, + 103, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 5, + 17, 17, 17, 17, 17, 5, 5, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 109, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 110, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, - 111, 111, 111, 111, 18, 0, 4, 4, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 4, 16, 4, 16, 16, 4, 16, 16, 4, 16, 0, 0, 0, 0, 0, 0, 0, - 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 48, 48, 48, 4, 4, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 0, 0, 4, 4, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, - 4, 4, 4, 48, 48, 16, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 48, 16, 16, - 16, 16, 16, 16, 16, 1, 4, 16, 16, 16, 16, 16, 16, 48, 48, 16, 16, 4, 16, - 16, 16, 16, 48, 48, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48, 48, 48, 4, 4, - 48, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, 48, 16, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 48, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 48, 48, 4, 4, 4, 4, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 111, 111, 0, 0, 49, 5, 5, 5, 5, 5, 5, 0, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 19, 0, 5, 5, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 5, 17, 5, 17, 17, 5, 17, 17, 5, 17, 0, 0, 0, 0, 0, 0, 0, + 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 0, 0, 5, 5, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, + 5, 5, 5, 49, 49, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 49, 17, 17, + 17, 17, 17, 17, 17, 1, 5, 17, 17, 17, 17, 17, 17, 49, 49, 17, 17, 5, 17, + 17, 17, 17, 49, 49, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, 5, 5, + 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 1, 49, 17, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 49, 49, 5, 5, 5, 5, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -500,604 +500,605 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 16, 48, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 48, 16, 16, 16, 16, 0, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 4, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 4, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 0, - 16, 16, 16, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 0, 0, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 0, 0, 0, 48, 48, 48, - 48, 0, 0, 16, 48, 16, 16, 16, 16, 16, 16, 16, 0, 0, 16, 16, 0, 0, 16, 16, - 16, 48, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 48, 48, 0, 48, 48, 48, - 16, 16, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48, 48, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 16, 16, 16, 0, 48, 48, 48, 48, 48, 48, 0, - 0, 0, 0, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, - 48, 48, 0, 48, 48, 0, 48, 48, 0, 0, 16, 0, 16, 16, 16, 16, 16, 0, 0, 0, - 0, 16, 16, 0, 0, 16, 16, 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 48, 48, - 48, 48, 0, 48, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 16, 16, 48, 48, 48, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, - 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 0, 48, 48, 48, 48, 48, 0, 0, 16, - 48, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 0, 16, 16, 16, 0, 0, - 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 16, 16, 0, 0, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 16, 16, 16, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 0, - 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 0, 48, 48, - 48, 48, 48, 0, 0, 16, 48, 16, 16, 16, 16, 16, 16, 16, 0, 0, 16, 16, 0, 0, - 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 48, 48, 0, 48, - 48, 48, 16, 16, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 48, 0, 48, 48, 48, 48, 48, 48, - 0, 0, 0, 48, 48, 48, 0, 48, 48, 48, 48, 0, 0, 0, 48, 48, 0, 48, 0, 48, - 48, 0, 0, 0, 48, 48, 0, 0, 0, 48, 48, 48, 0, 0, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 16, 16, 16, 16, 16, 0, 0, 0, 16, - 16, 16, 0, 16, 16, 16, 16, 0, 0, 48, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 16, 16, 16, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 0, 0, 0, 48, 16, 16, 16, 16, - 16, 16, 16, 0, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 16, - 16, 0, 48, 48, 0, 0, 0, 0, 0, 0, 48, 48, 16, 16, 0, 0, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 16, - 16, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 0, - 0, 16, 48, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 0, 16, 16, 16, 16, - 0, 0, 0, 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 48, 0, 48, 48, 16, 16, - 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 16, 16, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, - 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 48, 16, 16, 16, 16, 16, 16, 16, 0, - 16, 16, 16, 0, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, - 0, 0, 0, 0, 48, 48, 16, 16, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, - 4, 4, 4, 4, 4, 0, 0, 0, 4, 48, 48, 48, 48, 48, 48, 0, 0, 16, 16, 0, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, - 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, - 0, 0, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 16, 0, 0, 0, 0, 16, 16, 16, - 16, 16, 16, 0, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 48, 112, 16, - 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 4, 48, 48, 48, 48, 48, 48, 48, 16, - 16, 16, 16, 16, 16, 16, 16, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, 4, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 48, 0, 0, 48, 48, 0, - 48, 0, 0, 48, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, - 48, 48, 0, 48, 48, 48, 0, 48, 0, 48, 0, 0, 48, 48, 0, 48, 48, 48, 48, 16, - 48, 112, 16, 16, 16, 16, 16, 16, 0, 16, 16, 48, 0, 0, 48, 48, 48, 48, 48, - 0, 48, 0, 16, 16, 16, 16, 16, 16, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 4, 4, 4, 4, 4, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, - 4, 16, 4, 16, 4, 4, 4, 4, 16, 16, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, - 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 4, 16, 16, 48, 48, 48, 48, 0, 0, 0, 0, 16, 16, 16, 16, 16, - 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 0, 4, 4, 4, 4, 4, 4, 4, 4, 16, 4, 4, 4, 4, 4, 4, 0, 4, 4, - 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 48, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 4, 4, 4, 4, 4, 4, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 48, 48, 48, - 48, 16, 16, 16, 48, 16, 16, 16, 48, 48, 16, 16, 16, 16, 16, 16, 16, 48, - 48, 48, 16, 16, 16, 16, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 48, 16, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 0, 0, 0, 0, 4, 4, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 4, 48, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, - 48, 0, 48, 0, 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, - 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, - 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 0, 48, 48, 48, - 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 0, 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 0, 0, 0, 0, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 4, 4, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 4, 0, 0, 0, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 4, 4, 4, 123, 123, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 16, - 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 4, 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 0, 16, 16, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 1, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, - 4, 48, 4, 4, 4, 4, 48, 16, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, - 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 2, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 48, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 4, 0, 0, 0, 4, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 48, 48, 48, 48, 48, 48, 48, 16, 16, - 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 0, 0, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, 0, 0, 4, 4, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 16, - 16, 16, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 0, 0, 0, 48, 48, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 0, 0, 0, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 0, - 48, 48, 48, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 48, 124, 18, 18, 18, - 125, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 18, 18, 18, 18, 18, 126, 18, 18, 127, 18, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, - 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 0, 0, 129, 129, 129, - 129, 129, 129, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, - 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, - 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 0, - 0, 129, 129, 129, 129, 129, 129, 0, 0, 18, 128, 18, 128, 18, 128, 18, - 128, 0, 129, 0, 129, 0, 129, 0, 129, 128, 128, 128, 128, 128, 128, 128, - 128, 129, 129, 129, 129, 129, 129, 129, 129, 130, 130, 131, 131, 131, - 131, 132, 132, 133, 133, 134, 134, 135, 135, 0, 0, 128, 128, 128, 128, - 128, 128, 128, 128, 136, 136, 136, 136, 136, 136, 136, 136, 128, 128, - 128, 128, 128, 128, 128, 128, 136, 136, 136, 136, 136, 136, 136, 136, - 128, 128, 128, 128, 128, 128, 128, 128, 136, 136, 136, 136, 136, 136, - 136, 136, 128, 128, 18, 137, 18, 0, 18, 18, 129, 129, 138, 138, 139, 4, - 140, 4, 4, 4, 18, 137, 18, 0, 18, 18, 141, 141, 141, 141, 139, 4, 4, 4, - 128, 128, 18, 18, 0, 0, 18, 18, 129, 129, 142, 142, 0, 4, 4, 4, 128, 128, - 18, 18, 18, 103, 18, 18, 129, 129, 143, 143, 106, 4, 4, 4, 0, 0, 18, 137, - 18, 0, 18, 18, 144, 144, 145, 145, 139, 4, 4, 0, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 1, 1, 1, 1, 1, 2, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, 1, 1, 1, 1, 0, 0, 0, - 0, 0, 1, 1, 1, 1, 1, 1, 146, 18, 0, 0, 147, 148, 149, 150, 151, 152, 4, - 4, 4, 4, 4, 18, 146, 22, 19, 20, 147, 148, 149, 150, 151, 152, 4, 4, 4, - 4, 4, 0, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, 4, 4, 16, 4, 4, 4, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 4, 97, 4, 4, 4, 4, 97, 4, 4, 18, 97, 97, 97, 18, 18, 97, - 97, 97, 18, 4, 97, 4, 4, 123, 97, 97, 97, 97, 97, 4, 4, 4, 4, 4, 4, 97, - 4, 153, 4, 97, 4, 154, 155, 97, 97, 123, 18, 97, 97, 156, 97, 18, 48, 48, - 48, 48, 18, 4, 4, 18, 18, 97, 97, 4, 4, 4, 4, 4, 97, 18, 18, 18, 18, 4, - 4, 4, 4, 157, 4, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 158, - 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, - 158, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 123, 123, 123, 24, 25, 123, 123, 123, 123, 0, 0, 0, 0, 0, - 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 22, 19, 20, 147, 148, 149, 150, 151, 152, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 22, 19, 20, 147, 148, 149, 150, 151, 152, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 22, 19, 20, 147, 148, 149, 150, 151, 152, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, - 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, - 160, 160, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 17, 49, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 49, 17, 17, 17, 17, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 5, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 5, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 0, + 17, 17, 17, 0, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, 0, 0, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 0, 0, 0, 49, 49, 49, + 49, 0, 0, 17, 49, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 0, 0, 17, 17, + 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 49, 49, 0, 49, 49, 49, + 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, 49, 49, 49, 49, 49, 49, 0, + 0, 0, 0, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, + 49, 49, 0, 49, 49, 0, 49, 49, 0, 0, 17, 0, 17, 17, 17, 17, 17, 0, 0, 0, + 0, 17, 17, 0, 0, 17, 17, 17, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 49, 49, + 49, 49, 0, 49, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 17, 17, 49, 49, 49, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, + 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, 49, 49, 49, 49, 49, 0, 0, 17, + 49, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 0, 17, 17, 17, 0, 0, + 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 17, 17, 0, 0, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 17, 17, 0, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, + 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, 49, 49, + 49, 49, 49, 0, 0, 17, 49, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 0, 0, + 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 49, 49, 0, 49, + 49, 49, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 49, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 49, 0, 49, 49, 49, 49, 49, 49, + 0, 0, 0, 49, 49, 49, 0, 49, 49, 49, 49, 0, 0, 0, 49, 49, 0, 49, 0, 49, + 49, 0, 0, 0, 49, 49, 0, 0, 0, 49, 49, 49, 0, 0, 0, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 17, 17, 17, 17, 17, 0, 0, 0, 17, + 17, 17, 0, 17, 17, 17, 17, 0, 0, 49, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 0, 0, 0, 49, 17, 17, 17, + 17, 17, 17, 17, 0, 17, 17, 17, 0, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 0, 49, 49, 0, 0, 0, 0, 0, 0, 49, 49, 17, 17, 0, 0, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 17, 17, 0, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, + 49, 49, 0, 0, 17, 49, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 0, 17, + 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 49, 0, 49, + 49, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 5, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 0, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 49, 17, 17, 17, 17, 17, + 17, 17, 0, 17, 17, 17, 0, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, + 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 49, 49, 49, 49, 49, 49, 0, 0, 17, + 17, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 0, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 17, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 0, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, + 49, 113, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 5, 49, 49, 49, 49, 49, + 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 0, 49, 0, 0, + 49, 49, 0, 49, 0, 0, 49, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 0, 49, 49, 49, + 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, 0, 49, 0, 0, 49, 49, 0, 49, 49, 49, + 49, 17, 49, 113, 17, 17, 17, 17, 17, 17, 0, 17, 17, 49, 0, 0, 49, 49, 49, + 49, 49, 0, 49, 0, 17, 17, 17, 17, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 0, 0, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 5, 5, 5, 5, + 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 17, 5, 17, 5, 17, 5, 5, 5, 5, 17, 17, 49, 49, 49, 49, 49, 49, 49, 49, + 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 5, 17, 17, 49, 49, 49, 49, 0, 0, 0, 0, 17, 17, + 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 0, 5, 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, + 5, 0, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, + 49, 49, 49, 49, 17, 17, 17, 49, 17, 17, 17, 49, 49, 17, 17, 17, 17, 17, + 17, 17, 49, 49, 49, 17, 17, 17, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 17, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 5, 5, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 5, 49, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 49, + 49, 49, 49, 49, 0, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, + 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 0, + 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 49, 49, 49, 49, 49, 49, 49, 49, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 0, 0, + 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 5, 5, 5, 124, 124, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, + 49, 49, 49, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 0, 17, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 1, 1, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 5, 5, 5, 49, 5, 5, 5, 5, 49, 17, 0, 0, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, + 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, 2, 0, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, + 0, 0, 5, 0, 0, 0, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 49, 49, 49, + 49, 49, 49, 17, 17, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, + 17, 17, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 0, 17, 17, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 49, 49, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 0, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 0, 0, 0, 49, 49, 49, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 49, 125, + 19, 19, 19, 126, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 19, 19, 19, 19, 19, 127, 19, 19, 128, 19, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 129, 129, 129, 129, 129, 129, 129, 129, 130, 130, + 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, 129, 129, 0, 0, 130, + 130, 130, 130, 130, 130, 0, 0, 129, 129, 129, 129, 129, 129, 129, 129, + 130, 130, 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, 129, 129, + 129, 129, 130, 130, 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, + 129, 129, 0, 0, 130, 130, 130, 130, 130, 130, 0, 0, 19, 129, 19, 129, 19, + 129, 19, 129, 0, 130, 0, 130, 0, 130, 0, 130, 129, 129, 129, 129, 129, + 129, 129, 129, 130, 130, 130, 130, 130, 130, 130, 130, 131, 131, 132, + 132, 132, 132, 133, 133, 134, 134, 135, 135, 136, 136, 0, 0, 129, 129, + 129, 129, 129, 129, 129, 129, 137, 137, 137, 137, 137, 137, 137, 137, + 129, 129, 129, 129, 129, 129, 129, 129, 137, 137, 137, 137, 137, 137, + 137, 137, 129, 129, 129, 129, 129, 129, 129, 129, 137, 137, 137, 137, + 137, 137, 137, 137, 129, 129, 19, 138, 19, 0, 19, 19, 130, 130, 139, 139, + 140, 5, 141, 5, 5, 5, 19, 138, 19, 0, 19, 19, 142, 142, 142, 142, 140, 5, + 5, 5, 129, 129, 19, 19, 0, 0, 19, 19, 130, 130, 143, 143, 0, 5, 5, 5, + 129, 129, 19, 19, 19, 104, 19, 19, 130, 130, 144, 144, 107, 5, 5, 5, 0, + 0, 19, 138, 19, 0, 19, 19, 145, 145, 146, 146, 140, 5, 5, 0, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 1, 1, 1, 1, 1, 2, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 147, 19, 0, 0, 148, 149, 150, 151, + 152, 153, 5, 5, 5, 5, 5, 19, 147, 23, 20, 21, 148, 149, 150, 151, 152, + 153, 5, 5, 5, 5, 5, 0, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 17, 5, + 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 98, 5, 5, 5, 5, 98, 5, 5, 19, 98, 98, + 98, 19, 19, 98, 98, 98, 19, 5, 98, 5, 5, 124, 98, 98, 98, 98, 98, 5, 5, + 5, 5, 5, 5, 98, 5, 154, 5, 98, 5, 155, 156, 98, 98, 124, 19, 98, 98, 157, + 98, 19, 49, 49, 49, 49, 19, 5, 5, 19, 19, 98, 98, 5, 5, 5, 5, 5, 98, 19, + 19, 19, 19, 5, 5, 5, 5, 158, 5, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 124, 124, 124, 25, 26, 124, 124, 124, 124, 0, 0, + 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 23, 20, 21, 148, 149, 150, 151, 152, 153, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 23, 20, 21, 148, 149, 150, 151, 152, 153, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 23, 20, 21, 148, 149, 150, 151, 152, 153, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, - 146, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 22, 19, 20, 147, 148, 149, 150, 151, - 152, 4, 146, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, - 4, 0, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 0, 4, 0, 4, 4, 4, 4, 0, 0, 0, 4, 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 22, 19, 20, 147, - 148, 149, 150, 151, 152, 4, 22, 19, 20, 147, 148, 149, 150, 151, 152, 4, - 22, 19, 20, 147, 148, 149, 150, 151, 152, 4, 4, 0, 0, 0, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, - 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 161, 161, 161, 161, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 147, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 23, 20, 21, 148, 149, 150, + 151, 152, 153, 5, 147, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 0, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 0, 5, 0, 5, 5, 5, 5, 0, 0, 0, 5, 0, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 23, 20, + 21, 148, 149, 150, 151, 152, 153, 5, 23, 20, 21, 148, 149, 150, 151, 152, + 153, 5, 23, 20, 21, 148, 149, 150, 151, 152, 153, 5, 5, 0, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 5, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 0, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, - 111, 111, 111, 111, 111, 111, 111, 0, 24, 25, 162, 163, 164, 165, 166, - 24, 25, 24, 25, 24, 25, 167, 168, 169, 0, 18, 24, 25, 18, 24, 25, 18, 18, - 18, 18, 18, 18, 48, 0, 0, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 18, 4, 4, - 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, - 4, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, - 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, - 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, - 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, - 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, - 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, - 48, 48, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 84, 4, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 0, 0, 0, 0, 2, 4, 4, 4, 4, 48, 48, 123, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 16, 16, 16, 16, 16, 16, 4, 48, 48, 48, 48, 48, 4, 4, - 123, 123, 123, 48, 48, 4, 4, 4, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 16, 16, 4, 4, 48, 48, 48, 4, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 48, 48, 48, - 48, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 4, 4, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 0, 0, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 48, 16, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 16, 16, 4, 48, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, - 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 4, 4, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 18, 18, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 24, 25, 48, 18, 18, 18, - 18, 18, 18, 18, 18, 24, 25, 24, 25, 171, 24, 25, 24, 25, 24, 25, 24, 25, - 24, 25, 48, 4, 4, 24, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, - 48, 48, 48, 48, 48, 16, 48, 48, 48, 16, 48, 48, 48, 48, 16, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 16, 16, 16, 16, 16, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 48, 48, 48, 16, 48, 48, 48, 48, 48, 48, 48, 48, 16, 16, 0, 0, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 0, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 0, 25, 26, 163, 164, 165, 166, + 167, 25, 26, 25, 26, 25, 26, 168, 169, 170, 0, 19, 25, 26, 19, 25, 26, + 19, 19, 19, 19, 19, 19, 49, 0, 0, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 19, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, + 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, + 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, + 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, + 49, 49, 49, 49, 49, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 85, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 2, 5, 5, 5, 5, 49, 49, 124, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 17, 17, 17, 17, 17, 17, 5, 49, 49, 49, + 49, 49, 5, 5, 124, 124, 124, 49, 49, 5, 5, 5, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 17, 17, 5, 5, 49, 49, 49, 5, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, + 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 5, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 0, 0, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 49, 17, 5, 5, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 17, 5, 49, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, + 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 19, 19, 25, 26, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 25, 26, 49, + 19, 19, 19, 19, 19, 19, 19, 19, 25, 26, 25, 26, 172, 25, 26, 25, 26, 25, + 26, 25, 26, 25, 26, 49, 5, 5, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 49, 49, 49, 49, 49, 49, 49, 17, 49, 49, 49, 17, 49, 49, 49, 49, 17, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 17, + 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 17, 49, 49, 49, 49, 49, 49, + 49, 49, 17, 17, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 5, 5, 5, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1107,371 +1108,372 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 48, 16, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 0, 48, 0, 48, 48, 0, 48, 48, - 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 84, 84, 84, 84, 84, 84, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 84, 84, 4, 4, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 16, - 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 16, 16, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, - 16, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 0, 4, 4, 4, 4, 0, 0, 0, 0, 84, 48, 84, 48, 84, 0, 84, 48, 84, 48, 84, 48, - 84, 48, 84, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 0, 0, 1, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 4, 4, 4, 4, 4, 4, 4, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 4, 4, 4, 4, 16, 4, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 112, 112, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 0, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 48, - 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 48, 0, 0, 0, 4, - 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 4, 4, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, - 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, - 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, - 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 123, 48, 48, 48, 48, 48, 48, 48, 48, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 4, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 48, 48, 48, 48, 48, - 48, 48, 48, 4, 123, 123, 123, 123, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, + 19, 0, 0, 0, 0, 0, 49, 17, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 0, + 49, 0, 49, 49, 0, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 85, 85, 85, 85, 85, 85, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 85, 85, 5, 5, 0, 0, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 17, 17, 17, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 0, 0, 0, 0, 85, 49, 85, 49, 85, 0, + 85, 49, 85, 49, 85, 49, 85, 49, 85, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 1, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, + 5, 5, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 5, 5, 5, 5, 17, 5, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 113, 113, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 49, 49, 49, 49, 49, + 49, 0, 0, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, 49, 49, 49, 49, 0, 0, 49, + 49, 49, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 5, 5, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, + 0, 0, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 0, 0, 48, 0, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 0, 0, 0, 48, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 5, 5, 5, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 124, 49, 49, 49, 49, 49, 49, 49, 49, 124, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 5, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, + 49, 49, 49, 49, 49, 49, 49, 49, 5, 124, 124, 124, 124, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, + 49, 0, 0, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 49, 49, 0, 0, 0, 49, + 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 4, 4, 4, 4, 0, 0, 0, 0, 0, 4, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, - 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 5, 5, 5, 5, 0, 0, 0, 0, 0, 5, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 48, 16, 16, 16, 0, 16, 16, 0, 0, 0, 0, 0, 16, 16, 16, 16, 48, - 48, 48, 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, - 0, 16, 16, 16, 0, 0, 0, 0, 16, 22, 19, 20, 147, 4, 4, 4, 4, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 17, 17, 17, 0, 17, 17, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 49, 49, 49, 49, 0, 49, 49, 49, 0, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 0, 0, 0, 0, 17, 17, 17, 0, 0, 0, 0, 17, 23, 20, 21, 148, 5, + 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 16, 16, 16, 16, 16, 4, 4, 4, 16, 16, 16, 16, 16, 16, 1, 1, 1, - 1, 1, 1, 1, 1, 16, 16, 16, 16, 16, 16, 16, 16, 4, 4, 16, 16, 16, 16, 16, - 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, 17, 17, 5, 5, 5, 17, 17, 17, 17, + 17, 17, 1, 1, 1, 1, 1, 1, 1, 1, 17, 17, 17, 17, 17, 17, 17, 17, 5, 5, 17, + 17, 17, 17, 17, 17, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 17, 17, 17, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, + 17, 17, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, 18, 18, - 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 97, 0, 97, 97, 0, 0, 97, 0, 0, 97, 97, 0, 0, 97, 97, 97, 97, 0, 97, 97, - 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, 0, 18, 0, 18, 18, 18, 18, 18, 18, - 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 97, 97, 0, 97, 97, 97, 97, 0, - 0, 97, 97, 97, 97, 97, 97, 97, 97, 0, 97, 97, 97, 97, 97, 97, 97, 0, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 97, 97, 0, 97, 97, 97, 97, 0, 97, 97, 97, 97, - 97, 0, 97, 0, 0, 0, 97, 97, 97, 97, 97, 97, 97, 0, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 4, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 4, 18, 18, 18, 18, 18, 18, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 4, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 4, 18, 18, 18, 18, - 18, 18, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 4, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 4, - 18, 18, 18, 18, 18, 18, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 4, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 4, 18, 18, 18, 18, 18, 18, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 4, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 4, 18, 18, 18, 18, 18, 18, 97, 18, 0, 0, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 98, 0, 98, 98, 0, 0, 98, 0, 0, 98, 98, 0, 0, 98, 98, 98, + 98, 0, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 0, 19, 0, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, 0, + 98, 98, 98, 98, 0, 0, 98, 98, 98, 98, 98, 98, 98, 98, 0, 98, 98, 98, 98, + 98, 98, 98, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, 0, 98, 98, 98, + 98, 0, 98, 98, 98, 98, 98, 0, 98, 0, 0, 0, 98, 98, 98, 98, 98, 98, 98, 0, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 5, 19, 19, 19, + 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 5, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 5, 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 5, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 5, 19, 19, 19, 19, 19, 19, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 5, 19, 19, 19, 19, 19, 19, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 5, 19, 19, 19, 19, 19, + 19, 98, 19, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1481,6 +1483,6 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, }; Modified: python/branches/release30-maint/Tools/unicode/makeunicodedata.py ============================================================================== --- python/branches/release30-maint/Tools/unicode/makeunicodedata.py (original) +++ python/branches/release30-maint/Tools/unicode/makeunicodedata.py Thu Mar 26 22:51:18 2009 @@ -375,7 +375,7 @@ flags |= TITLE_MASK if category == "Lu": flags |= UPPER_MASK - if char == " " or category[0] not in ("C", "Z"): + if char == ord(" ") or category[0] not in ("C", "Z"): flags |= PRINTABLE_MASK if "XID_Start" in properties: flags |= XID_START_MASK From buildbot at python.org Thu Mar 26 22:54:08 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 21:54:08 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090326215408.D34471E4050@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/271 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_descr Traceback (most recent call last): File "./Lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "/home/pybot/buildarea/trunk.klose-debian-ppc/build/Lib/test/test_descr.py", line 9, in class OperatorsTest(unittest.TestCase): File "/home/pybot/buildarea/trunk.klose-debian-ppc/build/Lib/test/test_descr.py", line 310, in OperatorsTest @test_support.impl_detail("the module 'xxsubtype' is internal") File "/home/pybot/buildarea/trunk.klose-debian-ppc/build/Lib/test/test_support.py", line 708, in impl_detail if check_impl_detail(guards): TypeError: check_impl_detail() takes exactly 0 arguments (1 given) make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Thu Mar 26 22:54:54 2009 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 26 Mar 2009 22:54:54 +0100 (CET) Subject: [Python-checkins] r70630 - in python/branches/release30-maint: Lib/platform.py Lib/test/test_platform.py Lib/urllib/request.py Misc/python.man Message-ID: <20090326215454.148471E4002@bag.python.org> Author: benjamin.peterson Date: Thu Mar 26 22:54:53 2009 New Revision: 70630 Log: Merged revisions 70628 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70628 | benjamin.peterson | 2009-03-26 16:49:58 -0500 (Thu, 26 Mar 2009) | 31 lines Merged revisions 70518,70521,70590,70594-70595 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70518 | matthias.klose | 2009-03-22 08:08:22 -0500 (Sun, 22 Mar 2009) | 2 lines - Fix comment macro in python.man ........ r70521 | benjamin.peterson | 2009-03-22 12:45:11 -0500 (Sun, 22 Mar 2009) | 1 line close the file even if an exception occurs #5536 ........ r70590 | skip.montanaro | 2009-03-24 19:52:11 -0500 (Tue, 24 Mar 2009) | 1 line clarify the type of data returned ........ r70594 | marc-andre.lemburg | 2009-03-25 14:44:58 -0500 (Wed, 25 Mar 2009) | 9 lines Remove the sys.version_info shortcut, since they cause the APIs to return different information than the _sys_version() output used in previous Python versions. This also fixes issue5561: platform.python_version_tuple returns tuple of ints, should be strings Added more tests for the various platform functions. ........ r70595 | marc-andre.lemburg | 2009-03-25 14:45:33 -0500 (Wed, 25 Mar 2009) | 3 lines News item for the platform.py fix (r70594). ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/platform.py python/branches/release30-maint/Lib/test/test_platform.py python/branches/release30-maint/Lib/urllib/request.py python/branches/release30-maint/Misc/python.man Modified: python/branches/release30-maint/Lib/platform.py ============================================================================== --- python/branches/release30-maint/Lib/platform.py (original) +++ python/branches/release30-maint/Lib/platform.py Thu Mar 26 22:54:53 2009 @@ -1254,10 +1254,10 @@ def _sys_version(sys_version=None): """ Returns a parsed version of Python's sys.version as tuple - (name, version, branch, revision, buildno, builddate, compiler) - referring to the Python implementation name, version, branch, - revision, build number, build date/time as string and the compiler - identification string. + (name, version, branch, revision, buildno, builddate, compiler) + referring to the Python implementation name, version, branch, + revision, build number, build date/time as string and the compiler + identification string. Note that unlike the Python sys.version, the returned value for the Python version will always include the patchlevel (it @@ -1359,8 +1359,6 @@ will always include the patchlevel (it defaults to 0). """ - if hasattr(sys, 'version_info'): - return '%i.%i.%i' % sys.version_info[:3] return _sys_version()[1] def python_version_tuple(): @@ -1372,8 +1370,6 @@ will always include the patchlevel (it defaults to 0). """ - if hasattr(sys, 'version_info'): - return sys.version_info[:3] return tuple(_sys_version()[1].split('.')) def python_branch(): Modified: python/branches/release30-maint/Lib/test/test_platform.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_platform.py (original) +++ python/branches/release30-maint/Lib/test/test_platform.py Thu Mar 26 22:54:53 2009 @@ -25,39 +25,48 @@ finally: os.remove(link) - def test_machine(self): - res = platform.machine() - - def test_node(self): - res = platform.node() - def test_platform(self): for aliased in (False, True): for terse in (False, True): res = platform.platform(aliased, terse) - def test_processor(self): - res = platform.processor() + def test_system(self): + res = platform.system() - def test_python_build(self): - res = platform.python_build() + def test_node(self): + res = platform.node() - def test_python_compiler(self): - res = platform.python_compiler() + def test_release(self): + res = platform.release() def test_version(self): - res1 = platform.version() - res2 = platform.version_tuple() + res = platform.version() + + def test_machine(self): + res = platform.machine() + + def test_processor(self): + res = platform.processor() + + def test_python_implementation(self): + res = platform.python_implementation() + + def test_python_version(self): + res1 = platform.python_version() + res2 = platform.python_version_tuple() self.assertEqual(res1, ".".join(res2)) - def test_release(self): - res = platform.release() + def test_python_branch(self): + res = platform.python_branch() - def test_system(self): - res = platform.system() + def test_python_revision(self): + res = platform.python_revision() - def test_version(self): - res = platform.version() + def test_python_build(self): + res = platform.python_build() + + def test_python_compiler(self): + res = platform.python_compiler() def test_system_alias(self): res = platform.system_alias( Modified: python/branches/release30-maint/Lib/urllib/request.py ============================================================================== --- python/branches/release30-maint/Lib/urllib/request.py (original) +++ python/branches/release30-maint/Lib/urllib/request.py Thu Mar 26 22:54:53 2009 @@ -1474,41 +1474,45 @@ except IOError as msg: pass fp = self.open(url, data) - headers = fp.info() - if filename: - tfp = open(filename, 'wb') - else: - import tempfile - garbage, path = splittype(url) - garbage, path = splithost(path or "") - path, garbage = splitquery(path or "") - path, garbage = splitattr(path or "") - suffix = os.path.splitext(path)[1] - (fd, filename) = tempfile.mkstemp(suffix) - self.__tempfiles.append(filename) - tfp = os.fdopen(fd, 'wb') - result = filename, headers - if self.tempcache is not None: - self.tempcache[url] = result - bs = 1024*8 - size = -1 - read = 0 - blocknum = 0 - if reporthook: - if "content-length" in headers: - size = int(headers["Content-Length"]) - reporthook(blocknum, bs, size) - while 1: - block = fp.read(bs) - if not block: - break - read += len(block) - tfp.write(block) - blocknum += 1 - if reporthook: - reporthook(blocknum, bs, size) - fp.close() - tfp.close() + try: + headers = fp.info() + if filename: + tfp = open(filename, 'wb') + else: + import tempfile + garbage, path = splittype(url) + garbage, path = splithost(path or "") + path, garbage = splitquery(path or "") + path, garbage = splitattr(path or "") + suffix = os.path.splitext(path)[1] + (fd, filename) = tempfile.mkstemp(suffix) + self.__tempfiles.append(filename) + tfp = os.fdopen(fd, 'wb') + try: + result = filename, headers + if self.tempcache is not None: + self.tempcache[url] = result + bs = 1024*8 + size = -1 + read = 0 + blocknum = 0 + if reporthook: + if "content-length" in headers: + size = int(headers["Content-Length"]) + reporthook(blocknum, bs, size) + while 1: + block = fp.read(bs) + if not block: + break + read += len(block) + tfp.write(block) + blocknum += 1 + if reporthook: + reporthook(blocknum, bs, size) + finally: + tfp.close() + finally: + fp.close() del fp del tfp Modified: python/branches/release30-maint/Misc/python.man ============================================================================== --- python/branches/release30-maint/Misc/python.man (original) +++ python/branches/release30-maint/Misc/python.man Thu Mar 26 22:54:53 2009 @@ -1,7 +1,7 @@ .TH PYTHON "1" "$Date$" -./" To view this file while editing, run it through groff: -./" groff -Tascii -man python.man | less +.\" To view this file while editing, run it through groff: +.\" groff -Tascii -man python.man | less .SH NAME python \- an interpreted, interactive, object-oriented programming language From python-checkins at python.org Thu Mar 26 23:04:05 2009 From: python-checkins at python.org (jeremy.hylton) Date: Thu, 26 Mar 2009 23:04:05 +0100 (CET) Subject: [Python-checkins] r70631 - python/branches/py3k/Lib/http/client.py Message-ID: <20090326220405.7B52E1E4002@bag.python.org> Author: jeremy.hylton Date: Thu Mar 26 23:04:05 2009 New Revision: 70631 Log: Simplify complex expression. Modified: python/branches/py3k/Lib/http/client.py Modified: python/branches/py3k/Lib/http/client.py ============================================================================== --- python/branches/py3k/Lib/http/client.py (original) +++ python/branches/py3k/Lib/http/client.py Thu Mar 26 23:04:05 2009 @@ -906,7 +906,9 @@ self._set_content_length(body) for hdr, value in headers.items(): self.putheader(hdr, value) - self.endheaders(body.encode('ascii') if isinstance(body, str) else body) + if isinstance(body, str): + body = body.encode('ascii') + self.endheaders(body) def getresponse(self): """Get the response from the server.""" From buildbot at python.org Thu Mar 26 23:16:38 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 22:16:38 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090326221639.328C91E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/519 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_json make: *** [buildbottest] Error 1 sincerely, -The Buildbot From nnorwitz at gmail.com Fri Mar 27 00:21:59 2009 From: nnorwitz at gmail.com (Neal Norwitz) Date: Thu, 26 Mar 2009 18:21:59 -0500 Subject: [Python-checkins] Python Regression Test Failures all (3) Message-ID: <20090326232159.GA23804@python.psfb.org> 314 tests OK. 3 tests failed: test_al test_bsddb185 test_imgfile 47 tests skipped: test__locale test_aepack test_applesingle test_cd test_cl test_commands test_decimal test_dl test_email_codecs test_epoll test_fork1 test_gl test_ioctl test_kqueue test_largefile test_lib2to3 test_locale test_macos test_macostools test_mhlib test_minidom test_multiprocessing test_openpty test_pep277 test_pipes test_poll test_popen2 test_pty test_py3kwarn test_scriptpackages test_site test_socketserver test_sqlite test_startfile test_sunaudiodev test_tcl test_threaded_import test_threadsignals test_tk test_ttk_guionly test_ttk_textonly test_unicode_file test_wait3 test_wait4 test_winreg test_winsound test_zipfile64 26 skips unexpected on linux2: test_wait4 test_pipes test_wait3 test_pty test_locale test_multiprocessing test_ttk_textonly test_email_codecs test_threadsignals test_minidom test_decimal test_poll test_epoll test_site test_popen2 test_lib2to3 test_ttk_guionly test_mhlib test_openpty test_commands test_threaded_import test_fork1 test__locale test_tk test_ioctl test_socketserver test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_SimpleHTTPServer test_StringIO test___all__ test___future__ test__locale test__locale skipped -- cannot import name SkipTest test_abc test_abstract_numbers test_aepack test_aepack skipped -- No module named aepack test_al test test_al crashed -- : global name 'SkipTest' is not defined test_anydbm test_applesingle test_applesingle skipped -- No module named macostools test_array test_ast test_asynchat test_asyncore 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 test_bsddb185 crashed -- : global name 'SkipTest' is not defined test_bsddb3 Sleepycat Software: Berkeley DB 4.1.25: (December 19, 2002) Test path prefix: /tmp/z-test_bsddb3-6521 test_buffer test_bufio test_bytes test_bz2 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 test_cmd_line test_cmd_line_script 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_commands skipped -- cannot import name SkipTest test_compare test_compile test_compileall test_compiler testCompileLibrary still working, be patient... 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 Exception RuntimeError: 'maximum recursion depth exceeded while calling a Python object' in ignored test_cprofile test_crypt test_csv test_ctypes test_datetime test_dbm test_decimal test_decimal skipped -- cannot import name SkipTest test_decorators test_defaultdict test_deque test_descr test_descrtut test_difflib test_dircache test_dis test_distutils test_dl test_dl skipped -- cannot import name SkipTest test_docxmlrpc test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_codecs skipped -- cannot import name TestSkipped test_email_renamed test_enumerate test_eof test_epoll test_epoll skipped -- kernel doesn't support epoll() test_errno test_exception_variations test_extcall test_fcntl test_file test_filecmp test_fileinput test_fileio test_float test_fnmatch test_fork1 test_fork1 skipped -- cannot import name SkipTest test_format test_fpformat test_fractions test_frozen test_ftplib test_funcattrs test_functools test_future test_future3 test_future4 test_future5 test_future_builtins test_gc test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- cannot import name SkipTest test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_httpservers [13179 refs] [13179 refs] [23375 refs] test_imageop test_imaplib test_imgfile test test_imgfile crashed -- : global name 'SkipTest' is not defined test_imp test_import test_importhooks test_importlib test_index test_inspect test_int test_int_literal test_io test_ioctl test_ioctl skipped -- cannot import name SkipTest test_isinstance test_iter test_iterlen test_itertools test_json test_kqueue test_kqueue skipped -- test works only on BSD test_largefile test_largefile skipped -- cannot import name SkipTest test_lib2to3 test_lib2to3 skipped -- No module named myfixes test_list test_locale test_locale skipped -- cannot import name SkipTest test_logging test_long test_long_future test_longexp test_macos test_macos skipped -- No module named MacOS test_macostools test_macostools skipped -- No module named macostools test_macpath test_mailbox test_marshal test_math test_md5 test_memoryio test_mhlib test_mhlib skipped -- cannot import name SkipTest test_mimetools test_mimetypes test_minidom test_minidom skipped -- cannot import name SkipTest test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_multiprocessing test_multiprocessing skipped -- cannot import name SkipTest test_mutants test_mutex test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_openpty skipped -- cannot import name SkipTest test_operator test_optparse test_os test_parser Expecting 's_push: parser stack overflow' in next line s_push: parser stack overflow 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_pipes test_pipes skipped -- cannot import name SkipTest test_pkg test_pkgimport test_pkgutil test_platform [14834 refs] [14834 refs] test_plistlib test_poll test_poll skipped -- cannot import name SkipTest test_popen [13184 refs] [13184 refs] [13184 refs] test_popen2 test_popen2 skipped -- cannot import name SkipTest test_poplib test_posix test_posixpath test_pow test_pprint test_print test_profile test_profilehooks test_property test_pstats test_pty test_pty skipped -- cannot import name SkipTest test_pwd test_py3kwarn test_py3kwarn skipped -- cannot import name SkipTest test_pyclbr test_pydoc [18903 refs] test_pyexpat test_queue test_quopri [15704 refs] [15704 refs] test_random test_re test_repr test_resource test_rfc822 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_site skipped -- cannot import name SkipTest test_slice test_smtplib test_socket test_socketserver test_socketserver skipped -- cannot import name SkipTest test_softspace test_sort test_sqlite test_sqlite skipped -- cannot import name SkipTest test_ssl 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 [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [15079 refs] [13394 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] [13179 refs] . [13179 refs] [13179 refs] this bit of output is from a test of stdout in a different process ... [13179 refs] [13179 refs] [13394 refs] test_sunaudiodev test_sunaudiodev skipped -- cannot import name SkipTest test_sundry /tmp/python-test/local/lib/python2.7/test/test_sundry.py:66: DeprecationWarning: The posixfile module is deprecated; fcntl.lockf() provides better locking import posixfile test_symtable test_syntax test_sys [13179 refs] [13179 refs] [13408 refs] [13202 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [13182 refs] test_textwrap test_thread test_threaded_import test_threaded_import skipped -- cannot import name SkipTest test_threadedtempfile test_threading [16675 refs] [18026 refs] [17842 refs] [17842 refs] [17842 refs] [17842 refs] test_threading_local test_threadsignals test_threadsignals skipped -- cannot import name SkipTest test_time test_timeout test_tk test_tk skipped -- No module named _tkinter test_tokenize test_trace test_traceback test_transformer test_ttk_guionly test_ttk_guionly skipped -- No module named _tkinter test_ttk_textonly test_ttk_textonly skipped -- No module named runtktests test_tuple test_typechecks test_ucn test_unary test_undocumented_details test_unicode test_unicode_file test_unicode_file skipped -- cannot import name SkipTest test_unicodedata test_univnewlines test_unpack test_urllib test_urllib2 test_urllib2_localnet 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_wait3 skipped -- cannot import name SkipTest test_wait4 test_wait4 skipped -- cannot import name SkipTest 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_zipimport_support test_zlib 314 tests OK. 3 tests failed: test_al test_bsddb185 test_imgfile 47 tests skipped: test__locale test_aepack test_applesingle test_cd test_cl test_commands test_decimal test_dl test_email_codecs test_epoll test_fork1 test_gl test_ioctl test_kqueue test_largefile test_lib2to3 test_locale test_macos test_macostools test_mhlib test_minidom test_multiprocessing test_openpty test_pep277 test_pipes test_poll test_popen2 test_pty test_py3kwarn test_scriptpackages test_site test_socketserver test_sqlite test_startfile test_sunaudiodev test_tcl test_threaded_import test_threadsignals test_tk test_ttk_guionly test_ttk_textonly test_unicode_file test_wait3 test_wait4 test_winreg test_winsound test_zipfile64 26 skips unexpected on linux2: test_wait4 test_pipes test_wait3 test_pty test_locale test_multiprocessing test_ttk_textonly test_email_codecs test_threadsignals test_minidom test_decimal test_poll test_epoll test_site test_popen2 test_lib2to3 test_ttk_guionly test_mhlib test_openpty test_commands test_threaded_import test_fork1 test__locale test_tk test_ioctl test_socketserver [652892 refs] From buildbot at python.org Fri Mar 27 00:24:12 2009 From: buildbot at python.org (buildbot at python.org) Date: Thu, 26 Mar 2009 23:24:12 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090326232412.A646A1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/558 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Fri Mar 27 01:22:37 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Mar 2009 00:22:37 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090327002237.799F41E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/453 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_pipes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Fri Mar 27 03:02:08 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Mar 2009 02:02:08 +0000 Subject: [Python-checkins] buildbot failure in x86 XP-4 3.0 Message-ID: <20090327020208.D8E411E4002@bag.python.org> The Buildbot has detected a new failure of x86 XP-4 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20XP-4%203.0/builds/183 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: bolen-windows Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: benjamin.peterson,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_memoryio ====================================================================== FAIL: test_newline_none (test.test_memoryio.PyStringIOTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\3.0.bolen-windows\build\lib\test\test_memoryio.py", line 381, in test_newline_none self.assertEqual(memio.readlines(), ["hello\n", "hi\n"]) AssertionError: ['hello\n', '\n', 'hi\n', '\n'] != ['hello\n', 'hi\n'] ====================================================================== FAIL: test_newline_none (test.test_memoryio.CStringIOTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\cygwin\home\db3l\buildarea\3.0.bolen-windows\build\lib\test\test_memoryio.py", line 381, in test_newline_none self.assertEqual(memio.readlines(), ["hello\n", "hi\n"]) AssertionError: ['hello\n', '\n', '\n', 'hi\n', '\n', '\n'] != ['hello\n', 'hi\n'] sincerely, -The Buildbot From buildbot at python.org Fri Mar 27 04:26:15 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Mar 2009 03:26:15 +0000 Subject: [Python-checkins] buildbot failure in x86 XP-4 trunk Message-ID: <20090327032615.BB3DE1E4002@bag.python.org> The Buildbot has detected a new failure of x86 XP-4 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20XP-4%20trunk/builds/1989 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: bolen-windows Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 3 tests failed: test_fork1 test_posix test_wait4 Traceback (most recent call last): File "../lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "E:\cygwin\home\db3l\buildarea\trunk.bolen-windows\build\lib\test\test_fork1.py", line 12, in raise unittest.SkipTest, "os.fork not defined -- skipping test_fork1" NameError: name 'unittest' is not defined Traceback (most recent call last): File "../lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "E:\cygwin\home\db3l\buildarea\trunk.bolen-windows\build\lib\test\test_posix.py", line 8, in raise unittest.SkipTest, "posix is not available" NameError: name 'unittest' is not defined Traceback (most recent call last): File "../lib/test/regrtest.py", line 552, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "E:\cygwin\home\db3l\buildarea\trunk.bolen-windows\build\lib\test\test_wait4.py", line 12, in raise unittest.SkipTest, "os.fork not defined -- skipping test_wait4" NameError: name 'unittest' is not defined sincerely, -The Buildbot From python-checkins at python.org Fri Mar 27 04:33:13 2009 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 27 Mar 2009 04:33:13 +0100 (CET) Subject: [Python-checkins] r70632 - peps/trunk/pep-0380.txt Message-ID: <20090327033313.C122F1E4002@bag.python.org> Author: guido.van.rossum Date: Fri Mar 27 04:33:12 2009 New Revision: 70632 Log: Greg's latest version. Modified: peps/trunk/pep-0380.txt Modified: peps/trunk/pep-0380.txt ============================================================================== --- peps/trunk/pep-0380.txt (original) +++ peps/trunk/pep-0380.txt Fri Mar 27 04:33:12 2009 @@ -24,6 +24,37 @@ one generator re-yields values produced by another. +Motivation +========== + +A Python generator is a form of coroutine, but has the limitation that +it can only yield to its immediate caller. This means that a piece of +code containing a ``yield`` cannot be factored out and put into a +separate function in the same way as other code. Performing such a +factoring causes the called function to itself become a generator, and +it is necessary to explicitly iterate over this second generator and +re-yield any values that it produces. + +If yielding of values is the only concern, this can be performed without +much difficulty using a loop such as + +:: + + for v in g: + yield v + +However, if the subgenerator is to interact properly with the caller +in the case of calls to ``send()``, ``throw()`` and ``close()``, things +become considerably more difficult. As will be seen later, the necessary +code is very complicated, and it is tricky to handle all the corner cases +correctly. + +A new syntax will be proposed to address this issue. In the simplest +use cases, it will be equivalent to the above for-loop, but it will also +handle the full range of generator behaviour, and allow generator code +to be refactored in a simple and straightforward way. + + Proposal ======== @@ -32,7 +63,7 @@ :: - yield from + yield from where is an expression evaluating to an iterable, from which an iterator is extracted. The iterator is run to exhaustion, during which @@ -40,40 +71,55 @@ the generator containing the ``yield from`` expression (the "delegating generator"). -When the iterator is another generator, the effect is the same as if -the body of the subgenerator were inlined at the point of the ``yield -from`` expression. Furthermore, the subgenerator is allowed to execute -a ``return`` statement with a value, and that value becomes the value of -the ``yield from`` expression. +Furthermore, when the iterator is another generator, the subgenerator is +allowed to execute a ``return`` statement with a value, and that value +becomes the value of the ``yield from`` expression. -In general, the semantics can be understood in terms of the iterator +In general, the semantics can be described in terms of the iterator protocol as follows: - * Any values that the iterator yields are passed directly to the - caller. + * Any values that the iterator yields are passed directly to the + caller. + + * Any values sent to the delegating generator using ``send()`` + are passed directly to the iterator. If the sent value is None, + the iterator's ``next()`` method is called. If the sent value is + not None, the iterator's ``send()`` method is called. Any exception + resulting from attempting to call ``next`` or ``send`` is raised + in the delegating generator. + + * Exceptions passed to the ``throw()`` method of the delegating + generator are forwarded to the ``throw()`` method of the iterator. + If the iterator does not have a ``throw()`` method, its ``close()`` + method is called if it has one, then the thrown-in exception is + raised in the delegating generator. Any exception resulting from + attempting to call these methods (apart from one case noted below) + is raised in the delegating generator. + + * The value of the ``yield from`` expression is the first argument + to the ``StopIteration`` exception raised by the iterator when it + terminates. + + * ``return expr`` in a generator causes ``StopIteration(expr)`` to + be raised. + + +Fine Details +------------ + +The implicit GeneratorExit resulting from closing the delegating +generator is treated as though it were passed in using ``throw()``. +An iterator having a ``throw()`` method is expected to recognize +this as a request to finalize itself. + +If a call to the iterator's ``throw()`` method raises a StopIteration +exception, and it is *not* the same exception object that was thrown +in, its value is returned as the value of the ``yield from`` expression +and the delegating generator is resumed. - * Any values sent to the delegating generator using ``send()`` - are passed directly to the iterator. If the sent value is None, - the iterator's ``next()`` method is called. If the sent value is - not None, the iterator's ``send()`` method is called. Any exception - resulting from attempting to call ``next`` or ``send`` is raised - in the delegating generator. - - * Calls to the ``throw()`` method of the delegating generator are - forwarded to the iterator. If the iterator does not have a - ``throw()`` method, the thrown-in exception is raised in the - delegating generator. - - * If the delegating generator's ``close()`` method is called, the - ``close() method of the iterator is called first if it has one, - then the delegating generator is finalised. - - * The value of the ``yield from`` expression is the first argument - to the ``StopIteration`` exception raised by the iterator when it - terminates. - * ``return expr`` in a generator causes ``StopIteration(expr)`` to - be raised. +Enhancements to StopIteration +----------------------------- For convenience, the ``StopIteration`` exception will be given a ``value`` attribute that holds its first argument, or None if there @@ -87,50 +133,66 @@ :: - result = yield from expr + RESULT = yield from EXPR is semantically equivalent to :: - _i = iter(expr) - try: - _u = _i.next() - while 1: - try: - _v = yield _u - except Exception, _e: - _m = getattr(_i, 'throw', None) - if _m is not None: - _u = _m(_e) - else: - raise - else: - if _v is None: - _u = _i.next() - else: - _u = _i.send(_v) - except StopIteration, _e: - result = _e.value - finally: - _m = getattr(_i, 'close', None) - if _m is not None: - _m() + _i = iter(EXPR) + try: + try: + _y = _i.next() + except StopIteration, _e: + _r = _e.value + else: + while 1: + try: + _s = yield _y + except: + _m = getattr(_i, 'throw', None) + if _m is not None: + _x = sys.exc_info() + try: + _y = _m(*_x) + except StopIteration, _e: + if _e is _x[1]: + raise + else: + _r = _e.value + break + else: + _m = getattr(_i, 'close', None) + if _m is not None: + _m() + raise + else: + try: + if _s is None: + _y = _i.next() + else: + _y = _i.send(_s) + except StopIteration, _e: + _r = _e.value + break + finally: + del _i + RESULT = _r except that implementations are free to cache bound methods for the 'next', -'send', 'throw' and 'close' methods of the iterator. +'send' and 'throw' methods of the iterator upon first use. 2. In a generator, the statement :: - return value + return value is semantically equivalent to :: - raise StopIteration(value) + raise StopIteration(value) except that, as currently, the exception cannot be caught by ``except`` clauses within the returning generator. @@ -139,66 +201,82 @@ :: - class StopIteration(Exception): + class StopIteration(Exception): - def __init__(self, *args): - if len(args) > 0: - self.value = args[0] - else: - self.value = None - Exception.__init__(self, *args) + def __init__(self, *args): + if len(args) > 0: + self.value = args[0] + else: + self.value = None + Exception.__init__(self, *args) Rationale ========= -A Python generator is a form of coroutine, but has the limitation that -it can only yield to its immediate caller. This means that a piece of -code containing a ``yield`` cannot be factored out and put into a -separate function in the same way as other code. Performing such a -factoring causes the called function to itself become a generator, and -it is necessary to explicitly iterate over this second generator and -re-yield any values that it produces. - -If yielding of values is the only concern, this is not very arduous -and can be performed with a loop such as - -:: - - for v in g: - yield v +The Refactoring Principle +------------------------- -However, if the subgenerator is to interact properly with the caller -in the case of calls to ``send()``, ``throw()`` and ``close()``, things -become considerably more complicated. As the formal expansion presented -above illustrates, the necessary code is very longwinded, and it is tricky -to handle all the corner cases correctly. In this situation, the advantages -of a specialised syntax should be clear. +The rationale behind most of the semantics presented above stems from +the desire to be able to refactor generator code. It should be possible +to take an section of code containing one or more ``yield`` expressions, +move it into a separate function (using the usual techniques to deal +with references to variables in the surrounding scope, etc.), and +call the new function using a ``yield from`` expression. + +The behaviour of the resulting compound generator should be, as far as +possible, exactly the same as the original unfactored generator in all +situations, including calls to ``next()``, ``send()``, ``throw()`` and +``close()``. + +The semantics in cases of subiterators other than generators has been +chosen as a reasonable generalization of the generator case. + + +Finalization +------------ + +There was some debate as to whether explicitly finalizing the delegating +generator by calling its ``close()`` method while it is suspended at a +``yield from`` should also finalize the subiterator. An argument against +doing so is that it would result in premature finalization of the +subiterator if references to it exist elsewhere. + +Consideration of non-refcounting Python implementations led to the +decision that this explicit finalization should be performed, so that +explicitly closing a factored generator has the same effect as doing +so to an unfactored one in all Python implementations. + +The assumption made is that, in the majority of use cases, the subiterator +will not be shared. The rare case of a shared subiterator can be +accommodated by means of a wrapper that blocks ``throw()`` and ``send()`` +calls, or by using a means other than ``yield from`` to call the +subiterator. Generators as Threads --------------------- -A motivating use case for generators being able to return values -concerns the use of generators to implement lightweight threads. When -using generators in that way, it is reasonable to want to spread the +A motivation for generators being able to return values concerns the +use of generators to implement lightweight threads. When using +generators in that way, it is reasonable to want to spread the computation performed by the lightweight thread over many functions. -One would like to be able to call a subgenerator as though it were -an ordinary function, passing it parameters and receiving a returned +One would like to be able to call a subgenerator as though it were an +ordinary function, passing it parameters and receiving a returned value. Using the proposed syntax, a statement such as :: - y = f(x) + y = f(x) where f is an ordinary function, can be transformed into a delegation call :: - y = yield from g(x) + y = yield from g(x) where g is a generator. One can reason about the behaviour of the resulting code by thinking of g as an ordinary function that can be @@ -236,7 +314,8 @@ when there is a long chain of generators. Such chains can arise, for instance, when recursively traversing a tree structure. The overhead of passing ``next()`` calls and yielded values down and up the chain -can cause what ought to be an O(n) operation to become O(n\*\*2). +can cause what ought to be an O(n) operation to become, in the worst +case, O(n\*\*2). A possible strategy is to add a slot to generator objects to hold a generator being delegated to. When a ``next()`` or ``send()`` call is @@ -262,13 +341,13 @@ mechanism is attractive for a couple of reasons: * Using the StopIteration exception makes it easy for other kinds - of iterators to participate in the protocol without having to - grow extra attributes or a close() method. + of iterators to participate in the protocol without having to + grow an extra attribute or a close() method. * It simplifies the implementation, because the point at which the - return value from the subgenerator becomes available is the same - point at which StopIteration is raised. Delaying until any later - time would require storing the return value somewhere. + return value from the subgenerator becomes available is the same + point at which StopIteration is raised. Delaying until any later + time would require storing the return value somewhere. Criticisms @@ -316,18 +395,19 @@ To the author's knowledge, previous proposals have focused only on yielding values, and thereby suffered from the criticism that the two-line for-loop they replace is not sufficiently tiresome to write -to justify a new syntax. By also dealing with calls to ``send()``, -``throw()`` and ``close()``, this proposal provides considerably more -benefit. +to justify a new syntax. By dealing with the full generator +protocol, this proposal provides considerably more benefit. + +Additional Material +=================== -Implementation -============== +Some examples of the use of the proposed syntax are available, and also a +prototype implementation based on the first optimisation outlined above. -A `prototype implementation`_ is available, based on the first -optimisation outlined above. +`Examples and Implementation`_ -.. _prototype implementation: http://www.cosc.canterbury.ac.nz/greg.ewing/python/yield-from/ +.. _Examples and Implementation: http://www.cosc.canterbury.ac.nz/greg.ewing/python/yield-from/ Copyright From python-checkins at python.org Fri Mar 27 18:14:19 2009 From: python-checkins at python.org (jeremy.hylton) Date: Fri, 27 Mar 2009 18:14:19 +0100 (CET) Subject: [Python-checkins] r70633 - in python/branches/py3k/Lib/http: client.py server.py Message-ID: <20090327171419.4B1781E4002@bag.python.org> Author: jeremy.hylton Date: Fri Mar 27 18:14:18 2009 New Revision: 70633 Log: Replace duplicate code in http.server with call to http.client.parse_headers(). Modified: python/branches/py3k/Lib/http/client.py python/branches/py3k/Lib/http/server.py Modified: python/branches/py3k/Lib/http/client.py ============================================================================== --- python/branches/py3k/Lib/http/client.py (original) +++ python/branches/py3k/Lib/http/client.py Fri Mar 27 18:14:18 2009 @@ -237,8 +237,6 @@ to parse. """ - # XXX: Copied from http.server.BaseHTTPRequestHandler.parse_request, - # maybe we can just call this function from there. headers = [] while True: line = fp.readline() Modified: python/branches/py3k/Lib/http/server.py ============================================================================== --- python/branches/py3k/Lib/http/server.py (original) +++ python/branches/py3k/Lib/http/server.py Fri Mar 27 18:14:18 2009 @@ -88,6 +88,7 @@ import os import sys import cgi +import http.client import time import socket # For gethostbyaddr() import shutil @@ -312,20 +313,7 @@ self.command, self.path, self.request_version = command, path, version # Examine the headers and look for a Connection directive. - - # MessageClass wants to see strings rather than bytes. - # But a TextIOWrapper around self.rfile would buffer too many bytes - # from the stream, bytes which we later need to read as bytes. - # So we read the correct bytes here, as bytes, then use StringIO - # to make them look like strings for MessageClass to parse. - headers = [] - while True: - line = self.rfile.readline() - headers.append(line) - if line in (b'\r\n', b'\n', b''): - break - hfile = io.StringIO(b''.join(headers).decode('iso-8859-1')) - self.headers = email.parser.Parser(_class=self.MessageClass).parse(hfile) + self.headers = http.client.parse_headers(self.rfile) conntype = self.headers.get('Connection', "") if conntype.lower() == 'close': @@ -524,7 +512,6 @@ protocol_version = "HTTP/1.0" # MessageClass used to parse headers - import http.client MessageClass = http.client.HTTPMessage # Table mapping response codes to messages; entries have the From python-checkins at python.org Fri Mar 27 18:16:07 2009 From: python-checkins at python.org (jeremy.hylton) Date: Fri, 27 Mar 2009 18:16:07 +0100 (CET) Subject: [Python-checkins] r70634 - python/branches/py3k/Lib/http/server.py Message-ID: <20090327171607.16B4F1E4022@bag.python.org> Author: jeremy.hylton Date: Fri Mar 27 18:16:06 2009 New Revision: 70634 Log: Sort import list. Modified: python/branches/py3k/Lib/http/server.py Modified: python/branches/py3k/Lib/http/server.py ============================================================================== --- python/branches/py3k/Lib/http/server.py (original) +++ python/branches/py3k/Lib/http/server.py Fri Mar 27 18:16:06 2009 @@ -84,21 +84,21 @@ __all__ = ["HTTPServer", "BaseHTTPRequestHandler"] -import io -import os -import sys import cgi +import email.message +import email.parser import http.client -import time -import socket # For gethostbyaddr() -import shutil -import urllib.parse -import select +import io import mimetypes +import os import posixpath +import select +import shutil +import socket # For gethostbyaddr() import socketserver -import email.message -import email.parser +import sys +import time +import urllib.parse # Default error message template DEFAULT_ERROR_MESSAGE = """\ From buildbot at python.org Fri Mar 27 18:34:56 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Mar 2009 17:34:56 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090327173456.50B481E4037@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/560 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_xmlrpc ====================================================================== FAIL: test_fail_no_info (test.test_xmlrpc.FailingServerTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/test/test_xmlrpc.py", line 529, in test_fail_no_info self.fail('ProtocolError not raised') AssertionError: ProtocolError not raised ====================================================================== FAIL: test_fail_with_info (test.test_xmlrpc.FailingServerTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-ubuntu-i386/build/Lib/test/test_xmlrpc.py", line 550, in test_fail_with_info self.fail('ProtocolError not raised') AssertionError: ProtocolError not raised make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Fri Mar 27 18:39:24 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Mar 2009 17:39:24 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090327173925.62C7D1E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/462 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_xmlrpc ====================================================================== FAIL: test_fail_no_info (test.test_xmlrpc.FailingServerTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_xmlrpc.py", line 529, in test_fail_no_info self.fail('ProtocolError not raised') AssertionError: ProtocolError not raised ====================================================================== FAIL: test_fail_with_info (test.test_xmlrpc.FailingServerTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/3.x.norwitz-amd64/build/Lib/test/test_xmlrpc.py", line 550, in test_fail_with_info self.fail('ProtocolError not raised') AssertionError: ProtocolError not raised make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Fri Mar 27 18:44:29 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Mar 2009 17:44:29 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090327174429.3631A1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/521 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_xmlrpc ====================================================================== FAIL: test_fail_no_info (test.test_xmlrpc.FailingServerTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildbot/buildarea/3.x.heller-x86-osx5/build/Lib/test/test_xmlrpc.py", line 529, in test_fail_no_info self.fail('ProtocolError not raised') AssertionError: ProtocolError not raised ====================================================================== FAIL: test_fail_with_info (test.test_xmlrpc.FailingServerTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildbot/buildarea/3.x.heller-x86-osx5/build/Lib/test/test_xmlrpc.py", line 550, in test_fail_with_info self.fail('ProtocolError not raised') AssertionError: ProtocolError not raised make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Fri Mar 27 18:53:36 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Mar 2009 17:53:36 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090327175336.E07321E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/497 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_xmlrpc ====================================================================== FAIL: test_fail_no_info (test.test_xmlrpc.FailingServerTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ppc/build/Lib/test/test_xmlrpc.py", line 529, in test_fail_no_info self.fail('ProtocolError not raised') AssertionError: ProtocolError not raised ====================================================================== FAIL: test_fail_with_info (test.test_xmlrpc.FailingServerTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/3.x.klose-debian-ppc/build/Lib/test/test_xmlrpc.py", line 550, in test_fail_with_info self.fail('ProtocolError not raised') AssertionError: ProtocolError not raised make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Fri Mar 27 19:31:37 2009 From: python-checkins at python.org (jeremy.hylton) Date: Fri, 27 Mar 2009 19:31:37 +0100 (CET) Subject: [Python-checkins] r70635 - in python/branches/py3k/Lib/http: client.py server.py Message-ID: <20090327183137.3A94A1E4002@bag.python.org> Author: jeremy.hylton Date: Fri Mar 27 19:31:36 2009 New Revision: 70635 Log: Fix compatibility issue with HTTPMessage class. The server needs to use MessageClass to parse. Modified: python/branches/py3k/Lib/http/client.py python/branches/py3k/Lib/http/server.py Modified: python/branches/py3k/Lib/http/client.py ============================================================================== --- python/branches/py3k/Lib/http/client.py (original) +++ python/branches/py3k/Lib/http/client.py Fri Mar 27 19:31:36 2009 @@ -213,7 +213,6 @@ occurrences are returned. Case is not important in the header name. """ - # XXX: copied from rfc822.Message for compatibility name = name.lower() + ':' n = len(name) lst = [] @@ -227,7 +226,7 @@ lst.append(line) return lst -def parse_headers(fp): +def parse_headers(fp, _class=HTTPMessage): """Parses only RFC2822 headers from a file pointer. email Parser wants to see strings rather than bytes. @@ -245,7 +244,7 @@ break hstring = b''.join(headers).decode('iso-8859-1') - return email.parser.Parser(_class=HTTPMessage).parsestr(hstring) + return email.parser.Parser(_class=_class).parsestr(hstring) class HTTPResponse(io.RawIOBase): Modified: python/branches/py3k/Lib/http/server.py ============================================================================== --- python/branches/py3k/Lib/http/server.py (original) +++ python/branches/py3k/Lib/http/server.py Fri Mar 27 19:31:36 2009 @@ -313,7 +313,8 @@ self.command, self.path, self.request_version = command, path, version # Examine the headers and look for a Connection directive. - self.headers = http.client.parse_headers(self.rfile) + self.headers = http.client.parse_headers(self.rfile, + _class=self.MessageClass) conntype = self.headers.get('Connection', "") if conntype.lower() == 'close': From buildbot at python.org Fri Mar 27 20:01:07 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Mar 2009 19:01:07 +0000 Subject: [Python-checkins] buildbot failure in x86 XP-4 3.x Message-ID: <20090327190108.DFBA11E4002@bag.python.org> The Buildbot has detected a new failure of x86 XP-4 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20XP-4%203.x/builds/389 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: bolen-windows Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed compile sincerely, -The Buildbot From python-checkins at python.org Fri Mar 27 20:19:32 2009 From: python-checkins at python.org (jim.fulton) Date: Fri, 27 Mar 2009 20:19:32 +0100 (CET) Subject: [Python-checkins] r70636 - peps/branches/jim-update-345 Message-ID: <20090327191932.821B01E4002@bag.python.org> Author: jim.fulton Date: Fri Mar 27 20:19:28 2009 New Revision: 70636 Log: Update meta data reflecting work in setuptools Added: peps/branches/jim-update-345/ - copied from r70635, /peps/trunk/ From python-checkins at python.org Fri Mar 27 20:33:34 2009 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 27 Mar 2009 20:33:34 +0100 (CET) Subject: [Python-checkins] r70637 - peps/trunk/pep-0380.txt Message-ID: <20090327193334.18D561E4034@bag.python.org> Author: guido.van.rossum Date: Fri Mar 27 20:33:33 2009 New Revision: 70637 Log: New version from Greg. Modified: peps/trunk/pep-0380.txt Modified: peps/trunk/pep-0380.txt ============================================================================== --- peps/trunk/pep-0380.txt (original) +++ peps/trunk/pep-0380.txt Fri Mar 27 20:33:33 2009 @@ -40,8 +40,8 @@ :: - for v in g: - yield v + for v in g: + yield v However, if the subgenerator is to interact properly with the caller in the case of calls to ``send()``, ``throw()`` and ``close()``, things @@ -63,7 +63,7 @@ :: - yield from + yield from where is an expression evaluating to an iterable, from which an iterator is extracted. The iterator is run to exhaustion, during which @@ -78,30 +78,30 @@ In general, the semantics can be described in terms of the iterator protocol as follows: - * Any values that the iterator yields are passed directly to the - caller. + * Any values that the iterator yields are passed directly to the + caller. - * Any values sent to the delegating generator using ``send()`` - are passed directly to the iterator. If the sent value is None, - the iterator's ``next()`` method is called. If the sent value is - not None, the iterator's ``send()`` method is called. Any exception - resulting from attempting to call ``next`` or ``send`` is raised - in the delegating generator. - - * Exceptions passed to the ``throw()`` method of the delegating - generator are forwarded to the ``throw()`` method of the iterator. - If the iterator does not have a ``throw()`` method, its ``close()`` - method is called if it has one, then the thrown-in exception is - raised in the delegating generator. Any exception resulting from - attempting to call these methods (apart from one case noted below) - is raised in the delegating generator. - - * The value of the ``yield from`` expression is the first argument - to the ``StopIteration`` exception raised by the iterator when it - terminates. + * Any values sent to the delegating generator using ``send()`` + are passed directly to the iterator. If the sent value is None, + the iterator's ``next()`` method is called. If the sent value is + not None, the iterator's ``send()`` method is called. Any exception + resulting from attempting to call ``next`` or ``send`` is raised + in the delegating generator. + + * Exceptions passed to the ``throw()`` method of the delegating + generator are forwarded to the ``throw()`` method of the iterator. + If the iterator does not have a ``throw()`` method, its ``close()`` + method is called if it has one, then the thrown-in exception is + raised in the delegating generator. Any exception resulting from + attempting to call these methods (apart from one case noted below) + is raised in the delegating generator. + + * The value of the ``yield from`` expression is the first argument + to the ``StopIteration`` exception raised by the iterator when it + terminates. - * ``return expr`` in a generator causes ``StopIteration(expr)`` to - be raised. + * ``return expr`` in a generator causes ``StopIteration(expr)`` to + be raised. Fine Details @@ -113,8 +113,9 @@ this as a request to finalize itself. If a call to the iterator's ``throw()`` method raises a StopIteration -exception, and it is *not* the same exception object that was thrown -in, its value is returned as the value of the ``yield from`` expression +exception, and it is *not* the same exception object that was thrown in, +and the original exception was not GeneratorExit, then the value of the +new exception is returned as the value of the ``yield from`` expression and the delegating generator is resumed. @@ -133,51 +134,48 @@ :: - RESULT = yield from EXPR + RESULT = yield from EXPR is semantically equivalent to :: - _i = iter(EXPR) - try: - try: - _y = _i.next() - except StopIteration, _e: - _r = _e.value - else: - while 1: - try: - _s = yield _y - except: - _m = getattr(_i, 'throw', None) - if _m is not None: - _x = sys.exc_info() - try: - _y = _m(*_x) - except StopIteration, _e: - if _e is _x[1]: - raise - else: - _r = _e.value - break - else: - _m = getattr(_i, 'close', None) - if _m is not None: - _m() - raise - else: - try: - if _s is None: - _y = _i.next() - else: - _y = _i.send(_s) - except StopIteration, _e: - _r = _e.value - break - finally: - del _i - RESULT = _r + _i = iter(EXPR) + try: + _y = _i.next() + except StopIteration, _e: + _r = _e.value + else: + while 1: + try: + _s = yield _y + except: + _m = getattr(_i, 'throw', None) + if _m is not None: + _x = sys.exc_info() + try: + _y = _m(*_x) + except StopIteration, _e: + if _e is _x[1] or isinstance(_x[1], GeneratorExit): + raise + else: + _r = _e.value + break + else: + _m = getattr(_i, 'close', None) + if _m is not None: + _m() + raise + else: + try: + if _s is None: + _y = _i.next() + else: + _y = _i.send(_s) + except StopIteration, _e: + _r = _e.value + break + RESULT = _r except that implementations are free to cache bound methods for the 'next', 'send' and 'throw' methods of the iterator upon first use. @@ -186,13 +184,13 @@ :: - return value + return value is semantically equivalent to :: - raise StopIteration(value) + raise StopIteration(value) except that, as currently, the exception cannot be caught by ``except`` clauses within the returning generator. @@ -201,14 +199,14 @@ :: - class StopIteration(Exception): + class StopIteration(Exception): - def __init__(self, *args): - if len(args) > 0: - self.value = args[0] - else: - self.value = None - Exception.__init__(self, *args) + def __init__(self, *args): + if len(args) > 0: + self.value = args[0] + else: + self.value = None + Exception.__init__(self, *args) Rationale @@ -249,7 +247,7 @@ The assumption made is that, in the majority of use cases, the subiterator will not be shared. The rare case of a shared subiterator can be -accommodated by means of a wrapper that blocks ``throw()`` and ``send()`` +accommodated by means of a wrapper that blocks ``throw()`` and ``close()`` calls, or by using a means other than ``yield from`` to call the subiterator. @@ -269,14 +267,14 @@ :: - y = f(x) + y = f(x) where f is an ordinary function, can be transformed into a delegation call :: - y = yield from g(x) + y = yield from g(x) where g is a generator. One can reason about the behaviour of the resulting code by thinking of g as an ordinary function that can be @@ -341,13 +339,13 @@ mechanism is attractive for a couple of reasons: * Using the StopIteration exception makes it easy for other kinds - of iterators to participate in the protocol without having to - grow an extra attribute or a close() method. + of iterators to participate in the protocol without having to + grow an extra attribute or a close() method. * It simplifies the implementation, because the point at which the - return value from the subgenerator becomes available is the same - point at which StopIteration is raised. Delaying until any later - time would require storing the return value somewhere. + return value from the subgenerator becomes available is the same + point at which StopIteration is raised. Delaying until any later + time would require storing the return value somewhere. Criticisms From python-checkins at python.org Fri Mar 27 21:24:35 2009 From: python-checkins at python.org (jeremy.hylton) Date: Fri, 27 Mar 2009 21:24:35 +0100 (CET) Subject: [Python-checkins] r70638 - in python/branches/py3k: Doc/library/http.client.rst Lib/http/client.py Lib/test/test_httplib.py Message-ID: <20090327202435.27D871E4002@bag.python.org> Author: jeremy.hylton Date: Fri Mar 27 21:24:34 2009 New Revision: 70638 Log: Fix some string encoding issues with entity bodies in HTTP requests. RFC 2616 says that iso-8859-1 is the default charset for HTTP entity bodies, but we encoded strings using ascii. See http://bugs.python.org/issue5314. Changed docs and code to use iso-8859-1. Also fix some brokenness with passing a file as the body instead of a string. Add tests to show that some of this behavior actually works. Modified: python/branches/py3k/Doc/library/http.client.rst python/branches/py3k/Lib/http/client.py python/branches/py3k/Lib/test/test_httplib.py Modified: python/branches/py3k/Doc/library/http.client.rst ============================================================================== --- python/branches/py3k/Doc/library/http.client.rst (original) +++ python/branches/py3k/Doc/library/http.client.rst Fri Mar 27 21:24:34 2009 @@ -351,14 +351,22 @@ .. method:: HTTPConnection.request(method, url[, body[, headers]]) - This will send a request to the server using the HTTP request method *method* - and the selector *url*. If the *body* argument is present, it should be a - string of data to send after the headers are finished. Alternatively, it may - be an open file object, in which case the contents of the file is sent; this - file object should support ``fileno()`` and ``read()`` methods. The header - Content-Length is automatically set to the correct value. The *headers* - argument should be a mapping of extra HTTP headers to send with the request. + This will send a request to the server using the HTTP request + method *method* and the selector *url*. If the *body* argument is + present, it should be string or bytes object of data to send after + the headers are finished. Strings are encoded as ISO-8859-1, the + default charset for HTTP. To use other encodings, pass a bytes + object. The Content-Length header is set to the length of the + string. + + The *body* may also be an open file object, in which case the + contents of the file is sent; this file object should support + ``fileno()`` and ``read()`` methods. The header Content-Length is + automatically set to the length of the file as reported by + stat. + The *headers* argument should be a mapping of extra HTTP + headers to send with the request. .. method:: HTTPConnection.getresponse() Modified: python/branches/py3k/Lib/http/client.py ============================================================================== --- python/branches/py3k/Lib/http/client.py (original) +++ python/branches/py3k/Lib/http/client.py Fri Mar 27 21:24:34 2009 @@ -243,7 +243,6 @@ if line in (b'\r\n', b'\n', b''): break hstring = b''.join(headers).decode('iso-8859-1') - return email.parser.Parser(_class=_class).parsestr(hstring) class HTTPResponse(io.RawIOBase): @@ -675,13 +674,22 @@ if self.debuglevel > 0: print("send:", repr(str)) try: - blocksize=8192 - if hasattr(str,'read') : - if self.debuglevel > 0: print("sendIng a read()able") - data=str.read(blocksize) - while data: + blocksize = 8192 + if hasattr(str, "read") : + if self.debuglevel > 0: + print("sendIng a read()able") + encode = False + if "b" not in str.mode: + encode = True + if self.debuglevel > 0: + print("encoding file using iso-8859-1") + while 1: + data = str.read(blocksize) + if not data: + break + if encode: + data = data.encode("iso-8859-1") self.sock.sendall(data) - data=str.read(blocksize) else: self.sock.sendall(str) except socket.error as v: @@ -713,8 +721,8 @@ message_body = None self.send(msg) if message_body is not None: - #message_body was not a string (i.e. it is a file) and - #we must run the risk of Nagle + # message_body was not a string (i.e. it is a file), and + # we must run the risk of Nagle. self.send(message_body) def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0): @@ -904,7 +912,9 @@ for hdr, value in headers.items(): self.putheader(hdr, value) if isinstance(body, str): - body = body.encode('ascii') + # RFC 2616 Section 3.7.1 says that text default has a + # default charset of iso-8859-1. + body = body.encode('iso-8859-1') self.endheaders(body) def getresponse(self): Modified: python/branches/py3k/Lib/test/test_httplib.py ============================================================================== --- python/branches/py3k/Lib/test/test_httplib.py (original) +++ python/branches/py3k/Lib/test/test_httplib.py Fri Mar 27 21:24:34 2009 @@ -272,9 +272,80 @@ h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30) self.assertEqual(h.timeout, 30) +class RequestBodyTest(TestCase): + """Test cases where a request includes a message body.""" + + def setUp(self): + self.conn = httplib.HTTPConnection('example.com') + self.sock = FakeSocket("") + self.conn.sock = self.sock + + def get_headers_and_fp(self): + f = io.BytesIO(self.sock.data) + f.readline() # read the request line + message = httplib.parse_headers(f) + return message, f + + def test_manual_content_length(self): + # Set an incorrect content-length so that we can verify that + # it will not be over-ridden by the library. + self.conn.request("PUT", "/url", "body", + {"Content-Length": "42"}) + message, f = self.get_headers_and_fp() + self.assertEqual("42", message.get("content-length")) + self.assertEqual(4, len(f.read())) + + def test_ascii_body(self): + self.conn.request("PUT", "/url", "body") + message, f = self.get_headers_and_fp() + self.assertEqual("text/plain", message.get_content_type()) + self.assertEqual(None, message.get_charset()) + self.assertEqual("4", message.get("content-length")) + self.assertEqual(b'body', f.read()) + + def test_latin1_body(self): + self.conn.request("PUT", "/url", "body\xc1") + message, f = self.get_headers_and_fp() + self.assertEqual("text/plain", message.get_content_type()) + self.assertEqual(None, message.get_charset()) + self.assertEqual("5", message.get("content-length")) + self.assertEqual(b'body\xc1', f.read()) + + def test_bytes_body(self): + self.conn.request("PUT", "/url", b"body\xc1") + message, f = self.get_headers_and_fp() + self.assertEqual("text/plain", message.get_content_type()) + self.assertEqual(None, message.get_charset()) + self.assertEqual("5", message.get("content-length")) + self.assertEqual(b'body\xc1', f.read()) + + def test_file_body(self): + f = open(support.TESTFN, "w") + f.write("body") + f.close() + f = open(support.TESTFN) + self.conn.request("PUT", "/url", f) + message, f = self.get_headers_and_fp() + self.assertEqual("text/plain", message.get_content_type()) + self.assertEqual(None, message.get_charset()) + self.assertEqual("4", message.get("content-length")) + self.assertEqual(b'body', f.read()) + + def test_binary_file_body(self): + f = open(support.TESTFN, "wb") + f.write(b"body\xc1") + f.close() + f = open(support.TESTFN, "rb") + self.conn.request("PUT", "/url", f) + message, f = self.get_headers_and_fp() + self.assertEqual("text/plain", message.get_content_type()) + self.assertEqual(None, message.get_charset()) + self.assertEqual("5", message.get("content-length")) + self.assertEqual(b'body\xc1', f.read()) + def test_main(verbose=None): support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest, - HTTPSTimeoutTest) + HTTPSTimeoutTest, RequestBodyTest) if __name__ == '__main__': test_main() From python-checkins at python.org Fri Mar 27 22:24:45 2009 From: python-checkins at python.org (jeremy.hylton) Date: Fri, 27 Mar 2009 22:24:45 +0100 (CET) Subject: [Python-checkins] r70639 - python/branches/py3k/Makefile.pre.in Message-ID: <20090327212445.628621E402B@bag.python.org> Author: jeremy.hylton Date: Fri Mar 27 22:24:45 2009 New Revision: 70639 Log: Update the tests skipped with quicktest target. Some tests that used to be slow are now fast, and there are brand new slow tests. Modified: python/branches/py3k/Makefile.pre.in Modified: python/branches/py3k/Makefile.pre.in ============================================================================== --- python/branches/py3k/Makefile.pre.in (original) +++ python/branches/py3k/Makefile.pre.in Fri Mar 27 22:24:45 2009 @@ -727,9 +727,10 @@ fi $(TESTPYTHON) $(TESTPROG) $(TESTOPTS) -uall -rw -QUICKTESTOPTS= $(TESTOPTS) -x test_thread test_signal test_strftime \ - test_unicodedata test_re test_sre test_select test_poll \ - test_struct test_zlib +QUICKTESTOPTS= $(TESTOPTS) -x test_subprocess test_io test_lib2to3 \ + test_multibytecodec test_urllib2_localnet test_itertools \ + test_multiprocessing test_mailbox test_socket test_poll \ + test_select test_zipfile quicktest: all platform -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f -$(TESTPYTHON) $(TESTPROG) $(QUICKTESTOPTS) From python-checkins at python.org Fri Mar 27 22:31:04 2009 From: python-checkins at python.org (jeremy.hylton) Date: Fri, 27 Mar 2009 22:31:04 +0100 (CET) Subject: [Python-checkins] r70640 - python/branches/py3k/Lib/test/test_httplib.py Message-ID: <20090327213104.28E7D1E4002@bag.python.org> Author: jeremy.hylton Date: Fri Mar 27 22:31:03 2009 New Revision: 70640 Log: Replace references to httplib with http.client. Modified: python/branches/py3k/Lib/test/test_httplib.py Modified: python/branches/py3k/Lib/test/test_httplib.py ============================================================================== --- python/branches/py3k/Lib/test/test_httplib.py (original) +++ python/branches/py3k/Lib/test/test_httplib.py Fri Mar 27 22:31:03 2009 @@ -1,4 +1,4 @@ -import http.client as httplib +from http import client import io import socket @@ -21,13 +21,13 @@ def makefile(self, mode, bufsize=None): if mode != 'r' and mode != 'rb': - raise httplib.UnimplementedFileMode() + raise client.UnimplementedFileMode() return self.fileclass(self.text) class NoEOFStringIO(io.BytesIO): """Like StringIO, but raises AssertionError on EOF. - This is used below to test that httplib doesn't try to read + This is used below to test that http.client doesn't try to read more from the underlying file than it should. """ def read(self, n=-1): @@ -61,7 +61,7 @@ for explicit_header in True, False: for header in 'Content-length', 'Host', 'Accept-encoding': - conn = httplib.HTTPConnection('example.com') + conn = client.HTTPConnection('example.com') conn.sock = FakeSocket('blahblahblah') conn._buffer = HeaderCountingBuffer() @@ -78,22 +78,22 @@ body = "HTTP/1.1 200 Ok\r\n\r\nText" sock = FakeSocket(body) - resp = httplib.HTTPResponse(sock) + resp = client.HTTPResponse(sock) resp.begin() self.assertEqual(resp.read(), b"Text") self.assertTrue(resp.isclosed()) body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText" sock = FakeSocket(body) - resp = httplib.HTTPResponse(sock) - self.assertRaises(httplib.BadStatusLine, resp.begin) + resp = client.HTTPResponse(sock) + self.assertRaises(client.BadStatusLine, resp.begin) def test_partial_reads(self): # if we have a lenght, the system knows when to close itself # same behaviour than when we read the whole thing with read() body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText" sock = FakeSocket(body) - resp = httplib.HTTPResponse(sock) + resp = client.HTTPResponse(sock) resp.begin() self.assertEqual(resp.read(2), b'Te') self.assertFalse(resp.isclosed()) @@ -104,14 +104,14 @@ # Check invalid host_port for hp in ("www.python.org:abc", "www.python.org:"): - self.assertRaises(httplib.InvalidURL, httplib.HTTPConnection, hp) + self.assertRaises(client.InvalidURL, client.HTTPConnection, hp) for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b", 8000), ("www.python.org:80", "www.python.org", 80), ("www.python.org", "www.python.org", 80), ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)): - c = httplib.HTTPConnection(hp) + c = client.HTTPConnection(hp) self.assertEqual(h, c.host) self.assertEqual(p, c.port) @@ -128,7 +128,7 @@ ', ' 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"') s = FakeSocket(text) - r = httplib.HTTPResponse(s) + r = client.HTTPResponse(s) r.begin() cookies = r.getheader("Set-Cookie") self.assertEqual(cookies, hdr) @@ -141,7 +141,7 @@ 'Content-Length: 14432\r\n' '\r\n', NoEOFStringIO) - resp = httplib.HTTPResponse(sock, method="HEAD") + resp = client.HTTPResponse(sock, method="HEAD") resp.begin() if resp.read(): self.fail("Did not expect response from HEAD request") @@ -151,7 +151,7 @@ b'Accept-Encoding: identity\r\nContent-Length:') body = open(__file__, 'rb') - conn = httplib.HTTPConnection('example.com') + conn = client.HTTPConnection('example.com') sock = FakeSocket(body) conn.sock = sock conn.request('GET', '/foo', body) @@ -168,18 +168,18 @@ 'd\r\n' ) sock = FakeSocket(chunked_start + '0\r\n') - resp = httplib.HTTPResponse(sock, method="GET") + resp = client.HTTPResponse(sock, method="GET") resp.begin() self.assertEquals(resp.read(), b'hello world') resp.close() for x in ('', 'foo\r\n'): sock = FakeSocket(chunked_start + x) - resp = httplib.HTTPResponse(sock, method="GET") + resp = client.HTTPResponse(sock, method="GET") resp.begin() try: resp.read() - except httplib.IncompleteRead as i: + except client.IncompleteRead as i: self.assertEquals(i.partial, b'hello world') self.assertEqual(repr(i),'IncompleteRead(11 bytes read)') self.assertEqual(str(i),'IncompleteRead(11 bytes read)') @@ -191,18 +191,18 @@ def test_negative_content_length(self): sock = FakeSocket( 'HTTP/1.1 200 OK\r\nContent-Length: -1\r\n\r\nHello\r\n') - resp = httplib.HTTPResponse(sock, method="GET") + resp = client.HTTPResponse(sock, method="GET") resp.begin() self.assertEquals(resp.read(), b'Hello\r\n') resp.close() def test_incomplete_read(self): sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n') - resp = httplib.HTTPResponse(sock, method="GET") + resp = client.HTTPResponse(sock, method="GET") resp.begin() try: resp.read() - except httplib.IncompleteRead as i: + except client.IncompleteRead as i: self.assertEquals(i.partial, b'Hello\r\n') self.assertEqual(repr(i), "IncompleteRead(7 bytes read, 3 more expected)") @@ -216,7 +216,7 @@ class OfflineTest(TestCase): def test_responses(self): - self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found") + self.assertEquals(client.responses[client.NOT_FOUND], "Not Found") class TimeoutTest(TestCase): PORT = None @@ -238,7 +238,7 @@ self.assert_(socket.getdefaulttimeout() is None) socket.setdefaulttimeout(30) try: - httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT) + httpConn = client.HTTPConnection(HOST, TimeoutTest.PORT) httpConn.connect() finally: socket.setdefaulttimeout(None) @@ -249,7 +249,7 @@ self.assert_(socket.getdefaulttimeout() is None) socket.setdefaulttimeout(30) try: - httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, + httpConn = client.HTTPConnection(HOST, TimeoutTest.PORT, timeout=None) httpConn.connect() finally: @@ -258,7 +258,7 @@ httpConn.close() # a value - httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30) + httpConn = client.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30) httpConn.connect() self.assertEqual(httpConn.sock.gettimeout(), 30) httpConn.close() @@ -268,22 +268,22 @@ def test_attributes(self): # simple test to check it's storing it - if hasattr(httplib, 'HTTPSConnection'): - h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30) + if hasattr(client, 'HTTPSConnection'): + h = client.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30) self.assertEqual(h.timeout, 30) class RequestBodyTest(TestCase): """Test cases where a request includes a message body.""" def setUp(self): - self.conn = httplib.HTTPConnection('example.com') + self.conn = client.HTTPConnection('example.com') self.sock = FakeSocket("") self.conn.sock = self.sock def get_headers_and_fp(self): f = io.BytesIO(self.sock.data) f.readline() # read the request line - message = httplib.parse_headers(f) + message = client.parse_headers(f) return message, f def test_manual_content_length(self): From python-checkins at python.org Fri Mar 27 22:43:09 2009 From: python-checkins at python.org (guilherme.polo) Date: Fri, 27 Mar 2009 22:43:09 +0100 (CET) Subject: [Python-checkins] r70641 - in python/trunk: Misc/NEWS Modules/_tkinter.c Message-ID: <20090327214309.0D4921E4002@bag.python.org> Author: guilherme.polo Date: Fri Mar 27 22:43:08 2009 New Revision: 70641 Log: Adjusted _tkinter to compile without warnings when WITH_THREAD is not defined (part of issue #5035) Modified: python/trunk/Misc/NEWS python/trunk/Modules/_tkinter.c Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Fri Mar 27 22:43:08 2009 @@ -197,6 +197,9 @@ Library ------- +- Adjusted _tkinter to compile without warnings when WITH_THREAD is not + defined (part of issue #5035). + - Issue #5561: Removed the sys.version_info shortcuts from platform's python_version() and python_version_tuple() since they produced different output compared to previous Python versions. Modified: python/trunk/Modules/_tkinter.c ============================================================================== --- python/trunk/Modules/_tkinter.c (original) +++ python/trunk/Modules/_tkinter.c Fri Mar 27 22:43:08 2009 @@ -734,6 +734,7 @@ } +#ifdef WITH_THREAD static void Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev, Tcl_Condition *cond, Tcl_Mutex *mutex) @@ -746,6 +747,7 @@ Tcl_MutexUnlock(mutex); Py_END_ALLOW_THREADS } +#endif /** Tcl Eval **/ @@ -1135,8 +1137,8 @@ return newPyTclObject(value); } +#ifdef WITH_THREAD /* This mutex synchronizes inter-thread command calls. */ - TCL_DECLARE_MUTEX(call_mutex) typedef struct Tkapp_CallEvent { @@ -1148,6 +1150,7 @@ PyObject **exc_type, **exc_value, **exc_tb; Tcl_Condition *done; } Tkapp_CallEvent; +#endif void Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc) @@ -1258,6 +1261,8 @@ return res; } +#ifdef WITH_THREAD + /* Tkapp_CallProc is the event procedure that is executed in the context of the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't hold the Python lock. */ @@ -1302,6 +1307,8 @@ return 1; } +#endif + /* This is the main entry point for calling a Tcl command. It supports three cases, with regard to threading: 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in @@ -1531,9 +1538,11 @@ /** Tcl Variable **/ +typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags); + +#ifdef WITH_THREAD TCL_DECLARE_MUTEX(var_mutex) -typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags); typedef struct VarEvent { Tcl_Event ev; /* must be first */ PyObject *self; @@ -1545,6 +1554,7 @@ PyObject **exc_val; Tcl_Condition *cond; } VarEvent; +#endif static int varname_converter(PyObject *in, void *_out) @@ -1562,6 +1572,8 @@ return 0; } +#ifdef WITH_THREAD + static void var_perform(VarEvent *ev) { @@ -1589,11 +1601,13 @@ return 1; } +#endif + static PyObject* var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags) { - TkappObject *self = (TkappObject*)selfptr; #ifdef WITH_THREAD + TkappObject *self = (TkappObject*)selfptr; if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { TkappObject *self = (TkappObject*)selfptr; VarEvent *ev; @@ -2096,6 +2110,7 @@ +#ifdef WITH_THREAD TCL_DECLARE_MUTEX(command_mutex) typedef struct CommandEvent{ @@ -2122,6 +2137,7 @@ Tcl_MutexUnlock(&command_mutex); return 1; } +#endif static PyObject * Tkapp_CreateCommand(PyObject *selfptr, PyObject *args) @@ -2152,7 +2168,8 @@ Py_INCREF(func); data->self = selfptr; data->func = func; - + +#ifdef WITH_THREAD if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { Tcl_Condition cond = NULL; CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent)); @@ -2166,7 +2183,9 @@ Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex); Tcl_ConditionFinalize(&cond); } - else { + else +#endif + { ENTER_TCL err = Tcl_CreateCommand( Tkapp_Interp(self), cmdName, PythonCmd, @@ -2194,6 +2213,8 @@ if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName)) return NULL; + +#ifdef WITH_THREAD if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { Tcl_Condition cond = NULL; CommandEvent *ev; @@ -2208,7 +2229,9 @@ &command_mutex); Tcl_ConditionFinalize(&cond); } - else { + else +#endif + { ENTER_TCL err = Tcl_DeleteCommand(self->interp, cmdName); LEAVE_TCL From buildbot at python.org Fri Mar 27 23:21:35 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Mar 2009 22:21:35 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090327222135.475151E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/524 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Fri Mar 27 23:27:28 2009 From: buildbot at python.org (buildbot at python.org) Date: Fri, 27 Mar 2009 22:27:28 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090327222728.B075D1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/781 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: guilherme.polo BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Abort trap sincerely, -The Buildbot From python-checkins at python.org Sat Mar 28 01:48:48 2009 From: python-checkins at python.org (georg.brandl) Date: Sat, 28 Mar 2009 01:48:48 +0100 (CET) Subject: [Python-checkins] r70642 - python/trunk/Lib/distutils/version.py Message-ID: <20090328004848.DAABF1E4002@bag.python.org> Author: georg.brandl Date: Sat Mar 28 01:48:48 2009 New Revision: 70642 Log: Fix typo. Modified: python/trunk/Lib/distutils/version.py Modified: python/trunk/Lib/distutils/version.py ============================================================================== --- python/trunk/Lib/distutils/version.py (original) +++ python/trunk/Lib/distutils/version.py Sat Mar 28 01:48:48 2009 @@ -162,7 +162,7 @@ # The rules according to Greg Stein: -# 1) a version number has 1 or more numbers separate by a period or by +# 1) a version number has 1 or more numbers separated by a period or by # sequences of letters. If only periods, then these are compared # left-to-right to determine an ordering. # 2) sequences of letters are part of the tuple for comparison and are From python-checkins at python.org Sat Mar 28 05:34:21 2009 From: python-checkins at python.org (jeremy.hylton) Date: Sat, 28 Mar 2009 05:34:21 +0100 (CET) Subject: [Python-checkins] r70643 - in python/branches/py3k/Lib: http/client.py test/test_httplib.py Message-ID: <20090328043421.CAD671E4002@bag.python.org> Author: jeremy.hylton Date: Sat Mar 28 05:34:21 2009 New Revision: 70643 Log: Remove special logic that closes HTTPConnection socket on EPIPE. http://bugs.python.org/issue5542 If the socket is closed, the client has no chance to read the response from the server. EPIPE means that it isn't possible to write more data from the socket, but not that it is impossible to read. Also, various formatting changes. Modified: python/branches/py3k/Lib/http/client.py python/branches/py3k/Lib/test/test_httplib.py Modified: python/branches/py3k/Lib/http/client.py ============================================================================== --- python/branches/py3k/Lib/http/client.py (original) +++ python/branches/py3k/Lib/http/client.py Sat Mar 28 05:34:21 2009 @@ -66,10 +66,11 @@ Req-sent-unread-response _CS_REQ_SENT """ -import io -import socket import email.parser import email.message +import io +import os +import socket from urllib.parse import urlsplit import warnings @@ -673,29 +674,24 @@ # ignore the error... the caller will know if they can retry. if self.debuglevel > 0: print("send:", repr(str)) - try: - blocksize = 8192 - if hasattr(str, "read") : + blocksize = 8192 + if hasattr(str, "read") : + if self.debuglevel > 0: + print("sendIng a read()able") + encode = False + if "b" not in str.mode: + encode = True if self.debuglevel > 0: - print("sendIng a read()able") - encode = False - if "b" not in str.mode: - encode = True - if self.debuglevel > 0: - print("encoding file using iso-8859-1") - while 1: - data = str.read(blocksize) - if not data: - break - if encode: - data = data.encode("iso-8859-1") - self.sock.sendall(data) - else: - self.sock.sendall(str) - except socket.error as v: - if v.args[0] == 32: # Broken pipe - self.close() - raise + print("encoding file using iso-8859-1") + while 1: + data = str.read(blocksize) + if not data: + break + if encode: + data = data.encode("iso-8859-1") + self.sock.sendall(data) + else: + self.sock.sendall(str) def _output(self, s): """Add a line of output to the current request buffer. @@ -869,14 +865,7 @@ def request(self, method, url, body=None, headers={}): """Send a complete request to the server.""" - try: - self._send_request(method, url, body, headers) - except socket.error as v: - # trap 'Broken pipe' if we're allowed to automatically reconnect - if v.args[0] != 32 or not self.auto_open: - raise - # try one more time - self._send_request(method, url, body, headers) + self._send_request(method, url, body, headers) def _set_content_length(self, body): # Set the content-length based on the body. @@ -886,7 +875,6 @@ except TypeError as te: # If this is a file-like object, try to # fstat its file descriptor - import os try: thelen = str(os.fstat(body.fileno()).st_size) except (AttributeError, OSError): @@ -897,7 +885,7 @@ self.putheader('Content-Length', thelen) def _send_request(self, method, url, body, headers): - # honour explicitly requested Host: and Accept-Encoding headers + # Honor explicitly requested Host: and Accept-Encoding: headers. header_names = dict.fromkeys([k.lower() for k in headers]) skips = {} if 'host' in header_names: @@ -983,7 +971,8 @@ def connect(self): "Connect to a host on a given (SSL) port." - sock = socket.create_connection((self.host, self.port), self.timeout) + sock = socket.create_connection((self.host, self.port), + self.timeout) self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file) Modified: python/branches/py3k/Lib/test/test_httplib.py ============================================================================== --- python/branches/py3k/Lib/test/test_httplib.py (original) +++ python/branches/py3k/Lib/test/test_httplib.py Sat Mar 28 05:34:21 2009 @@ -1,3 +1,4 @@ +import errno from http import client import io import socket @@ -24,6 +25,21 @@ raise client.UnimplementedFileMode() return self.fileclass(self.text) +class EPipeSocket(FakeSocket): + + def __init__(self, text, pipe_trigger): + # When sendall() is called with pipe_trigger, raise EPIPE. + FakeSocket.__init__(self, text) + self.pipe_trigger = pipe_trigger + + def sendall(self, data): + if self.pipe_trigger in data: + raise socket.error(errno.EPIPE, "gotcha") + self.data += data + + def close(self): + pass + class NoEOFStringIO(io.BytesIO): """Like StringIO, but raises AssertionError on EOF. @@ -213,6 +229,20 @@ finally: resp.close() + def test_epipe(self): + sock = EPipeSocket( + "HTTP/1.0 401 Authorization Required\r\n" + "Content-type: text/html\r\n" + "WWW-Authenticate: Basic realm=\"example\"\r\n", + b"Content-Length") + conn = client.HTTPConnection("example.com") + conn.sock = sock + self.assertRaises(socket.error, + lambda: conn.request("PUT", "/url", "body")) + resp = conn.getresponse() + self.assertEqual(401, resp.status) + self.assertEqual("Basic realm=\"example\"", + resp.getheader("www-authenticate")) class OfflineTest(TestCase): def test_responses(self): @@ -277,7 +307,7 @@ def setUp(self): self.conn = client.HTTPConnection('example.com') - self.sock = FakeSocket("") + self.conn.sock = self.sock = FakeSocket("") self.conn.sock = self.sock def get_headers_and_fp(self): From python-checkins at python.org Sat Mar 28 19:49:24 2009 From: python-checkins at python.org (tarek.ziade) Date: Sat, 28 Mar 2009 19:49:24 +0100 (CET) Subject: [Python-checkins] r70644 - peps/trunk/pep-0376.txt Message-ID: <20090328184924.CACE21E4002@bag.python.org> Author: tarek.ziade Date: Sat Mar 28 19:49:24 2009 New Revision: 70644 Log: removing the python version bit for the egg.info directory Modified: peps/trunk/pep-0376.txt Modified: peps/trunk/pep-0376.txt ============================================================================== --- peps/trunk/pep-0376.txt (original) +++ peps/trunk/pep-0376.txt Sat Mar 28 19:49:24 2009 @@ -45,9 +45,9 @@ will be installed in `site-packages`:: - zlib - - zlib-2.5.2-py2.6.egg-info + - zlib-2.5.2.egg-info -Where `zlib` is the package itself, and `zlib-2.5.2-py2.6.egg-info` is +Where `zlib` is the package itself, and `zlib-2.5.2.egg-info` is a file containing the package metadata as described in PEP 314. This file corresponds to the file called `PKG-INFO`, built by @@ -143,8 +143,9 @@ - the `RECORD` file will hold the list of installed files. These correspond to the files listed by the `record` option of the `install` command, and will always be generated. This will allow uninstall, as - explained later in this PEP. + explained later in this PEP. +The two files will need to use '/'-separated relative paths. The `install` command will record by default installed files in the RECORD file. @@ -161,13 +162,12 @@ Back to our `zlib` example, we will have:: - zlib - - zlib-2.5.2-py2.6.egg-info/ + - zlib-2.5.2.egg-info/ PKG-INFO MANIFEST RECORD -XXX See if we want to keep the 2.5.2-py2.6 part - +XXX See if we want to add Python version in the PKG-INFO New functions in pkgutil ======================== From python-checkins at python.org Sat Mar 28 19:53:28 2009 From: python-checkins at python.org (tarek.ziade) Date: Sat, 28 Mar 2009 19:53:28 +0100 (CET) Subject: [Python-checkins] r70645 - peps/trunk/pep-0376.txt Message-ID: <20090328185328.C98401E4002@bag.python.org> Author: tarek.ziade Date: Sat Mar 28 19:53:28 2009 New Revision: 70645 Log: fixing the example Modified: peps/trunk/pep-0376.txt Modified: peps/trunk/pep-0376.txt ============================================================================== --- peps/trunk/pep-0376.txt (original) +++ peps/trunk/pep-0376.txt Sat Mar 28 19:53:28 2009 @@ -204,7 +204,7 @@ >>> from pkgutil import get_egg_info, get_metadata, get_egg_info_file >>> get_egg_info('zlib') - '/opt/local/lib/python2.6/site-packages/zlib-2.5.2-py2.6.egg-info' + '/opt/local/lib/python2.6/site-packages/zlib-2.5.2.egg-info' >>> metadata = get_metadata('zlib') >>> metadata.version '2.5.2' From python-checkins at python.org Sat Mar 28 20:08:48 2009 From: python-checkins at python.org (tarek.ziade) Date: Sat, 28 Mar 2009 20:08:48 +0100 (CET) Subject: [Python-checkins] r70646 - peps/trunk/pep-0376.txt Message-ID: <20090328190848.E361C1E4002@bag.python.org> Author: tarek.ziade Date: Sat Mar 28 20:08:48 2009 New Revision: 70646 Log: more notes and details for BoF work Modified: peps/trunk/pep-0376.txt Modified: peps/trunk/pep-0376.txt ============================================================================== --- peps/trunk/pep-0376.txt (original) +++ peps/trunk/pep-0376.txt Sat Mar 28 20:08:48 2009 @@ -218,6 +218,8 @@ Adding an install and an uninstall script ========================================= +XXX decide wheter we include these scripts. + `easy_install` and `pip` does basically the same work, besides other features that are not discussed here. @@ -226,19 +228,49 @@ - they install it inside the site-packages directory - they add an entry in a .pth file +Distutils will provide two simple reference scripts, that are just able +to do the features mentioned. Third party packages will be able to fetch +dependencies. + +Install script +-------------- + A new script called `install.py` is added in a new directory called `scripts` in Distutils, and lets people run an installation using:: $ python -m distutils.scripts.install zlib +Where `zlib` can be: +- the name of the package +- an url of an archive +- a path + +The install script process is done in 3 steps: + +1. it looks for the package at PyPI if it's a package name + XXX explain here how (easy_install code) +2. it downloads it in a temporary directory (or copy it if it's a path) +3. it runs the install command, with the --record option + XXX explains here how (see pip code) + +The install script takes several options : + +Uninstall script +---------------- + An uninstall command is added as well that removes the files recorded in the RECORD file. This removal will warn on files that no longer exist and will not take care of side effects, like the removal of a file used by another element of the system. -XXX work to be done here : specification of the two commands -(probably a mix of easy_install and pip) + $ python -m distutils.scripts.uninstall zlib + +XXX work to be done here : detail specification of the uninstall process + +Aknowledgments +============== +Jim Fulton, Ian Bicking, Phillip Eby, and many people at Pycon and Distutils-SIG. Copyright ========= From python-checkins at python.org Sat Mar 28 20:10:13 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 28 Mar 2009 20:10:13 +0100 (CET) Subject: [Python-checkins] r70647 - python/trunk/Doc/whatsnew/2.7.rst Message-ID: <20090328191013.582F91E4002@bag.python.org> Author: antoine.pitrou Date: Sat Mar 28 20:10:13 2009 New Revision: 70647 Log: Publicize the GC untracking optimization Modified: python/trunk/Doc/whatsnew/2.7.rst Modified: python/trunk/Doc/whatsnew/2.7.rst ============================================================================== --- python/trunk/Doc/whatsnew/2.7.rst (original) +++ python/trunk/Doc/whatsnew/2.7.rst Sat Mar 28 20:10:13 2009 @@ -129,6 +129,14 @@ (Suggested by Martin von Loewis and implemented by Antoine Pitrou; :issue:`4074`.) +* The garbage collector tries to avoid tracking simple containers which + can't be part of a cycle. As of now, this is true for tuples and dicts + containing atomic types (such as ints, strings, etc.). Transitively, a dict + containing tuples of atomic types won't be tracked either. This helps brings + down the cost of full garbage collections, since it decreases the number of + objects to be considered and traversed by the collector. + (Contributed by Antoine Pitrou; :issue:`4688`.) + .. ====================================================================== From python-checkins at python.org Sat Mar 28 20:10:37 2009 From: python-checkins at python.org (georg.brandl) Date: Sat, 28 Mar 2009 20:10:37 +0100 (CET) Subject: [Python-checkins] r70648 - python/trunk/Doc/library/stdtypes.rst Message-ID: <20090328191037.A97041E4002@bag.python.org> Author: georg.brandl Date: Sat Mar 28 20:10:37 2009 New Revision: 70648 Log: #5324: document __subclasses__(). Modified: python/trunk/Doc/library/stdtypes.rst Modified: python/trunk/Doc/library/stdtypes.rst ============================================================================== --- python/trunk/Doc/library/stdtypes.rst (original) +++ python/trunk/Doc/library/stdtypes.rst Sat Mar 28 20:10:37 2009 @@ -2674,6 +2674,17 @@ The name of the class or type. + +.. method:: class.__subclasses__ + + :term:`New-style class`\ es keep a list of weak references to their immediate + subclasses. This method returns a list of all those references still alive. + Example:: + + >>> int.__subclasses__() + [] + + .. rubric:: Footnotes .. [#] Additional information on these special methods may be found in the Python From python-checkins at python.org Sat Mar 28 20:13:21 2009 From: python-checkins at python.org (georg.brandl) Date: Sat, 28 Mar 2009 20:13:21 +0100 (CET) Subject: [Python-checkins] r70649 - in python/branches/py3k: Doc/library/stdtypes.rst Message-ID: <20090328191321.7DBCE1E4002@bag.python.org> Author: georg.brandl Date: Sat Mar 28 20:13:21 2009 New Revision: 70649 Log: Merged revisions 70648 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70648 | georg.brandl | 2009-03-28 14:10:37 -0500 (Sa, 28 M?r 2009) | 1 line #5324: document __subclasses__(). ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/stdtypes.rst Modified: python/branches/py3k/Doc/library/stdtypes.rst ============================================================================== --- python/branches/py3k/Doc/library/stdtypes.rst (original) +++ python/branches/py3k/Doc/library/stdtypes.rst Sat Mar 28 20:13:21 2009 @@ -2665,6 +2665,16 @@ The name of the class or type. + +.. method:: class.__subclasses__ + + All classes keep a list of weak references to their immediate subclasses. + This method returns a list of all those references still alive. Example:: + + >>> int.__subclasses__() + [] + + .. rubric:: Footnotes .. [#] Additional information on these special methods may be found in the Python From python-checkins at python.org Sat Mar 28 20:16:10 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 28 Mar 2009 20:16:10 +0100 (CET) Subject: [Python-checkins] r70650 - in python/trunk/Doc/library: os.rst string.rst Message-ID: <20090328191610.F12A71E4002@bag.python.org> Author: benjamin.peterson Date: Sat Mar 28 20:16:10 2009 New Revision: 70650 Log: give os.symlink and os.link() better parameter names #5564 Modified: python/trunk/Doc/library/os.rst python/trunk/Doc/library/string.rst Modified: python/trunk/Doc/library/os.rst ============================================================================== --- python/trunk/Doc/library/os.rst (original) +++ python/trunk/Doc/library/os.rst Sat Mar 28 20:16:10 2009 @@ -924,9 +924,10 @@ .. versionadded:: 2.3 -.. function:: link(src, dst) +.. function:: link(source, link_name) - Create a hard link pointing to *src* named *dst*. Availability: Unix. + Create a hard link pointing to *source* named *link_name*. Availability: + Unix. .. function:: listdir(path) @@ -1246,9 +1247,10 @@ Added access to values as attributes of the returned object. -.. function:: symlink(src, dst) +.. function:: symlink(source, link_name) - Create a symbolic link pointing to *src* named *dst*. Availability: Unix. + Create a symbolic link pointing to *source* named *link_name*. Availability: + Unix. .. function:: tempnam([dir[, prefix]]) Modified: python/trunk/Doc/library/string.rst ============================================================================== --- python/trunk/Doc/library/string.rst (original) +++ python/trunk/Doc/library/string.rst Sat Mar 28 20:16:10 2009 @@ -243,6 +243,7 @@ Some simple format string examples:: "First, thou shalt count to {0}" # References first positional argument + "Bring me a {}" # Implicitly references the first positional argument "My quest is {name}" # References keyword argument 'name' "Weight in tons {0.weight}" # 'weight' attribute of first positional arg "Units destroyed: {players[0]}" # First element of keyword argument 'players'. From python-checkins at python.org Sat Mar 28 20:17:17 2009 From: python-checkins at python.org (guilherme.polo) Date: Sat, 28 Mar 2009 20:17:17 +0100 (CET) Subject: [Python-checkins] r70651 - python/trunk/Modules/_tkinter.c Message-ID: <20090328191717.698981E4002@bag.python.org> Author: guilherme.polo Date: Sat Mar 28 20:17:16 2009 New Revision: 70651 Log: Typo fix Modified: python/trunk/Modules/_tkinter.c Modified: python/trunk/Modules/_tkinter.c ============================================================================== --- python/trunk/Modules/_tkinter.c (original) +++ python/trunk/Modules/_tkinter.c Sat Mar 28 20:17:16 2009 @@ -2703,7 +2703,7 @@ if (!self && Py_Py3kWarningFlag) { if (PyErr_Warn(PyExc_DeprecationWarning, - "_tkinter.createfilehandler is gone in 3.x") < 0) + "_tkinter.quit is gone in 3.x") < 0) return NULL; } From python-checkins at python.org Sat Mar 28 20:17:54 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 28 Mar 2009 20:17:54 +0100 (CET) Subject: [Python-checkins] r70652 - python/trunk/Doc/whatsnew/2.7.rst Message-ID: <20090328191754.952D11E4002@bag.python.org> Author: antoine.pitrou Date: Sat Mar 28 20:17:54 2009 New Revision: 70652 Log: Fix a typo and be more specific Modified: python/trunk/Doc/whatsnew/2.7.rst Modified: python/trunk/Doc/whatsnew/2.7.rst ============================================================================== --- python/trunk/Doc/whatsnew/2.7.rst (original) +++ python/trunk/Doc/whatsnew/2.7.rst Sat Mar 28 20:17:54 2009 @@ -132,9 +132,13 @@ * The garbage collector tries to avoid tracking simple containers which can't be part of a cycle. As of now, this is true for tuples and dicts containing atomic types (such as ints, strings, etc.). Transitively, a dict - containing tuples of atomic types won't be tracked either. This helps brings - down the cost of full garbage collections, since it decreases the number of - objects to be considered and traversed by the collector. + containing tuples of atomic types won't be tracked either. This helps bring + down the individual cost of each garbage collection, since it decreases the + number of objects to be considered and traversed by the collector. + + To help diagnosing this optimization, a new function in the :mod:`gc` + module, :func:`is_tracked`, returns True if a given instance is tracked + by the garbage collector, False otherwise. (Contributed by Antoine Pitrou; :issue:`4688`.) From python-checkins at python.org Sat Mar 28 20:20:09 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 28 Mar 2009 20:20:09 +0100 (CET) Subject: [Python-checkins] r70653 - in python/branches/py3k: Doc/whatsnew/2.7.rst Message-ID: <20090328192009.C9A4C1E4020@bag.python.org> Author: antoine.pitrou Date: Sat Mar 28 20:20:09 2009 New Revision: 70653 Log: Merged revisions 70647,70652 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70647 | antoine.pitrou | 2009-03-28 20:10:13 +0100 (sam., 28 mars 2009) | 3 lines Publicize the GC untracking optimization ........ r70652 | antoine.pitrou | 2009-03-28 20:17:54 +0100 (sam., 28 mars 2009) | 3 lines Fix a typo and be more specific ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/whatsnew/2.7.rst Modified: python/branches/py3k/Doc/whatsnew/2.7.rst ============================================================================== --- python/branches/py3k/Doc/whatsnew/2.7.rst (original) +++ python/branches/py3k/Doc/whatsnew/2.7.rst Sat Mar 28 20:20:09 2009 @@ -129,6 +129,18 @@ (Suggested by Martin von Loewis and implemented by Antoine Pitrou; :issue:`4074`.) +* The garbage collector tries to avoid tracking simple containers which + can't be part of a cycle. As of now, this is true for tuples and dicts + containing atomic types (such as ints, strings, etc.). Transitively, a dict + containing tuples of atomic types won't be tracked either. This helps bring + down the individual cost of each garbage collection, since it decreases the + number of objects to be considered and traversed by the collector. + + To help diagnosing this optimization, a new function in the :mod:`gc` + module, :func:`is_tracked`, returns True if a given instance is tracked + by the garbage collector, False otherwise. + (Contributed by Antoine Pitrou; :issue:`4688`.) + .. ====================================================================== From python-checkins at python.org Sat Mar 28 20:20:52 2009 From: python-checkins at python.org (guilherme.polo) Date: Sat, 28 Mar 2009 20:20:52 +0100 (CET) Subject: [Python-checkins] r70654 - python/branches/release26-maint Message-ID: <20090328192052.DF7F81E4033@bag.python.org> Author: guilherme.polo Date: Sat Mar 28 20:20:52 2009 New Revision: 70654 Log: Blocked revisions 70641,70651 via svnmerge ........ r70641 | guilherme.polo | 2009-03-27 18:43:08 -0300 (Fri, 27 Mar 2009) | 3 lines Adjusted _tkinter to compile without warnings when WITH_THREAD is not defined (part of issue #5035) ........ r70651 | guilherme.polo | 2009-03-28 16:17:16 -0300 (Sat, 28 Mar 2009) | 1 line Typo fix ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Sat Mar 28 20:23:16 2009 From: python-checkins at python.org (guilherme.polo) Date: Sat, 28 Mar 2009 20:23:16 +0100 (CET) Subject: [Python-checkins] r70655 - python/branches/py3k Message-ID: <20090328192316.7510E1E4002@bag.python.org> Author: guilherme.polo Date: Sat Mar 28 20:23:16 2009 New Revision: 70655 Log: Blocked revisions 70651 via svnmerge ........ r70651 | guilherme.polo | 2009-03-28 16:17:16 -0300 (Sat, 28 Mar 2009) | 1 line Typo fix ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Sat Mar 28 20:33:34 2009 From: python-checkins at python.org (georg.brandl) Date: Sat, 28 Mar 2009 20:33:34 +0100 (CET) Subject: [Python-checkins] r70656 - python/trunk/Tools/scripts/reindent-rst.py Message-ID: <20090328193334.2AFD81E400C@bag.python.org> Author: georg.brandl Date: Sat Mar 28 20:33:33 2009 New Revision: 70656 Log: Add a script to fixup rst files if the pre-commit hook rejects them. Added: python/trunk/Tools/scripts/reindent-rst.py (contents, props changed) Added: python/trunk/Tools/scripts/reindent-rst.py ============================================================================== --- (empty file) +++ python/trunk/Tools/scripts/reindent-rst.py Sat Mar 28 20:33:33 2009 @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +# Make a reST file compliant to our pre-commit hook. +# Currently just remove trailing whitespace. + +from __future__ import with_statement +import sys, re, shutil + +ws_re = re.compile(r'\s+(\r?\n)$') + +def main(argv=sys.argv): + rv = 0 + for filename in argv[1:]: + try: + with open(filename, 'rb') as f: + lines = f.readlines() + new_lines = [ws_re.sub(r'\1', line) for line in lines] + if new_lines != lines: + print 'Fixing %s...' % filename + shutil.copyfile(filename, filename + '.bak') + with open(filename, 'wb') as f: + f.writelines(new_lines) + except Exception, err: + print 'Cannot fix %s: %s' % (filename, err) + rv = 1 + return rv + +if __name__ == '__main__': + sys.exit(main()) From python-checkins at python.org Sat Mar 28 20:45:27 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 28 Mar 2009 20:45:27 +0100 (CET) Subject: [Python-checkins] r70658 - python/branches/py3k/Doc/whatsnew/3.1.rst Message-ID: <20090328194527.405691E4002@bag.python.org> Author: antoine.pitrou Date: Sat Mar 28 20:45:26 2009 New Revision: 70658 Log: Publicize 3.1-specific performance enhancements Modified: python/branches/py3k/Doc/whatsnew/3.1.rst Modified: python/branches/py3k/Doc/whatsnew/3.1.rst ============================================================================== --- python/branches/py3k/Doc/whatsnew/3.1.rst (original) +++ python/branches/py3k/Doc/whatsnew/3.1.rst Sat Mar 28 20:45:26 2009 @@ -112,3 +112,27 @@ .. ====================================================================== + + +Optimizations +------------- + +Major performance enhancements have been added: + +* The new I/O library (as defined in :pep:`3116`) was mostly written in + Python and quickly proved to be a problematic bottleneck in Python 3.0. + In Python 3.1, the I/O library has been entirely rewritten in C and is + 2 to 20 times faster depending on the task at hand. The pure Python + version is still available for experimentation purposes through + the ``_pyio`` module. + + (Contributed by Amaury Forgeot d'Arc and Antoine Pitrou.) + +* A new configure flag, ``--with-computed-gotos``, enables a faster opcode + dispatch mechanism on compilers which support it. Speedups of up to 20% + have been observed, depending on the system and compiler. + + (Contributed by Antoine Pitrou, :issue:`4753`.) + + +.. ====================================================================== From python-checkins at python.org Sat Mar 28 20:52:59 2009 From: python-checkins at python.org (georg.brandl) Date: Sat, 28 Mar 2009 20:52:59 +0100 (CET) Subject: [Python-checkins] r70660 - python/trunk/Doc/Makefile Message-ID: <20090328195259.48CCE1E4002@bag.python.org> Author: georg.brandl Date: Sat Mar 28 20:52:58 2009 New Revision: 70660 Log: Switch to fixed Sphinx version. Modified: python/trunk/Doc/Makefile Modified: python/trunk/Doc/Makefile ============================================================================== --- python/trunk/Doc/Makefile (original) +++ python/trunk/Doc/Makefile Sat Mar 28 20:52:58 2009 @@ -31,7 +31,7 @@ checkout: @if [ ! -d tools/sphinx ]; then \ echo "Checking out Sphinx..."; \ - svn checkout $(SVNROOT)/doctools/trunk/sphinx tools/sphinx; \ + svn checkout $(SVNROOT)/external/Sphinx-0.6.1/sphinx tools/sphinx; \ fi @if [ ! -d tools/docutils ]; then \ echo "Checking out Docutils..."; \ From python-checkins at python.org Sat Mar 28 20:57:36 2009 From: python-checkins at python.org (georg.brandl) Date: Sat, 28 Mar 2009 20:57:36 +0100 (CET) Subject: [Python-checkins] r70661 - in python/trunk/Doc: distutils/index.rst documenting/index.rst extending/index.rst library/index.rst reference/index.rst tutorial/index.rst using/index.rst Message-ID: <20090328195736.6FF581E4002@bag.python.org> Author: georg.brandl Date: Sat Mar 28 20:57:36 2009 New Revision: 70661 Log: Add section numbering to some of the larger subdocuments. Modified: python/trunk/Doc/distutils/index.rst python/trunk/Doc/documenting/index.rst python/trunk/Doc/extending/index.rst python/trunk/Doc/library/index.rst python/trunk/Doc/reference/index.rst python/trunk/Doc/tutorial/index.rst python/trunk/Doc/using/index.rst Modified: python/trunk/Doc/distutils/index.rst ============================================================================== --- python/trunk/Doc/distutils/index.rst (original) +++ python/trunk/Doc/distutils/index.rst Sat Mar 28 20:57:36 2009 @@ -16,6 +16,7 @@ .. toctree:: :maxdepth: 2 + :numbered: introduction.rst setupscript.rst Modified: python/trunk/Doc/documenting/index.rst ============================================================================== --- python/trunk/Doc/documenting/index.rst (original) +++ python/trunk/Doc/documenting/index.rst Sat Mar 28 20:57:36 2009 @@ -23,6 +23,7 @@ are more than welcome as well. .. toctree:: + :numbered: intro.rst style.rst Modified: python/trunk/Doc/extending/index.rst ============================================================================== --- python/trunk/Doc/extending/index.rst (original) +++ python/trunk/Doc/extending/index.rst Sat Mar 28 20:57:36 2009 @@ -26,6 +26,7 @@ .. toctree:: :maxdepth: 2 + :numbered: extending.rst newtypes.rst Modified: python/trunk/Doc/library/index.rst ============================================================================== --- python/trunk/Doc/library/index.rst (original) +++ python/trunk/Doc/library/index.rst Sat Mar 28 20:57:36 2009 @@ -38,6 +38,7 @@ .. toctree:: :maxdepth: 2 + :numbered: intro.rst functions.rst Modified: python/trunk/Doc/reference/index.rst ============================================================================== --- python/trunk/Doc/reference/index.rst (original) +++ python/trunk/Doc/reference/index.rst Sat Mar 28 20:57:36 2009 @@ -18,6 +18,7 @@ .. toctree:: :maxdepth: 2 + :numbered: introduction.rst lexical_analysis.rst Modified: python/trunk/Doc/tutorial/index.rst ============================================================================== --- python/trunk/Doc/tutorial/index.rst (original) +++ python/trunk/Doc/tutorial/index.rst Sat Mar 28 20:57:36 2009 @@ -44,6 +44,7 @@ The :ref:`glossary` is also worth going through. .. toctree:: + :numbered: appetite.rst interpreter.rst Modified: python/trunk/Doc/using/index.rst ============================================================================== --- python/trunk/Doc/using/index.rst (original) +++ python/trunk/Doc/using/index.rst Sat Mar 28 20:57:36 2009 @@ -11,6 +11,7 @@ .. toctree:: + :numbered: cmdline.rst unix.rst From buildbot at python.org Sat Mar 28 21:21:52 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 28 Mar 2009 20:21:52 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090328202152.7BF9F1E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/275 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: antoine.pitrou,benjamin.peterson,georg.brandl,guilherme.polo BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sat Mar 28 21:41:35 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 28 Mar 2009 20:41:35 +0000 Subject: [Python-checkins] buildbot failure in OS X x86 2.6 Message-ID: <20090328204136.E58131E4002@bag.python.org> The Buildbot has detected a new failure of OS X x86 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/OS%20X%20x86%202.6/builds/145 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: noller-osx86 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: guilherme.polo BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_shelve ====================================================================== ERROR: test_update (test.test_shelve.TestAsciiFileShelve) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/mapping_tests.py", line 182, in test_update d = self._empty_mapping() File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/test_shelve.py", line 108, in _empty_mapping x= shelve.open(self.fn+str(self.counter), **self._args) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/shelve.py", line 234, in open return DbfilenameShelf(filename, flag, protocol, writeback) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/shelve.py", line 218, in __init__ Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/anydbm.py", line 83, in open return mod.open(file, flag, mode) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/dbhash.py", line 19, in open return bsddb.hashopen(file, flag, mode) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/bsddb/__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test_write (test.test_shelve.TestAsciiFileShelve) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/mapping_tests.py", line 107, in test_write d = self._full_mapping(self.reference) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/mapping_tests.py", line 24, in _full_mapping x = self._empty_mapping() File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/test_shelve.py", line 108, in _empty_mapping x= shelve.open(self.fn+str(self.counter), **self._args) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/shelve.py", line 234, in open return DbfilenameShelf(filename, flag, protocol, writeback) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/shelve.py", line 218, in __init__ Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/anydbm.py", line 83, in open return mod.open(file, flag, mode) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/dbhash.py", line 19, in open return bsddb.hashopen(file, flag, mode) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/bsddb/__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test_update (test.test_shelve.TestBinaryFileShelve) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/mapping_tests.py", line 182, in test_update d = self._empty_mapping() File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/test_shelve.py", line 108, in _empty_mapping x= shelve.open(self.fn+str(self.counter), **self._args) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/shelve.py", line 234, in open return DbfilenameShelf(filename, flag, protocol, writeback) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/shelve.py", line 218, in __init__ Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/anydbm.py", line 83, in open return mod.open(file, flag, mode) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/dbhash.py", line 19, in open return bsddb.hashopen(file, flag, mode) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/bsddb/__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test_write (test.test_shelve.TestBinaryFileShelve) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/mapping_tests.py", line 107, in test_write d = self._full_mapping(self.reference) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/mapping_tests.py", line 24, in _full_mapping x = self._empty_mapping() File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/test_shelve.py", line 108, in _empty_mapping x= shelve.open(self.fn+str(self.counter), **self._args) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/shelve.py", line 234, in open return DbfilenameShelf(filename, flag, protocol, writeback) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/shelve.py", line 218, in __init__ Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/anydbm.py", line 83, in open return mod.open(file, flag, mode) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/dbhash.py", line 19, in open return bsddb.hashopen(file, flag, mode) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/bsddb/__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test_update (test.test_shelve.TestProto2FileShelve) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/mapping_tests.py", line 182, in test_update d = self._empty_mapping() File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/test_shelve.py", line 108, in _empty_mapping x= shelve.open(self.fn+str(self.counter), **self._args) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/shelve.py", line 234, in open return DbfilenameShelf(filename, flag, protocol, writeback) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/shelve.py", line 218, in __init__ Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/anydbm.py", line 83, in open return mod.open(file, flag, mode) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/dbhash.py", line 19, in open return bsddb.hashopen(file, flag, mode) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/bsddb/__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') ====================================================================== ERROR: test_write (test.test_shelve.TestProto2FileShelve) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/mapping_tests.py", line 107, in test_write d = self._full_mapping(self.reference) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/mapping_tests.py", line 24, in _full_mapping x = self._empty_mapping() File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/test/test_shelve.py", line 108, in _empty_mapping x= shelve.open(self.fn+str(self.counter), **self._args) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/shelve.py", line 234, in open return DbfilenameShelf(filename, flag, protocol, writeback) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/shelve.py", line 218, in __init__ Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/anydbm.py", line 83, in open return mod.open(file, flag, mode) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/dbhash.py", line 19, in open return bsddb.hashopen(file, flag, mode) File "/Users/buildbot/buildarea/2.6.noller-osx86/build/Lib/bsddb/__init__.py", line 361, in hashopen d.open(file, db.DB_HASH, flags, mode) DBFileExistsError: (17, 'File exists -- __fop_file_setup: Retry limit (100) exceeded') make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sat Mar 28 21:50:49 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 28 Mar 2009 20:50:49 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090328205050.5B3BE1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/191 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: guilherme.polo BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Sat Mar 28 22:28:23 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 28 Mar 2009 21:28:23 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090328212823.D37741E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/784 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/threaded_import_hangers.py", line 28, in run self.function(*self.args) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/tempfile.py", line 480, in TemporaryFile _os.close(fd) OSError: [Errno 9] Bad file descriptor make: *** [buildbottest] Abort trap sincerely, -The Buildbot From python-checkins at python.org Sat Mar 28 22:42:06 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 28 Mar 2009 22:42:06 +0100 (CET) Subject: [Python-checkins] r70662 - in python/branches/py3k: Doc/library/unittest.rst Lib/email/test/test_email_codecs.py Lib/platform.py Lib/test/regrtest.py Lib/test/support.py Lib/test/test__locale.py Lib/test/test_curses.py Lib/test/test_decimal.py Lib/test/test_descr.py Lib/test/test_epoll.py Lib/test/test_fork1.py Lib/test/test_ioctl.py Lib/test/test_kqueue.py Lib/test/test_largefile.py Lib/test/test_locale.py Lib/test/test_minidom.py Lib/test/test_multiprocessing.py Lib/test/test_nis.py Lib/test/test_openpty.py Lib/test/test_ossaudiodev.py Lib/test/test_pep277.py Lib/test/test_pipes.py Lib/test/test_platform.py Lib/test/test_poll.py Lib/test/test_posix.py Lib/test/test_pty.py Lib/test/test_signal.py Lib/test/test_site.py Lib/test/test_socketserver.py Lib/test/test_sqlite.py Lib/test/test_ssl.py Lib/test/test_tempfile.py Lib/test/test_threaded_import.py Lib/test/test_threadsignals.py Lib/test/test_tk.py Lib/test/test_ttk_guionly.py Lib/test/test_unicode_file.py Lib/test/test_unittest.py Lib/test/test_univnewlines.py Lib/test/test_wait3.py Lib/test/test_wait4.py Lib/traceback.py Lib/unittest.py Message-ID: <20090328214206.B72011E4002@bag.python.org> Author: benjamin.peterson Date: Sat Mar 28 22:42:05 2009 New Revision: 70662 Log: Merged revisions 70554,70588-70589,70598,70605,70611-70621,70623-70624,70626-70627 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70554 | benjamin.peterson | 2009-03-23 16:25:15 -0500 (Mon, 23 Mar 2009) | 1 line complain when there's no last exception ........ r70588 | benjamin.peterson | 2009-03-24 17:56:32 -0500 (Tue, 24 Mar 2009) | 1 line fix newline issue in test summary ........ r70589 | benjamin.peterson | 2009-03-24 18:07:07 -0500 (Tue, 24 Mar 2009) | 1 line another style nit ........ r70598 | benjamin.peterson | 2009-03-25 16:24:04 -0500 (Wed, 25 Mar 2009) | 1 line add shorthands for expected failures and unexpected success ........ r70605 | benjamin.peterson | 2009-03-26 11:32:23 -0500 (Thu, 26 Mar 2009) | 1 line remove uneeded function ........ r70611 | benjamin.peterson | 2009-03-26 13:35:37 -0500 (Thu, 26 Mar 2009) | 1 line add much better tests for python version information parsing ........ r70612 | benjamin.peterson | 2009-03-26 13:55:48 -0500 (Thu, 26 Mar 2009) | 1 line more and more implementations now support sys.subversion ........ r70613 | benjamin.peterson | 2009-03-26 13:58:30 -0500 (Thu, 26 Mar 2009) | 1 line roll old test in with new one ........ r70614 | benjamin.peterson | 2009-03-26 14:09:21 -0500 (Thu, 26 Mar 2009) | 1 line add support for PyPy ........ r70615 | benjamin.peterson | 2009-03-26 14:58:18 -0500 (Thu, 26 Mar 2009) | 5 lines add some useful utilities for skipping tests with unittest's new skipping ability most significantly apply a modified portion of the patch from #4242 with patches for skipping implementation details ........ r70616 | benjamin.peterson | 2009-03-26 15:05:50 -0500 (Thu, 26 Mar 2009) | 1 line rename TestCase.skip() to skipTest() because it causes annoying problems with trial #5571 ........ r70617 | benjamin.peterson | 2009-03-26 15:17:27 -0500 (Thu, 26 Mar 2009) | 1 line apply the second part of #4242's patch; classify all the implementation details in test_descr ........ r70618 | benjamin.peterson | 2009-03-26 15:48:25 -0500 (Thu, 26 Mar 2009) | 1 line remove test_support.TestSkipped and just use unittest.SkipTest ........ r70619 | benjamin.peterson | 2009-03-26 15:49:40 -0500 (Thu, 26 Mar 2009) | 1 line fix naming ........ r70620 | benjamin.peterson | 2009-03-26 16:10:30 -0500 (Thu, 26 Mar 2009) | 1 line fix incorrect auto-translation of TestSkipped -> unittest.SkipTest ........ r70621 | benjamin.peterson | 2009-03-26 16:11:16 -0500 (Thu, 26 Mar 2009) | 1 line must pass argument to get expected behavior ;) ........ r70623 | benjamin.peterson | 2009-03-26 16:30:10 -0500 (Thu, 26 Mar 2009) | 1 line add missing import ........ r70624 | benjamin.peterson | 2009-03-26 16:30:54 -0500 (Thu, 26 Mar 2009) | 1 line ** is required here ........ r70626 | benjamin.peterson | 2009-03-26 16:40:29 -0500 (Thu, 26 Mar 2009) | 1 line update email tests to use SkipTest ........ r70627 | benjamin.peterson | 2009-03-26 16:44:43 -0500 (Thu, 26 Mar 2009) | 1 line fix another name ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/unittest.rst python/branches/py3k/Lib/email/test/test_email_codecs.py python/branches/py3k/Lib/platform.py python/branches/py3k/Lib/test/regrtest.py python/branches/py3k/Lib/test/support.py python/branches/py3k/Lib/test/test__locale.py python/branches/py3k/Lib/test/test_curses.py python/branches/py3k/Lib/test/test_decimal.py python/branches/py3k/Lib/test/test_descr.py python/branches/py3k/Lib/test/test_epoll.py python/branches/py3k/Lib/test/test_fork1.py python/branches/py3k/Lib/test/test_ioctl.py python/branches/py3k/Lib/test/test_kqueue.py python/branches/py3k/Lib/test/test_largefile.py python/branches/py3k/Lib/test/test_locale.py python/branches/py3k/Lib/test/test_minidom.py python/branches/py3k/Lib/test/test_multiprocessing.py python/branches/py3k/Lib/test/test_nis.py python/branches/py3k/Lib/test/test_openpty.py python/branches/py3k/Lib/test/test_ossaudiodev.py python/branches/py3k/Lib/test/test_pep277.py python/branches/py3k/Lib/test/test_pipes.py python/branches/py3k/Lib/test/test_platform.py python/branches/py3k/Lib/test/test_poll.py python/branches/py3k/Lib/test/test_posix.py python/branches/py3k/Lib/test/test_pty.py python/branches/py3k/Lib/test/test_signal.py python/branches/py3k/Lib/test/test_site.py python/branches/py3k/Lib/test/test_socketserver.py python/branches/py3k/Lib/test/test_sqlite.py python/branches/py3k/Lib/test/test_ssl.py python/branches/py3k/Lib/test/test_tempfile.py python/branches/py3k/Lib/test/test_threaded_import.py python/branches/py3k/Lib/test/test_threadsignals.py python/branches/py3k/Lib/test/test_tk.py python/branches/py3k/Lib/test/test_ttk_guionly.py python/branches/py3k/Lib/test/test_unicode_file.py python/branches/py3k/Lib/test/test_unittest.py python/branches/py3k/Lib/test/test_univnewlines.py python/branches/py3k/Lib/test/test_wait3.py python/branches/py3k/Lib/test/test_wait4.py python/branches/py3k/Lib/traceback.py python/branches/py3k/Lib/unittest.py Modified: python/branches/py3k/Doc/library/unittest.rst ============================================================================== --- python/branches/py3k/Doc/library/unittest.rst (original) +++ python/branches/py3k/Doc/library/unittest.rst Sat Mar 28 22:42:05 2009 @@ -575,7 +575,7 @@ instance. - .. method:: skip(reason) + .. method:: skipTest(reason) Calling this during the a test method or :meth:`setUp` skips the current test. See :ref:`unittest-skipping` for more information. Modified: python/branches/py3k/Lib/email/test/test_email_codecs.py ============================================================================== --- python/branches/py3k/Lib/email/test/test_email_codecs.py (original) +++ python/branches/py3k/Lib/email/test/test_email_codecs.py Sat Mar 28 22:42:05 2009 @@ -3,7 +3,7 @@ # email package unit tests for (optional) Asian codecs import unittest -from test.support import TestSkipped, run_unittest +from test.support import run_unittest from email.test.test_email import TestEmailBase from email.Charset import Charset @@ -15,7 +15,7 @@ try: str('foo', 'euc-jp') except LookupError: - raise TestSkipped + raise unittest.SkipTest Modified: python/branches/py3k/Lib/platform.py ============================================================================== --- python/branches/py3k/Lib/platform.py (original) +++ python/branches/py3k/Lib/platform.py Sat Mar 28 22:42:05 2009 @@ -1240,15 +1240,17 @@ '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*' '\[([^\]]+)\]?', re.ASCII) -_jython_sys_version_parser = re.compile( - r'([\d\.]+)', re.ASCII) - _ironpython_sys_version_parser = re.compile( r'IronPython\s*' '([\d\.]+)' '(?: \(([\d\.]+)\))?' ' on (.NET [\d\.]+)', re.ASCII) +_pypy_sys_version_parser = re.compile( + r'([\w.+]+)\s*' + '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*' + '\[PyPy [^\]]+\]?') + _sys_version_cache = {} def _sys_version(sys_version=None): @@ -1290,25 +1292,29 @@ 'failed to parse IronPython sys.version: %s' % repr(sys_version)) version, alt_version, compiler = match.groups() - branch = '' - revision = '' buildno = '' builddate = '' elif sys.platform[:4] == 'java': # Jython name = 'Jython' - match = _jython_sys_version_parser.match(sys_version) + match = _sys_version_parser.match(sys_version) if match is None: raise ValueError( 'failed to parse Jython sys.version: %s' % repr(sys_version)) - version, = match.groups() - branch = '' - revision = '' + version, buildno, builddate, buildtime, _ = match.groups() compiler = sys.platform - buildno = '' - builddate = '' + + elif "PyPy" in sys_version: + # PyPy + name = "PyPy" + match = _pypy_sys_version_parser.match(sys_version) + if match is None: + raise ValueError("failed to parse PyPy sys.version: %s" % + repr(sys_version)) + version, buildno, builddate, buildtime = match.groups() + compiler = "" else: # CPython @@ -1319,15 +1325,16 @@ repr(sys_version)) version, buildno, builddate, buildtime, compiler = \ match.groups() - if hasattr(sys, 'subversion'): - # sys.subversion was added in Python 2.5 - name, branch, revision = sys.subversion - else: - name = 'CPython' - branch = '' - revision = '' + name = 'CPython' builddate = builddate + ' ' + buildtime + if hasattr(sys, 'subversion'): + # sys.subversion was added in Python 2.5 + _, branch, revision = sys.subversion + else: + branch = '' + revision = '' + # Add the patchlevel version if missing l = version.split('.') if len(l) == 2: Modified: python/branches/py3k/Lib/test/regrtest.py ============================================================================== --- python/branches/py3k/Lib/test/regrtest.py (original) +++ python/branches/py3k/Lib/test/regrtest.py Sat Mar 28 22:42:05 2009 @@ -139,6 +139,7 @@ import time import traceback import warnings +import unittest from inspect import isabstract # I see no other way to suppress these warnings; @@ -614,7 +615,7 @@ print(test, "skipped --", msg) sys.stdout.flush() return -2 - except (ImportError, support.TestSkipped) as msg: + except (ImportError, unittest.SkipTest) as msg: if not quiet: print(test, "skipped --", msg) sys.stdout.flush() Modified: python/branches/py3k/Lib/test/support.py ============================================================================== --- python/branches/py3k/Lib/test/support.py (original) +++ python/branches/py3k/Lib/test/support.py Sat Mar 28 22:42:05 2009 @@ -8,12 +8,12 @@ import socket import sys import os -import os.path +import platform import shutil import warnings import unittest -__all__ = ["Error", "TestFailed", "TestSkipped", "ResourceDenied", "import_module", +__all__ = ["Error", "TestFailed", "ResourceDenied", "import_module", "verbose", "use_resources", "max_memuse", "record_original_stdout", "get_original_stdout", "unload", "unlink", "rmtree", "forget", "is_resource_enabled", "requires", "find_unused_port", "bind_port", @@ -24,7 +24,7 @@ "TransientResource", "transient_internet", "run_with_locale", "set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner", "run_unittest", "run_doctest", "threading_setup", "threading_cleanup", - "reap_children"] + "reap_children", "cpython_only", "check_impl_detail"] class Error(Exception): """Base class for regression test exceptions.""" @@ -32,17 +32,7 @@ class TestFailed(Error): """Test failed.""" -class TestSkipped(Error): - """Test skipped. - - This can be raised to indicate that a test was deliberatly - skipped, but not because a feature wasn't available. For - example, if some resource can't be used, such as the network - appears to be unavailable, this should be raised instead of - TestFailed. - """ - -class ResourceDenied(TestSkipped): +class ResourceDenied(unittest.SkipTest): """Test skipped because it requested a disallowed resource. This is raised when a test calls requires() for a resource that @@ -51,7 +41,7 @@ """ def import_module(name, deprecated=False): - """Import the module to be tested, raising TestSkipped if it is not + """Import the module to be tested, raising SkipTest if it is not available.""" with warnings.catch_warnings(): if deprecated: @@ -60,7 +50,7 @@ try: module = __import__(name, level=0) except ImportError: - raise TestSkipped("No module named " + name) + raise unittest.SkipTest("No module named " + name) else: return module @@ -124,7 +114,7 @@ possibility of False being returned occurs when regrtest.py is executing.""" # see if the caller's module is __main__ - if so, treat as if # the resource was set - if sys._getframe().f_back.f_globals.get("__name__") == "__main__": + if sys._getframe(1).f_globals.get("__name__") == "__main__": return if not is_resource_enabled(resource): if msg is None: @@ -357,12 +347,8 @@ unlink(TESTFN) def check_syntax_error(testcase, statement): - try: - compile(statement, '', 'exec') - except SyntaxError: - pass - else: - testcase.fail('Missing SyntaxError: "%s"' % statement) + testcase.assertRaises(SyntaxError, compile, statement, + '', 'exec') def open_urlresource(url, *args, **kw): import urllib.request, urllib.parse @@ -522,6 +508,21 @@ def captured_stdout(): return captured_output("stdout") +def gc_collect(): + """Force as many objects as possible to be collected. + + In non-CPython implementations of Python, this is needed because timely + deallocation is not guaranteed by the garbage collector. (Even in CPython + this can be the case in case of reference cycles.) This means that __del__ + methods may be called later than expected and weakrefs may remain alive for + longer than expected. This function tries its best to force all garbage + objects to disappear. + """ + import gc + gc.collect() + gc.collect() + gc.collect() + #======================================================================= # Decorator for running a function in a different locale, correctly resetting @@ -681,6 +682,55 @@ test(result) return result +def _id(obj): + return obj + +def requires_resource(resource): + if resource_is_enabled(resource): + return _id + else: + return unittest.skip("resource {0!r} is not enabled".format(resource)) + +def cpython_only(test): + """ + Decorator for tests only applicable on CPython. + """ + return impl_detail(cpython=True)(test) + +def impl_detail(msg=None, **guards): + if check_impl_detail(**guards): + return _id + if msg is None: + guardnames, default = _parse_guards(guards) + if default: + msg = "implementation detail not available on {0}" + else: + msg = "implementation detail specific to {0}" + guardnames = sorted(guardnames.keys()) + msg = msg.format(' or '.join(guardnames)) + return unittest.skip(msg) + +def _parse_guards(guards): + # Returns a tuple ({platform_name: run_me}, default_value) + if not guards: + return ({'cpython': True}, False) + is_true = guards.values()[0] + assert guards.values() == [is_true] * len(guards) # all True or all False + return (guards, not is_true) + +# Use the following check to guard CPython's implementation-specific tests -- +# or to run them only on the implementation(s) guarded by the arguments. +def check_impl_detail(**guards): + """This function returns True or False depending on the host platform. + Examples: + if check_impl_detail(): # only on CPython (default) + if check_impl_detail(jython=True): # only on Jython + if check_impl_detail(cpython=False): # everywhere except on CPython + """ + guards, default = _parse_guards(guards) + return guards.get(platform.python_implementation().lower(), default) + + def _run_suite(suite): """Run tests from a unittest.TestSuite-derived class.""" Modified: python/branches/py3k/Lib/test/test__locale.py ============================================================================== --- python/branches/py3k/Lib/test/test__locale.py (original) +++ python/branches/py3k/Lib/test/test__locale.py Sat Mar 28 22:42:05 2009 @@ -1,4 +1,4 @@ -from test.support import verbose, TestSkipped, run_unittest +from test.support import verbose, run_unittest from _locale import (setlocale, LC_ALL, LC_CTYPE, LC_NUMERIC, RADIXCHAR, THOUSEP, nl_langinfo, localeconv, Error) import unittest @@ -7,7 +7,7 @@ if uname()[0] == "Darwin": maj, min, mic = [int(part) for part in uname()[2].split(".")] if (maj, min, mic) < (8, 0, 0): - raise TestSkipped("locale support broken for OS X < 10.4") + raise unittest.SkipTest("locale support broken for OS X < 10.4") candidate_locales = ['es_UY', 'fr_FR', 'fi_FI', 'es_CO', 'pt_PT', 'it_IT', 'et_EE', 'es_PY', 'no_NO', 'nl_NL', 'lv_LV', 'el_GR', 'be_BY', 'fr_BE', Modified: python/branches/py3k/Lib/test/test_curses.py ============================================================================== --- python/branches/py3k/Lib/test/test_curses.py (original) +++ python/branches/py3k/Lib/test/test_curses.py Sat Mar 28 22:42:05 2009 @@ -16,16 +16,16 @@ # 'curses' resource be given on the regrtest command line using the -u # option. If not available, nothing after this line will be executed. -from test.support import requires, TestSkipped +from test.support import requires requires('curses') # XXX: if newterm was supported we could use it instead of initscr and not exit term = os.environ.get('TERM') if not term or term == 'unknown': - raise TestSkipped("$TERM=%r, calling initscr() may cause exit" % term) + raise unittest.SkipTest("$TERM=%r, calling initscr() may cause exit" % term) if sys.platform == "cygwin": - raise TestSkipped("cygwin's curses mostly just hangs") + raise unittest.SkipTest("cygwin's curses mostly just hangs") def window_funcs(stdscr): "Test the methods of windows" Modified: python/branches/py3k/Lib/test/test_decimal.py ============================================================================== --- python/branches/py3k/Lib/test/test_decimal.py (original) +++ python/branches/py3k/Lib/test/test_decimal.py Sat Mar 28 22:42:05 2009 @@ -31,8 +31,7 @@ import unittest from decimal import * import numbers -from test.support import (TestSkipped, run_unittest, run_doctest, - is_resource_enabled) +from test.support import run_unittest, run_doctest, is_resource_enabled import random try: import threading @@ -194,7 +193,7 @@ def eval_file(self, file): global skip_expected if skip_expected: - raise TestSkipped + raise unittest.SkipTest return for line in open(file): line = line.replace('\r\n', '').replace('\n', '') Modified: python/branches/py3k/Lib/test/test_descr.py ============================================================================== --- python/branches/py3k/Lib/test/test_descr.py (original) +++ python/branches/py3k/Lib/test/test_descr.py Sat Mar 28 22:42:05 2009 @@ -65,8 +65,9 @@ # Find method in parent class while meth not in t.__dict__: t = t.__bases__[0] - - self.assertEqual(m, t.__dict__[meth]) + # in some implementations (e.g. PyPy), 'm' can be a regular unbound + # method object; the getattr() below obtains its underlying function. + self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) self.assertEqual(m(a), res) bm = getattr(a, meth) self.assertEqual(bm(), res) @@ -85,7 +86,9 @@ m = getattr(t, meth) while meth not in t.__dict__: t = t.__bases__[0] - self.assertEqual(m, t.__dict__[meth]) + # in some implementations (e.g. PyPy), 'm' can be a regular unbound + # method object; the getattr() below obtains its underlying function. + self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) self.assertEqual(m(a, b), res) bm = getattr(a, meth) self.assertEqual(bm(b), res) @@ -97,7 +100,9 @@ m = getattr(t, meth) while meth not in t.__dict__: t = t.__bases__[0] - self.assertEqual(m, t.__dict__[meth]) + # in some implementations (e.g. PyPy), 'm' can be a regular unbound + # method object; the getattr() below obtains its underlying function. + self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) self.assertEqual(m(a, slice(b, c)), res) bm = getattr(a, meth) self.assertEqual(bm(slice(b, c)), res) @@ -110,7 +115,9 @@ m = getattr(t, meth) while meth not in t.__dict__: t = t.__bases__[0] - self.assertEqual(m, t.__dict__[meth]) + # in some implementations (e.g. PyPy), 'm' can be a regular unbound + # method object; the getattr() below obtains its underlying function. + self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) d['a'] = deepcopy(a) m(d['a'], b) self.assertEqual(d['a'], res) @@ -127,7 +134,9 @@ m = getattr(t, meth) while meth not in t.__dict__: t = t.__bases__[0] - self.assertEqual(m, t.__dict__[meth]) + # in some implementations (e.g. PyPy), 'm' can be a regular unbound + # method object; the getattr() below obtains its underlying function. + self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) d['a'] = deepcopy(a) m(d['a'], b, c) self.assertEqual(d['a'], res) @@ -144,7 +153,9 @@ while meth not in t.__dict__: t = t.__bases__[0] m = getattr(t, meth) - self.assertEqual(m, t.__dict__[meth]) + # in some implementations (e.g. PyPy), 'm' can be a regular unbound + # method object; the getattr() below obtains its underlying function. + self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) dictionary['a'] = deepcopy(a) m(dictionary['a'], slice(b, c), d) self.assertEqual(dictionary['a'], res) @@ -276,6 +287,7 @@ self.assertEqual(repr(a), "234.5") self.assertEqual(a.prec, 12) + @support.impl_detail("the module 'xxsubtype' is internal") def test_spam_lists(self): # Testing spamlist operations... import copy, xxsubtype as spam @@ -319,6 +331,7 @@ a.setstate(42) self.assertEqual(a.getstate(), 42) + @support.impl_detail("the module 'xxsubtype' is internal") def test_spam_dicts(self): # Testing spamdict operations... import copy, xxsubtype as spam @@ -778,8 +791,11 @@ try: callable(*args) except exc as msg: - if not str(msg).startswith(expected): - self.fail("Message %r, expected %r" % (str(msg), expected)) + # the exact msg is generally considered an impl detail + if support.check_impl_detail(): + if not str(msg).startswith(expected): + self.fail("Message %r, expected %r" % + (str(msg), expected)) else: self.fail("Expected %s" % exc) @@ -967,6 +983,7 @@ x.c = Counted() self.assertEqual(Counted.counter, 3) del x + support.gc_collect() self.assertEqual(Counted.counter, 0) class D(C): pass @@ -975,6 +992,7 @@ x.z = Counted() self.assertEqual(Counted.counter, 2) del x + support.gc_collect() self.assertEqual(Counted.counter, 0) class E(D): __slots__ = ['e'] @@ -984,6 +1002,7 @@ x.e = Counted() self.assertEqual(Counted.counter, 3) del x + support.gc_collect() self.assertEqual(Counted.counter, 0) # Test cyclical leaks [SF bug 519621] @@ -994,21 +1013,22 @@ s.a = [Counted(), s] self.assertEqual(Counted.counter, 1) s = None - import gc - gc.collect() + support.gc_collect() self.assertEqual(Counted.counter, 0) # Test lookup leaks [SF bug 572567] import sys,gc - class G(object): - def __eq__(self, other): - return 1 - g = G() - orig_objects = len(gc.get_objects()) - for i in range(10): - g==g - new_objects = len(gc.get_objects()) - self.assertEqual(orig_objects, new_objects) + if hasattr(gc, 'get_objects'): + class G(object): + def __cmp__(self, other): + return 0 + g = G() + orig_objects = len(gc.get_objects()) + for i in range(10): + g==g + new_objects = len(gc.get_objects()) + self.assertEqual(orig_objects, new_objects) + class H(object): __slots__ = ['a', 'b'] def __init__(self): @@ -1262,6 +1282,7 @@ else: self.fail("classmethod shouldn't accept keyword args") + @support.impl_detail("the module 'xxsubtype' is internal") def test_classmethods_in_c(self): # Testing C-based class methods... import xxsubtype as spam @@ -1293,6 +1314,7 @@ self.assertEqual(d.foo(1), (d, 1)) self.assertEqual(D.foo(d, 1), (d, 1)) + @support.impl_detail("the module 'xxsubtype' is internal") def test_staticmethods_in_c(self): # Testing C-based static methods... import xxsubtype as spam @@ -1410,6 +1432,14 @@ return [self, dict, object] class X(object, metaclass=_metaclass): pass + # In CPython, the class creation above already raises + # TypeError, as a protection against the fact that + # instances of X would segfault it. In other Python + # implementations it would be ok to let the class X + # be created, but instead get a clean TypeError on the + # __setitem__ below. + x = object.__new__(X) + x[5] = 6 except TypeError: pass else: @@ -1614,6 +1644,7 @@ r = weakref.ref(c) self.assertEqual(r(), c) del c + support.gc_collect() self.assertEqual(r(), None) del r class NoWeak(object): @@ -1631,6 +1662,7 @@ r = weakref.ref(yes) self.assertEqual(r(), yes) del yes + support.gc_collect() self.assertEqual(r(), None) del r @@ -1936,7 +1968,10 @@ # Two essentially featureless objects, just inheriting stuff from # object. - self.assertEqual(dir(None), dir(Ellipsis)) + self.assertEqual(dir(NotImplemented), dir(Ellipsis)) + if support.check_impl_detail(): + # None differs in PyPy: it has a __nonzero__ + self.assertEqual(dir(None), dir(Ellipsis)) # Nasty test case for proxied objects class Wrapper(object): @@ -2652,7 +2687,7 @@ self.fail("shouldn't allow %r.__class__ = %r" % (x, C)) try: delattr(x, "__class__") - except TypeError: + except (TypeError, AttributeError): pass else: self.fail("shouldn't allow del %r.__class__" % x) @@ -2780,6 +2815,16 @@ mod.__dict__["spam"] = "eggs" # Exception's __dict__ can be replaced, but not deleted + # (at least not any more than regular exception's __dict__ can + # be deleted; on CPython it is not the case, whereas on PyPy they + # can, just like any other new-style instance's __dict__.) + def can_delete_dict(e): + try: + del e.__dict__ + except (TypeError, AttributeError): + return False + else: + return True class Exception1(Exception, Base): pass class Exception2(Base, Exception): @@ -2788,12 +2833,7 @@ e = ExceptionType() e.__dict__ = {"a": 1} self.assertEqual(e.a, 1) - try: - del e.__dict__ - except (TypeError, AttributeError): - pass - else: - self.fail("%r's __dict__ can be deleted" % e) + self.assertEqual(can_delete_dict(e), can_delete_dict(ValueError())) def test_pickles(self): # Testing pickling and copying new-style classes and objects... @@ -3070,7 +3110,7 @@ class B(A): pass del B - gc.collect() + support.gc_collect() A.__setitem__ = lambda *a: None # crash def test_buffer_inheritance(self): @@ -3154,6 +3194,7 @@ c = C() self.assertEqual(log, []) del c + support.gc_collect() self.assertEqual(log, [1]) class D(object): pass @@ -3249,7 +3290,7 @@ self.assertEqual(hasattr(m, "__name__"), 0) self.assertEqual(hasattr(m, "__file__"), 0) self.assertEqual(hasattr(m, "foo"), 0) - self.assertEqual(m.__dict__, None) + self.assertFalse(m.__dict__) # None or {} are both reasonable answers m.foo = 1 self.assertEqual(m.__dict__, {"foo": 1}) @@ -3384,17 +3425,23 @@ c = C() c.attr = 42 - # The most interesting thing here is whether this blows up, due to flawed - # GC tracking logic in typeobject.c's call_finalizer() (a 2.2.1 bug). + # The most interesting thing here is whether this blows up, due to + # flawed GC tracking logic in typeobject.c's call_finalizer() (a 2.2.1 + # bug). del c # If that didn't blow up, it's also interesting to see whether clearing - # the last container slot works: that will attempt to delete c again, - # which will cause c to get appended back to the container again "during" - # the del. - del C.container[-1] + # the last container slot works: that will attempt to delete c again, + # which will cause c to get appended back to the container again + # "during" the del. (On non-CPython implementations, however, __del__ + # is typically not called again.) + support.gc_collect() self.assertEqual(len(C.container), 1) - self.assertEqual(C.container[-1].attr, 42) + del C.container[-1] + if support.check_impl_detail(): + support.gc_collect() + self.assertEqual(len(C.container), 1) + self.assertEqual(C.container[-1].attr, 42) # Make c mortal again, so that the test framework with -l doesn't report # it as a leak. @@ -3420,7 +3467,8 @@ pass class C(A,B) : __slots__=() - self.assertEqual(C.__basicsize__, B.__basicsize__) + if support.check_impl_detail(): + self.assertEqual(C.__basicsize__, B.__basicsize__) self.assert_(hasattr(C, '__dict__')) self.assert_(hasattr(C, '__weakref__')) C().x = 2 @@ -3503,7 +3551,7 @@ try: del D.__bases__ - except TypeError: + except (TypeError, AttributeError): pass else: self.fail("shouldn't be able to delete .__bases__") @@ -3681,6 +3729,7 @@ self.assertEqual(E() // C(), "C.__floordiv__") self.assertEqual(C() // E(), "C.__floordiv__") # This one would fail + @support.impl_detail("testing an internal kind of method object") def test_meth_class_get(self): # Testing __get__ method of METH_CLASS C methods... # Full coverage of descrobject.c::classmethod_get() @@ -3866,7 +3915,7 @@ self.assertEqual(c.attr, 1) # this makes a crash more likely: - import gc; gc.collect() + support.gc_collect() self.assertEqual(hasattr(c, 'attr'), False) def test_init(self): @@ -3893,8 +3942,14 @@ self.assert_(l.__add__ != [5].__add__) self.assert_(l.__add__ != l.__mul__) self.assert_(l.__add__.__name__ == '__add__') - self.assert_(l.__add__.__self__ is l) - self.assert_(l.__add__.__objclass__ is list) + if hasattr(l.__add__, '__self__'): + # CPython + self.assert_(l.__add__.__self__ is l) + self.assert_(l.__add__.__objclass__ is list) + else: + # Python implementations where [].__add__ is a normal bound method + self.assert_(l.__add__.im_self is l) + self.assert_(l.__add__.im_class is list) self.assertEqual(l.__add__.__doc__, list.__add__.__doc__) try: hash(l.__add__) Modified: python/branches/py3k/Lib/test/test_epoll.py ============================================================================== --- python/branches/py3k/Lib/test/test_epoll.py (original) +++ python/branches/py3k/Lib/test/test_epoll.py Sat Mar 28 22:42:05 2009 @@ -31,13 +31,13 @@ from test import support if not hasattr(select, "epoll"): - raise support.TestSkipped("test works only on Linux 2.6") + raise unittest.SkipTest("test works only on Linux 2.6") try: select.epoll() except IOError as e: if e.errno == errno.ENOSYS: - raise support.TestSkipped("kernel doesn't support epoll()") + raise unittest.SkipTest("kernel doesn't support epoll()") class TestEPoll(unittest.TestCase): Modified: python/branches/py3k/Lib/test/test_fork1.py ============================================================================== --- python/branches/py3k/Lib/test/test_fork1.py (original) +++ python/branches/py3k/Lib/test/test_fork1.py Sat Mar 28 22:42:05 2009 @@ -4,12 +4,12 @@ import os import time from test.fork_wait import ForkWait -from test.support import TestSkipped, run_unittest, reap_children +from test.support import run_unittest, reap_children try: os.fork except AttributeError: - raise TestSkipped("os.fork not defined -- skipping test_fork1") + raise unittest.SkipTest("os.fork not defined -- skipping test_fork1") class ForkTest(ForkWait): def wait_impl(self, cpid): Modified: python/branches/py3k/Lib/test/test_ioctl.py ============================================================================== --- python/branches/py3k/Lib/test/test_ioctl.py (original) +++ python/branches/py3k/Lib/test/test_ioctl.py Sat Mar 28 22:42:05 2009 @@ -1,18 +1,18 @@ import unittest -from test.support import TestSkipped, run_unittest +from test.support import run_unittest import os, struct try: import fcntl, termios except ImportError: - raise TestSkipped("No fcntl or termios module") + raise unittest.SkipTest("No fcntl or termios module") if not hasattr(termios,'TIOCGPGRP'): - raise TestSkipped("termios module doesn't have TIOCGPGRP") + raise unittest.SkipTest("termios module doesn't have TIOCGPGRP") try: tty = open("/dev/tty", "r") tty.close() except IOError: - raise TestSkipped("Unable to open /dev/tty") + raise unittest.SkipTest("Unable to open /dev/tty") try: import pty @@ -41,7 +41,7 @@ def test_ioctl_signed_unsigned_code_param(self): if not pty: - raise TestSkipped('pty module required') + raise unittest.SkipTest('pty module required') mfd, sfd = pty.openpty() try: if termios.TIOCSWINSZ < 0: Modified: python/branches/py3k/Lib/test/test_kqueue.py ============================================================================== --- python/branches/py3k/Lib/test/test_kqueue.py (original) +++ python/branches/py3k/Lib/test/test_kqueue.py Sat Mar 28 22:42:05 2009 @@ -10,7 +10,7 @@ from test import support if not hasattr(select, "kqueue"): - raise support.TestSkipped("test works only on BSD") + raise unittest.SkipTest("test works only on BSD") class TestKQueue(unittest.TestCase): def test_create_queue(self): Modified: python/branches/py3k/Lib/test/test_largefile.py ============================================================================== --- python/branches/py3k/Lib/test/test_largefile.py (original) +++ python/branches/py3k/Lib/test/test_largefile.py Sat Mar 28 22:42:05 2009 @@ -6,7 +6,7 @@ import sys import unittest from test.support import run_unittest, TESTFN, verbose, requires, \ - TestSkipped, unlink + unlink import io # C implementation of io import _pyio as pyio # Python implementation of io @@ -106,7 +106,7 @@ # this is already decided before start running the test suite # but we do it anyway for extra protection if not hasattr(f, 'truncate'): - raise TestSkipped("open().truncate() not available on this system") + raise unittest.SkipTest("open().truncate() not available on this system") f.seek(0, 2) # else we've lost track of the true size self.assertEqual(f.tell(), size+1) @@ -165,7 +165,7 @@ except (IOError, OverflowError): f.close() unlink(TESTFN) - raise TestSkipped("filesystem does not have largefile support") + raise unittest.SkipTest("filesystem does not have largefile support") else: f.close() suite = unittest.TestSuite() Modified: python/branches/py3k/Lib/test/test_locale.py ============================================================================== --- python/branches/py3k/Lib/test/test_locale.py (original) +++ python/branches/py3k/Lib/test/test_locale.py Sat Mar 28 22:42:05 2009 @@ -1,4 +1,4 @@ -from test.support import run_unittest, TestSkipped, verbose +from test.support import run_unittest, verbose import unittest import locale import sys @@ -9,7 +9,7 @@ def get_enUS_locale(): global enUS_locale if sys.platform == 'darwin': - raise TestSkipped("Locale support on MacOSX is minimal") + raise unittest.SkipTest("Locale support on MacOSX is minimal") if sys.platform.startswith("win"): tlocs = ("En", "English") else: @@ -22,7 +22,7 @@ continue break else: - raise TestSkipped( + raise unittest.SkipTest( "Test locale not supported (tried %s)" % (', '.join(tlocs))) enUS_locale = tloc locale.setlocale(locale.LC_NUMERIC, oldlocale) @@ -318,10 +318,10 @@ TestCNumberFormatting, TestFrFRNumberFormatting, ] - # TestSkipped can't be raised inside unittests, handle it manually instead + # SkipTest can't be raised inside unittests, handle it manually instead try: get_enUS_locale() - except TestSkipped as e: + except unittest.SkipTest as e: if verbose: print("Some tests will be disabled: %s" % e) else: Modified: python/branches/py3k/Lib/test/test_minidom.py ============================================================================== --- python/branches/py3k/Lib/test/test_minidom.py (original) +++ python/branches/py3k/Lib/test/test_minidom.py Sat Mar 28 22:42:05 2009 @@ -3,7 +3,7 @@ import os import sys import pickle -from test.support import verbose, run_unittest, TestSkipped +from test.support import verbose, run_unittest import unittest import xml.dom Modified: python/branches/py3k/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/py3k/Lib/test/test_multiprocessing.py (original) +++ python/branches/py3k/Lib/test/test_multiprocessing.py Sat Mar 28 22:42:05 2009 @@ -23,8 +23,7 @@ try: import multiprocessing.synchronize except ImportError as e: - from test.test_support import TestSkipped - raise TestSkipped(e) + raise unittest.SkipTest(e) import multiprocessing.dummy import multiprocessing.connection @@ -1814,7 +1813,7 @@ lock = multiprocessing.RLock() except OSError: from test.support import TestSkipped - raise TestSkipped("OSError raises on RLock creation, see issue 3111!") + raise unittest.SkipTest("OSError raises on RLock creation, see issue 3111!") if run is None: from test.support import run_unittest as run Modified: python/branches/py3k/Lib/test/test_nis.py ============================================================================== --- python/branches/py3k/Lib/test/test_nis.py (original) +++ python/branches/py3k/Lib/test/test_nis.py Sat Mar 28 22:42:05 2009 @@ -2,7 +2,7 @@ import unittest import nis -raise support.TestSkipped("test_nis hangs on Solaris") +raise unittest.SkipTest("test_nis hangs on Solaris") class NisTests(unittest.TestCase): def test_maps(self): @@ -12,7 +12,7 @@ # NIS is probably not active, so this test isn't useful if support.verbose: print("Test Skipped:", msg) - # Can't raise TestSkipped as regrtest only recognizes the exception + # Can't raise SkipTest as regrtest only recognizes the exception # import time. return try: Modified: python/branches/py3k/Lib/test/test_openpty.py ============================================================================== --- python/branches/py3k/Lib/test/test_openpty.py (original) +++ python/branches/py3k/Lib/test/test_openpty.py Sat Mar 28 22:42:05 2009 @@ -1,10 +1,10 @@ # Test to see if openpty works. (But don't worry if it isn't available.) import os, unittest -from test.support import run_unittest, TestSkipped +from test.support import run_unittest if not hasattr(os, "openpty"): - raise TestSkipped("No openpty() available.") + raise unittest.SkipTest("No openpty() available.") class OpenptyTest(unittest.TestCase): Modified: python/branches/py3k/Lib/test/test_ossaudiodev.py ============================================================================== --- python/branches/py3k/Lib/test/test_ossaudiodev.py (original) +++ python/branches/py3k/Lib/test/test_ossaudiodev.py Sat Mar 28 22:42:05 2009 @@ -1,7 +1,7 @@ from test import support support.requires('audio') -from test.support import findfile, TestSkipped +from test.support import findfile import errno import ossaudiodev @@ -46,7 +46,7 @@ except IOError as msg: if msg.args[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): - raise TestSkipped(msg) + raise unittest.SkipTest(msg) raise # at least check that these methods can be invoked @@ -165,7 +165,7 @@ except (ossaudiodev.error, IOError) as msg: if msg.args[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY): - raise TestSkipped(msg) + raise unittest.SkipTest(msg) raise dsp.close() support.run_unittest(__name__) Modified: python/branches/py3k/Lib/test/test_pep277.py ============================================================================== --- python/branches/py3k/Lib/test/test_pep277.py (original) +++ python/branches/py3k/Lib/test/test_pep277.py Sat Mar 28 22:42:05 2009 @@ -3,7 +3,7 @@ import sys, os, unittest from test import support if not os.path.supports_unicode_filenames: - raise support.TestSkipped("test works only on NT+") + raise unittest.SkipTest("test works only on NT+") filenames = [ 'abc', Modified: python/branches/py3k/Lib/test/test_pipes.py ============================================================================== --- python/branches/py3k/Lib/test/test_pipes.py (original) +++ python/branches/py3k/Lib/test/test_pipes.py Sat Mar 28 22:42:05 2009 @@ -2,10 +2,10 @@ import os import string import unittest -from test.support import TESTFN, run_unittest, unlink, TestSkipped +from test.support import TESTFN, run_unittest, unlink if os.name != 'posix': - raise TestSkipped('pipes module only works on posix') + raise unittest.SkipTest('pipes module only works on posix') TESTFN2 = TESTFN + "2" Modified: python/branches/py3k/Lib/test/test_platform.py ============================================================================== --- python/branches/py3k/Lib/test/test_platform.py (original) +++ python/branches/py3k/Lib/test/test_platform.py Sat Mar 28 22:42:05 2009 @@ -48,25 +48,73 @@ def test_processor(self): res = platform.processor() - def test_python_implementation(self): - res = platform.python_implementation() + def setUp(self): + self.save_version = sys.version + self.save_subversion = sys.subversion + self.save_platform = sys.platform + + def tearDown(self): + sys.version = self.save_version + sys.subversion = self.save_subversion + sys.platform = self.save_platform - def test_python_version(self): - res1 = platform.python_version() - res2 = platform.python_version_tuple() - self.assertEqual(res1, ".".join(res2)) - - def test_python_branch(self): - res = platform.python_branch() - - def test_python_revision(self): - res = platform.python_revision() - - def test_python_build(self): - res = platform.python_build() + def test_sys_version(self): + # Old test. + for input, output in ( + ('2.4.3 (#1, Jun 21 2006, 13:54:21) \n[GCC 3.3.4 (pre 3.3.5 20040809)]', + ('CPython', '2.4.3', '', '', '1', 'Jun 21 2006 13:54:21', 'GCC 3.3.4 (pre 3.3.5 20040809)')), + ('IronPython 1.0.60816 on .NET 2.0.50727.42', + ('IronPython', '1.0.60816', '', '', '', '', '.NET 2.0.50727.42')), + ('IronPython 1.0 (1.0.61005.1977) on .NET 2.0.50727.42', + ('IronPython', '1.0.0', '', '', '', '', '.NET 2.0.50727.42')), + ): + # branch and revision are not "parsed", but fetched + # from sys.subversion. Ignore them + (name, version, branch, revision, buildno, builddate, compiler) \ + = platform._sys_version(input) + self.assertEqual( + (name, version, '', '', buildno, builddate, compiler), output) - def test_python_compiler(self): - res = platform.python_compiler() + # Tests for python_implementation(), python_version(), python_branch(), + # python_revision(), python_build(), and python_compiler(). + sys_versions = { + ("2.6.1 (r261:67515, Dec 6 2008, 15:26:00) \n[GCC 4.0.1 (Apple Computer, Inc. build 5370)]", + ('CPython', 'tags/r261', '67515'), self.save_platform) + : + ("CPython", "2.6.1", "tags/r261", "67515", + ('r261:67515', 'Dec 6 2008 15:26:00'), + 'GCC 4.0.1 (Apple Computer, Inc. build 5370)'), + ("IronPython 2.0 (2.0.0.0) on .NET 2.0.50727.3053", None, "cli") + : + ("IronPython", "2.0.0", "", "", ("", ""), + ".NET 2.0.50727.3053"), + ("2.5 (trunk:6107, Mar 26 2009, 13:02:18) \n[Java HotSpot(TM) Client VM (\"Apple Computer, Inc.\")]", + ('Jython', 'trunk', '6107'), "java1.5.0_16") + : + ("Jython", "2.5.0", "trunk", "6107", + ('trunk:6107', 'Mar 26 2009'), "java1.5.0_16"), + ("2.5.2 (63378, Mar 26 2009, 18:03:29)\n[PyPy 1.0.0]", + ('PyPy', 'trunk', '63378'), self.save_platform) + : + ("PyPy", "2.5.2", "trunk", "63378", ('63378', 'Mar 26 2009'), + "") + } + for (version_tag, subversion, sys_platform), info in \ + sys_versions.items(): + sys.version = version_tag + if subversion is None: + if hasattr(sys, "subversion"): + del sys.subversion + else: + sys.subversion = subversion + if sys_platform is not None: + sys.platform = sys_platform + self.assertEqual(platform.python_implementation(), info[0]) + self.assertEqual(platform.python_version(), info[1]) + self.assertEqual(platform.python_branch(), info[2]) + self.assertEqual(platform.python_revision(), info[3]) + self.assertEqual(platform.python_build(), info[4]) + self.assertEqual(platform.python_compiler(), info[5]) def test_system_alias(self): res = platform.system_alias( @@ -140,23 +188,6 @@ ): self.assertEqual(platform._parse_release_file(input), output) - def test_sys_version(self): - - platform._sys_version_cache.clear() - for input, output in ( - ('2.4.3 (#1, Jun 21 2006, 13:54:21) \n[GCC 3.3.4 (pre 3.3.5 20040809)]', - ('CPython', '2.4.3', '', '', '1', 'Jun 21 2006 13:54:21', 'GCC 3.3.4 (pre 3.3.5 20040809)')), - ('IronPython 1.0.60816 on .NET 2.0.50727.42', - ('IronPython', '1.0.60816', '', '', '', '', '.NET 2.0.50727.42')), - ('IronPython 1.0 (1.0.61005.1977) on .NET 2.0.50727.42', - ('IronPython', '1.0.0', '', '', '', '', '.NET 2.0.50727.42')), - ): - # branch and revision are not "parsed", but fetched - # from sys.subversion. Ignore them - (name, version, branch, revision, buildno, builddate, compiler) \ - = platform._sys_version(input) - self.assertEqual( - (name, version, '', '', buildno, builddate, compiler), output) def test_main(): support.run_unittest( Modified: python/branches/py3k/Lib/test/test_poll.py ============================================================================== --- python/branches/py3k/Lib/test/test_poll.py (original) +++ python/branches/py3k/Lib/test/test_poll.py Sat Mar 28 22:42:05 2009 @@ -1,12 +1,12 @@ # Test case for the os.poll() function import os, select, random, unittest -from test.support import TestSkipped, TESTFN, run_unittest +from test.support import TESTFN, run_unittest try: select.poll except AttributeError: - raise TestSkipped("select.poll not defined -- skipping test_poll") + raise unittest.SkipTest("select.poll not defined -- skipping test_poll") def find_ready_matching(ready, flag): Modified: python/branches/py3k/Lib/test/test_posix.py ============================================================================== --- python/branches/py3k/Lib/test/test_posix.py (original) +++ python/branches/py3k/Lib/test/test_posix.py Sat Mar 28 22:42:05 2009 @@ -5,7 +5,7 @@ try: import posix except ImportError: - raise support.TestSkipped("posix is not available") + raise unittest.SkipTest("posix is not available") import time import os @@ -225,17 +225,17 @@ os.mkdir(base_path) os.chdir(base_path) except: -# Just returning nothing instead of the TestSkipped exception, +# Just returning nothing instead of the SkipTest exception, # because the test results in Error in that case. # Is that ok? -# raise support.TestSkipped, "cannot create directory for testing" +# raise unittest.SkipTest("cannot create directory for testing") return def _create_and_do_getcwd(dirname, current_path_length = 0): try: os.mkdir(dirname) except: - raise support.TestSkipped("mkdir cannot create directory sufficiently deep for getcwd test") + raise unittest.SkipTest("mkdir cannot create directory sufficiently deep for getcwd test") os.chdir(dirname) try: Modified: python/branches/py3k/Lib/test/test_pty.py ============================================================================== --- python/branches/py3k/Lib/test/test_pty.py (original) +++ python/branches/py3k/Lib/test/test_pty.py Sat Mar 28 22:42:05 2009 @@ -4,7 +4,7 @@ import os import sys import signal -from test.support import verbose, TestSkipped, run_unittest +from test.support import verbose, run_unittest import unittest TEST_STRING_1 = b"I wish to buy a fish license.\n" @@ -69,7 +69,7 @@ debug("Got slave_fd '%d'" % slave_fd) except OSError: # " An optional feature could not be imported " ... ? - raise TestSkipped("Pseudo-terminals (seemingly) not functional.") + raise unittest.SkipTest("Pseudo-terminals (seemingly) not functional.") self.assertTrue(os.isatty(slave_fd), 'slave_fd is not a tty') Modified: python/branches/py3k/Lib/test/test_signal.py ============================================================================== --- python/branches/py3k/Lib/test/test_signal.py (original) +++ python/branches/py3k/Lib/test/test_signal.py Sat Mar 28 22:42:05 2009 @@ -10,7 +10,7 @@ import sys, os, time, errno if sys.platform[:3] in ('win', 'os2') or sys.platform == 'riscos': - raise support.TestSkipped("Can't test signal on %s" % \ + raise unittest.SkipTest("Can't test signal on %s" % \ sys.platform) Modified: python/branches/py3k/Lib/test/test_site.py ============================================================================== --- python/branches/py3k/Lib/test/test_site.py (original) +++ python/branches/py3k/Lib/test/test_site.py Sat Mar 28 22:42:05 2009 @@ -5,7 +5,7 @@ """ import unittest -from test.support import TestSkipped, run_unittest, TESTFN +from test.support import run_unittest, TESTFN import builtins import os import sys @@ -17,7 +17,7 @@ if "site" in sys.modules: import site else: - raise TestSkipped("importation of site.py suppressed") + raise unittest.SkipTest("importation of site.py suppressed") if not os.path.isdir(site.USER_SITE): # need to add user site directory for tests Modified: python/branches/py3k/Lib/test/test_socketserver.py ============================================================================== --- python/branches/py3k/Lib/test/test_socketserver.py (original) +++ python/branches/py3k/Lib/test/test_socketserver.py Sat Mar 28 22:42:05 2009 @@ -16,7 +16,7 @@ import socketserver import test.support -from test.support import reap_children, verbose, TestSkipped +from test.support import reap_children, verbose from test.support import TESTFN as TEST_FILE test.support.requires("network") @@ -247,7 +247,7 @@ def test_main(): if imp.lock_held(): # If the import lock is held, the threads will hang - raise TestSkipped("can't run when import lock is held") + raise unittest.SkipTest("can't run when import lock is held") test.support.run_unittest(SocketServerTest) Modified: python/branches/py3k/Lib/test/test_sqlite.py ============================================================================== --- python/branches/py3k/Lib/test/test_sqlite.py (original) +++ python/branches/py3k/Lib/test/test_sqlite.py Sat Mar 28 22:42:05 2009 @@ -1,9 +1,10 @@ -from test.support import run_unittest, TestSkipped +import unittest +from test.support import run_unittest try: import _sqlite3 except ImportError: - raise TestSkipped('no sqlite available') + raise unittest.SkipTest('no sqlite available') from sqlite3.test import (dbapi, types, userfunctions, factory, transactions, hooks, regression, dump) Modified: python/branches/py3k/Lib/test/test_ssl.py ============================================================================== --- python/branches/py3k/Lib/test/test_ssl.py (original) +++ python/branches/py3k/Lib/test/test_ssl.py Sat Mar 28 22:42:05 2009 @@ -1161,7 +1161,7 @@ def test_main(verbose=False): if skip_expected: - raise support.TestSkipped("No SSL support") + raise unittest.SkipTest("No SSL support") global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, Modified: python/branches/py3k/Lib/test/test_tempfile.py ============================================================================== --- python/branches/py3k/Lib/test/test_tempfile.py (original) +++ python/branches/py3k/Lib/test/test_tempfile.py Sat Mar 28 22:42:05 2009 @@ -259,7 +259,7 @@ def test_file_mode(self): # _mkstemp_inner creates files with the proper mode if not has_stat: - return # ugh, can't use TestSkipped. + return # ugh, can't use SkipTest. file = self.do_create() mode = stat.S_IMODE(os.stat(file.name).st_mode) @@ -274,7 +274,7 @@ def test_noinherit(self): # _mkstemp_inner file handles are not inherited by child processes if not has_spawnl: - return # ugh, can't use TestSkipped. + return # ugh, can't use SkipTest. if support.verbose: v="v" @@ -312,7 +312,7 @@ def test_textmode(self): # _mkstemp_inner can create files in text mode if not has_textmode: - return # ugh, can't use TestSkipped. + return # ugh, can't use SkipTest. self.do_create(bin=0).write(b"blat\n") # XXX should test that the file really is a text file @@ -476,7 +476,7 @@ def test_mode(self): # mkdtemp creates directories with the proper mode if not has_stat: - return # ugh, can't use TestSkipped. + return # ugh, can't use SkipTest. dir = self.do_create() try: Modified: python/branches/py3k/Lib/test/test_threaded_import.py ============================================================================== --- python/branches/py3k/Lib/test/test_threaded_import.py (original) +++ python/branches/py3k/Lib/test/test_threaded_import.py Sat Mar 28 22:42:05 2009 @@ -6,7 +6,7 @@ # randrange, and then Python hangs. import _thread as thread -from test.support import verbose, TestSkipped, TestFailed +from test.support import verbose, TestFailed critical_section = thread.allocate_lock() done = thread.allocate_lock() @@ -56,7 +56,7 @@ import imp if imp.lock_held(): # This triggers on, e.g., from test import autotest. - raise TestSkipped("can't run when import lock is held") + raise unittest.SkipTest("can't run when import lock is held") done.acquire() for N in (20, 50) * 3: Modified: python/branches/py3k/Lib/test/test_threadsignals.py ============================================================================== --- python/branches/py3k/Lib/test/test_threadsignals.py (original) +++ python/branches/py3k/Lib/test/test_threadsignals.py Sat Mar 28 22:42:05 2009 @@ -5,10 +5,10 @@ import signal import os import sys -from test.support import run_unittest, TestSkipped +from test.support import run_unittest -if sys.platform[:3] in ('win', 'os2'): - raise TestSkipped("Can't test signal on %s" % sys.platform) +if sys.platform[:3] in ('win', 'os2') or sys.platform=='riscos': + raise unittest.SkipTest("Can't test signal on %s" % sys.platform) process_pid = os.getpid() signalled_all=thread.allocate_lock() Modified: python/branches/py3k/Lib/test/test_tk.py ============================================================================== --- python/branches/py3k/Lib/test/test_tk.py (original) +++ python/branches/py3k/Lib/test/test_tk.py Sat Mar 28 22:42:05 2009 @@ -1,12 +1,13 @@ import tkinter from tkinter.test import runtktests from test import support +import unittest try: tkinter.Button() except tkinter.TclError as msg: # assuming tk is not available - raise support.TestSkipped("tk not available: %s" % msg) + raise unittest.SkipTest("tk not available: %s" % msg) def test_main(enable_gui=False): if enable_gui: Modified: python/branches/py3k/Lib/test/test_ttk_guionly.py ============================================================================== --- python/branches/py3k/Lib/test/test_ttk_guionly.py (original) +++ python/branches/py3k/Lib/test/test_ttk_guionly.py Sat Mar 28 22:42:05 2009 @@ -2,6 +2,7 @@ import sys from tkinter import ttk from tkinter.test import runtktests +import unittest from _tkinter import TclError from test import support @@ -9,7 +10,7 @@ ttk.Button() except TclError as msg: # assuming ttk is not available - raise support.TestSkipped("ttk not available: %s" % msg) + raise unittest.SkipTest("ttk not available: %s" % msg) def test_main(enable_gui=False): if enable_gui: Modified: python/branches/py3k/Lib/test/test_unicode_file.py ============================================================================== --- python/branches/py3k/Lib/test/test_unicode_file.py (original) +++ python/branches/py3k/Lib/test/test_unicode_file.py Sat Mar 28 22:42:05 2009 @@ -5,14 +5,14 @@ import unicodedata import unittest -from test.support import run_unittest, TestSkipped, TESTFN_UNICODE, rmtree +from test.support import run_unittest, TESTFN_UNICODE, rmtree from test.support import TESTFN_ENCODING, TESTFN_UNICODE_UNENCODEABLE try: TESTFN_UNICODE.encode(TESTFN_ENCODING) except (UnicodeError, TypeError): # Either the file system encoding is None, or the file name # cannot be encoded in the file system encoding. - raise TestSkipped("No Unicode filesystem semantics on this platform") + raise unittest.SkipTest("No Unicode filesystem semantics on this platform.") def remove_if_exists(filename): if os.path.exists(filename): Modified: python/branches/py3k/Lib/test/test_unittest.py ============================================================================== --- python/branches/py3k/Lib/test/test_unittest.py (original) +++ python/branches/py3k/Lib/test/test_unittest.py Sat Mar 28 22:42:05 2009 @@ -2304,7 +2304,7 @@ def test_skipping(self): class Foo(unittest.TestCase): def test_skip_me(self): - self.skip("skip") + self.skipTest("skip") events = [] result = LoggingResult(events) test = Foo("test_skip_me") @@ -2315,7 +2315,7 @@ # Try letting setUp skip the test now. class Foo(unittest.TestCase): def setUp(self): - self.skip("testing") + self.skipTest("testing") def test_nothing(self): pass events = [] result = LoggingResult(events) Modified: python/branches/py3k/Lib/test/test_univnewlines.py ============================================================================== --- python/branches/py3k/Lib/test/test_univnewlines.py (original) +++ python/branches/py3k/Lib/test/test_univnewlines.py Sat Mar 28 22:42:05 2009 @@ -7,8 +7,8 @@ from test import support if not hasattr(sys.stdin, 'newlines'): - raise support.TestSkipped( - "This Python does not have universal newline support") + raise unittest.SkipTest( + "This Python does not have universal newline support") FATX = 'x' * (2**14) Modified: python/branches/py3k/Lib/test/test_wait3.py ============================================================================== --- python/branches/py3k/Lib/test/test_wait3.py (original) +++ python/branches/py3k/Lib/test/test_wait3.py Sat Mar 28 22:42:05 2009 @@ -3,18 +3,19 @@ import os import time +import unittest from test.fork_wait import ForkWait -from test.support import TestSkipped, run_unittest, reap_children +from test.support import run_unittest, reap_children try: os.fork except AttributeError: - raise TestSkipped("os.fork not defined -- skipping test_wait3") + raise unittest.SkipTest("os.fork not defined -- skipping test_wait3") try: os.wait3 except AttributeError: - raise TestSkipped("os.wait3 not defined -- skipping test_wait3") + raise unittest.SkipTest("os.wait3 not defined -- skipping test_wait3") class Wait3Test(ForkWait): def wait_impl(self, cpid): Modified: python/branches/py3k/Lib/test/test_wait4.py ============================================================================== --- python/branches/py3k/Lib/test/test_wait4.py (original) +++ python/branches/py3k/Lib/test/test_wait4.py Sat Mar 28 22:42:05 2009 @@ -4,17 +4,17 @@ import os import time from test.fork_wait import ForkWait -from test.support import TestSkipped, run_unittest, reap_children +from test.support import run_unittest, reap_children try: os.fork except AttributeError: - raise TestSkipped("os.fork not defined -- skipping test_wait4") + raise unittest.SkipTest("os.fork not defined -- skipping test_wait4") try: os.wait4 except AttributeError: - raise TestSkipped("os.wait4 not defined -- skipping test_wait4") + raise unittest.SkipTest("os.wait4 not defined -- skipping test_wait4") class Wait4Test(ForkWait): def wait_impl(self, cpid): Modified: python/branches/py3k/Lib/traceback.py ============================================================================== --- python/branches/py3k/Lib/traceback.py (original) +++ python/branches/py3k/Lib/traceback.py Sat Mar 28 22:42:05 2009 @@ -274,6 +274,8 @@ def print_last(limit=None, file=None, chain=True): """This is a shorthand for 'print_exception(sys.last_type, sys.last_value, sys.last_traceback, limit, file)'.""" + if not hasattr(sys, "last_type"): + raise ValueError("no last exception") if file is None: file = sys.stderr print_exception(sys.last_type, sys.last_value, sys.last_traceback, Modified: python/branches/py3k/Lib/unittest.py ============================================================================== --- python/branches/py3k/Lib/unittest.py (original) +++ python/branches/py3k/Lib/unittest.py Sat Mar 28 22:42:05 2009 @@ -373,14 +373,14 @@ result.addSkip(self, str(e)) return except Exception: - result.addError(self, self._exc_info()) + result.addError(self, sys.exc_info()) return success = False try: testMethod() except self.failureException: - result.addFailure(self, self._exc_info()) + result.addFailure(self, sys.exc_info()) except _ExpectedFailure as e: result.addExpectedFailure(self, e.exc_info) except _UnexpectedSuccess: @@ -388,14 +388,14 @@ except SkipTest as e: result.addSkip(self, str(e)) except Exception: - result.addError(self, self._exc_info()) + result.addError(self, sys.exc_info()) else: success = True try: self.tearDown() except Exception: - result.addError(self, self._exc_info()) + result.addError(self, sys.exc_info()) success = False if success: result.addSuccess(self) @@ -411,14 +411,7 @@ getattr(self, self._testMethodName)() self.tearDown() - def _exc_info(self): - """Return a version of sys.exc_info() with the traceback frame - minimised; usually the top level of the traceback frame is not - needed. - """ - return sys.exc_info() - - def skip(self, reason): + def skipTest(self, reason): """Skip this test.""" raise SkipTest(reason) @@ -830,7 +823,8 @@ return getattr(self.stream,attr) def writeln(self, arg=None): - if arg: self.write(arg) + if arg: + self.write(arg) self.write('\n') # text-mode streams translate to \r\n if needed @@ -899,7 +893,7 @@ if self.showAll: self.stream.writeln("expected failure") elif self.dots: - self.stream.write(".") + self.stream.write("x") self.stream.flush() def addUnexpectedSuccess(self, test): @@ -907,7 +901,7 @@ if self.showAll: self.stream.writeln("unexpected success") elif self.dots: - self.stream.write(".") + self.stream.write("u") self.stream.flush() def printErrors(self): @@ -964,7 +958,7 @@ if errored: infos.append("errors=%d" % errored) else: - self.stream.writeln("OK") + self.stream.write("OK") if skipped: infos.append("skipped=%d" % skipped) if expectedFails: @@ -973,6 +967,8 @@ infos.append("unexpected successes=%d" % unexpectedSuccesses) if infos: self.stream.writeln(" (%s)" % (", ".join(infos),)) + else: + self.stream.write("\n") return result From buildbot at python.org Sat Mar 28 22:58:37 2009 From: buildbot at python.org (buildbot at python.org) Date: Sat, 28 Mar 2009 21:58:37 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090328215837.7B6E51E400C@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/461 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: antoine.pitrou,guilherme.polo BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_pipes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sat Mar 28 23:16:42 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 28 Mar 2009 23:16:42 +0100 (CET) Subject: [Python-checkins] r70663 - python/branches/py3k/Modules/_textio.c Message-ID: <20090328221642.90DF31E4002@bag.python.org> Author: antoine.pitrou Date: Sat Mar 28 23:16:42 2009 New Revision: 70663 Log: Issue #5592: make the encodefuncs symbol static Modified: python/branches/py3k/Modules/_textio.c Modified: python/branches/py3k/Modules/_textio.c ============================================================================== --- python/branches/py3k/Modules/_textio.c (original) +++ python/branches/py3k/Modules/_textio.c Sat Mar 28 23:16:42 2009 @@ -1,8 +1,8 @@ /* An implementation of Text I/O as defined by PEP 3116 - "New I/O" - + Classes defined here: TextIOBase, IncrementalNewlineDecoder, TextIOWrapper. - + Written by Amaury Forgeot d'Arc and Antoine Pitrou */ @@ -169,7 +169,7 @@ } PyNewLineDecoderObject; static int -IncrementalNewlineDecoder_init(PyNewLineDecoderObject *self, +IncrementalNewlineDecoder_init(PyNewLineDecoderObject *self, PyObject *args, PyObject *kwds) { PyObject *decoder; @@ -215,7 +215,7 @@ #define SEEN_ALL (SEEN_CR | SEEN_LF | SEEN_CRLF) PyObject * -_PyIncrementalNewlineDecoder_decode(PyObject *_self, +_PyIncrementalNewlineDecoder_decode(PyObject *_self, PyObject *input, int final) { PyObject *output; @@ -267,7 +267,7 @@ * then readline() is sure to get \r\n in one pass */ if (!final) { - if (output_len > 0 + if (output_len > 0 && PyUnicode_AS_UNICODE(output)[output_len - 1] == '\r') { if (Py_REFCNT(output) == 1) { @@ -433,7 +433,7 @@ } static PyObject * -IncrementalNewlineDecoder_decode(PyNewLineDecoderObject *self, +IncrementalNewlineDecoder_decode(PyNewLineDecoderObject *self, PyObject *args, PyObject *kwds) { char *kwlist[] = {"input", "final", NULL}; @@ -635,7 +635,7 @@ /* Reads and writes are internally buffered in order to speed things up. However, any read will first flush the write buffer if itsn't empty. - + Please also note that text to be written is first encoded before being buffered. This is necessary so that encoding errors are immediately reported to the caller, but it unfortunately means that the @@ -731,7 +731,7 @@ encodefunc_t encodefunc; } encodefuncentry; -encodefuncentry encodefuncs[] = { +static encodefuncentry encodefuncs[] = { {"ascii", (encodefunc_t) ascii_encode}, {"iso8859-1", (encodefunc_t) latin1_encode}, {"utf-16-be", (encodefunc_t) utf16be_encode}, @@ -942,7 +942,7 @@ self->buffer = buffer; Py_INCREF(buffer); - + if (Py_TYPE(buffer) == &PyBufferedReader_Type || Py_TYPE(buffer) == &PyBufferedWriter_Type || Py_TYPE(buffer) == &PyBufferedRandom_Type) { @@ -1084,7 +1084,7 @@ return NULL; } -/* Flush the internal write buffer. This doesn't explicitly flush the +/* Flush the internal write buffer. This doesn't explicitly flush the underlying buffered object, though. */ static int _TextIOWrapper_writeflush(PyTextIOWrapperObject *self) @@ -1177,7 +1177,7 @@ if (_TextIOWrapper_writeflush(self) < 0) return NULL; } - + if (needflush) { ret = PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_flush, NULL); if (ret == NULL) From python-checkins at python.org Sun Mar 29 01:45:26 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 29 Mar 2009 01:45:26 +0100 (CET) Subject: [Python-checkins] r70664 - in python/branches/py3k: Misc/NEWS Modules/_fileio.c Message-ID: <20090329004526.BDA1F1E400C@bag.python.org> Author: antoine.pitrou Date: Sun Mar 29 01:45:26 2009 New Revision: 70664 Log: Issue #1174606: Calling read() without arguments of an unbounded file (typically /dev/zero under Unix) could crash the interpreter. No test as there always seems to be a risk of putting the machine on its knees. Modified: python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_fileio.c Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Mar 29 01:45:26 2009 @@ -43,6 +43,9 @@ Library ------- +- Issue #1174606: Calling read() without arguments of an unbounded file + (typically /dev/zero under Unix) could crash the interpreter. + - The max_buffer_size arguments of io.BufferedWriter, io.BufferedRWPair, and io.BufferedRandom have been deprecated for removal in Python 3.2. Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Sun Mar 29 01:45:26 2009 @@ -502,9 +502,14 @@ if (fstat(self->fd, &st) == 0) { end = st.st_size; pos = lseek(self->fd, 0L, SEEK_CUR); - if (end >= pos && pos >= 0) + /* Files claiming a size smaller than SMALLCHUNK may + actually be streaming pseudo-files. In this case, we + apply the more aggressive algorithm below. + */ + if (end >= SMALLCHUNK && pos >= 0) { + /* Add 1 so if the file were to grow we'd notice. */ return currentsize + end - pos + 1; - /* Add 1 so if the file were to grow we'd notice. */ + } } #endif if (currentsize > SMALLCHUNK) { @@ -533,7 +538,13 @@ return NULL; while (1) { - Py_ssize_t newsize = new_buffersize(self, total); + size_t newsize = new_buffersize(self, total); + if (newsize > PY_SSIZE_T_MAX || newsize <= 0) { + PyErr_SetString(PyExc_OverflowError, + "unbounded read returned more bytes " + "than a Python string can hold "); + return NULL; + } if (PyBytes_GET_SIZE(result) < newsize) { if (_PyBytes_Resize(&result, newsize) < 0) { From python-checkins at python.org Sun Mar 29 01:57:21 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 29 Mar 2009 01:57:21 +0100 (CET) Subject: [Python-checkins] r70665 - in python/branches/release30-maint: Misc/NEWS Modules/_fileio.c Message-ID: <20090329005721.0EF611E400C@bag.python.org> Author: antoine.pitrou Date: Sun Mar 29 01:57:20 2009 New Revision: 70665 Log: Merged revisions 70664 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70664 | antoine.pitrou | 2009-03-29 01:45:26 +0100 (dim., 29 mars 2009) | 6 lines Issue #1174606: Calling read() without arguments of an unbounded file (typically /dev/zero under Unix) could crash the interpreter. No test as there always seems to be a risk of putting the machine on its knees. ........ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Misc/NEWS python/branches/release30-maint/Modules/_fileio.c Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Sun Mar 29 01:57:20 2009 @@ -26,6 +26,9 @@ Library ------- +- Issue #1174606: Calling read() without arguments of an unbounded file + (typically /dev/zero under Unix) could crash the interpreter. + - Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop forever on incomplete input. That caused tarfile.open() to hang when used with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or Modified: python/branches/release30-maint/Modules/_fileio.c ============================================================================== --- python/branches/release30-maint/Modules/_fileio.c (original) +++ python/branches/release30-maint/Modules/_fileio.c Sun Mar 29 01:57:20 2009 @@ -451,7 +451,7 @@ return NULL; while (1) { - Py_ssize_t newsize = (total < SMALLCHUNK) ? SMALLCHUNK : total; + size_t newsize = (total < SMALLCHUNK) ? SMALLCHUNK : total; /* Keep doubling until we reach BIGCHUNK; then keep adding BIGCHUNK. */ @@ -459,9 +459,14 @@ newsize += newsize; } else { - /* NOTE: overflow impossible due to limits on BUFSIZ */ newsize += BIGCHUNK; } + if (newsize > PY_SSIZE_T_MAX || newsize <= 0) { + PyErr_SetString(PyExc_OverflowError, + "unbounded read returned more bytes " + "than a Python string can hold "); + return NULL; + } if (PyBytes_GET_SIZE(result) < newsize) { if (_PyBytes_Resize(&result, newsize) < 0) { From python-checkins at python.org Sun Mar 29 03:09:52 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 29 Mar 2009 03:09:52 +0200 (CEST) Subject: [Python-checkins] r70666 - python/branches/py3k/Modules/_fileio.c Message-ID: <20090329010952.67DD01E4002@bag.python.org> Author: antoine.pitrou Date: Sun Mar 29 03:09:51 2009 New Revision: 70666 Log: Restore a conditional I removed by mistake. Modified: python/branches/py3k/Modules/_fileio.c Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Sun Mar 29 03:09:51 2009 @@ -506,7 +506,7 @@ actually be streaming pseudo-files. In this case, we apply the more aggressive algorithm below. */ - if (end >= SMALLCHUNK && pos >= 0) { + if (end >= SMALLCHUNK && end >= pos && pos >= 0) { /* Add 1 so if the file were to grow we'd notice. */ return currentsize + end - pos + 1; } From python-checkins at python.org Sun Mar 29 03:10:15 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 29 Mar 2009 03:10:15 +0200 (CEST) Subject: [Python-checkins] r70667 - python/branches/release30-maint Message-ID: <20090329011015.21FC11E4002@bag.python.org> Author: antoine.pitrou Date: Sun Mar 29 03:10:14 2009 New Revision: 70667 Log: Blocked revisions 70666 via svnmerge ........ r70666 | antoine.pitrou | 2009-03-29 03:09:51 +0200 (dim., 29 mars 2009) | 3 lines Restore a conditional I removed by mistake. ........ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Sun Mar 29 03:15:10 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 01:15:10 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090329011511.324C81E4037@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/531 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_slice make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sun Mar 29 04:59:33 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 02:59:33 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090329025933.A05281E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/229 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: 3 tests failed: test_distutils test_posix test_subprocess ====================================================================== FAIL: test_get_python_inc (distutils.tests.test_sysconfig.SysconfigTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/distutils/tests/test_sysconfig.py", line 45, in test_get_python_inc self.assert_(os.path.isdir(inc_dir), inc_dir) AssertionError: /home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/Include ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_subprocess.py", line 115, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From python-checkins at python.org Sun Mar 29 05:16:57 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 29 Mar 2009 05:16:57 +0200 (CEST) Subject: [Python-checkins] r70668 - python/trunk/Doc/library/unittest.rst Message-ID: <20090329031657.E52D11E4002@bag.python.org> Author: benjamin.peterson Date: Sun Mar 29 05:16:57 2009 New Revision: 70668 Log: a more realistic example Modified: python/trunk/Doc/library/unittest.rst Modified: python/trunk/Doc/library/unittest.rst ============================================================================== --- python/trunk/Doc/library/unittest.rst (original) +++ python/trunk/Doc/library/unittest.rst Sun Mar 29 05:16:57 2009 @@ -447,12 +447,26 @@ def test_nothing(self): self.fail("shouldn't happen") + @unittest.skipIf(mylib.__version__ < (1, 3), "not supported in this library version") + def test_format(self): + # 2.6+ only code here. + pass + + @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") + def test_windows_support(self): + # windows specific testing code + pass + This is the output of running the example above in verbose mode: :: + test_format (__main__.MyTestCase) ... skipped 'not supported in this Python version' test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping' + test_windows_support (__main__.MyTestCase) ... skipped 'requires Windows' ---------------------------------------------------------------------- - Ran 1 test in 0.072s + Ran 3 tests in 0.005s + + OK (skipped=3) Classes can be skipped just like methods: :: From python-checkins at python.org Sun Mar 29 05:31:40 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 29 Mar 2009 05:31:40 +0200 (CEST) Subject: [Python-checkins] r70669 - python/trunk/Doc/library/unittest.rst Message-ID: <20090329033140.906D71E4002@bag.python.org> Author: benjamin.peterson Date: Sun Mar 29 05:31:40 2009 New Revision: 70669 Log: stop the versionchanged directive from hiding the docs Modified: python/trunk/Doc/library/unittest.rst Modified: python/trunk/Doc/library/unittest.rst ============================================================================== --- python/trunk/Doc/library/unittest.rst (original) +++ python/trunk/Doc/library/unittest.rst Sun Mar 29 05:31:40 2009 @@ -672,13 +672,15 @@ To catch any of a group of exceptions, a tuple containing the exception classes may be passed as *exception*. - .. versionchanged:: 2.7 + If *callable* is omitted or None, returns a context manager so that the + code under test can be written inline rather than as a function:: + + with self.failUnlessRaises(some_error_class): + do_something() - If *callable* is omitted or None, returns a context manager so that the - code under test can be written inline rather than as a function:: + .. versionchanged:: 2.7 + Added the ability to use :meth:`assertRaises` as a context manager. - with self.failUnlessRaises(some_error_class): - do_something() .. method:: failIf(expr[, msg]) assertFalse(expr[, msg]) From ncoghlan at gmail.com Sun Mar 29 05:36:51 2009 From: ncoghlan at gmail.com (Nick Coghlan) Date: Sun, 29 Mar 2009 13:36:51 +1000 Subject: [Python-checkins] r70668 - python/trunk/Doc/library/unittest.rst In-Reply-To: <20090329031657.E52D11E4002@bag.python.org> References: <20090329031657.E52D11E4002@bag.python.org> Message-ID: <49CEECD3.6070901@gmail.com> benjamin.peterson wrote: > Author: benjamin.peterson > Date: Sun Mar 29 05:16:57 2009 > New Revision: 70668 > > Log: > a more realistic example > > Modified: > python/trunk/Doc/library/unittest.rst > > Modified: python/trunk/Doc/library/unittest.rst > ============================================================================== > --- python/trunk/Doc/library/unittest.rst (original) > +++ python/trunk/Doc/library/unittest.rst Sun Mar 29 05:16:57 2009 > @@ -447,12 +447,26 @@ > def test_nothing(self): > self.fail("shouldn't happen") > > + @unittest.skipIf(mylib.__version__ < (1, 3), "not supported in this library version") Judging by the rest of the example, was that line meant to be: @unittest.skipIf(sys.version_info < (2, 6), "not supported in this Python version") Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- From python-checkins at python.org Sun Mar 29 05:37:58 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 29 Mar 2009 05:37:58 +0200 (CEST) Subject: [Python-checkins] r70670 - peps/trunk/pep-0227.txt Message-ID: <20090329033758.D33A31E4002@bag.python.org> Author: benjamin.peterson Date: Sun Mar 29 05:37:58 2009 New Revision: 70670 Log: this was only implemented about 8 years ago Modified: peps/trunk/pep-0227.txt Modified: peps/trunk/pep-0227.txt ============================================================================== --- peps/trunk/pep-0227.txt (original) +++ peps/trunk/pep-0227.txt Sun Mar 29 05:37:58 2009 @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: jeremy at alum.mit.edu (Jeremy Hylton) -Status: Draft +Status: Final Type: Standards Track Created: 01-Nov-2000 Python-Version: 2.1 From python-checkins at python.org Sun Mar 29 05:39:58 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 29 Mar 2009 05:39:58 +0200 (CEST) Subject: [Python-checkins] r70671 - python/trunk/Doc/library/unittest.rst Message-ID: <20090329033958.A50D71E4002@bag.python.org> Author: benjamin.peterson Date: Sun Mar 29 05:39:58 2009 New Revision: 70671 Log: fix consistency Modified: python/trunk/Doc/library/unittest.rst Modified: python/trunk/Doc/library/unittest.rst ============================================================================== --- python/trunk/Doc/library/unittest.rst (original) +++ python/trunk/Doc/library/unittest.rst Sun Mar 29 05:39:58 2009 @@ -449,7 +449,7 @@ @unittest.skipIf(mylib.__version__ < (1, 3), "not supported in this library version") def test_format(self): - # 2.6+ only code here. + # Tests that work for only a certain version of the library. pass @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") @@ -459,7 +459,7 @@ This is the output of running the example above in verbose mode: :: - test_format (__main__.MyTestCase) ... skipped 'not supported in this Python version' + test_format (__main__.MyTestCase) ... skipped 'not supported in this library version' test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping' test_windows_support (__main__.MyTestCase) ... skipped 'requires Windows' From python-checkins at python.org Sun Mar 29 05:44:19 2009 From: python-checkins at python.org (collin.winter) Date: Sun, 29 Mar 2009 05:44:19 +0200 (CEST) Subject: [Python-checkins] r70672 - python/trunk/Lib/test/regrtest.py Message-ID: <20090329034419.943971E4002@bag.python.org> Author: collin.winter Date: Sun Mar 29 05:44:19 2009 New Revision: 70672 Log: Add the ability to control the random seed used by regrtest.py -r. This adds a --randseed option, and makes regrtest.py -r indicate what random seed it's using so that that value can later be fed back to --randseed. This option is useful for tracking down test order-related issues found by make buildbottest, for example. Modified: python/trunk/Lib/test/regrtest.py Modified: python/trunk/Lib/test/regrtest.py ============================================================================== --- python/trunk/Lib/test/regrtest.py (original) +++ python/trunk/Lib/test/regrtest.py Sun Mar 29 05:44:19 2009 @@ -31,6 +31,10 @@ unless -x is given, in which case they are names for tests not to run. If no test names are given, all tests are run. +-r randomizes test execution order. You can use --randseed=int to provide a +int seed value for the randomizer; this is useful for reproducing troublesome +test orders. + -T turns on code coverage tracing with the trace module. -D specifies the directory where coverage files are put. @@ -183,7 +187,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, exclude=False, single=False, randomize=False, fromfile=None, findleaks=False, use_resources=None, trace=False, coverdir='coverage', - runleaks=False, huntrleaks=False, verbose2=False, print_slow=False): + runleaks=False, huntrleaks=False, verbose2=False, print_slow=False, + random_seed=None): """Execute a test suite. This also parses command-line options and modifies its behavior @@ -201,8 +206,8 @@ files beginning with test_ will be used. The other default arguments (verbose, quiet, exclude, - single, randomize, findleaks, use_resources, trace, coverdir, and - print_slow) allow programmers calling main() directly to set the + single, randomize, findleaks, use_resources, trace, coverdir, print_slow and + random_seed) allow programmers calling main() directly to set the values that would normally be set by flags on the command line. """ @@ -214,11 +219,14 @@ 'findleaks', 'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir', 'runleaks', 'huntrleaks=', 'verbose2', 'memlimit=', + 'randseed=' ]) except getopt.error, msg: usage(2, msg) # Defaults + if random_seed is None: + random_seed = random.randrange(10000000) if use_resources is None: use_resources = [] for o, a in opts: @@ -239,6 +247,8 @@ print_slow = True elif o in ('-r', '--randomize'): randomize = True + elif o == '--randseed': + random_seed = int(a) elif o in ('-f', '--fromfile'): fromfile = a elif o in ('-l', '--findleaks'): @@ -347,6 +357,8 @@ if single: tests = tests[:1] if randomize: + random.seed(random_seed) + print "Using random seed", random_seed random.shuffle(tests) if trace: import trace From python-checkins at python.org Sun Mar 29 06:05:05 2009 From: python-checkins at python.org (collin.winter) Date: Sun, 29 Mar 2009 06:05:05 +0200 (CEST) Subject: [Python-checkins] r70673 - python/branches/py3k/Lib/test/regrtest.py Message-ID: <20090329040505.8DBE01E4002@bag.python.org> Author: collin.winter Date: Sun Mar 29 06:05:05 2009 New Revision: 70673 Log: Port r70672 to py3k. Add the ability to control the random seed used by regrtest.py -r. Modified: python/branches/py3k/Lib/test/regrtest.py Modified: python/branches/py3k/Lib/test/regrtest.py ============================================================================== --- python/branches/py3k/Lib/test/regrtest.py (original) +++ python/branches/py3k/Lib/test/regrtest.py Sun Mar 29 06:05:05 2009 @@ -35,6 +35,10 @@ -v is incompatible with -g and does not compare test output files. +-r randomizes test execution order. You can use --randseed=int to provide a +int seed value for the randomizer; this is useful for reproducing troublesome +test orders. + -T turns on code coverage tracing with the trace module. -D specifies the directory where coverage files are put. @@ -191,7 +195,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, generate=False, exclude=False, single=False, randomize=False, fromfile=None, findleaks=False, use_resources=None, trace=False, coverdir='coverage', - runleaks=False, huntrleaks=False, verbose2=False, print_slow=False): + runleaks=False, huntrleaks=False, verbose2=False, print_slow=False, + random_seed=None): """Execute a test suite. This also parses command-line options and modifies its behavior @@ -209,9 +214,10 @@ files beginning with test_ will be used. The other default arguments (verbose, quiet, generate, exclude, - single, randomize, findleaks, use_resources, trace, coverdir, and - print_slow) allow programmers calling main() directly to set the - values that would normally be set by flags on the command line. + single, randomize, findleaks, use_resources, trace, coverdir, + print_slow, and random_seed) allow programmers calling main() + directly to set the values that would normally be set by flags + on the command line. """ support.record_original_stdout(sys.stdout) @@ -222,12 +228,15 @@ 'findleaks', 'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir', 'runleaks', 'huntrleaks=', 'verbose2', 'memlimit=', - 'debug', 'start=', "nowindows" + 'debug', 'start=', 'nowindows', + 'randseed=', ]) except getopt.error as msg: usage(msg) # Defaults + if random_seed is None: + random_seed = random.randrange(10000000) if use_resources is None: use_resources = [] debug = False @@ -255,6 +264,8 @@ print_slow = True elif o in ('-r', '--randomize'): randomize = True + elif o == '--randseed': + random_seed = int(a) elif o in ('-f', '--fromfile'): fromfile = a elif o in ('-l', '--findleaks'): @@ -389,6 +400,8 @@ except ValueError: print("Couldn't find starting test (%s), using all tests" % start) if randomize: + random.seed(random_seed) + print("Using random seed", random_seed) random.shuffle(tests) if trace: import trace From buildbot at python.org Sun Mar 29 07:29:11 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 05:29:11 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090329052912.184891E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/509 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: collin.winter BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Sun Mar 29 11:20:41 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 09:20:41 +0000 Subject: [Python-checkins] buildbot failure in x86 XP-4 trunk Message-ID: <20090329092041.B13AC1E4002@bag.python.org> The Buildbot has detected a new failure of x86 XP-4 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20XP-4%20trunk/builds/1994 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: bolen-windows Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson,collin.winter,georg.brandl BUILD FAILED: failed test Excerpt from the test logfile: 3 tests failed: test_fork1 test_posix test_wait4 Traceback (most recent call last): File "../lib/test/regrtest.py", line 564, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "E:\cygwin\home\db3l\buildarea\trunk.bolen-windows\build\lib\test\test_fork1.py", line 12, in raise unittest.SkipTest, "os.fork not defined -- skipping test_fork1" NameError: name 'unittest' is not defined Traceback (most recent call last): File "../lib/test/regrtest.py", line 564, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "E:\cygwin\home\db3l\buildarea\trunk.bolen-windows\build\lib\test\test_posix.py", line 8, in raise unittest.SkipTest, "posix is not available" NameError: name 'unittest' is not defined Traceback (most recent call last): File "../lib/test/regrtest.py", line 564, in runtest_inner the_package = __import__(abstest, globals(), locals(), []) File "E:\cygwin\home\db3l\buildarea\trunk.bolen-windows\build\lib\test\test_wait4.py", line 12, in raise unittest.SkipTest, "os.fork not defined -- skipping test_wait4" NameError: name 'unittest' is not defined sincerely, -The Buildbot From python-checkins at python.org Sun Mar 29 12:19:05 2009 From: python-checkins at python.org (guilherme.polo) Date: Sun, 29 Mar 2009 12:19:05 +0200 (CEST) Subject: [Python-checkins] r70674 - python/trunk/Lib/idlelib/configHandler.py Message-ID: <20090329101905.9ABA71E4002@bag.python.org> Author: guilherme.polo Date: Sun Mar 29 12:19:05 2009 New Revision: 70674 Log: Typo fix. Modified: python/trunk/Lib/idlelib/configHandler.py Modified: python/trunk/Lib/idlelib/configHandler.py ============================================================================== --- python/trunk/Lib/idlelib/configHandler.py (original) +++ python/trunk/Lib/idlelib/configHandler.py Sun Mar 29 12:19:05 2009 @@ -246,7 +246,7 @@ else: #returning default, print warning if warn_on_default: warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n' - ' problem retrieving configration option %r\n' + ' problem retrieving configuration option %r\n' ' from section %r.\n' ' returning default value: %r\n' % (option, section, default)) From python-checkins at python.org Sun Mar 29 14:35:20 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 29 Mar 2009 14:35:20 +0200 (CEST) Subject: [Python-checkins] r70675 - python/branches/py3k Message-ID: <20090329123520.8264D1E4023@bag.python.org> Author: benjamin.peterson Date: Sun Mar 29 14:35:19 2009 New Revision: 70675 Log: Blocked revisions 70672 via svnmerge ........ r70672 | collin.winter | 2009-03-28 22:44:19 -0500 (Sat, 28 Mar 2009) | 4 lines Add the ability to control the random seed used by regrtest.py -r. This adds a --randseed option, and makes regrtest.py -r indicate what random seed it's using so that that value can later be fed back to --randseed. This option is useful for tracking down test order-related issues found by make buildbottest, for example. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Sun Mar 29 15:02:52 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 29 Mar 2009 15:02:52 +0200 (CEST) Subject: [Python-checkins] r70676 - in python/branches/py3k: Lib/ntpath.py Misc/NEWS Message-ID: <20090329130252.6479D1E4002@bag.python.org> Author: benjamin.peterson Date: Sun Mar 29 15:02:52 2009 New Revision: 70676 Log: fix variable name #5595 Modified: python/branches/py3k/Lib/ntpath.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/ntpath.py ============================================================================== --- python/branches/py3k/Lib/ntpath.py (original) +++ python/branches/py3k/Lib/ntpath.py Sun Mar 29 15:02:52 2009 @@ -257,7 +257,7 @@ def ismount(path): """Test whether a path is a mount point (defined as root of drive)""" unc, rest = splitunc(path) - seps = _get_bothseps(p) + seps = _get_bothseps(path) if unc: return rest in p[:0] + seps p = splitdrive(path)[1] Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Mar 29 15:02:52 2009 @@ -43,6 +43,8 @@ Library ------- +- Issue #5595: Fix UnboundedLocalError in ntpath.ismount(). + - Issue #1174606: Calling read() without arguments of an unbounded file (typically /dev/zero under Unix) could crash the interpreter. From python-checkins at python.org Sun Mar 29 15:12:59 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 29 Mar 2009 15:12:59 +0200 (CEST) Subject: [Python-checkins] r70677 - in python/branches/release30-maint: Lib/ntpath.py Misc/NEWS Message-ID: <20090329131259.E74641E4002@bag.python.org> Author: benjamin.peterson Date: Sun Mar 29 15:12:59 2009 New Revision: 70677 Log: Merged revisions 70676 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70676 | benjamin.peterson | 2009-03-29 08:02:52 -0500 (Sun, 29 Mar 2009) | 1 line fix variable name #5595 ........ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/ntpath.py python/branches/release30-maint/Misc/NEWS Modified: python/branches/release30-maint/Lib/ntpath.py ============================================================================== --- python/branches/release30-maint/Lib/ntpath.py (original) +++ python/branches/release30-maint/Lib/ntpath.py Sun Mar 29 15:12:59 2009 @@ -257,7 +257,7 @@ def ismount(path): """Test whether a path is a mount point (defined as root of drive)""" unc, rest = splitunc(path) - seps = _get_bothseps(p) + seps = _get_bothseps(path) if unc: return rest in p[:0] + seps p = splitdrive(path)[1] Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Sun Mar 29 15:12:59 2009 @@ -26,6 +26,8 @@ Library ------- +- Issue #5595: Fix UnboundedLocalError in ntpath.ismount(). + - Issue #1174606: Calling read() without arguments of an unbounded file (typically /dev/zero under Unix) could crash the interpreter. From buildbot at python.org Sun Mar 29 15:47:05 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 13:47:05 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.0 Message-ID: <20090329134706.4A38A1E4026@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.0/builds/204 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sun Mar 29 16:37:52 2009 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Mar 2009 16:37:52 +0200 (CEST) Subject: [Python-checkins] r70678 - in python/trunk: Doc/library/stdtypes.rst Objects/stringlib/formatter.h Objects/stringobject.c Objects/unicodeobject.c Message-ID: <20090329143752.058D51E403E@bag.python.org> Author: mark.dickinson Date: Sun Mar 29 16:37:51 2009 New Revision: 70678 Log: Issue #532631: Replace confusing fabs(x)/1e25 >= 1e25 test with fabs(x) >= 1e50, and fix documentation. Modified: python/trunk/Doc/library/stdtypes.rst python/trunk/Objects/stringlib/formatter.h python/trunk/Objects/stringobject.c python/trunk/Objects/unicodeobject.c Modified: python/trunk/Doc/library/stdtypes.rst ============================================================================== --- python/trunk/Doc/library/stdtypes.rst (original) +++ python/trunk/Doc/library/stdtypes.rst Sun Mar 29 16:37:51 2009 @@ -1409,7 +1409,7 @@ .. XXX Examples? For safety reasons, floating point precisions are clipped to 50; ``%f`` -conversions for numbers whose absolute value is over 1e25 are replaced by ``%g`` +conversions for numbers whose absolute value is over 1e50 are replaced by ``%g`` conversions. [#]_ All other errors raise exceptions. .. index:: Modified: python/trunk/Objects/stringlib/formatter.h ============================================================================== --- python/trunk/Objects/stringlib/formatter.h (original) +++ python/trunk/Objects/stringlib/formatter.h Sun Mar 29 16:37:51 2009 @@ -789,7 +789,7 @@ if (precision < 0) precision = 6; - if (type == 'f' && (fabs(x) / 1e25) >= 1e25) + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* cast "type", because if we're in unicode we need to pass a Modified: python/trunk/Objects/stringobject.c ============================================================================== --- python/trunk/Objects/stringobject.c (original) +++ python/trunk/Objects/stringobject.c Sun Mar 29 16:37:51 2009 @@ -4344,7 +4344,7 @@ } if (prec < 0) prec = 6; - if (type == 'f' && fabs(x)/1e25 >= 1e25) + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* Worst case length calc to ensure no buffer overrun: Modified: python/trunk/Objects/unicodeobject.c ============================================================================== --- python/trunk/Objects/unicodeobject.c (original) +++ python/trunk/Objects/unicodeobject.c Sun Mar 29 16:37:51 2009 @@ -8286,7 +8286,7 @@ return -1; if (prec < 0) prec = 6; - if (type == 'f' && (fabs(x) / 1e25) >= 1e25) + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* Worst case length calc to ensure no buffer overrun: From python-checkins at python.org Sun Mar 29 17:06:29 2009 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Mar 2009 17:06:29 +0200 (CEST) Subject: [Python-checkins] r70679 - in python/branches/release26-maint: Doc/library/stdtypes.rst Objects/stringlib/formatter.h Objects/stringobject.c Objects/unicodeobject.c Message-ID: <20090329150629.AB3831E4002@bag.python.org> Author: mark.dickinson Date: Sun Mar 29 17:06:29 2009 New Revision: 70679 Log: Merged revisions 70678 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70678 | mark.dickinson | 2009-03-29 15:37:51 +0100 (Sun, 29 Mar 2009) | 3 lines Issue #532631: Replace confusing fabs(x)/1e25 >= 1e25 test with fabs(x) >= 1e50, and fix documentation. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/library/stdtypes.rst python/branches/release26-maint/Objects/stringlib/formatter.h python/branches/release26-maint/Objects/stringobject.c python/branches/release26-maint/Objects/unicodeobject.c Modified: python/branches/release26-maint/Doc/library/stdtypes.rst ============================================================================== --- python/branches/release26-maint/Doc/library/stdtypes.rst (original) +++ python/branches/release26-maint/Doc/library/stdtypes.rst Sun Mar 29 17:06:29 2009 @@ -1378,7 +1378,7 @@ .. XXX Examples? For safety reasons, floating point precisions are clipped to 50; ``%f`` -conversions for numbers whose absolute value is over 1e25 are replaced by ``%g`` +conversions for numbers whose absolute value is over 1e50 are replaced by ``%g`` conversions. [#]_ All other errors raise exceptions. .. index:: Modified: python/branches/release26-maint/Objects/stringlib/formatter.h ============================================================================== --- python/branches/release26-maint/Objects/stringlib/formatter.h (original) +++ python/branches/release26-maint/Objects/stringlib/formatter.h Sun Mar 29 17:06:29 2009 @@ -789,7 +789,7 @@ if (precision < 0) precision = 6; - if (type == 'f' && (fabs(x) / 1e25) >= 1e25) + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* cast "type", because if we're in unicode we need to pass a Modified: python/branches/release26-maint/Objects/stringobject.c ============================================================================== --- python/branches/release26-maint/Objects/stringobject.c (original) +++ python/branches/release26-maint/Objects/stringobject.c Sun Mar 29 17:06:29 2009 @@ -4336,7 +4336,7 @@ } if (prec < 0) prec = 6; - if (type == 'f' && fabs(x)/1e25 >= 1e25) + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* Worst case length calc to ensure no buffer overrun: Modified: python/branches/release26-maint/Objects/unicodeobject.c ============================================================================== --- python/branches/release26-maint/Objects/unicodeobject.c (original) +++ python/branches/release26-maint/Objects/unicodeobject.c Sun Mar 29 17:06:29 2009 @@ -8228,7 +8228,7 @@ return -1; if (prec < 0) prec = 6; - if (type == 'f' && (fabs(x) / 1e25) >= 1e25) + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* Worst case length calc to ensure no buffer overrun: From python-checkins at python.org Sun Mar 29 17:19:47 2009 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Mar 2009 17:19:47 +0200 (CEST) Subject: [Python-checkins] r70680 - in python/branches/py3k: Doc/library/stdtypes.rst Objects/stringlib/formatter.h Objects/unicodeobject.c Message-ID: <20090329151947.5ABCE1E4002@bag.python.org> Author: mark.dickinson Date: Sun Mar 29 17:19:47 2009 New Revision: 70680 Log: Merged revisions 70678 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70678 | mark.dickinson | 2009-03-29 15:37:51 +0100 (Sun, 29 Mar 2009) | 3 lines Issue #532631: Replace confusing fabs(x)/1e25 >= 1e25 test with fabs(x) >= 1e50, and fix documentation. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/stdtypes.rst python/branches/py3k/Objects/stringlib/formatter.h python/branches/py3k/Objects/unicodeobject.c Modified: python/branches/py3k/Doc/library/stdtypes.rst ============================================================================== --- python/branches/py3k/Doc/library/stdtypes.rst (original) +++ python/branches/py3k/Doc/library/stdtypes.rst Sun Mar 29 17:19:47 2009 @@ -1322,7 +1322,7 @@ .. XXX Examples? For safety reasons, floating point precisions are clipped to 50; ``%f`` -conversions for numbers whose absolute value is over 1e25 are replaced by ``%g`` +conversions for numbers whose absolute value is over 1e50 are replaced by ``%g`` conversions. [#]_ All other errors raise exceptions. .. index:: Modified: python/branches/py3k/Objects/stringlib/formatter.h ============================================================================== --- python/branches/py3k/Objects/stringlib/formatter.h (original) +++ python/branches/py3k/Objects/stringlib/formatter.h Sun Mar 29 17:19:47 2009 @@ -789,7 +789,7 @@ if (precision < 0) precision = 6; - if (type == 'f' && (fabs(x) / 1e25) >= 1e25) + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* cast "type", because if we're in unicode we need to pass a Modified: python/branches/py3k/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k/Objects/unicodeobject.c (original) +++ python/branches/py3k/Objects/unicodeobject.c Sun Mar 29 17:19:47 2009 @@ -8847,7 +8847,7 @@ return -1; if (prec < 0) prec = 6; - if (type == 'f' && (fabs(x) / 1e25) >= 1e25) + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* Worst case length calc to ensure no buffer overrun: From python-checkins at python.org Sun Mar 29 17:21:46 2009 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Mar 2009 17:21:46 +0200 (CEST) Subject: [Python-checkins] r70681 - in python/branches/release30-maint: Doc/library/stdtypes.rst Objects/stringlib/formatter.h Objects/unicodeobject.c Message-ID: <20090329152146.8AE4B1E4002@bag.python.org> Author: mark.dickinson Date: Sun Mar 29 17:21:46 2009 New Revision: 70681 Log: Merged revisions 70680 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70680 | mark.dickinson | 2009-03-29 16:19:47 +0100 (Sun, 29 Mar 2009) | 10 lines Merged revisions 70678 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70678 | mark.dickinson | 2009-03-29 15:37:51 +0100 (Sun, 29 Mar 2009) | 3 lines Issue #532631: Replace confusing fabs(x)/1e25 >= 1e25 test with fabs(x) >= 1e50, and fix documentation. ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Doc/library/stdtypes.rst python/branches/release30-maint/Objects/stringlib/formatter.h python/branches/release30-maint/Objects/unicodeobject.c Modified: python/branches/release30-maint/Doc/library/stdtypes.rst ============================================================================== --- python/branches/release30-maint/Doc/library/stdtypes.rst (original) +++ python/branches/release30-maint/Doc/library/stdtypes.rst Sun Mar 29 17:21:46 2009 @@ -1322,7 +1322,7 @@ .. XXX Examples? For safety reasons, floating point precisions are clipped to 50; ``%f`` -conversions for numbers whose absolute value is over 1e25 are replaced by ``%g`` +conversions for numbers whose absolute value is over 1e50 are replaced by ``%g`` conversions. [#]_ All other errors raise exceptions. .. index:: Modified: python/branches/release30-maint/Objects/stringlib/formatter.h ============================================================================== --- python/branches/release30-maint/Objects/stringlib/formatter.h (original) +++ python/branches/release30-maint/Objects/stringlib/formatter.h Sun Mar 29 17:21:46 2009 @@ -789,7 +789,7 @@ if (precision < 0) precision = 6; - if (type == 'f' && (fabs(x) / 1e25) >= 1e25) + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* cast "type", because if we're in unicode we need to pass a Modified: python/branches/release30-maint/Objects/unicodeobject.c ============================================================================== --- python/branches/release30-maint/Objects/unicodeobject.c (original) +++ python/branches/release30-maint/Objects/unicodeobject.c Sun Mar 29 17:21:46 2009 @@ -8584,7 +8584,7 @@ return -1; if (prec < 0) prec = 6; - if (type == 'f' && (fabs(x) / 1e25) >= 1e25) + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* Worst case length calc to ensure no buffer overrun: From buildbot at python.org Sun Mar 29 17:48:23 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 15:48:23 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090329154823.AB9C21E4011@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/536 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Alarm clock sincerely, -The Buildbot From buildbot at python.org Sun Mar 29 17:53:21 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 15:53:21 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090329155321.C5D161E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/477 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_smtplib make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Sun Mar 29 18:17:17 2009 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Mar 2009 18:17:17 +0200 (CEST) Subject: [Python-checkins] r70682 - python/trunk/Objects/stringobject.c Message-ID: <20090329161717.603911E4002@bag.python.org> Author: mark.dickinson Date: Sun Mar 29 18:17:16 2009 New Revision: 70682 Log: Issue #532631: Add paranoid check to avoid potential buffer overflow on systems with sizeof(int) > 4. Modified: python/trunk/Objects/stringobject.c Modified: python/trunk/Objects/stringobject.c ============================================================================== --- python/trunk/Objects/stringobject.c (original) +++ python/trunk/Objects/stringobject.c Sun Mar 29 18:17:16 2009 @@ -4344,6 +4344,15 @@ } if (prec < 0) prec = 6; + /* make sure that the decimal representation of precision really does + need at most 10 digits: platforms with sizeof(int) == 8 exist! */ + if (prec > 0x7fffffffL) { + PyErr_SetString(PyExc_OverflowError, + "outrageously large precision " + "for formatted float"); + return -1; + } + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* Worst case length calc to ensure no buffer overrun: @@ -4372,7 +4381,7 @@ PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%d%c", (flags&F_ALT) ? "#" : "", prec, type); - PyOS_ascii_formatd(buf, buflen, fmt, x); + PyOS_ascii_formatd(buf, buflen, fmt, x); return (int)strlen(buf); } From python-checkins at python.org Sun Mar 29 18:18:34 2009 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Mar 2009 18:18:34 +0200 (CEST) Subject: [Python-checkins] r70683 - in python/branches/release26-maint: Objects/stringobject.c Message-ID: <20090329161834.AD02B1E4002@bag.python.org> Author: mark.dickinson Date: Sun Mar 29 18:18:33 2009 New Revision: 70683 Log: Merged revisions 70682 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70682 | mark.dickinson | 2009-03-29 17:17:16 +0100 (Sun, 29 Mar 2009) | 3 lines Issue #532631: Add paranoid check to avoid potential buffer overflow on systems with sizeof(int) > 4. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Objects/stringobject.c Modified: python/branches/release26-maint/Objects/stringobject.c ============================================================================== --- python/branches/release26-maint/Objects/stringobject.c (original) +++ python/branches/release26-maint/Objects/stringobject.c Sun Mar 29 18:18:33 2009 @@ -4336,6 +4336,15 @@ } if (prec < 0) prec = 6; + /* make sure that the decimal representation of precision really does + need at most 10 digits: platforms with sizeof(int) == 8 exist! */ + if (prec > 0x7fffffffL) { + PyErr_SetString(PyExc_OverflowError, + "outrageously large precision " + "for formatted float"); + return -1; + } + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* Worst case length calc to ensure no buffer overrun: @@ -4364,7 +4373,7 @@ PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%d%c", (flags&F_ALT) ? "#" : "", prec, type); - PyOS_ascii_formatd(buf, buflen, fmt, x); + PyOS_ascii_formatd(buf, buflen, fmt, x); return (int)strlen(buf); } From python-checkins at python.org Sun Mar 29 18:24:30 2009 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Mar 2009 18:24:30 +0200 (CEST) Subject: [Python-checkins] r70684 - python/trunk/Objects/unicodeobject.c Message-ID: <20090329162430.33AD41E4002@bag.python.org> Author: mark.dickinson Date: Sun Mar 29 18:24:29 2009 New Revision: 70684 Log: Issue #532631: Apply floatformat changes to unicodeobject.c as well as stringobject.c. Modified: python/trunk/Objects/unicodeobject.c Modified: python/trunk/Objects/unicodeobject.c ============================================================================== --- python/trunk/Objects/unicodeobject.c (original) +++ python/trunk/Objects/unicodeobject.c Sun Mar 29 18:24:29 2009 @@ -8286,6 +8286,15 @@ return -1; if (prec < 0) prec = 6; + /* make sure that the decimal representation of precision really does + need at most 10 digits: platforms with sizeof(int) == 8 exist! */ + if (prec > 0x7fffffffL) { + PyErr_SetString(PyExc_OverflowError, + "outrageously large precision " + "for formatted float"); + return -1; + } + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* Worst case length calc to ensure no buffer overrun: From python-checkins at python.org Sun Mar 29 18:25:47 2009 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Mar 2009 18:25:47 +0200 (CEST) Subject: [Python-checkins] r70685 - in python/branches/release26-maint: Objects/unicodeobject.c Message-ID: <20090329162547.033801E401B@bag.python.org> Author: mark.dickinson Date: Sun Mar 29 18:25:46 2009 New Revision: 70685 Log: Merged revisions 70684 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70684 | mark.dickinson | 2009-03-29 17:24:29 +0100 (Sun, 29 Mar 2009) | 3 lines Issue #532631: Apply floatformat changes to unicodeobject.c as well as stringobject.c. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Objects/unicodeobject.c Modified: python/branches/release26-maint/Objects/unicodeobject.c ============================================================================== --- python/branches/release26-maint/Objects/unicodeobject.c (original) +++ python/branches/release26-maint/Objects/unicodeobject.c Sun Mar 29 18:25:46 2009 @@ -8228,6 +8228,15 @@ return -1; if (prec < 0) prec = 6; + /* make sure that the decimal representation of precision really does + need at most 10 digits: platforms with sizeof(int) == 8 exist! */ + if (prec > 0x7fffffffL) { + PyErr_SetString(PyExc_OverflowError, + "outrageously large precision " + "for formatted float"); + return -1; + } + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* Worst case length calc to ensure no buffer overrun: From python-checkins at python.org Sun Mar 29 18:34:21 2009 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Mar 2009 18:34:21 +0200 (CEST) Subject: [Python-checkins] r70686 - in python/branches/py3k: Objects/unicodeobject.c Message-ID: <20090329163421.78A071E4002@bag.python.org> Author: mark.dickinson Date: Sun Mar 29 18:34:21 2009 New Revision: 70686 Log: Merged revisions 70682,70684 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70682 | mark.dickinson | 2009-03-29 17:17:16 +0100 (Sun, 29 Mar 2009) | 3 lines Issue #532631: Add paranoid check to avoid potential buffer overflow on systems with sizeof(int) > 4. ........ r70684 | mark.dickinson | 2009-03-29 17:24:29 +0100 (Sun, 29 Mar 2009) | 3 lines Issue #532631: Apply floatformat changes to unicodeobject.c as well as stringobject.c. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Objects/unicodeobject.c Modified: python/branches/py3k/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k/Objects/unicodeobject.c (original) +++ python/branches/py3k/Objects/unicodeobject.c Sun Mar 29 18:34:21 2009 @@ -8847,6 +8847,15 @@ return -1; if (prec < 0) prec = 6; + /* make sure that the decimal representation of precision really does + need at most 10 digits: platforms with sizeof(int) == 8 exist! */ + if (prec > 0x7fffffffL) { + PyErr_SetString(PyExc_OverflowError, + "outrageously large precision " + "for formatted float"); + return -1; + } + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* Worst case length calc to ensure no buffer overrun: From python-checkins at python.org Sun Mar 29 18:36:02 2009 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Mar 2009 18:36:02 +0200 (CEST) Subject: [Python-checkins] r70687 - in python/branches/release30-maint: Objects/unicodeobject.c Message-ID: <20090329163602.132D51E4002@bag.python.org> Author: mark.dickinson Date: Sun Mar 29 18:36:01 2009 New Revision: 70687 Log: Merged revisions 70686 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70686 | mark.dickinson | 2009-03-29 17:34:21 +0100 (Sun, 29 Mar 2009) | 15 lines Merged revisions 70682,70684 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70682 | mark.dickinson | 2009-03-29 17:17:16 +0100 (Sun, 29 Mar 2009) | 3 lines Issue #532631: Add paranoid check to avoid potential buffer overflow on systems with sizeof(int) > 4. ........ r70684 | mark.dickinson | 2009-03-29 17:24:29 +0100 (Sun, 29 Mar 2009) | 3 lines Issue #532631: Apply floatformat changes to unicodeobject.c as well as stringobject.c. ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Objects/unicodeobject.c Modified: python/branches/release30-maint/Objects/unicodeobject.c ============================================================================== --- python/branches/release30-maint/Objects/unicodeobject.c (original) +++ python/branches/release30-maint/Objects/unicodeobject.c Sun Mar 29 18:36:01 2009 @@ -8584,6 +8584,15 @@ return -1; if (prec < 0) prec = 6; + /* make sure that the decimal representation of precision really does + need at most 10 digits: platforms with sizeof(int) == 8 exist! */ + if (prec > 0x7fffffffL) { + PyErr_SetString(PyExc_OverflowError, + "outrageously large precision " + "for formatted float"); + return -1; + } + if (type == 'f' && fabs(x) >= 1e50) type = 'g'; /* Worst case length calc to ensure no buffer overrun: From buildbot at python.org Sun Mar 29 18:49:40 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 16:49:40 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090329164941.2AB2B1E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/231 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_distutils test_posix ====================================================================== FAIL: test_get_python_inc (distutils.tests.test_sysconfig.SysconfigTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/distutils/tests/test_sysconfig.py", line 45, in test_get_python_inc self.assert_(os.path.isdir(inc_dir), inc_dir) AssertionError: /home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/Include ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From python-checkins at python.org Sun Mar 29 18:58:22 2009 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Mar 2009 18:58:22 +0200 (CEST) Subject: [Python-checkins] r70688 - in python/branches/py3k: Doc/library/struct.rst Lib/test/test_struct.py Misc/NEWS Modules/_struct.c Message-ID: <20090329165822.101E91E4002@bag.python.org> Author: mark.dickinson Date: Sun Mar 29 18:58:21 2009 New Revision: 70688 Log: Issue #5463: Remove _PY_STRUCT_RANGE_CHECKING constant from struct module, and remove associated code from test_struct. This was a mechanism for skipping some of the tests for overflow behaviour when packing integers; it's no longer necessary. Modified: python/branches/py3k/Doc/library/struct.rst python/branches/py3k/Lib/test/test_struct.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_struct.c Modified: python/branches/py3k/Doc/library/struct.rst ============================================================================== --- python/branches/py3k/Doc/library/struct.rst (original) +++ python/branches/py3k/Doc/library/struct.rst Sun Mar 29 18:58:21 2009 @@ -134,6 +134,16 @@ specified number of bytes. As a special case, ``'0s'`` means a single, empty string (while ``'0c'`` means 0 characters). +When packing a value ``x`` using one of the integer formats (``'b'``, +``'B'``, ``'h'``, ``'H'``, ``'i'``, ``'I'``, ``'l'``, ``'L'``, +``'q'``, ``'Q'``), if ``x`` is outside the valid range for that format +then :exc:`struct.error` is raised. + +.. versionchanged:: 3.1 + In 3.0, some of the integer formats wrapped out-of-range values and + raised :exc:`DeprecationWarning` instead of :exc:`struct.error`. + + The ``'p'`` format character encodes a "Pascal string", meaning a short variable-length string stored in a fixed number of bytes. The count is the total number of bytes stored. The first byte stored is the length of the string, or Modified: python/branches/py3k/Lib/test/test_struct.py ============================================================================== --- python/branches/py3k/Lib/test/test_struct.py (original) +++ python/branches/py3k/Lib/test/test_struct.py Sun Mar 29 18:58:21 2009 @@ -14,10 +14,8 @@ try: import _struct except ImportError: - PY_STRUCT_RANGE_CHECKING = 0 PY_STRUCT_FLOAT_COERCE = 2 else: - PY_STRUCT_RANGE_CHECKING = getattr(_struct, '_PY_STRUCT_RANGE_CHECKING', 0) PY_STRUCT_FLOAT_COERCE = getattr(_struct, '_PY_STRUCT_FLOAT_COERCE', 0) def string_reverse(s): @@ -40,20 +38,6 @@ return func(*args, **kw) return decorator - at with_warning_restore -def deprecated_err(func, *args): - try: - func(*args) - except (struct.error, OverflowError): - pass - except DeprecationWarning: - raise TestFailed("%s%s expected to raise DeprecationWarning" % ( - func.__name__, args)) - else: - raise TestFailed("%s%s did not raise error" % ( - func.__name__, args)) - - class StructTest(unittest.TestCase): @with_warning_restore @@ -222,12 +206,6 @@ class IntTester(unittest.TestCase): - # XXX Most std integer modes fail to test for out-of-range. - # The "i" and "l" codes appear to range-check OK on 32-bit boxes, but - # fail to check correctly on some 64-bit ones (Tru64 Unix + Compaq C - # reported by Mark Favas). - BUGGY_RANGE_CHECK = "bBhHiIlL" - def __init__(self, formatpair, bytesize): self.assertEqual(len(formatpair), 2) self.formatpair = formatpair @@ -291,12 +269,10 @@ else: # x is out of range -- verify pack realizes that. - if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK: - if verbose: - print("Skipping buggy range check for code", code) - else: - deprecated_err(pack, ">" + code, x) - deprecated_err(pack, "<" + code, x) + self.assertRaises((struct.error, OverflowError), + pack, ">" + code, x) + self.assertRaises((struct.error, OverflowError), + pack, "<" + code, x) # Much the same for unsigned. code = self.unsigned_code @@ -340,12 +316,10 @@ else: # x is out of range -- verify pack realizes that. - if not PY_STRUCT_RANGE_CHECKING and code in self.BUGGY_RANGE_CHECK: - if verbose: - print("Skipping buggy range check for code", code) - else: - deprecated_err(pack, ">" + code, x) - deprecated_err(pack, "<" + code, x) + self.assertRaises((struct.error, OverflowError), + pack, ">" + code, x) + self.assertRaises((struct.error, OverflowError), + pack, "<" + code, x) def run(self): from random import randrange @@ -443,20 +417,24 @@ big = math.ldexp(big, 127 - 24) self.assertRaises(OverflowError, struct.pack, ">f", big) - if PY_STRUCT_RANGE_CHECKING: - def test_1229380(self): - # SF bug 1229380. No struct.pack exception for some out of - # range integers - import sys - for endian in ('', '>', '<'): - for fmt in ('B', 'H', 'I', 'L'): - deprecated_err(struct.pack, endian + fmt, -1) - - deprecated_err(struct.pack, endian + 'B', 300) - deprecated_err(struct.pack, endian + 'H', 70000) - - deprecated_err(struct.pack, endian + 'I', sys.maxsize * 4) - deprecated_err(struct.pack, endian + 'L', sys.maxsize * 4) + def test_1229380(self): + # SF bug 1229380. No struct.pack exception for some out of + # range integers + import sys + for endian in ('', '>', '<'): + for fmt in ('B', 'H', 'I', 'L'): + self.assertRaises((struct.error, OverflowError), struct.pack, + endian + fmt, -1) + + self.assertRaises((struct.error, OverflowError), struct.pack, + endian + 'B', 300) + self.assertRaises((struct.error, OverflowError), struct.pack, + endian + 'H', 70000) + + self.assertRaises((struct.error, OverflowError), struct.pack, + endian + 'I', sys.maxsize * 4) + self.assertRaises((struct.error, OverflowError), struct.pack, + endian + 'L', sys.maxsize * 4) def XXXtest_1530559(self): # XXX This is broken: see the bug report Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Mar 29 18:58:21 2009 @@ -73,7 +73,9 @@ - Issue #5463: In struct module, remove deprecated overflow wrapping when packing an integer: struct.pack('=L', -1) now raises - struct.error instead of returning b'\xff\xff\xff\xff'. + struct.error instead of returning b'\xff\xff\xff\xff'. The + _PY_STRUCT_RANGE_CHECKING and _PY_STRUCT_OVERFLOW_MASKING constants + have been removed from the struct module. What's New in Python 3.1 alpha 1 Modified: python/branches/py3k/Modules/_struct.c ============================================================================== --- python/branches/py3k/Modules/_struct.c (original) +++ python/branches/py3k/Modules/_struct.c Sun Mar 29 18:58:21 2009 @@ -2028,7 +2028,6 @@ PyModule_AddObject(m, "__version__", ver); - PyModule_AddIntConstant(m, "_PY_STRUCT_RANGE_CHECKING", 1); #ifdef PY_STRUCT_FLOAT_COERCE PyModule_AddIntConstant(m, "_PY_STRUCT_FLOAT_COERCE", 1); #endif From python-checkins at python.org Sun Mar 29 19:00:24 2009 From: python-checkins at python.org (mark.dickinson) Date: Sun, 29 Mar 2009 19:00:24 +0200 (CEST) Subject: [Python-checkins] r70689 - python/branches/release30-maint Message-ID: <20090329170024.54DB01E4002@bag.python.org> Author: mark.dickinson Date: Sun Mar 29 19:00:24 2009 New Revision: 70689 Log: Blocked revisions 70688 via svnmerge ........ r70688 | mark.dickinson | 2009-03-29 17:58:21 +0100 (Sun, 29 Mar 2009) | 6 lines Issue #5463: Remove _PY_STRUCT_RANGE_CHECKING constant from struct module, and remove associated code from test_struct. This was a mechanism for skipping some of the tests for overflow behaviour when packing integers; it's no longer necessary. ........ Modified: python/branches/release30-maint/ (props changed) From buildbot at python.org Sun Mar 29 19:08:29 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 17:08:29 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090329170829.E357A1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/788 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_poplib.py", line 131, in run asyncore.loop(timeout=0.1, count=1) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 204, in loop poll_fun(timeout, map) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 141, in poll read(obj) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 78, in read obj.handle_error() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 74, in read obj.handle_read_event() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 413, in handle_read_event self.handle_read() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_ssl.py", line 408, in handle_read self.send(data.lower()) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 519, in send self.initiate_send() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 506, in initiate_send num_sent = dispatcher.send(self, self.out_buffer[:512]) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 349, in send result = self.socket.send(data) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/socket.py", line 165, in _dummy raise error(EBADF, 'Bad file descriptor') error: [Errno 9] Bad file descriptor sincerely, -The Buildbot From buildbot at python.org Sun Mar 29 20:22:06 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 18:22:06 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 2.6 Message-ID: <20090329182206.C4C531E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%202.6/builds/189 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 ====================================================================== FAIL: test01_basic_replication (bsddb.test.test_replication.DBReplicationManager) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/2.6.klose-debian-ppc/build/Lib/bsddb/test/test_replication.py", line 134, in test01_basic_replication self.assertTrue(time.time() Author: antoine.pitrou Date: Sun Mar 29 20:40:13 2009 New Revision: 70690 Log: Fix leak in _fileio.c (patch by Hirokazu Yamamoto) Modified: python/branches/py3k/Modules/_fileio.c Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Sun Mar 29 20:40:13 2009 @@ -622,6 +622,7 @@ n = -1; if (n < 0) { + Py_DECREF(bytes); if (errno == EAGAIN) Py_RETURN_NONE; PyErr_SetFromErrno(PyExc_IOError); From python-checkins at python.org Sun Mar 29 20:51:11 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 29 Mar 2009 20:51:11 +0200 (CEST) Subject: [Python-checkins] r70691 - python/trunk/Lib/heapq.py Message-ID: <20090329185111.8A5001E4002@bag.python.org> Author: raymond.hettinger Date: Sun Mar 29 20:51:11 2009 New Revision: 70691 Log: Make life easier for non-CPython implementations. Modified: python/trunk/Lib/heapq.py Modified: python/trunk/Lib/heapq.py ============================================================================== --- python/trunk/Lib/heapq.py (original) +++ python/trunk/Lib/heapq.py Sun Mar 29 20:51:11 2009 @@ -308,7 +308,7 @@ # If available, use C implementation try: - from _heapq import heappush, heappop, heapify, heapreplace, nlargest, nsmallest, heappushpop + from _heapq import * except ImportError: pass From python-checkins at python.org Sun Mar 29 20:55:13 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 29 Mar 2009 20:55:13 +0200 (CEST) Subject: [Python-checkins] r70692 - in python/branches/py3k: Lib/test/test_io.py Modules/_fileio.c Message-ID: <20090329185513.2A8C11E4002@bag.python.org> Author: antoine.pitrou Date: Sun Mar 29 20:55:12 2009 New Revision: 70692 Log: Plug another leak, and finally add a test for #1174606 (read() from /dev/zero). The leak was the reason my previous attempts at testing failed... Modified: python/branches/py3k/Lib/test/test_io.py python/branches/py3k/Modules/_fileio.c Modified: python/branches/py3k/Lib/test/test_io.py ============================================================================== --- python/branches/py3k/Lib/test/test_io.py (original) +++ python/branches/py3k/Lib/test/test_io.py Sun Mar 29 20:55:12 2009 @@ -505,6 +505,22 @@ with open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"abcxxx") + def test_unbounded_file(self): + # Issue #1174606: reading from an unbounded stream such as /dev/zero. + zero = "/dev/zero" + if not os.path.exists(zero): + raise unittest.SkipTest("{0} does not exist".format(zero)) + if sys.maxsize > 0x7FFFFFFF: + raise unittest.SkipTest("test can only run in a 32-bit address space") + if support.real_max_memuse < support._2G: + raise unittest.SkipTest("test requires at least 2GB of memory") + with open(zero, "rb", buffering=0) as f: + self.assertRaises(OverflowError, f.read) + with open(zero, "rb") as f: + self.assertRaises(OverflowError, f.read) + with open(zero, "r") as f: + self.assertRaises(OverflowError, f.read) + class CIOTest(IOTest): pass Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Sun Mar 29 20:55:12 2009 @@ -543,6 +543,7 @@ PyErr_SetString(PyExc_OverflowError, "unbounded read returned more bytes " "than a Python string can hold "); + Py_DECREF(result); return NULL; } From python-checkins at python.org Sun Mar 29 21:03:52 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 29 Mar 2009 21:03:52 +0200 (CEST) Subject: [Python-checkins] r70693 - in python/branches/release30-maint: Lib/test/test_io.py Modules/_fileio.c Message-ID: <20090329190352.A09E51E4002@bag.python.org> Author: antoine.pitrou Date: Sun Mar 29 21:03:52 2009 New Revision: 70693 Log: Merged revisions 70690,70692 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r70690 | antoine.pitrou | 2009-03-29 20:40:13 +0200 (dim., 29 mars 2009) | 3 lines Fix leak in _fileio.c (patch by Hirokazu Yamamoto) ........ r70692 | antoine.pitrou | 2009-03-29 20:55:12 +0200 (dim., 29 mars 2009) | 4 lines Plug another leak, and finally add a test for #1174606 (read() from /dev/zero). The leak was the reason my previous attempts at testing failed... ........ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/test/test_io.py python/branches/release30-maint/Modules/_fileio.c Modified: python/branches/release30-maint/Lib/test/test_io.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_io.py (original) +++ python/branches/release30-maint/Lib/test/test_io.py Sun Mar 29 21:03:52 2009 @@ -305,6 +305,22 @@ file = io.open(f.fileno(), "r", closefd=False) self.assertEqual(file.buffer.raw.closefd, False) + def test_unbounded_file(self): + # Issue #1174606: reading from an unbounded stream such as /dev/zero. + zero = "/dev/zero" + if not os.path.exists(zero): + return # /dev/zero does not exist + if sys.maxsize > 0x7FFFFFFF: + return # test can only run in a 32-bit address space + if support.real_max_memuse < support._2G: + return # test requires at least 2GB of memory + with open(zero, "rb", buffering=0) as f: + self.assertRaises(OverflowError, f.read) + with open(zero, "rb") as f: + self.assertRaises(OverflowError, f.read) + with open(zero, "r") as f: + self.assertRaises(OverflowError, f.read) + class MemorySeekTestMixin: Modified: python/branches/release30-maint/Modules/_fileio.c ============================================================================== --- python/branches/release30-maint/Modules/_fileio.c (original) +++ python/branches/release30-maint/Modules/_fileio.c Sun Mar 29 21:03:52 2009 @@ -465,6 +465,7 @@ PyErr_SetString(PyExc_OverflowError, "unbounded read returned more bytes " "than a Python string can hold "); + Py_DECREF(result); return NULL; } @@ -541,6 +542,7 @@ Py_END_ALLOW_THREADS if (n < 0) { + Py_DECREF(bytes); if (errno == EAGAIN) Py_RETURN_NONE; PyErr_SetFromErrno(PyExc_IOError); From python-checkins at python.org Sun Mar 29 21:19:50 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 29 Mar 2009 21:19:50 +0200 (CEST) Subject: [Python-checkins] r70694 - in python/branches/py3k/Modules: _bufferedio.c _iobase.c Message-ID: <20090329191950.0DBD41E4002@bag.python.org> Author: antoine.pitrou Date: Sun Mar 29 21:19:49 2009 New Revision: 70694 Log: Rewrite IOBase.readall to avoid costly string resizes, and plug a leak Modified: python/branches/py3k/Modules/_bufferedio.c python/branches/py3k/Modules/_iobase.c Modified: python/branches/py3k/Modules/_bufferedio.c ============================================================================== --- python/branches/py3k/Modules/_bufferedio.c (original) +++ python/branches/py3k/Modules/_bufferedio.c Sun Mar 29 21:19:49 2009 @@ -1144,7 +1144,6 @@ PyObject *data, *res = NULL; Py_ssize_t current_size, remaining, written; char *out; - static PyObject *sep = NULL; /* Special case for when the number of bytes to read is unspecified. */ if (n == -1) { @@ -1201,15 +1200,7 @@ return data; } else { - if (sep == NULL) { - sep = PyBytes_FromStringAndSize(NULL, 0); - if (sep == NULL) { - Py_DECREF(data); - Py_DECREF(chunks); - return NULL; - } - } - res =_PyBytes_Join(sep, chunks); + res = _PyBytes_Join(_PyIO_empty_bytes, chunks); Py_DECREF(data); Py_DECREF(chunks); return res; Modified: python/branches/py3k/Modules/_iobase.c ============================================================================== --- python/branches/py3k/Modules/_iobase.c (original) +++ python/branches/py3k/Modules/_iobase.c Sun Mar 29 21:19:49 2009 @@ -809,49 +809,41 @@ static PyObject * RawIOBase_readall(PyObject *self, PyObject *args) { - PyObject *b = NULL; - Py_ssize_t cursize = 0; + int r; + PyObject *chunks = PyList_New(0); + PyObject *result; + + if (chunks == NULL) + return NULL; while (1) { - Py_ssize_t length; PyObject *data = PyObject_CallMethod(self, "read", "i", DEFAULT_BUFFER_SIZE); - if (!data) { - Py_XDECREF(b); + Py_DECREF(chunks); return NULL; } - if (!PyBytes_Check(data)) { - Py_XDECREF(b); + Py_DECREF(chunks); Py_DECREF(data); PyErr_SetString(PyExc_TypeError, "read() should return bytes"); return NULL; } - - length = Py_SIZE(data); - - if (b == NULL) - b = data; - else if (length != 0) { - - _PyBytes_Resize(&b, cursize + length); - if (b == NULL) { - Py_DECREF(data); - return NULL; - } - - memcpy(PyBytes_AS_STRING(b) + cursize, - PyBytes_AS_STRING(data), length); + if (PyBytes_GET_SIZE(data) == 0) { + /* EOF */ Py_DECREF(data); - } - - if (length == 0) break; + } + r = PyList_Append(chunks, data); + Py_DECREF(data); + if (r < 0) { + Py_DECREF(chunks); + return NULL; + } } - - return b; - + result = _PyBytes_Join(_PyIO_empty_bytes, chunks); + Py_DECREF(chunks); + return result; } static PyMethodDef RawIOBase_methods[] = { From python-checkins at python.org Sun Mar 29 21:30:50 2009 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 29 Mar 2009 21:30:50 +0200 (CEST) Subject: [Python-checkins] r70695 - python/branches/py3k/Lib/heapq.py Message-ID: <20090329193050.B169E1E4002@bag.python.org> Author: raymond.hettinger Date: Sun Mar 29 21:30:50 2009 New Revision: 70695 Log: Make life easier for non-CPython implementations Modified: python/branches/py3k/Lib/heapq.py Modified: python/branches/py3k/Lib/heapq.py ============================================================================== --- python/branches/py3k/Lib/heapq.py (original) +++ python/branches/py3k/Lib/heapq.py Sun Mar 29 21:30:50 2009 @@ -307,7 +307,7 @@ # If available, use C implementation try: - from _heapq import heappush, heappop, heapify, heapreplace, nlargest, nsmallest, heappushpop + from _heapq import * except ImportError: pass From python-checkins at python.org Sun Mar 29 21:30:55 2009 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 29 Mar 2009 21:30:55 +0200 (CEST) Subject: [Python-checkins] r70696 - python/branches/py3k/Lib/test/test_subprocess.py Message-ID: <20090329193055.4E6931E4002@bag.python.org> Author: antoine.pitrou Date: Sun Mar 29 21:30:55 2009 New Revision: 70696 Log: Fix test_subprocess so that it works when launched from another directory than the source dist. Modified: python/branches/py3k/Lib/test/test_subprocess.py Modified: python/branches/py3k/Lib/test/test_subprocess.py ============================================================================== --- python/branches/py3k/Lib/test/test_subprocess.py (original) +++ python/branches/py3k/Lib/test/test_subprocess.py Sun Mar 29 21:30:55 2009 @@ -142,8 +142,9 @@ self.assertEqual(p.stderr, None) def test_executable(self): - p = subprocess.Popen(["somethingyoudonthave", - "-c", "import sys; sys.exit(47)"], + arg0 = os.path.join(os.path.dirname(sys.executable), + "somethingyoudonthave") + p = subprocess.Popen([arg0, "-c", "import sys; sys.exit(47)"], executable=sys.executable) p.wait() self.assertEqual(p.returncode, 47) From buildbot at python.org Sun Mar 29 22:25:07 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 20:25:07 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090329202507.62CC01E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/233 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed test Excerpt from the test logfile: 2 tests failed: test_posix test_subprocess ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== FAIL: test_executable (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_subprocess.py", line 115, in test_executable self.assertEqual(p.returncode, 47) AssertionError: -6 != 47 sincerely, -The Buildbot From buildbot at python.org Sun Mar 29 23:09:03 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 21:09:03 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090329210903.6F13E1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/539 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: antoine.pitrou BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Sun Mar 29 23:22:35 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 29 Mar 2009 23:22:35 +0200 (CEST) Subject: [Python-checkins] r70697 - python/trunk/Lib/test/crashers/multithreaded_close.py Message-ID: <20090329212235.95DA01E4002@bag.python.org> Author: benjamin.peterson Date: Sun Mar 29 23:22:35 2009 New Revision: 70697 Log: this has been fixed since 2.6 (I love removing these) Removed: python/trunk/Lib/test/crashers/multithreaded_close.py Deleted: python/trunk/Lib/test/crashers/multithreaded_close.py ============================================================================== --- python/trunk/Lib/test/crashers/multithreaded_close.py Sun Mar 29 23:22:35 2009 +++ (empty file) @@ -1,14 +0,0 @@ -# f.close() is not thread-safe: calling it at the same time as another -# operation (or another close) on the same file, but done from another -# thread, causes crashes. The issue is more complicated than it seems, -# witness the discussions in: -# -# http://bugs.python.org/issue595601 -# http://bugs.python.org/issue815646 - -import thread - -while 1: - f = open("multithreaded_close.tmp", "w") - thread.start_new_thread(f.close, ()) - f.close() From python-checkins at python.org Sun Mar 29 23:31:05 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 29 Mar 2009 23:31:05 +0200 (CEST) Subject: [Python-checkins] r70698 - python/trunk/Lib/test/crashers/bogus_sre_bytecode.py Message-ID: <20090329213105.53B311E4025@bag.python.org> Author: benjamin.peterson Date: Sun Mar 29 23:31:05 2009 New Revision: 70698 Log: thanks to guido's bytecode verifier, this is fixed Removed: python/trunk/Lib/test/crashers/bogus_sre_bytecode.py Deleted: python/trunk/Lib/test/crashers/bogus_sre_bytecode.py ============================================================================== --- python/trunk/Lib/test/crashers/bogus_sre_bytecode.py Sun Mar 29 23:31:05 2009 +++ (empty file) @@ -1,47 +0,0 @@ -""" -The regular expression engine in '_sre' can segfault when interpreting -bogus bytecode. - -It is unclear whether this is a real bug or a "won't fix" case like -bogus_code_obj.py, because it requires bytecode that is built by hand, -as opposed to compiled by 're' from a string-source regexp. The -difference with bogus_code_obj, though, is that the only existing regexp -compiler is written in Python, so that the C code has no choice but -accept arbitrary bytecode from Python-level. - -The test below builds and runs random bytecodes until 'match' crashes -Python. I have not investigated why exactly segfaults occur nor how -hard they would be to fix. Here are a few examples of 'code' that -segfault for me: - - [21, 50814, 8, 29, 16] - [21, 3967, 26, 10, 23, 54113] - [29, 23, 0, 2, 5] - [31, 64351, 0, 28, 3, 22281, 20, 4463, 9, 25, 59154, 15245, 2, - 16343, 3, 11600, 24380, 10, 37556, 10, 31, 15, 31] - -Here is also a 'code' that triggers an infinite uninterruptible loop: - - [29, 1, 8, 21, 1, 43083, 6] - -""" - -import _sre, random - -def pick(): - n = random.randrange(-65536, 65536) - if n < 0: - n &= 31 - return n - -ss = ["", "world", "x" * 500] - -while 1: - code = [pick() for i in range(random.randrange(5, 25))] - print code - pat = _sre.compile(None, 0, code) - for s in ss: - try: - pat.match(s) - except RuntimeError: - pass From python-checkins at python.org Sun Mar 29 23:37:27 2009 From: python-checkins at python.org (tarek.ziade) Date: Sun, 29 Mar 2009 23:37:27 +0200 (CEST) Subject: [Python-checkins] r70699 - peps/trunk/pep-0381.txt Message-ID: <20090329213727.6EEA81E4002@bag.python.org> Author: tarek.ziade Date: Sun Mar 29 23:37:27 2009 New Revision: 70699 Log: start to rewrite mirrorring specs (using DNS approach) Modified: peps/trunk/pep-0381.txt Modified: peps/trunk/pep-0381.txt ============================================================================== --- peps/trunk/pep-0381.txt (original) +++ peps/trunk/pep-0381.txt Sun Mar 29 23:37:27 2009 @@ -19,8 +19,8 @@ Rationale ========= -PyPI is hosting over 4000 projects and is used on a daily basis by -people to build applications. Especially systems like `easy_install` +PyPI is hosting over 6000 projects and is used on a daily basis +by people to build applications. Especially systems like `easy_install` and `zc.buildout` make intensive usage of PyPI. For people making intensive use of PyPI, it can act as a single point @@ -41,48 +41,26 @@ Mirror listing and registering ============================== -A new text page will be added at http://pypi.python.org/mirrors that -can be browsed like the simple index. This page gives a list of the -mirrors through a list of links. - -These links are the URL of the simple index of each mirror. The page -will look like this:: - - # PyPI mirrors - # - # If you want to register a new mirror, send an email - # to the catalog-SIG at python.org with: - # - # - The urls of your mirror: - # - the root of the server - # - the index page - # - the last modified page - # - the local stats page - # - the global stats page - # - the mirrors page - # - # - The name and email of the maintainer. - # - # The registering is done manually and to become a - # mirror, you need to strictly follow the mirror protocol - # described here: - # - # http://wiki.python.org/PEP_374 - # - # root,index,last-modified,local-stats,stats,mirrors - http://example.com/pypi,index,last-modified,local-stats,stats,mirrors - http://example2.com/pypi,index,last-modified,local-stats,stats,mirrors - -When a mirror is proposed on the mailing list, it is manually added in -the mirror list in the PyPI application after it has been checked to -be compliant with the mirroring rules. - -The mirror list page is a simple text page that can be browsed by any -tool that wants to get a list of registered mirrors. Other package -indexes that are not mirrors of PyPI are not added in the mirror list -in PyPI, although they can provide themselve the same mirroring list -mechanism for their own mirrors. +People that wants to mirror PyPI make a proposal on catalog-SIG. +When a mirror is proposed on the mailing list, it is manually +added in a mirror list in the PyPI application after it +has been checked to be compliant with the mirroring rules. +A mirror has to be a hostname. For example: + +- http://pypi.my-company.com +- http://mirror-pypi.somewhere.org + +The mirror list is handled by a DNS entry for this hostname: + + mirrors.pypi.python.org + +When a mirror is added into the DNS, it becomes an official +IP for `mirrors.pypi.python.org`. + +The new mirror also appears at `http://pypi.python.org/mirrors` +which is a human-readable page that gives the list of mirrors. +This page also explains how to register a new mirror. Special pages a mirror needs to provide ======================================= From python-checkins at python.org Sun Mar 29 23:50:15 2009 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 29 Mar 2009 23:50:15 +0200 (CEST) Subject: [Python-checkins] r70700 - python/trunk/Doc/tools/sphinxext/pyspecific.py Message-ID: <20090329215015.B3EE11E4002@bag.python.org> Author: benjamin.peterson Date: Sun Mar 29 23:50:14 2009 New Revision: 70700 Log: use the awesome new status iterator Modified: python/trunk/Doc/tools/sphinxext/pyspecific.py Modified: python/trunk/Doc/tools/sphinxext/pyspecific.py ============================================================================== --- python/trunk/Doc/tools/sphinxext/pyspecific.py (original) +++ python/trunk/Doc/tools/sphinxext/pyspecific.py Sun Mar 29 23:50:14 2009 @@ -74,7 +74,9 @@ def write(self, *ignored): writer = TextWriter(self) - for label in self.status_iterator(pydoc_topic_labels, 'building topics... '): + for label in self.status_iterator(pydoc_topic_labels, + 'building topics... ', + length=len(pydoc_topic_labels)): if label not in self.env.labels: self.warn('label %r not in documentation' % label) continue From ncoghlan at gmail.com Mon Mar 30 00:06:15 2009 From: ncoghlan at gmail.com (Nick Coghlan) Date: Mon, 30 Mar 2009 08:06:15 +1000 Subject: [Python-checkins] r70697 - python/trunk/Lib/test/crashers/multithreaded_close.py In-Reply-To: <20090329212235.95DA01E4002@bag.python.org> References: <20090329212235.95DA01E4002@bag.python.org> Message-ID: <49CFF0D7.7000604@gmail.com> benjamin.peterson wrote: > Author: benjamin.peterson > Date: Sun Mar 29 23:22:35 2009 > New Revision: 70697 > > Log: > this has been fixed since 2.6 (I love removing these) Did this and the other removed crasher get normal unit tests when they were fixed? (the lack of such unit tests is one of the reasons crashers sometimes hang around, even after they're nominally fixed - although sometimes it really is just because nobody thought to remove them!) Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- From benjamin at python.org Mon Mar 30 00:08:16 2009 From: benjamin at python.org (Benjamin Peterson) Date: Sun, 29 Mar 2009 17:08:16 -0500 Subject: [Python-checkins] r70697 - python/trunk/Lib/test/crashers/multithreaded_close.py In-Reply-To: <49CFF0D7.7000604@gmail.com> References: <20090329212235.95DA01E4002@bag.python.org> <49CFF0D7.7000604@gmail.com> Message-ID: <1afaf6160903291508p7c1bdeapc39c843541a508ee@mail.gmail.com> 2009/3/29 Nick Coghlan : > benjamin.peterson wrote: >> Author: benjamin.peterson >> Date: Sun Mar 29 23:22:35 2009 >> New Revision: 70697 >> >> Log: >> this has been fixed since 2.6 (I love removing these) > > Did this and the other removed crasher get normal unit tests when they > were fixed? (the lack of such unit tests is one of the reasons crashers > sometimes hang around, even after they're nominally fixed - although > sometimes it really is just because nobody thought to remove them!) I'm sure the thread one did, and GvR added the bytecode verifier with tests IIRC. -- Regards, Benjamin From python-checkins at python.org Mon Mar 30 00:27:26 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 30 Mar 2009 00:27:26 +0200 (CEST) Subject: [Python-checkins] r70701 - python/trunk/Lib/test/test_tk.py Message-ID: <20090329222726.9F5C01E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 30 00:27:26 2009 New Revision: 70701 Log: add missing import Modified: python/trunk/Lib/test/test_tk.py Modified: python/trunk/Lib/test/test_tk.py ============================================================================== --- python/trunk/Lib/test/test_tk.py (original) +++ python/trunk/Lib/test/test_tk.py Mon Mar 30 00:27:26 2009 @@ -1,5 +1,6 @@ import os import sys +import unittest import Tkinter from test import test_support From python-checkins at python.org Mon Mar 30 00:33:58 2009 From: python-checkins at python.org (bob.ippolito) Date: Mon, 30 Mar 2009 00:33:58 +0200 (CEST) Subject: [Python-checkins] r70702 - in python/trunk: Lib/json/__init__.py Lib/json/scanner.py Lib/json/tests/test_decode.py Lib/json/tests/test_float.py Modules/_json.c Message-ID: <20090329223358.E5D601E4015@bag.python.org> Author: bob.ippolito Date: Mon Mar 30 00:33:58 2009 New Revision: 70702 Log: Issue 5381: fix regression in pure python code path, Issue 5584: fix a decoder bug for unicode float literals outside of a container Modified: python/trunk/Lib/json/__init__.py python/trunk/Lib/json/scanner.py python/trunk/Lib/json/tests/test_decode.py python/trunk/Lib/json/tests/test_float.py python/trunk/Modules/_json.c Modified: python/trunk/Lib/json/__init__.py ============================================================================== --- python/trunk/Lib/json/__init__.py (original) +++ python/trunk/Lib/json/__init__.py Mon Mar 30 00:33:58 2009 @@ -266,7 +266,8 @@ return loads(fp.read(), encoding=encoding, cls=cls, object_hook=object_hook, parse_float=parse_float, parse_int=parse_int, - parse_constant=parse_constant, object_pairs_hook=None, **kw) + parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, + **kw) def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, Modified: python/trunk/Lib/json/scanner.py ============================================================================== --- python/trunk/Lib/json/scanner.py (original) +++ python/trunk/Lib/json/scanner.py Mon Mar 30 00:33:58 2009 @@ -23,6 +23,7 @@ parse_int = context.parse_int parse_constant = context.parse_constant object_hook = context.object_hook + object_pairs_hook = context.object_pairs_hook def _scan_once(string, idx): try: @@ -34,7 +35,7 @@ return parse_string(string, idx + 1, encoding, strict) elif nextchar == '{': return parse_object((string, idx + 1), encoding, strict, - _scan_once, object_hook) + _scan_once, object_hook, object_pairs_hook) elif nextchar == '[': return parse_array((string, idx + 1), _scan_once) elif nextchar == 'n' and string[idx:idx + 4] == 'null': Modified: python/trunk/Lib/json/tests/test_decode.py ============================================================================== --- python/trunk/Lib/json/tests/test_decode.py (original) +++ python/trunk/Lib/json/tests/test_decode.py Mon Mar 30 00:33:58 2009 @@ -1,5 +1,6 @@ import decimal from unittest import TestCase +from StringIO import StringIO import json from collections import OrderedDict @@ -27,12 +28,14 @@ p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), ("qrt", 5), ("pad", 6), ("hoy", 7)] self.assertEqual(json.loads(s), eval(s)) - self.assertEqual(json.loads(s, object_pairs_hook = lambda x: x), p) - od = json.loads(s, object_pairs_hook = OrderedDict) + self.assertEqual(json.loads(s, object_pairs_hook=lambda x: x), p) + self.assertEqual(json.load(StringIO(s), + object_pairs_hook=lambda x: x), p) + od = json.loads(s, object_pairs_hook=OrderedDict) self.assertEqual(od, OrderedDict(p)) self.assertEqual(type(od), OrderedDict) # the object_pairs_hook takes priority over the object_hook self.assertEqual(json.loads(s, - object_pairs_hook = OrderedDict, - object_hook = lambda x: None), + object_pairs_hook=OrderedDict, + object_hook=lambda x: None), OrderedDict(p)) Modified: python/trunk/Lib/json/tests/test_float.py ============================================================================== --- python/trunk/Lib/json/tests/test_float.py (original) +++ python/trunk/Lib/json/tests/test_float.py Mon Mar 30 00:33:58 2009 @@ -5,11 +5,15 @@ class TestFloat(TestCase): def test_floats(self): - for num in [1617161771.7650001, math.pi, math.pi**100, math.pi**-100, 3.1]: + for num in [1617161771.7650001, math.pi, math.pi**100, + math.pi**-100, 3.1]: self.assertEquals(float(json.dumps(num)), num) self.assertEquals(json.loads(json.dumps(num)), num) + self.assertEquals(json.loads(unicode(json.dumps(num))), num) def test_ints(self): for num in [1, 1L, 1<<32, 1<<64]: self.assertEquals(json.dumps(num), str(num)) self.assertEquals(int(json.dumps(num)), num) + self.assertEquals(json.loads(json.dumps(num)), num) + self.assertEquals(json.loads(unicode(json.dumps(num))), num) Modified: python/trunk/Modules/_json.c ============================================================================== --- python/trunk/Modules/_json.c (original) +++ python/trunk/Modules/_json.c Mon Mar 30 00:33:58 2009 @@ -1468,7 +1468,7 @@ if (idx < end_idx && str[idx] == '.' && str[idx + 1] >= '0' && str[idx + 1] <= '9') { is_float = 1; idx += 2; - while (idx < end_idx && str[idx] >= '0' && str[idx] <= '9') idx++; + while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++; } /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */ From ncoghlan at gmail.com Mon Mar 30 00:35:10 2009 From: ncoghlan at gmail.com (Nick Coghlan) Date: Mon, 30 Mar 2009 08:35:10 +1000 Subject: [Python-checkins] r70697 - python/trunk/Lib/test/crashers/multithreaded_close.py In-Reply-To: <1afaf6160903291508p7c1bdeapc39c843541a508ee@mail.gmail.com> References: <20090329212235.95DA01E4002@bag.python.org> <49CFF0D7.7000604@gmail.com> <1afaf6160903291508p7c1bdeapc39c843541a508ee@mail.gmail.com> Message-ID: <49CFF79E.3010208@gmail.com> Benjamin Peterson wrote: > 2009/3/29 Nick Coghlan : >> benjamin.peterson wrote: >>> Author: benjamin.peterson >>> Date: Sun Mar 29 23:22:35 2009 >>> New Revision: 70697 >>> >>> Log: >>> this has been fixed since 2.6 (I love removing these) >> Did this and the other removed crasher get normal unit tests when they >> were fixed? (the lack of such unit tests is one of the reasons crashers >> sometimes hang around, even after they're nominally fixed - although >> sometimes it really is just because nobody thought to remove them!) > > I'm sure the thread one did, and GvR added the bytecode verifier with > tests IIRC. Cool, just checking :) Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- From buildbot at python.org Mon Mar 30 01:06:29 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 23:06:29 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090329230629.39A6B1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/793 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson,bob.ippolito BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_urllib2_localnet make: *** [buildbottest] Error 1 sincerely, -The Buildbot From martin at v.loewis.de Mon Mar 30 01:12:16 2009 From: martin at v.loewis.de (=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=) Date: Sun, 29 Mar 2009 18:12:16 -0500 Subject: [Python-checkins] r70699 - peps/trunk/pep-0381.txt In-Reply-To: <20090329213727.6EEA81E4002@bag.python.org> References: <20090329213727.6EEA81E4002@bag.python.org> Message-ID: <49D00050.8020300@v.loewis.de> > +A mirror has to be a hostname. For example: > + > +- http://pypi.my-company.com > +- http://mirror-pypi.somewhere.org > + That actually doesn't work - the mirrors have to be IP addresses (and I need a commitment from the mirror operator to not change it) Regards, Martin From buildbot at python.org Mon Mar 30 01:53:39 2009 From: buildbot at python.org (buildbot at python.org) Date: Sun, 29 Mar 2009 23:53:39 +0000 Subject: [Python-checkins] buildbot failure in x86 gentoo 2.6 Message-ID: <20090329235340.1AAFE1E4002@bag.python.org> The Buildbot has detected a new failure of x86 gentoo 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20gentoo%202.6/builds/195 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-x86 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: mark.dickinson BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From buildbot at python.org Mon Mar 30 02:05:39 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 00:05:39 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090330000539.BF9D71E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/284 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: benjamin.peterson,bob.ippolito BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 30 04:14:21 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 30 Mar 2009 04:14:21 +0200 (CEST) Subject: [Python-checkins] r70703 - python/trunk/Lib/email/test/test_email_codecs_renamed.py Message-ID: <20090330021421.2F0431E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 30 04:14:21 2009 New Revision: 70703 Log: fix import Modified: python/trunk/Lib/email/test/test_email_codecs_renamed.py Modified: python/trunk/Lib/email/test/test_email_codecs_renamed.py ============================================================================== --- python/trunk/Lib/email/test/test_email_codecs_renamed.py (original) +++ python/trunk/Lib/email/test/test_email_codecs_renamed.py Mon Mar 30 04:14:21 2009 @@ -3,7 +3,7 @@ # email package unit tests for (optional) Asian codecs import unittest -from test.test_support import TestSkipped, run_unittest +from test.test_support import run_unittest from email.test.test_email import TestEmailBase from email.charset import Charset @@ -15,7 +15,7 @@ try: unicode('foo', 'euc-jp') except LookupError: - raise TestSkipped + raise unittest.SkipTest From python-checkins at python.org Mon Mar 30 04:49:32 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 30 Mar 2009 04:49:32 +0200 (CEST) Subject: [Python-checkins] r70704 - python/trunk/Doc/library/webbrowser.rst Message-ID: <20090330024932.4CCBD1E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 30 04:49:32 2009 New Revision: 70704 Log: there's actually three methods here #5600 Modified: python/trunk/Doc/library/webbrowser.rst Modified: python/trunk/Doc/library/webbrowser.rst ============================================================================== --- python/trunk/Doc/library/webbrowser.rst (original) +++ python/trunk/Doc/library/webbrowser.rst Mon Mar 30 04:49:32 2009 @@ -172,8 +172,8 @@ Browser Controller Objects -------------------------- -Browser controllers provide these methods which parallel two of the module-level -convenience functions: +Browser controllers provide these methods which parallel three of the +module-level convenience functions: .. method:: controller.open(url[, new[, autoraise=1]]) From ziade.tarek at gmail.com Mon Mar 30 06:25:45 2009 From: ziade.tarek at gmail.com (=?ISO-8859-1?Q?Tarek_Ziad=E9?=) Date: Sun, 29 Mar 2009 23:25:45 -0500 Subject: [Python-checkins] r70699 - peps/trunk/pep-0381.txt In-Reply-To: <49D00050.8020300@v.loewis.de> References: <20090329213727.6EEA81E4002@bag.python.org> <49D00050.8020300@v.loewis.de> Message-ID: <94bdd2610903292125y38856111m43ddca582ee43c7b@mail.gmail.com> RIght I am fixing this right now. There's something we didn't talk about yet : since there will be other package indexes out there (not PyPI mirrors) that might have their own mirrors, we do need to provide somewhere the hostname that holds the mirrors IP for the client software to work the same way in all case. That is, mirrors.pypi.python.org for PyPI, but maybe mirrors.packages.plone.org for another index. I'd go for a /mirror-hostname unique page at PyPI (and its mirrors) even if this page is unreachable when PyPI is down. This enforces that the other indexes also use the DNS technique, but I think it's fine Tarek On Sun, Mar 29, 2009 at 6:12 PM, "Martin v. L?wis" wrote: > >> +A mirror has to be a hostname. For example: >> + >> +- http://pypi.my-company.com >> +- http://mirror-pypi.somewhere.org >> + > > That actually doesn't work - the mirrors have to be > IP addresses (and I need a commitment from the mirror > operator to not change it) > > Regards, > Martin > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > -- Tarek Ziad? | Association AfPy | www.afpy.org Blog FR | http://programmation-python.org Blog EN | http://tarekziade.wordpress.com/ From python-checkins at python.org Mon Mar 30 06:53:46 2009 From: python-checkins at python.org (tarek.ziade) Date: Mon, 30 Mar 2009 06:53:46 +0200 (CEST) Subject: [Python-checkins] r70705 - peps/trunk/pep-0381.txt Message-ID: <20090330045346.B05771E4014@bag.python.org> Author: tarek.ziade Date: Mon Mar 30 06:53:39 2009 New Revision: 70705 Log: various fixes, more details Modified: peps/trunk/pep-0381.txt Modified: peps/trunk/pep-0381.txt ============================================================================== --- peps/trunk/pep-0381.txt (original) +++ peps/trunk/pep-0381.txt Mon Mar 30 06:53:39 2009 @@ -10,6 +10,7 @@ Python-Version: N.A. Post-History: + Abstract ======== @@ -35,7 +36,6 @@ by PyPI, in order to get hit counts and the last modified date. - how a mirror should synchronize with PyPI - how a client can implement a fail-over mechanism -- a contact form for Package maintainers Mirror listing and registering @@ -46,31 +46,59 @@ added in a mirror list in the PyPI application after it has been checked to be compliant with the mirroring rules. -A mirror has to be a hostname. For example: - -- http://pypi.my-company.com -- http://mirror-pypi.somewhere.org - The mirror list is handled by a DNS entry for this hostname: mirrors.pypi.python.org When a mirror is added into the DNS, it becomes an official -IP for `mirrors.pypi.python.org`. +IP for `mirrors.pypi.python.org`, and requests will be sent +to the given IP. Therefore the mirror maintainer should not +change the IP provided. If the IP has to change for any reason, +the mirror maintainer has to send a mail to catalog-SIG at least +one week before the change so the DNS entry can be changed on time. The new mirror also appears at `http://pypi.python.org/mirrors` which is a human-readable page that gives the list of mirrors. This page also explains how to register a new mirror. +Statistics page +::::::::::::::: + +PyPI provides statistics on downloads at `/stats`. This page is +calculated daily by PyPI, by reading all mirrors' local stats and +summing them. + +The stats are presented in daily or montly files, under `/stats/days` +and `/stats/months`. Each file is a `bzip2` file with these formats: + +- YYYY-MM-DD.bz2 for daily files +- YYYY-MM.bz2 for monthly files + +Examples: + +- /stats/days/2008-11-06.bz2 +- /stats/days/2008-11-07.bz2 +- /stats/days/2008-11-08.bz2 +- /stats/months/2008-11.bz2 +- /stats/months/2008-10.bz2 + + Special pages a mirror needs to provide ======================================= -A mirror needs to provide four pages, beside the index one: +A mirror is a strict copy of PyPI, so it provides the same structure +by copying it. + +- pypi: html version of the package index +- simple: rest version of the package index +- packages: packages, stored by Python version, and letters +- stats : statistics on downloads +- XXX + +It also needs to provide two specific elements: - last-modified - local-stats -- stats -- mirrors Last modified date :::::::::::::::::: @@ -81,12 +109,11 @@ For PyPI, each mirror needs to maintain a URL with simple text content that represents the last synchronisation date the mirror maintains. -The date is provided in GMT time, using the ISO 8601 format (see -http://en.wikipedia.org/wiki/ISO_8601). - +The date is provided in GMT time, using the ISO 8601 format [#iso8601]_. Each mirror will be responsible to maintain its last modified date. -Conventionally, this page should be reachable at: `/last-modified`. +This page must be located at : `/last-modified` and must be a +text/plain page. Local statistics :::::::::::::::: @@ -124,42 +151,7 @@ - /local-stats/days/2008-11-07.bz2 - /local-stats/days/2008-11-08.bz2 -Conventionally the name should be `local-stats`, but it can be any -name provided when the mirror is registered. - -Statistics page -::::::::::::::: - -PyPI and each mirror are responsible to provide the grand total page -at `/stats`. This page is calculated daily by PyPI, by reading all -mirrors' local stats and summing them. - -Therefore the mirrors should not try to rebuild this stat page but -simply get the one on PyPI during each synchronization. - -It has the same structure as `local-stats` but also provides counts -for months. - -Examples: - -- /stats/days/2008-11-06.bz2 -- /stats/days/2008-11-07.bz2 -- /stats/days/2008-11-08.bz2 -- /stats/months/2008-11.bz2 -- /stats/months/2008-10.bz2 - -Conventionally the name should be `stats`, but it can be any name -provided when the mirror is registered. - - -Mirrors listing page -:::::::::::::::::::: - -Like `/stats`, each mirror should get and provide a copy of the -`/mirrors` page. - -Conventionally the name should be `mirrors`, but it can be any name -provided when the mirror is registered. +This page must be located at `/local-stats`. How a mirror should synchronize with PyPI @@ -175,7 +167,7 @@ XXX Need to describe the protocol here. -The zc.pypimirror package [#zcpkg]_ provides an application that +The z3c.pypimirror package [#zcpkg]_ provides an application that respects this protocol to browse PyPI. User-agent request header @@ -187,10 +179,9 @@ This is also true for all clients like: -- `zc.buildout `_ -- `setuptools `_ -- `pip `_ -- etc. +- zc.buildout [#zc.buildout]_. +- setuptools [#setuptools]_. +- pip [#pip]_. XXX user agent registering mechanism at PyPI ? @@ -198,7 +189,13 @@ ::::::::::::::::::::::::::::::::::::::::: Clients that are browsing PyPI should be able to use alternative -mirrors, by reading the `/mirrors` page at PyPI. +mirrors, by getting the list of the mirrors using `mirrors.pypi.python.org`. + +Code example:: + + >>> import socket + >>> socket.gethostbyname_ex('mirrors.pypi.python.org')[-1] + ['82.94.164.163', '88.191.64.248'] The clients so far that could use this mechanism: @@ -212,9 +209,6 @@ Clients that are browsing PyPI should be able to use a fail-over mechanism when PyPI or the used mirror is not responding. -This can be done by parsing the `/mirrors` page of PyPI or the one -located on any PyPI mirror. - It is up to the client to decide wich mirror should be used, maybe by looking at its geographical location and its responsivness. @@ -242,9 +236,8 @@ Softwares that are compatible with PyPI and Distutils so far: -- `PloneSoftwareCenter `_ - wich is used to run plone.org products section. -- `EggBasket `_ +- PloneSoftwareCenter [#psc]_ wich is used to run plone.org products section. +- EggBasket [#eggbasket]_. **An extra package index is not a mirror of PyPI, but can have some mirrors itself.** @@ -257,8 +250,10 @@ source of packages. Different indexes should be defined as a sorted list for the client to look for a package. -Each independant index can of course provide a list of its mirrors, if -the `/mirrors` page is available. +Each independant index can of course provide a list of its mirrors. + +XXX define how to get the hostname for the mirrors of an arbitrary +index. That permits all combinations at client level, for a reliable packaging system with all levels of privacy. @@ -275,6 +270,30 @@ .. [#zcpkg] http://pypi.python.org/pypi/z3c.pypimirror +.. [#iso8601] + http://en.wikipedia.org/wiki/ISO_8601 + +.. [#zc.buildout] + http://pypi.python.org/pypi/zc.buildout + +.. [#setuptools] + http://pypi.python.org/pypi/setuptools + +.. [#pip] + http://pypi.python.org/pypi/pip + +.. [#psc] + http://plone.org/products/plonesoftwarecenter + +.. [#eggbasket] + http://www.chrisarndt.de/projects/eggbasket + + +Aknowledgments +============== + +Martin von Loewis, Georg Brandl. + Copyright ========= From python-checkins at python.org Mon Mar 30 16:42:24 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 30 Mar 2009 16:42:24 +0200 (CEST) Subject: [Python-checkins] r70706 - python/trunk/Lib/test/test_fork1.py Message-ID: <20090330144224.600CC1E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 30 16:42:23 2009 New Revision: 70706 Log: add missing import Modified: python/trunk/Lib/test/test_fork1.py Modified: python/trunk/Lib/test/test_fork1.py ============================================================================== --- python/trunk/Lib/test/test_fork1.py (original) +++ python/trunk/Lib/test/test_fork1.py Mon Mar 30 16:42:23 2009 @@ -3,6 +3,7 @@ import os import time +import unittest from test.fork_wait import ForkWait from test.test_support import run_unittest, reap_children From python-checkins at python.org Mon Mar 30 16:51:58 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 30 Mar 2009 16:51:58 +0200 (CEST) Subject: [Python-checkins] r70707 - in python/branches/py3k: Doc/Makefile Doc/distutils/index.rst Doc/documenting/index.rst Doc/extending/index.rst Doc/library/index.rst Doc/library/os.rst Doc/library/string.rst Doc/library/webbrowser.rst Doc/reference/index.rst Doc/tools/sphinxext/pyspecific.py Doc/tutorial/index.rst Doc/using/index.rst Lib/distutils/version.py Lib/idlelib/configHandler.py Lib/test/crashers/bogus_sre_bytecode.py Lib/test/crashers/multithreaded_close.py Modules/_tkinter.c Message-ID: <20090330145158.44D7B1E4038@bag.python.org> Author: benjamin.peterson Date: Mon Mar 30 16:51:56 2009 New Revision: 70707 Log: Merged revisions 70578,70599,70641-70642,70650,70660-70661,70674,70691,70697-70698,70700,70704 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70578 | benjamin.peterson | 2009-03-23 22:24:56 -0500 (Mon, 23 Mar 2009) | 1 line this is better written using assertRaises ........ r70599 | benjamin.peterson | 2009-03-25 16:42:51 -0500 (Wed, 25 Mar 2009) | 1 line this can be slightly less ugly ........ r70641 | guilherme.polo | 2009-03-27 16:43:08 -0500 (Fri, 27 Mar 2009) | 3 lines Adjusted _tkinter to compile without warnings when WITH_THREAD is not defined (part of issue #5035) ........ r70642 | georg.brandl | 2009-03-27 19:48:48 -0500 (Fri, 27 Mar 2009) | 1 line Fix typo. ........ r70650 | benjamin.peterson | 2009-03-28 14:16:10 -0500 (Sat, 28 Mar 2009) | 1 line give os.symlink and os.link() better parameter names #5564 ........ r70660 | georg.brandl | 2009-03-28 14:52:58 -0500 (Sat, 28 Mar 2009) | 1 line Switch to fixed Sphinx version. ........ r70661 | georg.brandl | 2009-03-28 14:57:36 -0500 (Sat, 28 Mar 2009) | 2 lines Add section numbering to some of the larger subdocuments. ........ r70674 | guilherme.polo | 2009-03-29 05:19:05 -0500 (Sun, 29 Mar 2009) | 1 line Typo fix. ........ r70691 | raymond.hettinger | 2009-03-29 13:51:11 -0500 (Sun, 29 Mar 2009) | 1 line Make life easier for non-CPython implementations. ........ r70697 | benjamin.peterson | 2009-03-29 16:22:35 -0500 (Sun, 29 Mar 2009) | 1 line this has been fixed since 2.6 (I love removing these) ........ r70698 | benjamin.peterson | 2009-03-29 16:31:05 -0500 (Sun, 29 Mar 2009) | 1 line thanks to guido's bytecode verifier, this is fixed ........ r70700 | benjamin.peterson | 2009-03-29 16:50:14 -0500 (Sun, 29 Mar 2009) | 1 line use the awesome new status iterator ........ r70704 | benjamin.peterson | 2009-03-29 21:49:32 -0500 (Sun, 29 Mar 2009) | 1 line there's actually three methods here #5600 ........ Removed: python/branches/py3k/Lib/test/crashers/bogus_sre_bytecode.py python/branches/py3k/Lib/test/crashers/multithreaded_close.py Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/Makefile python/branches/py3k/Doc/distutils/index.rst python/branches/py3k/Doc/documenting/index.rst python/branches/py3k/Doc/extending/index.rst python/branches/py3k/Doc/library/index.rst python/branches/py3k/Doc/library/os.rst python/branches/py3k/Doc/library/string.rst python/branches/py3k/Doc/library/webbrowser.rst python/branches/py3k/Doc/reference/index.rst python/branches/py3k/Doc/tools/sphinxext/pyspecific.py python/branches/py3k/Doc/tutorial/index.rst python/branches/py3k/Doc/using/index.rst python/branches/py3k/Lib/distutils/version.py python/branches/py3k/Lib/idlelib/configHandler.py python/branches/py3k/Modules/_tkinter.c Modified: python/branches/py3k/Doc/Makefile ============================================================================== --- python/branches/py3k/Doc/Makefile (original) +++ python/branches/py3k/Doc/Makefile Mon Mar 30 16:51:56 2009 @@ -31,7 +31,7 @@ checkout: @if [ ! -d tools/sphinx ]; then \ echo "Checking out Sphinx..."; \ - svn checkout $(SVNROOT)/doctools/trunk/sphinx tools/sphinx; \ + svn checkout $(SVNROOT)/external/Sphinx-0.6.1/sphinx tools/sphinx; \ fi @if [ ! -d tools/docutils ]; then \ echo "Checking out Docutils..."; \ Modified: python/branches/py3k/Doc/distutils/index.rst ============================================================================== --- python/branches/py3k/Doc/distutils/index.rst (original) +++ python/branches/py3k/Doc/distutils/index.rst Mon Mar 30 16:51:56 2009 @@ -16,6 +16,7 @@ .. toctree:: :maxdepth: 2 + :numbered: introduction.rst setupscript.rst Modified: python/branches/py3k/Doc/documenting/index.rst ============================================================================== --- python/branches/py3k/Doc/documenting/index.rst (original) +++ python/branches/py3k/Doc/documenting/index.rst Mon Mar 30 16:51:56 2009 @@ -23,6 +23,7 @@ are more than welcome as well. .. toctree:: + :numbered: intro.rst style.rst Modified: python/branches/py3k/Doc/extending/index.rst ============================================================================== --- python/branches/py3k/Doc/extending/index.rst (original) +++ python/branches/py3k/Doc/extending/index.rst Mon Mar 30 16:51:56 2009 @@ -26,6 +26,7 @@ .. toctree:: :maxdepth: 2 + :numbered: extending.rst newtypes.rst Modified: python/branches/py3k/Doc/library/index.rst ============================================================================== --- python/branches/py3k/Doc/library/index.rst (original) +++ python/branches/py3k/Doc/library/index.rst Mon Mar 30 16:51:56 2009 @@ -38,6 +38,7 @@ .. toctree:: :maxdepth: 2 + :numbered: intro.rst functions.rst Modified: python/branches/py3k/Doc/library/os.rst ============================================================================== --- python/branches/py3k/Doc/library/os.rst (original) +++ python/branches/py3k/Doc/library/os.rst Mon Mar 30 16:51:56 2009 @@ -796,9 +796,10 @@ function will not follow symbolic links. Availability: Unix. -.. function:: link(src, dst) +.. function:: link(source, link_name) - Create a hard link pointing to *src* named *dst*. Availability: Unix. + Create a hard link pointing to *source* named *link_name*. Availability: + Unix. .. function:: listdir(path) @@ -1078,9 +1079,10 @@ :attr:`f_flag`, :attr:`f_namemax`. Availability: Unix. -.. function:: symlink(src, dst) +.. function:: symlink(source, link_name) - Create a symbolic link pointing to *src* named *dst*. Availability: Unix. + Create a symbolic link pointing to *source* named *link_name*. Availability: + Unix. .. function:: unlink(path) Modified: python/branches/py3k/Doc/library/string.rst ============================================================================== --- python/branches/py3k/Doc/library/string.rst (original) +++ python/branches/py3k/Doc/library/string.rst Mon Mar 30 16:51:56 2009 @@ -218,6 +218,7 @@ Some simple format string examples:: "First, thou shalt count to {0}" # References first positional argument + "Bring me a {}" # Implicitly references the first positional argument "My quest is {name}" # References keyword argument 'name' "Weight in tons {0.weight}" # 'weight' attribute of first positional arg "Units destroyed: {players[0]}" # First element of keyword argument 'players'. Modified: python/branches/py3k/Doc/library/webbrowser.rst ============================================================================== --- python/branches/py3k/Doc/library/webbrowser.rst (original) +++ python/branches/py3k/Doc/library/webbrowser.rst Mon Mar 30 16:51:56 2009 @@ -167,8 +167,8 @@ Browser Controller Objects -------------------------- -Browser controllers provide these methods which parallel two of the module-level -convenience functions: +Browser controllers provide these methods which parallel three of the +module-level convenience functions: .. method:: controller.open(url[, new[, autoraise=1]]) Modified: python/branches/py3k/Doc/reference/index.rst ============================================================================== --- python/branches/py3k/Doc/reference/index.rst (original) +++ python/branches/py3k/Doc/reference/index.rst Mon Mar 30 16:51:56 2009 @@ -18,6 +18,7 @@ .. toctree:: :maxdepth: 2 + :numbered: introduction.rst lexical_analysis.rst Modified: python/branches/py3k/Doc/tools/sphinxext/pyspecific.py ============================================================================== --- python/branches/py3k/Doc/tools/sphinxext/pyspecific.py (original) +++ python/branches/py3k/Doc/tools/sphinxext/pyspecific.py Mon Mar 30 16:51:56 2009 @@ -72,7 +72,9 @@ def write(self, *ignored): writer = TextWriter(self) - for label in self.status_iterator(pydoc_topic_labels, 'building topics... '): + for label in self.status_iterator(pydoc_topic_labels, + 'building topics... ', + length=len(pydoc_topic_labels)): if label not in self.env.labels: self.warn('label %r not in documentation' % label) continue Modified: python/branches/py3k/Doc/tutorial/index.rst ============================================================================== --- python/branches/py3k/Doc/tutorial/index.rst (original) +++ python/branches/py3k/Doc/tutorial/index.rst Mon Mar 30 16:51:56 2009 @@ -44,6 +44,7 @@ The :ref:`glossary` is also worth going through. .. toctree:: + :numbered: appetite.rst interpreter.rst Modified: python/branches/py3k/Doc/using/index.rst ============================================================================== --- python/branches/py3k/Doc/using/index.rst (original) +++ python/branches/py3k/Doc/using/index.rst Mon Mar 30 16:51:56 2009 @@ -11,6 +11,7 @@ .. toctree:: + :numbered: cmdline.rst unix.rst Modified: python/branches/py3k/Lib/distutils/version.py ============================================================================== --- python/branches/py3k/Lib/distutils/version.py (original) +++ python/branches/py3k/Lib/distutils/version.py Mon Mar 30 16:51:56 2009 @@ -207,7 +207,7 @@ # The rules according to Greg Stein: -# 1) a version number has 1 or more numbers separate by a period or by +# 1) a version number has 1 or more numbers separated by a period or by # sequences of letters. If only periods, then these are compared # left-to-right to determine an ordering. # 2) sequences of letters are part of the tuple for comparison and are Modified: python/branches/py3k/Lib/idlelib/configHandler.py ============================================================================== --- python/branches/py3k/Lib/idlelib/configHandler.py (original) +++ python/branches/py3k/Lib/idlelib/configHandler.py Mon Mar 30 16:51:56 2009 @@ -246,7 +246,7 @@ else: #returning default, print warning if warn_on_default: warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n' - ' problem retrieving configration option %r\n' + ' problem retrieving configuration option %r\n' ' from section %r.\n' ' returning default value: %r\n' % (option, section, default)) Deleted: python/branches/py3k/Lib/test/crashers/bogus_sre_bytecode.py ============================================================================== --- python/branches/py3k/Lib/test/crashers/bogus_sre_bytecode.py Mon Mar 30 16:51:56 2009 +++ (empty file) @@ -1,47 +0,0 @@ -""" -The regular expression engine in '_sre' can segfault when interpreting -bogus bytecode. - -It is unclear whether this is a real bug or a "won't fix" case like -bogus_code_obj.py, because it requires bytecode that is built by hand, -as opposed to compiled by 're' from a string-source regexp. The -difference with bogus_code_obj, though, is that the only existing regexp -compiler is written in Python, so that the C code has no choice but -accept arbitrary bytecode from Python-level. - -The test below builds and runs random bytecodes until 'match' crashes -Python. I have not investigated why exactly segfaults occur nor how -hard they would be to fix. Here are a few examples of 'code' that -segfault for me: - - [21, 50814, 8, 29, 16] - [21, 3967, 26, 10, 23, 54113] - [29, 23, 0, 2, 5] - [31, 64351, 0, 28, 3, 22281, 20, 4463, 9, 25, 59154, 15245, 2, - 16343, 3, 11600, 24380, 10, 37556, 10, 31, 15, 31] - -Here is also a 'code' that triggers an infinite uninterruptible loop: - - [29, 1, 8, 21, 1, 43083, 6] - -""" - -import _sre, random - -def pick(): - n = random.randrange(-65536, 65536) - if n < 0: - n &= 31 - return n - -ss = ["", "world", "x" * 500] - -while 1: - code = [pick() for i in range(random.randrange(5, 25))] - print(code) - pat = _sre.compile(None, 0, code) - for s in ss: - try: - pat.match(s) - except RuntimeError: - pass Deleted: python/branches/py3k/Lib/test/crashers/multithreaded_close.py ============================================================================== --- python/branches/py3k/Lib/test/crashers/multithreaded_close.py Mon Mar 30 16:51:56 2009 +++ (empty file) @@ -1,14 +0,0 @@ -# f.close() is not thread-safe: calling it at the same time as another -# operation (or another close) on the same file, but done from another -# thread, causes crashes. The issue is more complicated than it seems, -# witness the discussions in: -# -# http://bugs.python.org/issue595601 -# http://bugs.python.org/issue815646 - -import _thread - -while 1: - f = open("multithreaded_close.tmp", "w") - _thread.start_new_thread(f.close, ()) - f.close() Modified: python/branches/py3k/Modules/_tkinter.c ============================================================================== --- python/branches/py3k/Modules/_tkinter.c (original) +++ python/branches/py3k/Modules/_tkinter.c Mon Mar 30 16:51:56 2009 @@ -732,6 +732,7 @@ } +#ifdef WITH_THREAD static void Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev, Tcl_Condition *cond, Tcl_Mutex *mutex) @@ -744,6 +745,7 @@ Tcl_MutexUnlock(mutex); Py_END_ALLOW_THREADS } +#endif /** Tcl Eval **/ @@ -1110,8 +1112,8 @@ return newPyTclObject(value); } +#ifdef WITH_THREAD /* This mutex synchronizes inter-thread command calls. */ - TCL_DECLARE_MUTEX(call_mutex) typedef struct Tkapp_CallEvent { @@ -1123,6 +1125,7 @@ PyObject **exc_type, **exc_value, **exc_tb; Tcl_Condition *done; } Tkapp_CallEvent; +#endif void Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc) @@ -1210,6 +1213,8 @@ return res; } +#ifdef WITH_THREAD + /* Tkapp_CallProc is the event procedure that is executed in the context of the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't hold the Python lock. */ @@ -1254,6 +1259,8 @@ return 1; } +#endif + /* This is the main entry point for calling a Tcl command. It supports three cases, with regard to threading: 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in @@ -1483,9 +1490,11 @@ /** Tcl Variable **/ +typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags); + +#ifdef WITH_THREAD TCL_DECLARE_MUTEX(var_mutex) -typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags); typedef struct VarEvent { Tcl_Event ev; /* must be first */ PyObject *self; @@ -1497,6 +1506,7 @@ PyObject **exc_val; Tcl_Condition *cond; } VarEvent; +#endif static int varname_converter(PyObject *in, void *_out) @@ -1518,6 +1528,8 @@ return 0; } +#ifdef WITH_THREAD + static void var_perform(VarEvent *ev) { @@ -1545,11 +1557,13 @@ return 1; } +#endif + static PyObject* var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags) { - TkappObject *self = (TkappObject*)selfptr; #ifdef WITH_THREAD + TkappObject *self = (TkappObject*)selfptr; if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { TkappObject *self = (TkappObject*)selfptr; VarEvent *ev; @@ -2052,6 +2066,7 @@ +#ifdef WITH_THREAD TCL_DECLARE_MUTEX(command_mutex) typedef struct CommandEvent{ @@ -2078,6 +2093,7 @@ Tcl_MutexUnlock(&command_mutex); return 1; } +#endif static PyObject * Tkapp_CreateCommand(PyObject *selfptr, PyObject *args) @@ -2108,7 +2124,7 @@ Py_INCREF(func); data->self = selfptr; data->func = func; - +#ifdef WITH_THREAD if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { Tcl_Condition cond = NULL; CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent)); @@ -2122,7 +2138,9 @@ Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex); Tcl_ConditionFinalize(&cond); } - else { + else +#endif + { ENTER_TCL err = Tcl_CreateCommand( Tkapp_Interp(self), cmdName, PythonCmd, @@ -2150,6 +2168,8 @@ if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName)) return NULL; + +#ifdef WITH_THREAD if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { Tcl_Condition cond = NULL; CommandEvent *ev; @@ -2164,7 +2184,9 @@ &command_mutex); Tcl_ConditionFinalize(&cond); } - else { + else +#endif + { ENTER_TCL err = Tcl_DeleteCommand(self->interp, cmdName); LEAVE_TCL From python-checkins at python.org Mon Mar 30 16:55:03 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 30 Mar 2009 16:55:03 +0200 (CEST) Subject: [Python-checkins] r70708 - in python/branches/release30-maint: Doc/Makefile Doc/distutils/index.rst Doc/documenting/index.rst Doc/extending/index.rst Doc/library/index.rst Doc/library/os.rst Doc/library/string.rst Doc/library/webbrowser.rst Doc/reference/index.rst Doc/tools/sphinxext/pyspecific.py Doc/tutorial/index.rst Doc/using/index.rst Lib/distutils/version.py Lib/idlelib/configHandler.py Lib/test/crashers/bogus_sre_bytecode.py Lib/test/crashers/multithreaded_close.py Modules/_tkinter.c Message-ID: <20090330145503.37B431E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 30 16:55:02 2009 New Revision: 70708 Log: Merged revisions 70707 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70707 | benjamin.peterson | 2009-03-30 09:51:56 -0500 (Mon, 30 Mar 2009) | 58 lines Merged revisions 70578,70599,70641-70642,70650,70660-70661,70674,70691,70697-70698,70700,70704 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70578 | benjamin.peterson | 2009-03-23 22:24:56 -0500 (Mon, 23 Mar 2009) | 1 line this is better written using assertRaises ........ r70599 | benjamin.peterson | 2009-03-25 16:42:51 -0500 (Wed, 25 Mar 2009) | 1 line this can be slightly less ugly ........ r70641 | guilherme.polo | 2009-03-27 16:43:08 -0500 (Fri, 27 Mar 2009) | 3 lines Adjusted _tkinter to compile without warnings when WITH_THREAD is not defined (part of issue #5035) ........ r70642 | georg.brandl | 2009-03-27 19:48:48 -0500 (Fri, 27 Mar 2009) | 1 line Fix typo. ........ r70650 | benjamin.peterson | 2009-03-28 14:16:10 -0500 (Sat, 28 Mar 2009) | 1 line give os.symlink and os.link() better parameter names #5564 ........ r70660 | georg.brandl | 2009-03-28 14:52:58 -0500 (Sat, 28 Mar 2009) | 1 line Switch to fixed Sphinx version. ........ r70661 | georg.brandl | 2009-03-28 14:57:36 -0500 (Sat, 28 Mar 2009) | 2 lines Add section numbering to some of the larger subdocuments. ........ r70674 | guilherme.polo | 2009-03-29 05:19:05 -0500 (Sun, 29 Mar 2009) | 1 line Typo fix. ........ r70691 | raymond.hettinger | 2009-03-29 13:51:11 -0500 (Sun, 29 Mar 2009) | 1 line Make life easier for non-CPython implementations. ........ r70697 | benjamin.peterson | 2009-03-29 16:22:35 -0500 (Sun, 29 Mar 2009) | 1 line this has been fixed since 2.6 (I love removing these) ........ r70698 | benjamin.peterson | 2009-03-29 16:31:05 -0500 (Sun, 29 Mar 2009) | 1 line thanks to guido's bytecode verifier, this is fixed ........ r70700 | benjamin.peterson | 2009-03-29 16:50:14 -0500 (Sun, 29 Mar 2009) | 1 line use the awesome new status iterator ........ r70704 | benjamin.peterson | 2009-03-29 21:49:32 -0500 (Sun, 29 Mar 2009) | 1 line there's actually three methods here #5600 ........ ................ Removed: python/branches/release30-maint/Lib/test/crashers/bogus_sre_bytecode.py python/branches/release30-maint/Lib/test/crashers/multithreaded_close.py Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Doc/Makefile python/branches/release30-maint/Doc/distutils/index.rst python/branches/release30-maint/Doc/documenting/index.rst python/branches/release30-maint/Doc/extending/index.rst python/branches/release30-maint/Doc/library/index.rst python/branches/release30-maint/Doc/library/os.rst python/branches/release30-maint/Doc/library/string.rst python/branches/release30-maint/Doc/library/webbrowser.rst python/branches/release30-maint/Doc/reference/index.rst python/branches/release30-maint/Doc/tools/sphinxext/pyspecific.py python/branches/release30-maint/Doc/tutorial/index.rst python/branches/release30-maint/Doc/using/index.rst python/branches/release30-maint/Lib/distutils/version.py python/branches/release30-maint/Lib/idlelib/configHandler.py python/branches/release30-maint/Modules/_tkinter.c Modified: python/branches/release30-maint/Doc/Makefile ============================================================================== --- python/branches/release30-maint/Doc/Makefile (original) +++ python/branches/release30-maint/Doc/Makefile Mon Mar 30 16:55:02 2009 @@ -31,7 +31,7 @@ checkout: @if [ ! -d tools/sphinx ]; then \ echo "Checking out Sphinx..."; \ - svn checkout $(SVNROOT)/doctools/trunk/sphinx tools/sphinx; \ + svn checkout $(SVNROOT)/external/Sphinx-0.6.1/sphinx tools/sphinx; \ fi @if [ ! -d tools/docutils ]; then \ echo "Checking out Docutils..."; \ Modified: python/branches/release30-maint/Doc/distutils/index.rst ============================================================================== --- python/branches/release30-maint/Doc/distutils/index.rst (original) +++ python/branches/release30-maint/Doc/distutils/index.rst Mon Mar 30 16:55:02 2009 @@ -16,6 +16,7 @@ .. toctree:: :maxdepth: 2 + :numbered: introduction.rst setupscript.rst Modified: python/branches/release30-maint/Doc/documenting/index.rst ============================================================================== --- python/branches/release30-maint/Doc/documenting/index.rst (original) +++ python/branches/release30-maint/Doc/documenting/index.rst Mon Mar 30 16:55:02 2009 @@ -23,6 +23,7 @@ are more than welcome as well. .. toctree:: + :numbered: intro.rst style.rst Modified: python/branches/release30-maint/Doc/extending/index.rst ============================================================================== --- python/branches/release30-maint/Doc/extending/index.rst (original) +++ python/branches/release30-maint/Doc/extending/index.rst Mon Mar 30 16:55:02 2009 @@ -26,6 +26,7 @@ .. toctree:: :maxdepth: 2 + :numbered: extending.rst newtypes.rst Modified: python/branches/release30-maint/Doc/library/index.rst ============================================================================== --- python/branches/release30-maint/Doc/library/index.rst (original) +++ python/branches/release30-maint/Doc/library/index.rst Mon Mar 30 16:55:02 2009 @@ -38,6 +38,7 @@ .. toctree:: :maxdepth: 2 + :numbered: intro.rst functions.rst Modified: python/branches/release30-maint/Doc/library/os.rst ============================================================================== --- python/branches/release30-maint/Doc/library/os.rst (original) +++ python/branches/release30-maint/Doc/library/os.rst Mon Mar 30 16:55:02 2009 @@ -796,9 +796,10 @@ function will not follow symbolic links. Availability: Unix. -.. function:: link(src, dst) +.. function:: link(source, link_name) - Create a hard link pointing to *src* named *dst*. Availability: Unix. + Create a hard link pointing to *source* named *link_name*. Availability: + Unix. .. function:: listdir(path) @@ -1078,9 +1079,10 @@ :attr:`f_flag`, :attr:`f_namemax`. Availability: Unix. -.. function:: symlink(src, dst) +.. function:: symlink(source, link_name) - Create a symbolic link pointing to *src* named *dst*. Availability: Unix. + Create a symbolic link pointing to *source* named *link_name*. Availability: + Unix. .. function:: unlink(path) Modified: python/branches/release30-maint/Doc/library/string.rst ============================================================================== --- python/branches/release30-maint/Doc/library/string.rst (original) +++ python/branches/release30-maint/Doc/library/string.rst Mon Mar 30 16:55:02 2009 @@ -218,6 +218,7 @@ Some simple format string examples:: "First, thou shalt count to {0}" # References first positional argument + "Bring me a {}" # Implicitly references the first positional argument "My quest is {name}" # References keyword argument 'name' "Weight in tons {0.weight}" # 'weight' attribute of first positional arg "Units destroyed: {players[0]}" # First element of keyword argument 'players'. Modified: python/branches/release30-maint/Doc/library/webbrowser.rst ============================================================================== --- python/branches/release30-maint/Doc/library/webbrowser.rst (original) +++ python/branches/release30-maint/Doc/library/webbrowser.rst Mon Mar 30 16:55:02 2009 @@ -167,8 +167,8 @@ Browser Controller Objects -------------------------- -Browser controllers provide these methods which parallel two of the module-level -convenience functions: +Browser controllers provide these methods which parallel three of the +module-level convenience functions: .. method:: controller.open(url[, new[, autoraise=1]]) Modified: python/branches/release30-maint/Doc/reference/index.rst ============================================================================== --- python/branches/release30-maint/Doc/reference/index.rst (original) +++ python/branches/release30-maint/Doc/reference/index.rst Mon Mar 30 16:55:02 2009 @@ -18,6 +18,7 @@ .. toctree:: :maxdepth: 2 + :numbered: introduction.rst lexical_analysis.rst Modified: python/branches/release30-maint/Doc/tools/sphinxext/pyspecific.py ============================================================================== --- python/branches/release30-maint/Doc/tools/sphinxext/pyspecific.py (original) +++ python/branches/release30-maint/Doc/tools/sphinxext/pyspecific.py Mon Mar 30 16:55:02 2009 @@ -79,7 +79,9 @@ def write(self, *ignored): writer = TextWriter(self) - for label in self.status_iterator(pydoc_topic_labels, 'building topics... '): + for label in self.status_iterator(pydoc_topic_labels, + 'building topics... ', + length=len(pydoc_topic_labels)): if label not in self.env.labels: self.warn('label %r not in documentation' % label) continue Modified: python/branches/release30-maint/Doc/tutorial/index.rst ============================================================================== --- python/branches/release30-maint/Doc/tutorial/index.rst (original) +++ python/branches/release30-maint/Doc/tutorial/index.rst Mon Mar 30 16:55:02 2009 @@ -44,6 +44,7 @@ The :ref:`glossary` is also worth going through. .. toctree:: + :numbered: appetite.rst interpreter.rst Modified: python/branches/release30-maint/Doc/using/index.rst ============================================================================== --- python/branches/release30-maint/Doc/using/index.rst (original) +++ python/branches/release30-maint/Doc/using/index.rst Mon Mar 30 16:55:02 2009 @@ -11,6 +11,7 @@ .. toctree:: + :numbered: cmdline.rst unix.rst Modified: python/branches/release30-maint/Lib/distutils/version.py ============================================================================== --- python/branches/release30-maint/Lib/distutils/version.py (original) +++ python/branches/release30-maint/Lib/distutils/version.py Mon Mar 30 16:55:02 2009 @@ -207,7 +207,7 @@ # The rules according to Greg Stein: -# 1) a version number has 1 or more numbers separate by a period or by +# 1) a version number has 1 or more numbers separated by a period or by # sequences of letters. If only periods, then these are compared # left-to-right to determine an ordering. # 2) sequences of letters are part of the tuple for comparison and are Modified: python/branches/release30-maint/Lib/idlelib/configHandler.py ============================================================================== --- python/branches/release30-maint/Lib/idlelib/configHandler.py (original) +++ python/branches/release30-maint/Lib/idlelib/configHandler.py Mon Mar 30 16:55:02 2009 @@ -246,7 +246,7 @@ else: #returning default, print warning if warn_on_default: warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n' - ' problem retrieving configration option %r\n' + ' problem retrieving configuration option %r\n' ' from section %r.\n' ' returning default value: %r\n' % (option, section, default)) Deleted: python/branches/release30-maint/Lib/test/crashers/bogus_sre_bytecode.py ============================================================================== --- python/branches/release30-maint/Lib/test/crashers/bogus_sre_bytecode.py Mon Mar 30 16:55:02 2009 +++ (empty file) @@ -1,47 +0,0 @@ -""" -The regular expression engine in '_sre' can segfault when interpreting -bogus bytecode. - -It is unclear whether this is a real bug or a "won't fix" case like -bogus_code_obj.py, because it requires bytecode that is built by hand, -as opposed to compiled by 're' from a string-source regexp. The -difference with bogus_code_obj, though, is that the only existing regexp -compiler is written in Python, so that the C code has no choice but -accept arbitrary bytecode from Python-level. - -The test below builds and runs random bytecodes until 'match' crashes -Python. I have not investigated why exactly segfaults occur nor how -hard they would be to fix. Here are a few examples of 'code' that -segfault for me: - - [21, 50814, 8, 29, 16] - [21, 3967, 26, 10, 23, 54113] - [29, 23, 0, 2, 5] - [31, 64351, 0, 28, 3, 22281, 20, 4463, 9, 25, 59154, 15245, 2, - 16343, 3, 11600, 24380, 10, 37556, 10, 31, 15, 31] - -Here is also a 'code' that triggers an infinite uninterruptible loop: - - [29, 1, 8, 21, 1, 43083, 6] - -""" - -import _sre, random - -def pick(): - n = random.randrange(-65536, 65536) - if n < 0: - n &= 31 - return n - -ss = ["", "world", "x" * 500] - -while 1: - code = [pick() for i in range(random.randrange(5, 25))] - print(code) - pat = _sre.compile(None, 0, code) - for s in ss: - try: - pat.match(s) - except RuntimeError: - pass Deleted: python/branches/release30-maint/Lib/test/crashers/multithreaded_close.py ============================================================================== --- python/branches/release30-maint/Lib/test/crashers/multithreaded_close.py Mon Mar 30 16:55:02 2009 +++ (empty file) @@ -1,14 +0,0 @@ -# f.close() is not thread-safe: calling it at the same time as another -# operation (or another close) on the same file, but done from another -# thread, causes crashes. The issue is more complicated than it seems, -# witness the discussions in: -# -# http://bugs.python.org/issue595601 -# http://bugs.python.org/issue815646 - -import _thread - -while 1: - f = open("multithreaded_close.tmp", "w") - _thread.start_new_thread(f.close, ()) - f.close() Modified: python/branches/release30-maint/Modules/_tkinter.c ============================================================================== --- python/branches/release30-maint/Modules/_tkinter.c (original) +++ python/branches/release30-maint/Modules/_tkinter.c Mon Mar 30 16:55:02 2009 @@ -696,6 +696,7 @@ } +#ifdef WITH_THREAD static void Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev, Tcl_Condition *cond, Tcl_Mutex *mutex) @@ -708,6 +709,7 @@ Tcl_MutexUnlock(mutex); Py_END_ALLOW_THREADS } +#endif /** Tcl Eval **/ @@ -1074,8 +1076,8 @@ return newPyTclObject(value); } +#ifdef WITH_THREAD /* This mutex synchronizes inter-thread command calls. */ - TCL_DECLARE_MUTEX(call_mutex) typedef struct Tkapp_CallEvent { @@ -1087,6 +1089,7 @@ PyObject **exc_type, **exc_value, **exc_tb; Tcl_Condition done; } Tkapp_CallEvent; +#endif void Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc) @@ -1174,6 +1177,8 @@ return res; } +#ifdef WITH_THREAD + /* Tkapp_CallProc is the event procedure that is executed in the context of the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't hold the Python lock. */ @@ -1218,6 +1223,8 @@ return 1; } +#endif + /* This is the main entry point for calling a Tcl command. It supports three cases, with regard to threading: 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in @@ -1445,9 +1452,11 @@ /** Tcl Variable **/ +typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags); + +#ifdef WITH_THREAD TCL_DECLARE_MUTEX(var_mutex) -typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags); typedef struct VarEvent { Tcl_Event ev; /* must be first */ PyObject *self; @@ -1459,6 +1468,7 @@ PyObject **exc_val; Tcl_Condition cond; } VarEvent; +#endif static int varname_converter(PyObject *in, void *_out) @@ -1480,6 +1490,8 @@ return 0; } +#ifdef WITH_THREAD + static void var_perform(VarEvent *ev) { @@ -1507,11 +1519,13 @@ return 1; } +#endif + static PyObject* var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags) { - TkappObject *self = (TkappObject*)selfptr; #ifdef WITH_THREAD + TkappObject *self = (TkappObject*)selfptr; if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { TkappObject *self = (TkappObject*)selfptr; VarEvent *ev; @@ -2012,6 +2026,7 @@ +#ifdef WITH_THREAD TCL_DECLARE_MUTEX(command_mutex) typedef struct CommandEvent{ @@ -2038,6 +2053,7 @@ Tcl_MutexUnlock(&command_mutex); return 1; } +#endif static PyObject * Tkapp_CreateCommand(PyObject *selfptr, PyObject *args) @@ -2068,7 +2084,7 @@ Py_INCREF(func); data->self = selfptr; data->func = func; - +#ifdef WITH_THREAD if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent)); ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc; @@ -2080,7 +2096,9 @@ ev->done = NULL; Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex); } - else { + else +#endif + { ENTER_TCL err = Tcl_CreateCommand( Tkapp_Interp(self), cmdName, PythonCmd, @@ -2108,6 +2126,8 @@ if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName)) return NULL; + +#ifdef WITH_THREAD if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { CommandEvent *ev; ev = (CommandEvent*)ckalloc(sizeof(CommandEvent)); @@ -2120,7 +2140,9 @@ Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex); } - else { + else +#endif + { ENTER_TCL err = Tcl_DeleteCommand(self->interp, cmdName); LEAVE_TCL From python-checkins at python.org Mon Mar 30 17:04:16 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 30 Mar 2009 17:04:16 +0200 (CEST) Subject: [Python-checkins] r70709 - in python/branches/py3k: Doc/library/unittest.rst Lib/email/test/test_email_codecs_renamed.py Lib/test/test_fork1.py Tools/scripts/reindent-rst.py Message-ID: <20090330150416.821121E4002@bag.python.org> Author: benjamin.peterson Date: Mon Mar 30 17:04:16 2009 New Revision: 70709 Log: Merged revisions 70656,70668-70669,70671,70701,70703,70706 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70656 | georg.brandl | 2009-03-28 14:33:33 -0500 (Sat, 28 Mar 2009) | 2 lines Add a script to fixup rst files if the pre-commit hook rejects them. ........ r70668 | benjamin.peterson | 2009-03-28 22:16:57 -0500 (Sat, 28 Mar 2009) | 1 line a more realistic example ........ r70669 | benjamin.peterson | 2009-03-28 22:31:40 -0500 (Sat, 28 Mar 2009) | 1 line stop the versionchanged directive from hiding the docs ........ r70671 | benjamin.peterson | 2009-03-28 22:39:58 -0500 (Sat, 28 Mar 2009) | 1 line fix consistency ........ r70701 | benjamin.peterson | 2009-03-29 17:27:26 -0500 (Sun, 29 Mar 2009) | 1 line add missing import ........ r70703 | benjamin.peterson | 2009-03-29 21:14:21 -0500 (Sun, 29 Mar 2009) | 1 line fix import ........ r70706 | benjamin.peterson | 2009-03-30 09:42:23 -0500 (Mon, 30 Mar 2009) | 1 line add missing import ........ Added: python/branches/py3k/Tools/scripts/reindent-rst.py - copied unchanged from r70656, /python/trunk/Tools/scripts/reindent-rst.py Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/unittest.rst python/branches/py3k/Lib/email/test/test_email_codecs_renamed.py python/branches/py3k/Lib/test/test_fork1.py Modified: python/branches/py3k/Doc/library/unittest.rst ============================================================================== --- python/branches/py3k/Doc/library/unittest.rst (original) +++ python/branches/py3k/Doc/library/unittest.rst Mon Mar 30 17:04:16 2009 @@ -446,12 +446,26 @@ def test_nothing(self): self.fail("shouldn't happen") + @unittest.skipIf(mylib.__version__ < (1, 3), "not supported in this library version") + def test_format(self): + # Tests that work for only a certain version of the library. + pass + + @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") + def test_windows_support(self): + # windows specific testing code + pass + This is the output of running the example above in verbose mode: :: + test_format (__main__.MyTestCase) ... skipped 'not supported in this library version' test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping' + test_windows_support (__main__.MyTestCase) ... skipped 'requires Windows' ---------------------------------------------------------------------- - Ran 1 test in 0.072s + Ran 3 tests in 0.005s + + OK (skipped=3) Classes can be skipped just like methods: :: @@ -657,13 +671,15 @@ To catch any of a group of exceptions, a tuple containing the exception classes may be passed as *exception*. - .. versionchanged:: 3.1 + If *callable* is omitted or None, returns a context manager so that the + code under test can be written inline rather than as a function:: - If *callable* is omitted or None, returns a context manager so that the - code under test can be written inline rather than as a function:: + with self.failUnlessRaises(some_error_class): + do_something() + + .. versionchanged:: 3.1 + Added the ability to use :meth:`assertRaises` as a context manager. - with self.failUnlessRaises(some_error_class): - do_something() .. method:: failIf(expr[, msg]) assertFalse(expr[, msg]) Modified: python/branches/py3k/Lib/email/test/test_email_codecs_renamed.py ============================================================================== --- python/branches/py3k/Lib/email/test/test_email_codecs_renamed.py (original) +++ python/branches/py3k/Lib/email/test/test_email_codecs_renamed.py Mon Mar 30 17:04:16 2009 @@ -3,7 +3,7 @@ # email package unit tests for (optional) Asian codecs import unittest -from test.support import TestSkipped, run_unittest +from test.support import run_unittest from email.test.test_email import TestEmailBase from email.charset import Charset @@ -15,7 +15,7 @@ try: str('foo', 'euc-jp') except LookupError: - raise TestSkipped + raise unittest.SkipTest Modified: python/branches/py3k/Lib/test/test_fork1.py ============================================================================== --- python/branches/py3k/Lib/test/test_fork1.py (original) +++ python/branches/py3k/Lib/test/test_fork1.py Mon Mar 30 17:04:16 2009 @@ -3,6 +3,7 @@ import os import time +import unittest from test.fork_wait import ForkWait from test.support import run_unittest, reap_children From python-checkins at python.org Mon Mar 30 17:09:20 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 30 Mar 2009 17:09:20 +0200 (CEST) Subject: [Python-checkins] r70710 - in python/branches/release26-maint: Doc/Makefile Message-ID: <20090330150920.10C401E400C@bag.python.org> Author: benjamin.peterson Date: Mon Mar 30 17:09:19 2009 New Revision: 70710 Log: Merged revisions 70660 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70660 | georg.brandl | 2009-03-28 14:52:58 -0500 (Sat, 28 Mar 2009) | 1 line Switch to fixed Sphinx version. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/Makefile Modified: python/branches/release26-maint/Doc/Makefile ============================================================================== --- python/branches/release26-maint/Doc/Makefile (original) +++ python/branches/release26-maint/Doc/Makefile Mon Mar 30 17:09:19 2009 @@ -31,7 +31,7 @@ checkout: @if [ ! -d tools/sphinx ]; then \ echo "Checking out Sphinx..."; \ - svn checkout $(SVNROOT)/doctools/trunk/sphinx tools/sphinx; \ + svn checkout $(SVNROOT)/external/Sphinx-0.6.1/sphinx tools/sphinx; \ fi @if [ ! -d tools/docutils ]; then \ echo "Checking out Docutils..."; \ From python-checkins at python.org Mon Mar 30 17:14:02 2009 From: python-checkins at python.org (r.david.murray) Date: Mon, 30 Mar 2009 17:14:02 +0200 (CEST) Subject: [Python-checkins] r70711 - python/trunk/Lib/test/test_fork1.py Message-ID: <20090330151402.45A471E4002@bag.python.org> Author: r.david.murray Date: Mon Mar 30 17:14:01 2009 New Revision: 70711 Log: Convert import try/except to use test_support.import_module(). Modified: python/trunk/Lib/test/test_fork1.py Modified: python/trunk/Lib/test/test_fork1.py ============================================================================== --- python/trunk/Lib/test/test_fork1.py (original) +++ python/trunk/Lib/test/test_fork1.py Mon Mar 30 17:14:01 2009 @@ -3,14 +3,11 @@ import os import time -import unittest from test.fork_wait import ForkWait -from test.test_support import run_unittest, reap_children +from test.test_support import run_unittest, reap_children, import_module + +import_module('os.fork') -try: - os.fork -except AttributeError: - raise unittest.SkipTest, "os.fork not defined -- skipping test_fork1" class ForkTest(ForkWait): def wait_impl(self, cpid): From python-checkins at python.org Mon Mar 30 17:15:38 2009 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 30 Mar 2009 17:15:38 +0200 (CEST) Subject: [Python-checkins] r70712 - python/trunk/Lib/test/test_pprint.py Message-ID: <20090330151538.AB2921E403B@bag.python.org> Author: benjamin.peterson Date: Mon Mar 30 17:15:38 2009 New Revision: 70712 Log: don't rely on the order dict repr #5605 Modified: python/trunk/Lib/test/test_pprint.py Modified: python/trunk/Lib/test/test_pprint.py ============================================================================== --- python/trunk/Lib/test/test_pprint.py (original) +++ python/trunk/Lib/test/test_pprint.py Mon Mar 30 17:15:38 2009 @@ -121,10 +121,10 @@ {}, dict2(), dict3(), verify, pprint, -6, -6L, -6-6j, -1.5, "x", uni("x"), (3,), [3], {3: 6}, - (1,2), [3,4], {5: 6, 7: 8}, + (1,2), [3,4], {5: 6}, tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), [3,4], list2([3,4]), list3([3,4]), list3(range(100)), - {5: 6, 7: 8}, dict2({5: 6}), dict3({5: 6}), + dict2({5: 6}), dict3({5: 6}), range(10, -11, -1) ): native = repr(simple) From python-checkins at python.org Mon Mar 30 17:20:47 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 17:20:47 +0200 (CEST) Subject: [Python-checkins] r70713 - in python/trunk/Mac/Modules/qt: _Qtmodule.c qtsupport.py Message-ID: <20090330152047.23BCF1E402E@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 17:20:46 2009 New Revision: 70713 Log: This patch fixes issue 1254695 (wrong argument type conversion in Carbon.Qt) Modified: python/trunk/Mac/Modules/qt/_Qtmodule.c python/trunk/Mac/Modules/qt/qtsupport.py Modified: python/trunk/Mac/Modules/qt/_Qtmodule.c ============================================================================== --- python/trunk/Mac/Modules/qt/_Qtmodule.c (original) +++ python/trunk/Mac/Modules/qt/_Qtmodule.c Mon Mar 30 17:20:46 2009 @@ -11551,7 +11551,7 @@ PyMac_PRECHECK(GraphicsImportSetDataReference); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataReType)) return NULL; @@ -11574,7 +11574,7 @@ PyMac_PRECHECK(GraphicsImportGetDataReference); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDataReference(ci, &dataRef, @@ -11596,7 +11596,7 @@ PyMac_PRECHECK(GraphicsImportSetDataFile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile)) return NULL; _rv = GraphicsImportSetDataFile(ci, @@ -11616,7 +11616,7 @@ PyMac_PRECHECK(GraphicsImportGetDataFile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile)) return NULL; _rv = GraphicsImportGetDataFile(ci, @@ -11636,7 +11636,7 @@ PyMac_PRECHECK(GraphicsImportSetDataHandle); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &h)) return NULL; _rv = GraphicsImportSetDataHandle(ci, @@ -11656,7 +11656,7 @@ PyMac_PRECHECK(GraphicsImportGetDataHandle); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDataHandle(ci, &h); @@ -11676,7 +11676,7 @@ PyMac_PRECHECK(GraphicsImportGetImageDescription); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetImageDescription(ci, &desc); @@ -11697,7 +11697,7 @@ PyMac_PRECHECK(GraphicsImportGetDataOffsetAndSize); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDataOffsetAndSize(ci, &offset, @@ -11721,7 +11721,7 @@ PyMac_PRECHECK(GraphicsImportReadData); #endif if (!PyArg_ParseTuple(_args, "O&sll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &dataPtr, &dataOffset, &dataSize)) @@ -11745,7 +11745,7 @@ PyMac_PRECHECK(GraphicsImportSetClip); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &clipRgn)) return NULL; _rv = GraphicsImportSetClip(ci, @@ -11765,7 +11765,7 @@ PyMac_PRECHECK(GraphicsImportGetClip); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetClip(ci, &clipRgn); @@ -11785,7 +11785,7 @@ PyMac_PRECHECK(GraphicsImportSetSourceRect); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetRect, &sourceRect)) return NULL; _rv = GraphicsImportSetSourceRect(ci, @@ -11805,7 +11805,7 @@ PyMac_PRECHECK(GraphicsImportGetSourceRect); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetSourceRect(ci, &sourceRect); @@ -11825,7 +11825,7 @@ PyMac_PRECHECK(GraphicsImportGetNaturalBounds); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetNaturalBounds(ci, &naturalBounds); @@ -11844,7 +11844,7 @@ PyMac_PRECHECK(GraphicsImportDraw); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportDraw(ci); _res = Py_BuildValue("l", @@ -11863,7 +11863,7 @@ PyMac_PRECHECK(GraphicsImportSetGWorld); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, GrafObj_Convert, &port, OptResObj_Convert, &gd)) return NULL; @@ -11886,7 +11886,7 @@ PyMac_PRECHECK(GraphicsImportGetGWorld); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetGWorld(ci, &port, @@ -11908,7 +11908,7 @@ PyMac_PRECHECK(GraphicsImportSetBoundsRect); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetRect, &bounds)) return NULL; _rv = GraphicsImportSetBoundsRect(ci, @@ -11928,7 +11928,7 @@ PyMac_PRECHECK(GraphicsImportGetBoundsRect); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetBoundsRect(ci, &bounds); @@ -11949,7 +11949,7 @@ PyMac_PRECHECK(GraphicsImportSaveAsPicture); #endif if (!PyArg_ParseTuple(_args, "O&O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &fss, &scriptTag)) return NULL; @@ -11972,7 +11972,7 @@ PyMac_PRECHECK(GraphicsImportSetGraphicsMode); #endif if (!PyArg_ParseTuple(_args, "O&lO&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &graphicsMode, QdRGB_Convert, &opColor)) return NULL; @@ -11995,7 +11995,7 @@ PyMac_PRECHECK(GraphicsImportGetGraphicsMode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetGraphicsMode(ci, &graphicsMode, @@ -12017,7 +12017,7 @@ PyMac_PRECHECK(GraphicsImportSetQuality); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &quality)) return NULL; _rv = GraphicsImportSetQuality(ci, @@ -12037,7 +12037,7 @@ PyMac_PRECHECK(GraphicsImportGetQuality); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetQuality(ci, &quality); @@ -12058,7 +12058,7 @@ PyMac_PRECHECK(GraphicsImportSaveAsQuickTimeImageFile); #endif if (!PyArg_ParseTuple(_args, "O&O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &fss, &scriptTag)) return NULL; @@ -12081,7 +12081,7 @@ PyMac_PRECHECK(GraphicsImportSetDataReferenceOffsetAndLimit); #endif if (!PyArg_ParseTuple(_args, "O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &offset, &limit)) return NULL; @@ -12104,7 +12104,7 @@ PyMac_PRECHECK(GraphicsImportGetDataReferenceOffsetAndLimit); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDataReferenceOffsetAndLimit(ci, &offset, @@ -12127,7 +12127,7 @@ PyMac_PRECHECK(GraphicsImportGetAliasedDataReference); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetAliasedDataReference(ci, &dataRef, @@ -12149,7 +12149,7 @@ PyMac_PRECHECK(GraphicsImportValidate); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportValidate(ci, &valid); @@ -12169,7 +12169,7 @@ PyMac_PRECHECK(GraphicsImportGetMetaData); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &userData)) return NULL; _rv = GraphicsImportGetMetaData(ci, @@ -12189,7 +12189,7 @@ PyMac_PRECHECK(GraphicsImportGetMIMETypeList); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainerPtr)) return NULL; _rv = GraphicsImportGetMIMETypeList(ci, @@ -12209,7 +12209,7 @@ PyMac_PRECHECK(GraphicsImportDoesDrawAllPixels); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportDoesDrawAllPixels(ci, &drawsAllPixels); @@ -12229,7 +12229,7 @@ PyMac_PRECHECK(GraphicsImportGetAsPicture); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetAsPicture(ci, &picture); @@ -12252,7 +12252,7 @@ PyMac_PRECHECK(GraphicsImportExportImageFile); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetOSType, &fileType, PyMac_GetOSType, &fileCreator, PyMac_GetFSSpec, &fss, @@ -12278,7 +12278,7 @@ PyMac_PRECHECK(GraphicsImportGetExportImageTypeList); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainerPtr)) return NULL; _rv = GraphicsImportGetExportImageTypeList(ci, @@ -12298,7 +12298,7 @@ PyMac_PRECHECK(GraphicsImportGetExportSettingsAsAtomContainer); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainerPtr)) return NULL; _rv = GraphicsImportGetExportSettingsAsAtomContainer(ci, @@ -12318,7 +12318,7 @@ PyMac_PRECHECK(GraphicsImportSetExportSettingsFromAtomContainer); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainer)) return NULL; _rv = GraphicsImportSetExportSettingsFromAtomContainer(ci, @@ -12338,7 +12338,7 @@ PyMac_PRECHECK(GraphicsImportGetImageCount); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetImageCount(ci, &imageCount); @@ -12358,7 +12358,7 @@ PyMac_PRECHECK(GraphicsImportSetImageIndex); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &imageIndex)) return NULL; _rv = GraphicsImportSetImageIndex(ci, @@ -12378,7 +12378,7 @@ PyMac_PRECHECK(GraphicsImportGetImageIndex); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetImageIndex(ci, &imageIndex); @@ -12399,7 +12399,7 @@ PyMac_PRECHECK(GraphicsImportGetDataOffsetAndSize64); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDataOffsetAndSize64(ci, &offset, @@ -12423,7 +12423,7 @@ PyMac_PRECHECK(GraphicsImportReadData64); #endif if (!PyArg_ParseTuple(_args, "O&sO&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &dataPtr, PyMac_Getwide, &dataOffset, &dataSize)) @@ -12448,7 +12448,7 @@ PyMac_PRECHECK(GraphicsImportSetDataReferenceOffsetAndLimit64); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_Getwide, &offset, PyMac_Getwide, &limit)) return NULL; @@ -12471,7 +12471,7 @@ PyMac_PRECHECK(GraphicsImportGetDataReferenceOffsetAndLimit64); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDataReferenceOffsetAndLimit64(ci, &offset, @@ -12493,7 +12493,7 @@ PyMac_PRECHECK(GraphicsImportGetDefaultClip); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDefaultClip(ci, &defaultRgn); @@ -12514,7 +12514,7 @@ PyMac_PRECHECK(GraphicsImportGetDefaultGraphicsMode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDefaultGraphicsMode(ci, &defaultGraphicsMode, @@ -12536,7 +12536,7 @@ PyMac_PRECHECK(GraphicsImportGetDefaultSourceRect); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDefaultSourceRect(ci, &defaultSourceRect); @@ -12556,7 +12556,7 @@ PyMac_PRECHECK(GraphicsImportGetColorSyncProfile); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetColorSyncProfile(ci, &profile); @@ -12576,7 +12576,7 @@ PyMac_PRECHECK(GraphicsImportSetDestRect); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetRect, &destRect)) return NULL; _rv = GraphicsImportSetDestRect(ci, @@ -12596,7 +12596,7 @@ PyMac_PRECHECK(GraphicsImportGetDestRect); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDestRect(ci, &destRect); @@ -12616,7 +12616,7 @@ PyMac_PRECHECK(GraphicsImportSetFlags); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &flags)) return NULL; _rv = GraphicsImportSetFlags(ci, @@ -12636,7 +12636,7 @@ PyMac_PRECHECK(GraphicsImportGetFlags); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetFlags(ci, &flags); @@ -12657,7 +12657,7 @@ PyMac_PRECHECK(GraphicsImportGetBaseDataOffsetAndSize64); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetBaseDataOffsetAndSize64(ci, &offset, @@ -12678,7 +12678,7 @@ PyMac_PRECHECK(GraphicsImportSetImageIndexToThumbnail); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportSetImageIndexToThumbnail(ci); _res = Py_BuildValue("l", @@ -12696,7 +12696,7 @@ PyMac_PRECHECK(GraphicsExportDoExport); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportDoExport(ci, &actualSizeWritten); @@ -12716,7 +12716,7 @@ PyMac_PRECHECK(GraphicsExportCanTranscode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportCanTranscode(ci, &canTranscode); @@ -12735,7 +12735,7 @@ PyMac_PRECHECK(GraphicsExportDoTranscode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportDoTranscode(ci); _res = Py_BuildValue("l", @@ -12754,7 +12754,7 @@ PyMac_PRECHECK(GraphicsExportCanUseCompressor); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &codecSettingsAtomContainerPtr)) return NULL; _rv = GraphicsExportCanUseCompressor(ci, @@ -12777,7 +12777,7 @@ PyMac_PRECHECK(GraphicsExportDoUseCompressor); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &codecSettingsAtomContainer)) return NULL; _rv = GraphicsExportDoUseCompressor(ci, @@ -12798,7 +12798,7 @@ PyMac_PRECHECK(GraphicsExportDoStandaloneExport); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportDoStandaloneExport(ci); _res = Py_BuildValue("l", @@ -12817,7 +12817,7 @@ PyMac_PRECHECK(GraphicsExportGetDefaultFileTypeAndCreator); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetDefaultFileTypeAndCreator(ci, &fileType, @@ -12839,7 +12839,7 @@ PyMac_PRECHECK(GraphicsExportGetDefaultFileNameExtension); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetDefaultFileNameExtension(ci, &fileNameExtension); @@ -12859,7 +12859,7 @@ PyMac_PRECHECK(GraphicsExportGetMIMETypeList); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainerPtr)) return NULL; _rv = GraphicsExportGetMIMETypeList(ci, @@ -12879,7 +12879,7 @@ PyMac_PRECHECK(GraphicsExportSetSettingsFromAtomContainer); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainer)) return NULL; _rv = GraphicsExportSetSettingsFromAtomContainer(ci, @@ -12899,7 +12899,7 @@ PyMac_PRECHECK(GraphicsExportGetSettingsAsAtomContainer); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainerPtr)) return NULL; _rv = GraphicsExportGetSettingsAsAtomContainer(ci, @@ -12919,7 +12919,7 @@ PyMac_PRECHECK(GraphicsExportGetSettingsAsText); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetSettingsAsText(ci, &theText); @@ -12939,7 +12939,7 @@ PyMac_PRECHECK(GraphicsExportSetDontRecompress); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &dontRecompress)) return NULL; _rv = GraphicsExportSetDontRecompress(ci, @@ -12959,7 +12959,7 @@ PyMac_PRECHECK(GraphicsExportGetDontRecompress); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetDontRecompress(ci, &dontRecompress); @@ -12979,7 +12979,7 @@ PyMac_PRECHECK(GraphicsExportSetInterlaceStyle); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &interlaceStyle)) return NULL; _rv = GraphicsExportSetInterlaceStyle(ci, @@ -12999,7 +12999,7 @@ PyMac_PRECHECK(GraphicsExportGetInterlaceStyle); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInterlaceStyle(ci, &interlaceStyle); @@ -13019,7 +13019,7 @@ PyMac_PRECHECK(GraphicsExportSetMetaData); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &userData)) return NULL; _rv = GraphicsExportSetMetaData(ci, @@ -13039,7 +13039,7 @@ PyMac_PRECHECK(GraphicsExportGetMetaData); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &userData)) return NULL; _rv = GraphicsExportGetMetaData(ci, @@ -13059,7 +13059,7 @@ PyMac_PRECHECK(GraphicsExportSetTargetDataSize); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &targetDataSize)) return NULL; _rv = GraphicsExportSetTargetDataSize(ci, @@ -13079,7 +13079,7 @@ PyMac_PRECHECK(GraphicsExportGetTargetDataSize); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetTargetDataSize(ci, &targetDataSize); @@ -13099,7 +13099,7 @@ PyMac_PRECHECK(GraphicsExportSetCompressionMethod); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &compressionMethod)) return NULL; _rv = GraphicsExportSetCompressionMethod(ci, @@ -13119,7 +13119,7 @@ PyMac_PRECHECK(GraphicsExportGetCompressionMethod); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetCompressionMethod(ci, &compressionMethod); @@ -13139,7 +13139,7 @@ PyMac_PRECHECK(GraphicsExportSetCompressionQuality); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &spatialQuality)) return NULL; _rv = GraphicsExportSetCompressionQuality(ci, @@ -13159,7 +13159,7 @@ PyMac_PRECHECK(GraphicsExportGetCompressionQuality); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetCompressionQuality(ci, &spatialQuality); @@ -13180,7 +13180,7 @@ PyMac_PRECHECK(GraphicsExportSetResolution); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFixed, &horizontalResolution, PyMac_GetFixed, &verticalResolution)) return NULL; @@ -13203,7 +13203,7 @@ PyMac_PRECHECK(GraphicsExportGetResolution); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetResolution(ci, &horizontalResolution, @@ -13225,7 +13225,7 @@ PyMac_PRECHECK(GraphicsExportSetDepth); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &depth)) return NULL; _rv = GraphicsExportSetDepth(ci, @@ -13245,7 +13245,7 @@ PyMac_PRECHECK(GraphicsExportGetDepth); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetDepth(ci, &depth); @@ -13265,7 +13265,7 @@ PyMac_PRECHECK(GraphicsExportSetColorSyncProfile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &colorSyncProfile)) return NULL; _rv = GraphicsExportSetColorSyncProfile(ci, @@ -13285,7 +13285,7 @@ PyMac_PRECHECK(GraphicsExportGetColorSyncProfile); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetColorSyncProfile(ci, &colorSyncProfile); @@ -13307,7 +13307,7 @@ PyMac_PRECHECK(GraphicsExportSetInputDataReference); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType, ResObj_Convert, &desc)) @@ -13332,7 +13332,7 @@ PyMac_PRECHECK(GraphicsExportGetInputDataReference); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputDataReference(ci, &dataRef, @@ -13355,7 +13355,7 @@ PyMac_PRECHECK(GraphicsExportSetInputFile); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile, ResObj_Convert, &desc)) return NULL; @@ -13377,7 +13377,7 @@ PyMac_PRECHECK(GraphicsExportGetInputFile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile)) return NULL; _rv = GraphicsExportGetInputFile(ci, @@ -13398,7 +13398,7 @@ PyMac_PRECHECK(GraphicsExportSetInputHandle); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &h, ResObj_Convert, &desc)) return NULL; @@ -13420,7 +13420,7 @@ PyMac_PRECHECK(GraphicsExportGetInputHandle); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputHandle(ci, &h); @@ -13442,7 +13442,7 @@ PyMac_PRECHECK(GraphicsExportSetInputPtr); #endif if (!PyArg_ParseTuple(_args, "O&slO&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &p, &size, ResObj_Convert, &desc)) @@ -13466,8 +13466,8 @@ PyMac_PRECHECK(GraphicsExportSetInputGraphicsImporter); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, - CmpObj_Convert, &grip)) + CmpInstObj_Convert, &ci, + CmpInstObj_Convert, &grip)) return NULL; _rv = GraphicsExportSetInputGraphicsImporter(ci, grip); @@ -13486,13 +13486,13 @@ PyMac_PRECHECK(GraphicsExportGetInputGraphicsImporter); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputGraphicsImporter(ci, &grip); _res = Py_BuildValue("lO&", _rv, - CmpObj_New, grip); + CmpInstObj_New, grip); return _res; } @@ -13506,7 +13506,7 @@ PyMac_PRECHECK(GraphicsExportSetInputPicture); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &picture)) return NULL; _rv = GraphicsExportSetInputPicture(ci, @@ -13526,7 +13526,7 @@ PyMac_PRECHECK(GraphicsExportGetInputPicture); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputPicture(ci, &picture); @@ -13546,7 +13546,7 @@ PyMac_PRECHECK(GraphicsExportSetInputGWorld); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, GWorldObj_Convert, &gworld)) return NULL; _rv = GraphicsExportSetInputGWorld(ci, @@ -13566,7 +13566,7 @@ PyMac_PRECHECK(GraphicsExportGetInputGWorld); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputGWorld(ci, &gworld); @@ -13586,7 +13586,7 @@ PyMac_PRECHECK(GraphicsExportSetInputPixmap); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &pixmap)) return NULL; _rv = GraphicsExportSetInputPixmap(ci, @@ -13606,7 +13606,7 @@ PyMac_PRECHECK(GraphicsExportGetInputPixmap); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputPixmap(ci, &pixmap); @@ -13627,7 +13627,7 @@ PyMac_PRECHECK(GraphicsExportSetInputOffsetAndLimit); #endif if (!PyArg_ParseTuple(_args, "O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &offset, &limit)) return NULL; @@ -13650,7 +13650,7 @@ PyMac_PRECHECK(GraphicsExportGetInputOffsetAndLimit); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputOffsetAndLimit(ci, &offset, @@ -13672,7 +13672,7 @@ PyMac_PRECHECK(GraphicsExportMayExporterReadInputData); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportMayExporterReadInputData(ci, &mayReadInputData); @@ -13692,7 +13692,7 @@ PyMac_PRECHECK(GraphicsExportGetInputDataSize); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputDataSize(ci, &size); @@ -13714,7 +13714,7 @@ PyMac_PRECHECK(GraphicsExportReadInputData); #endif if (!PyArg_ParseTuple(_args, "O&sll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &dataPtr, &dataOffset, &dataSize)) @@ -13738,7 +13738,7 @@ PyMac_PRECHECK(GraphicsExportGetInputImageDescription); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputImageDescription(ci, &desc); @@ -13758,7 +13758,7 @@ PyMac_PRECHECK(GraphicsExportGetInputImageDimensions); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputImageDimensions(ci, &dimensions); @@ -13778,7 +13778,7 @@ PyMac_PRECHECK(GraphicsExportGetInputImageDepth); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputImageDepth(ci, &inputDepth); @@ -13801,7 +13801,7 @@ PyMac_PRECHECK(GraphicsExportDrawInputImage); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, GrafObj_Convert, &gw, OptResObj_Convert, &gd, PyMac_GetRect, &srcRect, @@ -13828,7 +13828,7 @@ PyMac_PRECHECK(GraphicsExportSetOutputDataReference); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType)) return NULL; @@ -13851,7 +13851,7 @@ PyMac_PRECHECK(GraphicsExportGetOutputDataReference); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetOutputDataReference(ci, &dataRef, @@ -13873,7 +13873,7 @@ PyMac_PRECHECK(GraphicsExportSetOutputFile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile)) return NULL; _rv = GraphicsExportSetOutputFile(ci, @@ -13893,7 +13893,7 @@ PyMac_PRECHECK(GraphicsExportGetOutputFile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile)) return NULL; _rv = GraphicsExportGetOutputFile(ci, @@ -13913,7 +13913,7 @@ PyMac_PRECHECK(GraphicsExportSetOutputHandle); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &h)) return NULL; _rv = GraphicsExportSetOutputHandle(ci, @@ -13933,7 +13933,7 @@ PyMac_PRECHECK(GraphicsExportGetOutputHandle); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetOutputHandle(ci, &h); @@ -13955,7 +13955,7 @@ PyMac_PRECHECK(GraphicsExportSetOutputOffsetAndMaxSize); #endif if (!PyArg_ParseTuple(_args, "O&llb", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &offset, &maxSize, &truncateFile)) @@ -13981,7 +13981,7 @@ PyMac_PRECHECK(GraphicsExportGetOutputOffsetAndMaxSize); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetOutputOffsetAndMaxSize(ci, &offset, @@ -14006,7 +14006,7 @@ PyMac_PRECHECK(GraphicsExportSetOutputFileTypeAndCreator); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetOSType, &fileType, PyMac_GetOSType, &fileCreator)) return NULL; @@ -14029,7 +14029,7 @@ PyMac_PRECHECK(GraphicsExportGetOutputFileTypeAndCreator); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetOutputFileTypeAndCreator(ci, &fileType, @@ -14051,7 +14051,7 @@ PyMac_PRECHECK(GraphicsExportSetOutputMark); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &mark)) return NULL; _rv = GraphicsExportSetOutputMark(ci, @@ -14071,7 +14071,7 @@ PyMac_PRECHECK(GraphicsExportGetOutputMark); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetOutputMark(ci, &mark); @@ -14093,7 +14093,7 @@ PyMac_PRECHECK(GraphicsExportReadOutputData); #endif if (!PyArg_ParseTuple(_args, "O&sll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &dataPtr, &dataOffset, &dataSize)) @@ -14119,7 +14119,7 @@ PyMac_PRECHECK(GraphicsExportSetThumbnailEnabled); #endif if (!PyArg_ParseTuple(_args, "O&bll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &enableThumbnail, &maxThumbnailWidth, &maxThumbnailHeight)) @@ -14145,7 +14145,7 @@ PyMac_PRECHECK(GraphicsExportGetThumbnailEnabled); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetThumbnailEnabled(ci, &thumbnailEnabled, @@ -14169,7 +14169,7 @@ PyMac_PRECHECK(GraphicsExportSetExifEnabled); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &enableExif)) return NULL; _rv = GraphicsExportSetExifEnabled(ci, @@ -14189,7 +14189,7 @@ PyMac_PRECHECK(GraphicsExportGetExifEnabled); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetExifEnabled(ci, &exifEnabled); @@ -14212,7 +14212,7 @@ PyMac_PRECHECK(ImageTranscoderBeginSequence); #endif if (!PyArg_ParseTuple(_args, "O&O&sl", - CmpObj_Convert, &itc, + CmpInstObj_Convert, &itc, ResObj_Convert, &srcDesc, &data, &dataSize)) @@ -14238,7 +14238,7 @@ PyMac_PRECHECK(ImageTranscoderDisposeData); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &itc, + CmpInstObj_Convert, &itc, &dstData)) return NULL; _rv = ImageTranscoderDisposeData(itc, @@ -14257,7 +14257,7 @@ PyMac_PRECHECK(ImageTranscoderEndSequence); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &itc)) + CmpInstObj_Convert, &itc)) return NULL; _rv = ImageTranscoderEndSequence(itc); _res = Py_BuildValue("l", @@ -14854,7 +14854,7 @@ PyMac_PRECHECK(TweenerReset); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &tc)) + CmpInstObj_Convert, &tc)) return NULL; _rv = TweenerReset(tc); _res = Py_BuildValue("l", @@ -14968,7 +14968,7 @@ PyMac_PRECHECK(MovieImportHandle); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataH, MovieObj_Convert, &theMovie, TrackObj_Convert, &targetTrack, @@ -15009,7 +15009,7 @@ PyMac_PRECHECK(MovieImportFile); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile, MovieObj_Convert, &theMovie, TrackObj_Convert, &targetTrack, @@ -15044,7 +15044,7 @@ PyMac_PRECHECK(MovieImportSetSampleDuration); #endif if (!PyArg_ParseTuple(_args, "O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &duration, &scale)) return NULL; @@ -15067,7 +15067,7 @@ PyMac_PRECHECK(MovieImportSetSampleDescription); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &desc, PyMac_GetOSType, &mediaType)) return NULL; @@ -15089,7 +15089,7 @@ PyMac_PRECHECK(MovieImportSetMediaFile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &alias)) return NULL; _rv = MovieImportSetMediaFile(ci, @@ -15110,7 +15110,7 @@ PyMac_PRECHECK(MovieImportSetDimensions); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFixed, &width, PyMac_GetFixed, &height)) return NULL; @@ -15132,7 +15132,7 @@ PyMac_PRECHECK(MovieImportSetChunkSize); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &chunkSize)) return NULL; _rv = MovieImportSetChunkSize(ci, @@ -15153,7 +15153,7 @@ PyMac_PRECHECK(MovieImportSetAuxiliaryData); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &data, PyMac_GetOSType, &handleType)) return NULL; @@ -15175,7 +15175,7 @@ PyMac_PRECHECK(MovieImportSetFromScrap); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &fromScrap)) return NULL; _rv = MovieImportSetFromScrap(ci, @@ -15197,7 +15197,7 @@ PyMac_PRECHECK(MovieImportDoUserDialog); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile, ResObj_Convert, &theData)) return NULL; @@ -15221,7 +15221,7 @@ PyMac_PRECHECK(MovieImportSetDuration); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &duration)) return NULL; _rv = MovieImportSetDuration(ci, @@ -15241,7 +15241,7 @@ PyMac_PRECHECK(MovieImportGetAuxiliaryDataType); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetAuxiliaryDataType(ci, &auxType); @@ -15263,7 +15263,7 @@ PyMac_PRECHECK(MovieImportValidate); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile, ResObj_Convert, &theData)) return NULL; @@ -15287,7 +15287,7 @@ PyMac_PRECHECK(MovieImportGetFileType); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetFileType(ci, &fileType); @@ -15315,7 +15315,7 @@ PyMac_PRECHECK(MovieImportDataRef); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType, MovieObj_Convert, &theMovie, @@ -15352,7 +15352,7 @@ PyMac_PRECHECK(MovieImportGetSampleDescription); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetSampleDescription(ci, &desc, @@ -15375,7 +15375,7 @@ PyMac_PRECHECK(MovieImportSetOffsetAndLimit); #endif if (!PyArg_ParseTuple(_args, "O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &offset, &limit)) return NULL; @@ -15398,7 +15398,7 @@ PyMac_PRECHECK(MovieImportSetOffsetAndLimit64); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_Getwide, &offset, PyMac_Getwide, &limit)) return NULL; @@ -15421,7 +15421,7 @@ PyMac_PRECHECK(MovieImportIdle); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &inFlags)) return NULL; _rv = MovieImportIdle(ci, @@ -15445,7 +15445,7 @@ PyMac_PRECHECK(MovieImportValidateDataRef); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType)) return NULL; @@ -15469,7 +15469,7 @@ PyMac_PRECHECK(MovieImportGetLoadState); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetLoadState(ci, &importerLoadState); @@ -15489,7 +15489,7 @@ PyMac_PRECHECK(MovieImportGetMaxLoadedTime); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetMaxLoadedTime(ci, &time); @@ -15509,7 +15509,7 @@ PyMac_PRECHECK(MovieImportEstimateCompletionTime); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportEstimateCompletionTime(ci, &time); @@ -15529,7 +15529,7 @@ PyMac_PRECHECK(MovieImportSetDontBlock); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &dontBlock)) return NULL; _rv = MovieImportSetDontBlock(ci, @@ -15549,7 +15549,7 @@ PyMac_PRECHECK(MovieImportGetDontBlock); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetDontBlock(ci, &willBlock); @@ -15569,7 +15569,7 @@ PyMac_PRECHECK(MovieImportSetIdleManager); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, IdleManagerObj_Convert, &im)) return NULL; _rv = MovieImportSetIdleManager(ci, @@ -15589,7 +15589,7 @@ PyMac_PRECHECK(MovieImportSetNewMovieFlags); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &newMovieFlags)) return NULL; _rv = MovieImportSetNewMovieFlags(ci, @@ -15609,7 +15609,7 @@ PyMac_PRECHECK(MovieImportGetDestinationMediaType); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetDestinationMediaType(ci, &mediaType); @@ -15633,7 +15633,7 @@ PyMac_PRECHECK(MovieExportToHandle); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataH, MovieObj_Convert, &theMovie, TrackObj_Convert, &onlyThisTrack, @@ -15665,7 +15665,7 @@ PyMac_PRECHECK(MovieExportToFile); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile, MovieObj_Convert, &theMovie, TrackObj_Convert, &onlyThisTrack, @@ -15694,7 +15694,7 @@ PyMac_PRECHECK(MovieExportGetAuxiliaryData); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataH)) return NULL; _rv = MovieExportGetAuxiliaryData(ci, @@ -15717,7 +15717,7 @@ PyMac_PRECHECK(MovieExportSetSampleDescription); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &desc, PyMac_GetOSType, &mediaType)) return NULL; @@ -15743,7 +15743,7 @@ PyMac_PRECHECK(MovieExportDoUserDialog); #endif if (!PyArg_ParseTuple(_args, "O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, MovieObj_Convert, &theMovie, TrackObj_Convert, &onlyThisTrack, &startTime, @@ -15771,7 +15771,7 @@ PyMac_PRECHECK(MovieExportGetCreatorType); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieExportGetCreatorType(ci, &creator); @@ -15796,7 +15796,7 @@ PyMac_PRECHECK(MovieExportToDataRef); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType, MovieObj_Convert, &theMovie, @@ -15827,7 +15827,7 @@ PyMac_PRECHECK(MovieExportFromProceduresToDataRef); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType)) return NULL; @@ -15851,7 +15851,7 @@ PyMac_PRECHECK(MovieExportValidate); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, MovieObj_Convert, &theMovie, TrackObj_Convert, &onlyThisTrack)) return NULL; @@ -15875,7 +15875,7 @@ PyMac_PRECHECK(MovieExportGetFileNameExtension); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieExportGetFileNameExtension(ci, &extension); @@ -15895,7 +15895,7 @@ PyMac_PRECHECK(MovieExportGetShortFileTypeString); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetStr255, typeString)) return NULL; _rv = MovieExportGetShortFileTypeString(ci, @@ -15915,7 +15915,7 @@ PyMac_PRECHECK(MovieExportGetSourceMediaType); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieExportGetSourceMediaType(ci, &mediaType); @@ -15935,7 +15935,7 @@ PyMac_PRECHECK(TextExportGetTimeFraction); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = TextExportGetTimeFraction(ci, &movieTimeFraction); @@ -15955,7 +15955,7 @@ PyMac_PRECHECK(TextExportSetTimeFraction); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &movieTimeFraction)) return NULL; _rv = TextExportSetTimeFraction(ci, @@ -15975,7 +15975,7 @@ PyMac_PRECHECK(TextExportGetSettings); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = TextExportGetSettings(ci, &setting); @@ -15995,7 +15995,7 @@ PyMac_PRECHECK(TextExportSetSettings); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &setting)) return NULL; _rv = TextExportSetSettings(ci, @@ -16015,7 +16015,7 @@ PyMac_PRECHECK(MIDIImportGetSettings); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MIDIImportGetSettings(ci, &setting); @@ -16035,7 +16035,7 @@ PyMac_PRECHECK(MIDIImportSetSettings); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &setting)) return NULL; _rv = MIDIImportSetSettings(ci, @@ -16055,7 +16055,7 @@ PyMac_PRECHECK(GraphicsImageImportSetSequenceEnabled); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &enable)) return NULL; _rv = GraphicsImageImportSetSequenceEnabled(ci, @@ -16075,7 +16075,7 @@ PyMac_PRECHECK(GraphicsImageImportGetSequenceEnabled); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImageImportGetSequenceEnabled(ci, &enable); @@ -16097,7 +16097,7 @@ PyMac_PRECHECK(PreviewShowData); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&", - CmpObj_Convert, &p, + CmpInstObj_Convert, &p, PyMac_GetOSType, &dataType, ResObj_Convert, &data, PyMac_GetRect, &inHere)) @@ -16123,7 +16123,7 @@ PyMac_PRECHECK(PreviewMakePreviewReference); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &p, + CmpInstObj_Convert, &p, PyMac_GetFSSpec, &sourceFile)) return NULL; _rv = PreviewMakePreviewReference(p, @@ -16148,7 +16148,7 @@ PyMac_PRECHECK(PreviewEvent); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &p)) + CmpInstObj_Convert, &p)) return NULL; _rv = PreviewEvent(p, &e, @@ -16173,7 +16173,7 @@ PyMac_PRECHECK(DataCodecDecompress); #endif if (!PyArg_ParseTuple(_args, "O&slsl", - CmpObj_Convert, &dc, + CmpInstObj_Convert, &dc, &srcData, &srcSize, &dstData, @@ -16200,7 +16200,7 @@ PyMac_PRECHECK(DataCodecGetCompressBufferSize); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &dc, + CmpInstObj_Convert, &dc, &srcSize)) return NULL; _rv = DataCodecGetCompressBufferSize(dc, @@ -16227,7 +16227,7 @@ PyMac_PRECHECK(DataCodecCompress); #endif if (!PyArg_ParseTuple(_args, "O&slsl", - CmpObj_Convert, &dc, + CmpInstObj_Convert, &dc, &srcData, &srcSize, &dstData, @@ -16257,7 +16257,7 @@ PyMac_PRECHECK(DataCodecBeginInterruptSafe); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &dc, + CmpInstObj_Convert, &dc, &maxSrcSize)) return NULL; _rv = DataCodecBeginInterruptSafe(dc, @@ -16276,7 +16276,7 @@ PyMac_PRECHECK(DataCodecEndInterruptSafe); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &dc)) + CmpInstObj_Convert, &dc)) return NULL; _rv = DataCodecEndInterruptSafe(dc); _res = Py_BuildValue("l", @@ -17695,7 +17695,7 @@ PyMac_PRECHECK(VDGetMaxSrcRect); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &inputStd)) return NULL; _rv = VDGetMaxSrcRect(ci, @@ -17718,7 +17718,7 @@ PyMac_PRECHECK(VDGetActiveSrcRect); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &inputStd)) return NULL; _rv = VDGetActiveSrcRect(ci, @@ -17740,7 +17740,7 @@ PyMac_PRECHECK(VDSetDigitizerRect); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetDigitizerRect(ci, &digitizerRect); @@ -17760,7 +17760,7 @@ PyMac_PRECHECK(VDGetDigitizerRect); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetDigitizerRect(ci, &digitizerRect); @@ -17781,7 +17781,7 @@ PyMac_PRECHECK(VDGetVBlankRect); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &inputStd)) return NULL; _rv = VDGetVBlankRect(ci, @@ -17803,7 +17803,7 @@ PyMac_PRECHECK(VDGetMaskPixMap); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &maskPixMap)) return NULL; _rv = VDGetMaskPixMap(ci, @@ -17823,7 +17823,7 @@ PyMac_PRECHECK(VDUseThisCLUT); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &colorTableHandle)) return NULL; _rv = VDUseThisCLUT(ci, @@ -17845,7 +17845,7 @@ PyMac_PRECHECK(VDSetInputGammaValue); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFixed, &channel1, PyMac_GetFixed, &channel2, PyMac_GetFixed, &channel3)) @@ -17871,7 +17871,7 @@ PyMac_PRECHECK(VDGetInputGammaValue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetInputGammaValue(ci, &channel1, @@ -17895,7 +17895,7 @@ PyMac_PRECHECK(VDSetBrightness); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetBrightness(ci, &brightness); @@ -17915,7 +17915,7 @@ PyMac_PRECHECK(VDGetBrightness); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetBrightness(ci, &brightness); @@ -17935,7 +17935,7 @@ PyMac_PRECHECK(VDSetContrast); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetContrast(ci, &contrast); @@ -17955,7 +17955,7 @@ PyMac_PRECHECK(VDSetHue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetHue(ci, &hue); @@ -17975,7 +17975,7 @@ PyMac_PRECHECK(VDSetSharpness); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetSharpness(ci, &sharpness); @@ -17995,7 +17995,7 @@ PyMac_PRECHECK(VDSetSaturation); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetSaturation(ci, &saturation); @@ -18015,7 +18015,7 @@ PyMac_PRECHECK(VDGetContrast); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetContrast(ci, &contrast); @@ -18035,7 +18035,7 @@ PyMac_PRECHECK(VDGetHue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetHue(ci, &hue); @@ -18055,7 +18055,7 @@ PyMac_PRECHECK(VDGetSharpness); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetSharpness(ci, &sharpness); @@ -18075,7 +18075,7 @@ PyMac_PRECHECK(VDGetSaturation); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetSaturation(ci, &saturation); @@ -18094,7 +18094,7 @@ PyMac_PRECHECK(VDGrabOneFrame); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGrabOneFrame(ci); _res = Py_BuildValue("l", @@ -18113,7 +18113,7 @@ PyMac_PRECHECK(VDGetMaxAuxBuffer); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetMaxAuxBuffer(ci, &pm, @@ -18136,7 +18136,7 @@ PyMac_PRECHECK(VDGetCurrentFlags); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetCurrentFlags(ci, &inputCurrentFlag, @@ -18158,7 +18158,7 @@ PyMac_PRECHECK(VDSetKeyColor); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &index)) return NULL; _rv = VDSetKeyColor(ci, @@ -18178,7 +18178,7 @@ PyMac_PRECHECK(VDGetKeyColor); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetKeyColor(ci, &index); @@ -18198,7 +18198,7 @@ PyMac_PRECHECK(VDAddKeyColor); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDAddKeyColor(ci, &index); @@ -18218,7 +18218,7 @@ PyMac_PRECHECK(VDGetNextKeyColor); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &index)) return NULL; _rv = VDGetNextKeyColor(ci, @@ -18239,7 +18239,7 @@ PyMac_PRECHECK(VDSetKeyColorRange); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetKeyColorRange(ci, &minRGB, @@ -18262,7 +18262,7 @@ PyMac_PRECHECK(VDGetKeyColorRange); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetKeyColorRange(ci, &minRGB, @@ -18284,7 +18284,7 @@ PyMac_PRECHECK(VDSetInputColorSpaceMode); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &colorSpaceMode)) return NULL; _rv = VDSetInputColorSpaceMode(ci, @@ -18304,7 +18304,7 @@ PyMac_PRECHECK(VDGetInputColorSpaceMode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetInputColorSpaceMode(ci, &colorSpaceMode); @@ -18324,7 +18324,7 @@ PyMac_PRECHECK(VDSetClipState); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &clipEnable)) return NULL; _rv = VDSetClipState(ci, @@ -18344,7 +18344,7 @@ PyMac_PRECHECK(VDGetClipState); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetClipState(ci, &clipEnable); @@ -18364,7 +18364,7 @@ PyMac_PRECHECK(VDSetClipRgn); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &clipRegion)) return NULL; _rv = VDSetClipRgn(ci, @@ -18384,7 +18384,7 @@ PyMac_PRECHECK(VDClearClipRgn); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &clipRegion)) return NULL; _rv = VDClearClipRgn(ci, @@ -18404,7 +18404,7 @@ PyMac_PRECHECK(VDGetCLUTInUse); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetCLUTInUse(ci, &colorTableHandle); @@ -18424,7 +18424,7 @@ PyMac_PRECHECK(VDSetPLLFilterType); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &pllType)) return NULL; _rv = VDSetPLLFilterType(ci, @@ -18444,7 +18444,7 @@ PyMac_PRECHECK(VDGetPLLFilterType); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetPLLFilterType(ci, &pllType); @@ -18466,7 +18466,7 @@ PyMac_PRECHECK(VDGetMaskandValue); #endif if (!PyArg_ParseTuple(_args, "O&H", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &blendLevel)) return NULL; _rv = VDGetMaskandValue(ci, @@ -18490,7 +18490,7 @@ PyMac_PRECHECK(VDSetMasterBlendLevel); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetMasterBlendLevel(ci, &blendLevel); @@ -18510,7 +18510,7 @@ PyMac_PRECHECK(VDSetPlayThruOnOff); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &state)) return NULL; _rv = VDSetPlayThruOnOff(ci, @@ -18530,7 +18530,7 @@ PyMac_PRECHECK(VDSetFieldPreference); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &fieldFlag)) return NULL; _rv = VDSetFieldPreference(ci, @@ -18550,7 +18550,7 @@ PyMac_PRECHECK(VDGetFieldPreference); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetFieldPreference(ci, &fieldFlag); @@ -18571,7 +18571,7 @@ PyMac_PRECHECK(VDPreflightGlobalRect); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, GrafObj_Convert, &theWindow)) return NULL; _rv = VDPreflightGlobalRect(ci, @@ -18594,7 +18594,7 @@ PyMac_PRECHECK(VDSetPlayThruGlobalRect); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, GrafObj_Convert, &theWindow)) return NULL; _rv = VDSetPlayThruGlobalRect(ci, @@ -18616,7 +18616,7 @@ PyMac_PRECHECK(VDSetBlackLevelValue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetBlackLevelValue(ci, &blackLevel); @@ -18636,7 +18636,7 @@ PyMac_PRECHECK(VDGetBlackLevelValue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetBlackLevelValue(ci, &blackLevel); @@ -18656,7 +18656,7 @@ PyMac_PRECHECK(VDSetWhiteLevelValue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetWhiteLevelValue(ci, &whiteLevel); @@ -18676,7 +18676,7 @@ PyMac_PRECHECK(VDGetWhiteLevelValue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetWhiteLevelValue(ci, &whiteLevel); @@ -18702,7 +18702,7 @@ PyMac_PRECHECK(VDGetVideoDefaults); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetVideoDefaults(ci, &blackLevel, @@ -18734,7 +18734,7 @@ PyMac_PRECHECK(VDGetNumberOfInputs); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetNumberOfInputs(ci, &inputs); @@ -18755,7 +18755,7 @@ PyMac_PRECHECK(VDGetInputFormat); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &input)) return NULL; _rv = VDGetInputFormat(ci, @@ -18777,7 +18777,7 @@ PyMac_PRECHECK(VDSetInput); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &input)) return NULL; _rv = VDSetInput(ci, @@ -18797,7 +18797,7 @@ PyMac_PRECHECK(VDGetInput); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetInput(ci, &input); @@ -18817,7 +18817,7 @@ PyMac_PRECHECK(VDSetInputStandard); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &inputStandard)) return NULL; _rv = VDSetInputStandard(ci, @@ -18837,7 +18837,7 @@ PyMac_PRECHECK(VDSetupBuffers); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &bufferList)) return NULL; _rv = VDSetupBuffers(ci, @@ -18857,7 +18857,7 @@ PyMac_PRECHECK(VDGrabOneFrameAsync); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &buffer)) return NULL; _rv = VDGrabOneFrameAsync(ci, @@ -18877,7 +18877,7 @@ PyMac_PRECHECK(VDDone); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &buffer)) return NULL; _rv = VDDone(ci, @@ -18902,7 +18902,7 @@ PyMac_PRECHECK(VDSetCompression); #endif if (!PyArg_ParseTuple(_args, "O&O&hlll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetOSType, &compressType, &depth, &spatialQuality, @@ -18931,7 +18931,7 @@ PyMac_PRECHECK(VDCompressOneFrameAsync); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDCompressOneFrameAsync(ci); _res = Py_BuildValue("l", @@ -18949,7 +18949,7 @@ PyMac_PRECHECK(VDGetImageDescription); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &desc)) return NULL; _rv = VDGetImageDescription(ci, @@ -18968,7 +18968,7 @@ PyMac_PRECHECK(VDResetCompressSequence); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDResetCompressSequence(ci); _res = Py_BuildValue("l", @@ -18986,7 +18986,7 @@ PyMac_PRECHECK(VDSetCompressionOnOff); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &state)) return NULL; _rv = VDSetCompressionOnOff(ci, @@ -19006,7 +19006,7 @@ PyMac_PRECHECK(VDGetCompressionTypes); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &h)) return NULL; _rv = VDGetCompressionTypes(ci, @@ -19026,7 +19026,7 @@ PyMac_PRECHECK(VDSetTimeBase); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, TimeBaseObj_Convert, &t)) return NULL; _rv = VDSetTimeBase(ci, @@ -19046,7 +19046,7 @@ PyMac_PRECHECK(VDSetFrameRate); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFixed, &framesPerSecond)) return NULL; _rv = VDSetFrameRate(ci, @@ -19068,7 +19068,7 @@ PyMac_PRECHECK(VDGetDataRate); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetDataRate(ci, &milliSecPerFrame, @@ -19092,7 +19092,7 @@ PyMac_PRECHECK(VDGetSoundInputDriver); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetStr255, soundDriverName)) return NULL; _rv = VDGetSoundInputDriver(ci, @@ -19113,7 +19113,7 @@ PyMac_PRECHECK(VDGetDMADepths); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetDMADepths(ci, &depthArray, @@ -19135,7 +19135,7 @@ PyMac_PRECHECK(VDGetPreferredTimeScale); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetPreferredTimeScale(ci, &preferred); @@ -19154,7 +19154,7 @@ PyMac_PRECHECK(VDReleaseAsyncBuffers); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDReleaseAsyncBuffers(ci); _res = Py_BuildValue("l", @@ -19172,7 +19172,7 @@ PyMac_PRECHECK(VDSetDataRate); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &bytesPerSecond)) return NULL; _rv = VDSetDataRate(ci, @@ -19194,7 +19194,7 @@ PyMac_PRECHECK(VDGetTimeCode); #endif if (!PyArg_ParseTuple(_args, "O&ss", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &timeCodeFormat, &timeCodeTime)) return NULL; @@ -19218,7 +19218,7 @@ PyMac_PRECHECK(VDUseSafeBuffers); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &useSafeBuffers)) return NULL; _rv = VDUseSafeBuffers(ci, @@ -19239,7 +19239,7 @@ PyMac_PRECHECK(VDGetSoundInputSource); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &videoInput)) return NULL; _rv = VDGetSoundInputSource(ci, @@ -19266,7 +19266,7 @@ PyMac_PRECHECK(VDGetCompressionTime); #endif if (!PyArg_ParseTuple(_args, "O&O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetOSType, &compressionType, &depth)) return NULL; @@ -19296,7 +19296,7 @@ PyMac_PRECHECK(VDSetPreferredPacketSize); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &preferredPacketSizeInBytes)) return NULL; _rv = VDSetPreferredPacketSize(ci, @@ -19317,7 +19317,7 @@ PyMac_PRECHECK(VDSetPreferredImageDimensions); #endif if (!PyArg_ParseTuple(_args, "O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &width, &height)) return NULL; @@ -19340,7 +19340,7 @@ PyMac_PRECHECK(VDGetPreferredImageDimensions); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetPreferredImageDimensions(ci, &width, @@ -19363,7 +19363,7 @@ PyMac_PRECHECK(VDGetInputName); #endif if (!PyArg_ParseTuple(_args, "O&lO&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &videoInput, PyMac_GetStr255, name)) return NULL; @@ -19385,7 +19385,7 @@ PyMac_PRECHECK(VDSetDestinationPort); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, GrafObj_Convert, &destPort)) return NULL; _rv = VDSetDestinationPort(ci, @@ -19406,7 +19406,7 @@ PyMac_PRECHECK(VDGetDeviceNameAndFlags); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetStr255, outName)) return NULL; _rv = VDGetDeviceNameAndFlags(ci, @@ -19428,7 +19428,7 @@ PyMac_PRECHECK(VDCaptureStateChanging); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &inStateFlags)) return NULL; _rv = VDCaptureStateChanging(ci, @@ -19687,7 +19687,7 @@ PyMac_PRECHECK(SGInitialize); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGInitialize(s); _res = Py_BuildValue("l", @@ -19706,7 +19706,7 @@ PyMac_PRECHECK(SGSetDataOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, PyMac_GetFSSpec, &movieFile, &whereFlags)) return NULL; @@ -19729,7 +19729,7 @@ PyMac_PRECHECK(SGGetDataOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, PyMac_GetFSSpec, &movieFile)) return NULL; _rv = SGGetDataOutput(s, @@ -19752,7 +19752,7 @@ PyMac_PRECHECK(SGSetGWorld); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, GrafObj_Convert, &gp, OptResObj_Convert, &gd)) return NULL; @@ -19775,7 +19775,7 @@ PyMac_PRECHECK(SGGetGWorld); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetGWorld(s, &gp, @@ -19798,7 +19798,7 @@ PyMac_PRECHECK(SGNewChannel); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, PyMac_GetOSType, &channelType)) return NULL; _rv = SGNewChannel(s, @@ -19820,7 +19820,7 @@ PyMac_PRECHECK(SGDisposeChannel); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c)) return NULL; _rv = SGDisposeChannel(s, @@ -19839,7 +19839,7 @@ PyMac_PRECHECK(SGStartPreview); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGStartPreview(s); _res = Py_BuildValue("l", @@ -19856,7 +19856,7 @@ PyMac_PRECHECK(SGStartRecord); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGStartRecord(s); _res = Py_BuildValue("l", @@ -19873,7 +19873,7 @@ PyMac_PRECHECK(SGIdle); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGIdle(s); _res = Py_BuildValue("l", @@ -19890,7 +19890,7 @@ PyMac_PRECHECK(SGStop); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGStop(s); _res = Py_BuildValue("l", @@ -19908,7 +19908,7 @@ PyMac_PRECHECK(SGPause); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &pause)) return NULL; _rv = SGPause(s, @@ -19929,7 +19929,7 @@ PyMac_PRECHECK(SGPrepare); #endif if (!PyArg_ParseTuple(_args, "O&bb", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &prepareForPreview, &prepareForRecord)) return NULL; @@ -19950,7 +19950,7 @@ PyMac_PRECHECK(SGRelease); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGRelease(s); _res = Py_BuildValue("l", @@ -19967,7 +19967,7 @@ PyMac_PRECHECK(SGGetMovie); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetMovie(s); _res = Py_BuildValue("O&", @@ -19985,7 +19985,7 @@ PyMac_PRECHECK(SGSetMaximumRecordTime); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &ticks)) return NULL; _rv = SGSetMaximumRecordTime(s, @@ -20005,7 +20005,7 @@ PyMac_PRECHECK(SGGetMaximumRecordTime); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetMaximumRecordTime(s, &ticks); @@ -20025,7 +20025,7 @@ PyMac_PRECHECK(SGGetStorageSpaceRemaining); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetStorageSpaceRemaining(s, &bytes); @@ -20045,7 +20045,7 @@ PyMac_PRECHECK(SGGetTimeRemaining); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetTimeRemaining(s, &ticksLeft); @@ -20068,7 +20068,7 @@ PyMac_PRECHECK(SGGrabPict); #endif if (!PyArg_ParseTuple(_args, "O&O&hl", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, PyMac_GetRect, &bounds, &offscreenDepth, &grabPictFlags)) @@ -20094,7 +20094,7 @@ PyMac_PRECHECK(SGGetLastMovieResID); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetLastMovieResID(s, &resID); @@ -20114,7 +20114,7 @@ PyMac_PRECHECK(SGSetFlags); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &sgFlags)) return NULL; _rv = SGSetFlags(s, @@ -20134,7 +20134,7 @@ PyMac_PRECHECK(SGGetFlags); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetFlags(s, &sgFlags); @@ -20155,7 +20155,7 @@ PyMac_PRECHECK(SGNewChannelFromComponent); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpObj_Convert, &sgChannelComponent)) return NULL; _rv = SGNewChannelFromComponent(s, @@ -20178,7 +20178,7 @@ PyMac_PRECHECK(SGSetSettings); #endif if (!PyArg_ParseTuple(_args, "O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, UserDataObj_Convert, &ud, &flags)) return NULL; @@ -20201,7 +20201,7 @@ PyMac_PRECHECK(SGGetSettings); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &flags)) return NULL; _rv = SGGetSettings(s, @@ -20225,7 +20225,7 @@ PyMac_PRECHECK(SGGetIndChannel); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &index)) return NULL; _rv = SGGetIndChannel(s, @@ -20249,7 +20249,7 @@ PyMac_PRECHECK(SGUpdate); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, ResObj_Convert, &updateRgn)) return NULL; _rv = SGUpdate(s, @@ -20269,7 +20269,7 @@ PyMac_PRECHECK(SGGetPause); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetPause(s, &paused); @@ -20291,7 +20291,7 @@ PyMac_PRECHECK(SGSetChannelSettings); #endif if (!PyArg_ParseTuple(_args, "O&O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, UserDataObj_Convert, &ud, &flags)) @@ -20317,7 +20317,7 @@ PyMac_PRECHECK(SGGetChannelSettings); #endif if (!PyArg_ParseTuple(_args, "O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, &flags)) return NULL; @@ -20342,7 +20342,7 @@ PyMac_PRECHECK(SGGetMode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetMode(s, &previewMode, @@ -20366,7 +20366,7 @@ PyMac_PRECHECK(SGSetDataRef); #endif if (!PyArg_ParseTuple(_args, "O&O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType, &whereFlags)) @@ -20392,7 +20392,7 @@ PyMac_PRECHECK(SGGetDataRef); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetDataRef(s, &dataRef, @@ -20419,7 +20419,7 @@ PyMac_PRECHECK(SGNewOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType, &whereFlags)) @@ -20445,7 +20445,7 @@ PyMac_PRECHECK(SGDisposeOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut)) return NULL; _rv = SGDisposeOutput(s, @@ -20466,7 +20466,7 @@ PyMac_PRECHECK(SGSetOutputFlags); #endif if (!PyArg_ParseTuple(_args, "O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut, &whereFlags)) return NULL; @@ -20489,7 +20489,7 @@ PyMac_PRECHECK(SGSetChannelOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, SGOutputObj_Convert, &sgOut)) return NULL; @@ -20512,7 +20512,7 @@ PyMac_PRECHECK(SGGetDataOutputStorageSpaceRemaining); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut)) return NULL; _rv = SGGetDataOutputStorageSpaceRemaining(s, @@ -20535,7 +20535,7 @@ PyMac_PRECHECK(SGHandleUpdateEvent); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, PyMac_GetEventRecord, &event)) return NULL; _rv = SGHandleUpdateEvent(s, @@ -20558,7 +20558,7 @@ PyMac_PRECHECK(SGSetOutputNextOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut, SGOutputObj_Convert, &nextOut)) return NULL; @@ -20581,7 +20581,7 @@ PyMac_PRECHECK(SGGetOutputNextOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut)) return NULL; _rv = SGGetOutputNextOutput(s, @@ -20604,7 +20604,7 @@ PyMac_PRECHECK(SGSetOutputMaximumOffset); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut, PyMac_Getwide, &maxOffset)) return NULL; @@ -20627,7 +20627,7 @@ PyMac_PRECHECK(SGGetOutputMaximumOffset); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut)) return NULL; _rv = SGGetOutputMaximumOffset(s, @@ -20651,7 +20651,7 @@ PyMac_PRECHECK(SGGetOutputDataReference); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut)) return NULL; _rv = SGGetOutputDataReference(s, @@ -20679,7 +20679,7 @@ PyMac_PRECHECK(SGWriteExtendedMovieData); #endif if (!PyArg_ParseTuple(_args, "O&O&sl", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, &p, &len)) @@ -20707,7 +20707,7 @@ PyMac_PRECHECK(SGGetStorageSpaceRemaining64); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetStorageSpaceRemaining64(s, &bytes); @@ -20728,7 +20728,7 @@ PyMac_PRECHECK(SGGetDataOutputStorageSpaceRemaining64); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut)) return NULL; _rv = SGGetDataOutputStorageSpaceRemaining64(s, @@ -20753,7 +20753,7 @@ PyMac_PRECHECK(SGWriteMovieData); #endif if (!PyArg_ParseTuple(_args, "O&O&sl", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, &p, &len)) @@ -20779,7 +20779,7 @@ PyMac_PRECHECK(SGGetTimeBase); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetTimeBase(s, &tb); @@ -20805,7 +20805,7 @@ PyMac_PRECHECK(SGAddMovieData); #endif if (!PyArg_ParseTuple(_args, "O&O&slllh", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, &p, &len, @@ -20837,7 +20837,7 @@ PyMac_PRECHECK(SGChangedSource); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c)) return NULL; _rv = SGChangedSource(s, @@ -20864,7 +20864,7 @@ PyMac_PRECHECK(SGAddExtendedMovieData); #endif if (!PyArg_ParseTuple(_args, "O&O&slllh", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, &p, &len, @@ -20900,7 +20900,7 @@ PyMac_PRECHECK(SGAddOutputDataRefToMedia); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut, MediaObj_Convert, &theMedia, ResObj_Convert, &desc)) @@ -20924,7 +20924,7 @@ PyMac_PRECHECK(SGSetSettingsSummary); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, ResObj_Convert, &summaryText)) return NULL; _rv = SGSetSettingsSummary(s, @@ -21534,7 +21534,7 @@ #endif if (!PyArg_ParseTuple(_args, "O&O&", CmpInstObj_Convert, &c, - CmpObj_Convert, &owner)) + CmpInstObj_Convert, &owner)) return NULL; _rv = SGInitChannel(c, owner); @@ -21616,7 +21616,7 @@ PyMac_PRECHECK(SGPanelGetDitl); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGPanelGetDitl(s, &ditl); @@ -21636,7 +21636,7 @@ PyMac_PRECHECK(SGPanelGetTitle); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, PyMac_GetStr255, title)) return NULL; _rv = SGPanelGetTitle(s, @@ -21656,7 +21656,7 @@ PyMac_PRECHECK(SGPanelCanRun); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c)) return NULL; _rv = SGPanelCanRun(s, @@ -21678,7 +21678,7 @@ PyMac_PRECHECK(SGPanelInstall); #endif if (!PyArg_ParseTuple(_args, "O&O&O&h", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, DlgObj_Convert, &d, &itemOffset)) @@ -21707,7 +21707,7 @@ PyMac_PRECHECK(SGPanelEvent); #endif if (!PyArg_ParseTuple(_args, "O&O&O&hO&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, DlgObj_Convert, &d, &itemOffset, @@ -21740,7 +21740,7 @@ PyMac_PRECHECK(SGPanelItem); #endif if (!PyArg_ParseTuple(_args, "O&O&O&hh", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, DlgObj_Convert, &d, &itemOffset, @@ -21768,7 +21768,7 @@ PyMac_PRECHECK(SGPanelRemove); #endif if (!PyArg_ParseTuple(_args, "O&O&O&h", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, DlgObj_Convert, &d, &itemOffset)) @@ -21792,8 +21792,8 @@ PyMac_PRECHECK(SGPanelSetGrabber); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, - CmpObj_Convert, &sg)) + CmpInstObj_Convert, &s, + CmpInstObj_Convert, &sg)) return NULL; _rv = SGPanelSetGrabber(s, sg); @@ -21812,7 +21812,7 @@ PyMac_PRECHECK(SGPanelSetResFile); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &resRef)) return NULL; _rv = SGPanelSetResFile(s, @@ -21834,7 +21834,7 @@ PyMac_PRECHECK(SGPanelGetSettings); #endif if (!PyArg_ParseTuple(_args, "O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, &flags)) return NULL; @@ -21860,7 +21860,7 @@ PyMac_PRECHECK(SGPanelSetSettings); #endif if (!PyArg_ParseTuple(_args, "O&O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, UserDataObj_Convert, &ud, &flags)) @@ -21884,7 +21884,7 @@ PyMac_PRECHECK(SGPanelValidateInput); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGPanelValidateInput(s, &ok); @@ -21905,7 +21905,7 @@ PyMac_PRECHECK(SGPanelGetDITLForSize); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGPanelGetDITLForSize(s, &ditl, @@ -22806,7 +22806,7 @@ PyMac_PRECHECK(QTVideoOutputGetCurrentClientName); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, PyMac_GetStr255, str)) return NULL; _rv = QTVideoOutputGetCurrentClientName(vo, @@ -22826,7 +22826,7 @@ PyMac_PRECHECK(QTVideoOutputSetClientName); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, PyMac_GetStr255, str)) return NULL; _rv = QTVideoOutputSetClientName(vo, @@ -22846,7 +22846,7 @@ PyMac_PRECHECK(QTVideoOutputGetClientName); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, PyMac_GetStr255, str)) return NULL; _rv = QTVideoOutputGetClientName(vo, @@ -22865,7 +22865,7 @@ PyMac_PRECHECK(QTVideoOutputBegin); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &vo)) + CmpInstObj_Convert, &vo)) return NULL; _rv = QTVideoOutputBegin(vo); _res = Py_BuildValue("l", @@ -22882,7 +22882,7 @@ PyMac_PRECHECK(QTVideoOutputEnd); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &vo)) + CmpInstObj_Convert, &vo)) return NULL; _rv = QTVideoOutputEnd(vo); _res = Py_BuildValue("l", @@ -22900,7 +22900,7 @@ PyMac_PRECHECK(QTVideoOutputSetDisplayMode); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, &displayModeID)) return NULL; _rv = QTVideoOutputSetDisplayMode(vo, @@ -22920,7 +22920,7 @@ PyMac_PRECHECK(QTVideoOutputGetDisplayMode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &vo)) + CmpInstObj_Convert, &vo)) return NULL; _rv = QTVideoOutputGetDisplayMode(vo, &displayModeID); @@ -22940,7 +22940,7 @@ PyMac_PRECHECK(QTVideoOutputGetGWorld); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &vo)) + CmpInstObj_Convert, &vo)) return NULL; _rv = QTVideoOutputGetGWorld(vo, &gw); @@ -22961,7 +22961,7 @@ PyMac_PRECHECK(QTVideoOutputGetIndSoundOutput); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, &index)) return NULL; _rv = QTVideoOutputGetIndSoundOutput(vo, @@ -22983,7 +22983,7 @@ PyMac_PRECHECK(QTVideoOutputGetClock); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &vo)) + CmpInstObj_Convert, &vo)) return NULL; _rv = QTVideoOutputGetClock(vo, &clock); @@ -23003,7 +23003,7 @@ PyMac_PRECHECK(QTVideoOutputSetEchoPort); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, GrafObj_Convert, &echoPort)) return NULL; _rv = QTVideoOutputSetEchoPort(vo, @@ -23024,7 +23024,7 @@ PyMac_PRECHECK(QTVideoOutputGetIndImageDecompressor); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, &index)) return NULL; _rv = QTVideoOutputGetIndImageDecompressor(vo, @@ -23046,7 +23046,7 @@ PyMac_PRECHECK(QTVideoOutputBaseSetEchoPort); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, GrafObj_Convert, &echoPort)) return NULL; _rv = QTVideoOutputBaseSetEchoPort(vo, Modified: python/trunk/Mac/Modules/qt/qtsupport.py ============================================================================== --- python/trunk/Mac/Modules/qt/qtsupport.py (original) +++ python/trunk/Mac/Modules/qt/qtsupport.py Mon Mar 30 17:20:46 2009 @@ -135,19 +135,22 @@ CompressorComponent = OpaqueByValueType('CompressorComponent', 'CmpObj') DecompressorComponent = OpaqueByValueType('DecompressorComponent', 'CmpObj') CodecComponent = OpaqueByValueType('CodecComponent', 'CmpObj') -GraphicsImportComponent = OpaqueByValueType('GraphicsImportComponent', 'CmpObj') -GraphicsExportComponent = OpaqueByValueType('GraphicsExportComponent', 'CmpObj') -ImageTranscoderComponent = OpaqueByValueType('ImageTranscoderComponent', 'CmpObj') -DataCodecComponent = OpaqueByValueType('DataCodecComponent', 'CmpObj') -GraphicImageMovieImportComponent = OpaqueByValueType('GraphicImageMovieImportComponent', 'CmpObj') -MovieExportComponent = OpaqueByValueType('MovieExportComponent', 'CmpObj') -MovieImportComponent = OpaqueByValueType('MovieImportComponent', 'CmpObj') -QTVideoOutputComponent = OpaqueByValueType('QTVideoOutputComponent', 'CmpObj') -SeqGrabComponent = OpaqueByValueType('SeqGrabComponent', 'CmpObj') -TextExportComponent = OpaqueByValueType('TextExportComponent', 'CmpObj') -TweenerComponent = OpaqueByValueType('TweenerComponent', 'CmpObj') -pnotComponent = OpaqueByValueType('pnotComponent', 'CmpObj') -VideoDigitizerComponent = OpaqueByValueType('VideoDigitizerComponent', 'CmpObj') + +# Despite their names, these are all ComponentInstance types +GraphicsImportComponent = OpaqueByValueType('GraphicsImportComponent', 'CmpInstObj') +GraphicsExportComponent = OpaqueByValueType('GraphicsExportComponent', 'CmpInstObj') +ImageTranscoderComponent = OpaqueByValueType('ImageTranscoderComponent', 'CmpInstObj') +MovieImportComponent = OpaqueByValueType('MovieImportComponent', 'CmpInstObj') +MovieExportComponent = OpaqueByValueType('MovieExportComponent', 'CmpInstObj') +TextExportComponent = OpaqueByValueType('TextExportComponent', 'CmpInstObj') +GraphicImageMovieImportComponent = OpaqueByValueType('GraphicImageMovieImportComponent', 'CmpInstObj') +pnotComponent = OpaqueByValueType('pnotComponent', 'CmpInstObj') +# DataCompressorComponent, DataDecompressorComponent would go here +DataCodecComponent = OpaqueByValueType('DataCodecComponent', 'CmpInstObj') +TweenerComponent = OpaqueByValueType('TweenerComponent', 'CmpInstObj') +QTVideoOutputComponent = OpaqueByValueType('QTVideoOutputComponent', 'CmpInstObj') +SeqGrabComponent = OpaqueByValueType('SeqGrabComponent', 'CmpInstObj') +VideoDigitizerComponent = OpaqueByValueType('VideoDigitizerComponent', 'CmpInstObj') ComponentInstance = OpaqueByValueType('ComponentInstance', 'CmpInstObj') MediaHandler = OpaqueByValueType('MediaHandler', 'CmpInstObj') From python-checkins at python.org Mon Mar 30 17:20:53 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 30 Mar 2009 17:20:53 +0200 (CEST) Subject: [Python-checkins] r70714 - python/trunk/Misc/developers.txt Message-ID: <20090330152053.5F7F21E402C@bag.python.org> Author: brett.cannon Date: Mon Mar 30 17:20:53 2009 New Revision: 70714 Log: Add an entry to developers.txt. Modified: python/trunk/Misc/developers.txt Modified: python/trunk/Misc/developers.txt ============================================================================== --- python/trunk/Misc/developers.txt (original) +++ python/trunk/Misc/developers.txt Mon Mar 30 17:20:53 2009 @@ -17,6 +17,9 @@ Permissions History ------------------- +- R. David Murray was given SVN access on March 30 2009 by MvL, after + recommendation by BAC. + - Chris Withers was given SVN access on March 8 2009 by MvL, after recommendation by GvR. From python-checkins at python.org Mon Mar 30 17:24:09 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 17:24:09 +0200 (CEST) Subject: [Python-checkins] r70715 - in python/branches/release26-maint: Mac/Modules/qt/_Qtmodule.c Mac/Modules/qt/qtsupport.py Message-ID: <20090330152409.3AC761E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 17:24:08 2009 New Revision: 70715 Log: Merged revisions 70713 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70713 | ronald.oussoren | 2009-03-30 10:20:46 -0500 (Mon, 30 Mar 2009) | 2 lines This patch fixes issue 1254695 (wrong argument type conversion in Carbon.Qt) ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Mac/Modules/qt/_Qtmodule.c python/branches/release26-maint/Mac/Modules/qt/qtsupport.py Modified: python/branches/release26-maint/Mac/Modules/qt/_Qtmodule.c ============================================================================== --- python/branches/release26-maint/Mac/Modules/qt/_Qtmodule.c (original) +++ python/branches/release26-maint/Mac/Modules/qt/_Qtmodule.c Mon Mar 30 17:24:08 2009 @@ -11551,7 +11551,7 @@ PyMac_PRECHECK(GraphicsImportSetDataReference); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataReType)) return NULL; @@ -11574,7 +11574,7 @@ PyMac_PRECHECK(GraphicsImportGetDataReference); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDataReference(ci, &dataRef, @@ -11596,7 +11596,7 @@ PyMac_PRECHECK(GraphicsImportSetDataFile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile)) return NULL; _rv = GraphicsImportSetDataFile(ci, @@ -11616,7 +11616,7 @@ PyMac_PRECHECK(GraphicsImportGetDataFile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile)) return NULL; _rv = GraphicsImportGetDataFile(ci, @@ -11636,7 +11636,7 @@ PyMac_PRECHECK(GraphicsImportSetDataHandle); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &h)) return NULL; _rv = GraphicsImportSetDataHandle(ci, @@ -11656,7 +11656,7 @@ PyMac_PRECHECK(GraphicsImportGetDataHandle); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDataHandle(ci, &h); @@ -11676,7 +11676,7 @@ PyMac_PRECHECK(GraphicsImportGetImageDescription); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetImageDescription(ci, &desc); @@ -11697,7 +11697,7 @@ PyMac_PRECHECK(GraphicsImportGetDataOffsetAndSize); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDataOffsetAndSize(ci, &offset, @@ -11721,7 +11721,7 @@ PyMac_PRECHECK(GraphicsImportReadData); #endif if (!PyArg_ParseTuple(_args, "O&sll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &dataPtr, &dataOffset, &dataSize)) @@ -11745,7 +11745,7 @@ PyMac_PRECHECK(GraphicsImportSetClip); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &clipRgn)) return NULL; _rv = GraphicsImportSetClip(ci, @@ -11765,7 +11765,7 @@ PyMac_PRECHECK(GraphicsImportGetClip); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetClip(ci, &clipRgn); @@ -11785,7 +11785,7 @@ PyMac_PRECHECK(GraphicsImportSetSourceRect); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetRect, &sourceRect)) return NULL; _rv = GraphicsImportSetSourceRect(ci, @@ -11805,7 +11805,7 @@ PyMac_PRECHECK(GraphicsImportGetSourceRect); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetSourceRect(ci, &sourceRect); @@ -11825,7 +11825,7 @@ PyMac_PRECHECK(GraphicsImportGetNaturalBounds); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetNaturalBounds(ci, &naturalBounds); @@ -11844,7 +11844,7 @@ PyMac_PRECHECK(GraphicsImportDraw); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportDraw(ci); _res = Py_BuildValue("l", @@ -11863,7 +11863,7 @@ PyMac_PRECHECK(GraphicsImportSetGWorld); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, GrafObj_Convert, &port, OptResObj_Convert, &gd)) return NULL; @@ -11886,7 +11886,7 @@ PyMac_PRECHECK(GraphicsImportGetGWorld); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetGWorld(ci, &port, @@ -11908,7 +11908,7 @@ PyMac_PRECHECK(GraphicsImportSetBoundsRect); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetRect, &bounds)) return NULL; _rv = GraphicsImportSetBoundsRect(ci, @@ -11928,7 +11928,7 @@ PyMac_PRECHECK(GraphicsImportGetBoundsRect); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetBoundsRect(ci, &bounds); @@ -11949,7 +11949,7 @@ PyMac_PRECHECK(GraphicsImportSaveAsPicture); #endif if (!PyArg_ParseTuple(_args, "O&O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &fss, &scriptTag)) return NULL; @@ -11972,7 +11972,7 @@ PyMac_PRECHECK(GraphicsImportSetGraphicsMode); #endif if (!PyArg_ParseTuple(_args, "O&lO&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &graphicsMode, QdRGB_Convert, &opColor)) return NULL; @@ -11995,7 +11995,7 @@ PyMac_PRECHECK(GraphicsImportGetGraphicsMode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetGraphicsMode(ci, &graphicsMode, @@ -12017,7 +12017,7 @@ PyMac_PRECHECK(GraphicsImportSetQuality); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &quality)) return NULL; _rv = GraphicsImportSetQuality(ci, @@ -12037,7 +12037,7 @@ PyMac_PRECHECK(GraphicsImportGetQuality); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetQuality(ci, &quality); @@ -12058,7 +12058,7 @@ PyMac_PRECHECK(GraphicsImportSaveAsQuickTimeImageFile); #endif if (!PyArg_ParseTuple(_args, "O&O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &fss, &scriptTag)) return NULL; @@ -12081,7 +12081,7 @@ PyMac_PRECHECK(GraphicsImportSetDataReferenceOffsetAndLimit); #endif if (!PyArg_ParseTuple(_args, "O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &offset, &limit)) return NULL; @@ -12104,7 +12104,7 @@ PyMac_PRECHECK(GraphicsImportGetDataReferenceOffsetAndLimit); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDataReferenceOffsetAndLimit(ci, &offset, @@ -12127,7 +12127,7 @@ PyMac_PRECHECK(GraphicsImportGetAliasedDataReference); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetAliasedDataReference(ci, &dataRef, @@ -12149,7 +12149,7 @@ PyMac_PRECHECK(GraphicsImportValidate); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportValidate(ci, &valid); @@ -12169,7 +12169,7 @@ PyMac_PRECHECK(GraphicsImportGetMetaData); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &userData)) return NULL; _rv = GraphicsImportGetMetaData(ci, @@ -12189,7 +12189,7 @@ PyMac_PRECHECK(GraphicsImportGetMIMETypeList); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainerPtr)) return NULL; _rv = GraphicsImportGetMIMETypeList(ci, @@ -12209,7 +12209,7 @@ PyMac_PRECHECK(GraphicsImportDoesDrawAllPixels); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportDoesDrawAllPixels(ci, &drawsAllPixels); @@ -12229,7 +12229,7 @@ PyMac_PRECHECK(GraphicsImportGetAsPicture); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetAsPicture(ci, &picture); @@ -12252,7 +12252,7 @@ PyMac_PRECHECK(GraphicsImportExportImageFile); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetOSType, &fileType, PyMac_GetOSType, &fileCreator, PyMac_GetFSSpec, &fss, @@ -12278,7 +12278,7 @@ PyMac_PRECHECK(GraphicsImportGetExportImageTypeList); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainerPtr)) return NULL; _rv = GraphicsImportGetExportImageTypeList(ci, @@ -12298,7 +12298,7 @@ PyMac_PRECHECK(GraphicsImportGetExportSettingsAsAtomContainer); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainerPtr)) return NULL; _rv = GraphicsImportGetExportSettingsAsAtomContainer(ci, @@ -12318,7 +12318,7 @@ PyMac_PRECHECK(GraphicsImportSetExportSettingsFromAtomContainer); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainer)) return NULL; _rv = GraphicsImportSetExportSettingsFromAtomContainer(ci, @@ -12338,7 +12338,7 @@ PyMac_PRECHECK(GraphicsImportGetImageCount); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetImageCount(ci, &imageCount); @@ -12358,7 +12358,7 @@ PyMac_PRECHECK(GraphicsImportSetImageIndex); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &imageIndex)) return NULL; _rv = GraphicsImportSetImageIndex(ci, @@ -12378,7 +12378,7 @@ PyMac_PRECHECK(GraphicsImportGetImageIndex); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetImageIndex(ci, &imageIndex); @@ -12399,7 +12399,7 @@ PyMac_PRECHECK(GraphicsImportGetDataOffsetAndSize64); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDataOffsetAndSize64(ci, &offset, @@ -12423,7 +12423,7 @@ PyMac_PRECHECK(GraphicsImportReadData64); #endif if (!PyArg_ParseTuple(_args, "O&sO&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &dataPtr, PyMac_Getwide, &dataOffset, &dataSize)) @@ -12448,7 +12448,7 @@ PyMac_PRECHECK(GraphicsImportSetDataReferenceOffsetAndLimit64); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_Getwide, &offset, PyMac_Getwide, &limit)) return NULL; @@ -12471,7 +12471,7 @@ PyMac_PRECHECK(GraphicsImportGetDataReferenceOffsetAndLimit64); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDataReferenceOffsetAndLimit64(ci, &offset, @@ -12493,7 +12493,7 @@ PyMac_PRECHECK(GraphicsImportGetDefaultClip); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDefaultClip(ci, &defaultRgn); @@ -12514,7 +12514,7 @@ PyMac_PRECHECK(GraphicsImportGetDefaultGraphicsMode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDefaultGraphicsMode(ci, &defaultGraphicsMode, @@ -12536,7 +12536,7 @@ PyMac_PRECHECK(GraphicsImportGetDefaultSourceRect); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDefaultSourceRect(ci, &defaultSourceRect); @@ -12556,7 +12556,7 @@ PyMac_PRECHECK(GraphicsImportGetColorSyncProfile); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetColorSyncProfile(ci, &profile); @@ -12576,7 +12576,7 @@ PyMac_PRECHECK(GraphicsImportSetDestRect); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetRect, &destRect)) return NULL; _rv = GraphicsImportSetDestRect(ci, @@ -12596,7 +12596,7 @@ PyMac_PRECHECK(GraphicsImportGetDestRect); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetDestRect(ci, &destRect); @@ -12616,7 +12616,7 @@ PyMac_PRECHECK(GraphicsImportSetFlags); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &flags)) return NULL; _rv = GraphicsImportSetFlags(ci, @@ -12636,7 +12636,7 @@ PyMac_PRECHECK(GraphicsImportGetFlags); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetFlags(ci, &flags); @@ -12657,7 +12657,7 @@ PyMac_PRECHECK(GraphicsImportGetBaseDataOffsetAndSize64); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportGetBaseDataOffsetAndSize64(ci, &offset, @@ -12678,7 +12678,7 @@ PyMac_PRECHECK(GraphicsImportSetImageIndexToThumbnail); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImportSetImageIndexToThumbnail(ci); _res = Py_BuildValue("l", @@ -12696,7 +12696,7 @@ PyMac_PRECHECK(GraphicsExportDoExport); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportDoExport(ci, &actualSizeWritten); @@ -12716,7 +12716,7 @@ PyMac_PRECHECK(GraphicsExportCanTranscode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportCanTranscode(ci, &canTranscode); @@ -12735,7 +12735,7 @@ PyMac_PRECHECK(GraphicsExportDoTranscode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportDoTranscode(ci); _res = Py_BuildValue("l", @@ -12754,7 +12754,7 @@ PyMac_PRECHECK(GraphicsExportCanUseCompressor); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &codecSettingsAtomContainerPtr)) return NULL; _rv = GraphicsExportCanUseCompressor(ci, @@ -12777,7 +12777,7 @@ PyMac_PRECHECK(GraphicsExportDoUseCompressor); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &codecSettingsAtomContainer)) return NULL; _rv = GraphicsExportDoUseCompressor(ci, @@ -12798,7 +12798,7 @@ PyMac_PRECHECK(GraphicsExportDoStandaloneExport); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportDoStandaloneExport(ci); _res = Py_BuildValue("l", @@ -12817,7 +12817,7 @@ PyMac_PRECHECK(GraphicsExportGetDefaultFileTypeAndCreator); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetDefaultFileTypeAndCreator(ci, &fileType, @@ -12839,7 +12839,7 @@ PyMac_PRECHECK(GraphicsExportGetDefaultFileNameExtension); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetDefaultFileNameExtension(ci, &fileNameExtension); @@ -12859,7 +12859,7 @@ PyMac_PRECHECK(GraphicsExportGetMIMETypeList); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainerPtr)) return NULL; _rv = GraphicsExportGetMIMETypeList(ci, @@ -12879,7 +12879,7 @@ PyMac_PRECHECK(GraphicsExportSetSettingsFromAtomContainer); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainer)) return NULL; _rv = GraphicsExportSetSettingsFromAtomContainer(ci, @@ -12899,7 +12899,7 @@ PyMac_PRECHECK(GraphicsExportGetSettingsAsAtomContainer); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &qtAtomContainerPtr)) return NULL; _rv = GraphicsExportGetSettingsAsAtomContainer(ci, @@ -12919,7 +12919,7 @@ PyMac_PRECHECK(GraphicsExportGetSettingsAsText); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetSettingsAsText(ci, &theText); @@ -12939,7 +12939,7 @@ PyMac_PRECHECK(GraphicsExportSetDontRecompress); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &dontRecompress)) return NULL; _rv = GraphicsExportSetDontRecompress(ci, @@ -12959,7 +12959,7 @@ PyMac_PRECHECK(GraphicsExportGetDontRecompress); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetDontRecompress(ci, &dontRecompress); @@ -12979,7 +12979,7 @@ PyMac_PRECHECK(GraphicsExportSetInterlaceStyle); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &interlaceStyle)) return NULL; _rv = GraphicsExportSetInterlaceStyle(ci, @@ -12999,7 +12999,7 @@ PyMac_PRECHECK(GraphicsExportGetInterlaceStyle); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInterlaceStyle(ci, &interlaceStyle); @@ -13019,7 +13019,7 @@ PyMac_PRECHECK(GraphicsExportSetMetaData); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &userData)) return NULL; _rv = GraphicsExportSetMetaData(ci, @@ -13039,7 +13039,7 @@ PyMac_PRECHECK(GraphicsExportGetMetaData); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &userData)) return NULL; _rv = GraphicsExportGetMetaData(ci, @@ -13059,7 +13059,7 @@ PyMac_PRECHECK(GraphicsExportSetTargetDataSize); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &targetDataSize)) return NULL; _rv = GraphicsExportSetTargetDataSize(ci, @@ -13079,7 +13079,7 @@ PyMac_PRECHECK(GraphicsExportGetTargetDataSize); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetTargetDataSize(ci, &targetDataSize); @@ -13099,7 +13099,7 @@ PyMac_PRECHECK(GraphicsExportSetCompressionMethod); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &compressionMethod)) return NULL; _rv = GraphicsExportSetCompressionMethod(ci, @@ -13119,7 +13119,7 @@ PyMac_PRECHECK(GraphicsExportGetCompressionMethod); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetCompressionMethod(ci, &compressionMethod); @@ -13139,7 +13139,7 @@ PyMac_PRECHECK(GraphicsExportSetCompressionQuality); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &spatialQuality)) return NULL; _rv = GraphicsExportSetCompressionQuality(ci, @@ -13159,7 +13159,7 @@ PyMac_PRECHECK(GraphicsExportGetCompressionQuality); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetCompressionQuality(ci, &spatialQuality); @@ -13180,7 +13180,7 @@ PyMac_PRECHECK(GraphicsExportSetResolution); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFixed, &horizontalResolution, PyMac_GetFixed, &verticalResolution)) return NULL; @@ -13203,7 +13203,7 @@ PyMac_PRECHECK(GraphicsExportGetResolution); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetResolution(ci, &horizontalResolution, @@ -13225,7 +13225,7 @@ PyMac_PRECHECK(GraphicsExportSetDepth); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &depth)) return NULL; _rv = GraphicsExportSetDepth(ci, @@ -13245,7 +13245,7 @@ PyMac_PRECHECK(GraphicsExportGetDepth); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetDepth(ci, &depth); @@ -13265,7 +13265,7 @@ PyMac_PRECHECK(GraphicsExportSetColorSyncProfile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &colorSyncProfile)) return NULL; _rv = GraphicsExportSetColorSyncProfile(ci, @@ -13285,7 +13285,7 @@ PyMac_PRECHECK(GraphicsExportGetColorSyncProfile); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetColorSyncProfile(ci, &colorSyncProfile); @@ -13307,7 +13307,7 @@ PyMac_PRECHECK(GraphicsExportSetInputDataReference); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType, ResObj_Convert, &desc)) @@ -13332,7 +13332,7 @@ PyMac_PRECHECK(GraphicsExportGetInputDataReference); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputDataReference(ci, &dataRef, @@ -13355,7 +13355,7 @@ PyMac_PRECHECK(GraphicsExportSetInputFile); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile, ResObj_Convert, &desc)) return NULL; @@ -13377,7 +13377,7 @@ PyMac_PRECHECK(GraphicsExportGetInputFile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile)) return NULL; _rv = GraphicsExportGetInputFile(ci, @@ -13398,7 +13398,7 @@ PyMac_PRECHECK(GraphicsExportSetInputHandle); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &h, ResObj_Convert, &desc)) return NULL; @@ -13420,7 +13420,7 @@ PyMac_PRECHECK(GraphicsExportGetInputHandle); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputHandle(ci, &h); @@ -13442,7 +13442,7 @@ PyMac_PRECHECK(GraphicsExportSetInputPtr); #endif if (!PyArg_ParseTuple(_args, "O&slO&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &p, &size, ResObj_Convert, &desc)) @@ -13466,8 +13466,8 @@ PyMac_PRECHECK(GraphicsExportSetInputGraphicsImporter); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, - CmpObj_Convert, &grip)) + CmpInstObj_Convert, &ci, + CmpInstObj_Convert, &grip)) return NULL; _rv = GraphicsExportSetInputGraphicsImporter(ci, grip); @@ -13486,13 +13486,13 @@ PyMac_PRECHECK(GraphicsExportGetInputGraphicsImporter); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputGraphicsImporter(ci, &grip); _res = Py_BuildValue("lO&", _rv, - CmpObj_New, grip); + CmpInstObj_New, grip); return _res; } @@ -13506,7 +13506,7 @@ PyMac_PRECHECK(GraphicsExportSetInputPicture); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &picture)) return NULL; _rv = GraphicsExportSetInputPicture(ci, @@ -13526,7 +13526,7 @@ PyMac_PRECHECK(GraphicsExportGetInputPicture); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputPicture(ci, &picture); @@ -13546,7 +13546,7 @@ PyMac_PRECHECK(GraphicsExportSetInputGWorld); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, GWorldObj_Convert, &gworld)) return NULL; _rv = GraphicsExportSetInputGWorld(ci, @@ -13566,7 +13566,7 @@ PyMac_PRECHECK(GraphicsExportGetInputGWorld); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputGWorld(ci, &gworld); @@ -13586,7 +13586,7 @@ PyMac_PRECHECK(GraphicsExportSetInputPixmap); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &pixmap)) return NULL; _rv = GraphicsExportSetInputPixmap(ci, @@ -13606,7 +13606,7 @@ PyMac_PRECHECK(GraphicsExportGetInputPixmap); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputPixmap(ci, &pixmap); @@ -13627,7 +13627,7 @@ PyMac_PRECHECK(GraphicsExportSetInputOffsetAndLimit); #endif if (!PyArg_ParseTuple(_args, "O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &offset, &limit)) return NULL; @@ -13650,7 +13650,7 @@ PyMac_PRECHECK(GraphicsExportGetInputOffsetAndLimit); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputOffsetAndLimit(ci, &offset, @@ -13672,7 +13672,7 @@ PyMac_PRECHECK(GraphicsExportMayExporterReadInputData); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportMayExporterReadInputData(ci, &mayReadInputData); @@ -13692,7 +13692,7 @@ PyMac_PRECHECK(GraphicsExportGetInputDataSize); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputDataSize(ci, &size); @@ -13714,7 +13714,7 @@ PyMac_PRECHECK(GraphicsExportReadInputData); #endif if (!PyArg_ParseTuple(_args, "O&sll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &dataPtr, &dataOffset, &dataSize)) @@ -13738,7 +13738,7 @@ PyMac_PRECHECK(GraphicsExportGetInputImageDescription); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputImageDescription(ci, &desc); @@ -13758,7 +13758,7 @@ PyMac_PRECHECK(GraphicsExportGetInputImageDimensions); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputImageDimensions(ci, &dimensions); @@ -13778,7 +13778,7 @@ PyMac_PRECHECK(GraphicsExportGetInputImageDepth); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetInputImageDepth(ci, &inputDepth); @@ -13801,7 +13801,7 @@ PyMac_PRECHECK(GraphicsExportDrawInputImage); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, GrafObj_Convert, &gw, OptResObj_Convert, &gd, PyMac_GetRect, &srcRect, @@ -13828,7 +13828,7 @@ PyMac_PRECHECK(GraphicsExportSetOutputDataReference); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType)) return NULL; @@ -13851,7 +13851,7 @@ PyMac_PRECHECK(GraphicsExportGetOutputDataReference); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetOutputDataReference(ci, &dataRef, @@ -13873,7 +13873,7 @@ PyMac_PRECHECK(GraphicsExportSetOutputFile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile)) return NULL; _rv = GraphicsExportSetOutputFile(ci, @@ -13893,7 +13893,7 @@ PyMac_PRECHECK(GraphicsExportGetOutputFile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile)) return NULL; _rv = GraphicsExportGetOutputFile(ci, @@ -13913,7 +13913,7 @@ PyMac_PRECHECK(GraphicsExportSetOutputHandle); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &h)) return NULL; _rv = GraphicsExportSetOutputHandle(ci, @@ -13933,7 +13933,7 @@ PyMac_PRECHECK(GraphicsExportGetOutputHandle); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetOutputHandle(ci, &h); @@ -13955,7 +13955,7 @@ PyMac_PRECHECK(GraphicsExportSetOutputOffsetAndMaxSize); #endif if (!PyArg_ParseTuple(_args, "O&llb", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &offset, &maxSize, &truncateFile)) @@ -13981,7 +13981,7 @@ PyMac_PRECHECK(GraphicsExportGetOutputOffsetAndMaxSize); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetOutputOffsetAndMaxSize(ci, &offset, @@ -14006,7 +14006,7 @@ PyMac_PRECHECK(GraphicsExportSetOutputFileTypeAndCreator); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetOSType, &fileType, PyMac_GetOSType, &fileCreator)) return NULL; @@ -14029,7 +14029,7 @@ PyMac_PRECHECK(GraphicsExportGetOutputFileTypeAndCreator); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetOutputFileTypeAndCreator(ci, &fileType, @@ -14051,7 +14051,7 @@ PyMac_PRECHECK(GraphicsExportSetOutputMark); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &mark)) return NULL; _rv = GraphicsExportSetOutputMark(ci, @@ -14071,7 +14071,7 @@ PyMac_PRECHECK(GraphicsExportGetOutputMark); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetOutputMark(ci, &mark); @@ -14093,7 +14093,7 @@ PyMac_PRECHECK(GraphicsExportReadOutputData); #endif if (!PyArg_ParseTuple(_args, "O&sll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &dataPtr, &dataOffset, &dataSize)) @@ -14119,7 +14119,7 @@ PyMac_PRECHECK(GraphicsExportSetThumbnailEnabled); #endif if (!PyArg_ParseTuple(_args, "O&bll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &enableThumbnail, &maxThumbnailWidth, &maxThumbnailHeight)) @@ -14145,7 +14145,7 @@ PyMac_PRECHECK(GraphicsExportGetThumbnailEnabled); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetThumbnailEnabled(ci, &thumbnailEnabled, @@ -14169,7 +14169,7 @@ PyMac_PRECHECK(GraphicsExportSetExifEnabled); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &enableExif)) return NULL; _rv = GraphicsExportSetExifEnabled(ci, @@ -14189,7 +14189,7 @@ PyMac_PRECHECK(GraphicsExportGetExifEnabled); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsExportGetExifEnabled(ci, &exifEnabled); @@ -14212,7 +14212,7 @@ PyMac_PRECHECK(ImageTranscoderBeginSequence); #endif if (!PyArg_ParseTuple(_args, "O&O&sl", - CmpObj_Convert, &itc, + CmpInstObj_Convert, &itc, ResObj_Convert, &srcDesc, &data, &dataSize)) @@ -14238,7 +14238,7 @@ PyMac_PRECHECK(ImageTranscoderDisposeData); #endif if (!PyArg_ParseTuple(_args, "O&s", - CmpObj_Convert, &itc, + CmpInstObj_Convert, &itc, &dstData)) return NULL; _rv = ImageTranscoderDisposeData(itc, @@ -14257,7 +14257,7 @@ PyMac_PRECHECK(ImageTranscoderEndSequence); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &itc)) + CmpInstObj_Convert, &itc)) return NULL; _rv = ImageTranscoderEndSequence(itc); _res = Py_BuildValue("l", @@ -14854,7 +14854,7 @@ PyMac_PRECHECK(TweenerReset); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &tc)) + CmpInstObj_Convert, &tc)) return NULL; _rv = TweenerReset(tc); _res = Py_BuildValue("l", @@ -14968,7 +14968,7 @@ PyMac_PRECHECK(MovieImportHandle); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataH, MovieObj_Convert, &theMovie, TrackObj_Convert, &targetTrack, @@ -15009,7 +15009,7 @@ PyMac_PRECHECK(MovieImportFile); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile, MovieObj_Convert, &theMovie, TrackObj_Convert, &targetTrack, @@ -15044,7 +15044,7 @@ PyMac_PRECHECK(MovieImportSetSampleDuration); #endif if (!PyArg_ParseTuple(_args, "O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &duration, &scale)) return NULL; @@ -15067,7 +15067,7 @@ PyMac_PRECHECK(MovieImportSetSampleDescription); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &desc, PyMac_GetOSType, &mediaType)) return NULL; @@ -15089,7 +15089,7 @@ PyMac_PRECHECK(MovieImportSetMediaFile); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &alias)) return NULL; _rv = MovieImportSetMediaFile(ci, @@ -15110,7 +15110,7 @@ PyMac_PRECHECK(MovieImportSetDimensions); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFixed, &width, PyMac_GetFixed, &height)) return NULL; @@ -15132,7 +15132,7 @@ PyMac_PRECHECK(MovieImportSetChunkSize); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &chunkSize)) return NULL; _rv = MovieImportSetChunkSize(ci, @@ -15153,7 +15153,7 @@ PyMac_PRECHECK(MovieImportSetAuxiliaryData); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &data, PyMac_GetOSType, &handleType)) return NULL; @@ -15175,7 +15175,7 @@ PyMac_PRECHECK(MovieImportSetFromScrap); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &fromScrap)) return NULL; _rv = MovieImportSetFromScrap(ci, @@ -15197,7 +15197,7 @@ PyMac_PRECHECK(MovieImportDoUserDialog); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile, ResObj_Convert, &theData)) return NULL; @@ -15221,7 +15221,7 @@ PyMac_PRECHECK(MovieImportSetDuration); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &duration)) return NULL; _rv = MovieImportSetDuration(ci, @@ -15241,7 +15241,7 @@ PyMac_PRECHECK(MovieImportGetAuxiliaryDataType); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetAuxiliaryDataType(ci, &auxType); @@ -15263,7 +15263,7 @@ PyMac_PRECHECK(MovieImportValidate); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile, ResObj_Convert, &theData)) return NULL; @@ -15287,7 +15287,7 @@ PyMac_PRECHECK(MovieImportGetFileType); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetFileType(ci, &fileType); @@ -15315,7 +15315,7 @@ PyMac_PRECHECK(MovieImportDataRef); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType, MovieObj_Convert, &theMovie, @@ -15352,7 +15352,7 @@ PyMac_PRECHECK(MovieImportGetSampleDescription); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetSampleDescription(ci, &desc, @@ -15375,7 +15375,7 @@ PyMac_PRECHECK(MovieImportSetOffsetAndLimit); #endif if (!PyArg_ParseTuple(_args, "O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &offset, &limit)) return NULL; @@ -15398,7 +15398,7 @@ PyMac_PRECHECK(MovieImportSetOffsetAndLimit64); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_Getwide, &offset, PyMac_Getwide, &limit)) return NULL; @@ -15421,7 +15421,7 @@ PyMac_PRECHECK(MovieImportIdle); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &inFlags)) return NULL; _rv = MovieImportIdle(ci, @@ -15445,7 +15445,7 @@ PyMac_PRECHECK(MovieImportValidateDataRef); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType)) return NULL; @@ -15469,7 +15469,7 @@ PyMac_PRECHECK(MovieImportGetLoadState); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetLoadState(ci, &importerLoadState); @@ -15489,7 +15489,7 @@ PyMac_PRECHECK(MovieImportGetMaxLoadedTime); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetMaxLoadedTime(ci, &time); @@ -15509,7 +15509,7 @@ PyMac_PRECHECK(MovieImportEstimateCompletionTime); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportEstimateCompletionTime(ci, &time); @@ -15529,7 +15529,7 @@ PyMac_PRECHECK(MovieImportSetDontBlock); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &dontBlock)) return NULL; _rv = MovieImportSetDontBlock(ci, @@ -15549,7 +15549,7 @@ PyMac_PRECHECK(MovieImportGetDontBlock); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetDontBlock(ci, &willBlock); @@ -15569,7 +15569,7 @@ PyMac_PRECHECK(MovieImportSetIdleManager); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, IdleManagerObj_Convert, &im)) return NULL; _rv = MovieImportSetIdleManager(ci, @@ -15589,7 +15589,7 @@ PyMac_PRECHECK(MovieImportSetNewMovieFlags); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &newMovieFlags)) return NULL; _rv = MovieImportSetNewMovieFlags(ci, @@ -15609,7 +15609,7 @@ PyMac_PRECHECK(MovieImportGetDestinationMediaType); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieImportGetDestinationMediaType(ci, &mediaType); @@ -15633,7 +15633,7 @@ PyMac_PRECHECK(MovieExportToHandle); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataH, MovieObj_Convert, &theMovie, TrackObj_Convert, &onlyThisTrack, @@ -15665,7 +15665,7 @@ PyMac_PRECHECK(MovieExportToFile); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFSSpec, &theFile, MovieObj_Convert, &theMovie, TrackObj_Convert, &onlyThisTrack, @@ -15694,7 +15694,7 @@ PyMac_PRECHECK(MovieExportGetAuxiliaryData); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataH)) return NULL; _rv = MovieExportGetAuxiliaryData(ci, @@ -15717,7 +15717,7 @@ PyMac_PRECHECK(MovieExportSetSampleDescription); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &desc, PyMac_GetOSType, &mediaType)) return NULL; @@ -15743,7 +15743,7 @@ PyMac_PRECHECK(MovieExportDoUserDialog); #endif if (!PyArg_ParseTuple(_args, "O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, MovieObj_Convert, &theMovie, TrackObj_Convert, &onlyThisTrack, &startTime, @@ -15771,7 +15771,7 @@ PyMac_PRECHECK(MovieExportGetCreatorType); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieExportGetCreatorType(ci, &creator); @@ -15796,7 +15796,7 @@ PyMac_PRECHECK(MovieExportToDataRef); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType, MovieObj_Convert, &theMovie, @@ -15827,7 +15827,7 @@ PyMac_PRECHECK(MovieExportFromProceduresToDataRef); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType)) return NULL; @@ -15851,7 +15851,7 @@ PyMac_PRECHECK(MovieExportValidate); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, MovieObj_Convert, &theMovie, TrackObj_Convert, &onlyThisTrack)) return NULL; @@ -15875,7 +15875,7 @@ PyMac_PRECHECK(MovieExportGetFileNameExtension); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieExportGetFileNameExtension(ci, &extension); @@ -15895,7 +15895,7 @@ PyMac_PRECHECK(MovieExportGetShortFileTypeString); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetStr255, typeString)) return NULL; _rv = MovieExportGetShortFileTypeString(ci, @@ -15915,7 +15915,7 @@ PyMac_PRECHECK(MovieExportGetSourceMediaType); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MovieExportGetSourceMediaType(ci, &mediaType); @@ -15935,7 +15935,7 @@ PyMac_PRECHECK(TextExportGetTimeFraction); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = TextExportGetTimeFraction(ci, &movieTimeFraction); @@ -15955,7 +15955,7 @@ PyMac_PRECHECK(TextExportSetTimeFraction); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &movieTimeFraction)) return NULL; _rv = TextExportSetTimeFraction(ci, @@ -15975,7 +15975,7 @@ PyMac_PRECHECK(TextExportGetSettings); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = TextExportGetSettings(ci, &setting); @@ -15995,7 +15995,7 @@ PyMac_PRECHECK(TextExportSetSettings); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &setting)) return NULL; _rv = TextExportSetSettings(ci, @@ -16015,7 +16015,7 @@ PyMac_PRECHECK(MIDIImportGetSettings); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = MIDIImportGetSettings(ci, &setting); @@ -16035,7 +16035,7 @@ PyMac_PRECHECK(MIDIImportSetSettings); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &setting)) return NULL; _rv = MIDIImportSetSettings(ci, @@ -16055,7 +16055,7 @@ PyMac_PRECHECK(GraphicsImageImportSetSequenceEnabled); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &enable)) return NULL; _rv = GraphicsImageImportSetSequenceEnabled(ci, @@ -16075,7 +16075,7 @@ PyMac_PRECHECK(GraphicsImageImportGetSequenceEnabled); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = GraphicsImageImportGetSequenceEnabled(ci, &enable); @@ -16097,7 +16097,7 @@ PyMac_PRECHECK(PreviewShowData); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&", - CmpObj_Convert, &p, + CmpInstObj_Convert, &p, PyMac_GetOSType, &dataType, ResObj_Convert, &data, PyMac_GetRect, &inHere)) @@ -16123,7 +16123,7 @@ PyMac_PRECHECK(PreviewMakePreviewReference); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &p, + CmpInstObj_Convert, &p, PyMac_GetFSSpec, &sourceFile)) return NULL; _rv = PreviewMakePreviewReference(p, @@ -16148,7 +16148,7 @@ PyMac_PRECHECK(PreviewEvent); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &p)) + CmpInstObj_Convert, &p)) return NULL; _rv = PreviewEvent(p, &e, @@ -16173,7 +16173,7 @@ PyMac_PRECHECK(DataCodecDecompress); #endif if (!PyArg_ParseTuple(_args, "O&slsl", - CmpObj_Convert, &dc, + CmpInstObj_Convert, &dc, &srcData, &srcSize, &dstData, @@ -16200,7 +16200,7 @@ PyMac_PRECHECK(DataCodecGetCompressBufferSize); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &dc, + CmpInstObj_Convert, &dc, &srcSize)) return NULL; _rv = DataCodecGetCompressBufferSize(dc, @@ -16227,7 +16227,7 @@ PyMac_PRECHECK(DataCodecCompress); #endif if (!PyArg_ParseTuple(_args, "O&slsl", - CmpObj_Convert, &dc, + CmpInstObj_Convert, &dc, &srcData, &srcSize, &dstData, @@ -16257,7 +16257,7 @@ PyMac_PRECHECK(DataCodecBeginInterruptSafe); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &dc, + CmpInstObj_Convert, &dc, &maxSrcSize)) return NULL; _rv = DataCodecBeginInterruptSafe(dc, @@ -16276,7 +16276,7 @@ PyMac_PRECHECK(DataCodecEndInterruptSafe); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &dc)) + CmpInstObj_Convert, &dc)) return NULL; _rv = DataCodecEndInterruptSafe(dc); _res = Py_BuildValue("l", @@ -17695,7 +17695,7 @@ PyMac_PRECHECK(VDGetMaxSrcRect); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &inputStd)) return NULL; _rv = VDGetMaxSrcRect(ci, @@ -17718,7 +17718,7 @@ PyMac_PRECHECK(VDGetActiveSrcRect); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &inputStd)) return NULL; _rv = VDGetActiveSrcRect(ci, @@ -17740,7 +17740,7 @@ PyMac_PRECHECK(VDSetDigitizerRect); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetDigitizerRect(ci, &digitizerRect); @@ -17760,7 +17760,7 @@ PyMac_PRECHECK(VDGetDigitizerRect); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetDigitizerRect(ci, &digitizerRect); @@ -17781,7 +17781,7 @@ PyMac_PRECHECK(VDGetVBlankRect); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &inputStd)) return NULL; _rv = VDGetVBlankRect(ci, @@ -17803,7 +17803,7 @@ PyMac_PRECHECK(VDGetMaskPixMap); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &maskPixMap)) return NULL; _rv = VDGetMaskPixMap(ci, @@ -17823,7 +17823,7 @@ PyMac_PRECHECK(VDUseThisCLUT); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &colorTableHandle)) return NULL; _rv = VDUseThisCLUT(ci, @@ -17845,7 +17845,7 @@ PyMac_PRECHECK(VDSetInputGammaValue); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFixed, &channel1, PyMac_GetFixed, &channel2, PyMac_GetFixed, &channel3)) @@ -17871,7 +17871,7 @@ PyMac_PRECHECK(VDGetInputGammaValue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetInputGammaValue(ci, &channel1, @@ -17895,7 +17895,7 @@ PyMac_PRECHECK(VDSetBrightness); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetBrightness(ci, &brightness); @@ -17915,7 +17915,7 @@ PyMac_PRECHECK(VDGetBrightness); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetBrightness(ci, &brightness); @@ -17935,7 +17935,7 @@ PyMac_PRECHECK(VDSetContrast); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetContrast(ci, &contrast); @@ -17955,7 +17955,7 @@ PyMac_PRECHECK(VDSetHue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetHue(ci, &hue); @@ -17975,7 +17975,7 @@ PyMac_PRECHECK(VDSetSharpness); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetSharpness(ci, &sharpness); @@ -17995,7 +17995,7 @@ PyMac_PRECHECK(VDSetSaturation); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetSaturation(ci, &saturation); @@ -18015,7 +18015,7 @@ PyMac_PRECHECK(VDGetContrast); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetContrast(ci, &contrast); @@ -18035,7 +18035,7 @@ PyMac_PRECHECK(VDGetHue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetHue(ci, &hue); @@ -18055,7 +18055,7 @@ PyMac_PRECHECK(VDGetSharpness); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetSharpness(ci, &sharpness); @@ -18075,7 +18075,7 @@ PyMac_PRECHECK(VDGetSaturation); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetSaturation(ci, &saturation); @@ -18094,7 +18094,7 @@ PyMac_PRECHECK(VDGrabOneFrame); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGrabOneFrame(ci); _res = Py_BuildValue("l", @@ -18113,7 +18113,7 @@ PyMac_PRECHECK(VDGetMaxAuxBuffer); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetMaxAuxBuffer(ci, &pm, @@ -18136,7 +18136,7 @@ PyMac_PRECHECK(VDGetCurrentFlags); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetCurrentFlags(ci, &inputCurrentFlag, @@ -18158,7 +18158,7 @@ PyMac_PRECHECK(VDSetKeyColor); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &index)) return NULL; _rv = VDSetKeyColor(ci, @@ -18178,7 +18178,7 @@ PyMac_PRECHECK(VDGetKeyColor); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetKeyColor(ci, &index); @@ -18198,7 +18198,7 @@ PyMac_PRECHECK(VDAddKeyColor); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDAddKeyColor(ci, &index); @@ -18218,7 +18218,7 @@ PyMac_PRECHECK(VDGetNextKeyColor); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &index)) return NULL; _rv = VDGetNextKeyColor(ci, @@ -18239,7 +18239,7 @@ PyMac_PRECHECK(VDSetKeyColorRange); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetKeyColorRange(ci, &minRGB, @@ -18262,7 +18262,7 @@ PyMac_PRECHECK(VDGetKeyColorRange); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetKeyColorRange(ci, &minRGB, @@ -18284,7 +18284,7 @@ PyMac_PRECHECK(VDSetInputColorSpaceMode); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &colorSpaceMode)) return NULL; _rv = VDSetInputColorSpaceMode(ci, @@ -18304,7 +18304,7 @@ PyMac_PRECHECK(VDGetInputColorSpaceMode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetInputColorSpaceMode(ci, &colorSpaceMode); @@ -18324,7 +18324,7 @@ PyMac_PRECHECK(VDSetClipState); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &clipEnable)) return NULL; _rv = VDSetClipState(ci, @@ -18344,7 +18344,7 @@ PyMac_PRECHECK(VDGetClipState); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetClipState(ci, &clipEnable); @@ -18364,7 +18364,7 @@ PyMac_PRECHECK(VDSetClipRgn); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &clipRegion)) return NULL; _rv = VDSetClipRgn(ci, @@ -18384,7 +18384,7 @@ PyMac_PRECHECK(VDClearClipRgn); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &clipRegion)) return NULL; _rv = VDClearClipRgn(ci, @@ -18404,7 +18404,7 @@ PyMac_PRECHECK(VDGetCLUTInUse); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetCLUTInUse(ci, &colorTableHandle); @@ -18424,7 +18424,7 @@ PyMac_PRECHECK(VDSetPLLFilterType); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &pllType)) return NULL; _rv = VDSetPLLFilterType(ci, @@ -18444,7 +18444,7 @@ PyMac_PRECHECK(VDGetPLLFilterType); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetPLLFilterType(ci, &pllType); @@ -18466,7 +18466,7 @@ PyMac_PRECHECK(VDGetMaskandValue); #endif if (!PyArg_ParseTuple(_args, "O&H", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &blendLevel)) return NULL; _rv = VDGetMaskandValue(ci, @@ -18490,7 +18490,7 @@ PyMac_PRECHECK(VDSetMasterBlendLevel); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetMasterBlendLevel(ci, &blendLevel); @@ -18510,7 +18510,7 @@ PyMac_PRECHECK(VDSetPlayThruOnOff); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &state)) return NULL; _rv = VDSetPlayThruOnOff(ci, @@ -18530,7 +18530,7 @@ PyMac_PRECHECK(VDSetFieldPreference); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &fieldFlag)) return NULL; _rv = VDSetFieldPreference(ci, @@ -18550,7 +18550,7 @@ PyMac_PRECHECK(VDGetFieldPreference); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetFieldPreference(ci, &fieldFlag); @@ -18571,7 +18571,7 @@ PyMac_PRECHECK(VDPreflightGlobalRect); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, GrafObj_Convert, &theWindow)) return NULL; _rv = VDPreflightGlobalRect(ci, @@ -18594,7 +18594,7 @@ PyMac_PRECHECK(VDSetPlayThruGlobalRect); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, GrafObj_Convert, &theWindow)) return NULL; _rv = VDSetPlayThruGlobalRect(ci, @@ -18616,7 +18616,7 @@ PyMac_PRECHECK(VDSetBlackLevelValue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetBlackLevelValue(ci, &blackLevel); @@ -18636,7 +18636,7 @@ PyMac_PRECHECK(VDGetBlackLevelValue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetBlackLevelValue(ci, &blackLevel); @@ -18656,7 +18656,7 @@ PyMac_PRECHECK(VDSetWhiteLevelValue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDSetWhiteLevelValue(ci, &whiteLevel); @@ -18676,7 +18676,7 @@ PyMac_PRECHECK(VDGetWhiteLevelValue); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetWhiteLevelValue(ci, &whiteLevel); @@ -18702,7 +18702,7 @@ PyMac_PRECHECK(VDGetVideoDefaults); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetVideoDefaults(ci, &blackLevel, @@ -18734,7 +18734,7 @@ PyMac_PRECHECK(VDGetNumberOfInputs); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetNumberOfInputs(ci, &inputs); @@ -18755,7 +18755,7 @@ PyMac_PRECHECK(VDGetInputFormat); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &input)) return NULL; _rv = VDGetInputFormat(ci, @@ -18777,7 +18777,7 @@ PyMac_PRECHECK(VDSetInput); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &input)) return NULL; _rv = VDSetInput(ci, @@ -18797,7 +18797,7 @@ PyMac_PRECHECK(VDGetInput); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetInput(ci, &input); @@ -18817,7 +18817,7 @@ PyMac_PRECHECK(VDSetInputStandard); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &inputStandard)) return NULL; _rv = VDSetInputStandard(ci, @@ -18837,7 +18837,7 @@ PyMac_PRECHECK(VDSetupBuffers); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &bufferList)) return NULL; _rv = VDSetupBuffers(ci, @@ -18857,7 +18857,7 @@ PyMac_PRECHECK(VDGrabOneFrameAsync); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &buffer)) return NULL; _rv = VDGrabOneFrameAsync(ci, @@ -18877,7 +18877,7 @@ PyMac_PRECHECK(VDDone); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &buffer)) return NULL; _rv = VDDone(ci, @@ -18902,7 +18902,7 @@ PyMac_PRECHECK(VDSetCompression); #endif if (!PyArg_ParseTuple(_args, "O&O&hlll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetOSType, &compressType, &depth, &spatialQuality, @@ -18931,7 +18931,7 @@ PyMac_PRECHECK(VDCompressOneFrameAsync); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDCompressOneFrameAsync(ci); _res = Py_BuildValue("l", @@ -18949,7 +18949,7 @@ PyMac_PRECHECK(VDGetImageDescription); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &desc)) return NULL; _rv = VDGetImageDescription(ci, @@ -18968,7 +18968,7 @@ PyMac_PRECHECK(VDResetCompressSequence); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDResetCompressSequence(ci); _res = Py_BuildValue("l", @@ -18986,7 +18986,7 @@ PyMac_PRECHECK(VDSetCompressionOnOff); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &state)) return NULL; _rv = VDSetCompressionOnOff(ci, @@ -19006,7 +19006,7 @@ PyMac_PRECHECK(VDGetCompressionTypes); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, ResObj_Convert, &h)) return NULL; _rv = VDGetCompressionTypes(ci, @@ -19026,7 +19026,7 @@ PyMac_PRECHECK(VDSetTimeBase); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, TimeBaseObj_Convert, &t)) return NULL; _rv = VDSetTimeBase(ci, @@ -19046,7 +19046,7 @@ PyMac_PRECHECK(VDSetFrameRate); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetFixed, &framesPerSecond)) return NULL; _rv = VDSetFrameRate(ci, @@ -19068,7 +19068,7 @@ PyMac_PRECHECK(VDGetDataRate); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetDataRate(ci, &milliSecPerFrame, @@ -19092,7 +19092,7 @@ PyMac_PRECHECK(VDGetSoundInputDriver); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetStr255, soundDriverName)) return NULL; _rv = VDGetSoundInputDriver(ci, @@ -19113,7 +19113,7 @@ PyMac_PRECHECK(VDGetDMADepths); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetDMADepths(ci, &depthArray, @@ -19135,7 +19135,7 @@ PyMac_PRECHECK(VDGetPreferredTimeScale); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetPreferredTimeScale(ci, &preferred); @@ -19154,7 +19154,7 @@ PyMac_PRECHECK(VDReleaseAsyncBuffers); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDReleaseAsyncBuffers(ci); _res = Py_BuildValue("l", @@ -19172,7 +19172,7 @@ PyMac_PRECHECK(VDSetDataRate); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &bytesPerSecond)) return NULL; _rv = VDSetDataRate(ci, @@ -19194,7 +19194,7 @@ PyMac_PRECHECK(VDGetTimeCode); #endif if (!PyArg_ParseTuple(_args, "O&ss", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &timeCodeFormat, &timeCodeTime)) return NULL; @@ -19218,7 +19218,7 @@ PyMac_PRECHECK(VDUseSafeBuffers); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &useSafeBuffers)) return NULL; _rv = VDUseSafeBuffers(ci, @@ -19239,7 +19239,7 @@ PyMac_PRECHECK(VDGetSoundInputSource); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &videoInput)) return NULL; _rv = VDGetSoundInputSource(ci, @@ -19266,7 +19266,7 @@ PyMac_PRECHECK(VDGetCompressionTime); #endif if (!PyArg_ParseTuple(_args, "O&O&h", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetOSType, &compressionType, &depth)) return NULL; @@ -19296,7 +19296,7 @@ PyMac_PRECHECK(VDSetPreferredPacketSize); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &preferredPacketSizeInBytes)) return NULL; _rv = VDSetPreferredPacketSize(ci, @@ -19317,7 +19317,7 @@ PyMac_PRECHECK(VDSetPreferredImageDimensions); #endif if (!PyArg_ParseTuple(_args, "O&ll", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &width, &height)) return NULL; @@ -19340,7 +19340,7 @@ PyMac_PRECHECK(VDGetPreferredImageDimensions); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &ci)) + CmpInstObj_Convert, &ci)) return NULL; _rv = VDGetPreferredImageDimensions(ci, &width, @@ -19363,7 +19363,7 @@ PyMac_PRECHECK(VDGetInputName); #endif if (!PyArg_ParseTuple(_args, "O&lO&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &videoInput, PyMac_GetStr255, name)) return NULL; @@ -19385,7 +19385,7 @@ PyMac_PRECHECK(VDSetDestinationPort); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, GrafObj_Convert, &destPort)) return NULL; _rv = VDSetDestinationPort(ci, @@ -19406,7 +19406,7 @@ PyMac_PRECHECK(VDGetDeviceNameAndFlags); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, PyMac_GetStr255, outName)) return NULL; _rv = VDGetDeviceNameAndFlags(ci, @@ -19428,7 +19428,7 @@ PyMac_PRECHECK(VDCaptureStateChanging); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &ci, + CmpInstObj_Convert, &ci, &inStateFlags)) return NULL; _rv = VDCaptureStateChanging(ci, @@ -19687,7 +19687,7 @@ PyMac_PRECHECK(SGInitialize); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGInitialize(s); _res = Py_BuildValue("l", @@ -19706,7 +19706,7 @@ PyMac_PRECHECK(SGSetDataOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, PyMac_GetFSSpec, &movieFile, &whereFlags)) return NULL; @@ -19729,7 +19729,7 @@ PyMac_PRECHECK(SGGetDataOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, PyMac_GetFSSpec, &movieFile)) return NULL; _rv = SGGetDataOutput(s, @@ -19752,7 +19752,7 @@ PyMac_PRECHECK(SGSetGWorld); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, GrafObj_Convert, &gp, OptResObj_Convert, &gd)) return NULL; @@ -19775,7 +19775,7 @@ PyMac_PRECHECK(SGGetGWorld); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetGWorld(s, &gp, @@ -19798,7 +19798,7 @@ PyMac_PRECHECK(SGNewChannel); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, PyMac_GetOSType, &channelType)) return NULL; _rv = SGNewChannel(s, @@ -19820,7 +19820,7 @@ PyMac_PRECHECK(SGDisposeChannel); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c)) return NULL; _rv = SGDisposeChannel(s, @@ -19839,7 +19839,7 @@ PyMac_PRECHECK(SGStartPreview); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGStartPreview(s); _res = Py_BuildValue("l", @@ -19856,7 +19856,7 @@ PyMac_PRECHECK(SGStartRecord); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGStartRecord(s); _res = Py_BuildValue("l", @@ -19873,7 +19873,7 @@ PyMac_PRECHECK(SGIdle); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGIdle(s); _res = Py_BuildValue("l", @@ -19890,7 +19890,7 @@ PyMac_PRECHECK(SGStop); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGStop(s); _res = Py_BuildValue("l", @@ -19908,7 +19908,7 @@ PyMac_PRECHECK(SGPause); #endif if (!PyArg_ParseTuple(_args, "O&b", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &pause)) return NULL; _rv = SGPause(s, @@ -19929,7 +19929,7 @@ PyMac_PRECHECK(SGPrepare); #endif if (!PyArg_ParseTuple(_args, "O&bb", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &prepareForPreview, &prepareForRecord)) return NULL; @@ -19950,7 +19950,7 @@ PyMac_PRECHECK(SGRelease); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGRelease(s); _res = Py_BuildValue("l", @@ -19967,7 +19967,7 @@ PyMac_PRECHECK(SGGetMovie); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetMovie(s); _res = Py_BuildValue("O&", @@ -19985,7 +19985,7 @@ PyMac_PRECHECK(SGSetMaximumRecordTime); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &ticks)) return NULL; _rv = SGSetMaximumRecordTime(s, @@ -20005,7 +20005,7 @@ PyMac_PRECHECK(SGGetMaximumRecordTime); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetMaximumRecordTime(s, &ticks); @@ -20025,7 +20025,7 @@ PyMac_PRECHECK(SGGetStorageSpaceRemaining); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetStorageSpaceRemaining(s, &bytes); @@ -20045,7 +20045,7 @@ PyMac_PRECHECK(SGGetTimeRemaining); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetTimeRemaining(s, &ticksLeft); @@ -20068,7 +20068,7 @@ PyMac_PRECHECK(SGGrabPict); #endif if (!PyArg_ParseTuple(_args, "O&O&hl", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, PyMac_GetRect, &bounds, &offscreenDepth, &grabPictFlags)) @@ -20094,7 +20094,7 @@ PyMac_PRECHECK(SGGetLastMovieResID); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetLastMovieResID(s, &resID); @@ -20114,7 +20114,7 @@ PyMac_PRECHECK(SGSetFlags); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &sgFlags)) return NULL; _rv = SGSetFlags(s, @@ -20134,7 +20134,7 @@ PyMac_PRECHECK(SGGetFlags); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetFlags(s, &sgFlags); @@ -20155,7 +20155,7 @@ PyMac_PRECHECK(SGNewChannelFromComponent); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpObj_Convert, &sgChannelComponent)) return NULL; _rv = SGNewChannelFromComponent(s, @@ -20178,7 +20178,7 @@ PyMac_PRECHECK(SGSetSettings); #endif if (!PyArg_ParseTuple(_args, "O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, UserDataObj_Convert, &ud, &flags)) return NULL; @@ -20201,7 +20201,7 @@ PyMac_PRECHECK(SGGetSettings); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &flags)) return NULL; _rv = SGGetSettings(s, @@ -20225,7 +20225,7 @@ PyMac_PRECHECK(SGGetIndChannel); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &index)) return NULL; _rv = SGGetIndChannel(s, @@ -20249,7 +20249,7 @@ PyMac_PRECHECK(SGUpdate); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, ResObj_Convert, &updateRgn)) return NULL; _rv = SGUpdate(s, @@ -20269,7 +20269,7 @@ PyMac_PRECHECK(SGGetPause); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetPause(s, &paused); @@ -20291,7 +20291,7 @@ PyMac_PRECHECK(SGSetChannelSettings); #endif if (!PyArg_ParseTuple(_args, "O&O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, UserDataObj_Convert, &ud, &flags)) @@ -20317,7 +20317,7 @@ PyMac_PRECHECK(SGGetChannelSettings); #endif if (!PyArg_ParseTuple(_args, "O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, &flags)) return NULL; @@ -20342,7 +20342,7 @@ PyMac_PRECHECK(SGGetMode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetMode(s, &previewMode, @@ -20366,7 +20366,7 @@ PyMac_PRECHECK(SGSetDataRef); #endif if (!PyArg_ParseTuple(_args, "O&O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType, &whereFlags)) @@ -20392,7 +20392,7 @@ PyMac_PRECHECK(SGGetDataRef); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetDataRef(s, &dataRef, @@ -20419,7 +20419,7 @@ PyMac_PRECHECK(SGNewOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, ResObj_Convert, &dataRef, PyMac_GetOSType, &dataRefType, &whereFlags)) @@ -20445,7 +20445,7 @@ PyMac_PRECHECK(SGDisposeOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut)) return NULL; _rv = SGDisposeOutput(s, @@ -20466,7 +20466,7 @@ PyMac_PRECHECK(SGSetOutputFlags); #endif if (!PyArg_ParseTuple(_args, "O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut, &whereFlags)) return NULL; @@ -20489,7 +20489,7 @@ PyMac_PRECHECK(SGSetChannelOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, SGOutputObj_Convert, &sgOut)) return NULL; @@ -20512,7 +20512,7 @@ PyMac_PRECHECK(SGGetDataOutputStorageSpaceRemaining); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut)) return NULL; _rv = SGGetDataOutputStorageSpaceRemaining(s, @@ -20535,7 +20535,7 @@ PyMac_PRECHECK(SGHandleUpdateEvent); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, PyMac_GetEventRecord, &event)) return NULL; _rv = SGHandleUpdateEvent(s, @@ -20558,7 +20558,7 @@ PyMac_PRECHECK(SGSetOutputNextOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut, SGOutputObj_Convert, &nextOut)) return NULL; @@ -20581,7 +20581,7 @@ PyMac_PRECHECK(SGGetOutputNextOutput); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut)) return NULL; _rv = SGGetOutputNextOutput(s, @@ -20604,7 +20604,7 @@ PyMac_PRECHECK(SGSetOutputMaximumOffset); #endif if (!PyArg_ParseTuple(_args, "O&O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut, PyMac_Getwide, &maxOffset)) return NULL; @@ -20627,7 +20627,7 @@ PyMac_PRECHECK(SGGetOutputMaximumOffset); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut)) return NULL; _rv = SGGetOutputMaximumOffset(s, @@ -20651,7 +20651,7 @@ PyMac_PRECHECK(SGGetOutputDataReference); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut)) return NULL; _rv = SGGetOutputDataReference(s, @@ -20679,7 +20679,7 @@ PyMac_PRECHECK(SGWriteExtendedMovieData); #endif if (!PyArg_ParseTuple(_args, "O&O&sl", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, &p, &len)) @@ -20707,7 +20707,7 @@ PyMac_PRECHECK(SGGetStorageSpaceRemaining64); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetStorageSpaceRemaining64(s, &bytes); @@ -20728,7 +20728,7 @@ PyMac_PRECHECK(SGGetDataOutputStorageSpaceRemaining64); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut)) return NULL; _rv = SGGetDataOutputStorageSpaceRemaining64(s, @@ -20753,7 +20753,7 @@ PyMac_PRECHECK(SGWriteMovieData); #endif if (!PyArg_ParseTuple(_args, "O&O&sl", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, &p, &len)) @@ -20779,7 +20779,7 @@ PyMac_PRECHECK(SGGetTimeBase); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGGetTimeBase(s, &tb); @@ -20805,7 +20805,7 @@ PyMac_PRECHECK(SGAddMovieData); #endif if (!PyArg_ParseTuple(_args, "O&O&slllh", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, &p, &len, @@ -20837,7 +20837,7 @@ PyMac_PRECHECK(SGChangedSource); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c)) return NULL; _rv = SGChangedSource(s, @@ -20864,7 +20864,7 @@ PyMac_PRECHECK(SGAddExtendedMovieData); #endif if (!PyArg_ParseTuple(_args, "O&O&slllh", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, &p, &len, @@ -20900,7 +20900,7 @@ PyMac_PRECHECK(SGAddOutputDataRefToMedia); #endif if (!PyArg_ParseTuple(_args, "O&O&O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, SGOutputObj_Convert, &sgOut, MediaObj_Convert, &theMedia, ResObj_Convert, &desc)) @@ -20924,7 +20924,7 @@ PyMac_PRECHECK(SGSetSettingsSummary); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, ResObj_Convert, &summaryText)) return NULL; _rv = SGSetSettingsSummary(s, @@ -21534,7 +21534,7 @@ #endif if (!PyArg_ParseTuple(_args, "O&O&", CmpInstObj_Convert, &c, - CmpObj_Convert, &owner)) + CmpInstObj_Convert, &owner)) return NULL; _rv = SGInitChannel(c, owner); @@ -21616,7 +21616,7 @@ PyMac_PRECHECK(SGPanelGetDitl); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGPanelGetDitl(s, &ditl); @@ -21636,7 +21636,7 @@ PyMac_PRECHECK(SGPanelGetTitle); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, PyMac_GetStr255, title)) return NULL; _rv = SGPanelGetTitle(s, @@ -21656,7 +21656,7 @@ PyMac_PRECHECK(SGPanelCanRun); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c)) return NULL; _rv = SGPanelCanRun(s, @@ -21678,7 +21678,7 @@ PyMac_PRECHECK(SGPanelInstall); #endif if (!PyArg_ParseTuple(_args, "O&O&O&h", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, DlgObj_Convert, &d, &itemOffset)) @@ -21707,7 +21707,7 @@ PyMac_PRECHECK(SGPanelEvent); #endif if (!PyArg_ParseTuple(_args, "O&O&O&hO&", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, DlgObj_Convert, &d, &itemOffset, @@ -21740,7 +21740,7 @@ PyMac_PRECHECK(SGPanelItem); #endif if (!PyArg_ParseTuple(_args, "O&O&O&hh", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, DlgObj_Convert, &d, &itemOffset, @@ -21768,7 +21768,7 @@ PyMac_PRECHECK(SGPanelRemove); #endif if (!PyArg_ParseTuple(_args, "O&O&O&h", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, DlgObj_Convert, &d, &itemOffset)) @@ -21792,8 +21792,8 @@ PyMac_PRECHECK(SGPanelSetGrabber); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &s, - CmpObj_Convert, &sg)) + CmpInstObj_Convert, &s, + CmpInstObj_Convert, &sg)) return NULL; _rv = SGPanelSetGrabber(s, sg); @@ -21812,7 +21812,7 @@ PyMac_PRECHECK(SGPanelSetResFile); #endif if (!PyArg_ParseTuple(_args, "O&h", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, &resRef)) return NULL; _rv = SGPanelSetResFile(s, @@ -21834,7 +21834,7 @@ PyMac_PRECHECK(SGPanelGetSettings); #endif if (!PyArg_ParseTuple(_args, "O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, &flags)) return NULL; @@ -21860,7 +21860,7 @@ PyMac_PRECHECK(SGPanelSetSettings); #endif if (!PyArg_ParseTuple(_args, "O&O&O&l", - CmpObj_Convert, &s, + CmpInstObj_Convert, &s, CmpInstObj_Convert, &c, UserDataObj_Convert, &ud, &flags)) @@ -21884,7 +21884,7 @@ PyMac_PRECHECK(SGPanelValidateInput); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGPanelValidateInput(s, &ok); @@ -21905,7 +21905,7 @@ PyMac_PRECHECK(SGPanelGetDITLForSize); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &s)) + CmpInstObj_Convert, &s)) return NULL; _rv = SGPanelGetDITLForSize(s, &ditl, @@ -22806,7 +22806,7 @@ PyMac_PRECHECK(QTVideoOutputGetCurrentClientName); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, PyMac_GetStr255, str)) return NULL; _rv = QTVideoOutputGetCurrentClientName(vo, @@ -22826,7 +22826,7 @@ PyMac_PRECHECK(QTVideoOutputSetClientName); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, PyMac_GetStr255, str)) return NULL; _rv = QTVideoOutputSetClientName(vo, @@ -22846,7 +22846,7 @@ PyMac_PRECHECK(QTVideoOutputGetClientName); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, PyMac_GetStr255, str)) return NULL; _rv = QTVideoOutputGetClientName(vo, @@ -22865,7 +22865,7 @@ PyMac_PRECHECK(QTVideoOutputBegin); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &vo)) + CmpInstObj_Convert, &vo)) return NULL; _rv = QTVideoOutputBegin(vo); _res = Py_BuildValue("l", @@ -22882,7 +22882,7 @@ PyMac_PRECHECK(QTVideoOutputEnd); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &vo)) + CmpInstObj_Convert, &vo)) return NULL; _rv = QTVideoOutputEnd(vo); _res = Py_BuildValue("l", @@ -22900,7 +22900,7 @@ PyMac_PRECHECK(QTVideoOutputSetDisplayMode); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, &displayModeID)) return NULL; _rv = QTVideoOutputSetDisplayMode(vo, @@ -22920,7 +22920,7 @@ PyMac_PRECHECK(QTVideoOutputGetDisplayMode); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &vo)) + CmpInstObj_Convert, &vo)) return NULL; _rv = QTVideoOutputGetDisplayMode(vo, &displayModeID); @@ -22940,7 +22940,7 @@ PyMac_PRECHECK(QTVideoOutputGetGWorld); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &vo)) + CmpInstObj_Convert, &vo)) return NULL; _rv = QTVideoOutputGetGWorld(vo, &gw); @@ -22961,7 +22961,7 @@ PyMac_PRECHECK(QTVideoOutputGetIndSoundOutput); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, &index)) return NULL; _rv = QTVideoOutputGetIndSoundOutput(vo, @@ -22983,7 +22983,7 @@ PyMac_PRECHECK(QTVideoOutputGetClock); #endif if (!PyArg_ParseTuple(_args, "O&", - CmpObj_Convert, &vo)) + CmpInstObj_Convert, &vo)) return NULL; _rv = QTVideoOutputGetClock(vo, &clock); @@ -23003,7 +23003,7 @@ PyMac_PRECHECK(QTVideoOutputSetEchoPort); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, GrafObj_Convert, &echoPort)) return NULL; _rv = QTVideoOutputSetEchoPort(vo, @@ -23024,7 +23024,7 @@ PyMac_PRECHECK(QTVideoOutputGetIndImageDecompressor); #endif if (!PyArg_ParseTuple(_args, "O&l", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, &index)) return NULL; _rv = QTVideoOutputGetIndImageDecompressor(vo, @@ -23046,7 +23046,7 @@ PyMac_PRECHECK(QTVideoOutputBaseSetEchoPort); #endif if (!PyArg_ParseTuple(_args, "O&O&", - CmpObj_Convert, &vo, + CmpInstObj_Convert, &vo, GrafObj_Convert, &echoPort)) return NULL; _rv = QTVideoOutputBaseSetEchoPort(vo, Modified: python/branches/release26-maint/Mac/Modules/qt/qtsupport.py ============================================================================== --- python/branches/release26-maint/Mac/Modules/qt/qtsupport.py (original) +++ python/branches/release26-maint/Mac/Modules/qt/qtsupport.py Mon Mar 30 17:24:08 2009 @@ -135,19 +135,22 @@ CompressorComponent = OpaqueByValueType('CompressorComponent', 'CmpObj') DecompressorComponent = OpaqueByValueType('DecompressorComponent', 'CmpObj') CodecComponent = OpaqueByValueType('CodecComponent', 'CmpObj') -GraphicsImportComponent = OpaqueByValueType('GraphicsImportComponent', 'CmpObj') -GraphicsExportComponent = OpaqueByValueType('GraphicsExportComponent', 'CmpObj') -ImageTranscoderComponent = OpaqueByValueType('ImageTranscoderComponent', 'CmpObj') -DataCodecComponent = OpaqueByValueType('DataCodecComponent', 'CmpObj') -GraphicImageMovieImportComponent = OpaqueByValueType('GraphicImageMovieImportComponent', 'CmpObj') -MovieExportComponent = OpaqueByValueType('MovieExportComponent', 'CmpObj') -MovieImportComponent = OpaqueByValueType('MovieImportComponent', 'CmpObj') -QTVideoOutputComponent = OpaqueByValueType('QTVideoOutputComponent', 'CmpObj') -SeqGrabComponent = OpaqueByValueType('SeqGrabComponent', 'CmpObj') -TextExportComponent = OpaqueByValueType('TextExportComponent', 'CmpObj') -TweenerComponent = OpaqueByValueType('TweenerComponent', 'CmpObj') -pnotComponent = OpaqueByValueType('pnotComponent', 'CmpObj') -VideoDigitizerComponent = OpaqueByValueType('VideoDigitizerComponent', 'CmpObj') + +# Despite their names, these are all ComponentInstance types +GraphicsImportComponent = OpaqueByValueType('GraphicsImportComponent', 'CmpInstObj') +GraphicsExportComponent = OpaqueByValueType('GraphicsExportComponent', 'CmpInstObj') +ImageTranscoderComponent = OpaqueByValueType('ImageTranscoderComponent', 'CmpInstObj') +MovieImportComponent = OpaqueByValueType('MovieImportComponent', 'CmpInstObj') +MovieExportComponent = OpaqueByValueType('MovieExportComponent', 'CmpInstObj') +TextExportComponent = OpaqueByValueType('TextExportComponent', 'CmpInstObj') +GraphicImageMovieImportComponent = OpaqueByValueType('GraphicImageMovieImportComponent', 'CmpInstObj') +pnotComponent = OpaqueByValueType('pnotComponent', 'CmpInstObj') +# DataCompressorComponent, DataDecompressorComponent would go here +DataCodecComponent = OpaqueByValueType('DataCodecComponent', 'CmpInstObj') +TweenerComponent = OpaqueByValueType('TweenerComponent', 'CmpInstObj') +QTVideoOutputComponent = OpaqueByValueType('QTVideoOutputComponent', 'CmpInstObj') +SeqGrabComponent = OpaqueByValueType('SeqGrabComponent', 'CmpInstObj') +VideoDigitizerComponent = OpaqueByValueType('VideoDigitizerComponent', 'CmpInstObj') ComponentInstance = OpaqueByValueType('ComponentInstance', 'CmpInstObj') MediaHandler = OpaqueByValueType('MediaHandler', 'CmpInstObj') From python-checkins at python.org Mon Mar 30 17:30:35 2009 From: python-checkins at python.org (r.david.murray) Date: Mon, 30 Mar 2009 17:30:35 +0200 (CEST) Subject: [Python-checkins] r70716 - python/trunk/Lib/test/test_fork1.py Message-ID: <20090330153035.192831E4021@bag.python.org> Author: r.david.murray Date: Mon Mar 30 17:30:34 2009 New Revision: 70716 Log: Revert incorrect change. Modified: python/trunk/Lib/test/test_fork1.py Modified: python/trunk/Lib/test/test_fork1.py ============================================================================== --- python/trunk/Lib/test/test_fork1.py (original) +++ python/trunk/Lib/test/test_fork1.py Mon Mar 30 17:30:34 2009 @@ -3,11 +3,14 @@ import os import time +import unittest from test.fork_wait import ForkWait -from test.test_support import run_unittest, reap_children, import_module - -import_module('os.fork') +from test.test_support import run_unittest, reap_children +try: + os.fork +except AttributeError: + raise unittest.SkipTest, "os.fork not defined -- skipping test_fork1" class ForkTest(ForkWait): def wait_impl(self, cpid): From buildbot at python.org Mon Mar 30 17:37:54 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 15:37:54 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090330153754.3BADA1E4040@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/541 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/3.x.heller-x86-osx5/build/Lib/test/test_robotparser.py", line 217, in testPasswordProtectedSite parser.read() File "/Users/buildbot/buildarea/3.x.heller-x86-osx5/build/Lib/urllib/robotparser.py", line 56, in read f = urllib.request.urlopen(self.url) File "/Users/buildbot/buildarea/3.x.heller-x86-osx5/build/Lib/urllib/request.py", line 122, in urlopen return _opener.open(url, data, timeout) File "/Users/buildbot/buildarea/3.x.heller-x86-osx5/build/Lib/urllib/request.py", line 358, in open response = self._open(req, data) File "/Users/buildbot/buildarea/3.x.heller-x86-osx5/build/Lib/urllib/request.py", line 376, in _open '_open', req) File "/Users/buildbot/buildarea/3.x.heller-x86-osx5/build/Lib/urllib/request.py", line 336, in _call_chain result = func(*args) File "/Users/buildbot/buildarea/3.x.heller-x86-osx5/build/Lib/urllib/request.py", line 1082, in http_open return self.do_open(http.client.HTTPConnection, req) File "/Users/buildbot/buildarea/3.x.heller-x86-osx5/build/Lib/urllib/request.py", line 1070, in do_open raise URLError(err) urllib.error.URLError: 1 test failed: test_robotparser make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 30 17:50:42 2009 From: python-checkins at python.org (jesse.noller) Date: Mon, 30 Mar 2009 17:50:42 +0200 (CEST) Subject: [Python-checkins] r70717 - in python/trunk: Lib/multiprocessing/connection.py Lib/test/test_multiprocessing.py Misc/NEWS Message-ID: <20090330155042.485C71E4037@bag.python.org> Author: jesse.noller Date: Mon Mar 30 17:50:42 2009 New Revision: 70717 Log: Issue 5177: use socket.SO_REUSEADDR on multiprocessing SocketManager sockets Modified: python/trunk/Lib/multiprocessing/connection.py python/trunk/Lib/test/test_multiprocessing.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/multiprocessing/connection.py ============================================================================== --- python/trunk/Lib/multiprocessing/connection.py (original) +++ python/trunk/Lib/multiprocessing/connection.py Mon Mar 30 17:50:42 2009 @@ -214,6 +214,7 @@ ''' def __init__(self, address, family, backlog=1): self._socket = socket.socket(getattr(socket, family)) + self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._socket.bind(address) self._socket.listen(backlog) self._address = self._socket.getsockname() Modified: python/trunk/Lib/test/test_multiprocessing.py ============================================================================== --- python/trunk/Lib/test/test_multiprocessing.py (original) +++ python/trunk/Lib/test/test_multiprocessing.py Mon Mar 30 17:50:42 2009 @@ -1189,6 +1189,30 @@ del queue manager.shutdown() +class _TestManagerRestart(BaseTestCase): + + def _putter(self, address, authkey): + manager = QueueManager( + address=address, authkey=authkey, serializer=SERIALIZER) + manager.connect() + queue = manager.get_queue() + queue.put('hello world') + + def test_rapid_restart(self): + authkey = os.urandom(32) + manager = QueueManager( + address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) + manager.start() + + p = self.Process(target=self._putter, args=(manager.address, authkey)) + p.start() + queue = manager.get_queue() + self.assertEqual(queue.get(), 'hello world') + manager.shutdown() + manager = QueueManager( + address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) + manager.start() + # # # Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Mon Mar 30 17:50:42 2009 @@ -197,6 +197,10 @@ Library ------- +- Issue #5177: Multiprocessing's SocketListener class now uses + socket.SO_REUSEADDR on all connections so that the user no longer needs + to wait 120 seconds for the socket to expire. + - Adjusted _tkinter to compile without warnings when WITH_THREAD is not defined (part of issue #5035). From python-checkins at python.org Mon Mar 30 17:53:01 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 30 Mar 2009 17:53:01 +0200 (CEST) Subject: [Python-checkins] r70718 - python/branches/py3k/Lib/importlib/test/benchmark.py Message-ID: <20090330155301.D0C121E4002@bag.python.org> Author: brett.cannon Date: Mon Mar 30 17:53:01 2009 New Revision: 70718 Log: Add simple tests for __import__ for future optimizations to importlib. Added: python/branches/py3k/Lib/importlib/test/benchmark.py Added: python/branches/py3k/Lib/importlib/test/benchmark.py ============================================================================== --- (empty file) +++ python/branches/py3k/Lib/importlib/test/benchmark.py Mon Mar 30 17:53:01 2009 @@ -0,0 +1,82 @@ +from . import util +from .source import util as source_util +import gc +import decimal +import imp +import importlib +import sys +import timeit + + +def bench_cache(import_, repeat, number): + """Measure the time it takes to pull from sys.modules.""" + name = '' + with util.uncache(name): + module = imp.new_module(name) + sys.modules[name] = module + runs = [] + for x in range(repeat): + start_time = timeit.default_timer() + for y in range(number): + import_(name) + end_time = timeit.default_timer() + runs.append(end_time - start_time) + return min(runs) + + +def bench_importing_source(import_, repeat, number, loc=100000): + """Measure importing source from disk. + + For worst-case scenario, the line endings are \\r\\n and thus require + universal newline translation. + + """ + name = '__benchmark' + with source_util.create_modules(name) as mapping: + with open(mapping[name], 'w') as file: + for x in range(loc): + file.write("{0}\r\n".format(x)) + with util.import_state(path=[mapping['.root']]): + runs = [] + for x in range(repeat): + start_time = timeit.default_timer() + for y in range(number): + try: + import_(name) + finally: + del sys.modules[name] + end_time = timeit.default_timer() + runs.append(end_time - start_time) + return min(runs) + + +def main(import_): + args = [('sys.modules', bench_cache, 5, 500000), + ('source', bench_importing_source, 5, 10000)] + test_msg = "{test}, {number} times (best of {repeat}):" + result_msg = "{result:.2f} secs" + gc.disable() + try: + for name, meth, repeat, number in args: + result = meth(import_, repeat, number) + print(test_msg.format(test=name, repeat=repeat, + number=number).ljust(40), + result_msg.format(result=result).rjust(10)) + finally: + gc.enable() + + +if __name__ == '__main__': + import optparse + + parser = optparse.OptionParser() + parser.add_option('-b', '--builtin', dest='builtin', action='store_true', + default=False, help="use the built-in __import__") + options, args = parser.parse_args() + if args: + raise RuntimeError("unrecognized args: {0}".format(args)) + import_ = __import__ + if not options.builtin: + import_ = importlib.__import__ + + main(import_) From python-checkins at python.org Mon Mar 30 18:01:52 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 18:01:52 +0200 (CEST) Subject: [Python-checkins] r70719 - python/trunk/Doc/library/carbon.rst Message-ID: <20090330160152.0D7861E403B@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 18:01:51 2009 New Revision: 70719 Log: Fix for issue 896199 (some Carbon modules aren't present in the documentation) Modified: python/trunk/Doc/library/carbon.rst Modified: python/trunk/Doc/library/carbon.rst ============================================================================== --- python/trunk/Doc/library/carbon.rst (original) +++ python/trunk/Doc/library/carbon.rst Mon Mar 30 18:01:51 2009 @@ -55,6 +55,14 @@ :synopsis: Interface to the Appearance Manager. :deprecated: +:mod:`Carbon.Appearance` --- Appearance Manager constants +========================================================= + +.. module:: Carbon.Appearance + :platform: Mac + :synopsis: Constant definitions for the interface to the Appearance Manager. + :deprecated: + :mod:`Carbon.CF` --- Core Foundation @@ -88,6 +96,14 @@ :synopsis: Interface to the Carbon Event Manager. :deprecated: +:mod:`Carbon.CarbonEvents` --- Carbon Event Manager constants +============================================================= + +.. module:: Carbon.CarbonEvents + :platform: Mac + :synopsis: Constants for the interface to the Carbon Event Manager. + :deprecated: + :mod:`Carbon.Cm` --- Component Manager @@ -98,7 +114,46 @@ :synopsis: Interface to the Component Manager. :deprecated: +:mod:`Carbon.Components` --- Component Manager constants +======================================================== + +.. module:: Carbon.Components + :platform: Mac + :synopsis: Constants for the interface to the Component Manager. + :deprecated: + +:mod:`Carbon.ControlAccessor` --- Control Manager accssors +=========================================================== + +.. module:: Carbon.ControlAccessor + :platform: Mac + :synopsis: Accessor functions for the interface to the Control Manager. + :deprecated: + +:mod:`Carbon.Controls` --- Control Manager constants +==================================================== + +.. module:: Carbon.Controls + :platform: Mac + :synopsis: Constants for the interface to the Control Manager. + :deprecated: + +:mod:`Carbon.CoreFounation` --- CoreFounation constants +======================================================= + +.. module:: Carbon.CoreFounation + :platform: Mac + :synopsis: Constants for the interface to CoreFoundation. + :deprecated: + +:mod:`Carbon.CoreGraphics` --- CoreGraphics constants +======================================================= + +.. module:: Carbon.CoreGraphics + :platform: Mac + :synopsis: Constants for the interface to CoreGraphics. + :deprecated: :mod:`Carbon.Ctl` --- Control Manager ===================================== @@ -108,7 +163,13 @@ :synopsis: Interface to the Control Manager. :deprecated: +:mod:`Carbon.Dialogs` --- Dialog Manager constants +================================================== +.. module:: Carbon.Dialogs + :platform: Mac + :synopsis: Constants for the interface to the Dialog Manager. + :deprecated: :mod:`Carbon.Dlg` --- Dialog Manager ==================================== @@ -118,7 +179,29 @@ :synopsis: Interface to the Dialog Manager. :deprecated: +:mod:`Carbon.Drag` --- Drag and Drop Manager +============================================= + +.. module:: Carbon.Drag + :platform: Mac + :synopsis: Interface to the Drag and Drop Manager. + :deprecated: +:mod:`Carbon.Dragconst` --- Drag and Drop Manager constants +=========================================================== + +.. module:: Carbon.Dragconst + :platform: Mac + :synopsis: Constants for the interface to the Drag and Drop Manager. + :deprecated: + +:mod:`Carbon.Events` --- Event Manager constants +================================================ + +.. module:: Carbon.Events + :platform: Mac + :synopsis: Constants for the interface to the classic Event Manager. + :deprecated: :mod:`Carbon.Evt` --- Event Manager =================================== @@ -128,6 +211,21 @@ :synopsis: Interface to the classic Event Manager. :deprecated: +:mod:`Carbon.File` --- File Manager +=================================== + +.. module:: Carbon.File + :platform: Mac + :synopsis: Interface to the File Manager. + :deprecated: + +:mod:`Carbon.Files` --- File Manager constants +============================================== + +.. module:: Carbon.Files + :platform: Mac + :synopsis: Constants for the interface to the File Manager. + :deprecated: :mod:`Carbon.Fm` --- Font Manager @@ -148,6 +246,23 @@ :synopsis: Interface to the Folder Manager. :deprecated: +:mod:`Carbon.Folders` --- Folder Manager constants +================================================== + +.. module:: Carbon.Folders + :platform: Mac + :synopsis: Constants for the interface to the Folder Manager. + :deprecated: + + +:mod:`Carbon.Fonts` --- Font Manager constants +================================================== + +.. module:: Carbon.Fonts + :platform: Mac + :synopsis: Constants for the interface to the Font Manager. + :deprecated: + :mod:`Carbon.Help` --- Help Manager @@ -158,6 +273,53 @@ :synopsis: Interface to the Carbon Help Manager. :deprecated: +:mod:`Carbon.IBCarbon` --- Carbon InterfaceBuilder +================================================== + +.. module:: Carbon.IBCarbon + :platform: Mac + :synopsis: Interface to the Carbon InterfaceBuilder support libraries. + :deprecated: + +:mod:`Carbon.IBCarbonRuntime` --- Carbon InterfaceBuilder constants +=================================================================== + +.. module:: Carbon.IBCarbonRuntime + :platform: Mac + :synopsis: Constants for the interface to the Carbon InterfaceBuilder support libraries. + :deprecated: + +:mod:`Carbon.Icn` --- Carbon Icon Manager +========================================= + +.. module:: Carbon.Icns + :platform: Mac + :synopsis: Interface to the Carbon Icon Manager + :deprecated: + +:mod:`Carbon.Icons` --- Carbon Icon Manager constants +===================================================== + +.. module:: Carbon.Icons + :platform: Mac + :synopsis: Constants for the interface to the Carbon Icon Manager + :deprecated: + +:mod:`Carbon.Launch` --- Carbon Launch Services +=============================================== + +.. module:: Carbon.Launch + :platform: Mac + :synopsis: Interface to the Carbon Launch Services. + :deprecated: + +:mod:`Carbon.LaunchServices` --- Carbon Launch Services constants +================================================================= + +.. module:: Carbon.LaunchServices + :platform: Mac + :synopsis: Constants for the interface to the Carbon Launch Services. + :deprecated: :mod:`Carbon.List` --- List Manager @@ -170,6 +332,31 @@ +:mod:`Carbon.Lists` --- List Manager constants +============================================== + +.. module:: Carbon.Lists + :platform: Mac + :synopsis: Constants for the interface to the List Manager. + :deprecated: + +:mod:`Carbon.MacHelp` --- Help Manager constants +================================================ + +.. module:: Carbon.MacHelp + :platform: Mac + :synopsis: Constants for the interface to the Carbon Help Manager. + :deprecated: + +:mod:`Carbon.MediaDescr` --- Parsers and generators for Quicktime Media descriptors +=================================================================================== + +.. module:: Carbon.MediaDescr + :platform: Mac + :synopsis: Parsers and generators for Quicktime Media descriptors + :deprecated: + + :mod:`Carbon.Menu` --- Menu Manager =================================== @@ -178,6 +365,13 @@ :synopsis: Interface to the Menu Manager. :deprecated: +:mod:`Carbon.Menus` --- Menu Manager constants +============================================== + +.. module:: Carbon.Menus + :platform: Mac + :synopsis: Constants for the interface to the Menu Manager. + :deprecated: :mod:`Carbon.Mlte` --- MultiLingual Text Editor @@ -188,6 +382,29 @@ :synopsis: Interface to the MultiLingual Text Editor. :deprecated: +:mod:`Carbon.OSA` --- Carbon OSA Interface +========================================== + +.. module:: Carbon.OSA + :platform: Mac + :synopsis: Interface to the Carbon OSA Library. + :deprecated: + +:mod:`Carbon.OSAconst` --- Carbon OSA Interface constants +========================================================= + +.. module:: Carbon.OSAconst + :platform: Mac + :synopsis: Constants for the interface to the Carbon OSA Library. + :deprecated: + +:mod:`Carbon.QDOffscreen` --- QuickDraw Offscreen constants +=========================================================== + +.. module:: Carbon.QDOffscreen + :platform: Mac + :synopsis: Constants for the interface to the QuickDraw Offscreen APIs. + :deprecated: :mod:`Carbon.Qd` --- QuickDraw @@ -218,6 +435,21 @@ :synopsis: Interface to the QuickTime toolbox. :deprecated: +:mod:`Carbon.QuickDraw` --- QuickDraw constants +=============================================== + +.. module:: Carbon.QuickDraw + :platform: Mac + :synopsis: Constants for the interface to the QuickDraw toolbox. + :deprecated: + +:mod:`Carbon.QuickTime` --- QuickTime constants +=============================================== + +.. module:: Carbon.QuickTime + :platform: Mac + :synopsis: Constants for the interface to the QuickTime toolbox. + :deprecated: :mod:`Carbon.Res` --- Resource Manager and Handles @@ -228,6 +460,13 @@ :synopsis: Interface to the Resource Manager and Handles. :deprecated: +:mod:`Carbon.Resources` --- Resource Manager and Handles constants +================================================================== + +.. module:: Carbon.Resources + :platform: Mac + :synopsis: Constants for the interface to the Resource Manager and Handles. + :deprecated: :mod:`Carbon.Scrap` --- Scrap Manager @@ -290,6 +529,13 @@ :synopsis: Interface to the Sound Manager. :deprecated: +:mod:`Carbon.Sound` --- Sound Manager constants +=============================================== + +.. module:: Carbon.Sound + :platform: Mac + :synopsis: Constants for the interface to the Sound Manager. + :deprecated: :mod:`Carbon.TE` --- TextEdit @@ -300,6 +546,14 @@ :synopsis: Interface to TextEdit. :deprecated: +:mod:`Carbon.TextEdit` --- TextEdit constants +============================================= + +.. module:: Carbon.TextEdit + :platform: Mac + :synopsis: Constants for the interface to TextEdit. + :deprecated: + :mod:`Carbon.Win` --- Window Manager @@ -309,3 +563,11 @@ :platform: Mac :synopsis: Interface to the Window Manager. :deprecated: + +:mod:`Carbon.Windows` --- Window Manager constants +================================================== + +.. module:: Carbon.Windows + :platform: Mac + :synopsis: Constants for the interface to the Window Manager. + :deprecated: From python-checkins at python.org Mon Mar 30 18:03:42 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 18:03:42 +0200 (CEST) Subject: [Python-checkins] r70720 - in python/branches/release26-maint: Doc/library/carbon.rst Message-ID: <20090330160342.0E9881E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 18:03:41 2009 New Revision: 70720 Log: Merged revisions 70719 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70719 | ronald.oussoren | 2009-03-30 11:01:51 -0500 (Mon, 30 Mar 2009) | 2 lines Fix for issue 896199 (some Carbon modules aren't present in the documentation) ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/library/carbon.rst Modified: python/branches/release26-maint/Doc/library/carbon.rst ============================================================================== --- python/branches/release26-maint/Doc/library/carbon.rst (original) +++ python/branches/release26-maint/Doc/library/carbon.rst Mon Mar 30 18:03:41 2009 @@ -55,6 +55,14 @@ :synopsis: Interface to the Appearance Manager. :deprecated: +:mod:`Carbon.Appearance` --- Appearance Manager constants +========================================================= + +.. module:: Carbon.Appearance + :platform: Mac + :synopsis: Constant definitions for the interface to the Appearance Manager. + :deprecated: + :mod:`Carbon.CF` --- Core Foundation @@ -88,6 +96,14 @@ :synopsis: Interface to the Carbon Event Manager. :deprecated: +:mod:`Carbon.CarbonEvents` --- Carbon Event Manager constants +============================================================= + +.. module:: Carbon.CarbonEvents + :platform: Mac + :synopsis: Constants for the interface to the Carbon Event Manager. + :deprecated: + :mod:`Carbon.Cm` --- Component Manager @@ -98,7 +114,46 @@ :synopsis: Interface to the Component Manager. :deprecated: +:mod:`Carbon.Components` --- Component Manager constants +======================================================== + +.. module:: Carbon.Components + :platform: Mac + :synopsis: Constants for the interface to the Component Manager. + :deprecated: + +:mod:`Carbon.ControlAccessor` --- Control Manager accssors +=========================================================== + +.. module:: Carbon.ControlAccessor + :platform: Mac + :synopsis: Accessor functions for the interface to the Control Manager. + :deprecated: + +:mod:`Carbon.Controls` --- Control Manager constants +==================================================== + +.. module:: Carbon.Controls + :platform: Mac + :synopsis: Constants for the interface to the Control Manager. + :deprecated: + +:mod:`Carbon.CoreFounation` --- CoreFounation constants +======================================================= + +.. module:: Carbon.CoreFounation + :platform: Mac + :synopsis: Constants for the interface to CoreFoundation. + :deprecated: + +:mod:`Carbon.CoreGraphics` --- CoreGraphics constants +======================================================= + +.. module:: Carbon.CoreGraphics + :platform: Mac + :synopsis: Constants for the interface to CoreGraphics. + :deprecated: :mod:`Carbon.Ctl` --- Control Manager ===================================== @@ -108,7 +163,13 @@ :synopsis: Interface to the Control Manager. :deprecated: +:mod:`Carbon.Dialogs` --- Dialog Manager constants +================================================== +.. module:: Carbon.Dialogs + :platform: Mac + :synopsis: Constants for the interface to the Dialog Manager. + :deprecated: :mod:`Carbon.Dlg` --- Dialog Manager ==================================== @@ -118,7 +179,29 @@ :synopsis: Interface to the Dialog Manager. :deprecated: +:mod:`Carbon.Drag` --- Drag and Drop Manager +============================================= + +.. module:: Carbon.Drag + :platform: Mac + :synopsis: Interface to the Drag and Drop Manager. + :deprecated: +:mod:`Carbon.Dragconst` --- Drag and Drop Manager constants +=========================================================== + +.. module:: Carbon.Dragconst + :platform: Mac + :synopsis: Constants for the interface to the Drag and Drop Manager. + :deprecated: + +:mod:`Carbon.Events` --- Event Manager constants +================================================ + +.. module:: Carbon.Events + :platform: Mac + :synopsis: Constants for the interface to the classic Event Manager. + :deprecated: :mod:`Carbon.Evt` --- Event Manager =================================== @@ -128,6 +211,21 @@ :synopsis: Interface to the classic Event Manager. :deprecated: +:mod:`Carbon.File` --- File Manager +=================================== + +.. module:: Carbon.File + :platform: Mac + :synopsis: Interface to the File Manager. + :deprecated: + +:mod:`Carbon.Files` --- File Manager constants +============================================== + +.. module:: Carbon.Files + :platform: Mac + :synopsis: Constants for the interface to the File Manager. + :deprecated: :mod:`Carbon.Fm` --- Font Manager @@ -148,6 +246,23 @@ :synopsis: Interface to the Folder Manager. :deprecated: +:mod:`Carbon.Folders` --- Folder Manager constants +================================================== + +.. module:: Carbon.Folders + :platform: Mac + :synopsis: Constants for the interface to the Folder Manager. + :deprecated: + + +:mod:`Carbon.Fonts` --- Font Manager constants +================================================== + +.. module:: Carbon.Fonts + :platform: Mac + :synopsis: Constants for the interface to the Font Manager. + :deprecated: + :mod:`Carbon.Help` --- Help Manager @@ -158,6 +273,53 @@ :synopsis: Interface to the Carbon Help Manager. :deprecated: +:mod:`Carbon.IBCarbon` --- Carbon InterfaceBuilder +================================================== + +.. module:: Carbon.IBCarbon + :platform: Mac + :synopsis: Interface to the Carbon InterfaceBuilder support libraries. + :deprecated: + +:mod:`Carbon.IBCarbonRuntime` --- Carbon InterfaceBuilder constants +=================================================================== + +.. module:: Carbon.IBCarbonRuntime + :platform: Mac + :synopsis: Constants for the interface to the Carbon InterfaceBuilder support libraries. + :deprecated: + +:mod:`Carbon.Icn` --- Carbon Icon Manager +========================================= + +.. module:: Carbon.Icns + :platform: Mac + :synopsis: Interface to the Carbon Icon Manager + :deprecated: + +:mod:`Carbon.Icons` --- Carbon Icon Manager constants +===================================================== + +.. module:: Carbon.Icons + :platform: Mac + :synopsis: Constants for the interface to the Carbon Icon Manager + :deprecated: + +:mod:`Carbon.Launch` --- Carbon Launch Services +=============================================== + +.. module:: Carbon.Launch + :platform: Mac + :synopsis: Interface to the Carbon Launch Services. + :deprecated: + +:mod:`Carbon.LaunchServices` --- Carbon Launch Services constants +================================================================= + +.. module:: Carbon.LaunchServices + :platform: Mac + :synopsis: Constants for the interface to the Carbon Launch Services. + :deprecated: :mod:`Carbon.List` --- List Manager @@ -170,6 +332,31 @@ +:mod:`Carbon.Lists` --- List Manager constants +============================================== + +.. module:: Carbon.Lists + :platform: Mac + :synopsis: Constants for the interface to the List Manager. + :deprecated: + +:mod:`Carbon.MacHelp` --- Help Manager constants +================================================ + +.. module:: Carbon.MacHelp + :platform: Mac + :synopsis: Constants for the interface to the Carbon Help Manager. + :deprecated: + +:mod:`Carbon.MediaDescr` --- Parsers and generators for Quicktime Media descriptors +=================================================================================== + +.. module:: Carbon.MediaDescr + :platform: Mac + :synopsis: Parsers and generators for Quicktime Media descriptors + :deprecated: + + :mod:`Carbon.Menu` --- Menu Manager =================================== @@ -178,6 +365,13 @@ :synopsis: Interface to the Menu Manager. :deprecated: +:mod:`Carbon.Menus` --- Menu Manager constants +============================================== + +.. module:: Carbon.Menus + :platform: Mac + :synopsis: Constants for the interface to the Menu Manager. + :deprecated: :mod:`Carbon.Mlte` --- MultiLingual Text Editor @@ -188,6 +382,29 @@ :synopsis: Interface to the MultiLingual Text Editor. :deprecated: +:mod:`Carbon.OSA` --- Carbon OSA Interface +========================================== + +.. module:: Carbon.OSA + :platform: Mac + :synopsis: Interface to the Carbon OSA Library. + :deprecated: + +:mod:`Carbon.OSAconst` --- Carbon OSA Interface constants +========================================================= + +.. module:: Carbon.OSAconst + :platform: Mac + :synopsis: Constants for the interface to the Carbon OSA Library. + :deprecated: + +:mod:`Carbon.QDOffscreen` --- QuickDraw Offscreen constants +=========================================================== + +.. module:: Carbon.QDOffscreen + :platform: Mac + :synopsis: Constants for the interface to the QuickDraw Offscreen APIs. + :deprecated: :mod:`Carbon.Qd` --- QuickDraw @@ -218,6 +435,21 @@ :synopsis: Interface to the QuickTime toolbox. :deprecated: +:mod:`Carbon.QuickDraw` --- QuickDraw constants +=============================================== + +.. module:: Carbon.QuickDraw + :platform: Mac + :synopsis: Constants for the interface to the QuickDraw toolbox. + :deprecated: + +:mod:`Carbon.QuickTime` --- QuickTime constants +=============================================== + +.. module:: Carbon.QuickTime + :platform: Mac + :synopsis: Constants for the interface to the QuickTime toolbox. + :deprecated: :mod:`Carbon.Res` --- Resource Manager and Handles @@ -228,6 +460,13 @@ :synopsis: Interface to the Resource Manager and Handles. :deprecated: +:mod:`Carbon.Resources` --- Resource Manager and Handles constants +================================================================== + +.. module:: Carbon.Resources + :platform: Mac + :synopsis: Constants for the interface to the Resource Manager and Handles. + :deprecated: :mod:`Carbon.Scrap` --- Scrap Manager @@ -290,6 +529,13 @@ :synopsis: Interface to the Sound Manager. :deprecated: +:mod:`Carbon.Sound` --- Sound Manager constants +=============================================== + +.. module:: Carbon.Sound + :platform: Mac + :synopsis: Constants for the interface to the Sound Manager. + :deprecated: :mod:`Carbon.TE` --- TextEdit @@ -300,6 +546,14 @@ :synopsis: Interface to TextEdit. :deprecated: +:mod:`Carbon.TextEdit` --- TextEdit constants +============================================= + +.. module:: Carbon.TextEdit + :platform: Mac + :synopsis: Constants for the interface to TextEdit. + :deprecated: + :mod:`Carbon.Win` --- Window Manager @@ -309,3 +563,11 @@ :platform: Mac :synopsis: Interface to the Window Manager. :deprecated: + +:mod:`Carbon.Windows` --- Window Manager constants +================================================== + +.. module:: Carbon.Windows + :platform: Mac + :synopsis: Constants for the interface to the Window Manager. + :deprecated: From python-checkins at python.org Mon Mar 30 18:11:17 2009 From: python-checkins at python.org (jesse.noller) Date: Mon, 30 Mar 2009 18:11:17 +0200 (CEST) Subject: [Python-checkins] r70721 - in python/branches/release26-maint: Lib/test/test_multiprocessing.py Misc/NEWS Modules/_multiprocessing/connection.h Modules/_multiprocessing/socket_connection.c Message-ID: <20090330161117.1278D1E4011@bag.python.org> Author: jesse.noller Date: Mon Mar 30 18:11:16 2009 New Revision: 70721 Log: Merge 68768 to maint Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_multiprocessing.py python/branches/release26-maint/Misc/NEWS python/branches/release26-maint/Modules/_multiprocessing/connection.h python/branches/release26-maint/Modules/_multiprocessing/socket_connection.c Modified: python/branches/release26-maint/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_multiprocessing.py (original) +++ python/branches/release26-maint/Lib/test/test_multiprocessing.py Mon Mar 30 18:11:16 2009 @@ -61,6 +61,8 @@ HAVE_GETVALUE = not getattr(_multiprocessing, 'HAVE_BROKEN_SEM_GETVALUE', False) +WIN32 = (sys.platform == "win32") + # # Creates a wrapper for a function which records the time it takes to finish # @@ -1682,6 +1684,18 @@ logger.setLevel(level=LOG_LEVEL) # +# Test to verify handle verification, see issue 3321 +# + +class TestInvalidHandle(unittest.TestCase): + + def test_invalid_handles(self): + if WIN32: + return + conn = _multiprocessing.Connection(44977608) + self.assertRaises(IOError, conn.poll) + self.assertRaises(IOError, _multiprocessing.Connection, -1) +# # Functions used to create test cases from the base ones in this module # @@ -1785,7 +1799,7 @@ multiprocessing.connection.answer_challenge, _FakeConnection(), b'abc') -testcases_other = [OtherTest] +testcases_other = [OtherTest, TestInvalidHandle] # # Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Mon Mar 30 18:11:16 2009 @@ -150,6 +150,13 @@ - Issue #5203: Fixed ctypes segfaults when passing a unicode string to a function without argtypes (only occurs if HAVE_USABLE_WCHAR_T is false). +- Issue #3321: _multiprocessing.Connection() doesn't check handle; added checks + for *nix machines for negative handles and large int handles. Without this check + it is possible to segfault the interpreter. + +- Issue #4449: AssertionError in mp_benchmarks.py, caused by an underlying issue + in sharedctypes.py. + - Issue #3386: distutils.sysconfig.get_python_lib prefix argument was ignored under NT and OS2. Patch by Philip Jenvey. Modified: python/branches/release26-maint/Modules/_multiprocessing/connection.h ============================================================================== --- python/branches/release26-maint/Modules/_multiprocessing/connection.h (original) +++ python/branches/release26-maint/Modules/_multiprocessing/connection.h Mon Mar 30 18:11:16 2009 @@ -354,7 +354,7 @@ } Py_BEGIN_ALLOW_THREADS - res = conn_poll(self, timeout); + res = conn_poll(self, timeout, _save); Py_END_ALLOW_THREADS switch (res) { Modified: python/branches/release26-maint/Modules/_multiprocessing/socket_connection.c ============================================================================== --- python/branches/release26-maint/Modules/_multiprocessing/socket_connection.c (original) +++ python/branches/release26-maint/Modules/_multiprocessing/socket_connection.c Mon Mar 30 18:11:16 2009 @@ -153,11 +153,23 @@ */ static int -conn_poll(ConnectionObject *conn, double timeout) +conn_poll(ConnectionObject *conn, double timeout, PyThreadState *_save) { int res; fd_set rfds; + /* + * Verify the handle, issue 3321. Not required for windows. + */ + #ifndef MS_WINDOWS + if (((int)conn->handle) < 0 || ((int)conn->handle) >= FD_SETSIZE) { + Py_BLOCK_THREADS + PyErr_SetString(PyExc_IOError, "handle out of range in select()"); + Py_UNBLOCK_THREADS + return MP_EXCEPTION_HAS_BEEN_SET; + } + #endif + FD_ZERO(&rfds); FD_SET((SOCKET)conn->handle, &rfds); From python-checkins at python.org Mon Mar 30 18:19:12 2009 From: python-checkins at python.org (jesse.noller) Date: Mon, 30 Mar 2009 18:19:12 +0200 (CEST) Subject: [Python-checkins] r70722 - in python/branches/release26-maint: Lib/multiprocessing/connection.py Lib/test/test_multiprocessing.py Misc/NEWS Message-ID: <20090330161912.561251E4002@bag.python.org> Author: jesse.noller Date: Mon Mar 30 18:19:10 2009 New Revision: 70722 Log: Merge 70717 to 26maint Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/multiprocessing/connection.py python/branches/release26-maint/Lib/test/test_multiprocessing.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/multiprocessing/connection.py ============================================================================== --- python/branches/release26-maint/Lib/multiprocessing/connection.py (original) +++ python/branches/release26-maint/Lib/multiprocessing/connection.py Mon Mar 30 18:19:10 2009 @@ -214,6 +214,7 @@ ''' def __init__(self, address, family, backlog=1): self._socket = socket.socket(getattr(socket, family)) + self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._socket.bind(address) self._socket.listen(backlog) self._address = self._socket.getsockname() Modified: python/branches/release26-maint/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_multiprocessing.py (original) +++ python/branches/release26-maint/Lib/test/test_multiprocessing.py Mon Mar 30 18:19:10 2009 @@ -1188,6 +1188,30 @@ del queue manager.shutdown() +class _TestManagerRestart(BaseTestCase): + + def _putter(self, address, authkey): + manager = QueueManager( + address=address, authkey=authkey, serializer=SERIALIZER) + manager.connect() + queue = manager.get_queue() + queue.put('hello world') + + def test_rapid_restart(self): + authkey = os.urandom(32) + manager = QueueManager( + address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) + manager.start() + + p = self.Process(target=self._putter, args=(manager.address, authkey)) + p.start() + queue = manager.get_queue() + self.assertEqual(queue.get(), 'hello world') + manager.shutdown() + manager = QueueManager( + address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) + manager.start() + # # # Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Mon Mar 30 18:19:10 2009 @@ -92,6 +92,13 @@ Library ------- +- Issue #5177: Multiprocessing's SocketListener class now uses + socket.SO_REUSEADDR on all connections so that the user no longer needs + to wait 120 seconds for the socket to expire. + +- Adjusted _tkinter to compile without warnings when WITH_THREAD is not + defined (part of issue #5035). + - Issue #5561: Removed the sys.version_info shortcuts from platform's python_version() and python_version_tuple() since they produced different output compared to previous Python versions. From python-checkins at python.org Mon Mar 30 18:22:00 2009 From: python-checkins at python.org (kurt.kaiser) Date: Mon, 30 Mar 2009 18:22:00 +0200 (CEST) Subject: [Python-checkins] r70723 - in python/trunk/Lib/idlelib: EditorWindow.py NEWS.txt Message-ID: <20090330162200.AED211E4002@bag.python.org> Author: kurt.kaiser Date: Mon Mar 30 18:22:00 2009 New Revision: 70723 Log: Tk 8.5 Text widget requires 'wordprocessor' tabstyle attr to handle mixed space/tab properly. Issue 5120, patch by Guilherme Polo. Modified: python/trunk/Lib/idlelib/EditorWindow.py python/trunk/Lib/idlelib/NEWS.txt Modified: python/trunk/Lib/idlelib/EditorWindow.py ============================================================================== --- python/trunk/Lib/idlelib/EditorWindow.py (original) +++ python/trunk/Lib/idlelib/EditorWindow.py Mon Mar 30 18:22:00 2009 @@ -105,10 +105,18 @@ self.text_frame = text_frame = Frame(top) self.vbar = vbar = Scrollbar(text_frame, name='vbar') self.width = idleConf.GetOption('main','EditorWindow','width') - self.text = text = MultiCallCreator(Text)( - text_frame, name='text', padx=5, wrap='none', - width=self.width, - height=idleConf.GetOption('main','EditorWindow','height') ) + text_options = { + 'name': 'text', + 'padx': 5, + 'wrap': 'none', + 'width': self.width, + 'height': idleConf.GetOption('main', 'EditorWindow', 'height')} + if TkVersion >= 8.5: + # Starting with tk 8.5 we have to set the new tabstyle option + # to 'wordprocessor' to achieve the same display of tabs as in + # older tk versions. + text_options['tabstyle'] = 'wordprocessor' + self.text = text = MultiCallCreator(Text)(text_frame, **text_options) self.top.focused_widget = self.text self.createmenubar() Modified: python/trunk/Lib/idlelib/NEWS.txt ============================================================================== --- python/trunk/Lib/idlelib/NEWS.txt (original) +++ python/trunk/Lib/idlelib/NEWS.txt Mon Mar 30 18:22:00 2009 @@ -3,6 +3,9 @@ *Release date: XX-XXX-2009* +- Tk 8.5 Text widget requires 'wordprocessor' tabstyle attr to handle + mixed space/tab properly. Issue 5120, patch by Guilherme Polo. + - Issue #3549: On MacOS the preferences menu was not present From python-checkins at python.org Mon Mar 30 18:37:36 2009 From: python-checkins at python.org (jesse.noller) Date: Mon, 30 Mar 2009 18:37:36 +0200 (CEST) Subject: [Python-checkins] r70724 - in python/branches/py3k: Lib/multiprocessing/connection.py Lib/test/test_multiprocessing.py Misc/NEWS Message-ID: <20090330163736.580F91E4002@bag.python.org> Author: jesse.noller Date: Mon Mar 30 18:37:36 2009 New Revision: 70724 Log: Merge 70717 to 30maint Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/multiprocessing/connection.py python/branches/py3k/Lib/test/test_multiprocessing.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/multiprocessing/connection.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/connection.py (original) +++ python/branches/py3k/Lib/multiprocessing/connection.py Mon Mar 30 18:37:36 2009 @@ -214,6 +214,7 @@ ''' def __init__(self, address, family, backlog=1): self._socket = socket.socket(getattr(socket, family)) + self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._socket.bind(address) self._socket.listen(backlog) self._address = self._socket.getsockname() Modified: python/branches/py3k/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/py3k/Lib/test/test_multiprocessing.py (original) +++ python/branches/py3k/Lib/test/test_multiprocessing.py Mon Mar 30 18:37:36 2009 @@ -1190,6 +1190,30 @@ del queue manager.shutdown() +class _TestManagerRestart(BaseTestCase): + + def _putter(self, address, authkey): + manager = QueueManager( + address=address, authkey=authkey, serializer=SERIALIZER) + manager.connect() + queue = manager.get_queue() + queue.put('hello world') + + def test_rapid_restart(self): + authkey = os.urandom(32) + manager = QueueManager( + address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) + manager.start() + + p = self.Process(target=self._putter, args=(manager.address, authkey)) + p.start() + queue = manager.get_queue() + self.assertEqual(queue.get(), 'hello world') + manager.shutdown() + manager = QueueManager( + address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) + manager.start() + # # # Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Mon Mar 30 18:37:36 2009 @@ -255,6 +255,36 @@ Library ------- +- Issue #5177: Multiprocessing's SocketListener class now uses + socket.SO_REUSEADDR on all connections so that the user no longer needs + to wait 120 seconds for the socket to expire. + +- Adjusted _tkinter to compile without warnings when WITH_THREAD is not + defined (part of issue #5035). + +- Issue #5561: Removed the sys.version_info shortcuts from platform's + python_version() and python_version_tuple() since they produced different + output compared to previous Python versions. + +- Issue #1034053: unittest now supports skipping tests and expected failures. + +- Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop + forever on incomplete input. That caused tarfile.open() to hang when used + with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or + partial bzip2 compressed data. + +- Issue #5536: urllib.urlretrieve makes sure to close the file it's writing to + even if an exception occurs. + +- Issue #5381: Added object_pairs_hook to the json module. This allows + OrderedDicts to be built by the decoder. + +- Issue #2110: Add support for thousands separator and 'n' type + specifier to Decimal.__format__ + +- Fix Decimal.__format__ bug that swapped the meanings of the '<' and + '>' alignment characters. + - Issue #1222: locale.format() bug when the thousands separator is a space character. From ianb at colorstudy.com Mon Mar 30 18:42:16 2009 From: ianb at colorstudy.com (Ian Bicking) Date: Mon, 30 Mar 2009 11:42:16 -0500 Subject: [Python-checkins] [Catalog-sig] r70699 - peps/trunk/pep-0381.txt In-Reply-To: <94bdd2610903292125y38856111m43ddca582ee43c7b@mail.gmail.com> References: <20090329213727.6EEA81E4002@bag.python.org> <49D00050.8020300@v.loewis.de> <94bdd2610903292125y38856111m43ddca582ee43c7b@mail.gmail.com> Message-ID: 2009/3/29 Tarek Ziad? : > RIght I am fixing this right now. > > There's something we didn't talk about yet : since there will be other > package indexes > out there (not PyPI mirrors) that might have their own mirrors, we do > need to provide > somewhere the hostname that holds the mirrors IP for the client software to work > the same way in all case. > > That is, mirrors.pypi.python.org for PyPI, but maybe > mirrors.packages.plone.org for > another index. > > I'd go for a /mirror-hostname unique page at PyPI (and its mirrors) > even if this page is unreachable when PyPI is down. > > This enforces that the other indexes also use the DNS technique, but I > think it's fine Another approach is some way of detecting the mirror index (e.g., a on the index front page), and strongly suggest that clients cache that mirror index location. The most reliable way for a tool like pip to use the mirror, I think, would be to try the main index always to get metadata, then it could use a mirror for fetching the actual packages. There's less synchronization issues in that case, and only when an index is down would pip need to fall back entirely on the mirror. Anyway, this would fit the mirror index detection pattern. -- Ian Bicking | http://blog.ianbicking.org From python-checkins at python.org Mon Mar 30 18:47:15 2009 From: python-checkins at python.org (jesse.noller) Date: Mon, 30 Mar 2009 18:47:15 +0200 (CEST) Subject: [Python-checkins] r70725 - python/branches/py3k/Misc/NEWS Message-ID: <20090330164715.AD7691E4002@bag.python.org> Author: jesse.noller Date: Mon Mar 30 18:47:15 2009 New Revision: 70725 Log: fix bad NEWS merge Modified: python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Mon Mar 30 18:47:15 2009 @@ -43,6 +43,10 @@ Library ------- +- Issue #5177: Multiprocessing's SocketListener class now uses + socket.SO_REUSEADDR on all connections so that the user no longer needs + to wait 120 seconds for the socket to expire. + - Issue #5595: Fix UnboundedLocalError in ntpath.ismount(). - Issue #1174606: Calling read() without arguments of an unbounded file @@ -255,36 +259,6 @@ Library ------- -- Issue #5177: Multiprocessing's SocketListener class now uses - socket.SO_REUSEADDR on all connections so that the user no longer needs - to wait 120 seconds for the socket to expire. - -- Adjusted _tkinter to compile without warnings when WITH_THREAD is not - defined (part of issue #5035). - -- Issue #5561: Removed the sys.version_info shortcuts from platform's - python_version() and python_version_tuple() since they produced different - output compared to previous Python versions. - -- Issue #1034053: unittest now supports skipping tests and expected failures. - -- Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop - forever on incomplete input. That caused tarfile.open() to hang when used - with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or - partial bzip2 compressed data. - -- Issue #5536: urllib.urlretrieve makes sure to close the file it's writing to - even if an exception occurs. - -- Issue #5381: Added object_pairs_hook to the json module. This allows - OrderedDicts to be built by the decoder. - -- Issue #2110: Add support for thousands separator and 'n' type - specifier to Decimal.__format__ - -- Fix Decimal.__format__ bug that swapped the meanings of the '<' and - '>' alignment characters. - - Issue #1222: locale.format() bug when the thousands separator is a space character. From python-checkins at python.org Mon Mar 30 18:49:41 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 30 Mar 2009 18:49:41 +0200 (CEST) Subject: [Python-checkins] r70726 - peps/trunk/pep-0302.txt Message-ID: <20090330164941.F36B31E4037@bag.python.org> Author: brett.cannon Date: Mon Mar 30 18:49:41 2009 New Revision: 70726 Log: Move over to using the term 'finder' as used in importlib. Modified: peps/trunk/pep-0302.txt Modified: peps/trunk/pep-0302.txt ============================================================================== --- peps/trunk/pep-0302.txt (original) +++ peps/trunk/pep-0302.txt Mon Mar 30 18:49:41 2009 @@ -206,13 +206,13 @@ imports. By the time an importer gets a request for "spam.ham", module "spam" has already been imported. - The protocol involves two objects: an importer and a loader. An - importer object has a single method: + The protocol involves two objects: a finder and a loader. A + finder object has a single method: - importer.find_module(fullname, path=None) + finder.find_module(fullname, path=None) This method will be called with the fully qualified name of the - module. If the importer is installed on sys.meta_path, it will + module. If the finder is installed on sys.meta_path, it will receive a second argument, which is None for a top-level module, or package.__path__ for submodules or subpackages[7]. It should return a loader object if the module was found, or None if it wasn't. If @@ -228,17 +228,17 @@ propagated. If load_module() is asked to load 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. + In many cases the finder and loader can be one and the same + object: finder.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 - importer.find_module("spam.eggs.ham") is called, "spam.eggs" has + finder.find_module("spam.eggs.ham") is called, "spam.eggs" has already been imported and added to sys.modules. However, the find_module() method isn't necessarily always called during an actual import: meta tools that analyze import dependencies (such as freeze, Installer or py2exe) don't actually load modules, so an - importer shouldn't *depend* on the parent package being available in + finder shouldn't *depend* on the parent package being available in sys.modules. The load_module() method has a few responsibilities that it must @@ -301,7 +301,7 @@ Meta hooks are called at the start of import processing, before any other import processing (so that meta hooks can override sys.path processing, or frozen modules, or even built-in modules). To - register a meta hook, simply add the importer object to + register a meta hook, simply add the finder object to sys.meta_path (the list of registered meta hooks). Path hooks are called as part of sys.path (or package.__path__) @@ -498,7 +498,7 @@ optional) it is not clear that the __loader__ attribute will be helpful, in practice. - On the other hand, importer objects are mostly permanent, as they + On the other hand, finder objects are mostly permanent, as they live or are kept alive on sys.meta_path, sys.path_importer_cache, so for a loader to keep a reference to the importer costs us nothing extra. Whether loaders will ever need to carry so much independent @@ -575,7 +575,7 @@ [6] imp.set_frozenmodules() patch http://www.python.org/sf/642578 - [7] The path argument to importer.find_module() is there because the + [7] The path argument to finder.find_module() is there because the pkg.__path__ variable may be needed at this point. It may either come from the actual parent module or be supplied by imp.find_module() or the proposed imp.get_loader() function. From python-checkins at python.org Mon Mar 30 19:15:29 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 19:15:29 +0200 (CEST) Subject: [Python-checkins] r70727 - in python/trunk/Mac/BuildScript: build-installer.py seticon.m Message-ID: <20090330171529.780CA1E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 19:15:29 2009 New Revision: 70727 Log: * Updates installed dependencies to latest releaases (bzip, zlib, ...) * Changes code for updating folder icons from Python code that uses the deprecated Carbon module to a much simpler Cocoa program in Objective-C Added: python/trunk/Mac/BuildScript/seticon.m Modified: python/trunk/Mac/BuildScript/build-installer.py Modified: python/trunk/Mac/BuildScript/build-installer.py ============================================================================== --- python/trunk/Mac/BuildScript/build-installer.py (original) +++ python/trunk/Mac/BuildScript/build-installer.py Mon Mar 30 19:15:29 2009 @@ -1,4 +1,4 @@ -#!/usr/bin/python2.3 +#!/usr/bin/python """ This script is used to build the "official unofficial" universal build on Mac OS X. It requires Mac OS X 10.4, Xcode 2.2 and the 10.4u SDK to do its @@ -18,11 +18,6 @@ from plistlib import Plist import MacOS -import Carbon.File -import Carbon.Icn -import Carbon.Res -from Carbon.Files import kCustomIconResource, fsRdWrPerm, kHasCustomIcon -from Carbon.Files import kFSCatInfoFinderInfo try: from plistlib import writePlist @@ -94,8 +89,9 @@ # batteries included python. LIBRARY_RECIPES = [ dict( - name="Bzip2 1.0.3", - url="http://www.bzip.org/1.0.3/bzip2-1.0.3.tar.gz", + name="Bzip2 1.0.4", + url="http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz", + checksum='fc310b254f6ba5fbb5da018f04533688', configure=None, install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( shellQuote(os.path.join(WORKDIR, 'libraries')), @@ -106,6 +102,7 @@ dict( name="ZLib 1.2.3", url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz", + checksum='debc62758716a169df9f62e6ab2bc634', configure=None, install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( shellQuote(os.path.join(WORKDIR, 'libraries')), @@ -117,6 +114,7 @@ # Note that GNU readline is GPL'd software name="GNU Readline 5.1.4", url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" , + checksum='7ee5a692db88b30ca48927a13fd60e46', patchlevel='0', patches=[ # The readline maintainers don't do actual micro releases, but @@ -129,9 +127,9 @@ ), dict( - name="SQLite 3.6.3", - url="http://www.sqlite.org/sqlite-3.6.3.tar.gz", - checksum='93f742986e8bc2dfa34792e16df017a6feccf3a2', + name="SQLite 3.6.11", + url="http://www.sqlite.org/sqlite-3.6.11.tar.gz", + checksum='7ebb099696ab76cc6ff65dd496d17858', configure_pre=[ '--enable-threadsafe', '--enable-tempstore', @@ -144,6 +142,7 @@ dict( name="NCurses 5.5", url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz", + checksum='e73c1ac10b4bfc46db43b2ddfd6244ef', configure_pre=[ "--without-cxx", "--without-ada", @@ -172,8 +171,7 @@ dict( name="Sleepycat DB 4.7.25", url="http://download.oracle.com/berkeley-db/db-4.7.25.tar.gz", - #name="Sleepycat DB 4.3.29", - #url="http://downloads.sleepycat.com/db-4.3.29.tar.gz", + checksum='ec2b87e833779681a0c3a814aa71359e', buildDir="build_unix", configure="../dist/configure", configure_pre=[ @@ -578,31 +576,21 @@ def buildPythonDocs(): - # This stores the documentation as Resources/English.lproj/Docuentation + # This stores the documentation as Resources/English.lproj/Documentation # inside the framwork. pydoc and IDLE will pick it up there. print "Install python documentation" rootDir = os.path.join(WORKDIR, '_root') - version = getVersion() + buildDir = os.path.join('../../Doc') docdir = os.path.join(rootDir, 'pydocs') - - novername = 'python-docs-html.tar.bz2' - name = 'html-%s.tar.bz2'%(getFullVersion(),) - sourceArchive = os.path.join(DEPSRC, name) - if os.path.exists(sourceArchive): - print "Using local copy of %s"%(name,) - - else: - print "Downloading %s"%(novername,) - downloadURL('http://www.python.org/ftp/python/doc/%s/%s'%( - getFullVersion(), novername), sourceArchive) - print "Archive for %s stored as %s"%(name, sourceArchive) - - extractArchive(os.path.dirname(docdir), sourceArchive) - - os.rename( - os.path.join( - os.path.dirname(docdir), 'python-docs-html'), - docdir) + curDir = os.getcwd() + os.chdir(buildDir) + runCommand('make update') + runCommand('make html') + os.chdir(curDir) + if not os.path.exists(docdir): + os.mkdir(docdir) + os.rename(os.path.join(buildDir, 'build', 'html'), + os.path.join(docdir, 'python-docs-html')) def buildPython(): @@ -935,82 +923,20 @@ def setIcon(filePath, icnsPath): """ Set the custom icon for the specified file or directory. + """ - For a directory the icon data is written in a file named 'Icon\r' inside - the directory. For both files and directories write the icon as an 'icns' - resource. Furthermore set kHasCustomIcon in the finder flags for filePath. - """ - ref, isDirectory = Carbon.File.FSPathMakeRef(icnsPath) - icon = Carbon.Icn.ReadIconFile(ref) - del ref - - # - # Open the resource fork of the target, to add the icon later on. - # For directories we use the file 'Icon\r' inside the directory. - # - - ref, isDirectory = Carbon.File.FSPathMakeRef(filePath) - - if isDirectory: - # There is a problem with getting this into the pax(1) archive, - # just ignore directory icons for now. - return - - tmpPath = os.path.join(filePath, "Icon\r") - if not os.path.exists(tmpPath): - fp = open(tmpPath, 'w') - fp.close() - - tmpRef, _ = Carbon.File.FSPathMakeRef(tmpPath) - spec = Carbon.File.FSSpec(tmpRef) - - else: - spec = Carbon.File.FSSpec(ref) - - try: - Carbon.Res.HCreateResFile(*spec.as_tuple()) - except MacOS.Error: - pass - - # Try to create the resource fork again, this will avoid problems - # when adding an icon to a directory. I have no idea why this helps, - # but without this adding the icon to a directory will fail sometimes. - try: - Carbon.Res.HCreateResFile(*spec.as_tuple()) - except MacOS.Error: - pass - - refNum = Carbon.Res.FSpOpenResFile(spec, fsRdWrPerm) - - Carbon.Res.UseResFile(refNum) - - # Check if there already is an icon, remove it if there is. - try: - h = Carbon.Res.Get1Resource('icns', kCustomIconResource) - except MacOS.Error: - pass - - else: - h.RemoveResource() - del h + toolPath = os.path.join(os.path.dirname(__file__), "seticon.app/Contents/MacOS/seticon") + dirPath = os.path.dirname(__file__) + if not os.path.exists(toolPath) or os.stat(toolPath).st_mtime < os.stat(dirPath + '/seticon.m').st_mtime: + # NOTE: The tool is created inside an .app bundle, otherwise it won't work due + # to connections to the window server. + if not os.path.exists('seticon.app/Contents/MacOS'): + os.makedirs('seticon.app/Contents/MacOS') + runCommand("cc -o %s %s/seticon.m -framework Cocoa"%( + shellQuote(toolPath), shellQuote(dirPath))) - # Add the icon to the resource for of the target - res = Carbon.Res.Resource(icon) - res.AddResource('icns', kCustomIconResource, '') - res.WriteResource() - res.DetachResource() - Carbon.Res.CloseResFile(refNum) - - # And now set the kHasCustomIcon property for the target. Annoyingly, - # python doesn't seem to have bindings for the API that is needed for - # this. Cop out and call SetFile - os.system("/Developer/Tools/SetFile -a C %s"%( - shellQuote(filePath),)) - - if isDirectory: - os.system('/Developer/Tools/SetFile -a V %s'%( - shellQuote(tmpPath), - )) + runCommand("%s %s %s"%(shellQuote(os.path.abspath(toolPath)), shellQuote(icnsPath), + shellQuote(filePath))) def main(): # First parse options and check if we can perform our work @@ -1054,10 +980,12 @@ fp.close() # Custom icon for the DMG, shown when the DMG is mounted. - shutil.copy("../Icons/Disk Image.icns", - os.path.join(WORKDIR, "installer", ".VolumeIcon.icns")) - os.system("/Developer/Tools/SetFile -a C %s"%( - os.path.join(WORKDIR, "installer", ".VolumeIcon.icns"))) + # XXX: Code is diabled because it doesn't actually work :-( +# shutil.copy("../Icons/Disk Image.icns", +# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns")) +# os.system("/Developer/Tools/SetFile -a C %s"%( +# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns"))) + setIcon(os.path.join(WORKDIR, "installer"), "../Icons/Disk Image.icns") # And copy it to a DMG Added: python/trunk/Mac/BuildScript/seticon.m ============================================================================== --- (empty file) +++ python/trunk/Mac/BuildScript/seticon.m Mon Mar 30 19:15:29 2009 @@ -0,0 +1,26 @@ +/* + * Simple tool for setting an icon on a file. + */ +#import +#include + +int main(int argc, char** argv) +{ + if (argc != 3) { + fprintf(stderr, "Usage: seticon ICON TARGET"); + return 1; + } + + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSString* iconPath = [NSString stringWithUTF8String:argv[1]]; + NSString* filePath = [NSString stringWithUTF8String:argv[2]]; + + [NSApplication sharedApplication]; + + [[NSWorkspace sharedWorkspace] + setIcon: [[NSImage alloc] initWithContentsOfFile: iconPath] + forFile: filePath + options: 0]; + [pool release]; + return 0; +} From python-checkins at python.org Mon Mar 30 19:17:52 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 19:17:52 +0200 (CEST) Subject: [Python-checkins] r70728 - in python/branches/release26-maint: Mac/BuildScript/build-installer.py Message-ID: <20090330171752.722831E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 19:17:52 2009 New Revision: 70728 Log: Merged revisions 70727 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70727 | ronald.oussoren | 2009-03-30 12:15:29 -0500 (Mon, 30 Mar 2009) | 5 lines * Updates installed dependencies to latest releaases (bzip, zlib, ...) * Changes code for updating folder icons from Python code that uses the deprecated Carbon module to a much simpler Cocoa program in Objective-C ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Mac/BuildScript/build-installer.py Modified: python/branches/release26-maint/Mac/BuildScript/build-installer.py ============================================================================== --- python/branches/release26-maint/Mac/BuildScript/build-installer.py (original) +++ python/branches/release26-maint/Mac/BuildScript/build-installer.py Mon Mar 30 19:17:52 2009 @@ -1,4 +1,4 @@ -#!/usr/bin/python2.3 +#!/usr/bin/python """ This script is used to build the "official unofficial" universal build on Mac OS X. It requires Mac OS X 10.4, Xcode 2.2 and the 10.4u SDK to do its @@ -18,11 +18,6 @@ from plistlib import Plist import MacOS -import Carbon.File -import Carbon.Icn -import Carbon.Res -from Carbon.Files import kCustomIconResource, fsRdWrPerm, kHasCustomIcon -from Carbon.Files import kFSCatInfoFinderInfo try: from plistlib import writePlist @@ -94,8 +89,9 @@ # batteries included python. LIBRARY_RECIPES = [ dict( - name="Bzip2 1.0.3", - url="http://www.bzip.org/1.0.3/bzip2-1.0.3.tar.gz", + name="Bzip2 1.0.4", + url="http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz", + checksum='fc310b254f6ba5fbb5da018f04533688', configure=None, install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( shellQuote(os.path.join(WORKDIR, 'libraries')), @@ -106,6 +102,7 @@ dict( name="ZLib 1.2.3", url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz", + checksum='debc62758716a169df9f62e6ab2bc634', configure=None, install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( shellQuote(os.path.join(WORKDIR, 'libraries')), @@ -117,6 +114,7 @@ # Note that GNU readline is GPL'd software name="GNU Readline 5.1.4", url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" , + checksum='7ee5a692db88b30ca48927a13fd60e46', patchlevel='0', patches=[ # The readline maintainers don't do actual micro releases, but @@ -129,9 +127,9 @@ ), dict( - name="SQLite 3.6.3", - url="http://www.sqlite.org/sqlite-3.6.3.tar.gz", - checksum='93f742986e8bc2dfa34792e16df017a6feccf3a2', + name="SQLite 3.6.11", + url="http://www.sqlite.org/sqlite-3.6.11.tar.gz", + checksum='7ebb099696ab76cc6ff65dd496d17858', configure_pre=[ '--enable-threadsafe', '--enable-tempstore', @@ -144,6 +142,7 @@ dict( name="NCurses 5.5", url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz", + checksum='e73c1ac10b4bfc46db43b2ddfd6244ef', configure_pre=[ "--without-cxx", "--without-ada", @@ -172,8 +171,7 @@ dict( name="Sleepycat DB 4.7.25", url="http://download.oracle.com/berkeley-db/db-4.7.25.tar.gz", - #name="Sleepycat DB 4.3.29", - #url="http://downloads.sleepycat.com/db-4.3.29.tar.gz", + checksum='ec2b87e833779681a0c3a814aa71359e', buildDir="build_unix", configure="../dist/configure", configure_pre=[ @@ -578,31 +576,21 @@ def buildPythonDocs(): - # This stores the documentation as Resources/English.lproj/Docuentation + # This stores the documentation as Resources/English.lproj/Documentation # inside the framwork. pydoc and IDLE will pick it up there. print "Install python documentation" rootDir = os.path.join(WORKDIR, '_root') - version = getVersion() + buildDir = os.path.join('../../Doc') docdir = os.path.join(rootDir, 'pydocs') - - novername = 'python-docs-html.tar.bz2' - name = 'html-%s.tar.bz2'%(getFullVersion(),) - sourceArchive = os.path.join(DEPSRC, name) - if os.path.exists(sourceArchive): - print "Using local copy of %s"%(name,) - - else: - print "Downloading %s"%(novername,) - downloadURL('http://www.python.org/ftp/python/doc/%s/%s'%( - getFullVersion(), novername), sourceArchive) - print "Archive for %s stored as %s"%(name, sourceArchive) - - extractArchive(os.path.dirname(docdir), sourceArchive) - - os.rename( - os.path.join( - os.path.dirname(docdir), 'python-docs-html'), - docdir) + curDir = os.getcwd() + os.chdir(buildDir) + runCommand('make update') + runCommand('make html') + os.chdir(curDir) + if not os.path.exists(docdir): + os.mkdir(docdir) + os.rename(os.path.join(buildDir, 'build', 'html'), + os.path.join(docdir, 'python-docs-html')) def buildPython(): @@ -935,82 +923,20 @@ def setIcon(filePath, icnsPath): """ Set the custom icon for the specified file or directory. + """ - For a directory the icon data is written in a file named 'Icon\r' inside - the directory. For both files and directories write the icon as an 'icns' - resource. Furthermore set kHasCustomIcon in the finder flags for filePath. - """ - ref, isDirectory = Carbon.File.FSPathMakeRef(icnsPath) - icon = Carbon.Icn.ReadIconFile(ref) - del ref - - # - # Open the resource fork of the target, to add the icon later on. - # For directories we use the file 'Icon\r' inside the directory. - # - - ref, isDirectory = Carbon.File.FSPathMakeRef(filePath) - - if isDirectory: - # There is a problem with getting this into the pax(1) archive, - # just ignore directory icons for now. - return - - tmpPath = os.path.join(filePath, "Icon\r") - if not os.path.exists(tmpPath): - fp = open(tmpPath, 'w') - fp.close() - - tmpRef, _ = Carbon.File.FSPathMakeRef(tmpPath) - spec = Carbon.File.FSSpec(tmpRef) - - else: - spec = Carbon.File.FSSpec(ref) - - try: - Carbon.Res.HCreateResFile(*spec.as_tuple()) - except MacOS.Error: - pass - - # Try to create the resource fork again, this will avoid problems - # when adding an icon to a directory. I have no idea why this helps, - # but without this adding the icon to a directory will fail sometimes. - try: - Carbon.Res.HCreateResFile(*spec.as_tuple()) - except MacOS.Error: - pass - - refNum = Carbon.Res.FSpOpenResFile(spec, fsRdWrPerm) - - Carbon.Res.UseResFile(refNum) - - # Check if there already is an icon, remove it if there is. - try: - h = Carbon.Res.Get1Resource('icns', kCustomIconResource) - except MacOS.Error: - pass - - else: - h.RemoveResource() - del h + toolPath = os.path.join(os.path.dirname(__file__), "seticon.app/Contents/MacOS/seticon") + dirPath = os.path.dirname(__file__) + if not os.path.exists(toolPath) or os.stat(toolPath).st_mtime < os.stat(dirPath + '/seticon.m').st_mtime: + # NOTE: The tool is created inside an .app bundle, otherwise it won't work due + # to connections to the window server. + if not os.path.exists('seticon.app/Contents/MacOS'): + os.makedirs('seticon.app/Contents/MacOS') + runCommand("cc -o %s %s/seticon.m -framework Cocoa"%( + shellQuote(toolPath), shellQuote(dirPath))) - # Add the icon to the resource for of the target - res = Carbon.Res.Resource(icon) - res.AddResource('icns', kCustomIconResource, '') - res.WriteResource() - res.DetachResource() - Carbon.Res.CloseResFile(refNum) - - # And now set the kHasCustomIcon property for the target. Annoyingly, - # python doesn't seem to have bindings for the API that is needed for - # this. Cop out and call SetFile - os.system("/Developer/Tools/SetFile -a C %s"%( - shellQuote(filePath),)) - - if isDirectory: - os.system('/Developer/Tools/SetFile -a V %s'%( - shellQuote(tmpPath), - )) + runCommand("%s %s %s"%(shellQuote(os.path.abspath(toolPath)), shellQuote(icnsPath), + shellQuote(filePath))) def main(): # First parse options and check if we can perform our work @@ -1054,10 +980,12 @@ fp.close() # Custom icon for the DMG, shown when the DMG is mounted. - shutil.copy("../Icons/Disk Image.icns", - os.path.join(WORKDIR, "installer", ".VolumeIcon.icns")) - os.system("/Developer/Tools/SetFile -a C %s"%( - os.path.join(WORKDIR, "installer", ".VolumeIcon.icns"))) + # XXX: Code is diabled because it doesn't actually work :-( +# shutil.copy("../Icons/Disk Image.icns", +# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns")) +# os.system("/Developer/Tools/SetFile -a C %s"%( +# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns"))) + setIcon(os.path.join(WORKDIR, "installer"), "../Icons/Disk Image.icns") # And copy it to a DMG From python-checkins at python.org Mon Mar 30 19:20:30 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 19:20:30 +0200 (CEST) Subject: [Python-checkins] r70729 - in python/branches/py3k: Mac/BuildScript/build-installer.py Mac/BuildScript/seticon.m Message-ID: <20090330172030.72B681E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 19:20:30 2009 New Revision: 70729 Log: Merged revisions 70727 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70727 | ronald.oussoren | 2009-03-30 12:15:29 -0500 (Mon, 30 Mar 2009) | 5 lines * Updates installed dependencies to latest releaases (bzip, zlib, ...) * Changes code for updating folder icons from Python code that uses the deprecated Carbon module to a much simpler Cocoa program in Objective-C ........ Added: python/branches/py3k/Mac/BuildScript/seticon.m - copied unchanged from r70727, /python/trunk/Mac/BuildScript/seticon.m Modified: python/branches/py3k/ (props changed) python/branches/py3k/Mac/BuildScript/build-installer.py Modified: python/branches/py3k/Mac/BuildScript/build-installer.py ============================================================================== --- python/branches/py3k/Mac/BuildScript/build-installer.py (original) +++ python/branches/py3k/Mac/BuildScript/build-installer.py Mon Mar 30 19:20:30 2009 @@ -1,4 +1,4 @@ -#!/usr/bin/python2.3 +#!/usr/bin/python """ This script is used to build the "official unofficial" universal build on Mac OS X. It requires Mac OS X 10.4, Xcode 2.2 and the 10.4u SDK to do its @@ -18,11 +18,6 @@ from plistlib import Plist import MacOS -import Carbon.File -import Carbon.Icn -import Carbon.Res -from Carbon.Files import kCustomIconResource, fsRdWrPerm, kHasCustomIcon -from Carbon.Files import kFSCatInfoFinderInfo try: from plistlib import writePlist @@ -94,8 +89,9 @@ # batteries included python. LIBRARY_RECIPES = [ dict( - name="Bzip2 1.0.3", - url="http://www.bzip.org/1.0.3/bzip2-1.0.3.tar.gz", + name="Bzip2 1.0.4", + url="http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz", + checksum='fc310b254f6ba5fbb5da018f04533688', configure=None, install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( shellQuote(os.path.join(WORKDIR, 'libraries')), @@ -106,6 +102,7 @@ dict( name="ZLib 1.2.3", url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz", + checksum='debc62758716a169df9f62e6ab2bc634', configure=None, install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( shellQuote(os.path.join(WORKDIR, 'libraries')), @@ -117,6 +114,7 @@ # Note that GNU readline is GPL'd software name="GNU Readline 5.1.4", url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" , + checksum='7ee5a692db88b30ca48927a13fd60e46', patchlevel='0', patches=[ # The readline maintainers don't do actual micro releases, but @@ -129,9 +127,9 @@ ), dict( - name="SQLite 3.6.3", - url="http://www.sqlite.org/sqlite-3.6.3.tar.gz", - checksum='93f742986e8bc2dfa34792e16df017a6feccf3a2', + name="SQLite 3.6.11", + url="http://www.sqlite.org/sqlite-3.6.11.tar.gz", + checksum='7ebb099696ab76cc6ff65dd496d17858', configure_pre=[ '--enable-threadsafe', '--enable-tempstore', @@ -144,6 +142,7 @@ dict( name="NCurses 5.5", url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz", + checksum='e73c1ac10b4bfc46db43b2ddfd6244ef', configure_pre=[ "--without-cxx", "--without-ada", @@ -573,31 +572,21 @@ def buildPythonDocs(): - # This stores the documentation as Resources/English.lproj/Docuentation + # This stores the documentation as Resources/English.lproj/Documentation # inside the framwork. pydoc and IDLE will pick it up there. print "Install python documentation" rootDir = os.path.join(WORKDIR, '_root') - version = getVersion() + buildDir = os.path.join('../../Doc') docdir = os.path.join(rootDir, 'pydocs') - - novername = 'python-docs-html.tar.bz2' - name = 'html-%s.tar.bz2'%(getFullVersion(),) - sourceArchive = os.path.join(DEPSRC, name) - if os.path.exists(sourceArchive): - print "Using local copy of %s"%(name,) - - else: - print "Downloading %s"%(novername,) - downloadURL('http://www.python.org/ftp/python/doc/%s/%s'%( - getFullVersion(), novername), sourceArchive) - print "Archive for %s stored as %s"%(name, sourceArchive) - - extractArchive(os.path.dirname(docdir), sourceArchive) - - os.rename( - os.path.join( - os.path.dirname(docdir), 'python-docs-html'), - docdir) + curDir = os.getcwd() + os.chdir(buildDir) + runCommand('make update') + runCommand('make html') + os.chdir(curDir) + if not os.path.exists(docdir): + os.mkdir(docdir) + os.rename(os.path.join(buildDir, 'build', 'html'), + os.path.join(docdir, 'python-docs-html')) def buildPython(): @@ -937,82 +926,20 @@ def setIcon(filePath, icnsPath): """ Set the custom icon for the specified file or directory. + """ - For a directory the icon data is written in a file named 'Icon\r' inside - the directory. For both files and directories write the icon as an 'icns' - resource. Furthermore set kHasCustomIcon in the finder flags for filePath. - """ - ref, isDirectory = Carbon.File.FSPathMakeRef(icnsPath) - icon = Carbon.Icn.ReadIconFile(ref) - del ref - - # - # Open the resource fork of the target, to add the icon later on. - # For directories we use the file 'Icon\r' inside the directory. - # - - ref, isDirectory = Carbon.File.FSPathMakeRef(filePath) - - if isDirectory: - # There is a problem with getting this into the pax(1) archive, - # just ignore directory icons for now. - return - - tmpPath = os.path.join(filePath, "Icon\r") - if not os.path.exists(tmpPath): - fp = open(tmpPath, 'w') - fp.close() - - tmpRef, _ = Carbon.File.FSPathMakeRef(tmpPath) - spec = Carbon.File.FSSpec(tmpRef) - - else: - spec = Carbon.File.FSSpec(ref) - - try: - Carbon.Res.HCreateResFile(*spec.as_tuple()) - except MacOS.Error: - pass - - # Try to create the resource fork again, this will avoid problems - # when adding an icon to a directory. I have no idea why this helps, - # but without this adding the icon to a directory will fail sometimes. - try: - Carbon.Res.HCreateResFile(*spec.as_tuple()) - except MacOS.Error: - pass - - refNum = Carbon.Res.FSpOpenResFile(spec, fsRdWrPerm) - - Carbon.Res.UseResFile(refNum) - - # Check if there already is an icon, remove it if there is. - try: - h = Carbon.Res.Get1Resource('icns', kCustomIconResource) - except MacOS.Error: - pass - - else: - h.RemoveResource() - del h + toolPath = os.path.join(os.path.dirname(__file__), "seticon.app/Contents/MacOS/seticon") + dirPath = os.path.dirname(__file__) + if not os.path.exists(toolPath) or os.stat(toolPath).st_mtime < os.stat(dirPath + '/seticon.m').st_mtime: + # NOTE: The tool is created inside an .app bundle, otherwise it won't work due + # to connections to the window server. + if not os.path.exists('seticon.app/Contents/MacOS'): + os.makedirs('seticon.app/Contents/MacOS') + runCommand("cc -o %s %s/seticon.m -framework Cocoa"%( + shellQuote(toolPath), shellQuote(dirPath))) - # Add the icon to the resource for of the target - res = Carbon.Res.Resource(icon) - res.AddResource('icns', kCustomIconResource, '') - res.WriteResource() - res.DetachResource() - Carbon.Res.CloseResFile(refNum) - - # And now set the kHasCustomIcon property for the target. Annoyingly, - # python doesn't seem to have bindings for the API that is needed for - # this. Cop out and call SetFile - os.system("/Developer/Tools/SetFile -a C %s"%( - shellQuote(filePath),)) - - if isDirectory: - os.system('/Developer/Tools/SetFile -a V %s'%( - shellQuote(tmpPath), - )) + runCommand("%s %s %s"%(shellQuote(os.path.abspath(toolPath)), shellQuote(icnsPath), + shellQuote(filePath))) def main(): # First parse options and check if we can perform our work @@ -1056,10 +983,12 @@ fp.close() # Custom icon for the DMG, shown when the DMG is mounted. - shutil.copy("../Icons/Disk Image.icns", - os.path.join(WORKDIR, "installer", ".VolumeIcon.icns")) - os.system("/Developer/Tools/SetFile -a C %s"%( - os.path.join(WORKDIR, "installer", ".VolumeIcon.icns"))) + # XXX: Code is diabled because it doesn't actually work :-( +# shutil.copy("../Icons/Disk Image.icns", +# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns")) +# os.system("/Developer/Tools/SetFile -a C %s"%( +# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns"))) + setIcon(os.path.join(WORKDIR, "installer"), "../Icons/Disk Image.icns") # And copy it to a DMG From buildbot at python.org Mon Mar 30 19:41:36 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 17:41:36 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo trunk Message-ID: <20090330174136.C3C2B1E4002@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%20gentoo%20trunk/builds/2025 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: brett.cannon,jesse.noller,kurt.kaiser,r.david.murray,ronald.oussoren BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From python-checkins at python.org Mon Mar 30 19:53:39 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 19:53:39 +0200 (CEST) Subject: [Python-checkins] r70730 - in python/trunk: configure configure.in Message-ID: <20090330175339.9F75A1E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 19:53:39 2009 New Revision: 70730 Log: Fix issue where 'make altinstall' or 'make install' would install everything that needs to be installed on OSX (depending on the configure flags) Modified: python/trunk/configure python/trunk/configure.in Modified: python/trunk/configure ============================================================================== --- python/trunk/configure (original) +++ python/trunk/configure Mon Mar 30 19:53:39 2009 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 68312 . +# From configure.in Revision: 70479 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 2.7. # @@ -1972,7 +1972,9 @@ if test "$UNIVERSAL_ARCHS" = "all" then FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps4way frameworkinstallunixtools4way" + FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps4way frameworkaltinstallunixtools4way" else + FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools" FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools" fi Modified: python/trunk/configure.in ============================================================================== --- python/trunk/configure.in (original) +++ python/trunk/configure.in Mon Mar 30 19:53:39 2009 @@ -154,7 +154,9 @@ if test "$UNIVERSAL_ARCHS" = "all" then FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps4way frameworkinstallunixtools4way" + FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps4way frameworkaltinstallunixtools4way" else + FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools" FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools" fi From python-checkins at python.org Mon Mar 30 19:56:14 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 19:56:14 +0200 (CEST) Subject: [Python-checkins] r70731 - in python/branches/release26-maint: configure configure.in Message-ID: <20090330175614.56E351E4063@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 19:56:14 2009 New Revision: 70731 Log: Merged revisions 70730 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70730 | ronald.oussoren | 2009-03-30 12:53:39 -0500 (Mon, 30 Mar 2009) | 3 lines Fix issue where 'make altinstall' or 'make install' would install everything that needs to be installed on OSX (depending on the configure flags) ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/configure python/branches/release26-maint/configure.in Modified: python/branches/release26-maint/configure ============================================================================== --- python/branches/release26-maint/configure (original) +++ python/branches/release26-maint/configure Mon Mar 30 19:56:14 2009 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 68147 . +# From configure.in Revision: 68599 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 2.6. # @@ -1970,7 +1970,9 @@ if test "$UNIVERSAL_ARCHS" = "all" then FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps4way frameworkinstallunixtools4way" + FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps4way frameworkaltinstallunixtools4way" else + FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools" FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools" fi @@ -2256,7 +2258,7 @@ if test "${with_gcc+set}" = set; then withval=$with_gcc; case $withval in - no) CC=cc + no) CC=${CC:-cc} without_gcc=yes;; yes) CC=gcc without_gcc=no;; Modified: python/branches/release26-maint/configure.in ============================================================================== --- python/branches/release26-maint/configure.in (original) +++ python/branches/release26-maint/configure.in Mon Mar 30 19:56:14 2009 @@ -154,7 +154,9 @@ if test "$UNIVERSAL_ARCHS" = "all" then FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps4way frameworkinstallunixtools4way" + FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps4way frameworkaltinstallunixtools4way" else + FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools" FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools" fi From buildbot at python.org Mon Mar 30 19:56:30 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 17:56:30 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu trunk Message-ID: <20090330175630.531E61E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%20trunk/builds/1025 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: brett.cannon,jesse.noller,kurt.kaiser,r.david.murray,ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Mon Mar 30 20:00:28 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 20:00:28 +0200 (CEST) Subject: [Python-checkins] r70732 - in python/branches/py3k: configure configure.in Message-ID: <20090330180028.7657A1E4015@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 20:00:28 2009 New Revision: 70732 Log: Merged revisions 70730 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70730 | ronald.oussoren | 2009-03-30 12:53:39 -0500 (Mon, 30 Mar 2009) | 3 lines Fix issue where 'make altinstall' or 'make install' would install everything that needs to be installed on OSX (depending on the configure flags) ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/configure python/branches/py3k/configure.in Modified: python/branches/py3k/configure ============================================================================== --- python/branches/py3k/configure (original) +++ python/branches/py3k/configure Mon Mar 30 20:00:28 2009 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 68924 . +# From configure.in Revision: 70459 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 3.1. # @@ -1969,7 +1969,9 @@ if test "$UNIVERSAL_ARCHS" = "all" then FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps4way frameworkinstallunixtools4way" + FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps4way frameworkaltinstallunixtools4way" else + FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools" FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools" fi Modified: python/branches/py3k/configure.in ============================================================================== --- python/branches/py3k/configure.in (original) +++ python/branches/py3k/configure.in Mon Mar 30 20:00:28 2009 @@ -154,7 +154,9 @@ if test "$UNIVERSAL_ARCHS" = "all" then FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps4way frameworkinstallunixtools4way" + FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps4way frameworkaltinstallunixtools4way" else + FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools" FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools" fi From python-checkins at python.org Mon Mar 30 20:17:28 2009 From: python-checkins at python.org (mark.dickinson) Date: Mon, 30 Mar 2009 20:17:28 +0200 (CEST) Subject: [Python-checkins] r70733 - python/branches/py3k-short-float-repr Message-ID: <20090330181728.EF44B1E400C@bag.python.org> Author: mark.dickinson Date: Mon Mar 30 20:17:28 2009 New Revision: 70733 Log: Create new branch for working on issue #1580: shorter repr() for floats. Added: python/branches/py3k-short-float-repr/ - copied from r70732, /python/branches/py3k/ From buildbot at python.org Mon Mar 30 20:21:06 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 18:21:06 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090330182106.5079B1E403E@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/583 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_pipes make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Mon Mar 30 20:48:46 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 18:48:46 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090330184846.9F4B81E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/543 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon,jesse.noller BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Mon Mar 30 20:59:54 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 18:59:54 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090330185955.24D3D1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/473 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson,brett.cannon BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_cgi make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Mon Mar 30 21:04:01 2009 From: python-checkins at python.org (r.david.murray) Date: Mon, 30 Mar 2009 21:04:01 +0200 (CEST) Subject: [Python-checkins] r70734 - in python/trunk/Lib/test: test_aepack.py test_applesingle.py test_asynchat.py test_cd.py test_cl.py test_crypt.py test_fork1.py test_gl.py test_grp.py test_macos.py test_macostools.py test_mmap.py test_posix.py test_pwd.py test_scriptpackages.py test_startfile.py test_support.py test_ttk_guionly.py test_winreg.py test_winsound.py Message-ID: <20090330190401.5D61A1E4002@bag.python.org> Author: r.david.murray Date: Mon Mar 30 21:04:00 2009 New Revision: 70734 Log: Add import_function method to test.test_support, and modify a number of tests that expect to be skipped if imports fail or functions don't exist to use import_function and import_module. The ultimate goal is to change regrtest to not skip automatically on ImportError. Checking in now to make sure the buldbots don't show any errors on platforms I can't direct test on. Modified: python/trunk/Lib/test/test_aepack.py python/trunk/Lib/test/test_applesingle.py python/trunk/Lib/test/test_asynchat.py python/trunk/Lib/test/test_cd.py python/trunk/Lib/test/test_cl.py python/trunk/Lib/test/test_crypt.py python/trunk/Lib/test/test_fork1.py python/trunk/Lib/test/test_gl.py python/trunk/Lib/test/test_grp.py python/trunk/Lib/test/test_macos.py python/trunk/Lib/test/test_macostools.py python/trunk/Lib/test/test_mmap.py python/trunk/Lib/test/test_posix.py python/trunk/Lib/test/test_pwd.py python/trunk/Lib/test/test_scriptpackages.py python/trunk/Lib/test/test_startfile.py python/trunk/Lib/test/test_support.py python/trunk/Lib/test/test_ttk_guionly.py python/trunk/Lib/test/test_winreg.py python/trunk/Lib/test/test_winsound.py Modified: python/trunk/Lib/test/test_aepack.py ============================================================================== --- python/trunk/Lib/test/test_aepack.py (original) +++ python/trunk/Lib/test/test_aepack.py Mon Mar 30 21:04:00 2009 @@ -1,11 +1,12 @@ # Copyright (C) 2003 Python Software Foundation import unittest -import aepack -import aetypes import os from test import test_support +aetypes = test_support.import_module('aetypes') +aepack = test_support.import_module('aepack') + class TestAepack(unittest.TestCase): OBJECTS = [ aetypes.Enum('enum'), Modified: python/trunk/Lib/test/test_applesingle.py ============================================================================== --- python/trunk/Lib/test/test_applesingle.py (original) +++ python/trunk/Lib/test/test_applesingle.py Mon Mar 30 21:04:00 2009 @@ -1,13 +1,15 @@ # Copyright (C) 2003 Python Software Foundation import unittest -import macostools -import Carbon.File -import MacOS import os from test import test_support import struct + +MacOS = test_support.import_module('MacOS') +# The following should exist if MacOS does. +import macostools import applesingle +import Carbon.File AS_MAGIC=0x00051600 AS_VERSION=0x00020000 Modified: python/trunk/Lib/test/test_asynchat.py ============================================================================== --- python/trunk/Lib/test/test_asynchat.py (original) +++ python/trunk/Lib/test/test_asynchat.py Mon Mar 30 21:04:00 2009 @@ -1,11 +1,13 @@ -# test asynchat -- requires threading +# test asynchat -import thread # If this fails, we can't test this module import asyncore, asynchat, socket, threading, time import unittest import sys from test import test_support +# Skip tests if thread module does not exist. +test_support.import_module('thread') + HOST = test_support.HOST SERVER_QUIT = 'QUIT\n' Modified: python/trunk/Lib/test/test_cd.py ============================================================================== --- python/trunk/Lib/test/test_cd.py (original) +++ python/trunk/Lib/test/test_cd.py Mon Mar 30 21:04:00 2009 @@ -2,8 +2,9 @@ """Whimpy test script for the cd module Roger E. Masse """ -import cd -from test.test_support import verbose +from test.test_support import verbose, import_module + +cd = import_module('cd') cdattrs = ['BLOCKSIZE', 'CDROM', 'DATASIZE', 'ERROR', 'NODISC', 'PAUSED', 'PLAYING', 'READY', 'STILL', '__doc__', '__name__', 'atime', 'audio', 'catalog', 'control', 'createparser', 'error', Modified: python/trunk/Lib/test/test_cl.py ============================================================================== --- python/trunk/Lib/test/test_cl.py (original) +++ python/trunk/Lib/test/test_cl.py Mon Mar 30 21:04:00 2009 @@ -2,8 +2,9 @@ """Whimpy test script for the cl module Roger E. Masse """ -import cl -from test.test_support import verbose +from test.test_support import verbose, import_module + +cl = import_module('cl') clattrs = ['ADDED_ALGORITHM_ERROR', 'ALAW', 'ALGORITHM_ID', 'ALGORITHM_VERSION', 'AUDIO', 'AWARE_ERROR', 'AWARE_MPEG_AUDIO', Modified: python/trunk/Lib/test/test_crypt.py ============================================================================== --- python/trunk/Lib/test/test_crypt.py (original) +++ python/trunk/Lib/test/test_crypt.py Mon Mar 30 21:04:00 2009 @@ -1,6 +1,7 @@ from test import test_support import unittest -import crypt + +crypt = test_support.import_module('crypt') class CryptTestCase(unittest.TestCase): Modified: python/trunk/Lib/test/test_fork1.py ============================================================================== --- python/trunk/Lib/test/test_fork1.py (original) +++ python/trunk/Lib/test/test_fork1.py Mon Mar 30 21:04:00 2009 @@ -3,14 +3,12 @@ import os import time -import unittest from test.fork_wait import ForkWait -from test.test_support import run_unittest, reap_children +from test.test_support import run_unittest, reap_children, import_function + +#Skip test if fork does not exist. +import_function(os, 'fork') -try: - os.fork -except AttributeError: - raise unittest.SkipTest, "os.fork not defined -- skipping test_fork1" class ForkTest(ForkWait): def wait_impl(self, cpid): Modified: python/trunk/Lib/test/test_gl.py ============================================================================== --- python/trunk/Lib/test/test_gl.py (original) +++ python/trunk/Lib/test/test_gl.py Mon Mar 30 21:04:00 2009 @@ -3,8 +3,10 @@ taken mostly from the documentation. Roger E. Masse """ -from test.test_support import verbose -import gl, GL, time +from test.test_support import verbose, import_module +import time +gl = import_module('gl') +GL = import_module('GL') glattrs = ['RGBcolor', 'RGBcursor', 'RGBmode', 'RGBrange', 'RGBwritemask', '__doc__', '__name__', 'addtopup', 'altgetmatrix', 'arc', 'arcf', Modified: python/trunk/Lib/test/test_grp.py ============================================================================== --- python/trunk/Lib/test/test_grp.py (original) +++ python/trunk/Lib/test/test_grp.py Mon Mar 30 21:04:00 2009 @@ -1,9 +1,10 @@ """Test script for the grp module.""" -import grp import unittest from test import test_support +grp = test_support.import_module('grp') + class GroupDatabaseTestCase(unittest.TestCase): def check_value(self, value): Modified: python/trunk/Lib/test/test_macos.py ============================================================================== --- python/trunk/Lib/test/test_macos.py (original) +++ python/trunk/Lib/test/test_macos.py Mon Mar 30 21:04:00 2009 @@ -1,10 +1,12 @@ import unittest -import MacOS -import Carbon.File from test import test_support import os import subprocess +MacOS = test_support.import_module('MacOS') +#The following should exist if MacOS exists. +import Carbon.File + TESTFN2 = test_support.TESTFN + '2' class TestMacOS(unittest.TestCase): Modified: python/trunk/Lib/test/test_macostools.py ============================================================================== --- python/trunk/Lib/test/test_macostools.py (original) +++ python/trunk/Lib/test/test_macostools.py Mon Mar 30 21:04:00 2009 @@ -1,13 +1,15 @@ # Copyright (C) 2003 Python Software Foundation import unittest -import macostools -import Carbon.File -import MacOS import os import sys from test import test_support +MacOS = test_support.import_module('MacOS') +#The following modules should exist if MacOS exists. +import Carbon.File +import macostools + TESTFN2 = test_support.TESTFN + '2' class TestMacostools(unittest.TestCase): Modified: python/trunk/Lib/test/test_mmap.py ============================================================================== --- python/trunk/Lib/test/test_mmap.py (original) +++ python/trunk/Lib/test/test_mmap.py Mon Mar 30 21:04:00 2009 @@ -1,8 +1,9 @@ -from test.test_support import TESTFN, run_unittest -import mmap +from test.test_support import TESTFN, run_unittest, import_module import unittest import os, re +mmap = import_module('mmap') + PAGESIZE = mmap.PAGESIZE class MmapTests(unittest.TestCase): Modified: python/trunk/Lib/test/test_posix.py ============================================================================== --- python/trunk/Lib/test/test_posix.py (original) +++ python/trunk/Lib/test/test_posix.py Mon Mar 30 21:04:00 2009 @@ -2,10 +2,6 @@ from test import test_support -try: - import posix -except ImportError: - raise unittest.SkipTest, "posix is not available" import time import os @@ -13,6 +9,9 @@ import shutil import unittest import warnings + +posix = test_support.import_module('posix') + warnings.filterwarnings('ignore', '.* potential security risk .*', RuntimeWarning) Modified: python/trunk/Lib/test/test_pwd.py ============================================================================== --- python/trunk/Lib/test/test_pwd.py (original) +++ python/trunk/Lib/test/test_pwd.py Mon Mar 30 21:04:00 2009 @@ -1,7 +1,7 @@ import unittest from test import test_support -import pwd +pwd = test_support.import_module('pwd') class PwdTest(unittest.TestCase): Modified: python/trunk/Lib/test/test_scriptpackages.py ============================================================================== --- python/trunk/Lib/test/test_scriptpackages.py (original) +++ python/trunk/Lib/test/test_scriptpackages.py Mon Mar 30 21:04:00 2009 @@ -2,7 +2,8 @@ import unittest from test import test_support -import aetools + +aetools = test_support.import_module('aetools') class TestScriptpackages(unittest.TestCase): Modified: python/trunk/Lib/test/test_startfile.py ============================================================================== --- python/trunk/Lib/test/test_startfile.py (original) +++ python/trunk/Lib/test/test_startfile.py Mon Mar 30 21:04:00 2009 @@ -9,9 +9,11 @@ import unittest from test import test_support +import os +from os import path + +startfile = test_support.import_function(os, 'startfile') -# use this form so that the test is skipped when startfile is not available: -from os import startfile, path class TestCase(unittest.TestCase): def test_nonexisting(self): Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Mon Mar 30 21:04:00 2009 @@ -55,6 +55,20 @@ else: return module +def import_function(module, name, deprecated=False): + with warnings.catch_warnings(): + if deprecated: + warnings.filterwarnings("ignore", ".+ (module|package)", + DeprecationWarning) + try: + function = getattr(module, name) + except AttributeError: + raise unittest.SkipTest("No function named %s in module %s" % ( + name, module.__name__)) + else: + return function + + verbose = 1 # Flag set to 0 by regrtest.py use_resources = None # Flag set to [] by regrtest.py max_memuse = 0 # Disable bigmem tests (they will still be run with Modified: python/trunk/Lib/test/test_ttk_guionly.py ============================================================================== --- python/trunk/Lib/test/test_ttk_guionly.py (original) +++ python/trunk/Lib/test/test_ttk_guionly.py Mon Mar 30 21:04:00 2009 @@ -1,10 +1,12 @@ import os import sys -import ttk import unittest -from _tkinter import TclError from test import test_support +ttk = test_support.import_module('ttk') +#If ttk exists _tkinter must exist. +from _tkinter import TclError + try: ttk.Button() except TclError, msg: Modified: python/trunk/Lib/test/test_winreg.py ============================================================================== --- python/trunk/Lib/test/test_winreg.py (original) +++ python/trunk/Lib/test/test_winreg.py Mon Mar 30 21:04:00 2009 @@ -1,12 +1,15 @@ # Test the windows specific win32reg module. # Only win32reg functions not hit here: FlushKey, LoadKey and SaveKey -from _winreg import * import os, sys import unittest - from test import test_support +#Do this first so test will be skipped if module doesn't exist +test_support.import_module('_winreg') +#Now import everything +from _winreg import * + test_key_name = "SOFTWARE\\Python Registry Test Key - Delete Me" test_data = [ Modified: python/trunk/Lib/test/test_winsound.py ============================================================================== --- python/trunk/Lib/test/test_winsound.py (original) +++ python/trunk/Lib/test/test_winsound.py Mon Mar 30 21:04:00 2009 @@ -2,10 +2,12 @@ import unittest from test import test_support -import winsound, time +import time import os import subprocess +winsound = test_support.import_module('winsound') + class BeepTest(unittest.TestCase): # As with PlaySoundTest, incorporate the _have_soundcard() check From buildbot at python.org Mon Mar 30 21:09:51 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 19:09:51 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 2.6 Message-ID: <20090330190952.20E581E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%202.6/builds/203 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: jesse.noller BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From g.brandl at gmx.net Mon Mar 30 21:10:17 2009 From: g.brandl at gmx.net (Georg Brandl) Date: Mon, 30 Mar 2009 14:10:17 -0500 Subject: [Python-checkins] r70726 - peps/trunk/pep-0302.txt In-Reply-To: <20090330164941.F36B31E4037@bag.python.org> References: <20090330164941.F36B31E4037@bag.python.org> Message-ID: brett.cannon schrieb: > Author: brett.cannon > Date: Mon Mar 30 18:49:41 2009 > New Revision: 70726 > > Log: > Move over to using the term 'finder' as used in importlib. Should there be an "ImpFinder" alias of "ImpImporter" in pkgutil? 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 Mon Mar 30 21:22:56 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 21:22:56 +0200 (CEST) Subject: [Python-checkins] r70735 - python/trunk/Mac/PythonLauncher/FileSettings.m Message-ID: <20090330192256.E6AC21E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 21:22:56 2009 New Revision: 70735 Log: Remove usage of the deprecated '-cString' and '+stringWithCString:' API's in PythonLauncher, replacing them with the correct counterparts. Modified: python/trunk/Mac/PythonLauncher/FileSettings.m Modified: python/trunk/Mac/PythonLauncher/FileSettings.m ============================================================================== --- python/trunk/Mac/PythonLauncher/FileSettings.m (original) +++ python/trunk/Mac/PythonLauncher/FileSettings.m Mon Mar 30 21:22:56 2009 @@ -267,14 +267,14 @@ [script length]-[[script lastPathComponent] length]]; if (honourhashbang && - (fp=fopen([script cString], "r")) && + (fp=fopen([script fileSystemRepresentation], "r")) && fgets(hashbangbuf, sizeof(hashbangbuf), fp) && strncmp(hashbangbuf, "#!", 2) == 0 && (p=strchr(hashbangbuf, '\n'))) { *p = '\0'; p = hashbangbuf + 2; while (*p == ' ') p++; - cur_interp = [NSString stringWithCString: p]; + cur_interp = [NSString stringWithUTF8String: p]; } if (!cur_interp) cur_interp = interpreter; From python-checkins at python.org Mon Mar 30 21:25:23 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 21:25:23 +0200 (CEST) Subject: [Python-checkins] r70736 - in python/branches/py3k: Mac/PythonLauncher/FileSettings.m Message-ID: <20090330192523.3469D1E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 21:25:21 2009 New Revision: 70736 Log: Merged revisions 70735 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70735 | ronald.oussoren | 2009-03-30 14:22:56 -0500 (Mon, 30 Mar 2009) | 3 lines Remove usage of the deprecated '-cString' and '+stringWithCString:' API's in PythonLauncher, replacing them with the correct counterparts. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Mac/PythonLauncher/FileSettings.m Modified: python/branches/py3k/Mac/PythonLauncher/FileSettings.m ============================================================================== --- python/branches/py3k/Mac/PythonLauncher/FileSettings.m (original) +++ python/branches/py3k/Mac/PythonLauncher/FileSettings.m Mon Mar 30 21:25:21 2009 @@ -267,14 +267,14 @@ [script length]-[[script lastPathComponent] length]]; if (honourhashbang && - (fp=fopen([script cString], "r")) && + (fp=fopen([script fileSystemRepresentation], "r")) && fgets(hashbangbuf, sizeof(hashbangbuf), fp) && strncmp(hashbangbuf, "#!", 2) == 0 && (p=strchr(hashbangbuf, '\n'))) { *p = '\0'; p = hashbangbuf + 2; while (*p == ' ') p++; - cur_interp = [NSString stringWithCString: p]; + cur_interp = [NSString stringWithUTF8String: p]; } if (!cur_interp) cur_interp = interpreter; From python-checkins at python.org Mon Mar 30 21:34:51 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 21:34:51 +0200 (CEST) Subject: [Python-checkins] r70737 - in python/trunk/Mac/BuildScript: README.txt build-installer.py Message-ID: <20090330193451.773F61E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 21:34:51 2009 New Revision: 70737 Log: * Set a custom icon on the Python installer DMG * Remove last traces of "MacPython" * Add options to build different flavors of the installer (still defaulting to a 2-way universal build that runs on OSX 10.3) Modified: python/trunk/Mac/BuildScript/README.txt python/trunk/Mac/BuildScript/build-installer.py Modified: python/trunk/Mac/BuildScript/README.txt ============================================================================== --- python/trunk/Mac/BuildScript/README.txt (original) +++ python/trunk/Mac/BuildScript/README.txt Mon Mar 30 21:34:51 2009 @@ -37,6 +37,17 @@ * When done the script will tell you where the DMG image is (by default somewhere in ``/tmp/_py``). +Building a 4-way universal installer +.................................... + +It is also possible to build a 4-way universal installer that runs on +OSX Leopard or later:: + + $ ./build-installer.py --dep-target=10.5 --universal-archs=all --sdk=/ + +This requires that the deployment target is 10.5 (or later), and hence +also that your building on at least OSX 10.5. + Testing ------- Modified: python/trunk/Mac/BuildScript/build-installer.py ============================================================================== --- python/trunk/Mac/BuildScript/build-installer.py (original) +++ python/trunk/Mac/BuildScript/build-installer.py Mon Mar 30 21:34:51 2009 @@ -2,7 +2,8 @@ """ This script is used to build the "official unofficial" universal build on Mac OS X. It requires Mac OS X 10.4, Xcode 2.2 and the 10.4u SDK to do its -work. +work. 64-bit or four-way universal builds require at least OS X 10.5 and +the 10.5 SDK. Please ensure that this script keeps working with Python 2.3, to avoid bootstrap issues (/usr/bin/python is Python 2.3 on OSX 10.4) @@ -63,7 +64,15 @@ SDKPATH = "/Developer/SDKs/MacOSX10.4u.sdk" #SDKPATH = "/" -ARCHLIST = ('i386', 'ppc',) +universal_opts_map = { '32-bit': ('i386', 'ppc',), + '64-bit': ('x86_64', 'ppc64',), + 'all': ('i386', 'ppc', 'x86_64', 'ppc64',) } + +UNIVERSALOPTS = tuple(universal_opts_map.keys()) + +UNIVERSALARCHS = '32-bit' + +ARCHLIST = universal_opts_map[UNIVERSALARCHS] # Source directory (asume we're in Mac/BuildScript) SRCDIR = os.path.dirname( @@ -72,6 +81,9 @@ os.path.abspath(__file__ )))) +# $MACOSX_DEPLOYMENT_TARGET -> minimum OS X level +DEPTARGET = '10.3' + USAGE = textwrap.dedent("""\ Usage: build_python [options] @@ -82,103 +94,108 @@ --third-party=DIR: Store third-party sources here (default: %(DEPSRC)r) --sdk-path=DIR: Location of the SDK (default: %(SDKPATH)r) --src-dir=DIR: Location of the Python sources (default: %(SRCDIR)r) + --dep-target=10.n OS X deployment target (default: %(DEPTARGET)r) + --universal-archs=x universal architectures (options: %(UNIVERSALOPTS)r, default: %(UNIVERSALARCHS)r) """)% globals() # Instructions for building libraries that are necessary for building a # batteries included python. -LIBRARY_RECIPES = [ - dict( - name="Bzip2 1.0.4", - url="http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz", - checksum='fc310b254f6ba5fbb5da018f04533688', - configure=None, - install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( - shellQuote(os.path.join(WORKDIR, 'libraries')), - ' -arch '.join(ARCHLIST), - SDKPATH, - ), - ), - dict( - name="ZLib 1.2.3", - url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz", - checksum='debc62758716a169df9f62e6ab2bc634', - configure=None, - install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( - shellQuote(os.path.join(WORKDIR, 'libraries')), - ' -arch '.join(ARCHLIST), - SDKPATH, - ), - ), - dict( - # Note that GNU readline is GPL'd software - name="GNU Readline 5.1.4", - url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" , - checksum='7ee5a692db88b30ca48927a13fd60e46', - patchlevel='0', - patches=[ - # The readline maintainers don't do actual micro releases, but - # just ship a set of patches. - 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-001', - 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-002', - 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-003', - 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-004', - ] - ), - - dict( - name="SQLite 3.6.11", - url="http://www.sqlite.org/sqlite-3.6.11.tar.gz", - checksum='7ebb099696ab76cc6ff65dd496d17858', - configure_pre=[ - '--enable-threadsafe', - '--enable-tempstore', - '--enable-shared=no', - '--enable-static=yes', - '--disable-tcl', - ] - ), - - dict( - name="NCurses 5.5", - url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz", - checksum='e73c1ac10b4bfc46db43b2ddfd6244ef', - configure_pre=[ - "--without-cxx", - "--without-ada", - "--without-progs", - "--without-curses-h", - "--enable-shared", - "--with-shared", - "--datadir=/usr/share", - "--sysconfdir=/etc", - "--sharedstatedir=/usr/com", - "--with-terminfo-dirs=/usr/share/terminfo", - "--with-default-terminfo-dir=/usr/share/terminfo", - "--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib"%(getVersion(),), - "--enable-termcap", - ], - patches=[ - "ncurses-5.5.patch", - ], - useLDFlags=False, - install='make && make install DESTDIR=%s && cd %s/usr/local/lib && ln -fs ../../../Library/Frameworks/Python.framework/Versions/%s/lib/lib* .'%( - shellQuote(os.path.join(WORKDIR, 'libraries')), - shellQuote(os.path.join(WORKDIR, 'libraries')), - getVersion(), - ), - ), - dict( - name="Sleepycat DB 4.7.25", - url="http://download.oracle.com/berkeley-db/db-4.7.25.tar.gz", - checksum='ec2b87e833779681a0c3a814aa71359e', - buildDir="build_unix", - configure="../dist/configure", - configure_pre=[ - '--includedir=/usr/local/include/db4', - ] - ), -] +# [The recipes are defined here for convenience but instantiated later after +# command line options have been processed.] +def library_recipes(): + return [ + dict( + name="Bzip2 1.0.4", + url="http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz", + checksum='fc310b254f6ba5fbb5da018f04533688', + configure=None, + install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( + shellQuote(os.path.join(WORKDIR, 'libraries')), + ' -arch '.join(ARCHLIST), + SDKPATH, + ), + ), + dict( + name="ZLib 1.2.3", + url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz", + checksum='debc62758716a169df9f62e6ab2bc634', + configure=None, + install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( + shellQuote(os.path.join(WORKDIR, 'libraries')), + ' -arch '.join(ARCHLIST), + SDKPATH, + ), + ), + dict( + # Note that GNU readline is GPL'd software + name="GNU Readline 5.1.4", + url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" , + checksum='7ee5a692db88b30ca48927a13fd60e46', + patchlevel='0', + patches=[ + # The readline maintainers don't do actual micro releases, but + # just ship a set of patches. + 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-001', + 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-002', + 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-003', + 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-004', + ] + ), + + dict( + name="SQLite 3.6.11", + url="http://www.sqlite.org/sqlite-3.6.11.tar.gz", + checksum='7ebb099696ab76cc6ff65dd496d17858', + configure_pre=[ + '--enable-threadsafe', + '--enable-tempstore', + '--enable-shared=no', + '--enable-static=yes', + '--disable-tcl', + ] + ), + + dict( + name="NCurses 5.5", + url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz", + checksum='e73c1ac10b4bfc46db43b2ddfd6244ef', + configure_pre=[ + "--without-cxx", + "--without-ada", + "--without-progs", + "--without-curses-h", + "--enable-shared", + "--with-shared", + "--datadir=/usr/share", + "--sysconfdir=/etc", + "--sharedstatedir=/usr/com", + "--with-terminfo-dirs=/usr/share/terminfo", + "--with-default-terminfo-dir=/usr/share/terminfo", + "--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib"%(getVersion(),), + "--enable-termcap", + ], + patches=[ + "ncurses-5.5.patch", + ], + useLDFlags=False, + install='make && make install DESTDIR=%s && cd %s/usr/local/lib && ln -fs ../../../Library/Frameworks/Python.framework/Versions/%s/lib/lib* .'%( + shellQuote(os.path.join(WORKDIR, 'libraries')), + shellQuote(os.path.join(WORKDIR, 'libraries')), + getVersion(), + ), + ), + dict( + name="Sleepycat DB 4.7.25", + url="http://download.oracle.com/berkeley-db/db-4.7.25.tar.gz", + checksum='ec2b87e833779681a0c3a814aa71359e', + buildDir="build_unix", + configure="../dist/configure", + configure_pre=[ + '--includedir=/usr/local/include/db4', + ] + ), + ] # Instructions for building packages inside the .mpkg. @@ -213,8 +230,8 @@ source="/usr/local/bin", readme="""\ This package installs the unix tools in /usr/local/bin for - compatibility with older releases of MacPython. This package - is not necessary to use MacPython. + compatibility with older releases of Python. This package + is not necessary to use Python. """, required=False, ), @@ -237,7 +254,7 @@ long_name="Shell profile updater", readme="""\ This packages updates your shell profile to make sure that - the MacPython tools are found by your shell in preference of + the Python tools are found by your shell in preference of the system provided Python tools. If you don't install this package you'll have to add @@ -325,14 +342,16 @@ """ Parse arguments and update global settings. """ - global WORKDIR, DEPSRC, SDKPATH, SRCDIR + global WORKDIR, DEPSRC, SDKPATH, SRCDIR, DEPTARGET + global UNIVERSALOPTS, UNIVERSALARCHS, ARCHLIST if args is None: args = sys.argv[1:] try: options, args = getopt.getopt(args, '?hb', - [ 'build-dir=', 'third-party=', 'sdk-path=' , 'src-dir=']) + [ 'build-dir=', 'third-party=', 'sdk-path=' , 'src-dir=', + 'dep-target=', 'universal-archs=', 'help' ]) except getopt.error, msg: print msg sys.exit(1) @@ -342,7 +361,7 @@ sys.exit(1) for k, v in options: - if k in ('-h', '-?'): + if k in ('-h', '-?', '--help'): print USAGE sys.exit(0) @@ -358,6 +377,16 @@ elif k in ('--src-dir',): SRCDIR=v + elif k in ('--dep-target', ): + DEPTARGET=v + + elif k in ('--universal-archs', ): + if v in UNIVERSALOPTS: + UNIVERSALARCHS = v + ARCHLIST = universal_opts_map[UNIVERSALARCHS] + else: + raise NotImplementedError, v + else: raise NotImplementedError, k @@ -370,7 +399,9 @@ print " * Source directory:", SRCDIR print " * Build directory: ", WORKDIR print " * SDK location: ", SDKPATH - print " * third-party source:", DEPSRC + print " * Third-party source:", DEPSRC + print " * Deployment target:", DEPTARGET + print " * Universal architectures:", ARCHLIST print "" @@ -480,6 +511,7 @@ print "Using local copy of %s"%(name,) else: + print "Did not find local copy of %s"%(name,) print "Downloading %s"%(name,) downloadURL(url, sourceArchive) print "Archive for %s stored as %s"%(name, sourceArchive) @@ -570,7 +602,7 @@ os.makedirs(os.path.join(universal, 'usr', 'local', 'lib')) os.makedirs(os.path.join(universal, 'usr', 'local', 'include')) - for recipe in LIBRARY_RECIPES: + for recipe in library_recipes(): buildRecipe(recipe, universal, ARCHLIST) @@ -594,7 +626,7 @@ def buildPython(): - print "Building a universal python" + print "Building a universal python for %s architectures" % UNIVERSALARCHS buildDir = os.path.join(WORKDIR, '_bld', 'python') rootDir = os.path.join(WORKDIR, '_root') @@ -618,9 +650,13 @@ version = getVersion() print "Running configure..." - runCommand("%s -C --enable-framework --enable-universalsdk=%s LDFLAGS='-g -L%s/libraries/usr/local/lib' OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%( - shellQuote(os.path.join(SRCDIR, 'configure')), - shellQuote(SDKPATH), shellQuote(WORKDIR)[1:-1], + runCommand("%s -C --enable-framework --enable-universalsdk=%s " + "--with-universal-archs=%s " + "LDFLAGS='-g -L%s/libraries/usr/local/lib' " + "OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%( + shellQuote(os.path.join(SRCDIR, 'configure')), shellQuote(SDKPATH), + UNIVERSALARCHS, + shellQuote(WORKDIR)[1:-1], shellQuote(WORKDIR)[1:-1])) print "Running make" @@ -701,7 +737,7 @@ data = fileContents(inPath) data = data.replace('$FULL_VERSION', getFullVersion()) data = data.replace('$VERSION', getVersion()) - data = data.replace('$MACOSX_DEPLOYMENT_TARGET', '10.3 or later') + data = data.replace('$MACOSX_DEPLOYMENT_TARGET', ''.join((DEPTARGET, ' or later'))) data = data.replace('$ARCHITECTURES', "i386, ppc") data = data.replace('$INSTALL_SIZE', installSize()) @@ -781,9 +817,9 @@ vers = getFullVersion() major, minor = map(int, getVersion().split('.', 2)) pl = Plist( - CFBundleGetInfoString="MacPython.%s %s"%(pkgname, vers,), - CFBundleIdentifier='org.python.MacPython.%s'%(pkgname,), - CFBundleName='MacPython.%s'%(pkgname,), + CFBundleGetInfoString="Python.%s %s"%(pkgname, vers,), + CFBundleIdentifier='org.python.Python.%s'%(pkgname,), + CFBundleName='Python.%s'%(pkgname,), CFBundleShortVersionString=vers, IFMajorVersion=major, IFMinorVersion=minor, @@ -804,7 +840,7 @@ pl = Plist( IFPkgDescriptionDescription=readme, - IFPkgDescriptionTitle=recipe.get('long_name', "MacPython.%s"%(pkgname,)), + IFPkgDescriptionTitle=recipe.get('long_name', "Python.%s"%(pkgname,)), IFPkgDescriptionVersion=vers, ) writePlist(pl, os.path.join(packageContents, 'Resources', 'Description.plist')) @@ -819,9 +855,9 @@ major, minor = map(int, getVersion().split('.', 2)) pl = Plist( - CFBundleGetInfoString="MacPython %s"%(vers,), - CFBundleIdentifier='org.python.MacPython', - CFBundleName='MacPython', + CFBundleGetInfoString="Python %s"%(vers,), + CFBundleIdentifier='org.python.Python', + CFBundleName='Python', CFBundleShortVersionString=vers, IFMajorVersion=major, IFMinorVersion=minor, @@ -855,7 +891,7 @@ shutil.rmtree(outdir) os.mkdir(outdir) - pkgroot = os.path.join(outdir, 'MacPython.mpkg', 'Contents') + pkgroot = os.path.join(outdir, 'Python.mpkg', 'Contents') pkgcontents = os.path.join(pkgroot, 'Packages') os.makedirs(pkgcontents) for recipe in PKG_RECIPES: @@ -872,7 +908,7 @@ makeMpkgPlist(os.path.join(pkgroot, 'Info.plist')) pl = Plist( - IFPkgDescriptionTitle="Universal MacPython", + IFPkgDescriptionTitle="Python", IFPkgDescriptionVersion=getVersion(), ) @@ -912,10 +948,32 @@ imagepath = imagepath + '.dmg' os.mkdir(outdir) - runCommand("hdiutil create -volname 'Universal MacPython %s' -srcfolder %s %s"%( - getFullVersion(), + volname='Python %s'%(getFullVersion()) + runCommand("hdiutil create -format UDRW -volname %s -srcfolder %s %s"%( + shellQuote(volname), shellQuote(os.path.join(WORKDIR, 'installer')), - shellQuote(imagepath))) + shellQuote(imagepath + ".tmp.dmg" ))) + + + if not os.path.exists(os.path.join(WORKDIR, "mnt")): + os.mkdir(os.path.join(WORKDIR, "mnt")) + runCommand("hdiutil attach %s -mountroot %s"%( + shellQuote(imagepath + ".tmp.dmg"), shellQuote(os.path.join(WORKDIR, "mnt")))) + + # Custom icon for the DMG, shown when the DMG is mounted. + shutil.copy("../Icons/Disk Image.icns", + os.path.join(WORKDIR, "mnt", volname, ".VolumeIcon.icns")) + runCommand("/Developer/Tools/SetFile -a C %s/"%( + shellQuote(os.path.join(WORKDIR, "mnt", volname)),)) + + runCommand("hdiutil detach %s"%(shellQuote(os.path.join(WORKDIR, "mnt", volname)))) + + setIcon(imagepath + ".tmp.dmg", "../Icons/Disk Image.icns") + runCommand("hdiutil convert %s -format UDZO -o %s"%( + shellQuote(imagepath + ".tmp.dmg"), shellQuote(imagepath))) + setIcon(imagepath, "../Icons/Disk Image.icns") + + os.unlink(imagepath + ".tmp.dmg") return imagepath @@ -943,7 +1001,7 @@ parseOptions() checkEnvironment() - os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.3' + os.environ['MACOSX_DEPLOYMENT_TARGET'] = DEPTARGET if os.path.exists(WORKDIR): shutil.rmtree(WORKDIR) @@ -979,13 +1037,6 @@ print >> fp, "# By:", pwd.getpwuid(os.getuid()).pw_gecos fp.close() - # Custom icon for the DMG, shown when the DMG is mounted. - # XXX: Code is diabled because it doesn't actually work :-( -# shutil.copy("../Icons/Disk Image.icns", -# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns")) -# os.system("/Developer/Tools/SetFile -a C %s"%( -# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns"))) - setIcon(os.path.join(WORKDIR, "installer"), "../Icons/Disk Image.icns") # And copy it to a DMG From python-checkins at python.org Mon Mar 30 21:37:10 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 21:37:10 +0200 (CEST) Subject: [Python-checkins] r70738 - in python/branches/release26-maint: Mac/BuildScript/README.txt Mac/BuildScript/build-installer.py Message-ID: <20090330193710.EF2461E400C@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 21:37:10 2009 New Revision: 70738 Log: Merged revisions 70737 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70737 | ronald.oussoren | 2009-03-30 14:34:51 -0500 (Mon, 30 Mar 2009) | 6 lines * Set a custom icon on the Python installer DMG * Remove last traces of "MacPython" * Add options to build different flavors of the installer (still defaulting to a 2-way universal build that runs on OSX 10.3) ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Mac/BuildScript/README.txt python/branches/release26-maint/Mac/BuildScript/build-installer.py Modified: python/branches/release26-maint/Mac/BuildScript/README.txt ============================================================================== --- python/branches/release26-maint/Mac/BuildScript/README.txt (original) +++ python/branches/release26-maint/Mac/BuildScript/README.txt Mon Mar 30 21:37:10 2009 @@ -37,6 +37,17 @@ * When done the script will tell you where the DMG image is (by default somewhere in ``/tmp/_py``). +Building a 4-way universal installer +.................................... + +It is also possible to build a 4-way universal installer that runs on +OSX Leopard or later:: + + $ ./build-installer.py --dep-target=10.5 --universal-archs=all --sdk=/ + +This requires that the deployment target is 10.5 (or later), and hence +also that your building on at least OSX 10.5. + Testing ------- Modified: python/branches/release26-maint/Mac/BuildScript/build-installer.py ============================================================================== --- python/branches/release26-maint/Mac/BuildScript/build-installer.py (original) +++ python/branches/release26-maint/Mac/BuildScript/build-installer.py Mon Mar 30 21:37:10 2009 @@ -2,7 +2,8 @@ """ This script is used to build the "official unofficial" universal build on Mac OS X. It requires Mac OS X 10.4, Xcode 2.2 and the 10.4u SDK to do its -work. +work. 64-bit or four-way universal builds require at least OS X 10.5 and +the 10.5 SDK. Please ensure that this script keeps working with Python 2.3, to avoid bootstrap issues (/usr/bin/python is Python 2.3 on OSX 10.4) @@ -63,7 +64,15 @@ SDKPATH = "/Developer/SDKs/MacOSX10.4u.sdk" #SDKPATH = "/" -ARCHLIST = ('i386', 'ppc',) +universal_opts_map = { '32-bit': ('i386', 'ppc',), + '64-bit': ('x86_64', 'ppc64',), + 'all': ('i386', 'ppc', 'x86_64', 'ppc64',) } + +UNIVERSALOPTS = tuple(universal_opts_map.keys()) + +UNIVERSALARCHS = '32-bit' + +ARCHLIST = universal_opts_map[UNIVERSALARCHS] # Source directory (asume we're in Mac/BuildScript) SRCDIR = os.path.dirname( @@ -72,6 +81,9 @@ os.path.abspath(__file__ )))) +# $MACOSX_DEPLOYMENT_TARGET -> minimum OS X level +DEPTARGET = '10.3' + USAGE = textwrap.dedent("""\ Usage: build_python [options] @@ -82,103 +94,108 @@ --third-party=DIR: Store third-party sources here (default: %(DEPSRC)r) --sdk-path=DIR: Location of the SDK (default: %(SDKPATH)r) --src-dir=DIR: Location of the Python sources (default: %(SRCDIR)r) + --dep-target=10.n OS X deployment target (default: %(DEPTARGET)r) + --universal-archs=x universal architectures (options: %(UNIVERSALOPTS)r, default: %(UNIVERSALARCHS)r) """)% globals() # Instructions for building libraries that are necessary for building a # batteries included python. -LIBRARY_RECIPES = [ - dict( - name="Bzip2 1.0.4", - url="http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz", - checksum='fc310b254f6ba5fbb5da018f04533688', - configure=None, - install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( - shellQuote(os.path.join(WORKDIR, 'libraries')), - ' -arch '.join(ARCHLIST), - SDKPATH, - ), - ), - dict( - name="ZLib 1.2.3", - url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz", - checksum='debc62758716a169df9f62e6ab2bc634', - configure=None, - install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( - shellQuote(os.path.join(WORKDIR, 'libraries')), - ' -arch '.join(ARCHLIST), - SDKPATH, - ), - ), - dict( - # Note that GNU readline is GPL'd software - name="GNU Readline 5.1.4", - url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" , - checksum='7ee5a692db88b30ca48927a13fd60e46', - patchlevel='0', - patches=[ - # The readline maintainers don't do actual micro releases, but - # just ship a set of patches. - 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-001', - 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-002', - 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-003', - 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-004', - ] - ), - - dict( - name="SQLite 3.6.11", - url="http://www.sqlite.org/sqlite-3.6.11.tar.gz", - checksum='7ebb099696ab76cc6ff65dd496d17858', - configure_pre=[ - '--enable-threadsafe', - '--enable-tempstore', - '--enable-shared=no', - '--enable-static=yes', - '--disable-tcl', - ] - ), - - dict( - name="NCurses 5.5", - url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz", - checksum='e73c1ac10b4bfc46db43b2ddfd6244ef', - configure_pre=[ - "--without-cxx", - "--without-ada", - "--without-progs", - "--without-curses-h", - "--enable-shared", - "--with-shared", - "--datadir=/usr/share", - "--sysconfdir=/etc", - "--sharedstatedir=/usr/com", - "--with-terminfo-dirs=/usr/share/terminfo", - "--with-default-terminfo-dir=/usr/share/terminfo", - "--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib"%(getVersion(),), - "--enable-termcap", - ], - patches=[ - "ncurses-5.5.patch", - ], - useLDFlags=False, - install='make && make install DESTDIR=%s && cd %s/usr/local/lib && ln -fs ../../../Library/Frameworks/Python.framework/Versions/%s/lib/lib* .'%( - shellQuote(os.path.join(WORKDIR, 'libraries')), - shellQuote(os.path.join(WORKDIR, 'libraries')), - getVersion(), - ), - ), - dict( - name="Sleepycat DB 4.7.25", - url="http://download.oracle.com/berkeley-db/db-4.7.25.tar.gz", - checksum='ec2b87e833779681a0c3a814aa71359e', - buildDir="build_unix", - configure="../dist/configure", - configure_pre=[ - '--includedir=/usr/local/include/db4', - ] - ), -] +# [The recipes are defined here for convenience but instantiated later after +# command line options have been processed.] +def library_recipes(): + return [ + dict( + name="Bzip2 1.0.4", + url="http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz", + checksum='fc310b254f6ba5fbb5da018f04533688', + configure=None, + install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( + shellQuote(os.path.join(WORKDIR, 'libraries')), + ' -arch '.join(ARCHLIST), + SDKPATH, + ), + ), + dict( + name="ZLib 1.2.3", + url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz", + checksum='debc62758716a169df9f62e6ab2bc634', + configure=None, + install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( + shellQuote(os.path.join(WORKDIR, 'libraries')), + ' -arch '.join(ARCHLIST), + SDKPATH, + ), + ), + dict( + # Note that GNU readline is GPL'd software + name="GNU Readline 5.1.4", + url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" , + checksum='7ee5a692db88b30ca48927a13fd60e46', + patchlevel='0', + patches=[ + # The readline maintainers don't do actual micro releases, but + # just ship a set of patches. + 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-001', + 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-002', + 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-003', + 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-004', + ] + ), + + dict( + name="SQLite 3.6.11", + url="http://www.sqlite.org/sqlite-3.6.11.tar.gz", + checksum='7ebb099696ab76cc6ff65dd496d17858', + configure_pre=[ + '--enable-threadsafe', + '--enable-tempstore', + '--enable-shared=no', + '--enable-static=yes', + '--disable-tcl', + ] + ), + + dict( + name="NCurses 5.5", + url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz", + checksum='e73c1ac10b4bfc46db43b2ddfd6244ef', + configure_pre=[ + "--without-cxx", + "--without-ada", + "--without-progs", + "--without-curses-h", + "--enable-shared", + "--with-shared", + "--datadir=/usr/share", + "--sysconfdir=/etc", + "--sharedstatedir=/usr/com", + "--with-terminfo-dirs=/usr/share/terminfo", + "--with-default-terminfo-dir=/usr/share/terminfo", + "--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib"%(getVersion(),), + "--enable-termcap", + ], + patches=[ + "ncurses-5.5.patch", + ], + useLDFlags=False, + install='make && make install DESTDIR=%s && cd %s/usr/local/lib && ln -fs ../../../Library/Frameworks/Python.framework/Versions/%s/lib/lib* .'%( + shellQuote(os.path.join(WORKDIR, 'libraries')), + shellQuote(os.path.join(WORKDIR, 'libraries')), + getVersion(), + ), + ), + dict( + name="Sleepycat DB 4.7.25", + url="http://download.oracle.com/berkeley-db/db-4.7.25.tar.gz", + checksum='ec2b87e833779681a0c3a814aa71359e', + buildDir="build_unix", + configure="../dist/configure", + configure_pre=[ + '--includedir=/usr/local/include/db4', + ] + ), + ] # Instructions for building packages inside the .mpkg. @@ -213,8 +230,8 @@ source="/usr/local/bin", readme="""\ This package installs the unix tools in /usr/local/bin for - compatibility with older releases of MacPython. This package - is not necessary to use MacPython. + compatibility with older releases of Python. This package + is not necessary to use Python. """, required=False, ), @@ -237,7 +254,7 @@ long_name="Shell profile updater", readme="""\ This packages updates your shell profile to make sure that - the MacPython tools are found by your shell in preference of + the Python tools are found by your shell in preference of the system provided Python tools. If you don't install this package you'll have to add @@ -325,14 +342,16 @@ """ Parse arguments and update global settings. """ - global WORKDIR, DEPSRC, SDKPATH, SRCDIR + global WORKDIR, DEPSRC, SDKPATH, SRCDIR, DEPTARGET + global UNIVERSALOPTS, UNIVERSALARCHS, ARCHLIST if args is None: args = sys.argv[1:] try: options, args = getopt.getopt(args, '?hb', - [ 'build-dir=', 'third-party=', 'sdk-path=' , 'src-dir=']) + [ 'build-dir=', 'third-party=', 'sdk-path=' , 'src-dir=', + 'dep-target=', 'universal-archs=', 'help' ]) except getopt.error, msg: print msg sys.exit(1) @@ -342,7 +361,7 @@ sys.exit(1) for k, v in options: - if k in ('-h', '-?'): + if k in ('-h', '-?', '--help'): print USAGE sys.exit(0) @@ -358,6 +377,16 @@ elif k in ('--src-dir',): SRCDIR=v + elif k in ('--dep-target', ): + DEPTARGET=v + + elif k in ('--universal-archs', ): + if v in UNIVERSALOPTS: + UNIVERSALARCHS = v + ARCHLIST = universal_opts_map[UNIVERSALARCHS] + else: + raise NotImplementedError, v + else: raise NotImplementedError, k @@ -370,7 +399,9 @@ print " * Source directory:", SRCDIR print " * Build directory: ", WORKDIR print " * SDK location: ", SDKPATH - print " * third-party source:", DEPSRC + print " * Third-party source:", DEPSRC + print " * Deployment target:", DEPTARGET + print " * Universal architectures:", ARCHLIST print "" @@ -480,6 +511,7 @@ print "Using local copy of %s"%(name,) else: + print "Did not find local copy of %s"%(name,) print "Downloading %s"%(name,) downloadURL(url, sourceArchive) print "Archive for %s stored as %s"%(name, sourceArchive) @@ -570,7 +602,7 @@ os.makedirs(os.path.join(universal, 'usr', 'local', 'lib')) os.makedirs(os.path.join(universal, 'usr', 'local', 'include')) - for recipe in LIBRARY_RECIPES: + for recipe in library_recipes(): buildRecipe(recipe, universal, ARCHLIST) @@ -594,7 +626,7 @@ def buildPython(): - print "Building a universal python" + print "Building a universal python for %s architectures" % UNIVERSALARCHS buildDir = os.path.join(WORKDIR, '_bld', 'python') rootDir = os.path.join(WORKDIR, '_root') @@ -618,9 +650,13 @@ version = getVersion() print "Running configure..." - runCommand("%s -C --enable-framework --enable-universalsdk=%s LDFLAGS='-g -L%s/libraries/usr/local/lib' OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%( - shellQuote(os.path.join(SRCDIR, 'configure')), - shellQuote(SDKPATH), shellQuote(WORKDIR)[1:-1], + runCommand("%s -C --enable-framework --enable-universalsdk=%s " + "--with-universal-archs=%s " + "LDFLAGS='-g -L%s/libraries/usr/local/lib' " + "OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%( + shellQuote(os.path.join(SRCDIR, 'configure')), shellQuote(SDKPATH), + UNIVERSALARCHS, + shellQuote(WORKDIR)[1:-1], shellQuote(WORKDIR)[1:-1])) print "Running make" @@ -701,7 +737,7 @@ data = fileContents(inPath) data = data.replace('$FULL_VERSION', getFullVersion()) data = data.replace('$VERSION', getVersion()) - data = data.replace('$MACOSX_DEPLOYMENT_TARGET', '10.3 or later') + data = data.replace('$MACOSX_DEPLOYMENT_TARGET', ''.join((DEPTARGET, ' or later'))) data = data.replace('$ARCHITECTURES', "i386, ppc") data = data.replace('$INSTALL_SIZE', installSize()) @@ -781,9 +817,9 @@ vers = getFullVersion() major, minor = map(int, getVersion().split('.', 2)) pl = Plist( - CFBundleGetInfoString="MacPython.%s %s"%(pkgname, vers,), - CFBundleIdentifier='org.python.MacPython.%s'%(pkgname,), - CFBundleName='MacPython.%s'%(pkgname,), + CFBundleGetInfoString="Python.%s %s"%(pkgname, vers,), + CFBundleIdentifier='org.python.Python.%s'%(pkgname,), + CFBundleName='Python.%s'%(pkgname,), CFBundleShortVersionString=vers, IFMajorVersion=major, IFMinorVersion=minor, @@ -804,7 +840,7 @@ pl = Plist( IFPkgDescriptionDescription=readme, - IFPkgDescriptionTitle=recipe.get('long_name', "MacPython.%s"%(pkgname,)), + IFPkgDescriptionTitle=recipe.get('long_name', "Python.%s"%(pkgname,)), IFPkgDescriptionVersion=vers, ) writePlist(pl, os.path.join(packageContents, 'Resources', 'Description.plist')) @@ -819,9 +855,9 @@ major, minor = map(int, getVersion().split('.', 2)) pl = Plist( - CFBundleGetInfoString="MacPython %s"%(vers,), - CFBundleIdentifier='org.python.MacPython', - CFBundleName='MacPython', + CFBundleGetInfoString="Python %s"%(vers,), + CFBundleIdentifier='org.python.Python', + CFBundleName='Python', CFBundleShortVersionString=vers, IFMajorVersion=major, IFMinorVersion=minor, @@ -855,7 +891,7 @@ shutil.rmtree(outdir) os.mkdir(outdir) - pkgroot = os.path.join(outdir, 'MacPython.mpkg', 'Contents') + pkgroot = os.path.join(outdir, 'Python.mpkg', 'Contents') pkgcontents = os.path.join(pkgroot, 'Packages') os.makedirs(pkgcontents) for recipe in PKG_RECIPES: @@ -872,7 +908,7 @@ makeMpkgPlist(os.path.join(pkgroot, 'Info.plist')) pl = Plist( - IFPkgDescriptionTitle="Universal MacPython", + IFPkgDescriptionTitle="Python", IFPkgDescriptionVersion=getVersion(), ) @@ -912,10 +948,32 @@ imagepath = imagepath + '.dmg' os.mkdir(outdir) - runCommand("hdiutil create -volname 'Universal MacPython %s' -srcfolder %s %s"%( - getFullVersion(), + volname='Python %s'%(getFullVersion()) + runCommand("hdiutil create -format UDRW -volname %s -srcfolder %s %s"%( + shellQuote(volname), shellQuote(os.path.join(WORKDIR, 'installer')), - shellQuote(imagepath))) + shellQuote(imagepath + ".tmp.dmg" ))) + + + if not os.path.exists(os.path.join(WORKDIR, "mnt")): + os.mkdir(os.path.join(WORKDIR, "mnt")) + runCommand("hdiutil attach %s -mountroot %s"%( + shellQuote(imagepath + ".tmp.dmg"), shellQuote(os.path.join(WORKDIR, "mnt")))) + + # Custom icon for the DMG, shown when the DMG is mounted. + shutil.copy("../Icons/Disk Image.icns", + os.path.join(WORKDIR, "mnt", volname, ".VolumeIcon.icns")) + runCommand("/Developer/Tools/SetFile -a C %s/"%( + shellQuote(os.path.join(WORKDIR, "mnt", volname)),)) + + runCommand("hdiutil detach %s"%(shellQuote(os.path.join(WORKDIR, "mnt", volname)))) + + setIcon(imagepath + ".tmp.dmg", "../Icons/Disk Image.icns") + runCommand("hdiutil convert %s -format UDZO -o %s"%( + shellQuote(imagepath + ".tmp.dmg"), shellQuote(imagepath))) + setIcon(imagepath, "../Icons/Disk Image.icns") + + os.unlink(imagepath + ".tmp.dmg") return imagepath @@ -943,7 +1001,7 @@ parseOptions() checkEnvironment() - os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.3' + os.environ['MACOSX_DEPLOYMENT_TARGET'] = DEPTARGET if os.path.exists(WORKDIR): shutil.rmtree(WORKDIR) @@ -979,13 +1037,6 @@ print >> fp, "# By:", pwd.getpwuid(os.getuid()).pw_gecos fp.close() - # Custom icon for the DMG, shown when the DMG is mounted. - # XXX: Code is diabled because it doesn't actually work :-( -# shutil.copy("../Icons/Disk Image.icns", -# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns")) -# os.system("/Developer/Tools/SetFile -a C %s"%( -# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns"))) - setIcon(os.path.join(WORKDIR, "installer"), "../Icons/Disk Image.icns") # And copy it to a DMG From python-checkins at python.org Mon Mar 30 21:39:14 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 21:39:14 +0200 (CEST) Subject: [Python-checkins] r70739 - in python/branches/py3k: Mac/BuildScript/README.txt Mac/BuildScript/build-installer.py Message-ID: <20090330193914.DFBD01E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 21:39:14 2009 New Revision: 70739 Log: Merged revisions 70737 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70737 | ronald.oussoren | 2009-03-30 14:34:51 -0500 (Mon, 30 Mar 2009) | 6 lines * Set a custom icon on the Python installer DMG * Remove last traces of "MacPython" * Add options to build different flavors of the installer (still defaulting to a 2-way universal build that runs on OSX 10.3) ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Mac/BuildScript/README.txt python/branches/py3k/Mac/BuildScript/build-installer.py Modified: python/branches/py3k/Mac/BuildScript/README.txt ============================================================================== --- python/branches/py3k/Mac/BuildScript/README.txt (original) +++ python/branches/py3k/Mac/BuildScript/README.txt Mon Mar 30 21:39:14 2009 @@ -37,6 +37,17 @@ * When done the script will tell you where the DMG image is (by default somewhere in ``/tmp/_py``). +Building a 4-way universal installer +.................................... + +It is also possible to build a 4-way universal installer that runs on +OSX Leopard or later:: + + $ ./build-installer.py --dep-target=10.5 --universal-archs=all --sdk=/ + +This requires that the deployment target is 10.5 (or later), and hence +also that your building on at least OSX 10.5. + Testing ------- Modified: python/branches/py3k/Mac/BuildScript/build-installer.py ============================================================================== --- python/branches/py3k/Mac/BuildScript/build-installer.py (original) +++ python/branches/py3k/Mac/BuildScript/build-installer.py Mon Mar 30 21:39:14 2009 @@ -2,7 +2,8 @@ """ This script is used to build the "official unofficial" universal build on Mac OS X. It requires Mac OS X 10.4, Xcode 2.2 and the 10.4u SDK to do its -work. +work. 64-bit or four-way universal builds require at least OS X 10.5 and +the 10.5 SDK. Please ensure that this script keeps working with Python 2.3, to avoid bootstrap issues (/usr/bin/python is Python 2.3 on OSX 10.4) @@ -63,7 +64,15 @@ SDKPATH = "/Developer/SDKs/MacOSX10.4u.sdk" #SDKPATH = "/" -ARCHLIST = ('i386', 'ppc',) +universal_opts_map = { '32-bit': ('i386', 'ppc',), + '64-bit': ('x86_64', 'ppc64',), + 'all': ('i386', 'ppc', 'x86_64', 'ppc64',) } + +UNIVERSALOPTS = tuple(universal_opts_map.keys()) + +UNIVERSALARCHS = '32-bit' + +ARCHLIST = universal_opts_map[UNIVERSALARCHS] # Source directory (asume we're in Mac/BuildScript) SRCDIR = os.path.dirname( @@ -72,6 +81,9 @@ os.path.abspath(__file__ )))) +# $MACOSX_DEPLOYMENT_TARGET -> minimum OS X level +DEPTARGET = '10.3' + USAGE = textwrap.dedent("""\ Usage: build_python [options] @@ -82,62 +94,67 @@ --third-party=DIR: Store third-party sources here (default: %(DEPSRC)r) --sdk-path=DIR: Location of the SDK (default: %(SDKPATH)r) --src-dir=DIR: Location of the Python sources (default: %(SRCDIR)r) + --dep-target=10.n OS X deployment target (default: %(DEPTARGET)r) + --universal-archs=x universal architectures (options: %(UNIVERSALOPTS)r, default: %(UNIVERSALARCHS)r) """)% globals() # Instructions for building libraries that are necessary for building a # batteries included python. -LIBRARY_RECIPES = [ - dict( - name="Bzip2 1.0.4", - url="http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz", - checksum='fc310b254f6ba5fbb5da018f04533688', - configure=None, - install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( - shellQuote(os.path.join(WORKDIR, 'libraries')), - ' -arch '.join(ARCHLIST), - SDKPATH, - ), - ), - dict( - name="ZLib 1.2.3", - url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz", - checksum='debc62758716a169df9f62e6ab2bc634', - configure=None, - install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( - shellQuote(os.path.join(WORKDIR, 'libraries')), - ' -arch '.join(ARCHLIST), - SDKPATH, - ), - ), - dict( - # Note that GNU readline is GPL'd software - name="GNU Readline 5.1.4", - url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" , - checksum='7ee5a692db88b30ca48927a13fd60e46', - patchlevel='0', - patches=[ - # The readline maintainers don't do actual micro releases, but - # just ship a set of patches. - 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-001', - 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-002', - 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-003', - 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-004', - ] - ), - - dict( - name="SQLite 3.6.11", - url="http://www.sqlite.org/sqlite-3.6.11.tar.gz", - checksum='7ebb099696ab76cc6ff65dd496d17858', - configure_pre=[ - '--enable-threadsafe', - '--enable-tempstore', - '--enable-shared=no', - '--enable-static=yes', - '--disable-tcl', - ] - ), +# [The recipes are defined here for convenience but instantiated later after +# command line options have been processed.] +def library_recipes(): + return [ + dict( + name="Bzip2 1.0.4", + url="http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz", + checksum='fc310b254f6ba5fbb5da018f04533688', + configure=None, + install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( + shellQuote(os.path.join(WORKDIR, 'libraries')), + ' -arch '.join(ARCHLIST), + SDKPATH, + ), + ), + dict( + name="ZLib 1.2.3", + url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz", + checksum='debc62758716a169df9f62e6ab2bc634', + configure=None, + install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%( + shellQuote(os.path.join(WORKDIR, 'libraries')), + ' -arch '.join(ARCHLIST), + SDKPATH, + ), + ), + dict( + # Note that GNU readline is GPL'd software + name="GNU Readline 5.1.4", + url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" , + checksum='7ee5a692db88b30ca48927a13fd60e46', + patchlevel='0', + patches=[ + # The readline maintainers don't do actual micro releases, but + # just ship a set of patches. + 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-001', + 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-002', + 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-003', + 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-004', + ] + ), + + dict( + name="SQLite 3.6.11", + url="http://www.sqlite.org/sqlite-3.6.11.tar.gz", + checksum='7ebb099696ab76cc6ff65dd496d17858', + configure_pre=[ + '--enable-threadsafe', + '--enable-tempstore', + '--enable-shared=no', + '--enable-static=yes', + '--disable-tcl', + ] + ), dict( name="NCurses 5.5", @@ -170,7 +187,6 @@ ), ] - # Instructions for building packages inside the .mpkg. PKG_RECIPES = [ dict( @@ -205,8 +221,8 @@ source="/usr/local/bin", readme="""\ This package installs the unix tools in /usr/local/bin for - compatibility with older releases of MacPython. This package - is not necessary to use MacPython. + compatibility with older releases of Python. This package + is not necessary to use Python. """, required=False, selected='unselected', @@ -231,7 +247,7 @@ long_name="Shell profile updater", readme="""\ This packages updates your shell profile to make sure that - the MacPython tools are found by your shell in preference of + the Python tools are found by your shell in preference of the system provided Python tools. If you don't install this package you'll have to add @@ -321,14 +337,16 @@ """ Parse arguments and update global settings. """ - global WORKDIR, DEPSRC, SDKPATH, SRCDIR + global WORKDIR, DEPSRC, SDKPATH, SRCDIR, DEPTARGET + global UNIVERSALOPTS, UNIVERSALARCHS, ARCHLIST if args is None: args = sys.argv[1:] try: options, args = getopt.getopt(args, '?hb', - [ 'build-dir=', 'third-party=', 'sdk-path=' , 'src-dir=']) + [ 'build-dir=', 'third-party=', 'sdk-path=' , 'src-dir=', + 'dep-target=', 'universal-archs=', 'help' ]) except getopt.error, msg: print msg sys.exit(1) @@ -338,7 +356,7 @@ sys.exit(1) for k, v in options: - if k in ('-h', '-?'): + if k in ('-h', '-?', '--help'): print USAGE sys.exit(0) @@ -354,6 +372,16 @@ elif k in ('--src-dir',): SRCDIR=v + elif k in ('--dep-target', ): + DEPTARGET=v + + elif k in ('--universal-archs', ): + if v in UNIVERSALOPTS: + UNIVERSALARCHS = v + ARCHLIST = universal_opts_map[UNIVERSALARCHS] + else: + raise NotImplementedError, v + else: raise NotImplementedError, k @@ -366,7 +394,9 @@ print " * Source directory:", SRCDIR print " * Build directory: ", WORKDIR print " * SDK location: ", SDKPATH - print " * third-party source:", DEPSRC + print " * Third-party source:", DEPSRC + print " * Deployment target:", DEPTARGET + print " * Universal architectures:", ARCHLIST print "" @@ -476,6 +506,7 @@ print "Using local copy of %s"%(name,) else: + print "Did not find local copy of %s"%(name,) print "Downloading %s"%(name,) downloadURL(url, sourceArchive) print "Archive for %s stored as %s"%(name, sourceArchive) @@ -566,7 +597,7 @@ os.makedirs(os.path.join(universal, 'usr', 'local', 'lib')) os.makedirs(os.path.join(universal, 'usr', 'local', 'include')) - for recipe in LIBRARY_RECIPES: + for recipe in library_recipes(): buildRecipe(recipe, universal, ARCHLIST) @@ -590,7 +621,7 @@ def buildPython(): - print "Building a universal python" + print "Building a universal python for %s architectures" % UNIVERSALARCHS buildDir = os.path.join(WORKDIR, '_bld', 'python') rootDir = os.path.join(WORKDIR, '_root') @@ -614,9 +645,13 @@ version = getVersion() print "Running configure..." - runCommand("%s -C --enable-framework --enable-universalsdk=%s LDFLAGS='-g -L%s/libraries/usr/local/lib' OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%( - shellQuote(os.path.join(SRCDIR, 'configure')), - shellQuote(SDKPATH), shellQuote(WORKDIR)[1:-1], + runCommand("%s -C --enable-framework --enable-universalsdk=%s " + "--with-universal-archs=%s " + "LDFLAGS='-g -L%s/libraries/usr/local/lib' " + "OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%( + shellQuote(os.path.join(SRCDIR, 'configure')), shellQuote(SDKPATH), + UNIVERSALARCHS, + shellQuote(WORKDIR)[1:-1], shellQuote(WORKDIR)[1:-1])) print "Running make" @@ -704,7 +739,7 @@ data = fileContents(inPath) data = data.replace('$FULL_VERSION', getFullVersion()) data = data.replace('$VERSION', getVersion()) - data = data.replace('$MACOSX_DEPLOYMENT_TARGET', '10.3 or later') + data = data.replace('$MACOSX_DEPLOYMENT_TARGET', ''.join((DEPTARGET, ' or later'))) data = data.replace('$ARCHITECTURES', "i386, ppc") data = data.replace('$INSTALL_SIZE', installSize()) @@ -784,9 +819,9 @@ vers = getFullVersion() major, minor = map(int, getVersion().split('.', 2)) pl = Plist( - CFBundleGetInfoString="MacPython.%s %s"%(pkgname, vers,), - CFBundleIdentifier='org.python.MacPython.%s'%(pkgname,), - CFBundleName='MacPython.%s'%(pkgname,), + CFBundleGetInfoString="Python.%s %s"%(pkgname, vers,), + CFBundleIdentifier='org.python.Python.%s'%(pkgname,), + CFBundleName='Python.%s'%(pkgname,), CFBundleShortVersionString=vers, IFMajorVersion=major, IFMinorVersion=minor, @@ -807,7 +842,7 @@ pl = Plist( IFPkgDescriptionDescription=readme, - IFPkgDescriptionTitle=recipe.get('long_name', "MacPython.%s"%(pkgname,)), + IFPkgDescriptionTitle=recipe.get('long_name', "Python.%s"%(pkgname,)), IFPkgDescriptionVersion=vers, ) writePlist(pl, os.path.join(packageContents, 'Resources', 'Description.plist')) @@ -822,9 +857,9 @@ major, minor = map(int, getVersion().split('.', 2)) pl = Plist( - CFBundleGetInfoString="MacPython %s"%(vers,), - CFBundleIdentifier='org.python.MacPython', - CFBundleName='MacPython', + CFBundleGetInfoString="Python %s"%(vers,), + CFBundleIdentifier='org.python.Python', + CFBundleName='Python', CFBundleShortVersionString=vers, IFMajorVersion=major, IFMinorVersion=minor, @@ -858,7 +893,7 @@ shutil.rmtree(outdir) os.mkdir(outdir) - pkgroot = os.path.join(outdir, 'MacPython.mpkg', 'Contents') + pkgroot = os.path.join(outdir, 'Python.mpkg', 'Contents') pkgcontents = os.path.join(pkgroot, 'Packages') os.makedirs(pkgcontents) for recipe in PKG_RECIPES: @@ -875,7 +910,7 @@ makeMpkgPlist(os.path.join(pkgroot, 'Info.plist')) pl = Plist( - IFPkgDescriptionTitle="Universal MacPython", + IFPkgDescriptionTitle="Python", IFPkgDescriptionVersion=getVersion(), ) @@ -915,10 +950,32 @@ imagepath = imagepath + '.dmg' os.mkdir(outdir) - runCommand("hdiutil create -volname 'Universal MacPython %s' -srcfolder %s %s"%( - getFullVersion(), + volname='Python %s'%(getFullVersion()) + runCommand("hdiutil create -format UDRW -volname %s -srcfolder %s %s"%( + shellQuote(volname), shellQuote(os.path.join(WORKDIR, 'installer')), - shellQuote(imagepath))) + shellQuote(imagepath + ".tmp.dmg" ))) + + + if not os.path.exists(os.path.join(WORKDIR, "mnt")): + os.mkdir(os.path.join(WORKDIR, "mnt")) + runCommand("hdiutil attach %s -mountroot %s"%( + shellQuote(imagepath + ".tmp.dmg"), shellQuote(os.path.join(WORKDIR, "mnt")))) + + # Custom icon for the DMG, shown when the DMG is mounted. + shutil.copy("../Icons/Disk Image.icns", + os.path.join(WORKDIR, "mnt", volname, ".VolumeIcon.icns")) + runCommand("/Developer/Tools/SetFile -a C %s/"%( + shellQuote(os.path.join(WORKDIR, "mnt", volname)),)) + + runCommand("hdiutil detach %s"%(shellQuote(os.path.join(WORKDIR, "mnt", volname)))) + + setIcon(imagepath + ".tmp.dmg", "../Icons/Disk Image.icns") + runCommand("hdiutil convert %s -format UDZO -o %s"%( + shellQuote(imagepath + ".tmp.dmg"), shellQuote(imagepath))) + setIcon(imagepath, "../Icons/Disk Image.icns") + + os.unlink(imagepath + ".tmp.dmg") return imagepath @@ -946,7 +1003,7 @@ parseOptions() checkEnvironment() - os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.3' + os.environ['MACOSX_DEPLOYMENT_TARGET'] = DEPTARGET if os.path.exists(WORKDIR): shutil.rmtree(WORKDIR) @@ -982,13 +1039,6 @@ print >> fp, "# By:", pwd.getpwuid(os.getuid()).pw_gecos fp.close() - # Custom icon for the DMG, shown when the DMG is mounted. - # XXX: Code is diabled because it doesn't actually work :-( -# shutil.copy("../Icons/Disk Image.icns", -# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns")) -# os.system("/Developer/Tools/SetFile -a C %s"%( -# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns"))) - setIcon(os.path.join(WORKDIR, "installer"), "../Icons/Disk Image.icns") # And copy it to a DMG From buildbot at python.org Mon Mar 30 21:40:52 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 19:40:52 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 2.6 Message-ID: <20090330194054.F2CE61E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%202.6/builds/190 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: jesse.noller,ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Mon Mar 30 21:51:09 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 21:51:09 +0200 (CEST) Subject: [Python-checkins] r70740 - python/branches/py3k/Mac/BuildScript/build-installer.py Message-ID: <20090330195109.747E11E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 21:51:09 2009 New Revision: 70740 Log: Enable "--with-computed-gotos" for the binary installer on OSX. Modified: python/branches/py3k/Mac/BuildScript/build-installer.py Modified: python/branches/py3k/Mac/BuildScript/build-installer.py ============================================================================== --- python/branches/py3k/Mac/BuildScript/build-installer.py (original) +++ python/branches/py3k/Mac/BuildScript/build-installer.py Mon Mar 30 21:51:09 2009 @@ -646,7 +646,7 @@ print "Running configure..." runCommand("%s -C --enable-framework --enable-universalsdk=%s " - "--with-universal-archs=%s " + "--with-universal-archs=%s --with-computed-gotos" "LDFLAGS='-g -L%s/libraries/usr/local/lib' " "OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%( shellQuote(os.path.join(SRCDIR, 'configure')), shellQuote(SDKPATH), From python-checkins at python.org Mon Mar 30 21:56:25 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 21:56:25 +0200 (CEST) Subject: [Python-checkins] r70741 - in python/trunk/Mac: Makefile.in Resources/app/Info.plist.in Message-ID: <20090330195625.694701E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 21:56:25 2009 New Revision: 70741 Log: Fixes issue 5270 Modified: python/trunk/Mac/Makefile.in python/trunk/Mac/Resources/app/Info.plist.in Modified: python/trunk/Mac/Makefile.in ============================================================================== --- python/trunk/Mac/Makefile.in (original) +++ python/trunk/Mac/Makefile.in Mon Mar 30 21:56:25 2009 @@ -14,6 +14,7 @@ LDFLAGS=@LDFLAGS@ FRAMEWORKUNIXTOOLSPREFIX=@FRAMEWORKUNIXTOOLSPREFIX@ PYTHONFRAMEWORK=@PYTHONFRAMEWORK@ +PYTHONFRAMEWORKIDENTIFIER=@PYTHONFRAMEWORKIDENTIFIER@ # These are normally glimpsed from the previous set @@ -206,6 +207,12 @@ done; \ done $(INSTALL_PROGRAM) $(STRIPFLAG) $(BUILDPYTHON) "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)" + sed -e "s!%bundleid%!$(PYTHONFRAMEWORKIDENTIFIER)!g" \ + -e "s!%version%!`$(RUNSHARED) $(BUILDPYTHON) \ + -c 'import platform; print(platform.python_version())'`!g" \ + < "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist.in" \ + > "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist" + rm "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist.in" install_Python4way: install_Python lipo -extract i386 -extract ppc7400 -output "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)-32" "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)" Modified: python/trunk/Mac/Resources/app/Info.plist.in ============================================================================== --- python/trunk/Mac/Resources/app/Info.plist.in (original) +++ python/trunk/Mac/Resources/app/Info.plist.in Mon Mar 30 21:56:25 2009 @@ -20,7 +20,7 @@ CFBundleExecutable Python CFBundleGetInfoString - @VERSION@, (c) 2004 Python Software Foundation. + %version%, (c) 2004-2009 Python Software Foundation. CFBundleHelpBookFolder Documentation @@ -33,21 +33,21 @@ CFBundleIconFile PythonInterpreter.icns CFBundleIdentifier - @PYTHONFRAMEWORKIDENTIFIER at .app + %bundleid% CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString - @VERSION@, (c) 2004-2008 Python Software Foundation. + %version%, (c) 2004-2009 Python Software Foundation. CFBundleName Python CFBundlePackageType APPL CFBundleShortVersionString - @VERSION@ + %version% CFBundleSignature PytX CFBundleVersion - @VERSION@ + %version% CSResourcesFileMapped LSRequiresCarbon From python-checkins at python.org Mon Mar 30 21:57:15 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 30 Mar 2009 21:57:15 +0200 (CEST) Subject: [Python-checkins] r70742 - in python/branches/py3k/Lib/importlib: _bootstrap.py test/import_/test_path.py Message-ID: <20090330195715.CD5691E4002@bag.python.org> Author: brett.cannon Date: Mon Mar 30 21:57:15 2009 New Revision: 70742 Log: Fix importlib.machinery.PathFinder.find_module() to essentially skip over None entries in sys.path_importer_cache. While this differs from semantics in how __import__ works, it prevents any implicit semantics from taking hold with users. Modified: python/branches/py3k/Lib/importlib/_bootstrap.py python/branches/py3k/Lib/importlib/test/import_/test_path.py Modified: python/branches/py3k/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k/Lib/importlib/_bootstrap.py Mon Mar 30 21:57:15 2009 @@ -661,9 +661,10 @@ finder = cls._path_importer_cache(entry) except ImportError: continue - loader = finder.find_module(fullname) - if loader: - return loader + if finder: + loader = finder.find_module(fullname) + if loader: + return loader else: return None Modified: python/branches/py3k/Lib/importlib/test/import_/test_path.py ============================================================================== --- python/branches/py3k/Lib/importlib/test/import_/test_path.py (original) +++ python/branches/py3k/Lib/importlib/test/import_/test_path.py Mon Mar 30 21:57:15 2009 @@ -55,6 +55,25 @@ self.assert_(path in sys.path_importer_cache) self.assert_(sys.path_importer_cache[path] is importer) + def test_path_importer_cache_has_None(self): + # Test that if sys.path_importer_cache has None that None is returned. + clear_cache = {path: None for path in sys.path} + with util.import_state(path_importer_cache=clear_cache): + for name in ('asynchat', 'sys', ''): + self.assert_(machinery.PathFinder.find_module(name) is None) + + def test_path_importer_cache_has_None_continues(self): + # Test that having None in sys.path_importer_cache causes the search to + # continue. + path = '' + module = '' + importer = util.mock_modules(module) + with util.import_state(path=['1', '2'], + path_importer_cache={'1': None, '2': importer}): + loader = machinery.PathFinder.find_module(module) + self.assert_(loader is importer) + + class DefaultPathFinderTests(unittest.TestCase): From python-checkins at python.org Mon Mar 30 21:58:41 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 21:58:41 +0200 (CEST) Subject: [Python-checkins] r70743 - in python/branches/release26-maint: Mac/Makefile.in Mac/Resources/app/Info.plist.in Message-ID: <20090330195841.3F2091E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 21:58:41 2009 New Revision: 70743 Log: Merged revisions 70741 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70741 | ronald.oussoren | 2009-03-30 14:56:25 -0500 (Mon, 30 Mar 2009) | 2 lines Fixes issue 5270 ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Mac/Makefile.in python/branches/release26-maint/Mac/Resources/app/Info.plist.in Modified: python/branches/release26-maint/Mac/Makefile.in ============================================================================== --- python/branches/release26-maint/Mac/Makefile.in (original) +++ python/branches/release26-maint/Mac/Makefile.in Mon Mar 30 21:58:41 2009 @@ -14,6 +14,7 @@ LDFLAGS=@LDFLAGS@ FRAMEWORKUNIXTOOLSPREFIX=@FRAMEWORKUNIXTOOLSPREFIX@ PYTHONFRAMEWORK=@PYTHONFRAMEWORK@ +PYTHONFRAMEWORKIDENTIFIER=@PYTHONFRAMEWORKIDENTIFIER@ # These are normally glimpsed from the previous set @@ -206,6 +207,12 @@ done; \ done $(INSTALL_PROGRAM) $(STRIPFLAG) $(BUILDPYTHON) "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)" + sed -e "s!%bundleid%!$(PYTHONFRAMEWORKIDENTIFIER)!g" \ + -e "s!%version%!`$(RUNSHARED) $(BUILDPYTHON) \ + -c 'import platform; print(platform.python_version())'`!g" \ + < "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist.in" \ + > "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist" + rm "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist.in" install_Python4way: install_Python lipo -extract i386 -extract ppc7400 -output "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)-32" "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)" Modified: python/branches/release26-maint/Mac/Resources/app/Info.plist.in ============================================================================== --- python/branches/release26-maint/Mac/Resources/app/Info.plist.in (original) +++ python/branches/release26-maint/Mac/Resources/app/Info.plist.in Mon Mar 30 21:58:41 2009 @@ -20,7 +20,7 @@ CFBundleExecutable Python CFBundleGetInfoString - @VERSION@, (c) 2004 Python Software Foundation. + %version%, (c) 2004-2009 Python Software Foundation. CFBundleHelpBookFolder Documentation @@ -33,21 +33,21 @@ CFBundleIconFile PythonInterpreter.icns CFBundleIdentifier - @PYTHONFRAMEWORKIDENTIFIER at .app + %bundleid% CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString - @VERSION@, (c) 2004-2008 Python Software Foundation. + %version%, (c) 2004-2009 Python Software Foundation. CFBundleName Python CFBundlePackageType APPL CFBundleShortVersionString - @VERSION@ + %version% CFBundleSignature PytX CFBundleVersion - @VERSION@ + %version% CSResourcesFileMapped LSRequiresCarbon From python-checkins at python.org Mon Mar 30 21:59:49 2009 From: python-checkins at python.org (mark.dickinson) Date: Mon, 30 Mar 2009 21:59:49 +0200 (CEST) Subject: [Python-checkins] r70744 - in python/branches/py3k-short-float-repr: Doc/license.rst Python/dtoa.c Message-ID: <20090330195949.A9AF51E4002@bag.python.org> Author: mark.dickinson Date: Mon Mar 30 21:59:48 2009 New Revision: 70744 Log: Add David Gay's strtod and dtoa code to Python directory, and update licenses file accordingly. Added: python/branches/py3k-short-float-repr/Python/dtoa.c Modified: python/branches/py3k-short-float-repr/Doc/license.rst Modified: python/branches/py3k-short-float-repr/Doc/license.rst ============================================================================== --- python/branches/py3k-short-float-repr/Doc/license.rst (original) +++ python/branches/py3k-short-float-repr/Doc/license.rst Mon Mar 30 21:59:48 2009 @@ -658,3 +658,35 @@ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +strtod and dtoa +--------------- + +The file :file:`Python/dtoa.c`, which supplies C functions dtoa and +strtod for conversion of C doubles to and from strings, is derived +from the file of the same name by David M. Gay, currently available +from http://www.netlib.org/fp/. The original file, as retrieved on +March 16, 2009, contains the following copyright and licensing +notice:: + + /**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + + Added: python/branches/py3k-short-float-repr/Python/dtoa.c ============================================================================== --- (empty file) +++ python/branches/py3k-short-float-repr/Python/dtoa.c Mon Mar 30 21:59:48 2009 @@ -0,0 +1,4206 @@ +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +/* On a machine with IEEE extended-precision registers, it is + * necessary to specify double-precision (53-bit) rounding precision + * before invoking strtod or dtoa. If the machine uses (the equivalent + * of) Intel 80x87 arithmetic, the call + * _control87(PC_53, MCW_PC); + * does this with many compilers. Whether this or another call is + * appropriate depends on the compiler; for this to work, it may be + * necessary to #include "float.h" or another system-dependent header + * file. + */ + +/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. + * + * This strtod returns a nearest machine number to the input decimal + * string (or sets errno to ERANGE). With IEEE arithmetic, ties are + * broken by the IEEE round-even rule. Otherwise ties are broken by + * biased rounding (add half and chop). + * + * Inspired loosely by William D. Clinger's paper "How to Read Floating + * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * + * 1. We only require IEEE, IBM, or VAX double-precision + * arithmetic (not IEEE double-extended). + * 2. We get by with floating-point arithmetic in a case that + * Clinger missed -- when we're computing d * 10^n + * for a small integer d and the integer n is not too + * much larger than 22 (the maximum integer k for which + * we can represent 10^k exactly), we may be able to + * compute (d*10^k) * 10^(e-k) with just one roundoff. + * 3. Rather than a bit-at-a-time adjustment of the binary + * result in the hard case, we use floating-point + * arithmetic to determine the adjustment to within + * one bit; only in really hard cases do we need to + * compute a second residual. + * 4. Because of 3., we don't need a large table of powers of 10 + * for ten-to-e (just some small tables, e.g. of 10^k + * for 0 <= k <= 22). + */ + +/* + * #define IEEE_8087 for IEEE-arithmetic machines where the least + * significant byte has the lowest address. + * #define IEEE_MC68k for IEEE-arithmetic machines where the most + * significant byte has the lowest address. + * #define Long int on machines with 32-bit ints and 64-bit longs. + * #define IBM for IBM mainframe-style floating-point arithmetic. + * #define VAX for VAX-style floating-point arithmetic (D_floating). + * #define No_leftright to omit left-right logic in fast floating-point + * computation of dtoa. + * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 + * and strtod and dtoa should round accordingly. Unless Trust_FLT_ROUNDS + * is also #defined, fegetround() will be queried for the rounding mode. + * Note that both FLT_ROUNDS and fegetround() are specified by the C99 + * standard (and are specified to be consistent, with fesetround() + * affecting the value of FLT_ROUNDS), but that some (Linux) systems + * do not work correctly in this regard, so using fegetround() is more + * portable than using FLT_FOUNDS directly. + * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 + * and Honor_FLT_ROUNDS is not #defined. + * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines + * that use extended-precision instructions to compute rounded + * products and quotients) with IBM. + * #define ROUND_BIASED for IEEE-format with biased rounding. + * #define Inaccurate_Divide for IEEE-format with correctly rounded + * products but inaccurate quotients, e.g., for Intel i860. + * #define NO_LONG_LONG on machines that do not have a "long long" + * integer type (of >= 64 bits). On such machines, you can + * #define Just_16 to store 16 bits per 32-bit Long when doing + * high-precision integer arithmetic. Whether this speeds things + * up or slows things down depends on the machine and the number + * being converted. If long long is available and the name is + * something other than "long long", #define Llong to be the name, + * and if "unsigned Llong" does not work as an unsigned version of + * Llong, #define #ULLong to be the corresponding unsigned type. + * #define KR_headers for old-style C function headers. + * #define Bad_float_h if your system lacks a float.h or if it does not + * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, + * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. + * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) + * if memory is available and otherwise does something you deem + * appropriate. If MALLOC is undefined, malloc will be invoked + * directly -- and assumed always to succeed. Similarly, if you + * want something other than the system's free() to be called to + * recycle memory acquired from MALLOC, #define FREE to be the + * name of the alternate routine. (FREE or free is only called in + * pathological cases, e.g., in a dtoa call after a dtoa return in + * mode 3 with thousands of digits requested.) + * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making + * memory allocations from a private pool of memory when possible. + * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes, + * unless #defined to be a different length. This default length + * suffices to get rid of MALLOC calls except for unusual cases, + * such as decimal-to-binary conversion of a very long string of + * digits. The longest string dtoa can return is about 751 bytes + * long. For conversions by strtod of strings of 800 digits and + * all dtoa conversions in single-threaded executions with 8-byte + * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte + * pointers, PRIVATE_MEM >= 7112 appears adequate. + * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK + * #defined automatically on IEEE systems. On such systems, + * when INFNAN_CHECK is #defined, strtod checks + * for Infinity and NaN (case insensitively). On some systems + * (e.g., some HP systems), it may be necessary to #define NAN_WORD0 + * appropriately -- to the most significant word of a quiet NaN. + * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) + * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, + * strtod also accepts (case insensitively) strings of the form + * NaN(x), where x is a string of hexadecimal digits and spaces; + * if there is only one string of hexadecimal digits, it is taken + * for the 52 fraction bits of the resulting NaN; if there are two + * or more strings of hex digits, the first is for the high 20 bits, + * the second and subsequent for the low 32 bits, with intervening + * white space ignored; but if this results in none of the 52 + * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0 + * and NAN_WORD1 are used instead. + * #define MULTIPLE_THREADS if the system offers preemptively scheduled + * multiple threads. In this case, you must provide (or suitably + * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed + * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed + * in pow5mult, ensures lazy evaluation of only one copy of high + * powers of 5; omitting this lock would introduce a small + * probability of wasting memory, but would otherwise be harmless.) + * You must also invoke freedtoa(s) to free the value s returned by + * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. + * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that + * avoids underflows on inputs whose result does not underflow. + * If you #define NO_IEEE_Scale on a machine that uses IEEE-format + * floating-point numbers and flushes underflows to zero rather + * than implementing gradual underflow, then you must also #define + * Sudden_Underflow. + * #define USE_LOCALE to use the current locale's decimal_point value. + * #define SET_INEXACT if IEEE arithmetic is being used and extra + * computation should be done to set the inexact flag when the + * result is inexact and avoid setting inexact when the result + * is exact. In this case, dtoa.c must be compiled in + * an environment, perhaps provided by #include "dtoa.c" in a + * suitable wrapper, that defines two functions, + * int get_inexact(void); + * void clear_inexact(void); + * such that get_inexact() returns a nonzero value if the + * inexact bit is already set, and clear_inexact() sets the + * inexact bit to 0. When SET_INEXACT is #defined, strtod + * also does extra computations to set the underflow and overflow + * flags when appropriate (i.e., when the result is tiny and + * inexact or when it is a numeric value rounded to +-infinity). + * #define NO_ERRNO if strtod should not assign errno = ERANGE when + * the result overflows to +-Infinity or underflows to 0. + * #define NO_HEX_FP to omit recognition of hexadecimal floating-point + * values by strtod. + * #define NO_STRTOD_BIGCOMP (on IEEE-arithmetic systems only for now) + * to disable logic for "fast" testing of very long input strings + * to strtod. This testing proceeds by initially truncating the + * input string, then if necessary comparing the whole string with + * a decimal expansion to decide close cases. This logic is only + * used for input more than STRTOD_DIGLIM digits long (default 40). + */ + +#ifndef Long +#define Long long +#endif +#ifndef ULong +typedef unsigned Long ULong; +#endif + +#ifdef DEBUG +#include "stdio.h" +#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} +#endif + +#include "stdlib.h" +#include "string.h" + +#ifdef USE_LOCALE +#include "locale.h" +#endif + +#ifdef Honor_FLT_ROUNDS +#ifndef Trust_FLT_ROUNDS +#include +#endif +#endif + +#ifdef MALLOC +#ifdef KR_headers +extern char *MALLOC(); +#else +extern void *MALLOC(size_t); +#endif +#else +#define MALLOC malloc +#endif + +#ifndef Omit_Private_Memory +#ifndef PRIVATE_MEM +#define PRIVATE_MEM 2304 +#endif +#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) +static double private_mem[PRIVATE_mem], *pmem_next = private_mem; +#endif + +#undef IEEE_Arith +#undef Avoid_Underflow +#ifdef IEEE_MC68k +#define IEEE_Arith +#endif +#ifdef IEEE_8087 +#define IEEE_Arith +#endif + +#ifdef IEEE_Arith +#ifndef NO_INFNAN_CHECK +#undef INFNAN_CHECK +#define INFNAN_CHECK +#endif +#else +#undef INFNAN_CHECK +#define NO_STRTOD_BIGCOMP +#endif + +#include "errno.h" + +#ifdef Bad_float_h + +#ifdef IEEE_Arith +#define DBL_DIG 15 +#define DBL_MAX_10_EXP 308 +#define DBL_MAX_EXP 1024 +#define FLT_RADIX 2 +#endif /*IEEE_Arith*/ + +#ifdef IBM +#define DBL_DIG 16 +#define DBL_MAX_10_EXP 75 +#define DBL_MAX_EXP 63 +#define FLT_RADIX 16 +#define DBL_MAX 7.2370055773322621e+75 +#endif + +#ifdef VAX +#define DBL_DIG 16 +#define DBL_MAX_10_EXP 38 +#define DBL_MAX_EXP 127 +#define FLT_RADIX 2 +#define DBL_MAX 1.7014118346046923e+38 +#endif + +#ifndef LONG_MAX +#define LONG_MAX 2147483647 +#endif + +#else /* ifndef Bad_float_h */ +#include "float.h" +#endif /* Bad_float_h */ + +#ifndef __MATH_H__ +#include "math.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CONST +#ifdef KR_headers +#define CONST /* blank */ +#else +#define CONST const +#endif +#endif + +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 +Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +#endif + +typedef union { double d; ULong L[2]; } U; + +#ifdef IEEE_8087 +#define word0(x) (x)->L[1] +#define word1(x) (x)->L[0] +#else +#define word0(x) (x)->L[0] +#define word1(x) (x)->L[1] +#endif +#define dval(x) (x)->d + +#ifndef STRTOD_DIGLIM +#define STRTOD_DIGLIM 40 +#endif + +#ifdef DIGLIM_DEBUG +extern int strtod_diglim; +#else +#define strtod_diglim STRTOD_DIGLIM +#endif + +/* The following definition of Storeinc is appropriate for MIPS processors. + * An alternative that might be better on some machines is + * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) + */ +#if defined(IEEE_8087) + defined(VAX) +#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ +((unsigned short *)a)[0] = (unsigned short)c, a++) +#else +#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ +((unsigned short *)a)[1] = (unsigned short)c, a++) +#endif + +/* #define P DBL_MANT_DIG */ +/* Ten_pmax = floor(P*log(2)/log(5)) */ +/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ +/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ +/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ + +#ifdef IEEE_Arith +#define Exp_shift 20 +#define Exp_shift1 20 +#define Exp_msk1 0x100000 +#define Exp_msk11 0x100000 +#define Exp_mask 0x7ff00000 +#define P 53 +#define Nbits 53 +#define Bias 1023 +#define Emax 1023 +#define Emin (-1022) +#define Exp_1 0x3ff00000 +#define Exp_11 0x3ff00000 +#define Ebits 11 +#define Frac_mask 0xfffff +#define Frac_mask1 0xfffff +#define Ten_pmax 22 +#define Bletch 0x10 +#define Bndry_mask 0xfffff +#define Bndry_mask1 0xfffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 14 +#define Int_max 14 +#ifndef NO_IEEE_Scale +#define Avoid_Underflow +#ifdef Flush_Denorm /* debugging option */ +#undef Sudden_Underflow +#endif +#endif + +#ifndef Flt_Rounds +#ifdef FLT_ROUNDS +#define Flt_Rounds FLT_ROUNDS +#else +#define Flt_Rounds 1 +#endif +#endif /*Flt_Rounds*/ + +#ifdef Honor_FLT_ROUNDS +#undef Check_FLT_ROUNDS +#define Check_FLT_ROUNDS +#else +#define Rounding Flt_Rounds +#endif + +#else /* ifndef IEEE_Arith */ +#undef Check_FLT_ROUNDS +#undef Honor_FLT_ROUNDS +#undef SET_INEXACT +#undef Sudden_Underflow +#define Sudden_Underflow +#ifdef IBM +#undef Flt_Rounds +#define Flt_Rounds 0 +#define Exp_shift 24 +#define Exp_shift1 24 +#define Exp_msk1 0x1000000 +#define Exp_msk11 0x1000000 +#define Exp_mask 0x7f000000 +#define P 14 +#define Nbits 56 +#define Bias 65 +#define Emax 248 +#define Emin (-260) +#define Exp_1 0x41000000 +#define Exp_11 0x41000000 +#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ +#define Frac_mask 0xffffff +#define Frac_mask1 0xffffff +#define Bletch 4 +#define Ten_pmax 22 +#define Bndry_mask 0xefffff +#define Bndry_mask1 0xffffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 4 +#define Tiny0 0x100000 +#define Tiny1 0 +#define Quick_max 14 +#define Int_max 15 +#else /* VAX */ +#undef Flt_Rounds +#define Flt_Rounds 1 +#define Exp_shift 23 +#define Exp_shift1 7 +#define Exp_msk1 0x80 +#define Exp_msk11 0x800000 +#define Exp_mask 0x7f80 +#define P 56 +#define Nbits 56 +#define Bias 129 +#define Emax 126 +#define Emin (-129) +#define Exp_1 0x40800000 +#define Exp_11 0x4080 +#define Ebits 8 +#define Frac_mask 0x7fffff +#define Frac_mask1 0xffff007f +#define Ten_pmax 24 +#define Bletch 2 +#define Bndry_mask 0xffff007f +#define Bndry_mask1 0xffff007f +#define LSB 0x10000 +#define Sign_bit 0x8000 +#define Log2P 1 +#define Tiny0 0x80 +#define Tiny1 0 +#define Quick_max 15 +#define Int_max 15 +#endif /* IBM, VAX */ +#endif /* IEEE_Arith */ + +#ifndef IEEE_Arith +#define ROUND_BIASED +#endif + +#ifdef RND_PRODQUOT +#define rounded_product(a,b) a = rnd_prod(a, b) +#define rounded_quotient(a,b) a = rnd_quot(a, b) +#ifdef KR_headers +extern double rnd_prod(), rnd_quot(); +#else +extern double rnd_prod(double, double), rnd_quot(double, double); +#endif +#else +#define rounded_product(a,b) a *= b +#define rounded_quotient(a,b) a /= b +#endif + +#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) +#define Big1 0xffffffff + +#ifndef Pack_32 +#define Pack_32 +#endif + +typedef struct BCinfo BCinfo; + struct +BCinfo { int dp0, dp1, dplen, dsign, e0, inexact, nd, nd0, rounding, scale, uflchk; }; + +#ifdef KR_headers +#define FFFFFFFF ((((unsigned long)0xffff)<<16)|(unsigned long)0xffff) +#else +#define FFFFFFFF 0xffffffffUL +#endif + +#ifdef NO_LONG_LONG +#undef ULLong +#ifdef Just_16 +#undef Pack_32 +/* When Pack_32 is not defined, we store 16 bits per 32-bit Long. + * This makes some inner loops simpler and sometimes saves work + * during multiplications, but it often seems to make things slightly + * slower. Hence the default is now to store 32 bits per Long. + */ +#endif +#else /* long long available */ +#ifndef Llong +#define Llong long long +#endif +#ifndef ULLong +#define ULLong unsigned Llong +#endif +#endif /* NO_LONG_LONG */ + +#ifndef MULTIPLE_THREADS +#define ACQUIRE_DTOA_LOCK(n) /*nothing*/ +#define FREE_DTOA_LOCK(n) /*nothing*/ +#endif + +#define Kmax 7 + +#ifdef __cplusplus +extern "C" double strtod(const char *s00, char **se); +extern "C" char *dtoa(double d, int mode, int ndigits, + int *decpt, int *sign, char **rve); +#endif + + struct +Bigint { + struct Bigint *next; + int k, maxwds, sign, wds; + ULong x[1]; + }; + + typedef struct Bigint Bigint; + + static Bigint *freelist[Kmax+1]; + + static Bigint * +Balloc +#ifdef KR_headers + (k) int k; +#else + (int k) +#endif +{ + int x; + Bigint *rv; +#ifndef Omit_Private_Memory + unsigned int len; +#endif + + ACQUIRE_DTOA_LOCK(0); + /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */ + /* but this case seems very unlikely. */ + if (k <= Kmax && (rv = freelist[k])) + freelist[k] = rv->next; + else { + x = 1 << k; +#ifdef Omit_Private_Memory + rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong)); +#else + len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) + /sizeof(double); + if (pmem_next - private_mem + len <= PRIVATE_mem) { + rv = (Bigint*)pmem_next; + pmem_next += len; + } + else + rv = (Bigint*)MALLOC(len*sizeof(double)); +#endif + rv->k = k; + rv->maxwds = x; + } + FREE_DTOA_LOCK(0); + rv->sign = rv->wds = 0; + return rv; + } + + static void +Bfree +#ifdef KR_headers + (v) Bigint *v; +#else + (Bigint *v) +#endif +{ + if (v) { + if (v->k > Kmax) +#ifdef FREE + FREE((void*)v); +#else + free((void*)v); +#endif + else { + ACQUIRE_DTOA_LOCK(0); + v->next = freelist[v->k]; + freelist[v->k] = v; + FREE_DTOA_LOCK(0); + } + } + } + +#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ +y->wds*sizeof(Long) + 2*sizeof(int)) + + static Bigint * +multadd +#ifdef KR_headers + (b, m, a) Bigint *b; int m, a; +#else + (Bigint *b, int m, int a) /* multiply by m and add a */ +#endif +{ + int i, wds; +#ifdef ULLong + ULong *x; + ULLong carry, y; +#else + ULong carry, *x, y; +#ifdef Pack_32 + ULong xi, z; +#endif +#endif + Bigint *b1; + + wds = b->wds; + x = b->x; + i = 0; + carry = a; + do { +#ifdef ULLong + y = *x * (ULLong)m + carry; + carry = y >> 32; + *x++ = y & FFFFFFFF; +#else +#ifdef Pack_32 + xi = *x; + y = (xi & 0xffff) * m + carry; + z = (xi >> 16) * m + (y >> 16); + carry = z >> 16; + *x++ = (z << 16) + (y & 0xffff); +#else + y = *x * m + carry; + carry = y >> 16; + *x++ = y & 0xffff; +#endif +#endif + } + while(++i < wds); + if (carry) { + if (wds >= b->maxwds) { + b1 = Balloc(b->k+1); + Bcopy(b1, b); + Bfree(b); + b = b1; + } + b->x[wds++] = carry; + b->wds = wds; + } + return b; + } + + static Bigint * +s2b +#ifdef KR_headers + (s, nd0, nd, y9, dplen) CONST char *s; int nd0, nd, dplen; ULong y9; +#else + (CONST char *s, int nd0, int nd, ULong y9, int dplen) +#endif +{ + Bigint *b; + int i, k; + Long x, y; + + x = (nd + 8) / 9; + for(k = 0, y = 1; x > y; y <<= 1, k++) ; +#ifdef Pack_32 + b = Balloc(k); + b->x[0] = y9; + b->wds = 1; +#else + b = Balloc(k+1); + b->x[0] = y9 & 0xffff; + b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; +#endif + + i = 9; + if (9 < nd0) { + s += 9; + do b = multadd(b, 10, *s++ - '0'); + while(++i < nd0); + s += dplen; + } + else + s += dplen + 9; + for(; i < nd; i++) + b = multadd(b, 10, *s++ - '0'); + return b; + } + + static int +hi0bits +#ifdef KR_headers + (x) ULong x; +#else + (ULong x) +#endif +{ + int k = 0; + + if (!(x & 0xffff0000)) { + k = 16; + x <<= 16; + } + if (!(x & 0xff000000)) { + k += 8; + x <<= 8; + } + if (!(x & 0xf0000000)) { + k += 4; + x <<= 4; + } + if (!(x & 0xc0000000)) { + k += 2; + x <<= 2; + } + if (!(x & 0x80000000)) { + k++; + if (!(x & 0x40000000)) + return 32; + } + return k; + } + + static int +lo0bits +#ifdef KR_headers + (y) ULong *y; +#else + (ULong *y) +#endif +{ + int k; + ULong x = *y; + + if (x & 7) { + if (x & 1) + return 0; + if (x & 2) { + *y = x >> 1; + return 1; + } + *y = x >> 2; + return 2; + } + k = 0; + if (!(x & 0xffff)) { + k = 16; + x >>= 16; + } + if (!(x & 0xff)) { + k += 8; + x >>= 8; + } + if (!(x & 0xf)) { + k += 4; + x >>= 4; + } + if (!(x & 0x3)) { + k += 2; + x >>= 2; + } + if (!(x & 1)) { + k++; + x >>= 1; + if (!x) + return 32; + } + *y = x; + return k; + } + + static Bigint * +i2b +#ifdef KR_headers + (i) int i; +#else + (int i) +#endif +{ + Bigint *b; + + b = Balloc(1); + b->x[0] = i; + b->wds = 1; + return b; + } + + static Bigint * +mult +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + Bigint *c; + int k, wa, wb, wc; + ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; + ULong y; +#ifdef ULLong + ULLong carry, z; +#else + ULong carry, z; +#ifdef Pack_32 + ULong z2; +#endif +#endif + + if (a->wds < b->wds) { + c = a; + a = b; + b = c; + } + k = a->k; + wa = a->wds; + wb = b->wds; + wc = wa + wb; + if (wc > a->maxwds) + k++; + c = Balloc(k); + for(x = c->x, xa = x + wc; x < xa; x++) + *x = 0; + xa = a->x; + xae = xa + wa; + xb = b->x; + xbe = xb + wb; + xc0 = c->x; +#ifdef ULLong + for(; xb < xbe; xc0++) { + if ((y = *xb++)) { + x = xa; + xc = xc0; + carry = 0; + do { + z = *x++ * (ULLong)y + *xc + carry; + carry = z >> 32; + *xc++ = z & FFFFFFFF; + } + while(x < xae); + *xc = carry; + } + } +#else +#ifdef Pack_32 + for(; xb < xbe; xb++, xc0++) { + if (y = *xb & 0xffff) { + x = xa; + xc = xc0; + carry = 0; + do { + z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; + carry = z >> 16; + z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; + carry = z2 >> 16; + Storeinc(xc, z2, z); + } + while(x < xae); + *xc = carry; + } + if (y = *xb >> 16) { + x = xa; + xc = xc0; + carry = 0; + z2 = *xc; + do { + z = (*x & 0xffff) * y + (*xc >> 16) + carry; + carry = z >> 16; + Storeinc(xc, z, z2); + z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; + carry = z2 >> 16; + } + while(x < xae); + *xc = z2; + } + } +#else + for(; xb < xbe; xc0++) { + if (y = *xb++) { + x = xa; + xc = xc0; + carry = 0; + do { + z = *x++ * y + *xc + carry; + carry = z >> 16; + *xc++ = z & 0xffff; + } + while(x < xae); + *xc = carry; + } + } +#endif +#endif + for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; + c->wds = wc; + return c; + } + + static Bigint *p5s; + + static Bigint * +pow5mult +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (Bigint *b, int k) +#endif +{ + Bigint *b1, *p5, *p51; + int i; + static int p05[3] = { 5, 25, 125 }; + + if ((i = k & 3)) + b = multadd(b, p05[i-1], 0); + + if (!(k >>= 2)) + return b; + if (!(p5 = p5s)) { + /* first time */ +#ifdef MULTIPLE_THREADS + ACQUIRE_DTOA_LOCK(1); + if (!(p5 = p5s)) { + p5 = p5s = i2b(625); + p5->next = 0; + } + FREE_DTOA_LOCK(1); +#else + p5 = p5s = i2b(625); + p5->next = 0; +#endif + } + for(;;) { + if (k & 1) { + b1 = mult(b, p5); + Bfree(b); + b = b1; + } + if (!(k >>= 1)) + break; + if (!(p51 = p5->next)) { +#ifdef MULTIPLE_THREADS + ACQUIRE_DTOA_LOCK(1); + if (!(p51 = p5->next)) { + p51 = p5->next = mult(p5,p5); + p51->next = 0; + } + FREE_DTOA_LOCK(1); +#else + p51 = p5->next = mult(p5,p5); + p51->next = 0; +#endif + } + p5 = p51; + } + return b; + } + + static Bigint * +lshift +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (Bigint *b, int k) +#endif +{ + int i, k1, n, n1; + Bigint *b1; + ULong *x, *x1, *xe, z; + +#ifdef Pack_32 + n = k >> 5; +#else + n = k >> 4; +#endif + k1 = b->k; + n1 = n + b->wds + 1; + for(i = b->maxwds; n1 > i; i <<= 1) + k1++; + b1 = Balloc(k1); + x1 = b1->x; + for(i = 0; i < n; i++) + *x1++ = 0; + x = b->x; + xe = x + b->wds; +#ifdef Pack_32 + if (k &= 0x1f) { + k1 = 32 - k; + z = 0; + do { + *x1++ = *x << k | z; + z = *x++ >> k1; + } + while(x < xe); + if ((*x1 = z)) + ++n1; + } +#else + if (k &= 0xf) { + k1 = 16 - k; + z = 0; + do { + *x1++ = *x << k & 0xffff | z; + z = *x++ >> k1; + } + while(x < xe); + if (*x1 = z) + ++n1; + } +#endif + else do + *x1++ = *x++; + while(x < xe); + b1->wds = n1 - 1; + Bfree(b); + return b1; + } + + static int +cmp +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + ULong *xa, *xa0, *xb, *xb0; + int i, j; + + i = a->wds; + j = b->wds; +#ifdef DEBUG + if (i > 1 && !a->x[i-1]) + Bug("cmp called with a->x[a->wds-1] == 0"); + if (j > 1 && !b->x[j-1]) + Bug("cmp called with b->x[b->wds-1] == 0"); +#endif + if (i -= j) + return i; + xa0 = a->x; + xa = xa0 + j; + xb0 = b->x; + xb = xb0 + j; + for(;;) { + if (*--xa != *--xb) + return *xa < *xb ? -1 : 1; + if (xa <= xa0) + break; + } + return 0; + } + + static Bigint * +diff +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + Bigint *c; + int i, wa, wb; + ULong *xa, *xae, *xb, *xbe, *xc; +#ifdef ULLong + ULLong borrow, y; +#else + ULong borrow, y; +#ifdef Pack_32 + ULong z; +#endif +#endif + + i = cmp(a,b); + if (!i) { + c = Balloc(0); + c->wds = 1; + c->x[0] = 0; + return c; + } + if (i < 0) { + c = a; + a = b; + b = c; + i = 1; + } + else + i = 0; + c = Balloc(a->k); + c->sign = i; + wa = a->wds; + xa = a->x; + xae = xa + wa; + wb = b->wds; + xb = b->x; + xbe = xb + wb; + xc = c->x; + borrow = 0; +#ifdef ULLong + do { + y = (ULLong)*xa++ - *xb++ - borrow; + borrow = y >> 32 & (ULong)1; + *xc++ = y & FFFFFFFF; + } + while(xb < xbe); + while(xa < xae) { + y = *xa++ - borrow; + borrow = y >> 32 & (ULong)1; + *xc++ = y & FFFFFFFF; + } +#else +#ifdef Pack_32 + do { + y = (*xa & 0xffff) - (*xb & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(xc, z, y); + } + while(xb < xbe); + while(xa < xae) { + y = (*xa & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*xa++ >> 16) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(xc, z, y); + } +#else + do { + y = *xa++ - *xb++ - borrow; + borrow = (y & 0x10000) >> 16; + *xc++ = y & 0xffff; + } + while(xb < xbe); + while(xa < xae) { + y = *xa++ - borrow; + borrow = (y & 0x10000) >> 16; + *xc++ = y & 0xffff; + } +#endif +#endif + while(!*--xc) + wa--; + c->wds = wa; + return c; + } + + static double +ulp +#ifdef KR_headers + (x) U *x; +#else + (U *x) +#endif +{ + Long L; + U u; + + L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; +#ifndef Avoid_Underflow +#ifndef Sudden_Underflow + if (L > 0) { +#endif +#endif +#ifdef IBM + L |= Exp_msk1 >> 4; +#endif + word0(&u) = L; + word1(&u) = 0; +#ifndef Avoid_Underflow +#ifndef Sudden_Underflow + } + else { + L = -L >> Exp_shift; + if (L < Exp_shift) { + word0(&u) = 0x80000 >> L; + word1(&u) = 0; + } + else { + word0(&u) = 0; + L -= Exp_shift; + word1(&u) = L >= 31 ? 1 : 1 << 31 - L; + } + } +#endif +#endif + return dval(&u); + } + + static double +b2d +#ifdef KR_headers + (a, e) Bigint *a; int *e; +#else + (Bigint *a, int *e) +#endif +{ + ULong *xa, *xa0, w, y, z; + int k; + U d; +#ifdef VAX + ULong d0, d1; +#else +#define d0 word0(&d) +#define d1 word1(&d) +#endif + + xa0 = a->x; + xa = xa0 + a->wds; + y = *--xa; +#ifdef DEBUG + if (!y) Bug("zero y in b2d"); +#endif + k = hi0bits(y); + *e = 32 - k; +#ifdef Pack_32 + if (k < Ebits) { + d0 = Exp_1 | y >> (Ebits - k); + w = xa > xa0 ? *--xa : 0; + d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + if (k -= Ebits) { + d0 = Exp_1 | y << k | z >> (32 - k); + y = xa > xa0 ? *--xa : 0; + d1 = z << k | y >> (32 - k); + } + else { + d0 = Exp_1 | y; + d1 = z; + } +#else + if (k < Ebits + 16) { + z = xa > xa0 ? *--xa : 0; + d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k; + w = xa > xa0 ? *--xa : 0; + y = xa > xa0 ? *--xa : 0; + d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + w = xa > xa0 ? *--xa : 0; + k -= Ebits + 16; + d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k; + y = xa > xa0 ? *--xa : 0; + d1 = w << k + 16 | y << k; +#endif + ret_d: +#ifdef VAX + word0(&d) = d0 >> 16 | d0 << 16; + word1(&d) = d1 >> 16 | d1 << 16; +#else +#undef d0 +#undef d1 +#endif + return dval(&d); + } + + static Bigint * +d2b +#ifdef KR_headers + (d, e, bits) U *d; int *e, *bits; +#else + (U *d, int *e, int *bits) +#endif +{ + Bigint *b; + int de, k; + ULong *x, y, z; +#ifndef Sudden_Underflow + int i; +#endif +#ifdef VAX + ULong d0, d1; + d0 = word0(d) >> 16 | word0(d) << 16; + d1 = word1(d) >> 16 | word1(d) << 16; +#else +#define d0 word0(d) +#define d1 word1(d) +#endif + +#ifdef Pack_32 + b = Balloc(1); +#else + b = Balloc(2); +#endif + x = b->x; + + z = d0 & Frac_mask; + d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ +#ifdef Sudden_Underflow + de = (int)(d0 >> Exp_shift); +#ifndef IBM + z |= Exp_msk11; +#endif +#else + if ((de = (int)(d0 >> Exp_shift))) + z |= Exp_msk1; +#endif +#ifdef Pack_32 + if ((y = d1)) { + if ((k = lo0bits(&y))) { + x[0] = y | z << (32 - k); + z >>= k; + } + else + x[0] = y; +#ifndef Sudden_Underflow + i = +#endif + b->wds = (x[1] = z) ? 2 : 1; + } + else { + k = lo0bits(&z); + x[0] = z; +#ifndef Sudden_Underflow + i = +#endif + b->wds = 1; + k += 32; + } +#else + if (y = d1) { + if (k = lo0bits(&y)) + if (k >= 16) { + x[0] = y | z << 32 - k & 0xffff; + x[1] = z >> k - 16 & 0xffff; + x[2] = z >> k; + i = 2; + } + else { + x[0] = y & 0xffff; + x[1] = y >> 16 | z << 16 - k & 0xffff; + x[2] = z >> k & 0xffff; + x[3] = z >> k+16; + i = 3; + } + else { + x[0] = y & 0xffff; + x[1] = y >> 16; + x[2] = z & 0xffff; + x[3] = z >> 16; + i = 3; + } + } + else { +#ifdef DEBUG + if (!z) + Bug("Zero passed to d2b"); +#endif + k = lo0bits(&z); + if (k >= 16) { + x[0] = z; + i = 0; + } + else { + x[0] = z & 0xffff; + x[1] = z >> 16; + i = 1; + } + k += 32; + } + while(!x[i]) + --i; + b->wds = i + 1; +#endif +#ifndef Sudden_Underflow + if (de) { +#endif +#ifdef IBM + *e = (de - Bias - (P-1) << 2) + k; + *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); +#else + *e = de - Bias - (P-1) + k; + *bits = P - k; +#endif +#ifndef Sudden_Underflow + } + else { + *e = de - Bias - (P-1) + 1 + k; +#ifdef Pack_32 + *bits = 32*i - hi0bits(x[i-1]); +#else + *bits = (i+2)*16 - hi0bits(x[i]); +#endif + } +#endif + return b; + } +#undef d0 +#undef d1 + + static double +ratio +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + U da, db; + int k, ka, kb; + + dval(&da) = b2d(a, &ka); + dval(&db) = b2d(b, &kb); +#ifdef Pack_32 + k = ka - kb + 32*(a->wds - b->wds); +#else + k = ka - kb + 16*(a->wds - b->wds); +#endif +#ifdef IBM + if (k > 0) { + word0(&da) += (k >> 2)*Exp_msk1; + if (k &= 3) + dval(&da) *= 1 << k; + } + else { + k = -k; + word0(&db) += (k >> 2)*Exp_msk1; + if (k &= 3) + dval(&db) *= 1 << k; + } +#else + if (k > 0) + word0(&da) += k*Exp_msk1; + else { + k = -k; + word0(&db) += k*Exp_msk1; + } +#endif + return dval(&da) / dval(&db); + } + + static CONST double +tens[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22 +#ifdef VAX + , 1e23, 1e24 +#endif + }; + + static CONST double +#ifdef IEEE_Arith +bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; +static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, +#ifdef Avoid_Underflow + 9007199254740992.*9007199254740992.e-256 + /* = 2^106 * 1e-256 */ +#else + 1e-256 +#endif + }; +/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */ +/* flag unnecessarily. It leads to a song and dance at the end of strtod. */ +#define Scale_Bit 0x10 +#define n_bigtens 5 +#else +#ifdef IBM +bigtens[] = { 1e16, 1e32, 1e64 }; +static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 }; +#define n_bigtens 3 +#else +bigtens[] = { 1e16, 1e32 }; +static CONST double tinytens[] = { 1e-16, 1e-32 }; +#define n_bigtens 2 +#endif +#endif + +#undef Need_Hexdig +#ifdef INFNAN_CHECK +#ifndef No_Hex_NaN +#define Need_Hexdig +#endif +#endif + +#ifndef Need_Hexdig +#ifndef NO_HEX_FP +#define Need_Hexdig +#endif +#endif + +#ifdef Need_Hexdig /*{*/ +static unsigned char hexdig[256]; + + static void +#ifdef KR_headers +htinit(h, s, inc) unsigned char *h; unsigned char *s; int inc; +#else +htinit(unsigned char *h, unsigned char *s, int inc) +#endif +{ + int i, j; + for(i = 0; (j = s[i]) !=0; i++) + h[j] = i + inc; + } + + static void +#ifdef KR_headers +hexdig_init() +#else +hexdig_init(void) +#endif +{ +#define USC (unsigned char *) + htinit(hexdig, USC "0123456789", 0x10); + htinit(hexdig, USC "abcdef", 0x10 + 10); + htinit(hexdig, USC "ABCDEF", 0x10 + 10); + } +#endif /* } Need_Hexdig */ + +#ifdef INFNAN_CHECK + +#ifndef NAN_WORD0 +#define NAN_WORD0 0x7ff80000 +#endif + +#ifndef NAN_WORD1 +#define NAN_WORD1 0 +#endif + + static int +match +#ifdef KR_headers + (sp, t) char **sp, *t; +#else + (CONST char **sp, char *t) +#endif +{ + int c, d; + CONST char *s = *sp; + + while((d = *t++)) { + if ((c = *++s) >= 'A' && c <= 'Z') + c += 'a' - 'A'; + if (c != d) + return 0; + } + *sp = s + 1; + return 1; + } + +#ifndef No_Hex_NaN + static void +hexnan +#ifdef KR_headers + (rvp, sp) U *rvp; CONST char **sp; +#else + (U *rvp, CONST char **sp) +#endif +{ + ULong c, x[2]; + CONST char *s; + int c1, havedig, udx0, xshift; + + if (!hexdig['0']) + hexdig_init(); + x[0] = x[1] = 0; + havedig = xshift = 0; + udx0 = 1; + s = *sp; + /* allow optional initial 0x or 0X */ + while((c = *(CONST unsigned char*)(s+1)) && c <= ' ') + ++s; + if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')) + s += 2; + while((c = *(CONST unsigned char*)++s)) { + if ((c1 = hexdig[c])) + c = c1 & 0xf; + else if (c <= ' ') { + if (udx0 && havedig) { + udx0 = 0; + xshift = 1; + } + continue; + } +#ifdef GDTOA_NON_PEDANTIC_NANCHECK + else if (/*(*/ c == ')' && havedig) { + *sp = s + 1; + break; + } + else + return; /* invalid form: don't change *sp */ +#else + else { + do { + if (/*(*/ c == ')') { + *sp = s + 1; + break; + } + } while((c = *++s)); + break; + } +#endif + havedig = 1; + if (xshift) { + xshift = 0; + x[0] = x[1]; + x[1] = 0; + } + if (udx0) + x[0] = (x[0] << 4) | (x[1] >> 28); + x[1] = (x[1] << 4) | c; + } + if ((x[0] &= 0xfffff) || x[1]) { + word0(rvp) = Exp_mask | x[0]; + word1(rvp) = x[1]; + } + } +#endif /*No_Hex_NaN*/ +#endif /* INFNAN_CHECK */ + +#ifndef NO_HEX_FP /*{*/ +#ifdef Pack_32 +#define ULbits 32 +#define kshift 5 +#define kmask 31 +#else +#define ULbits 16 +#define kshift 4 +#define kmask 15 +#endif + + static void +#ifdef KR_headers +rshift(b, k) Bigint *b; int k; +#else +rshift(Bigint *b, int k) +#endif +{ + ULong *x, *x1, *xe, y; + int n; + + x = x1 = b->x; + n = k >> kshift; + if (n < b->wds) { + xe = x + b->wds; + x += n; + if (k &= kmask) { + n = 32 - k; + y = *x++ >> k; + while(x < xe) { + *x1++ = (y | (*x << n)) & 0xffffffff; + y = *x++ >> k; + } + if ((*x1 = y) !=0) + x1++; + } + else + while(x < xe) + *x1++ = *x++; + } + if ((b->wds = x1 - b->x) == 0) + b->x[0] = 0; + } + + static ULong +#ifdef KR_headers +any_on(b, k) Bigint *b; int k; +#else +any_on(Bigint *b, int k) +#endif +{ + int n, nwds; + ULong *x, *x0, x1, x2; + + x = b->x; + nwds = b->wds; + n = k >> kshift; + if (n > nwds) + n = nwds; + else if (n < nwds && (k &= kmask)) { + x1 = x2 = x[n]; + x1 >>= k; + x1 <<= k; + if (x1 != x2) + return 1; + } + x0 = x; + x += n; + while(x > x0) + if (*--x) + return 1; + return 0; + } + +enum { /* rounding values: same as FLT_ROUNDS */ + Round_zero = 0, + Round_near = 1, + Round_up = 2, + Round_down = 3 + }; + + static Bigint * +#ifdef KR_headers +increment(b) Bigint *b; +#else +increment(Bigint *b) +#endif +{ + ULong *x, *xe; + Bigint *b1; + + x = b->x; + xe = x + b->wds; + do { + if (*x < (ULong)0xffffffffL) { + ++*x; + return b; + } + *x++ = 0; + } while(x < xe); + { + if (b->wds >= b->maxwds) { + b1 = Balloc(b->k+1); + Bcopy(b1,b); + Bfree(b); + b = b1; + } + b->x[b->wds++] = 1; + } + return b; + } + + void +#ifdef KR_headers +gethex(sp, rvp, rounding, sign) + CONST char **sp; U *rvp; int rounding, sign; +#else +gethex( CONST char **sp, U *rvp, int rounding, int sign) +#endif +{ + Bigint *b; + CONST unsigned char *decpt, *s0, *s, *s1; + Long e, e1; + ULong L, lostbits, *x; + int big, denorm, esign, havedig, k, n, nbits, up, zret; +#ifdef IBM + int j; +#endif + enum { +#ifdef IEEE_Arith /*{{*/ + emax = 0x7fe - Bias - P + 1, + emin = Emin - P + 1 +#else /*}{*/ + emin = Emin - P, +#ifdef VAX + emax = 0x7ff - Bias - P + 1 +#endif +#ifdef IBM + emax = 0x7f - Bias - P +#endif +#endif /*}}*/ + }; +#ifdef USE_LOCALE + int i; +#ifdef NO_LOCALE_CACHE + const unsigned char *decimalpoint = (unsigned char*) + localeconv()->decimal_point; +#else + const unsigned char *decimalpoint; + static unsigned char *decimalpoint_cache; + if (!(s0 = decimalpoint_cache)) { + s0 = (unsigned char*)localeconv()->decimal_point; + if ((decimalpoint_cache = (unsigned char*) + MALLOC(strlen((CONST char*)s0) + 1))) { + strcpy((char*)decimalpoint_cache, (CONST char*)s0); + s0 = decimalpoint_cache; + } + } + decimalpoint = s0; +#endif +#endif + + if (!hexdig['0']) + hexdig_init(); + havedig = 0; + s0 = *(CONST unsigned char **)sp + 2; + while(s0[havedig] == '0') + havedig++; + s0 += havedig; + s = s0; + decpt = 0; + zret = 0; + e = 0; + if (hexdig[*s]) + havedig++; + else { + zret = 1; +#ifdef USE_LOCALE + for(i = 0; decimalpoint[i]; ++i) { + if (s[i] != decimalpoint[i]) + goto pcheck; + } + decpt = s += i; +#else + if (*s != '.') + goto pcheck; + decpt = ++s; +#endif + if (!hexdig[*s]) + goto pcheck; + while(*s == '0') + s++; + if (hexdig[*s]) + zret = 0; + havedig = 1; + s0 = s; + } + while(hexdig[*s]) + s++; +#ifdef USE_LOCALE + if (*s == *decimalpoint && !decpt) { + for(i = 1; decimalpoint[i]; ++i) { + if (s[i] != decimalpoint[i]) + goto pcheck; + } + decpt = s += i; +#else + if (*s == '.' && !decpt) { + decpt = ++s; +#endif + while(hexdig[*s]) + s++; + }/*}*/ + if (decpt) + e = -(((Long)(s-decpt)) << 2); + pcheck: + s1 = s; + big = esign = 0; + switch(*s) { + case 'p': + case 'P': + switch(*++s) { + case '-': + esign = 1; + /* no break */ + case '+': + s++; + } + if ((n = hexdig[*s]) == 0 || n > 0x19) { + s = s1; + break; + } + e1 = n - 0x10; + while((n = hexdig[*++s]) !=0 && n <= 0x19) { + if (e1 & 0xf8000000) + big = 1; + e1 = 10*e1 + n - 0x10; + } + if (esign) + e1 = -e1; + e += e1; + } + *sp = (char*)s; + if (!havedig) + *sp = (char*)s0 - 1; + if (zret) + goto retz1; + if (big) { + if (esign) { +#ifdef IEEE_Arith + switch(rounding) { + case Round_up: + if (sign) + break; + goto ret_tiny; + case Round_down: + if (!sign) + break; + goto ret_tiny; + } +#endif + goto retz; +#ifdef IEEE_Arith + ret_tiny: +#ifndef NO_ERRNO + errno = ERANGE; +#endif + word0(rvp) = 0; + word1(rvp) = 1; + return; +#endif /* IEEE_Arith */ + } + switch(rounding) { + case Round_near: + goto ovfl1; + case Round_up: + if (!sign) + goto ovfl1; + goto ret_big; + case Round_down: + if (sign) + goto ovfl1; + goto ret_big; + } + ret_big: + word0(rvp) = Big0; + word1(rvp) = Big1; + return; + } + n = s1 - s0 - 1; + for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1) + k++; + b = Balloc(k); + x = b->x; + n = 0; + L = 0; +#ifdef USE_LOCALE + for(i = 0; decimalpoint[i+1]; ++i); +#endif + while(s1 > s0) { +#ifdef USE_LOCALE + if (*--s1 == decimalpoint[i]) { + s1 -= i; + continue; + } +#else + if (*--s1 == '.') + continue; +#endif + if (n == ULbits) { + *x++ = L; + L = 0; + n = 0; + } + L |= (hexdig[*s1] & 0x0f) << n; + n += 4; + } + *x++ = L; + b->wds = n = x - b->x; + n = ULbits*n - hi0bits(L); + nbits = Nbits; + lostbits = 0; + x = b->x; + if (n > nbits) { + n -= nbits; + if (any_on(b,n)) { + lostbits = 1; + k = n - 1; + if (x[k>>kshift] & 1 << (k & kmask)) { + lostbits = 2; + if (k > 0 && any_on(b,k)) + lostbits = 3; + } + } + rshift(b, n); + e += n; + } + else if (n < nbits) { + n = nbits - n; + b = lshift(b, n); + e -= n; + x = b->x; + } + if (e > Emax) { + ovfl: + Bfree(b); + ovfl1: +#ifndef NO_ERRNO + errno = ERANGE; +#endif + word0(rvp) = Exp_mask; + word1(rvp) = 0; + return; + } + denorm = 0; + if (e < emin) { + denorm = 1; + n = emin - e; + if (n >= nbits) { +#ifdef IEEE_Arith /*{*/ + switch (rounding) { + case Round_near: + if (n == nbits && (n < 2 || any_on(b,n-1))) + goto ret_tiny; + break; + case Round_up: + if (!sign) + goto ret_tiny; + break; + case Round_down: + if (sign) + goto ret_tiny; + } +#endif /* } IEEE_Arith */ + Bfree(b); + retz: +#ifndef NO_ERRNO + errno = ERANGE; +#endif + retz1: + rvp->d = 0.; + return; + } + k = n - 1; + if (lostbits) + lostbits = 1; + else if (k > 0) + lostbits = any_on(b,k); + if (x[k>>kshift] & 1 << (k & kmask)) + lostbits |= 2; + nbits -= n; + rshift(b,n); + e = emin; + } + if (lostbits) { + up = 0; + switch(rounding) { + case Round_zero: + break; + case Round_near: + if (lostbits & 2 + && (lostbits & 1) | (x[0] & 1)) + up = 1; + break; + case Round_up: + up = 1 - sign; + break; + case Round_down: + up = sign; + } + if (up) { + k = b->wds; + b = increment(b); + x = b->x; + if (denorm) { +#if 0 + if (nbits == Nbits - 1 + && x[nbits >> kshift] & 1 << (nbits & kmask)) + denorm = 0; /* not currently used */ +#endif + } + else if (b->wds > k + || ((n = nbits & kmask) !=0 + && hi0bits(x[k-1]) < 32-n)) { + rshift(b,1); + if (++e > Emax) + goto ovfl; + } + } + } +#ifdef IEEE_Arith + if (denorm) + word0(rvp) = b->wds > 1 ? b->x[1] & ~0x100000 : 0; + else + word0(rvp) = (b->x[1] & ~0x100000) | ((e + 0x3ff + 52) << 20); + word1(rvp) = b->x[0]; +#endif +#ifdef IBM + if ((j = e & 3)) { + k = b->x[0] & ((1 << j) - 1); + rshift(b,j); + if (k) { + switch(rounding) { + case Round_up: + if (!sign) + increment(b); + break; + case Round_down: + if (sign) + increment(b); + break; + case Round_near: + j = 1 << (j-1); + if (k & j && ((k & (j-1)) | lostbits)) + increment(b); + } + } + } + e >>= 2; + word0(rvp) = b->x[1] | ((e + 65 + 13) << 24); + word1(rvp) = b->x[0]; +#endif +#ifdef VAX + /* The next two lines ignore swap of low- and high-order 2 bytes. */ + /* word0(rvp) = (b->x[1] & ~0x800000) | ((e + 129 + 55) << 23); */ + /* word1(rvp) = b->x[0]; */ + word0(rvp) = ((b->x[1] & ~0x800000) >> 16) | ((e + 129 + 55) << 7) | (b->x[1] << 16); + word1(rvp) = (b->x[0] >> 16) | (b->x[0] << 16); +#endif + Bfree(b); + } +#endif /*}!NO_HEX_FP*/ + + static int +#ifdef KR_headers +dshift(b, p2) Bigint *b; int p2; +#else +dshift(Bigint *b, int p2) +#endif +{ + int rv = hi0bits(b->x[b->wds-1]) - 4; + if (p2 > 0) + rv -= p2; + return rv & kmask; + } + + static int +quorem +#ifdef KR_headers + (b, S) Bigint *b, *S; +#else + (Bigint *b, Bigint *S) +#endif +{ + int n; + ULong *bx, *bxe, q, *sx, *sxe; +#ifdef ULLong + ULLong borrow, carry, y, ys; +#else + ULong borrow, carry, y, ys; +#ifdef Pack_32 + ULong si, z, zs; +#endif +#endif + + n = S->wds; +#ifdef DEBUG + /*debug*/ if (b->wds > n) + /*debug*/ Bug("oversize b in quorem"); +#endif + if (b->wds < n) + return 0; + sx = S->x; + sxe = sx + --n; + bx = b->x; + bxe = bx + n; + q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ +#ifdef DEBUG + /*debug*/ if (q > 9) + /*debug*/ Bug("oversized quotient in quorem"); +#endif + if (q) { + borrow = 0; + carry = 0; + do { +#ifdef ULLong + ys = *sx++ * (ULLong)q + carry; + carry = ys >> 32; + y = *bx - (ys & FFFFFFFF) - borrow; + borrow = y >> 32 & (ULong)1; + *bx++ = y & FFFFFFFF; +#else +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) * q + carry; + zs = (si >> 16) * q + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*bx >> 16) - (zs & 0xffff) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(bx, z, y); +#else + ys = *sx++ * q + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + *bx++ = y & 0xffff; +#endif +#endif + } + while(sx <= sxe); + if (!*bxe) { + bx = b->x; + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + if (cmp(b, S) >= 0) { + q++; + borrow = 0; + carry = 0; + bx = b->x; + sx = S->x; + do { +#ifdef ULLong + ys = *sx++ + carry; + carry = ys >> 32; + y = *bx - (ys & FFFFFFFF) - borrow; + borrow = y >> 32 & (ULong)1; + *bx++ = y & FFFFFFFF; +#else +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) + carry; + zs = (si >> 16) + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*bx >> 16) - (zs & 0xffff) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(bx, z, y); +#else + ys = *sx++ + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + *bx++ = y & 0xffff; +#endif +#endif + } + while(sx <= sxe); + bx = b->x; + bxe = bx + n; + if (!*bxe) { + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + return q; + } + +#ifndef NO_STRTOD_BIGCOMP + + static void +bigcomp +#ifdef KR_headers + (rv, s0, bc) + U *rv; CONST char *s0; BCinfo *bc; +#else + (U *rv, CONST char *s0, BCinfo *bc) +#endif +{ + Bigint *b, *d; + int b2, bbits, d2, dd, dig, dsign, i, j, nd, nd0, p2, p5, speccase; + + dsign = bc->dsign; + nd = bc->nd; + nd0 = bc->nd0; + p5 = nd + bc->e0 - 1; + speccase = 0; +#ifndef Sudden_Underflow + if (rv->d == 0.) { /* special case: value near underflow-to-zero */ + /* threshold was rounded to zero */ + b = i2b(1); + p2 = Emin - P + 1; + bbits = 1; +#ifdef Avoid_Underflow + word0(rv) = (P+2) << Exp_shift; +#else + word1(rv) = 1; +#endif + i = 0; +#ifdef Honor_FLT_ROUNDS + if (bc->rounding == 1) +#endif + { + speccase = 1; + --p2; + dsign = 0; + goto have_i; + } + } + else +#endif + b = d2b(rv, &p2, &bbits); +#ifdef Avoid_Underflow + p2 -= bc->scale; +#endif + /* floor(log2(rv)) == bbits - 1 + p2 */ + /* Check for denormal case. */ + i = P - bbits; + if (i > (j = P - Emin - 1 + p2)) { +#ifdef Sudden_Underflow + Bfree(b); + b = i2b(1); + p2 = Emin; + i = P - 1; +#ifdef Avoid_Underflow + word0(rv) = (1 + bc->scale) << Exp_shift; +#else + word0(rv) = Exp_msk1; +#endif + word1(rv) = 0; +#else + i = j; +#endif + } +#ifdef Honor_FLT_ROUNDS + if (bc->rounding != 1) { + if (i > 0) + b = lshift(b, i); + if (dsign) + b = increment(b); + } + else +#endif + { + b = lshift(b, ++i); + b->x[0] |= 1; + } +#ifndef Sudden_Underflow + have_i: +#endif + p2 -= p5 + i; + d = i2b(1); + /* Arrange for convenient computation of quotients: + * shift left if necessary so divisor has 4 leading 0 bits. + */ + if (p5 > 0) + d = pow5mult(d, p5); + else if (p5 < 0) + b = pow5mult(b, -p5); + if (p2 > 0) { + b2 = p2; + d2 = 0; + } + else { + b2 = 0; + d2 = -p2; + } + i = dshift(d, d2); + if ((b2 += i) > 0) + b = lshift(b, b2); + if ((d2 += i) > 0) + d = lshift(d, d2); + + /* Now b/d = exactly half-way between the two floating-point values */ + /* on either side of the input string. Compute first digit of b/d. */ + + if (!(dig = quorem(b,d))) { + b = multadd(b, 10, 0); /* very unlikely */ + dig = quorem(b,d); + } + + /* Compare b/d with s0 */ + + for(i = 0; i < nd0; ) { + if ((dd = s0[i++] - '0' - dig)) + goto ret; + if (!b->x[0] && b->wds == 1) { + if (i < nd) + dd = 1; + goto ret; + } + b = multadd(b, 10, 0); + dig = quorem(b,d); + } + for(j = bc->dp1; i++ < nd;) { + if ((dd = s0[j++] - '0' - dig)) + goto ret; + if (!b->x[0] && b->wds == 1) { + if (i < nd) + dd = 1; + goto ret; + } + b = multadd(b, 10, 0); + dig = quorem(b,d); + } + if (b->x[0] || b->wds > 1) + dd = -1; + ret: + Bfree(b); + Bfree(d); +#ifdef Honor_FLT_ROUNDS + if (bc->rounding != 1) { + if (dd < 0) { + if (bc->rounding == 0) { + if (!dsign) + goto retlow1; + } + else if (dsign) + goto rethi1; + } + else if (dd > 0) { + if (bc->rounding == 0) { + if (dsign) + goto rethi1; + goto ret1; + } + if (!dsign) + goto rethi1; + dval(rv) += 2.*ulp(rv); + } + else { + bc->inexact = 0; + if (dsign) + goto rethi1; + } + } + else +#endif + if (speccase) { + if (dd <= 0) + rv->d = 0.; + } + else if (dd < 0) { + if (!dsign) /* does not happen for round-near */ +retlow1: + dval(rv) -= ulp(rv); + } + else if (dd > 0) { + if (dsign) { + rethi1: + dval(rv) += ulp(rv); + } + } + else { + /* Exact half-way case: apply round-even rule. */ + if (word1(rv) & 1) { + if (dsign) + goto rethi1; + goto retlow1; + } + } + +#ifdef Honor_FLT_ROUNDS + ret1: +#endif + return; + } +#endif /* NO_STRTOD_BIGCOMP */ + + double +strtod +#ifdef KR_headers + (s00, se) CONST char *s00; char **se; +#else + (CONST char *s00, char **se) +#endif +{ + int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, e, e1; + int esign, i, j, k, nd, nd0, nf, nz, nz0, sign; + CONST char *s, *s0, *s1; + double aadj, aadj1; + Long L; + U aadj2, adj, rv, rv0; + ULong y, z; + BCinfo bc; + Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; +#ifdef SET_INEXACT + int oldinexact; +#endif +#ifdef Honor_FLT_ROUNDS /*{*/ +#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ + bc.rounding = Flt_Rounds; +#else /*}{*/ + bc.rounding = 1; + switch(fegetround()) { + case FE_TOWARDZERO: bc.rounding = 0; break; + case FE_UPWARD: bc.rounding = 2; break; + case FE_DOWNWARD: bc.rounding = 3; + } +#endif /*}}*/ +#endif /*}*/ +#ifdef USE_LOCALE + CONST char *s2; +#endif + + sign = nz0 = nz = bc.dplen = bc.uflchk = 0; + dval(&rv) = 0.; + for(s = s00;;s++) switch(*s) { + case '-': + sign = 1; + /* no break */ + case '+': + if (*++s) + goto break2; + /* no break */ + case 0: + goto ret0; + case '\t': + case '\n': + case '\v': + case '\f': + case '\r': + case ' ': + continue; + default: + goto break2; + } + break2: + if (*s == '0') { +#ifndef NO_HEX_FP /*{*/ + switch(s[1]) { + case 'x': + case 'X': +#ifdef Honor_FLT_ROUNDS + gethex(&s, &rv, bc.rounding, sign); +#else + gethex(&s, &rv, 1, sign); +#endif + goto ret; + } +#endif /*}*/ + nz0 = 1; + while(*++s == '0') ; + if (!*s) + goto ret; + } + s0 = s; + y = z = 0; + for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) + if (nd < 9) + y = 10*y + c - '0'; + else if (nd < 16) + z = 10*z + c - '0'; + nd0 = nd; + bc.dp0 = bc.dp1 = s - s0; +#ifdef USE_LOCALE + s1 = localeconv()->decimal_point; + if (c == *s1) { + c = '.'; + if (*++s1) { + s2 = s; + for(;;) { + if (*++s2 != *s1) { + c = 0; + break; + } + if (!*++s1) { + s = s2; + break; + } + } + } + } +#endif + if (c == '.') { + c = *++s; + bc.dp1 = s - s0; + bc.dplen = bc.dp1 - bc.dp0; + if (!nd) { + for(; c == '0'; c = *++s) + nz++; + if (c > '0' && c <= '9') { + s0 = s; + nf += nz; + nz = 0; + goto have_dig; + } + goto dig_done; + } + for(; c >= '0' && c <= '9'; c = *++s) { + have_dig: + nz++; + if (c -= '0') { + nf += nz; + for(i = 1; i < nz; i++) + if (nd++ < 9) + y *= 10; + else if (nd <= DBL_DIG + 1) + z *= 10; + if (nd++ < 9) + y = 10*y + c; + else if (nd <= DBL_DIG + 1) + z = 10*z + c; + nz = 0; + } + } + } + dig_done: + e = 0; + if (c == 'e' || c == 'E') { + if (!nd && !nz && !nz0) { + goto ret0; + } + s00 = s; + esign = 0; + switch(c = *++s) { + case '-': + esign = 1; + case '+': + c = *++s; + } + if (c >= '0' && c <= '9') { + while(c == '0') + c = *++s; + if (c > '0' && c <= '9') { + L = c - '0'; + s1 = s; + while((c = *++s) >= '0' && c <= '9') + L = 10*L + c - '0'; + if (s - s1 > 8 || L > 19999) + /* Avoid confusion from exponents + * so large that e might overflow. + */ + e = 19999; /* safe for 16 bit ints */ + else + e = (int)L; + if (esign) + e = -e; + } + else + e = 0; + } + else + s = s00; + } + if (!nd) { + if (!nz && !nz0) { +#ifdef INFNAN_CHECK + /* Check for Nan and Infinity */ + switch(c) { + case 'i': + case 'I': + if (match(&s,"nf")) { + --s; + if (!match(&s,"inity")) + ++s; + word0(&rv) = 0x7ff00000; + word1(&rv) = 0; + goto ret; + } + break; + case 'n': + case 'N': + if (match(&s, "an")) { + word0(&rv) = NAN_WORD0; + word1(&rv) = NAN_WORD1; +#ifndef No_Hex_NaN + if (*s == '(') /*)*/ + hexnan(&rv, &s); +#endif + goto ret; + } + } +#endif /* INFNAN_CHECK */ + ret0: + s = s00; + sign = 0; + } + goto ret; + } + bc.e0 = e1 = e -= nf; + + /* Now we have nd0 digits, starting at s0, followed by a + * decimal point, followed by nd-nd0 digits. The number we're + * after is the integer represented by those digits times + * 10**e */ + + if (!nd0) + nd0 = nd; + k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; + dval(&rv) = y; + if (k > 9) { +#ifdef SET_INEXACT + if (k > DBL_DIG) + oldinexact = get_inexact(); +#endif + dval(&rv) = tens[k - 9] * dval(&rv) + z; + } + bd0 = 0; + if (nd <= DBL_DIG +#ifndef RND_PRODQUOT +#ifndef Honor_FLT_ROUNDS + && Flt_Rounds == 1 +#endif +#endif + ) { + if (!e) + goto ret; + if (e > 0) { + if (e <= Ten_pmax) { +#ifdef VAX + goto vax_ovfl_check; +#else +#ifdef Honor_FLT_ROUNDS + /* round correctly FLT_ROUNDS = 2 or 3 */ + if (sign) { + rv.d = -rv.d; + sign = 0; + } +#endif + /* rv = */ rounded_product(dval(&rv), tens[e]); + goto ret; +#endif + } + i = DBL_DIG - nd; + if (e <= Ten_pmax + i) { + /* A fancier test would sometimes let us do + * this for larger i values. + */ +#ifdef Honor_FLT_ROUNDS + /* round correctly FLT_ROUNDS = 2 or 3 */ + if (sign) { + rv.d = -rv.d; + sign = 0; + } +#endif + e -= i; + dval(&rv) *= tens[i]; +#ifdef VAX + /* VAX exponent range is so narrow we must + * worry about overflow here... + */ + vax_ovfl_check: + word0(&rv) -= P*Exp_msk1; + /* rv = */ rounded_product(dval(&rv), tens[e]); + if ((word0(&rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) + goto ovfl; + word0(&rv) += P*Exp_msk1; +#else + /* rv = */ rounded_product(dval(&rv), tens[e]); +#endif + goto ret; + } + } +#ifndef Inaccurate_Divide + else if (e >= -Ten_pmax) { +#ifdef Honor_FLT_ROUNDS + /* round correctly FLT_ROUNDS = 2 or 3 */ + if (sign) { + rv.d = -rv.d; + sign = 0; + } +#endif + /* rv = */ rounded_quotient(dval(&rv), tens[-e]); + goto ret; + } +#endif + } + e1 += nd - k; + +#ifdef IEEE_Arith +#ifdef SET_INEXACT + bc.inexact = 1; + if (k <= DBL_DIG) + oldinexact = get_inexact(); +#endif +#ifdef Avoid_Underflow + bc.scale = 0; +#endif +#ifdef Honor_FLT_ROUNDS + if (bc.rounding >= 2) { + if (sign) + bc.rounding = bc.rounding == 2 ? 0 : 2; + else + if (bc.rounding != 2) + bc.rounding = 0; + } +#endif +#endif /*IEEE_Arith*/ + + /* Get starting approximation = rv * 10**e1 */ + + if (e1 > 0) { + if ((i = e1 & 15)) + dval(&rv) *= tens[i]; + if (e1 &= ~15) { + if (e1 > DBL_MAX_10_EXP) { + ovfl: +#ifndef NO_ERRNO + errno = ERANGE; +#endif + /* Can't trust HUGE_VAL */ +#ifdef IEEE_Arith +#ifdef Honor_FLT_ROUNDS + switch(bc.rounding) { + case 0: /* toward 0 */ + case 3: /* toward -infinity */ + word0(&rv) = Big0; + word1(&rv) = Big1; + break; + default: + word0(&rv) = Exp_mask; + word1(&rv) = 0; + } +#else /*Honor_FLT_ROUNDS*/ + word0(&rv) = Exp_mask; + word1(&rv) = 0; +#endif /*Honor_FLT_ROUNDS*/ +#ifdef SET_INEXACT + /* set overflow bit */ + dval(&rv0) = 1e300; + dval(&rv0) *= dval(&rv0); +#endif +#else /*IEEE_Arith*/ + word0(&rv) = Big0; + word1(&rv) = Big1; +#endif /*IEEE_Arith*/ + goto ret; + } + e1 >>= 4; + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + dval(&rv) *= bigtens[j]; + /* The last multiplication could overflow. */ + word0(&rv) -= P*Exp_msk1; + dval(&rv) *= bigtens[j]; + if ((z = word0(&rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-P)) + goto ovfl; + if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { + /* set to largest number */ + /* (Can't trust DBL_MAX) */ + word0(&rv) = Big0; + word1(&rv) = Big1; + } + else + word0(&rv) += P*Exp_msk1; + } + } + else if (e1 < 0) { + e1 = -e1; + if ((i = e1 & 15)) + dval(&rv) /= tens[i]; + if (e1 >>= 4) { + if (e1 >= 1 << n_bigtens) + goto undfl; +#ifdef Avoid_Underflow + if (e1 & Scale_Bit) + bc.scale = 2*P; + for(j = 0; e1 > 0; j++, e1 >>= 1) + if (e1 & 1) + dval(&rv) *= tinytens[j]; + if (bc.scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask) + >> Exp_shift)) > 0) { + /* scaled rv is denormal; clear j low bits */ + if (j >= 32) { + word1(&rv) = 0; + if (j >= 53) + word0(&rv) = (P+2)*Exp_msk1; + else + word0(&rv) &= 0xffffffff << (j-32); + } + else + word1(&rv) &= 0xffffffff << j; + } +#else + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + dval(&rv) *= tinytens[j]; + /* The last multiplication could underflow. */ + dval(&rv0) = dval(&rv); + dval(&rv) *= tinytens[j]; + if (!dval(&rv)) { + dval(&rv) = 2.*dval(&rv0); + dval(&rv) *= tinytens[j]; +#endif + if (!dval(&rv)) { + undfl: + dval(&rv) = 0.; +#ifndef NO_ERRNO + errno = ERANGE; +#endif + goto ret; + } +#ifndef Avoid_Underflow + word0(&rv) = Tiny0; + word1(&rv) = Tiny1; + /* The refinement below will clean + * this approximation up. + */ + } +#endif + } + } + + /* Now the hard part -- adjusting rv to the correct value.*/ + + /* Put digits into bd: true value = bd * 10^e */ + + bc.nd = nd; +#ifndef NO_STRTOD_BIGCOMP + bc.nd0 = nd0; /* Only needed if nd > strtod_diglim, but done here */ + /* to silence an erroneous warning about bc.nd0 */ + /* possibly not being initialized. */ + if (nd > strtod_diglim) { + /* ASSERT(strtod_diglim >= 18); 18 == one more than the */ + /* minimum number of decimal digits to distinguish double values */ + /* in IEEE arithmetic. */ + i = j = 18; + if (i > nd0) + j += bc.dplen; + for(;;) { + if (--j <= bc.dp1 && j >= bc.dp0) + j = bc.dp0 - 1; + if (s0[j] != '0') + break; + --i; + } + e += nd - i; + nd = i; + if (nd0 > nd) + nd0 = nd; + if (nd < 9) { /* must recompute y */ + y = 0; + for(i = 0; i < nd0; ++i) + y = 10*y + s0[i] - '0'; + for(j = bc.dp1; i < nd; ++i) + y = 10*y + s0[j++] - '0'; + } + } +#endif + bd0 = s2b(s0, nd0, nd, y, bc.dplen); + + for(;;) { + bd = Balloc(bd0->k); + Bcopy(bd, bd0); + bb = d2b(&rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ + bs = i2b(1); + + if (e >= 0) { + bb2 = bb5 = 0; + bd2 = bd5 = e; + } + else { + bb2 = bb5 = -e; + bd2 = bd5 = 0; + } + if (bbe >= 0) + bb2 += bbe; + else + bd2 -= bbe; + bs2 = bb2; +#ifdef Honor_FLT_ROUNDS + if (bc.rounding != 1) + bs2++; +#endif +#ifdef Avoid_Underflow + j = bbe - bc.scale; + i = j + bbbits - 1; /* logb(rv) */ + if (i < Emin) /* denormal */ + j += P - Emin; + else + j = P + 1 - bbbits; +#else /*Avoid_Underflow*/ +#ifdef Sudden_Underflow +#ifdef IBM + j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); +#else + j = P + 1 - bbbits; +#endif +#else /*Sudden_Underflow*/ + j = bbe; + i = j + bbbits - 1; /* logb(rv) */ + if (i < Emin) /* denormal */ + j += P - Emin; + else + j = P + 1 - bbbits; +#endif /*Sudden_Underflow*/ +#endif /*Avoid_Underflow*/ + bb2 += j; + bd2 += j; +#ifdef Avoid_Underflow + bd2 += bc.scale; +#endif + i = bb2 < bd2 ? bb2 : bd2; + if (i > bs2) + i = bs2; + if (i > 0) { + bb2 -= i; + bd2 -= i; + bs2 -= i; + } + if (bb5 > 0) { + bs = pow5mult(bs, bb5); + bb1 = mult(bs, bb); + Bfree(bb); + bb = bb1; + } + if (bb2 > 0) + bb = lshift(bb, bb2); + if (bd5 > 0) + bd = pow5mult(bd, bd5); + if (bd2 > 0) + bd = lshift(bd, bd2); + if (bs2 > 0) + bs = lshift(bs, bs2); + delta = diff(bb, bd); + bc.dsign = delta->sign; + delta->sign = 0; + i = cmp(delta, bs); +#ifndef NO_STRTOD_BIGCOMP + if (bc.nd > nd && i <= 0) { + if (bc.dsign) + break; /* Must use bigcomp(). */ +#ifdef Honor_FLT_ROUNDS + if (bc.rounding != 1) { + if (i < 0) + break; + } + else +#endif + { + bc.nd = nd; + i = -1; /* Discarded digits make delta smaller. */ + } + } +#endif +#ifdef Honor_FLT_ROUNDS + if (bc.rounding != 1) { + if (i < 0) { + /* Error is less than an ulp */ + if (!delta->x[0] && delta->wds <= 1) { + /* exact */ +#ifdef SET_INEXACT + bc.inexact = 0; +#endif + break; + } + if (bc.rounding) { + if (bc.dsign) { + adj.d = 1.; + goto apply_adj; + } + } + else if (!bc.dsign) { + adj.d = -1.; + if (!word1(&rv) + && !(word0(&rv) & Frac_mask)) { + y = word0(&rv) & Exp_mask; +#ifdef Avoid_Underflow + if (!bc.scale || y > 2*P*Exp_msk1) +#else + if (y) +#endif + { + delta = lshift(delta,Log2P); + if (cmp(delta, bs) <= 0) + adj.d = -0.5; + } + } + apply_adj: +#ifdef Avoid_Underflow + if (bc.scale && (y = word0(&rv) & Exp_mask) + <= 2*P*Exp_msk1) + word0(&adj) += (2*P+1)*Exp_msk1 - y; +#else +#ifdef Sudden_Underflow + if ((word0(&rv) & Exp_mask) <= + P*Exp_msk1) { + word0(&rv) += P*Exp_msk1; + dval(&rv) += adj.d*ulp(dval(&rv)); + word0(&rv) -= P*Exp_msk1; + } + else +#endif /*Sudden_Underflow*/ +#endif /*Avoid_Underflow*/ + dval(&rv) += adj.d*ulp(&rv); + } + break; + } + adj.d = ratio(delta, bs); + if (adj.d < 1.) + adj.d = 1.; + if (adj.d <= 0x7ffffffe) { + /* adj = rounding ? ceil(adj) : floor(adj); */ + y = adj.d; + if (y != adj.d) { + if (!((bc.rounding>>1) ^ bc.dsign)) + y++; + adj.d = y; + } + } +#ifdef Avoid_Underflow + if (bc.scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) + word0(&adj) += (2*P+1)*Exp_msk1 - y; +#else +#ifdef Sudden_Underflow + if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { + word0(&rv) += P*Exp_msk1; + adj.d *= ulp(dval(&rv)); + if (bc.dsign) + dval(&rv) += adj.d; + else + dval(&rv) -= adj.d; + word0(&rv) -= P*Exp_msk1; + goto cont; + } +#endif /*Sudden_Underflow*/ +#endif /*Avoid_Underflow*/ + adj.d *= ulp(&rv); + if (bc.dsign) { + if (word0(&rv) == Big0 && word1(&rv) == Big1) + goto ovfl; + dval(&rv) += adj.d; + } + else + dval(&rv) -= adj.d; + goto cont; + } +#endif /*Honor_FLT_ROUNDS*/ + + if (i < 0) { + /* Error is less than half an ulp -- check for + * special case of mantissa a power of two. + */ + if (bc.dsign || word1(&rv) || word0(&rv) & Bndry_mask +#ifdef IEEE_Arith +#ifdef Avoid_Underflow + || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1 +#else + || (word0(&rv) & Exp_mask) <= Exp_msk1 +#endif +#endif + ) { +#ifdef SET_INEXACT + if (!delta->x[0] && delta->wds <= 1) + bc.inexact = 0; +#endif + break; + } + if (!delta->x[0] && delta->wds <= 1) { + /* exact result */ +#ifdef SET_INEXACT + bc.inexact = 0; +#endif + break; + } + delta = lshift(delta,Log2P); + if (cmp(delta, bs) > 0) + goto drop_down; + break; + } + if (i == 0) { + /* exactly half-way between */ + if (bc.dsign) { + if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 + && word1(&rv) == ( +#ifdef Avoid_Underflow + (bc.scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) + ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : +#endif + 0xffffffff)) { + /*boundary case -- increment exponent*/ + word0(&rv) = (word0(&rv) & Exp_mask) + + Exp_msk1 +#ifdef IBM + | Exp_msk1 >> 4 +#endif + ; + word1(&rv) = 0; +#ifdef Avoid_Underflow + bc.dsign = 0; +#endif + break; + } + } + else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) { + drop_down: + /* boundary case -- decrement exponent */ +#ifdef Sudden_Underflow /*{{*/ + L = word0(&rv) & Exp_mask; +#ifdef IBM + if (L < Exp_msk1) +#else +#ifdef Avoid_Underflow + if (L <= (bc.scale ? (2*P+1)*Exp_msk1 : Exp_msk1)) +#else + if (L <= Exp_msk1) +#endif /*Avoid_Underflow*/ +#endif /*IBM*/ + { + if (bc.nd >nd) { + bc.uflchk = 1; + break; + } + goto undfl; + } + L -= Exp_msk1; +#else /*Sudden_Underflow}{*/ +#ifdef Avoid_Underflow + if (bc.scale) { + L = word0(&rv) & Exp_mask; + if (L <= (2*P+1)*Exp_msk1) { + if (L > (P+2)*Exp_msk1) + /* round even ==> */ + /* accept rv */ + break; + /* rv = smallest denormal */ + if (bc.nd >nd) { + bc.uflchk = 1; + break; + } + goto undfl; + } + } +#endif /*Avoid_Underflow*/ + L = (word0(&rv) & Exp_mask) - Exp_msk1; +#endif /*Sudden_Underflow}}*/ + word0(&rv) = L | Bndry_mask1; + word1(&rv) = 0xffffffff; +#ifdef IBM + goto cont; +#else + break; +#endif + } +#ifndef ROUND_BIASED + if (!(word1(&rv) & LSB)) + break; +#endif + if (bc.dsign) + dval(&rv) += ulp(&rv); +#ifndef ROUND_BIASED + else { + dval(&rv) -= ulp(&rv); +#ifndef Sudden_Underflow + if (!dval(&rv)) { + if (bc.nd >nd) { + bc.uflchk = 1; + break; + } + goto undfl; + } +#endif + } +#ifdef Avoid_Underflow + bc.dsign = 1 - bc.dsign; +#endif +#endif + break; + } + if ((aadj = ratio(delta, bs)) <= 2.) { + if (bc.dsign) + aadj = aadj1 = 1.; + else if (word1(&rv) || word0(&rv) & Bndry_mask) { +#ifndef Sudden_Underflow + if (word1(&rv) == Tiny1 && !word0(&rv)) { + if (bc.nd >nd) { + bc.uflchk = 1; + break; + } + goto undfl; + } +#endif + aadj = 1.; + aadj1 = -1.; + } + else { + /* special case -- power of FLT_RADIX to be */ + /* rounded down... */ + + if (aadj < 2./FLT_RADIX) + aadj = 1./FLT_RADIX; + else + aadj *= 0.5; + aadj1 = -aadj; + } + } + else { + aadj *= 0.5; + aadj1 = bc.dsign ? aadj : -aadj; +#ifdef Check_FLT_ROUNDS + switch(bc.rounding) { + case 2: /* towards +infinity */ + aadj1 -= 0.5; + break; + case 0: /* towards 0 */ + case 3: /* towards -infinity */ + aadj1 += 0.5; + } +#else + if (Flt_Rounds == 0) + aadj1 += 0.5; +#endif /*Check_FLT_ROUNDS*/ + } + y = word0(&rv) & Exp_mask; + + /* Check for overflow */ + + if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { + dval(&rv0) = dval(&rv); + word0(&rv) -= P*Exp_msk1; + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; + if ((word0(&rv) & Exp_mask) >= + Exp_msk1*(DBL_MAX_EXP+Bias-P)) { + if (word0(&rv0) == Big0 && word1(&rv0) == Big1) + goto ovfl; + word0(&rv) = Big0; + word1(&rv) = Big1; + goto cont; + } + else + word0(&rv) += P*Exp_msk1; + } + else { +#ifdef Avoid_Underflow + if (bc.scale && y <= 2*P*Exp_msk1) { + if (aadj <= 0x7fffffff) { + if ((z = aadj) <= 0) + z = 1; + aadj = z; + aadj1 = bc.dsign ? aadj : -aadj; + } + dval(&aadj2) = aadj1; + word0(&aadj2) += (2*P+1)*Exp_msk1 - y; + aadj1 = dval(&aadj2); + } + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; +#else +#ifdef Sudden_Underflow + if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { + dval(&rv0) = dval(&rv); + word0(&rv) += P*Exp_msk1; + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; +#ifdef IBM + if ((word0(&rv) & Exp_mask) < P*Exp_msk1) +#else + if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) +#endif + { + if (word0(&rv0) == Tiny0 + && word1(&rv0) == Tiny1) { + if (bc.nd >nd) { + bc.uflchk = 1; + break; + } + goto undfl; + } + word0(&rv) = Tiny0; + word1(&rv) = Tiny1; + goto cont; + } + else + word0(&rv) -= P*Exp_msk1; + } + else { + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; + } +#else /*Sudden_Underflow*/ + /* Compute adj so that the IEEE rounding rules will + * correctly round rv + adj in some half-way cases. + * If rv * ulp(rv) is denormalized (i.e., + * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid + * trouble from bits lost to denormalization; + * example: 1.2e-307 . + */ + if (y <= (P-1)*Exp_msk1 && aadj > 1.) { + aadj1 = (double)(int)(aadj + 0.5); + if (!bc.dsign) + aadj1 = -aadj1; + } + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; +#endif /*Sudden_Underflow*/ +#endif /*Avoid_Underflow*/ + } + z = word0(&rv) & Exp_mask; +#ifndef SET_INEXACT + if (bc.nd == nd) { +#ifdef Avoid_Underflow + if (!bc.scale) +#endif + if (y == z) { + /* Can we stop now? */ + L = (Long)aadj; + aadj -= L; + /* The tolerances below are conservative. */ + if (bc.dsign || word1(&rv) || word0(&rv) & Bndry_mask) { + if (aadj < .4999999 || aadj > .5000001) + break; + } + else if (aadj < .4999999/FLT_RADIX) + break; + } + } +#endif + cont: + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(delta); + } + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); +#ifndef NO_STRTOD_BIGCOMP + if (bc.nd > nd) + bigcomp(&rv, s0, &bc); +#endif +#ifdef SET_INEXACT + if (bc.inexact) { + if (!oldinexact) { + word0(&rv0) = Exp_1 + (70 << Exp_shift); + word1(&rv0) = 0; + dval(&rv0) += 1.; + } + } + else if (!oldinexact) + clear_inexact(); +#endif +#ifdef Avoid_Underflow + if (bc.scale) { + word0(&rv0) = Exp_1 - 2*P*Exp_msk1; + word1(&rv0) = 0; + dval(&rv) *= dval(&rv0); +#ifndef NO_ERRNO + /* try to avoid the bug of testing an 8087 register value */ +#ifdef IEEE_Arith + if (!(word0(&rv) & Exp_mask)) +#else + if (word0(&rv) == 0 && word1(&rv) == 0) +#endif + errno = ERANGE; +#endif + } +#endif /* Avoid_Underflow */ +#ifdef SET_INEXACT + if (bc.inexact && !(word0(&rv) & Exp_mask)) { + /* set underflow bit */ + dval(&rv0) = 1e-300; + dval(&rv0) *= dval(&rv0); + } +#endif + ret: + if (se) + *se = (char *)s; + return sign ? -dval(&rv) : dval(&rv); + } + +#ifndef MULTIPLE_THREADS + static char *dtoa_result; +#endif + + static char * +#ifdef KR_headers +rv_alloc(i) int i; +#else +rv_alloc(int i) +#endif +{ + int j, k, *r; + + j = sizeof(ULong); + for(k = 0; + sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i; + j <<= 1) + k++; + r = (int*)Balloc(k); + *r = k; + return +#ifndef MULTIPLE_THREADS + dtoa_result = +#endif + (char *)(r+1); + } + + static char * +#ifdef KR_headers +nrv_alloc(s, rve, n) char *s, **rve; int n; +#else +nrv_alloc(char *s, char **rve, int n) +#endif +{ + char *rv, *t; + + t = rv = rv_alloc(n); + while((*t = *s++)) t++; + if (rve) + *rve = t; + return rv; + } + +/* freedtoa(s) must be used to free values s returned by dtoa + * when MULTIPLE_THREADS is #defined. It should be used in all cases, + * but for consistency with earlier versions of dtoa, it is optional + * when MULTIPLE_THREADS is not defined. + */ + + void +#ifdef KR_headers +freedtoa(s) char *s; +#else +freedtoa(char *s) +#endif +{ + Bigint *b = (Bigint *)((int *)s - 1); + b->maxwds = 1 << (b->k = *(int*)b); + Bfree(b); +#ifndef MULTIPLE_THREADS + if (s == dtoa_result) + dtoa_result = 0; +#endif + } + +/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. + * + * Inspired by "How to Print Floating-Point Numbers Accurately" by + * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. + * + * Modifications: + * 1. Rather than iterating, we use a simple numeric overestimate + * to determine k = floor(log10(d)). We scale relevant + * quantities using O(log2(k)) rather than O(k) multiplications. + * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't + * try to generate digits strictly left to right. Instead, we + * compute with fewer bits and propagate the carry if necessary + * when rounding the final digit up. This is often faster. + * 3. Under the assumption that input will be rounded nearest, + * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. + * That is, we allow equality in stopping tests when the + * round-nearest rule will give the same floating-point value + * as would satisfaction of the stopping test with strict + * inequality. + * 4. We remove common factors of powers of 2 from relevant + * quantities. + * 5. When converting floating-point integers less than 1e16, + * we use floating-point arithmetic rather than resorting + * to multiple-precision integers. + * 6. When asked to produce fewer than 15 digits, we first try + * to get by with floating-point arithmetic; we resort to + * multiple-precision integer arithmetic only if we cannot + * guarantee that the floating-point calculation has given + * the correctly rounded result. For k requested digits and + * "uniformly" distributed input, the probability is + * something like 10^(k-15) that we must resort to the Long + * calculation. + */ + + char * +dtoa +#ifdef KR_headers + (dd, mode, ndigits, decpt, sign, rve) + double dd; int mode, ndigits, *decpt, *sign; char **rve; +#else + (double dd, int mode, int ndigits, int *decpt, int *sign, char **rve) +#endif +{ + /* Arguments ndigits, decpt, sign are similar to those + of ecvt and fcvt; trailing zeros are suppressed from + the returned string. If not null, *rve is set to point + to the end of the return value. If d is +-Infinity or NaN, + then *decpt is set to 9999. + + mode: + 0 ==> shortest string that yields d when read in + and rounded to nearest. + 1 ==> like 0, but with Steele & White stopping rule; + e.g. with IEEE P754 arithmetic , mode 0 gives + 1e23 whereas mode 1 gives 9.999999999999999e22. + 2 ==> max(1,ndigits) significant digits. This gives a + return value similar to that of ecvt, except + that trailing zeros are suppressed. + 3 ==> through ndigits past the decimal point. This + gives a return value similar to that from fcvt, + except that trailing zeros are suppressed, and + ndigits can be negative. + 4,5 ==> similar to 2 and 3, respectively, but (in + round-nearest mode) with the tests of mode 0 to + possibly return a shorter string that rounds to d. + With IEEE arithmetic and compilation with + -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same + as modes 2 and 3 when FLT_ROUNDS != 1. + 6-9 ==> Debugging modes similar to mode - 4: don't try + fast floating-point estimate (if applicable). + + Values of mode other than 0-9 are treated as mode 0. + + Sufficient space is allocated to the return value + to hold the suppressed trailing zeros. + */ + + int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, + j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, + spec_case, try_quick; + Long L; +#ifndef Sudden_Underflow + int denorm; + ULong x; +#endif + Bigint *b, *b1, *delta, *mlo, *mhi, *S; + U d2, eps, u; + double ds; + char *s, *s0; +#ifdef SET_INEXACT + int inexact, oldinexact; +#endif +#ifdef Honor_FLT_ROUNDS /*{*/ + int Rounding; +#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ + Rounding = Flt_Rounds; +#else /*}{*/ + Rounding = 1; + switch(fegetround()) { + case FE_TOWARDZERO: Rounding = 0; break; + case FE_UPWARD: Rounding = 2; break; + case FE_DOWNWARD: Rounding = 3; + } +#endif /*}}*/ +#endif /*}*/ + +#ifndef MULTIPLE_THREADS + if (dtoa_result) { + freedtoa(dtoa_result); + dtoa_result = 0; + } +#endif + + u.d = dd; + if (word0(&u) & Sign_bit) { + /* set sign for everything, including 0's and NaNs */ + *sign = 1; + word0(&u) &= ~Sign_bit; /* clear sign bit */ + } + else + *sign = 0; + +#if defined(IEEE_Arith) + defined(VAX) +#ifdef IEEE_Arith + if ((word0(&u) & Exp_mask) == Exp_mask) +#else + if (word0(&u) == 0x8000) +#endif + { + /* Infinity or NaN */ + *decpt = 9999; +#ifdef IEEE_Arith + if (!word1(&u) && !(word0(&u) & 0xfffff)) + return nrv_alloc("Infinity", rve, 8); +#endif + return nrv_alloc("NaN", rve, 3); + } +#endif +#ifdef IBM + dval(&u) += 0; /* normalize */ +#endif + if (!dval(&u)) { + *decpt = 1; + return nrv_alloc("0", rve, 1); + } + +#ifdef SET_INEXACT + try_quick = oldinexact = get_inexact(); + inexact = 1; +#endif +#ifdef Honor_FLT_ROUNDS + if (Rounding >= 2) { + if (*sign) + Rounding = Rounding == 2 ? 0 : 2; + else + if (Rounding != 2) + Rounding = 0; + } +#endif + + b = d2b(&u, &be, &bbits); +#ifdef Sudden_Underflow + i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); +#else + if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) { +#endif + dval(&d2) = dval(&u); + word0(&d2) &= Frac_mask1; + word0(&d2) |= Exp_11; +#ifdef IBM + if (j = 11 - hi0bits(word0(&d2) & Frac_mask)) + dval(&d2) /= 1 << j; +#endif + + /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 + * log10(x) = log(x) / log(10) + * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) + * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) + * + * This suggests computing an approximation k to log10(d) by + * + * k = (i - Bias)*0.301029995663981 + * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); + * + * We want k to be too large rather than too small. + * The error in the first-order Taylor series approximation + * is in our favor, so we just round up the constant enough + * to compensate for any error in the multiplication of + * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, + * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, + * adding 1e-13 to the constant term more than suffices. + * Hence we adjust the constant term to 0.1760912590558. + * (We could get a more accurate k by invoking log10, + * but this is probably not worthwhile.) + */ + + i -= Bias; +#ifdef IBM + i <<= 2; + i += j; +#endif +#ifndef Sudden_Underflow + denorm = 0; + } + else { + /* d is denormalized */ + + i = bbits + be + (Bias + (P-1) - 1); + x = i > 32 ? word0(&u) << (64 - i) | word1(&u) >> (i - 32) + : word1(&u) << (32 - i); + dval(&d2) = x; + word0(&d2) -= 31*Exp_msk1; /* adjust exponent */ + i -= (Bias + (P-1) - 1) + 1; + denorm = 1; + } +#endif + ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + k = (int)ds; + if (ds < 0. && ds != k) + k--; /* want k = floor(ds) */ + k_check = 1; + if (k >= 0 && k <= Ten_pmax) { + if (dval(&u) < tens[k]) + k--; + k_check = 0; + } + j = bbits - i - 1; + if (j >= 0) { + b2 = 0; + s2 = j; + } + else { + b2 = -j; + s2 = 0; + } + if (k >= 0) { + b5 = 0; + s5 = k; + s2 += k; + } + else { + b2 -= k; + b5 = -k; + s5 = 0; + } + if (mode < 0 || mode > 9) + mode = 0; + +#ifndef SET_INEXACT +#ifdef Check_FLT_ROUNDS + try_quick = Rounding == 1; +#else + try_quick = 1; +#endif +#endif /*SET_INEXACT*/ + + if (mode > 5) { + mode -= 4; + try_quick = 0; + } + leftright = 1; + ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */ + /* silence erroneous "gcc -Wall" warning. */ + switch(mode) { + case 0: + case 1: + i = 18; + ndigits = 0; + break; + case 2: + leftright = 0; + /* no break */ + case 4: + if (ndigits <= 0) + ndigits = 1; + ilim = ilim1 = i = ndigits; + break; + case 3: + leftright = 0; + /* no break */ + case 5: + i = ndigits + k + 1; + ilim = i; + ilim1 = i - 1; + if (i <= 0) + i = 1; + } + s = s0 = rv_alloc(i); + +#ifdef Honor_FLT_ROUNDS + if (mode > 1 && Rounding != 1) + leftright = 0; +#endif + + if (ilim >= 0 && ilim <= Quick_max && try_quick) { + + /* Try to get by with floating-point arithmetic. */ + + i = 0; + dval(&d2) = dval(&u); + k0 = k; + ilim0 = ilim; + ieps = 2; /* conservative */ + if (k > 0) { + ds = tens[k&0xf]; + j = k >> 4; + if (j & Bletch) { + /* prevent overflows */ + j &= Bletch - 1; + dval(&u) /= bigtens[n_bigtens-1]; + ieps++; + } + for(; j; j >>= 1, i++) + if (j & 1) { + ieps++; + ds *= bigtens[i]; + } + dval(&u) /= ds; + } + else if ((j1 = -k)) { + dval(&u) *= tens[j1 & 0xf]; + for(j = j1 >> 4; j; j >>= 1, i++) + if (j & 1) { + ieps++; + dval(&u) *= bigtens[i]; + } + } + if (k_check && dval(&u) < 1. && ilim > 0) { + if (ilim1 <= 0) + goto fast_failed; + ilim = ilim1; + k--; + dval(&u) *= 10.; + ieps++; + } + dval(&eps) = ieps*dval(&u) + 7.; + word0(&eps) -= (P-1)*Exp_msk1; + if (ilim == 0) { + S = mhi = 0; + dval(&u) -= 5.; + if (dval(&u) > dval(&eps)) + goto one_digit; + if (dval(&u) < -dval(&eps)) + goto no_digits; + goto fast_failed; + } +#ifndef No_leftright + if (leftright) { + /* Use Steele & White method of only + * generating digits needed. + */ + dval(&eps) = 0.5/tens[ilim-1] - dval(&eps); + for(i = 0;;) { + L = dval(&u); + dval(&u) -= L; + *s++ = '0' + (int)L; + if (dval(&u) < dval(&eps)) + goto ret1; + if (1. - dval(&u) < dval(&eps)) + goto bump_up; + if (++i >= ilim) + break; + dval(&eps) *= 10.; + dval(&u) *= 10.; + } + } + else { +#endif + /* Generate ilim digits, then fix them up. */ + dval(&eps) *= tens[ilim-1]; + for(i = 1;; i++, dval(&u) *= 10.) { + L = (Long)(dval(&u)); + if (!(dval(&u) -= L)) + ilim = i; + *s++ = '0' + (int)L; + if (i == ilim) { + if (dval(&u) > 0.5 + dval(&eps)) + goto bump_up; + else if (dval(&u) < 0.5 - dval(&eps)) { + while(*--s == '0'); + s++; + goto ret1; + } + break; + } + } +#ifndef No_leftright + } +#endif + fast_failed: + s = s0; + dval(&u) = dval(&d2); + k = k0; + ilim = ilim0; + } + + /* Do we have a "small" integer? */ + + if (be >= 0 && k <= Int_max) { + /* Yes. */ + ds = tens[k]; + if (ndigits < 0 && ilim <= 0) { + S = mhi = 0; + if (ilim < 0 || dval(&u) <= 5*ds) + goto no_digits; + goto one_digit; + } + for(i = 1;; i++, dval(&u) *= 10.) { + L = (Long)(dval(&u) / ds); + dval(&u) -= L*ds; +#ifdef Check_FLT_ROUNDS + /* If FLT_ROUNDS == 2, L will usually be high by 1 */ + if (dval(&u) < 0) { + L--; + dval(&u) += ds; + } +#endif + *s++ = '0' + (int)L; + if (!dval(&u)) { +#ifdef SET_INEXACT + inexact = 0; +#endif + break; + } + if (i == ilim) { +#ifdef Honor_FLT_ROUNDS + if (mode > 1) + switch(Rounding) { + case 0: goto ret1; + case 2: goto bump_up; + } +#endif + dval(&u) += dval(&u); + if (dval(&u) > ds || (dval(&u) == ds && L & 1)) { + bump_up: + while(*--s == '9') + if (s == s0) { + k++; + *s = '0'; + break; + } + ++*s++; + } + break; + } + } + goto ret1; + } + + m2 = b2; + m5 = b5; + mhi = mlo = 0; + if (leftright) { + i = +#ifndef Sudden_Underflow + denorm ? be + (Bias + (P-1) - 1 + 1) : +#endif +#ifdef IBM + 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3); +#else + 1 + P - bbits; +#endif + b2 += i; + s2 += i; + mhi = i2b(1); + } + if (m2 > 0 && s2 > 0) { + i = m2 < s2 ? m2 : s2; + b2 -= i; + m2 -= i; + s2 -= i; + } + if (b5 > 0) { + if (leftright) { + if (m5 > 0) { + mhi = pow5mult(mhi, m5); + b1 = mult(mhi, b); + Bfree(b); + b = b1; + } + if ((j = b5 - m5)) + b = pow5mult(b, j); + } + else + b = pow5mult(b, b5); + } + S = i2b(1); + if (s5 > 0) + S = pow5mult(S, s5); + + /* Check for special case that d is a normalized power of 2. */ + + spec_case = 0; + if ((mode < 2 || leftright) +#ifdef Honor_FLT_ROUNDS + && Rounding == 1 +#endif + ) { + if (!word1(&u) && !(word0(&u) & Bndry_mask) +#ifndef Sudden_Underflow + && word0(&u) & (Exp_mask & ~Exp_msk1) +#endif + ) { + /* The special case */ + b2 += Log2P; + s2 += Log2P; + spec_case = 1; + } + } + + /* Arrange for convenient computation of quotients: + * shift left if necessary so divisor has 4 leading 0 bits. + * + * Perhaps we should just compute leading 28 bits of S once + * and for all and pass them and a shift to quorem, so it + * can do shifts and ors to compute the numerator for q. + */ +#ifdef Pack_32 + if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)) + i = 32 - i; +#define iInc 28 +#else + if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) + i = 16 - i; +#define iInc 12 +#endif + i = dshift(S, s2); + b2 += i; + m2 += i; + s2 += i; + if (b2 > 0) + b = lshift(b, b2); + if (s2 > 0) + S = lshift(S, s2); + if (k_check) { + if (cmp(b,S) < 0) { + k--; + b = multadd(b, 10, 0); /* we botched the k estimate */ + if (leftright) + mhi = multadd(mhi, 10, 0); + ilim = ilim1; + } + } + if (ilim <= 0 && (mode == 3 || mode == 5)) { + if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { + /* no digits, fcvt style */ + no_digits: + k = -1 - ndigits; + goto ret; + } + one_digit: + *s++ = '1'; + k++; + goto ret; + } + if (leftright) { + if (m2 > 0) + mhi = lshift(mhi, m2); + + /* Compute mlo -- check for special case + * that d is a normalized power of 2. + */ + + mlo = mhi; + if (spec_case) { + mhi = Balloc(mhi->k); + Bcopy(mhi, mlo); + mhi = lshift(mhi, Log2P); + } + + for(i = 1;;i++) { + dig = quorem(b,S) + '0'; + /* Do we yet have the shortest decimal string + * that will round to d? + */ + j = cmp(b, mlo); + delta = diff(S, mhi); + j1 = delta->sign ? 1 : cmp(b, delta); + Bfree(delta); +#ifndef ROUND_BIASED + if (j1 == 0 && mode != 1 && !(word1(&u) & 1) +#ifdef Honor_FLT_ROUNDS + && Rounding >= 1 +#endif + ) { + if (dig == '9') + goto round_9_up; + if (j > 0) + dig++; +#ifdef SET_INEXACT + else if (!b->x[0] && b->wds <= 1) + inexact = 0; +#endif + *s++ = dig; + goto ret; + } +#endif + if (j < 0 || (j == 0 && mode != 1 +#ifndef ROUND_BIASED + && !(word1(&u) & 1) +#endif + )) { + if (!b->x[0] && b->wds <= 1) { +#ifdef SET_INEXACT + inexact = 0; +#endif + goto accept_dig; + } +#ifdef Honor_FLT_ROUNDS + if (mode > 1) + switch(Rounding) { + case 0: goto accept_dig; + case 2: goto keep_dig; + } +#endif /*Honor_FLT_ROUNDS*/ + if (j1 > 0) { + b = lshift(b, 1); + j1 = cmp(b, S); + if ((j1 > 0 || (j1 == 0 && dig & 1)) + && dig++ == '9') + goto round_9_up; + } + accept_dig: + *s++ = dig; + goto ret; + } + if (j1 > 0) { +#ifdef Honor_FLT_ROUNDS + if (!Rounding) + goto accept_dig; +#endif + if (dig == '9') { /* possible if i == 1 */ + round_9_up: + *s++ = '9'; + goto roundoff; + } + *s++ = dig + 1; + goto ret; + } +#ifdef Honor_FLT_ROUNDS + keep_dig: +#endif + *s++ = dig; + if (i == ilim) + break; + b = multadd(b, 10, 0); + if (mlo == mhi) + mlo = mhi = multadd(mhi, 10, 0); + else { + mlo = multadd(mlo, 10, 0); + mhi = multadd(mhi, 10, 0); + } + } + } + else + for(i = 1;; i++) { + *s++ = dig = quorem(b,S) + '0'; + if (!b->x[0] && b->wds <= 1) { +#ifdef SET_INEXACT + inexact = 0; +#endif + goto ret; + } + if (i >= ilim) + break; + b = multadd(b, 10, 0); + } + + /* Round off last digit */ + +#ifdef Honor_FLT_ROUNDS + switch(Rounding) { + case 0: goto trimzeros; + case 2: goto roundoff; + } +#endif + b = lshift(b, 1); + j = cmp(b, S); + if (j > 0 || (j == 0 && dig & 1)) { + roundoff: + while(*--s == '9') + if (s == s0) { + k++; + *s++ = '1'; + goto ret; + } + ++*s++; + } + else { +#ifdef Honor_FLT_ROUNDS + trimzeros: +#endif + while(*--s == '0'); + s++; + } + ret: + Bfree(S); + if (mhi) { + if (mlo && mlo != mhi) + Bfree(mlo); + Bfree(mhi); + } + ret1: +#ifdef SET_INEXACT + if (inexact) { + if (!oldinexact) { + word0(&u) = Exp_1 + (70 << Exp_shift); + word1(&u) = 0; + dval(&u) += 1.; + } + } + else if (!oldinexact) + clear_inexact(); +#endif + Bfree(b); + *s = 0; + *decpt = k + 1; + if (rve) + *rve = s; + return s0; + } +#ifdef __cplusplus +} +#endif From python-checkins at python.org Mon Mar 30 22:00:00 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 22:00:00 +0200 (CEST) Subject: [Python-checkins] r70745 - in python/branches/py3k: Mac/Makefile.in Mac/Resources/app/Info.plist.in Message-ID: <20090330200000.AE1261E4021@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 22:00:00 2009 New Revision: 70745 Log: Merged revisions 70741 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70741 | ronald.oussoren | 2009-03-30 14:56:25 -0500 (Mon, 30 Mar 2009) | 2 lines Fixes issue 5270 ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Mac/Makefile.in python/branches/py3k/Mac/Resources/app/Info.plist.in Modified: python/branches/py3k/Mac/Makefile.in ============================================================================== --- python/branches/py3k/Mac/Makefile.in (original) +++ python/branches/py3k/Mac/Makefile.in Mon Mar 30 22:00:00 2009 @@ -14,6 +14,7 @@ LDFLAGS=@LDFLAGS@ FRAMEWORKUNIXTOOLSPREFIX=@FRAMEWORKUNIXTOOLSPREFIX@ PYTHONFRAMEWORK=@PYTHONFRAMEWORK@ +PYTHONFRAMEWORKIDENTIFIER=@PYTHONFRAMEWORKIDENTIFIER@ # These are normally glimpsed from the previous set @@ -206,6 +207,12 @@ done; \ done $(INSTALL_PROGRAM) $(STRIPFLAG) $(BUILDPYTHON) "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)" + sed -e "s!%bundleid%!$(PYTHONFRAMEWORKIDENTIFIER)!g" \ + -e "s!%version%!`$(RUNSHARED) $(BUILDPYTHON) \ + -c 'import platform; print(platform.python_version())'`!g" \ + < "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist.in" \ + > "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist" + rm "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist.in" install_Python4way: install_Python lipo -extract i386 -extract ppc7400 -output "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)-32" "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)" Modified: python/branches/py3k/Mac/Resources/app/Info.plist.in ============================================================================== --- python/branches/py3k/Mac/Resources/app/Info.plist.in (original) +++ python/branches/py3k/Mac/Resources/app/Info.plist.in Mon Mar 30 22:00:00 2009 @@ -20,7 +20,7 @@ CFBundleExecutable Python CFBundleGetInfoString - @VERSION@, (c) 2004 Python Software Foundation. + %version%, (c) 2004-2009 Python Software Foundation. CFBundleHelpBookFolder Documentation @@ -33,21 +33,21 @@ CFBundleIconFile PythonInterpreter.icns CFBundleIdentifier - @PYTHONFRAMEWORKIDENTIFIER at .app + %bundleid% CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString - @VERSION@, (c) 2004-2008 Python Software Foundation. + %version%, (c) 2004-2009 Python Software Foundation. CFBundleName Python CFBundlePackageType APPL CFBundleShortVersionString - @VERSION@ + %version% CFBundleSignature PytX CFBundleVersion - @VERSION@ + %version% CSResourcesFileMapped LSRequiresCarbon From python-checkins at python.org Mon Mar 30 22:02:08 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 22:02:08 +0200 (CEST) Subject: [Python-checkins] r70746 - in python/trunk: Doc/library/os.path.rst Mac/BuildScript/build-installer.py Message-ID: <20090330200208.449C01E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 22:02:08 2009 New Revision: 70746 Log: Fix for issue 13095 Modified: python/trunk/Doc/library/os.path.rst python/trunk/Mac/BuildScript/build-installer.py Modified: python/trunk/Doc/library/os.path.rst ============================================================================== --- python/trunk/Doc/library/os.path.rst (original) +++ python/trunk/Doc/library/os.path.rst Mon Mar 30 22:02:08 2009 @@ -190,7 +190,7 @@ .. function:: normcase(path) - Normalize the case of a pathname. On Unix, this returns the path unchanged; on + Normalize the case of a pathname. On Unix and MacOSX, this returns the path unchanged; on case-insensitive filesystems, it converts the path to lowercase. On Windows, it also converts forward slashes to backward slashes. Modified: python/trunk/Mac/BuildScript/build-installer.py ============================================================================== --- python/trunk/Mac/BuildScript/build-installer.py (original) +++ python/trunk/Mac/BuildScript/build-installer.py Mon Mar 30 22:02:08 2009 @@ -649,6 +649,11 @@ # several paths. version = getVersion() + # Since the extra libs are not in their installed framework location + # during the build, augment the library path so that the interpreter + # will find them during its extension import sanity checks. + os.environ['DYLD_LIBRARY_PATH'] = os.path.join(WORKDIR, + 'libraries', 'usr', 'local', 'lib') print "Running configure..." runCommand("%s -C --enable-framework --enable-universalsdk=%s " "--with-universal-archs=%s " @@ -670,6 +675,7 @@ runCommand("make frameworkinstallextras DESTDIR=%s"%( shellQuote(rootDir))) + del os.environ['DYLD_LIBRARY_PATH'] print "Copying required shared libraries" if os.path.exists(os.path.join(WORKDIR, 'libraries', 'Library')): runCommand("mv %s/* %s"%( From python-checkins at python.org Mon Mar 30 22:04:07 2009 From: python-checkins at python.org (r.david.murray) Date: Mon, 30 Mar 2009 22:04:07 +0200 (CEST) Subject: [Python-checkins] r70747 - python/trunk/Lib/test/regrtest.py Message-ID: <20090330200407.16F2F1E4002@bag.python.org> Author: r.david.murray Date: Mon Mar 30 22:04:06 2009 New Revision: 70747 Log: Remove references to test_socket_ssl which was deleted in trunk in r64392 and py3k in r59038. Modified: python/trunk/Lib/test/regrtest.py Modified: python/trunk/Lib/test/regrtest.py ============================================================================== --- python/trunk/Lib/test/regrtest.py (original) +++ python/trunk/Lib/test/regrtest.py Mon Mar 30 22:04:06 2009 @@ -778,9 +778,6 @@ # test_pep277 # The _ExpectedSkips constructor adds this to the set of expected # skips if not os.path.supports_unicode_filenames. -# test_socket_ssl -# Controlled by test_socket_ssl.skip_expected. Requires the network -# resource, and a socket module with ssl support. # test_timeout # Controlled by test_timeout.skip_expected. Requires the network # resource and a socket module. @@ -1057,7 +1054,6 @@ test_ossaudiodev test_pep277 test_pty - test_socket_ssl test_socketserver test_tcl test_tk @@ -1145,14 +1141,6 @@ if not os.path.supports_unicode_filenames: self.expected.add('test_pep277') - try: - from test import test_socket_ssl - except ImportError: - pass - else: - if test_socket_ssl.skip_expected: - self.expected.add('test_socket_ssl') - if test_timeout.skip_expected: self.expected.add('test_timeout') From python-checkins at python.org Mon Mar 30 22:04:12 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 22:04:12 +0200 (CEST) Subject: [Python-checkins] r70748 - in python/branches/release26-maint: Doc/library/os.path.rst Mac/BuildScript/build-installer.py Message-ID: <20090330200412.F3D2D1E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 22:04:12 2009 New Revision: 70748 Log: Merged revisions 70746 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70746 | ronald.oussoren | 2009-03-30 15:02:08 -0500 (Mon, 30 Mar 2009) | 2 lines Fix for issue 13095 ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/library/os.path.rst python/branches/release26-maint/Mac/BuildScript/build-installer.py Modified: python/branches/release26-maint/Doc/library/os.path.rst ============================================================================== --- python/branches/release26-maint/Doc/library/os.path.rst (original) +++ python/branches/release26-maint/Doc/library/os.path.rst Mon Mar 30 22:04:12 2009 @@ -190,7 +190,7 @@ .. function:: normcase(path) - Normalize the case of a pathname. On Unix, this returns the path unchanged; on + Normalize the case of a pathname. On Unix and MacOSX, this returns the path unchanged; on case-insensitive filesystems, it converts the path to lowercase. On Windows, it also converts forward slashes to backward slashes. Modified: python/branches/release26-maint/Mac/BuildScript/build-installer.py ============================================================================== --- python/branches/release26-maint/Mac/BuildScript/build-installer.py (original) +++ python/branches/release26-maint/Mac/BuildScript/build-installer.py Mon Mar 30 22:04:12 2009 @@ -649,6 +649,11 @@ # several paths. version = getVersion() + # Since the extra libs are not in their installed framework location + # during the build, augment the library path so that the interpreter + # will find them during its extension import sanity checks. + os.environ['DYLD_LIBRARY_PATH'] = os.path.join(WORKDIR, + 'libraries', 'usr', 'local', 'lib') print "Running configure..." runCommand("%s -C --enable-framework --enable-universalsdk=%s " "--with-universal-archs=%s " @@ -670,6 +675,7 @@ runCommand("make frameworkinstallextras DESTDIR=%s"%( shellQuote(rootDir))) + del os.environ['DYLD_LIBRARY_PATH'] print "Copying required shared libraries" if os.path.exists(os.path.join(WORKDIR, 'libraries', 'Library')): runCommand("mv %s/* %s"%( From python-checkins at python.org Mon Mar 30 22:05:35 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 22:05:35 +0200 (CEST) Subject: [Python-checkins] r70749 - in python/branches/py3k: Doc/library/os.path.rst Mac/BuildScript/build-installer.py Message-ID: <20090330200535.6DCFE1E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 22:05:35 2009 New Revision: 70749 Log: Merged revisions 70746 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70746 | ronald.oussoren | 2009-03-30 15:02:08 -0500 (Mon, 30 Mar 2009) | 2 lines Fix for issue 13095 ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/os.path.rst python/branches/py3k/Mac/BuildScript/build-installer.py Modified: python/branches/py3k/Doc/library/os.path.rst ============================================================================== --- python/branches/py3k/Doc/library/os.path.rst (original) +++ python/branches/py3k/Doc/library/os.path.rst Mon Mar 30 22:05:35 2009 @@ -189,7 +189,7 @@ .. function:: normcase(path) - Normalize the case of a pathname. On Unix, this returns the path unchanged; on + Normalize the case of a pathname. On Unix and MacOSX, this returns the path unchanged; on case-insensitive filesystems, it converts the path to lowercase. On Windows, it also converts forward slashes to backward slashes. Modified: python/branches/py3k/Mac/BuildScript/build-installer.py ============================================================================== --- python/branches/py3k/Mac/BuildScript/build-installer.py (original) +++ python/branches/py3k/Mac/BuildScript/build-installer.py Mon Mar 30 22:05:35 2009 @@ -644,6 +644,11 @@ # several paths. version = getVersion() + # Since the extra libs are not in their installed framework location + # during the build, augment the library path so that the interpreter + # will find them during its extension import sanity checks. + os.environ['DYLD_LIBRARY_PATH'] = os.path.join(WORKDIR, + 'libraries', 'usr', 'local', 'lib') print "Running configure..." runCommand("%s -C --enable-framework --enable-universalsdk=%s " "--with-universal-archs=%s --with-computed-gotos" @@ -665,6 +670,7 @@ runCommand("make frameworkinstallextras DESTDIR=%s"%( shellQuote(rootDir))) + del os.environ['DYLD_LIBRARY_PATH'] print "Copying required shared libraries" if os.path.exists(os.path.join(WORKDIR, 'libraries', 'Library')): runCommand("mv %s/* %s"%( From buildbot at python.org Mon Mar 30 22:05:47 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 20:05:47 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090330200547.CF6951E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/517 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: benjamin.peterson BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_multiprocessing make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Mon Mar 30 22:09:12 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 20:09:12 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090330200912.771C61E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/488 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From python-checkins at python.org Mon Mar 30 22:10:18 2009 From: python-checkins at python.org (ronald.oussoren) Date: Mon, 30 Mar 2009 22:10:18 +0200 (CEST) Subject: [Python-checkins] r70750 - python/branches/py3k/Mac/BuildScript/resources/ReadMe.txt Message-ID: <20090330201018.8AE841E4002@bag.python.org> Author: ronald.oussoren Date: Mon Mar 30 22:10:18 2009 New Revision: 70750 Log: Fix for issue 5558 Modified: python/branches/py3k/Mac/BuildScript/resources/ReadMe.txt Modified: python/branches/py3k/Mac/BuildScript/resources/ReadMe.txt ============================================================================== --- python/branches/py3k/Mac/BuildScript/resources/ReadMe.txt (original) +++ python/branches/py3k/Mac/BuildScript/resources/ReadMe.txt Mon Mar 30 22:10:18 2009 @@ -19,9 +19,11 @@ that open up specific Macintosh technologies to Python programs. The installer puts the applications in "Python $VERSION" -in your Applications folder, command-line tools in -/usr/local/bin and the underlying machinery in -$PYTHONFRAMEWORKINSTALLDIR. +in your Applications folder, and the underlying machinery in +$PYTHONFRAMEWORKINSTALLDIR. It can optionally place +links to the command-line tools in /usr/local as well, +by default you have to add the "bin" directory inside +the framework to you shell's search path. More information on MacPython can be found at http://www.python.org/download/mac/. From buildbot at python.org Mon Mar 30 22:13:32 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 20:13:32 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu trunk Message-ID: <20090330201332.6BF4E1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%20trunk/builds/1174 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: jesse.noller,kurt.kaiser,r.david.murray,ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Mon Mar 30 22:28:36 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 20:28:36 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo trunk Message-ID: <20090330202836.E29931E4002@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%20gentoo%20trunk/builds/2030 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: r.david.murray,ronald.oussoren BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From python-checkins at python.org Mon Mar 30 22:34:58 2009 From: python-checkins at python.org (guido.van.rossum) Date: Mon, 30 Mar 2009 22:34:58 +0200 (CEST) Subject: [Python-checkins] r70751 - python/branches/py3k/Doc/library/importlib.rst Message-ID: <20090330203458.27A761E4002@bag.python.org> Author: guido.van.rossum Date: Mon Mar 30 22:34:57 2009 New Revision: 70751 Log: Thorough review of importlib docs. Reviewed by Brett himself. Modified: python/branches/py3k/Doc/library/importlib.rst Modified: python/branches/py3k/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k/Doc/library/importlib.rst (original) +++ python/branches/py3k/Doc/library/importlib.rst Mon Mar 30 22:34:57 2009 @@ -37,7 +37,7 @@ The :func:`.__import__` function The built-in function for which the :keyword:`import` statement is - syntactic sugar for. + syntactic sugar. :pep:`235` Import on Case-Insensitive Platforms @@ -71,8 +71,8 @@ Import a module. The *name* argument specifies what module to import in absolute or relative terms (e.g. either ``pkg.mod`` or ``..mod``). If the name is - specified in relative terms, then the *package* argument must be - set to the package which is to act as the anchor for resolving the + specified in relative terms, then the *package* argument must be set to + the name of the package which is to act as the anchor for resolving the package name (e.g. ``import_module('..mod', 'pkg.subpkg')`` will import ``pkg.mod``). @@ -80,7 +80,11 @@ :func:`__import__`. This means all semantics of the function are derived from :func:`__import__`, including requiring the package from which an import is occurring to have been previously imported (i.e., *package* - must already be imported). + must already be imported). The most important difference is that + :func:`import_module` returns the most nested package or module that + was imported (e.g. ``pkg.mod``), while :func:`__import__` returns the + top-level package or module (e.g. ``pkg``). + :mod:`importlib.abc` -- Abstract base classes related to import --------------------------------------------------------------- @@ -96,21 +100,21 @@ .. class:: Finder An abstract base class representing a :term:`finder`. + See :pep:`302` for the exact definition for a finder. .. method:: find_module(fullname, path=None) An abstract method for finding a :term:`loader` for the specified module. If the :term:`finder` is found on :data:`sys.meta_path` and the - module to be searched for is a subpackage or module then *path* is set - to the value of :attr:`__path__` from the parent package. If a loader + module to be searched for is a subpackage or module then *path* will + be the value of :attr:`__path__` from the parent package. If a loader cannot be found, :keyword:`None` is returned. - The exact definition of a :term:`finder` can be found in :pep:`302`. - .. class:: Loader An abstract base class for a :term:`loader`. + See :pep:`302` for the exact definition for a loader. .. method:: load_module(fullname) @@ -118,18 +122,19 @@ loaded, :exc:`ImportError` is raised, otherwise the loaded module is returned. - If the requested module is already exists in :data:`sys.modules`, that + If the requested module already exists in :data:`sys.modules`, that module should be used and reloaded. - Otherwise a new module is to be created by the loader and inserted into - :data:`sys.modules` before any loading begins to prevent recursion from - the import. If the loader inserted into a module and the load fails it + Otherwise the loader should create a new module and insert it into + :data:`sys.modules` before any loading begins, to prevent recursion + from the import. If the loader inserted a module and the load fails, it must be removed by the loader from :data:`sys.modules`; modules already in :data:`sys.modules` before the loader began execution should be left alone. The :func:`importlib.util.module_for_loader` decorator handles all of these details. - The loader is expected to set several attributes on the module when - adding a new module to :data:`sys.modules`. + The loader should set several attributes on the module. + (Note that some of these attributes can change when a module is + reloaded.) - :attr:`__name__` The name of the module. @@ -139,7 +144,7 @@ modules). - :attr:`__path__` - Set to a list of strings specifying the search path within a + A list of strings specifying the search path within a package. This attribute is not set on modules. - :attr:`__package__` @@ -149,9 +154,9 @@ for :attr:`__package__`. - :attr:`__loader__` - Set to the loader used to load the module. - - See :pep:`302` for the exact definition for a loader. + The loader used to load the module. + (This is not set by the built-in import machinery, + but it should be set whenever a :term:`loader` is used.) .. class:: ResourceLoader @@ -163,17 +168,20 @@ .. method:: get_data(path) An abstract method to return the bytes for the data located at *path*. - Loaders that have a file-like storage back-end can implement this - abstract method to give direct access + Loaders that have a file-like storage back-end + that allows storing arbitrary data (e.g. a zip archive loader) + can implement this abstract method to give direct access to the data stored. :exc:`IOError` is to be raised if the *path* cannot be found. The *path* is expected to be constructed using a module's :attr:`__path__` attribute or an item from :attr:`__path__`. +.. XXX What's the difference between the latter two? (Maybe one is __file__?) +.. XXX Could use a clarification so as not to depend on PEP 302. .. class:: InspectLoader An abstract base class for a :term:`loader` which implements the optional - :pep:`302` protocol for loaders which inspect modules. + :pep:`302` protocol for loaders that inspect modules. .. method:: get_code(fullname) @@ -185,7 +193,7 @@ .. method:: get_source(fullname) An abstract method to return the source of a module. It is returned as - a string with universal newline support. Returns :keyword:`None` if no + a text string with universal newlines. Returns :keyword:`None` if no source is available (e.g. a built-in module). Raises :exc:`ImportError` if the loader cannot find the module specified. @@ -224,14 +232,17 @@ A concrete implementation of :meth:`importlib.abc.InspectLoader.get_code` that creates code objects - from Python source code. + from Python source code, by requesting the source code (using + :meth:`source_path` and :meth:`get_data`), converting it to standard + newlines, and compiling it with the built-in :func:`compile` function. .. method:: get_source(fullname) A concrete implementation of :meth:`importlib.abc.InspectLoader.get_source`. Uses :meth:`importlib.abc.InspectLoader.get_data` and :meth:`source_path` to - get the source code. + get the source code. It tries to guess the source encoding using + :func:`tokenize.detect_encoding`. .. class:: PyPycLoader @@ -250,8 +261,9 @@ .. method:: bytecode_path(fullname) An abstract method which returns the path to the bytecode for the - specified module. :keyword:`None` is returned if there is no bytecode. - :exc:`ImportError` is raised if the module is not found. + specified module, if it exists. It returns :keyword:`None` + if no bytecode exists (yet). + Raises :exc:`ImportError` if the module is not found. .. method:: write_bytecode(fullname, bytecode) @@ -259,6 +271,7 @@ use. If the bytecode is written, return :keyword:`True`. Return :keyword:`False` if the bytecode could not be written. This method should not be called if :data:`sys.dont_write_bytecode` is true. + The *bytecode* argument should be a bytes string or bytes array. :mod:`importlib.machinery` -- Importers and path hooks @@ -328,16 +341,18 @@ .. function:: module_for_loader(method) - A :term:`decorator` for a :term:`loader` which handles selecting the proper + A :term:`decorator` for a :term:`loader` method, + to handle selecting the proper module object to load with. The decorated method is expected to have a call signature taking two positional arguments (e.g. ``load_module(self, module)``) for which the second argument - will be the module object to be used by the loader. Note that the decorator + will be the module **object** to be used by the loader. + Note that the decorator will not work on static methods because of the assumption of two arguments. - The decorated method will take in the name of the module to be loaded as - expected for a :term:`loader`. If the module is not found in + The decorated method will take in the **name** of the module to be loaded + as expected for a :term:`loader`. If the module is not found in :data:`sys.modules` then a new one is constructed with its :attr:`__name__` attribute set. Otherwise the module found in :data:`sys.modules` will be passed into the method. If an @@ -346,18 +361,17 @@ module from being in left in :data:`sys.modules`. If the module was already in :data:`sys.modules` then it is left alone. - Use of this decorator handles all the details of what module object a + Use of this decorator handles all the details of which module object a loader should initialize as specified by :pep:`302`. - .. function:: set_loader(fxn) - A :term:`decorator` for a :term:`loader` to set the :attr:`__loader__` + A :term:`decorator` for a :term:`loader` method, + to set the :attr:`__loader__` attribute on loaded modules. If the attribute is already set the decorator does nothing. It is assumed that the first positional argument to the wrapped method is what :attr:`__loader__` should be set to. - .. function:: set_package(fxn) A :term:`decorator` for a :term:`loader` to set the :attr:`__package__` @@ -365,3 +379,5 @@ set and has a value other than :keyword:`None` it will not be changed. Note that the module returned by the loader is what has the attribute set on and not the module found in :data:`sys.modules`. + +.. XXX This whole chapter desperately needs examples... From python-checkins at python.org Mon Mar 30 22:47:52 2009 From: python-checkins at python.org (mark.dickinson) Date: Mon, 30 Mar 2009 22:47:52 +0200 (CEST) Subject: [Python-checkins] r70752 - in python/branches/py3k-short-float-repr: Include/Python.h Include/dtoa.h Makefile.pre.in PCbuild/pythoncore.vcproj Python/dtoa.c Message-ID: <20090330204752.524BC1E4002@bag.python.org> Author: mark.dickinson Date: Mon Mar 30 22:47:52 2009 New Revision: 70752 Log: Make Gay's dtoa and strtod available to Python, as _Py_dg_dtoa and _Py_dg_strtod. Link endianness detection in pyconfig.h to Gay's code. Minimal changes to dtoa.c required to make it compile. Added: python/branches/py3k-short-float-repr/Include/dtoa.h Modified: python/branches/py3k-short-float-repr/Include/Python.h python/branches/py3k-short-float-repr/Makefile.pre.in python/branches/py3k-short-float-repr/PCbuild/pythoncore.vcproj python/branches/py3k-short-float-repr/Python/dtoa.c Modified: python/branches/py3k-short-float-repr/Include/Python.h ============================================================================== --- python/branches/py3k-short-float-repr/Include/Python.h (original) +++ python/branches/py3k-short-float-repr/Include/Python.h Mon Mar 30 22:47:52 2009 @@ -118,6 +118,7 @@ #include "pystrtod.h" #include "pystrcmp.h" +#include "dtoa.h" /* _Py_Mangle is defined in compile.c */ PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name); Added: python/branches/py3k-short-float-repr/Include/dtoa.h ============================================================================== --- (empty file) +++ python/branches/py3k-short-float-repr/Include/dtoa.h Mon Mar 30 22:47:52 2009 @@ -0,0 +1,11 @@ +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_FUNC(double) _Py_dg_strtod(const char *str, char **ptr); +PyAPI_FUNC(char *) _Py_dg_dtoa(double d, int mode, int ndigits, + int *decpt, int *sign, char **rve); + +#ifdef __cplusplus +} +#endif Modified: python/branches/py3k-short-float-repr/Makefile.pre.in ============================================================================== --- python/branches/py3k-short-float-repr/Makefile.pre.in (original) +++ python/branches/py3k-short-float-repr/Makefile.pre.in Mon Mar 30 22:47:52 2009 @@ -304,6 +304,7 @@ Python/getopt.o \ Python/pystrcmp.o \ Python/pystrtod.o \ + Python/dtoa.o \ Python/formatter_unicode.o \ Python/$(DYNLOADFILE) \ $(LIBOBJS) \ Modified: python/branches/py3k-short-float-repr/PCbuild/pythoncore.vcproj ============================================================================== --- python/branches/py3k-short-float-repr/PCbuild/pythoncore.vcproj (original) +++ python/branches/py3k-short-float-repr/PCbuild/pythoncore.vcproj Mon Mar 30 22:47:52 2009 @@ -895,6 +895,10 @@ > + + @@ -1743,6 +1747,10 @@ > + + Modified: python/branches/py3k-short-float-repr/Python/dtoa.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/dtoa.c (original) +++ python/branches/py3k-short-float-repr/Python/dtoa.c Mon Mar 30 22:47:52 2009 @@ -179,6 +179,21 @@ * used for input more than STRTOD_DIGLIM digits long (default 40). */ +/* Linking of Python's #defines to Gay's #defines starts here. */ + +#include "Python.h" + +/* use WORDS_BIGENDIAN to determine float endianness. This assumes that ints + and floats share the same endianness on the target machine, which appears + to be true for every platform that Python currently cares about. We're + also assuming IEEE 754 float format for now. */ + +#ifdef WORDS_BIGENDIAN +#define IEEE_MC68k +#else +#define IEEE_8087 +#endif + #ifndef Long #define Long long #endif @@ -293,7 +308,7 @@ #endif #if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 -Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +#error "Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined." #endif typedef union { double d; ULong L[2]; } U; @@ -511,12 +526,6 @@ #define Kmax 7 -#ifdef __cplusplus -extern "C" double strtod(const char *s00, char **se); -extern "C" char *dtoa(double d, int mode, int ndigits, - int *decpt, int *sign, char **rve); -#endif - struct Bigint { struct Bigint *next; @@ -2419,7 +2428,7 @@ #endif /* NO_STRTOD_BIGCOMP */ double -strtod +_Py_dg_strtod #ifdef KR_headers (s00, se) CONST char *s00; char **se; #else @@ -3515,7 +3524,7 @@ */ char * -dtoa +_Py_dg_dtoa #ifdef KR_headers (dd, mode, ndigits, decpt, sign, rve) double dd; int mode, ndigits, *decpt, *sign; char **rve; From buildbot at python.org Mon Mar 30 22:48:00 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 20:48:00 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090330204800.7041B1E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/490 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From buildbot at python.org Mon Mar 30 22:59:48 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 20:59:48 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 2.6 Message-ID: <20090330205949.69C941E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%202.6/builds/192 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: jesse.noller,ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Mon Mar 30 23:21:05 2009 From: python-checkins at python.org (georg.brandl) Date: Mon, 30 Mar 2009 23:21:05 +0200 (CEST) Subject: [Python-checkins] r70753 - python/branches/py3k/Doc/license.rst Message-ID: <20090330212105.3D19F1E4020@bag.python.org> Author: georg.brandl Date: Mon Mar 30 23:21:05 2009 New Revision: 70753 Log: Remove merging leftover. Modified: python/branches/py3k/Doc/license.rst Modified: python/branches/py3k/Doc/license.rst ============================================================================== --- python/branches/py3k/Doc/license.rst (original) +++ python/branches/py3k/Doc/license.rst Mon Mar 30 23:21:05 2009 @@ -31,7 +31,6 @@ Source Definition). Historically, most, but not all, Python releases have also been GPL-compatible; the table below summarizes the various releases. -<<<<<<< .working +----------------+--------------+------------+------------+-----------------+ | Release | Derived from | Year | Owner | GPL compatible? | +================+==============+============+============+=================+ From python-checkins at python.org Mon Mar 30 23:22:47 2009 From: python-checkins at python.org (mark.dickinson) Date: Mon, 30 Mar 2009 23:22:47 +0200 (CEST) Subject: [Python-checkins] r70754 - python/branches/py3k-short-float-repr/Objects/floatobject.c Message-ID: <20090330212247.7147C1E4002@bag.python.org> Author: mark.dickinson Date: Mon Mar 30 23:22:46 2009 New Revision: 70754 Log: Hook up repr(float) to _Py_dg_dtoa.c Modified: python/branches/py3k-short-float-repr/Objects/floatobject.c Modified: python/branches/py3k-short-float-repr/Objects/floatobject.c ============================================================================== --- python/branches/py3k-short-float-repr/Objects/floatobject.c (original) +++ python/branches/py3k-short-float-repr/Objects/floatobject.c Mon Mar 30 23:22:46 2009 @@ -379,6 +379,94 @@ } +/* convert a Python float to a minimal string that evaluates back to that + float. The output is minimal in the sense of having the least possible + number of significant digits. */ + +static void +format_float_short(char *buf, size_t buflen, PyFloatObject *v) +{ + double d; + char *digits, *digits_end; + int decpt, sign, exp_len; + size_t digits_len, i; + + assert(PyFloat_Check(v)); + d = PyFloat_AS_DOUBLE(v); + + /* _Py_dg_dtoa returns a digit string (no decimal point + or exponent) */ + digits = _Py_dg_dtoa(d, 0, 0, &decpt, &sign, &digits_end); + assert(digits_end != NULL && digits_end > digits); + digits_len = digits_end - digits; + + if (!isdigit(digits[0])) { + /* infinities and nans here; adapt Gay's output, + so convert Infinity to inf and NaN to nan, and + ignore sign of nan. */ + if (digits[0] == 'i' || digits[0] == 'I') { + if (sign == 1) { + *buf++ = '-'; + } + strncpy(buf, "inf", 3); + buf += 3; + } else { + assert(digits[0] == 'n' || digits[0] == 'N'); + strncpy(buf, "nan", 3); + buf += 3; + } + } + else if (-4 < decpt && decpt <= 17) { + if (sign == 1) { + *buf++ = '-'; + } + /* use fixed-point notation if 1e-4 <= value < 1e17 */ + if (decpt <= 0) { + /* output: 0.00...00dd...dd */ + *buf++ = '0'; + *buf++ = '.'; + for (i=0; i < -decpt; i++) + *buf++ = '0'; + strncpy(buf, digits, digits_len); + buf += digits_len; + } + else if (decpt < digits_len) { + /* output: dd...dd.dd...dd */ + strncpy(buf, digits, decpt); + buf += decpt; + *buf++ = '.'; + strncpy(buf, digits+decpt, digits_len-decpt); + buf += digits_len-decpt; + } + else { + /* decpt >= digits_len. output: dd...dd00...00.0 */ + strncpy(buf, digits, digits_len); + buf += digits_len; + for (i=0; i < decpt-digits_len; i++) + *buf++ = '0'; + *buf++ = '.'; + *buf++ = '0'; + } + } + else { + /* exponential notation: d[.dddd]e(+|-)ee; + at least 2 digits in exponent */ + if (sign == 1) { + *buf++ = '-'; + } + *buf++ = digits[0]; + if (digits_len > 1) { + *buf++ = '.'; + strncpy(buf, digits+1, digits_len-1); + buf += digits_len-1; + } + *buf++ = 'e'; + exp_len = sprintf(buf, "%+.02d", decpt-1); + buf += exp_len; + } + *buf++ = '\0'; +} + static void format_float(char *buf, size_t buflen, PyFloatObject *v, int precision) { @@ -439,7 +527,7 @@ float_repr(PyFloatObject *v) { char buf[100]; - format_float(buf, sizeof(buf), v, PREC_REPR); + format_float_short(buf, sizeof(buf), v); return PyUnicode_FromString(buf); } From python-checkins at python.org Mon Mar 30 23:30:26 2009 From: python-checkins at python.org (brett.cannon) Date: Mon, 30 Mar 2009 23:30:26 +0200 (CEST) Subject: [Python-checkins] r70755 - in python/branches/py3k: Doc/library/time.rst Lib/_strptime.py Lib/test/test_time.py Misc/ACKS Misc/NEWS Message-ID: <20090330213026.D134D1E4002@bag.python.org> Author: brett.cannon Date: Mon Mar 30 23:30:26 2009 New Revision: 70755 Log: Make sure time.strptime only accepts strings (and document the fact like strftime). Already didn't accept bytes but make the check earlier. This also lifts the limitation of requiring ASCII. Closes issue #5236. Thanks Tennessee Leeuwenburg. Modified: python/branches/py3k/Doc/library/time.rst python/branches/py3k/Lib/_strptime.py python/branches/py3k/Lib/test/test_time.py python/branches/py3k/Misc/ACKS python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Doc/library/time.rst ============================================================================== --- python/branches/py3k/Doc/library/time.rst (original) +++ python/branches/py3k/Doc/library/time.rst Mon Mar 30 23:30:26 2009 @@ -358,15 +358,17 @@ .. function:: strptime(string[, format]) - Parse a string representing a time according to a format. The return value is - a :class:`struct_time` as returned by :func:`gmtime` or :func:`localtime`. + Parse a string representing a time according to a format. The return value + is a :class:`struct_time` as returned by :func:`gmtime` or + :func:`localtime`. The *format* parameter uses the same directives as those used by :func:`strftime`; it defaults to ``"%a %b %d %H:%M:%S %Y"`` which matches the - formatting returned by :func:`ctime`. If *string* cannot be parsed according to - *format*, or if it has excess data after parsing, :exc:`ValueError` is raised. - The default values used to fill in any missing data when more accurate values - cannot be inferred are ``(1900, 1, 1, 0, 0, 0, 0, 1, -1)``. + formatting returned by :func:`ctime`. If *string* cannot be parsed according + to *format*, or if it has excess data after parsing, :exc:`ValueError` is + raised. The default values used to fill in any missing data when more + accurate values cannot be inferred are ``(1900, 1, 1, 0, 0, 0, 0, 1, -1)``. + Both *string* and *format* must be strings. For example: Modified: python/branches/py3k/Lib/_strptime.py ============================================================================== --- python/branches/py3k/Lib/_strptime.py (original) +++ python/branches/py3k/Lib/_strptime.py Mon Mar 30 23:30:26 2009 @@ -262,7 +262,7 @@ def compile(self, format): """Return a compiled re object for the format string.""" - return re_compile(self.pattern(format), IGNORECASE | ASCII) + return re_compile(self.pattern(format), IGNORECASE) _cache_lock = _thread_allocate_lock() # DO NOT modify _TimeRE_cache or _regex_cache without acquiring the cache lock @@ -294,8 +294,15 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): """Return a time struct based on the input string and the format string.""" + + for index, arg in enumerate([data_string, format]): + if not isinstance(arg, str): + msg = "strptime() argument {} must be str, not {}" + raise TypeError(msg.format(arg, index)) + global _TimeRE_cache, _regex_cache with _cache_lock: + if _getlang() != _TimeRE_cache.locale_time.lang: _TimeRE_cache = TimeRE() _regex_cache.clear() Modified: python/branches/py3k/Lib/test/test_time.py ============================================================================== --- python/branches/py3k/Lib/test/test_time.py (original) +++ python/branches/py3k/Lib/test/test_time.py Mon Mar 30 23:30:26 2009 @@ -116,6 +116,11 @@ self.fail("conversion specifier %r failed with '%s' input." % (format, strf_output)) + def test_strptime_bytes(self): + # Make sure only strings are accepted as arguments to strptime. + self.assertRaises(TypeError, time.strptime, b'2009', "%Y") + self.assertRaises(TypeError, time.strptime, '2009', b'%Y') + def test_asctime(self): time.asctime(time.gmtime(self.t)) self.assertRaises(TypeError, time.asctime, 0) Modified: python/branches/py3k/Misc/ACKS ============================================================================== --- python/branches/py3k/Misc/ACKS (original) +++ python/branches/py3k/Misc/ACKS Mon Mar 30 23:30:26 2009 @@ -411,6 +411,7 @@ Inyeol Lee Thomas Lee Christopher Lee +Tennessee Leeuwenburg Luc Lefebvre Kip Lehman Joerg Lehmann Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Mon Mar 30 23:30:26 2009 @@ -43,6 +43,9 @@ Library ------- +- Issue #5236: Change time.strptime() to only take strings. Didn't work with + bytes already but the failure was non-obvious. + - Issue #5177: Multiprocessing's SocketListener class now uses socket.SO_REUSEADDR on all connections so that the user no longer needs to wait 120 seconds for the socket to expire. From brett at python.org Mon Mar 30 23:33:55 2009 From: brett at python.org (Brett Cannon) Date: Mon, 30 Mar 2009 14:33:55 -0700 Subject: [Python-checkins] r70726 - peps/trunk/pep-0302.txt In-Reply-To: References: <20090330164941.F36B31E4037@bag.python.org> Message-ID: On Mon, Mar 30, 2009 at 12:10, Georg Brandl wrote: > brett.cannon schrieb: > > Author: brett.cannon > > Date: Mon Mar 30 18:49:41 2009 > > New Revision: 70726 > > > > Log: > > Move over to using the term 'finder' as used in importlib. > > Should there be an "ImpFinder" alias of "ImpImporter" in pkgutil? Maybe, but I don't feel like doing it. =) -Brett -------------- next part -------------- An HTML attachment was scrubbed... URL: From buildbot at python.org Mon Mar 30 23:36:01 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 21:36:01 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable trunk Message-ID: <20090330213601.A8B071E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%20trunk/builds/288 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: brett.cannon,jesse.noller,kurt.kaiser,r.david.murray,ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Mon Mar 30 23:43:25 2009 From: python-checkins at python.org (guido.van.rossum) Date: Mon, 30 Mar 2009 23:43:25 +0200 (CEST) Subject: [Python-checkins] r70756 - in python/branches/release30-maint: Lib/test/test_imp.py Misc/ACKS Misc/NEWS Python/import.c Message-ID: <20090330214325.A1FA91E4002@bag.python.org> Author: guido.van.rossum Date: Mon Mar 30 23:43:25 2009 New Revision: 70756 Log: Issue #5604: non-ASCII characters in module name passed to imp.find_module() were converted to UTF-8 while the path is converted to the default filesystem encoding, causing nonsense. Thanks Andrew Svetlov! Modified: python/branches/release30-maint/Lib/test/test_imp.py python/branches/release30-maint/Misc/ACKS python/branches/release30-maint/Misc/NEWS python/branches/release30-maint/Python/import.c Modified: python/branches/release30-maint/Lib/test/test_imp.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_imp.py (original) +++ python/branches/release30-maint/Lib/test/test_imp.py Mon Mar 30 23:43:25 2009 @@ -1,4 +1,7 @@ import imp +import locale +import os +import os.path import sys import unittest from test import support @@ -75,6 +78,74 @@ support.unlink(temp_mod_name + '.pyc') support.unlink(temp_mod_name + '.pyo') + def test_issue5604(self): + # Test cannot cover imp.load_compiled function. + # Martin von Loewis note what shared library cannot have non-ascii + # character because init_xxx function cannot be compiled + # and issue never happens for dynamic modules. + # But sources modified to follow generic way for processing pathes. + + locale_encoding = locale.getpreferredencoding() + + # covers utf-8 and Windows ANSI code pages + # one non-space symbol from every page + # (http://en.wikipedia.org/wiki/Code_page) + known_locales = { + 'utf-8' : b'\xe4', + 'cp1250' : b'\x8C', + 'cp1251' : b'\xc0', + 'cp1252' : b'\xc0', + 'cp1253' : b'\xc1', + 'cp1254' : b'\xc0', + 'cp1255' : b'\xe0', + 'cp1256' : b'\xe0', + 'cp1257' : b'\xc0', + 'cp1258' : b'\xc0', + } + + special_char = known_locales.get(locale_encoding) + if special_char: + encoded_char = special_char.decode(locale_encoding) + temp_mod_name = 'test_imp_helper_' + encoded_char + test_package_name = 'test_imp_helper_package_' + encoded_char + init_file_name = os.path.join(test_package_name, '__init__.py') + try: + with open(temp_mod_name + '.py', 'w') as file: + file.write('a = 1\n') + file, filename, info = imp.find_module(temp_mod_name) + self.assertNotEquals(None, file) + self.assertTrue(filename[:-3].endswith(temp_mod_name)) + self.assertEquals('.py', info[0]) + self.assertEquals('U', info[1]) + self.assertEquals(imp.PY_SOURCE, info[2]) + + mod = imp.load_module(temp_mod_name, file, filename, info) + self.assertEquals(1, mod.a) + file.close() + + mod = imp.load_source(temp_mod_name, temp_mod_name + '.py') + self.assertEquals(1, mod.a) + + mod = imp.load_compiled(temp_mod_name, temp_mod_name + '.pyc') + self.assertEquals(1, mod.a) + + if not os.path.exists(test_package_name): + os.mkdir(test_package_name) + with open(init_file_name, 'w') as file: + file.write('b = 2\n') + package = imp.load_package(test_package_name, test_package_name) + self.assertEquals(2, package.b) + finally: + support.unlink(temp_mod_name + '.py') + support.unlink(temp_mod_name + '.pyc') + support.unlink(temp_mod_name + '.pyo') + + support.unlink(init_file_name + '.py') + support.unlink(init_file_name + '.pyc') + support.unlink(init_file_name + '.pyo') + support.rmtree(test_package_name) + + def test_reload(self): import marshal imp.reload(marshal) Modified: python/branches/release30-maint/Misc/ACKS ============================================================================== --- python/branches/release30-maint/Misc/ACKS (original) +++ python/branches/release30-maint/Misc/ACKS Mon Mar 30 23:43:25 2009 @@ -675,6 +675,7 @@ Mark Summerfield Hisao Suzuki Kalle Svensson +Andrew Svetlov Paul Swartz Thenault Sylvain Geoff Talvola @@ -777,5 +778,5 @@ Mike Zarnstorff Siebren van der Zee Uwe Zessin -Tarek Ziad? +Tarek Ziad?? Peter ?strand Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Mon Mar 30 23:43:25 2009 @@ -12,6 +12,10 @@ Core and Builtins ----------------- +- Issue #5604: non-ASCII characters in module name passed to + imp.find_module() were converted to UTF-8 while the path is + converted to the default filesystem encoding, causing nonsense. + - Issue #5392: when a very low recursion limit was set, the interpreter would abort with a fatal error after the recursion limit was hit twice. Modified: python/branches/release30-maint/Python/import.c ============================================================================== --- python/branches/release30-maint/Python/import.c (original) +++ python/branches/release30-maint/Python/import.c Mon Mar 30 23:43:25 2009 @@ -3006,15 +3006,20 @@ PyObject *fob = NULL; PyObject *m; FILE *fp; - if (!PyArg_ParseTuple(args, "ss|O:load_compiled", - &name, &pathname, &fob)) + if (!PyArg_ParseTuple(args, "ses|O:load_compiled", + &name, + Py_FileSystemDefaultEncoding, &pathname, + &fob)) return NULL; fp = get_file(pathname, fob, "rb"); - if (fp == NULL) + if (fp == NULL) { + PyMem_Free(pathname); return NULL; + } m = load_compiled_module(name, pathname, fp); if (fob == NULL) fclose(fp); + PyMem_Free(pathname); return m; } @@ -3028,15 +3033,20 @@ PyObject *fob = NULL; PyObject *m; FILE *fp = NULL; - if (!PyArg_ParseTuple(args, "ss|O:load_dynamic", - &name, &pathname, &fob)) + if (!PyArg_ParseTuple(args, "ses|O:load_dynamic", + &name, + Py_FileSystemDefaultEncoding, &pathname, + &fob)) return NULL; if (fob) { fp = get_file(pathname, fob, "r"); - if (fp == NULL) + if (fp == NULL) { + PyMem_Free(pathname); return NULL; + } } m = _PyImport_LoadDynamicModule(name, pathname, fp); + PyMem_Free(pathname); return m; } @@ -3050,12 +3060,16 @@ PyObject *fob = NULL; PyObject *m; FILE *fp; - if (!PyArg_ParseTuple(args, "ss|O:load_source", - &name, &pathname, &fob)) + if (!PyArg_ParseTuple(args, "ses|O:load_source", + &name, + Py_FileSystemDefaultEncoding, &pathname, + &fob)) return NULL; fp = get_file(pathname, fob, "r"); - if (fp == NULL) + if (fp == NULL) { + PyMem_Free(pathname); return NULL; + } m = load_source_module(name, pathname, fp); if (fob == NULL) fclose(fp); @@ -3068,13 +3082,15 @@ char *name; PyObject *fob; char *pathname; + PyObject * ret; char *suffix; /* Unused */ char *mode; int type; FILE *fp; - if (!PyArg_ParseTuple(args, "sOs(ssi):load_module", - &name, &fob, &pathname, + if (!PyArg_ParseTuple(args, "sOes(ssi):load_module", + &name, &fob, + Py_FileSystemDefaultEncoding, &pathname, &suffix, &mode, &type)) return NULL; if (*mode) { @@ -3085,6 +3101,7 @@ if (!(*mode == 'r' || *mode == 'U') || strchr(mode, '+')) { PyErr_Format(PyExc_ValueError, "invalid file open mode %.200s", mode); + PyMem_Free(pathname); return NULL; } } @@ -3092,10 +3109,14 @@ fp = NULL; else { fp = get_file(NULL, fob, mode); - if (fp == NULL) + if (fp == NULL) { + PyMem_Free(pathname); return NULL; - } - return load_module(name, fp, pathname, type, NULL); + } + } + ret = load_module(name, fp, pathname, type, NULL); + PyMem_Free(pathname); + return ret; } static PyObject * @@ -3103,9 +3124,13 @@ { char *name; char *pathname; - if (!PyArg_ParseTuple(args, "ss:load_package", &name, &pathname)) + PyObject * ret; + if (!PyArg_ParseTuple(args, "ses:load_package", + &name, Py_FileSystemDefaultEncoding, &pathname)) return NULL; - return load_package(name, pathname); + ret = load_package(name, pathname); + PyMem_Free(pathname); + return ret; } static PyObject * From python-checkins at python.org Mon Mar 30 23:51:50 2009 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 30 Mar 2009 23:51:50 +0200 (CEST) Subject: [Python-checkins] r70757 - in python/trunk/Lib: test/test_urllib.py test/test_urlparse.py urllib.py urlparse.py Message-ID: <20090330215150.8F4C41E4010@bag.python.org> Author: senthil.kumaran Date: Mon Mar 30 23:51:50 2009 New Revision: 70757 Log: Fix for bugs: Issue4675 and Issue4962. Modified: python/trunk/Lib/test/test_urllib.py python/trunk/Lib/test/test_urlparse.py python/trunk/Lib/urllib.py python/trunk/Lib/urlparse.py Modified: python/trunk/Lib/test/test_urllib.py ============================================================================== --- python/trunk/Lib/test/test_urllib.py (original) +++ python/trunk/Lib/test/test_urllib.py Mon Mar 30 23:51:50 2009 @@ -582,6 +582,22 @@ "url2pathname() failed; %s != %s" % (expect, result)) +class Utility_Tests(unittest.TestCase): + """Testcase to test the various utility functions in the urllib.""" + + def test_splitpasswd(self): + """Some of the password examples are not sensible, but it is added to + confirming to RFC2617 and addressing issue4675. + """ + self.assertEqual(('user', 'ab'),urllib.splitpasswd('user:ab')) + self.assertEqual(('user', 'a\nb'),urllib.splitpasswd('user:a\nb')) + self.assertEqual(('user', 'a\tb'),urllib.splitpasswd('user:a\tb')) + self.assertEqual(('user', 'a\rb'),urllib.splitpasswd('user:a\rb')) + self.assertEqual(('user', 'a\fb'),urllib.splitpasswd('user:a\fb')) + self.assertEqual(('user', 'a\vb'),urllib.splitpasswd('user:a\vb')) + self.assertEqual(('user', 'a:b'),urllib.splitpasswd('user:a:b')) + + # Just commented them out. # Can't really tell why keep failing in windows and sparc. # Everywhere else they work ok, but on those machines, someteimes @@ -676,6 +692,7 @@ UnquotingTests, urlencode_Tests, Pathname_Tests, + Utility_Tests, #FTPWrapperTests, ) Modified: python/trunk/Lib/test/test_urlparse.py ============================================================================== --- python/trunk/Lib/test/test_urlparse.py (original) +++ python/trunk/Lib/test/test_urlparse.py Mon Mar 30 23:51:50 2009 @@ -96,6 +96,9 @@ '', '', ''), ('mms', 'wms.sys.hinet.net', '/cts/Drama/09006251100.asf', '', '')), + ('nfs://server/path/to/file.txt', + ('nfs', 'server', '/path/to/file.txt', '', '', ''), + ('nfs', 'server', '/path/to/file.txt', '', '')), ('svn+ssh://svn.zope.org/repos/main/ZConfig/trunk/', ('svn+ssh', 'svn.zope.org', '/repos/main/ZConfig/trunk/', '', '', ''), Modified: python/trunk/Lib/urllib.py ============================================================================== --- python/trunk/Lib/urllib.py (original) +++ python/trunk/Lib/urllib.py Mon Mar 30 23:51:50 2009 @@ -1073,7 +1073,7 @@ global _passwdprog if _passwdprog is None: import re - _passwdprog = re.compile('^([^:]*):(.*)$') + _passwdprog = re.compile('^([^:]*):(.*)$',re.S) match = _passwdprog.match(user) if match: return match.group(1, 2) Modified: python/trunk/Lib/urlparse.py ============================================================================== --- python/trunk/Lib/urlparse.py (original) +++ python/trunk/Lib/urlparse.py Mon Mar 30 23:51:50 2009 @@ -14,7 +14,7 @@ uses_netloc = ['ftp', 'http', 'gopher', 'nntp', 'telnet', 'imap', 'wais', 'file', 'mms', 'https', 'shttp', 'snews', 'prospero', 'rtsp', 'rtspu', 'rsync', '', - 'svn', 'svn+ssh', 'sftp'] + 'svn', 'svn+ssh', 'sftp','nfs'] non_hierarchical = ['gopher', 'hdl', 'mailto', 'news', 'telnet', 'wais', 'imap', 'snews', 'sip', 'sips'] uses_params = ['ftp', 'hdl', 'prospero', 'http', 'imap', From python-checkins at python.org Mon Mar 30 23:53:29 2009 From: python-checkins at python.org (jesse.noller) Date: Mon, 30 Mar 2009 23:53:29 +0200 (CEST) Subject: [Python-checkins] r70758 - python/trunk/Lib/test/test_multiprocessing.py Message-ID: <20090330215329.EB61D1E4018@bag.python.org> Author: jesse.noller Date: Mon Mar 30 23:53:29 2009 New Revision: 70758 Log: finalize the queue prior to shutdown Modified: python/trunk/Lib/test/test_multiprocessing.py Modified: python/trunk/Lib/test/test_multiprocessing.py ============================================================================== --- python/trunk/Lib/test/test_multiprocessing.py (original) +++ python/trunk/Lib/test/test_multiprocessing.py Mon Mar 30 23:53:29 2009 @@ -1208,10 +1208,12 @@ p.start() queue = manager.get_queue() self.assertEqual(queue.get(), 'hello world') + del queue manager.shutdown() manager = QueueManager( address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) manager.start() + manager.shutdown() # # From python-checkins at python.org Mon Mar 30 23:53:56 2009 From: python-checkins at python.org (eric.smith) Date: Mon, 30 Mar 2009 23:53:56 +0200 (CEST) Subject: [Python-checkins] r70759 - in python/branches/py3k-short-float-repr: Include/pystrtod.h Objects/floatobject.c Python/pystrtod.c Python/strtod.c Message-ID: <20090330215356.5A8A91E4002@bag.python.org> Author: eric.smith Date: Mon Mar 30 23:53:55 2009 New Revision: 70759 Log: Hooked up new float formats to float's str(); deleted unused strtod.c. Removed: python/branches/py3k-short-float-repr/Python/strtod.c Modified: python/branches/py3k-short-float-repr/Include/pystrtod.h python/branches/py3k-short-float-repr/Objects/floatobject.c python/branches/py3k-short-float-repr/Python/pystrtod.c Modified: python/branches/py3k-short-float-repr/Include/pystrtod.h ============================================================================== --- python/branches/py3k-short-float-repr/Include/pystrtod.h (original) +++ python/branches/py3k-short-float-repr/Include/pystrtod.h Mon Mar 30 23:53:55 2009 @@ -9,6 +9,13 @@ PyAPI_FUNC(double) PyOS_ascii_strtod(const char *str, char **ptr); PyAPI_FUNC(double) PyOS_ascii_atof(const char *str); PyAPI_FUNC(char *) PyOS_ascii_formatd(char *buffer, size_t buf_len, const char *format, double d); +PyAPI_FUNC(char *) PyOS_double_to_string(double val, + int mode, + char format_code, + int precision, + int sign, + int add_dot_0_if_integer); + #ifdef __cplusplus Modified: python/branches/py3k-short-float-repr/Objects/floatobject.c ============================================================================== --- python/branches/py3k-short-float-repr/Objects/floatobject.c (original) +++ python/branches/py3k-short-float-repr/Objects/floatobject.c Mon Mar 30 23:53:55 2009 @@ -379,101 +379,6 @@ } -/* convert a Python float to a minimal string that evaluates back to that - float. The output is minimal in the sense of having the least possible - number of significant digits. */ - -static void -format_float_short(char *buf, size_t buflen, PyFloatObject *v) -{ - double d; - char *digits, *digits_end; - int decpt, sign, exp_len; - size_t digits_len, i; - - assert(PyFloat_Check(v)); - d = PyFloat_AS_DOUBLE(v); - - /* _Py_dg_dtoa returns a digit string (no decimal point - or exponent) */ - digits = _Py_dg_dtoa(d, 0, 0, &decpt, &sign, &digits_end); - assert(digits_end != NULL && digits_end > digits); - digits_len = digits_end - digits; - - if (!isdigit(digits[0])) { - /* infinities and nans here; adapt Gay's output, - so convert Infinity to inf and NaN to nan, and - ignore sign of nan. */ - if (digits[0] == 'i' || digits[0] == 'I') { - if (sign == 1) { - *buf++ = '-'; - } - strncpy(buf, "inf", 3); - buf += 3; - } else { - assert(digits[0] == 'n' || digits[0] == 'N'); - strncpy(buf, "nan", 3); - buf += 3; - } - } - else if (-4 < decpt && decpt <= 17) { - if (sign == 1) { - *buf++ = '-'; - } - /* use fixed-point notation if 1e-4 <= value < 1e17 */ - if (decpt <= 0) { - /* output: 0.00...00dd...dd */ - *buf++ = '0'; - *buf++ = '.'; - for (i=0; i < -decpt; i++) - *buf++ = '0'; - strncpy(buf, digits, digits_len); - buf += digits_len; - } - else if (decpt < digits_len) { - /* output: dd...dd.dd...dd */ - strncpy(buf, digits, decpt); - buf += decpt; - *buf++ = '.'; - strncpy(buf, digits+decpt, digits_len-decpt); - buf += digits_len-decpt; - } - else { - /* decpt >= digits_len. output: dd...dd00...00.0 */ - strncpy(buf, digits, digits_len); - buf += digits_len; - for (i=0; i < decpt-digits_len; i++) - *buf++ = '0'; - *buf++ = '.'; - *buf++ = '0'; - } - } - else { - /* exponential notation: d[.dddd]e(+|-)ee; - at least 2 digits in exponent */ - if (sign == 1) { - *buf++ = '-'; - } - *buf++ = digits[0]; - if (digits_len > 1) { - *buf++ = '.'; - strncpy(buf, digits+1, digits_len-1); - buf += digits_len-1; - } - *buf++ = 'e'; - exp_len = sprintf(buf, "%+.02d", decpt-1); - buf += exp_len; - } - *buf++ = '\0'; -} - -static void -format_float(char *buf, size_t buflen, PyFloatObject *v, int precision) -{ - assert(PyFloat_Check(v)); - format_double(buf, buflen, PyFloat_AS_DOUBLE(v), precision); -} - /* Macro and helper that convert PyObject obj to a C double and store the value in dbl. If conversion to double raises an exception, obj is set to NULL, and the function invoking this macro returns NULL. If @@ -524,20 +429,29 @@ #define PREC_STR 12 static PyObject * -float_repr(PyFloatObject *v) +float_str_or_repr(PyFloatObject *v, int mode, int precision) { - char buf[100]; - format_float_short(buf, sizeof(buf), v); + PyObject *result; + char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v), + mode, 'g', precision, 0, 1); + if (!buf) + return PyErr_NoMemory(); + result = PyUnicode_FromString(buf); + PyMem_Free(buf); + return result; +} - return PyUnicode_FromString(buf); +static PyObject * +float_repr(PyFloatObject *v) +{ + /* XXX change PREC_REPR to 0 when mode is supported */ + return float_str_or_repr(v, 0, PREC_REPR); } static PyObject * float_str(PyFloatObject *v) { - char buf[100]; - format_float(buf, sizeof(buf), v, PREC_STR); - return PyUnicode_FromString(buf); + return float_str_or_repr(v, 2, PREC_STR); } /* Comparison is pretty much a nightmare. When comparing float to float, @@ -2067,7 +1981,9 @@ if (PyFloat_CheckExact(p) && Py_REFCNT(p) != 0) { char buf[100]; - format_float(buf, sizeof(buf), p, PREC_STR); + format_double(buf, sizeof(buf), + PyFloat_AS_DOUBLE(p), + PREC_STR); /* XXX(twouters) cast refcount to long until %zd is universally available Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/pystrtod.c (original) +++ python/branches/py3k-short-float-repr/Python/pystrtod.c Mon Mar 30 23:53:55 2009 @@ -488,3 +488,128 @@ { return PyOS_ascii_strtod(nptr, NULL); } + + +/* convert a Python float to a minimal string that evaluates back to that + float. The output is minimal in the sense of having the least possible + number of significant digits. */ + +static void +format_float_short(char *buf, size_t buflen, double d, int mode, int precision) +{ + char *digits, *digits_end; + int decpt, sign, exp_len; + size_t digits_len, i; + + /* _Py_dg_dtoa returns a digit string (no decimal point + or exponent) */ + digits = _Py_dg_dtoa(d, mode, precision, &decpt, &sign, &digits_end); + assert(digits_end != NULL && digits_end > digits); + digits_len = digits_end - digits; + + if (!isdigit(digits[0])) { + /* infinities and nans here; adapt Gay's output, + so convert Infinity to inf and NaN to nan, and + ignore sign of nan. */ + if (digits[0] == 'i' || digits[0] == 'I') { + if (sign == 1) { + *buf++ = '-'; + } + strncpy(buf, "inf", 3); + buf += 3; + } else { + assert(digits[0] == 'n' || digits[0] == 'N'); + strncpy(buf, "nan", 3); + buf += 3; + } + } + else if (-4 < decpt && decpt <= 17) { + if (sign == 1) { + *buf++ = '-'; + } + /* use fixed-point notation if 1e-4 <= value < 1e17 */ + if (decpt <= 0) { + /* output: 0.00...00dd...dd */ + *buf++ = '0'; + *buf++ = '.'; + for (i=0; i < -decpt; i++) + *buf++ = '0'; + strncpy(buf, digits, digits_len); + buf += digits_len; + } + else if (decpt < digits_len) { + /* output: dd...dd.dd...dd */ + strncpy(buf, digits, decpt); + buf += decpt; + *buf++ = '.'; + strncpy(buf, digits+decpt, digits_len-decpt); + buf += digits_len-decpt; + } + else { + /* decpt >= digits_len. output: dd...dd00...00.0 */ + strncpy(buf, digits, digits_len); + buf += digits_len; + for (i=0; i < decpt-digits_len; i++) + *buf++ = '0'; + *buf++ = '.'; + *buf++ = '0'; + } + } + else { + /* exponential notation: d[.dddd]e(+|-)ee; + at least 2 digits in exponent */ + if (sign == 1) { + *buf++ = '-'; + } + *buf++ = digits[0]; + if (digits_len > 1) { + *buf++ = '.'; + strncpy(buf, digits+1, digits_len-1); + buf += digits_len-1; + } + *buf++ = 'e'; + exp_len = sprintf(buf, "%+.02d", decpt-1); + buf += exp_len; + } + *buf++ = '\0'; +} + +PyAPI_FUNC(char *) PyOS_double_to_string(double val, + int mode, + char format_code, + int precision, + int sign, + int add_dot_0_if_integer) +{ + char fmt[32]; + char* buf = (char *)PyMem_Malloc(512); + +// printf("in PyOS_double_to_string\n"); + if (!buf) + return NULL; + + /* XXX validate format_code */ + + format_float_short(buf, 512, val, mode, precision); + + if (add_dot_0_if_integer) { + /* If the result was just an integer, without a decimal, then + add ".0" to the end of the string. */ + char *cp = buf; + if (*cp == '-') + cp++; + for (; *cp != '\0'; cp++) { + /* Any non-digit means it's not an integer; + this takes care of NAN and INF as well. */ + if (!isdigit(Py_CHARMASK(*cp))) + break; + } + if (*cp == '\0') { + *cp++ = '.'; + *cp++ = '0'; + *cp++ = '\0'; + } + } + + return buf; +} Deleted: python/branches/py3k-short-float-repr/Python/strtod.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/strtod.c Mon Mar 30 23:53:55 2009 +++ (empty file) @@ -1,156 +0,0 @@ -#include "pyconfig.h" - -/* comp.sources.misc strtod(), as posted in comp.lang.tcl, - with bugfix for "123000.0" and acceptance of space after 'e' sign nuked. - - ************************************************************ - * YOU MUST EDIT THE MACHINE-DEPENDENT DEFINITIONS BELOW!!! * - ************************************************************ -*/ - -/* File : stdtod.c (Modified version of str2dbl.c) - Author : Richard A. O'Keefe @ Quintus Computer Systems, Inc. - Updated: Tuesday August 2nd, 1988 - Defines: double strtod (char *str, char**ptr) -*/ - -/* This is an implementation of the strtod() function described in the - System V manuals, with a different name to avoid linker problems. - All that str2dbl() does itself is check that the argument is well-formed - and is in range. It leaves the work of conversion to atof(), which is - assumed to exist and deliver correct results (if they can be represented). - - There are two reasons why this should be provided to the net: - (a) some UNIX systems do not yet have strtod(), or do not have it - available in the BSD "universe" (but they do have atof()). - (b) some of the UNIX systems that *do* have it get it wrong. - (some crash with large arguments, some assign the wrong *ptr value). - There is a reason why *we* are providing it: we need a correct version - of strtod(), and if we give this one away maybe someone will look for - mistakes in it and fix them for us (:-). -*/ - -/* The following constants are machine-specific. MD{MIN,MAX}EXPT are - integers and MD{MIN,MAX}FRAC are strings such that - 0.${MDMAXFRAC}e${MDMAXEXPT} is the largest representable double, - 0.${MDMINFRAC}e${MDMINEXPT} is the smallest representable +ve double - MD{MIN,MAX}FRAC must not have any trailing zeros. - The values here are for IEEE-754 64-bit floats. - It is not perfectly clear to me whether an IEEE infinity should be - returned for overflow, nor what a portable way of writing one is, - so HUGE is just 0.MAXFRAC*10**MAXEXPT (this seems still to be the - UNIX convention). - - I do know about , but the whole point of this file is that - we can't always trust that stuff to be there or to be correct. -*/ -static int MDMINEXPT = -323; -static char MDMINFRAC[] = "494065645841246544"; -static double ZERO = 0.0; - -static int MDMAXEXPT = 309; -static char MDMAXFRAC[] = "17976931348623157"; -static double HUGE = 1.7976931348623157e308; - -extern double atof(const char *); /* Only called when result known to be ok */ - -#ifdef HAVE_ERRNO_H -#include -#endif -extern int errno; - -double strtod(char *str, char **ptr) -{ - int sign, scale, dotseen; - int esign, expt; - char *save; - register char *sp, *dp; - register int c; - char *buforg, *buflim; - char buffer[64]; /* 45-digit significant + */ - /* 13-digit exponent */ - sp = str; - while (*sp == ' ') sp++; - sign = 1; - if (*sp == '-') sign -= 2, sp++; - dotseen = 0, scale = 0; - dp = buffer; - *dp++ = '0'; *dp++ = '.'; - buforg = dp, buflim = buffer+48; - for (save = sp; c = *sp; sp++) - if (c == '.') { - if (dotseen) break; - dotseen++; - } else - if ((unsigned)(c-'0') > (unsigned)('9'-'0')) { - break; - } else - if (c == '0') { - if (dp != buforg) { - /* This is not the first digit, so we want to keep it */ - if (dp < buflim) *dp++ = c; - if (!dotseen) scale++; - } else { - /* No non-zero digits seen yet */ - /* If a . has been seen, scale must be adjusted */ - if (dotseen) scale--; - } - } else { - /* This is a nonzero digit, so we want to keep it */ - if (dp < buflim) *dp++ = c; - /* If it precedes a ., scale must be adjusted */ - if (!dotseen) scale++; - } - if (sp == save) { - if (ptr) *ptr = str; - errno = EDOM; /* what should this be? */ - return ZERO; - } - - while (dp > buforg && dp[-1] == '0') --dp; - if (dp == buforg) *dp++ = '0'; - *dp = '\0'; - /* Now the contents of buffer are - +--+--------+-+--------+ - |0.|fraction|\|leftover| - +--+--------+-+--------+ - ^dp points here - where fraction begins with 0 iff it is "0", and has at most - 45 digits in it, and leftover is at least 16 characters. - */ - save = sp, expt = 0, esign = 1; - do { - c = *sp++; - if (c != 'e' && c != 'E') break; - c = *sp++; - if (c == '-') esign -= 2, c = *sp++; else - if (c == '+' /* || c == ' ' */ ) c = *sp++; - if ((unsigned)(c-'0') > (unsigned)('9'-'0')) break; - while (c == '0') c = *sp++; - for (; (unsigned)(c-'0') <= (unsigned)('9'-'0'); c = *sp++) - expt = expt*10 + c-'0'; - if (esign < 0) expt = -expt; - save = sp-1; - } while (0); - if (ptr) *ptr = save; - expt += scale; - /* Now the number is sign*0.fraction*10**expt */ - errno = ERANGE; - if (expt > MDMAXEXPT) { - return HUGE*sign; - } else - if (expt == MDMAXEXPT) { - if (strcmp(buforg, MDMAXFRAC) > 0) return HUGE*sign; - } else - if (expt < MDMINEXPT) { - return ZERO*sign; - } else - if (expt == MDMINEXPT) { - if (strcmp(buforg, MDMINFRAC) < 0) return ZERO*sign; - } - /* We have now established that the number can be */ - /* represented without overflow or underflow */ - (void) sprintf(dp, "E%d", expt); - errno = 0; - return atof(buffer)*sign; -} From python-checkins at python.org Mon Mar 30 23:54:42 2009 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 30 Mar 2009 23:54:42 +0200 (CEST) Subject: [Python-checkins] r70760 - in python/branches/py3k/Lib: test/test_urllib.py test/test_urlparse.py urllib/parse.py Message-ID: <20090330215442.2234D1E402F@bag.python.org> Author: senthil.kumaran Date: Mon Mar 30 23:54:41 2009 New Revision: 70760 Log: Fix for Issue4962, issue4675. Modified: python/branches/py3k/Lib/test/test_urllib.py python/branches/py3k/Lib/test/test_urlparse.py python/branches/py3k/Lib/urllib/parse.py Modified: python/branches/py3k/Lib/test/test_urllib.py ============================================================================== --- python/branches/py3k/Lib/test/test_urllib.py (original) +++ python/branches/py3k/Lib/test/test_urllib.py Mon Mar 30 23:54:41 2009 @@ -830,6 +830,21 @@ "url2pathname() failed; %s != %s" % (expect, result)) +class Utility_Tests(unittest.TestCase): + """Testcase to test the various utility functions in the urllib.""" + + def test_splitpasswd(self): + """Some of password examples are not sensible, but it is added to + confirming to RFC2617 and addressing issue4675. + """ + self.assertEqual(('user', 'ab'),urllib.parse.splitpasswd('user:ab')) + self.assertEqual(('user', 'a\nb'),urllib.parse.splitpasswd('user:a\nb')) + self.assertEqual(('user', 'a\tb'),urllib.parse.splitpasswd('user:a\tb')) + self.assertEqual(('user', 'a\rb'),urllib.parse.splitpasswd('user:a\rb')) + self.assertEqual(('user', 'a\fb'),urllib.parse.splitpasswd('user:a\fb')) + self.assertEqual(('user', 'a\vb'),urllib.parse.splitpasswd('user:a\vb')) + self.assertEqual(('user', 'a:b'),urllib.parse.splitpasswd('user:a:b')) + # Just commented them out. # Can't really tell why keep failing in windows and sparc. # Everywhere else they work ok, but on those machines, someteimes @@ -920,6 +935,7 @@ UnquotingTests, urlencode_Tests, Pathname_Tests, + Utility_Tests, #FTPWrapperTests, ) Modified: python/branches/py3k/Lib/test/test_urlparse.py ============================================================================== --- python/branches/py3k/Lib/test/test_urlparse.py (original) +++ python/branches/py3k/Lib/test/test_urlparse.py Mon Mar 30 23:54:41 2009 @@ -97,6 +97,9 @@ '', '', ''), ('mms', 'wms.sys.hinet.net', '/cts/Drama/09006251100.asf', '', '')), + ('nfs://server/path/to/file.txt', + ('nfs', 'server', '/path/to/file.txt', '', '', ''), + ('nfs', 'server', '/path/to/file.txt', '', '')), ('svn+ssh://svn.zope.org/repos/main/ZConfig/trunk/', ('svn+ssh', 'svn.zope.org', '/repos/main/ZConfig/trunk/', '', '', ''), Modified: python/branches/py3k/Lib/urllib/parse.py ============================================================================== --- python/branches/py3k/Lib/urllib/parse.py (original) +++ python/branches/py3k/Lib/urllib/parse.py Mon Mar 30 23:54:41 2009 @@ -19,7 +19,7 @@ uses_netloc = ['ftp', 'http', 'gopher', 'nntp', 'telnet', 'imap', 'wais', 'file', 'mms', 'https', 'shttp', 'snews', 'prospero', 'rtsp', 'rtspu', 'rsync', '', - 'svn', 'svn+ssh', 'sftp'] + 'svn', 'svn+ssh', 'sftp','nfs'] non_hierarchical = ['gopher', 'hdl', 'mailto', 'news', 'telnet', 'wais', 'imap', 'snews', 'sip', 'sips'] uses_params = ['ftp', 'hdl', 'prospero', 'http', 'imap', @@ -645,7 +645,7 @@ global _passwdprog if _passwdprog is None: import re - _passwdprog = re.compile('^([^:]*):(.*)$') + _passwdprog = re.compile('^([^:]*):(.*)$',re.S) match = _passwdprog.match(user) if match: return match.group(1, 2) From python-checkins at python.org Mon Mar 30 23:57:37 2009 From: python-checkins at python.org (jesse.noller) Date: Mon, 30 Mar 2009 23:57:37 +0200 (CEST) Subject: [Python-checkins] r70761 - in python/branches/release26-maint: Lib/test/test_multiprocessing.py Message-ID: <20090330215737.2375D1E4002@bag.python.org> Author: jesse.noller Date: Mon Mar 30 23:57:36 2009 New Revision: 70761 Log: finalize the queue to resolve test issue Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_multiprocessing.py Modified: python/branches/release26-maint/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_multiprocessing.py (original) +++ python/branches/release26-maint/Lib/test/test_multiprocessing.py Mon Mar 30 23:57:36 2009 @@ -1207,10 +1207,12 @@ p.start() queue = manager.get_queue() self.assertEqual(queue.get(), 'hello world') + del queue manager.shutdown() manager = QueueManager( address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) manager.start() + manager.shutdown() # # From python-checkins at python.org Tue Mar 31 00:01:37 2009 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 31 Mar 2009 00:01:37 +0200 (CEST) Subject: [Python-checkins] r70762 - in python/branches/py3k: Lib/test/test_imp.py Misc/ACKS Misc/NEWS Python/import.c Message-ID: <20090330220137.3954A1E4002@bag.python.org> Author: guido.van.rossum Date: Tue Mar 31 00:01:35 2009 New Revision: 70762 Log: Issue #5604: non-ASCII characters in module name passed to imp.find_module() were converted to UTF-8 while the path is converted to the default filesystem encoding, causing nonsense. Thanks to Andrew Svetlov. (This time to the right branch. Will block duplicate merge to 3.0.2.) Modified: python/branches/py3k/Lib/test/test_imp.py python/branches/py3k/Misc/ACKS python/branches/py3k/Misc/NEWS python/branches/py3k/Python/import.c Modified: python/branches/py3k/Lib/test/test_imp.py ============================================================================== --- python/branches/py3k/Lib/test/test_imp.py (original) +++ python/branches/py3k/Lib/test/test_imp.py Tue Mar 31 00:01:35 2009 @@ -1,4 +1,7 @@ import imp +import locale +import os +import os.path import sys import unittest from test import support @@ -75,6 +78,74 @@ support.unlink(temp_mod_name + '.pyc') support.unlink(temp_mod_name + '.pyo') + def test_issue5604(self): + # Test cannot cover imp.load_compiled function. + # Martin von Loewis note what shared library cannot have non-ascii + # character because init_xxx function cannot be compiled + # and issue never happens for dynamic modules. + # But sources modified to follow generic way for processing pathes. + + locale_encoding = locale.getpreferredencoding() + + # covers utf-8 and Windows ANSI code pages + # one non-space symbol from every page + # (http://en.wikipedia.org/wiki/Code_page) + known_locales = { + 'utf-8' : b'\xe4', + 'cp1250' : b'\x8C', + 'cp1251' : b'\xc0', + 'cp1252' : b'\xc0', + 'cp1253' : b'\xc1', + 'cp1254' : b'\xc0', + 'cp1255' : b'\xe0', + 'cp1256' : b'\xe0', + 'cp1257' : b'\xc0', + 'cp1258' : b'\xc0', + } + + special_char = known_locales.get(locale_encoding) + if special_char: + encoded_char = special_char.decode(locale_encoding) + temp_mod_name = 'test_imp_helper_' + encoded_char + test_package_name = 'test_imp_helper_package_' + encoded_char + init_file_name = os.path.join(test_package_name, '__init__.py') + try: + with open(temp_mod_name + '.py', 'w') as file: + file.write('a = 1\n') + file, filename, info = imp.find_module(temp_mod_name) + self.assertNotEquals(None, file) + self.assertTrue(filename[:-3].endswith(temp_mod_name)) + self.assertEquals('.py', info[0]) + self.assertEquals('U', info[1]) + self.assertEquals(imp.PY_SOURCE, info[2]) + + mod = imp.load_module(temp_mod_name, file, filename, info) + self.assertEquals(1, mod.a) + file.close() + + mod = imp.load_source(temp_mod_name, temp_mod_name + '.py') + self.assertEquals(1, mod.a) + + mod = imp.load_compiled(temp_mod_name, temp_mod_name + '.pyc') + self.assertEquals(1, mod.a) + + if not os.path.exists(test_package_name): + os.mkdir(test_package_name) + with open(init_file_name, 'w') as file: + file.write('b = 2\n') + package = imp.load_package(test_package_name, test_package_name) + self.assertEquals(2, package.b) + finally: + support.unlink(temp_mod_name + '.py') + support.unlink(temp_mod_name + '.pyc') + support.unlink(temp_mod_name + '.pyo') + + support.unlink(init_file_name + '.py') + support.unlink(init_file_name + '.pyc') + support.unlink(init_file_name + '.pyo') + support.rmtree(test_package_name) + + def test_reload(self): import marshal imp.reload(marshal) Modified: python/branches/py3k/Misc/ACKS ============================================================================== --- python/branches/py3k/Misc/ACKS (original) +++ python/branches/py3k/Misc/ACKS Tue Mar 31 00:01:35 2009 @@ -688,6 +688,7 @@ Mark Summerfield Hisao Suzuki Kalle Svensson +Andrew Svetlov Paul Swartz Thenault Sylvain Geoff Talvola Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 31 00:01:35 2009 @@ -12,6 +12,10 @@ Core and Builtins ----------------- +- Issue #5604: non-ASCII characters in module name passed to + imp.find_module() were converted to UTF-8 while the path is + converted to the default filesystem encoding, causing nonsense. + - Issue #5126: str.isprintable() returned False for space characters. - Issue #4688: Add a heuristic so that tuples and dicts containing only Modified: python/branches/py3k/Python/import.c ============================================================================== --- python/branches/py3k/Python/import.c (original) +++ python/branches/py3k/Python/import.c Tue Mar 31 00:01:35 2009 @@ -3040,15 +3040,20 @@ PyObject *fob = NULL; PyObject *m; FILE *fp; - if (!PyArg_ParseTuple(args, "ss|O:load_compiled", - &name, &pathname, &fob)) + if (!PyArg_ParseTuple(args, "ses|O:load_compiled", + &name, + Py_FileSystemDefaultEncoding, &pathname, + &fob)) return NULL; fp = get_file(pathname, fob, "rb"); - if (fp == NULL) + if (fp == NULL) { + PyMem_Free(pathname); return NULL; + } m = load_compiled_module(name, pathname, fp); if (fob == NULL) fclose(fp); + PyMem_Free(pathname); return m; } @@ -3062,15 +3067,20 @@ PyObject *fob = NULL; PyObject *m; FILE *fp = NULL; - if (!PyArg_ParseTuple(args, "ss|O:load_dynamic", - &name, &pathname, &fob)) + if (!PyArg_ParseTuple(args, "ses|O:load_dynamic", + &name, + Py_FileSystemDefaultEncoding, &pathname, + &fob)) return NULL; if (fob) { fp = get_file(pathname, fob, "r"); - if (fp == NULL) + if (fp == NULL) { + PyMem_Free(pathname); return NULL; + } } m = _PyImport_LoadDynamicModule(name, pathname, fp); + PyMem_Free(pathname); return m; } @@ -3084,12 +3094,16 @@ PyObject *fob = NULL; PyObject *m; FILE *fp; - if (!PyArg_ParseTuple(args, "ss|O:load_source", - &name, &pathname, &fob)) + if (!PyArg_ParseTuple(args, "ses|O:load_source", + &name, + Py_FileSystemDefaultEncoding, &pathname, + &fob)) return NULL; fp = get_file(pathname, fob, "r"); - if (fp == NULL) + if (fp == NULL) { + PyMem_Free(pathname); return NULL; + } m = load_source_module(name, pathname, fp); if (fob == NULL) fclose(fp); @@ -3102,13 +3116,15 @@ char *name; PyObject *fob; char *pathname; + PyObject * ret; char *suffix; /* Unused */ char *mode; int type; FILE *fp; - if (!PyArg_ParseTuple(args, "sOs(ssi):load_module", - &name, &fob, &pathname, + if (!PyArg_ParseTuple(args, "sOes(ssi):load_module", + &name, &fob, + Py_FileSystemDefaultEncoding, &pathname, &suffix, &mode, &type)) return NULL; if (*mode) { @@ -3119,6 +3135,7 @@ if (!(*mode == 'r' || *mode == 'U') || strchr(mode, '+')) { PyErr_Format(PyExc_ValueError, "invalid file open mode %.200s", mode); + PyMem_Free(pathname); return NULL; } } @@ -3126,10 +3143,14 @@ fp = NULL; else { fp = get_file(NULL, fob, mode); - if (fp == NULL) + if (fp == NULL) { + PyMem_Free(pathname); return NULL; - } - return load_module(name, fp, pathname, type, NULL); + } + } + ret = load_module(name, fp, pathname, type, NULL); + PyMem_Free(pathname); + return ret; } static PyObject * @@ -3137,9 +3158,13 @@ { char *name; char *pathname; - if (!PyArg_ParseTuple(args, "ss:load_package", &name, &pathname)) + PyObject * ret; + if (!PyArg_ParseTuple(args, "ses:load_package", + &name, Py_FileSystemDefaultEncoding, &pathname)) return NULL; - return load_package(name, pathname); + ret = load_package(name, pathname); + PyMem_Free(pathname); + return ret; } static PyObject * From python-checkins at python.org Tue Mar 31 00:04:50 2009 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 31 Mar 2009 00:04:50 +0200 (CEST) Subject: [Python-checkins] r70763 - python/branches/release30-maint Message-ID: <20090330220450.0662F1E4002@bag.python.org> Author: guido.van.rossum Date: Tue Mar 31 00:04:49 2009 New Revision: 70763 Log: Blocked revisions 70762 via svnmerge ........ r70762 | guido.van.rossum | 2009-03-30 17:01:35 -0500 (Mon, 30 Mar 2009) | 8 lines Issue #5604: non-ASCII characters in module name passed to imp.find_module() were converted to UTF-8 while the path is converted to the default filesystem encoding, causing nonsense. Thanks to Andrew Svetlov. (This time to the right branch. Will block duplicate merge to 3.0.2.) ........ Modified: python/branches/release30-maint/ (props changed) From python-checkins at python.org Tue Mar 31 00:06:35 2009 From: python-checkins at python.org (martin.v.loewis) Date: Tue, 31 Mar 2009 00:06:35 +0200 (CEST) Subject: [Python-checkins] r70764 - python/trunk/Misc/developers.txt Message-ID: <20090330220635.2ED461E4002@bag.python.org> Author: martin.v.loewis Date: Tue Mar 31 00:06:33 2009 New Revision: 70764 Log: Add several VM developers. Modified: python/trunk/Misc/developers.txt Modified: python/trunk/Misc/developers.txt ============================================================================== --- python/trunk/Misc/developers.txt (original) +++ python/trunk/Misc/developers.txt Tue Mar 31 00:06:33 2009 @@ -17,6 +17,11 @@ Permissions History ------------------- +- Several developers of alternative Python implementations where + given access for test suite and library adaptions by MvL: + Allison Randal (Parrot), Michael Foord (IronPython), + Jim Baker, Philip Jenvey, and Frank Wierzbicki (all Jython). + - R. David Murray was given SVN access on March 30 2009 by MvL, after recommendation by BAC. From python-checkins at python.org Tue Mar 31 00:09:34 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 00:09:34 +0200 (CEST) Subject: [Python-checkins] r70765 - python/trunk/Doc/library/functions.rst Message-ID: <20090330220934.EFEE31E400C@bag.python.org> Author: georg.brandl Date: Tue Mar 31 00:09:34 2009 New Revision: 70765 Log: #5199: make warning about vars() assignment more visible. Modified: python/trunk/Doc/library/functions.rst Modified: python/trunk/Doc/library/functions.rst ============================================================================== --- python/trunk/Doc/library/functions.rst (original) +++ python/trunk/Doc/library/functions.rst Tue Mar 31 00:09:34 2009 @@ -1352,8 +1352,12 @@ Without arguments, return a dictionary corresponding to the current local symbol table. With a module, class or class instance object as argument (or anything else that has a :attr:`__dict__` attribute), returns a dictionary corresponding - to the object's symbol table. The returned dictionary should not be modified: - the effects on the corresponding symbol table are undefined. [#]_ + to the object's symbol table. + + .. warning:: + + The returned dictionary should not be modified: + the effects on the corresponding symbol table are undefined. [#]_ .. function:: xrange([start,] stop[, step]) From python-checkins at python.org Tue Mar 31 00:22:43 2009 From: python-checkins at python.org (eric.smith) Date: Tue, 31 Mar 2009 00:22:43 +0200 (CEST) Subject: [Python-checkins] r70766 - python/branches/py3k-short-float-repr/Modules/_pickle.c Message-ID: <20090330222243.868E71E4002@bag.python.org> Author: eric.smith Date: Tue Mar 31 00:22:43 2009 New Revision: 70766 Log: Hooked _pickle up to new float formatter. Modified: python/branches/py3k-short-float-repr/Modules/_pickle.c Modified: python/branches/py3k-short-float-repr/Modules/_pickle.c ============================================================================== --- python/branches/py3k-short-float-repr/Modules/_pickle.c (original) +++ python/branches/py3k-short-float-repr/Modules/_pickle.c Tue Mar 31 00:22:43 2009 @@ -1018,14 +1018,27 @@ return -1; } else { - char pdata[250]; - pdata[0] = FLOAT; - PyOS_ascii_formatd(pdata + 1, sizeof(pdata) - 2, "%.17g", x); - /* Extend the formatted string with a newline character */ - strcat(pdata, "\n"); + int result = -1; + char *buf = NULL; + char op = FLOAT; - if (pickler_write(self, pdata, strlen(pdata)) < 0) - return -1; + if (pickler_write(self, &op, 1) < 0) + goto done; + + buf = PyOS_double_to_string(x, 2, 'g', 17, 0, 0); + if (!buf) + goto done; + + if (pickler_write(self, buf, strlen(buf)) < 0) + goto done; + + if (pickler_write(self, "\n", 1) < 0) + goto done; + + result = 0; +done: + PyMem_Free(buf); + return result; } return 0; From python-checkins at python.org Tue Mar 31 00:27:03 2009 From: python-checkins at python.org (eric.smith) Date: Tue, 31 Mar 2009 00:27:03 +0200 (CEST) Subject: [Python-checkins] r70767 - python/branches/py3k-short-float-repr/Modules/_pickle.c Message-ID: <20090330222703.22BC41E4002@bag.python.org> Author: eric.smith Date: Tue Mar 31 00:27:02 2009 New Revision: 70767 Log: Set error if out of memory. Modified: python/branches/py3k-short-float-repr/Modules/_pickle.c Modified: python/branches/py3k-short-float-repr/Modules/_pickle.c ============================================================================== --- python/branches/py3k-short-float-repr/Modules/_pickle.c (original) +++ python/branches/py3k-short-float-repr/Modules/_pickle.c Tue Mar 31 00:27:02 2009 @@ -1026,8 +1026,10 @@ goto done; buf = PyOS_double_to_string(x, 2, 'g', 17, 0, 0); - if (!buf) + if (!buf) { + PyErr_NoMemory(); goto done; + } if (pickler_write(self, buf, strlen(buf)) < 0) goto done; From python-checkins at python.org Tue Mar 31 00:29:15 2009 From: python-checkins at python.org (andrew.kuchling) Date: Tue, 31 Mar 2009 00:29:15 +0200 (CEST) Subject: [Python-checkins] r70768 - python/trunk/Doc/library/json.rst Message-ID: <20090330222915.5D3451E4002@bag.python.org> Author: andrew.kuchling Date: Tue Mar 31 00:29:15 2009 New Revision: 70768 Log: Typo fixes Modified: python/trunk/Doc/library/json.rst Modified: python/trunk/Doc/library/json.rst ============================================================================== --- python/trunk/Doc/library/json.rst (original) +++ python/trunk/Doc/library/json.rst Tue Mar 31 00:29:15 2009 @@ -178,12 +178,12 @@ to a :class:`unicode` object and passed to :func:`loads`. *object_hook* is an optional function that will be called with the result of - any object literal decode (a :class:`dict`). The return value of + any object literal decoded (a :class:`dict`). The return value of *object_hook* will be used instead of the :class:`dict`. This feature can be used to implement custom decoders (e.g. JSON-RPC class hinting). *object_pairs_hook* is an optional function that will be called with the - result of any object literal decode with an ordered list of pairs. The + result of any object literal decoded with an ordered list of pairs. The return value of *object_pairs_hook* will be used instead of the :class:`dict`. This feature can be used to implement custom decoders that rely on the order that the key and value pairs are decoded (for example, From python-checkins at python.org Tue Mar 31 00:29:53 2009 From: python-checkins at python.org (andrew.kuchling) Date: Tue, 31 Mar 2009 00:29:53 +0200 (CEST) Subject: [Python-checkins] r70769 - python/trunk/Doc/whatsnew/2.6.rst Message-ID: <20090330222953.E6D501E4002@bag.python.org> Author: andrew.kuchling Date: Tue Mar 31 00:29:53 2009 New Revision: 70769 Log: Remove comment Modified: python/trunk/Doc/whatsnew/2.6.rst Modified: python/trunk/Doc/whatsnew/2.6.rst ============================================================================== --- python/trunk/Doc/whatsnew/2.6.rst (original) +++ python/trunk/Doc/whatsnew/2.6.rst Tue Mar 31 00:29:53 2009 @@ -84,8 +84,6 @@ .. ======================================================================== .. 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? .. ======================================================================== Python 3.0 From python-checkins at python.org Tue Mar 31 00:30:20 2009 From: python-checkins at python.org (andrew.kuchling) Date: Tue, 31 Mar 2009 00:30:20 +0200 (CEST) Subject: [Python-checkins] r70770 - python/trunk/Doc/whatsnew/2.7.rst Message-ID: <20090330223020.85B9D1E4032@bag.python.org> Author: andrew.kuchling Date: Tue Mar 31 00:30:20 2009 New Revision: 70770 Log: Add several items and placeholders Modified: python/trunk/Doc/whatsnew/2.7.rst Modified: python/trunk/Doc/whatsnew/2.7.rst ============================================================================== --- python/trunk/Doc/whatsnew/2.7.rst (original) +++ python/trunk/Doc/whatsnew/2.7.rst Tue Mar 31 00:30:20 2009 @@ -6,7 +6,8 @@ :Release: |release| :Date: |today| -.. Fix accents on Kristjan Valur Jonsson, Fuerstenau. +.. Fix accents on Kristjan Valur Jonsson, Fuerstenau, Tarek Ziade. +.. OrderedDict .. $Id$ Rules for maintenance: @@ -57,10 +58,18 @@ .. ======================================================================== .. 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? .. ======================================================================== +PEP 372: Adding an ordered dictionary to collections +============================= + +XXX write this + +Several modules will now use :class:`OrderedDict` by default. The +:mod:`ConfigParser` module uses :class:`OrderedDict` for the list +of sections and the options within a section. +The :method:`namedtuple._asdict` method returns an :class:`OrderedDict` +as well. Other Language Changes @@ -86,6 +95,34 @@ (Contributed by Fredrik Johansson and Victor Stinner; :issue:`3439`.) +.. ====================================================================== + + +Optimizations +------------- + +A few performance enhancements have been added: + +* The garbage collector now performs better when many objects are + being allocated without deallocating any. A full garbage collection + pass is only performed when the middle generation has been collected + 10 times and when the number of survivor objects from the middle + generation exceeds 10% of the number of objects in the oldest + generation. The second condition was added to reduce the number + of full garbage collections as the number of objects on the heap grows, + avoiding quadratic performance when allocating very many objects. + (Suggested by Martin von Loewis and implemented by Antoine Pitrou; + :issue:`4074`.) + +* The garbage collector tries to avoid tracking simple containers + which can't be part of a cycle. In Python 2.7, this is now true for + tuples and dicts containing atomic types (such as ints, strings, + etc.). Transitively, a dict containing tuples of atomic types won't + be tracked either. This helps reduce the cost of each + garbage collection by decreasing the number of objects to be + considered and traversed by the collector. + (Contributed by Antoine Pitrou; :issue:`4688`.) + * Integers are now stored internally either in base 2**15 or in base 2**30, the base being determined at build time. Previously, they were always stored in base 2**15. Using base 2**30 gives @@ -93,7 +130,7 @@ benchmark results on 32-bit machines have been mixed. Therefore, the default is to use base 2**30 on 64-bit machines and base 2**15 on 32-bit machines; on Unix, there's a new configure option - --enable-big-digits that can be used to override this default. + :option:`--enable-big-digits` that can be used to override this default. Apart from the performance improvements this change should be invisible to end users, with one exception: for testing and @@ -109,38 +146,12 @@ (Contributed by Mark Dickinson; :issue:`4258`.) - -.. ====================================================================== - - -Optimizations -------------- - -A few performance enhancements have been added: - -* The garbage collector now performs better when many objects are - being allocated without deallocating any. A full garbage collection - pass is only performed when the middle generation has been collected - 10 times and when the number of survivor objects from the middle - generation exceeds 10% of the number of objects in the oldest - generation. The second condition was added to reduce the number - of full garbage collections as the number of objects on the heap grows, - avoiding quadratic performance when allocating very many objects. - (Suggested by Martin von Loewis and implemented by Antoine Pitrou; - :issue:`4074`.) - -* The garbage collector tries to avoid tracking simple containers which - can't be part of a cycle. As of now, this is true for tuples and dicts - containing atomic types (such as ints, strings, etc.). Transitively, a dict - containing tuples of atomic types won't be tracked either. This helps bring - down the individual cost of each garbage collection, since it decreases the - number of objects to be considered and traversed by the collector. - - To help diagnosing this optimization, a new function in the :mod:`gc` - module, :func:`is_tracked`, returns True if a given instance is tracked - by the garbage collector, False otherwise. - (Contributed by Antoine Pitrou; :issue:`4688`.) - +* The division algorithm for long integers has been made faster + by tightening the inner loop, doing shifts instead of multiplications, + and fixing an unnecessary extra iteration. + Various benchmarks show speedups of between 50% and 150% for long + integer divisions and modulo operations. + (Contributed by Mark Dickinson; :issue:`5512`.) .. ====================================================================== @@ -153,14 +164,11 @@ :file:`Misc/NEWS` file in the source tree for a more complete list of changes, or look through the Subversion logs for all the details. -* In Distutils, distutils.sdist.add_defaults now uses package_dir and data_files - to feed MANIFEST. - -* It is not mandatory anymore to store clear text passwords in the +* It is no longer mandatory to store clear-text passwords in the :file:`.pypirc` file when registering and uploading packages to PyPI. As long as the username is present in that file, the :mod:`distutils` package will - prompt for the password if not present. (Added by tarek, with the initial - contribution of Nathan Van Gheem; :issue:`4394`.) + prompt for the password if not present. (Added by Tarek Ziade, + with the initial contribution by Nathan Van Gheem; :issue:`4394`.) * The :mod:`bz2` module's :class:`BZ2File` now supports the context management protocol, so you can write ``with bz2.BZ2File(...) as f: ...``. @@ -200,6 +208,13 @@ Contributed by Raymond Hettinger; :issue:`1696199`. +* In Distutils, :func:`distutils.sdist.add_defaults` now uses + *package_dir* and *data_files* to feed MANIFEST. + +* A new function in the :mod:`gc` module, :func:`is_tracked`, returns + True if a given instance is tracked by the garbage collector, False + otherwise. (Contributed by Antoine Pitrou; :issue:`4688`.) + * The :mod:`gzip` module's :class:`GzipFile` now supports the context management protocol, so you can write ``with gzip.GzipFile(...) as f: ...``. (Contributed by Hagen Fuerstenau; :issue:`3860`.) @@ -208,6 +223,17 @@ an invalid file descriptor. (Implemented by Benjamin Peterson; :issue:`4991`.) +* The :class:`itertools` +* The :mod:`json` module was upgraded to version 2.0.9 of the + simplejson package, which includes a C extension that makes + encoding and decoding faster. + (Contributed by Bob Ippolito; :issue:`4136`.) + + To support the new :class:`OrderedDict` type, :func:`json.load` + now has an optional *object_pairs_hook* parameter that will be called + with any object literal that decodes to a list of pairs. + (Contributed by Raymond Hettinger; :issue:`5381`.) + * The :mod:`pydoc` module now has help for the various symbols that Python uses. You can now do ``help('<<')`` or ``help('@')``, for example. (Contributed by David Laban; :issue:`4739`.) @@ -229,6 +255,13 @@ (Contributed by Gregory P. Smith.) +* The :mod:`unittest` module was enhanced in several ways. + Test cases can raise the :exc:`SkipTest` exception to skip a test. + (:issue:`1034053`.) + It will now use 'x' for expected failures + and 'u' for unexpected successes when run in its verbose mode. + (Contributed by Benjamin Peterson.) + * The :func:`is_zipfile` function in the :mod:`zipfile` module will now accept a file object, in addition to the path names accepted in earlier versions. (Contributed by Gabriel Genellina; :issue:`4756`.) @@ -236,6 +269,11 @@ .. ====================================================================== .. whole new modules get described in subsections here +importlib: Importing Modules +------------------------------ + +XXX write this + ttk: Themed Widgets for Tk -------------------------- @@ -294,6 +332,16 @@ ----------------------------------- +Other Changes and Fixes +======================= + +* The :file:`regrtest.py` script now takes a :option:`--randseed=` + switch that takes an integer that will be used as the random seed + for the :option:`-r` option that executes tests in random order. + The :option:`-r` option also now reports the seed that was used + (Added by Collin Winter.) + + .. ====================================================================== Porting to Python 2.7 From python-checkins at python.org Tue Mar 31 00:31:12 2009 From: python-checkins at python.org (andrew.kuchling) Date: Tue, 31 Mar 2009 00:31:12 +0200 (CEST) Subject: [Python-checkins] r70771 - python/trunk/Doc/library/ttk.rst Message-ID: <20090330223112.081E61E4010@bag.python.org> Author: andrew.kuchling Date: Tue Mar 31 00:31:11 2009 New Revision: 70771 Log: Many edits Modified: python/trunk/Doc/library/ttk.rst Modified: python/trunk/Doc/library/ttk.rst ============================================================================== --- python/trunk/Doc/library/ttk.rst (original) +++ python/trunk/Doc/library/ttk.rst Tue Mar 31 00:31:11 2009 @@ -249,7 +249,7 @@ ttk.Widget ^^^^^^^^^^ -Besides the methods described below, the class :class:`ttk.Widget` supports the +Besides the methods described below, the :class:`ttk.Widget` class supports the :meth:`Tkinter.Widget.cget` and :meth:`Tkinter.Widget.configure` methods. .. class:: Widget @@ -485,7 +485,7 @@ The tab will not be displayed, but the associated window remains managed by the notebook and its configuration remembered. Hidden tabs - may be restored with the add command. + may be restored with the :meth:`add` command. .. method:: identify(x, y) @@ -504,7 +504,7 @@ Inserts a pane at the specified position. - *pos* is either the string end, an integer index, or the name of a + *pos* is either the string "end", an integer index, or the name of a managed child. If *child* is already managed by the notebook, moves it to the specified position. @@ -524,7 +524,7 @@ Query or modify the options of the specific *tab_id*. - If *kw* is not given, returns a dict of the tab option values. If + If *kw* is not given, returns a dictionary of the tab option values. If *option* is specified, returns the value of that *option*. Otherwise, sets the options to the corresponding values. @@ -541,14 +541,14 @@ This will extend the bindings for the toplevel window containing the notebook as follows: - * Control-Tab: selects the tab following the currently selected one - * Shift-Control-Tab: selects the tab preceding the currently selected one + * Control-Tab: selects the tab following the currently selected one. + * Shift-Control-Tab: selects the tab preceding the currently selected one. * Alt-K: where K is the mnemonic (underlined) character of any tab, will select that tab. Multiple notebooks in a single toplevel may be enabled for traversal, including nested notebooks. However, notebook traversal only works - properly if all panes have as master the notebook they are in. + properly if all panes have the notebook they are in as master. Progressbar @@ -581,12 +581,12 @@ +----------+---------------------------------------------------------------+ | value | The current value of the progress bar. In "determinate" mode, | | | this represents the amount of work completed. In | - | | "indeterminate" mode, it is interpreted as modulo maximum; | + | | "indeterminate" mode, it is interpreted as modulo *maximum*; | | | that is, the progress bar completes one "cycle" when its value| - | | increases by maximum. | + | | increases by *maximum*. | +----------+---------------------------------------------------------------+ | variable | A name which is linked to the option value. If specified, the | - | | value of the progressbar is automatically set to the value of | + | | value of the progress bar is automatically set to the value of| | | this name whenever the latter is modified. | +----------+---------------------------------------------------------------+ | phase | Read-only option. The widget periodically increments the value| @@ -603,14 +603,14 @@ .. method:: start([interval]) - Begin autoincrement mode: schedules a recurring timer even that calls + Begin autoincrement mode: schedules a recurring timer event that calls :meth:`Progressbar.step` every *interval* milliseconds. If omitted, *interval* defaults to 50 milliseconds. .. method:: step([amount]) - Increments progressbar's value by *amount*. + Increments the progress bar's value by *amount*. *amount* defaults to 1.0 if omitted. @@ -618,7 +618,7 @@ .. method:: stop() Stop autoincrement mode: cancels any recurring timer event initiated by - :meth:`Progressbar.start` for this progressbar. + :meth:`Progressbar.start` for this progress bar. Separator @@ -627,7 +627,7 @@ The :class:`ttk.Separator` widget displays a horizontal or vertical separator bar. -It has no other method besides the ones inherited from :class:`ttk.Widget`. +It has no other methods besides the ones inherited from :class:`ttk.Widget`. Options @@ -646,18 +646,18 @@ Sizegrip -------- -The :class:`ttk.Sizegrip` widget (also known as grow box) allows the user to +The :class:`ttk.Sizegrip` widget (also known as a grow box) allows the user to resize the containing toplevel window by pressing and dragging the grip. -This widget has no specific options neither specific methods, besides the +This widget has neither specific options nor specific methods, besides the ones inherited from :class:`ttk.Widget`. Platform-specific notes ^^^^^^^^^^^^^^^^^^^^^^^ -* On Mac OSX, toplevel windows automatically include a built-in size grip - by default. Adding a Sizegrip there is harmless, since the built-in +* On MacOS X, toplevel windows automatically include a built-in size grip + by default. Adding a :class:`Sizegrip` is harmless, since the built-in grip will just mask the widget. @@ -665,8 +665,8 @@ ^^^^ * If the containing toplevel's position was specified relative to the right - or bottom of the screen (e.g. ....), the Sizegrip widget will not resize - the window. + or bottom of the screen (e.g. ....), the :class:`Sizegrip` widget will + not resize the window. * This widget supports only "southeast" resizing. @@ -679,16 +679,16 @@ label. The order in which data values are displayed may be controlled by setting -the widget option displaycolumns. The tree widget can also display column +the widget option ``displaycolumns``. The tree widget can also display column headings. Columns may be accessed by number or symbolic names listed in the widget option columns. See `Column Identifiers`_. Each item is identified by an unique name. The widget will generate item IDs if they are not supplied by the caller. There is a distinguished root item, -named {}. The root item itself is not displayed; its children appear at the +named ``{}``. The root item itself is not displayed; its children appear at the top level of the hierarchy. -Each item also has a list of tags, which can be used to associate even bindings +Each item also has a list of tags, which can be used to associate event bindings with individual items and control the appearance of the item. The Treeview widget supports horizontal and vertical scrolling, according to @@ -699,7 +699,7 @@ Options ^^^^^^^ -This widget accepts the following specific option: +This widget accepts the following specific options: +----------------+--------------------------------------------------------+ | option | description | @@ -727,8 +727,8 @@ | | be changed. | | | | | | Note that the application code and tag bindings can set| - | | the selection however they wish, regardless the value | - | | of this option. | + | | the selection however they wish, regardless of the | + | | value of this option. | +----------------+--------------------------------------------------------+ | show | A list containing zero or more of the following values,| | | specifying which elements of the tree to display. | @@ -739,7 +739,7 @@ | | The default is "tree headings", i.e., show all | | | elements. | | | | - | | **Note**: Column #0 always refer to the tree column, | + | | **Note**: Column #0 always refers to the tree column, | | | even if show="tree" is not specified. | +----------------+--------------------------------------------------------+ @@ -859,11 +859,11 @@ .. method:: set_children(item, *newchildren) - Replaces item's child with *newchildren*. + Replaces *item*'s child with *newchildren*. - Children present in item that are not present in *newchildren* are - detached from tree. No items in *newchildren* may be an ancestor of - item. Note that not specifying *newchildren* results in detaching + Children present in *item* that are not present in *newchildren* are + detached from the tree. No items in *newchildren* may be an ancestor of + *item*. Note that not specifying *newchildren* results in detaching *item*'s children. @@ -878,16 +878,16 @@ The valid options/values are: * id - Returns the column name, this is a read-only option. + Returns the column name. This is a read-only option. * anchor: One of the standard Tk anchor values. Specifies how the text in this column should be aligned with respect to the cell. * minwidth: width The minimum width of the column in pixels. The treeview widget will - not make the column any smaller than the specified by this option when + not make the column any smaller than specified by this option when the widget is resized or the user drags a column. * stretch: True/False - Specifies wheter or not the column's width should be adjusted when + Specifies whether the column's width should be adjusted when the widget is resized. * width: width The width of the column in pixels. @@ -913,8 +913,7 @@ .. method:: exists(item) - Returns True if the specified *item* is present in the three, - False otherwise. + Returns True if the specified *item* is present in the tree. .. method:: focus([item=None]) @@ -943,7 +942,7 @@ * command: callback A callback to be invoked when the heading label is pressed. - To configure the tree column heading, call this with column = "#0" + To configure the tree column heading, call this with column = "#0". .. method:: identify(component, x, y) @@ -986,7 +985,7 @@ .. method:: identify_element(x, y) - Returns the element at position x, y. + Returns the element at position *x*, *y*. Availability: Tk 8.6. @@ -998,16 +997,16 @@ .. method:: insert(parent, index[, iid=None[, **kw]]) - Creates a new item and return the item identifier of the newly created + Creates a new item and returns the item identifier of the newly created item. *parent* is the item ID of the parent item, or the empty string to create a new top-level item. *index* is an integer, or the value "end", specifying where in the list of parent's children to insert the new item. If *index* is less than or equal to zero, the new node is inserted at - the beginning, if *index* is greater than or equal to the current number + the beginning; if *index* is greater than or equal to the current number of children, it is inserted at the end. If *iid* is specified, it is used - as the item identifier, *iid* must not already exist in the tree. + as the item identifier; *iid* must not already exist in the tree. Otherwise, a new unique identifier is generated. See `Item Options`_ for the list of available points. @@ -1027,9 +1026,9 @@ Moves *item* to position *index* in *parent*'s list of children. - It is illegal to move an item under one of its descendants. If index is - less than or equal to zero, item is moved to the beginning, if greater - than or equal to the number of children, it is moved to the end. If item + It is illegal to move an item under one of its descendants. If *index* is + less than or equal to zero, *item* is moved to the beginning; if greater + than or equal to the number of children, it is moved to the end. If *item* was detached it is reattached. @@ -1102,7 +1101,7 @@ .. method:: tag_bind(tagname[, sequence=None[, callback=None]]) Bind a callback for the given event *sequence* to the tag *tagname*. - When an event is delivered to an item, the *callbacks* for each of the + When an event is delivered to an item, the callbacks for each of the item's tags option are called. @@ -1120,7 +1119,7 @@ If *item* is specified, returns 1 or 0 depending on whether the specified *item* has the given *tagname*. Otherwise, returns a list of all items - which have the specified tag. + that have the specified tag. Availability: Tk 8.6 @@ -1143,8 +1142,8 @@ Each widget in :mod:`ttk` is assigned a style, which specifies the set of elements making up the widget and how they are arranged, along with dynamic and default settings for element options. By default the style name is the same as -the widget's class name, but it may be overriden by the widget's style -option. If the class name of a widget is unkown, use the method +the widget's class name, but it may be overridden by the widget's style +option. If the class name of a widget is unknown, use the method :meth:`Misc.winfo_class` (somewidget.winfo_class()). .. seealso:: @@ -1160,7 +1159,7 @@ .. method:: configure(style, query_opt=None, **kw) - Query or sets the default value of the specified option(s) in *style*. + Query or set the default value of the specified option(s) in *style*. Each key in *kw* is an option and each value is a string identifying the value for that option. @@ -1186,10 +1185,10 @@ Query or sets dynamic values of the specified option(s) in *style*. - Each key in kw is an option and each value should be a list or a - tuple (usually) containing statespecs grouped in tuples, or list, or - something else of your preference. A statespec is compound of one or more - states and then a value. + Each key in *kw* is an option and each value should be a list or a + tuple (usually) containing statespecs grouped in tuples, lists, or + something else of your preference. A statespec is a compound of one + or more states and then a value. An example:: @@ -1209,13 +1208,11 @@ root.mainloop() - There is a thing to note in this previous short example: - - * The order of the (states, value) sequences for an option does matter, - if the order was changed to [('active', 'blue'), ('pressed', 'red')] in - the foreground option, for example, the style would be a blue - foreground when the widget was in active or pressed states. - + Note that the order of the (states, value) sequences for an + option matters. In the previous example, if you change the + order to ``[('active', 'blue'), ('pressed', 'red')]`` in the + foreground option, for example, you would get a blue foreground + when the widget is in the active or pressed states. .. method:: lookup(style, option[, state=None[, default=None]]) @@ -1237,13 +1234,13 @@ Define the widget layout for given *style*. If *layoutspec* is omitted, return the layout specification for given style. - *layoutspec*, if specified, is expected to be a list, or some other - sequence type (excluding string), where each item should be a tuple and + *layoutspec*, if specified, is expected to be a list or some other + sequence type (excluding strings), where each item should be a tuple and the first item is the layout name and the second item should have the format described described in `Layouts`_. - To understand the format, check this example below (it is not intended - to do anything useful):: + To understand the format, see the following example (it is not + intended to do anything useful):: import ttk import Tkinter @@ -1269,12 +1266,12 @@ .. method:: element_create(elementname, etype, *args, **kw) - Create a new element in the current theme of given *etype* which is + Create a new element in the current theme, of the given *etype* which is expected to be either "image", "from" or "vsapi". The latter is only available in Tk 8.6a for Windows XP and Vista and is not described here. If "image" is used, *args* should contain the default image name followed - by statespec/value pairs (this is the imagespec), *kw* may have the + by statespec/value pairs (this is the imagespec), and *kw* may have the following options: * border=padding @@ -1297,11 +1294,12 @@ Specifies a minimum width for the element. If less than zero, the base image's width is used as a default. - But if "from" is used, then :meth:`element_create` will clone an existing - element. *args* is expected to contain a themename, which is from where + If "from" is used as the value of *etype*, + :meth:`element_create` will clone an existing + element. *args* is expected to contain a themename, from which the element will be cloned, and optionally an element to clone from. If this element to clone from is not specified, an empty element will - be used. *kw* is discarded here. + be used. *kw* is discarded. .. method:: element_names() @@ -1335,7 +1333,7 @@ :meth:`Style.configure`, :meth:`Style.map`, :meth:`Style.layout` and :meth:`Style.element_create` respectively. - As an example, lets change the Combobox for the default theme a bit:: + As an example, let's change the Combobox for the default theme a bit:: import ttk import Tkinter @@ -1368,7 +1366,7 @@ .. method:: theme_use([themename]) - If *themename* is not given, returns the theme in use, otherwise, set + If *themename* is not given, returns the theme in use. Otherwise, sets the current theme to *themename*, refreshes all widgets and emits a <> event. @@ -1376,10 +1374,11 @@ Layouts ^^^^^^^ -A layout can be just None, if takes no options, or a dict of options specifying -how to arrange the element. The layout mechanism uses a simplified -version of the pack geometry manager: given an initial cavity, each element is -allocated a parcel. Valid options/values are: +A layout can be just None, if it takes no options, or a dict of +options specifying how to arrange the element. The layout mechanism +uses a simplified version of the pack geometry manager: given an +initial cavity, each element is allocated a parcel. Valid +options/values are: * side: whichside Specifies which side of the cavity to place the the element; one of From python-checkins at python.org Tue Mar 31 00:42:17 2009 From: python-checkins at python.org (barry.warsaw) Date: Tue, 31 Mar 2009 00:42:17 +0200 (CEST) Subject: [Python-checkins] r70772 - in python/trunk: Doc/library/email.header.rst Lib/email/generator.py Lib/email/test/test_email.py Lib/email/test/test_email_renamed.py Message-ID: <20090330224217.A62241E4002@bag.python.org> Author: barry.warsaw Date: Tue Mar 31 00:42:17 2009 New Revision: 70772 Log: A fix for issue 1974, inspired by the patch from Andi Albrecht (aalbrecht), though with some changes by me. This patch should not be back ported or forward ported. It's a bit too risky for 2.6 and 3.x does things fairly differently. Modified: python/trunk/Doc/library/email.header.rst python/trunk/Lib/email/generator.py python/trunk/Lib/email/test/test_email.py python/trunk/Lib/email/test/test_email_renamed.py Modified: python/trunk/Doc/library/email.header.rst ============================================================================== --- python/trunk/Doc/library/email.header.rst (original) +++ python/trunk/Doc/library/email.header.rst Tue Mar 31 00:42:17 2009 @@ -74,7 +74,8 @@ Optional *continuation_ws* must be :rfc:`2822`\ -compliant folding whitespace, and is usually either a space or a hard tab character. This character will be - prepended to continuation lines. + prepended to continuation lines. *continuation_ws* defaults to a single + space character (" "). Optional *errors* is passed straight through to the :meth:`append` method. Modified: python/trunk/Lib/email/generator.py ============================================================================== --- python/trunk/Lib/email/generator.py (original) +++ python/trunk/Lib/email/generator.py Tue Mar 31 00:42:17 2009 @@ -1,5 +1,4 @@ -# Copyright (C) 2001-2006 Python Software Foundation -# Author: Barry Warsaw +# Copyright (C) 2001-2009 Python Software Foundation # Contact: email-sig at python.org """Classes to generate plain text from a message object tree.""" @@ -156,10 +155,13 @@ # be to not split the string and risk it being too long. print >> self._fp, v else: - # Header's got lots of smarts, so use it. + # Header's got lots of smarts, so use it. Note that this is + # fundamentally broken though because we lose idempotency when + # the header string is continued with tabs. It will now be + # continued with spaces. This was reversedly broken before we + # fixed bug 1974. Either way, we lose. print >> self._fp, Header( - v, maxlinelen=self._maxheaderlen, - header_name=h, continuation_ws='\t').encode() + v, maxlinelen=self._maxheaderlen, header_name=h).encode() # A blank line always separates headers from body print >> self._fp Modified: python/trunk/Lib/email/test/test_email.py ============================================================================== --- python/trunk/Lib/email/test/test_email.py (original) +++ python/trunk/Lib/email/test/test_email.py Tue Mar 31 00:42:17 2009 @@ -1,4 +1,4 @@ -# Copyright (C) 2001-2007 Python Software Foundation +# Copyright (C) 2001-2009 Python Software Foundation # Contact: email-sig at python.org # email package unit tests @@ -251,7 +251,16 @@ msg = self._msgobj('msg_01.txt') fp = openfile('msg_01.txt') try: - text = fp.read() + # BAW 30-Mar-2009 Evil be here. So, the generator is broken with + # respect to long line breaking. It's also not idempotent when a + # header from a parsed message is continued with tabs rather than + # spaces. Before we fixed bug 1974 it was reversedly broken, + # i.e. headers that were continued with spaces got continued with + # tabs. For Python 2.x there's really no good fix and in Python + # 3.x all this stuff is re-written to be right(er). Chris Withers + # convinced me that using space as the default continuation + # character is less bad for more applications. + text = fp.read().replace('\t', ' ') finally: fp.close() eq(text, msg.as_string()) @@ -554,8 +563,8 @@ g.flatten(msg) eq(sfp.getvalue(), """\ Subject: bug demonstration -\t12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 -\tmore text + 12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 + more text test """) @@ -655,7 +664,7 @@ MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Foobar-Spoink-Defrobnit: wasnipoop; giraffes="very-long-necked-animals"; -\tspooge="yummy"; hippos="gargantuan"; marshmallows="gooey" + spooge="yummy"; hippos="gargantuan"; marshmallows="gooey" ''') @@ -671,7 +680,7 @@ eq(sfp.getvalue(), """\ From: test at dom.ain References: <0 at dom.ain> <1 at dom.ain> <2 at dom.ain> <3 at dom.ain> <4 at dom.ain> -\t<5 at dom.ain> <6 at dom.ain> <7 at dom.ain> <8 at dom.ain> <9 at dom.ain> + <5 at dom.ain> <6 at dom.ain> <7 at dom.ain> <8 at dom.ain> <9 at dom.ain> Test""") @@ -749,9 +758,9 @@ msg['To'] = to eq(msg.as_string(0), '''\ To: "Someone Test #A" , , -\t"Someone Test #B" , -\t"Someone Test #C" , -\t"Someone Test #D" + "Someone Test #B" , + "Someone Test #C" , + "Someone Test #D" ''') @@ -794,22 +803,22 @@ \throthgar.la.mastaler.com (tmda-ofmipd) with ESMTP; \tWed, 05 Mar 2003 18:10:18 -0700 Received-2: from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by -\throthgar.la.mastaler.com (tmda-ofmipd) with ESMTP; -\tWed, 05 Mar 2003 18:10:18 -0700 + hrothgar.la.mastaler.com (tmda-ofmipd) with ESMTP; + Wed, 05 Mar 2003 18:10:18 -0700 """) def test_string_headerinst_eq(self): h = '<15975.17901.207240.414604 at sgigritzmann1.mathematik.tu-muenchen.de> (David Bremner\'s message of "Thu, 6 Mar 2003 13:58:21 +0100")' msg = Message() - msg['Received-1'] = Header(h, header_name='Received-1', - continuation_ws='\t') - msg['Received-2'] = h - self.assertEqual(msg.as_string(), """\ -Received-1: <15975.17901.207240.414604 at sgigritzmann1.mathematik.tu-muenchen.de> -\t(David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") -Received-2: <15975.17901.207240.414604 at sgigritzmann1.mathematik.tu-muenchen.de> + msg['Received'] = Header(h, header_name='Received', + continuation_ws='\t') + msg['Received'] = h + self.ndiffAssertEqual(msg.as_string(), """\ +Received: <15975.17901.207240.414604 at sgigritzmann1.mathematik.tu-muenchen.de> \t(David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") +Received: <15975.17901.207240.414604 at sgigritzmann1.mathematik.tu-muenchen.de> + (David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") """) @@ -823,7 +832,7 @@ msg['Face-2'] = Header(t, header_name='Face-2') eq(msg.as_string(), """\ Face-1: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 -\tlocQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp + locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp Face-2: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp @@ -833,11 +842,11 @@ eq = self.ndiffAssertEqual m = '''\ Received: from siimage.com ([172.25.1.3]) by zima.siliconimage.com with Microsoft SMTPSVC(5.0.2195.4905); -\tWed, 16 Oct 2002 07:41:11 -0700''' + Wed, 16 Oct 2002 07:41:11 -0700''' msg = email.message_from_string(m) eq(msg.as_string(), '''\ Received: from siimage.com ([172.25.1.3]) by zima.siliconimage.com with -\tMicrosoft SMTPSVC(5.0.2195.4905); Wed, 16 Oct 2002 07:41:11 -0700 + Microsoft SMTPSVC(5.0.2195.4905); Wed, 16 Oct 2002 07:41:11 -0700 ''') @@ -851,7 +860,7 @@ msg['List'] = Header(h, header_name='List') eq(msg.as_string(), """\ List: List-Unsubscribe: , -\t + List: List-Unsubscribe: , @@ -2979,11 +2988,11 @@ msg = self._msgobj('msg_01.txt') msg.set_param('title', 'This is even more ***fun*** isn\'t it!', charset='us-ascii', language='en') - eq(msg.as_string(), """\ + self.ndiffAssertEqual(msg.as_string(), """\ Return-Path: Delivered-To: bbb at zzz.org Received: by mail.zzz.org (Postfix, from userid 889) -\tid 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Message-ID: <15090.61304.110929.45684 at aaa.zzz.org> @@ -2992,7 +3001,7 @@ Subject: This is a test message Date: Fri, 4 May 2001 14:05:44 -0400 Content-Type: text/plain; charset=us-ascii; -\ttitle*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" + title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" Hi, @@ -3013,7 +3022,7 @@ Return-Path: Delivered-To: bbb at zzz.org Received: by mail.zzz.org (Postfix, from userid 889) -\tid 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Message-ID: <15090.61304.110929.45684 at aaa.zzz.org> @@ -3022,7 +3031,7 @@ Subject: This is a test message Date: Fri, 4 May 2001 14:05:44 -0400 Content-Type: text/plain; charset="us-ascii"; -\ttitle*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" + title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" Hi, Modified: python/trunk/Lib/email/test/test_email_renamed.py ============================================================================== --- python/trunk/Lib/email/test/test_email_renamed.py (original) +++ python/trunk/Lib/email/test/test_email_renamed.py Tue Mar 31 00:42:17 2009 @@ -239,10 +239,19 @@ msg = self._msgobj('msg_01.txt') fp = openfile('msg_01.txt') try: - text = fp.read() + # BAW 30-Mar-2009 Evil be here. So, the generator is broken with + # respect to long line breaking. It's also not idempotent when a + # header from a parsed message is continued with tabs rather than + # spaces. Before we fixed bug 1974 it was reversedly broken, + # i.e. headers that were continued with spaces got continued with + # tabs. For Python 2.x there's really no good fix and in Python + # 3.x all this stuff is re-written to be right(er). Chris Withers + # convinced me that using space as the default continuation + # character is less bad for more applications. + text = fp.read().replace('\t', ' ') finally: fp.close() - eq(text, msg.as_string()) + self.ndiffAssertEqual(text, msg.as_string()) fullrepr = str(msg) lines = fullrepr.split('\n') self.failUnless(lines[0].startswith('From ')) @@ -535,8 +544,8 @@ g.flatten(msg) eq(sfp.getvalue(), """\ Subject: bug demonstration -\t12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 -\tmore text + 12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 + more text test """) @@ -636,7 +645,7 @@ MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Foobar-Spoink-Defrobnit: wasnipoop; giraffes="very-long-necked-animals"; -\tspooge="yummy"; hippos="gargantuan"; marshmallows="gooey" + spooge="yummy"; hippos="gargantuan"; marshmallows="gooey" ''') @@ -652,7 +661,7 @@ eq(sfp.getvalue(), """\ From: test at dom.ain References: <0 at dom.ain> <1 at dom.ain> <2 at dom.ain> <3 at dom.ain> <4 at dom.ain> -\t<5 at dom.ain> <6 at dom.ain> <7 at dom.ain> <8 at dom.ain> <9 at dom.ain> + <5 at dom.ain> <6 at dom.ain> <7 at dom.ain> <8 at dom.ain> <9 at dom.ain> Test""") @@ -730,9 +739,9 @@ msg['To'] = to eq(msg.as_string(0), '''\ To: "Someone Test #A" , , -\t"Someone Test #B" , -\t"Someone Test #C" , -\t"Someone Test #D" + "Someone Test #B" , + "Someone Test #C" , + "Someone Test #D" ''') @@ -770,27 +779,27 @@ msg = Message() msg['Received-1'] = Header(h, continuation_ws='\t') msg['Received-2'] = h - self.assertEqual(msg.as_string(), """\ + self.ndiffAssertEqual(msg.as_string(), """\ Received-1: from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by \throthgar.la.mastaler.com (tmda-ofmipd) with ESMTP; \tWed, 05 Mar 2003 18:10:18 -0700 Received-2: from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by -\throthgar.la.mastaler.com (tmda-ofmipd) with ESMTP; -\tWed, 05 Mar 2003 18:10:18 -0700 + hrothgar.la.mastaler.com (tmda-ofmipd) with ESMTP; + Wed, 05 Mar 2003 18:10:18 -0700 """) def test_string_headerinst_eq(self): h = '<15975.17901.207240.414604 at sgigritzmann1.mathematik.tu-muenchen.de> (David Bremner\'s message of "Thu, 6 Mar 2003 13:58:21 +0100")' msg = Message() - msg['Received-1'] = Header(h, header_name='Received-1', - continuation_ws='\t') - msg['Received-2'] = h - self.assertEqual(msg.as_string(), """\ -Received-1: <15975.17901.207240.414604 at sgigritzmann1.mathematik.tu-muenchen.de> -\t(David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") -Received-2: <15975.17901.207240.414604 at sgigritzmann1.mathematik.tu-muenchen.de> + msg['Received'] = Header(h, header_name='Received-1', + continuation_ws='\t') + msg['Received'] = h + self.ndiffAssertEqual(msg.as_string(), """\ +Received: <15975.17901.207240.414604 at sgigritzmann1.mathematik.tu-muenchen.de> \t(David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") +Received: <15975.17901.207240.414604 at sgigritzmann1.mathematik.tu-muenchen.de> + (David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") """) @@ -804,7 +813,7 @@ msg['Face-2'] = Header(t, header_name='Face-2') eq(msg.as_string(), """\ Face-1: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 -\tlocQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp + locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp Face-2: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp @@ -814,11 +823,11 @@ eq = self.ndiffAssertEqual m = '''\ Received: from siimage.com ([172.25.1.3]) by zima.siliconimage.com with Microsoft SMTPSVC(5.0.2195.4905); -\tWed, 16 Oct 2002 07:41:11 -0700''' + Wed, 16 Oct 2002 07:41:11 -0700''' msg = email.message_from_string(m) eq(msg.as_string(), '''\ Received: from siimage.com ([172.25.1.3]) by zima.siliconimage.com with -\tMicrosoft SMTPSVC(5.0.2195.4905); Wed, 16 Oct 2002 07:41:11 -0700 + Microsoft SMTPSVC(5.0.2195.4905); Wed, 16 Oct 2002 07:41:11 -0700 ''') @@ -830,9 +839,9 @@ msg = Message() msg['List'] = h msg['List'] = Header(h, header_name='List') - eq(msg.as_string(), """\ + self.ndiffAssertEqual(msg.as_string(), """\ List: List-Unsubscribe: , -\t + List: List-Unsubscribe: , @@ -2974,11 +2983,11 @@ msg = self._msgobj('msg_01.txt') msg.set_param('title', 'This is even more ***fun*** isn\'t it!', charset='us-ascii', language='en') - eq(msg.as_string(), """\ + self.ndiffAssertEqual(msg.as_string(), """\ Return-Path: Delivered-To: bbb at zzz.org Received: by mail.zzz.org (Postfix, from userid 889) -\tid 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Message-ID: <15090.61304.110929.45684 at aaa.zzz.org> @@ -2987,7 +2996,7 @@ Subject: This is a test message Date: Fri, 4 May 2001 14:05:44 -0400 Content-Type: text/plain; charset=us-ascii; -\ttitle*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" + title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" Hi, @@ -3008,7 +3017,7 @@ Return-Path: Delivered-To: bbb at zzz.org Received: by mail.zzz.org (Postfix, from userid 889) -\tid 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) + id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Message-ID: <15090.61304.110929.45684 at aaa.zzz.org> @@ -3017,7 +3026,7 @@ Subject: This is a test message Date: Fri, 4 May 2001 14:05:44 -0400 Content-Type: text/plain; charset="us-ascii"; -\ttitle*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" + title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" Hi, From python-checkins at python.org Tue Mar 31 00:43:00 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 00:43:00 +0200 (CEST) Subject: [Python-checkins] r70773 - python/trunk/Doc/reference/datamodel.rst Message-ID: <20090330224300.E2C891E4002@bag.python.org> Author: georg.brandl Date: Tue Mar 31 00:43:00 2009 New Revision: 70773 Log: #5039: make it clear that the impl. note refers to CPython. Modified: python/trunk/Doc/reference/datamodel.rst Modified: python/trunk/Doc/reference/datamodel.rst ============================================================================== --- python/trunk/Doc/reference/datamodel.rst (original) +++ python/trunk/Doc/reference/datamodel.rst Tue Mar 31 00:43:00 2009 @@ -56,12 +56,13 @@ they may be garbage-collected. An implementation is allowed to postpone garbage collection or omit it altogether --- it is a matter of implementation quality how garbage collection is implemented, as long as no objects are collected that -are still reachable. (Implementation note: the current implementation uses a +are still reachable. (Implementation note: CPython currently uses a reference-counting scheme with (optional) delayed detection of cyclically linked garbage, which collects most objects as soon as they become unreachable, but is not guaranteed to collect garbage containing circular references. See the documentation of the :mod:`gc` module for information on controlling the -collection of cyclic garbage.) +collection of cyclic garbage. Other implementations act differently and CPython +may change.) Note that the use of the implementation's tracing or debugging facilities may keep objects alive that would normally be collectable. Also note that catching From buildbot at python.org Tue Mar 31 00:55:57 2009 From: buildbot at python.org (buildbot at python.org) Date: Mon, 30 Mar 2009 22:55:57 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090330225557.79C451E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/546 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon,ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 00:59:27 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 00:59:27 +0200 (CEST) Subject: [Python-checkins] r70774 - in python/branches/py3k: Lib/test/test_multiprocessing.py Message-ID: <20090330225927.936C81E400C@bag.python.org> Author: jesse.noller Date: Tue Mar 31 00:59:27 2009 New Revision: 70774 Log: finalize the queue to resolve test issue Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_multiprocessing.py Modified: python/branches/py3k/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/py3k/Lib/test/test_multiprocessing.py (original) +++ python/branches/py3k/Lib/test/test_multiprocessing.py Tue Mar 31 00:59:27 2009 @@ -1209,10 +1209,12 @@ p.start() queue = manager.get_queue() self.assertEqual(queue.get(), 'hello world') + del queue manager.shutdown() manager = QueueManager( address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) manager.start() + manager.shutdown() # # From python-checkins at python.org Tue Mar 31 01:05:50 2009 From: python-checkins at python.org (r.david.murray) Date: Tue, 31 Mar 2009 01:05:50 +0200 (CEST) Subject: [Python-checkins] r70775 - in python/trunk/Lib/test: test_bsddb3.py test_bz2.py test_ctypes.py test_curses.py test_dbm.py test_fork1.py test_gdbm.py test_ioctl.py test_multiprocessing.py test_nis.py test_ossaudiodev.py test_resource.py test_sqlite.py test_startfile.py test_support.py test_xml_etree_c.py test_zlib.py Message-ID: <20090330230550.4F0E01E400C@bag.python.org> Author: r.david.murray Date: Tue Mar 31 01:05:48 2009 New Revision: 70775 Log: Change more tests to use import_module for the modules that should cause tests to be skipped. Also rename import_function to the more descriptive get_attribute and add a docstring. Modified: python/trunk/Lib/test/test_bsddb3.py python/trunk/Lib/test/test_bz2.py python/trunk/Lib/test/test_ctypes.py python/trunk/Lib/test/test_curses.py python/trunk/Lib/test/test_dbm.py python/trunk/Lib/test/test_fork1.py python/trunk/Lib/test/test_gdbm.py python/trunk/Lib/test/test_ioctl.py python/trunk/Lib/test/test_multiprocessing.py python/trunk/Lib/test/test_nis.py python/trunk/Lib/test/test_ossaudiodev.py python/trunk/Lib/test/test_resource.py python/trunk/Lib/test/test_sqlite.py python/trunk/Lib/test/test_startfile.py python/trunk/Lib/test/test_support.py python/trunk/Lib/test/test_xml_etree_c.py python/trunk/Lib/test/test_zlib.py Modified: python/trunk/Lib/test/test_bsddb3.py ============================================================================== --- python/trunk/Lib/test/test_bsddb3.py (original) +++ python/trunk/Lib/test/test_bsddb3.py Tue Mar 31 01:05:48 2009 @@ -7,7 +7,11 @@ import tempfile import time import unittest -from test.test_support import requires, verbose, run_unittest, unlink, rmtree +from test.test_support import (requires, verbose, run_unittest, unlink, rmtree, + import_module) + +#Skip test if bsddb cannot import _bsddb. +import_module('bsddb') # When running as a script instead of within the regrtest framework, skip the # requires test, since it's obvious we want to run them. Modified: python/trunk/Lib/test/test_bz2.py ============================================================================== --- python/trunk/Lib/test/test_bz2.py (original) +++ python/trunk/Lib/test/test_bz2.py Tue Mar 31 01:05:48 2009 @@ -1,6 +1,6 @@ #!/usr/bin/python from test import test_support -from test.test_support import TESTFN +from test.test_support import TESTFN, import_module import unittest from cStringIO import StringIO @@ -8,7 +8,7 @@ import subprocess import sys -import bz2 +bz2 = import_module('bz2') from bz2 import BZ2File, BZ2Compressor, BZ2Decompressor has_cmdline_bunzip2 = sys.platform not in ("win32", "os2emx", "riscos") Modified: python/trunk/Lib/test/test_ctypes.py ============================================================================== --- python/trunk/Lib/test/test_ctypes.py (original) +++ python/trunk/Lib/test/test_ctypes.py Tue Mar 31 01:05:48 2009 @@ -1,6 +1,9 @@ import unittest -from test.test_support import run_unittest +from test.test_support import run_unittest, import_module +#Skip tests if _ctypes module does not exist +import_module('_ctypes') + import ctypes.test def test_main(): Modified: python/trunk/Lib/test/test_curses.py ============================================================================== --- python/trunk/Lib/test/test_curses.py (original) +++ python/trunk/Lib/test/test_curses.py Tue Mar 31 01:05:48 2009 @@ -9,15 +9,16 @@ # Only called, not tested: getmouse(), ungetmouse() # -import curses, sys, tempfile, os -import curses.panel +import sys, tempfile, os # Optionally test curses module. This currently requires that the # 'curses' resource be given on the regrtest command line using the -u # option. If not available, nothing after this line will be executed. -from test.test_support import requires +from test.test_support import requires, import_module requires('curses') +curses = import_module('curses') +curses.panel = import_module('curses.panel') # XXX: if newterm was supported we could use it instead of initscr and not exit term = os.environ.get('TERM') Modified: python/trunk/Lib/test/test_dbm.py ============================================================================== --- python/trunk/Lib/test/test_dbm.py (original) +++ python/trunk/Lib/test/test_dbm.py Tue Mar 31 01:05:48 2009 @@ -1,6 +1,6 @@ from test import test_support import unittest -import dbm +dbm = test_support.import_module('dbm') class DbmTestCase(unittest.TestCase): Modified: python/trunk/Lib/test/test_fork1.py ============================================================================== --- python/trunk/Lib/test/test_fork1.py (original) +++ python/trunk/Lib/test/test_fork1.py Tue Mar 31 01:05:48 2009 @@ -4,10 +4,10 @@ import os import time from test.fork_wait import ForkWait -from test.test_support import run_unittest, reap_children, import_function +from test.test_support import run_unittest, reap_children, get_attribute #Skip test if fork does not exist. -import_function(os, 'fork') +get_attribute(os, 'fork') class ForkTest(ForkWait): Modified: python/trunk/Lib/test/test_gdbm.py ============================================================================== --- python/trunk/Lib/test/test_gdbm.py (original) +++ python/trunk/Lib/test/test_gdbm.py Tue Mar 31 01:05:48 2009 @@ -1,7 +1,8 @@ -import gdbm import unittest import os -from test.test_support import verbose, TESTFN, run_unittest, unlink +from test.test_support import (verbose, TESTFN, run_unittest, unlink, + import_module) +gdbm = import_module('gdbm') filename = TESTFN Modified: python/trunk/Lib/test/test_ioctl.py ============================================================================== --- python/trunk/Lib/test/test_ioctl.py (original) +++ python/trunk/Lib/test/test_ioctl.py Tue Mar 31 01:05:48 2009 @@ -1,12 +1,9 @@ import unittest -from test.test_support import run_unittest +from test.test_support import run_unittest, import_module, get_attribute import os, struct -try: - import fcntl, termios -except ImportError: - raise unittest.SkipTest("No fcntl or termios module") -if not hasattr(termios,'TIOCGPGRP'): - raise unittest.SkipTest("termios module doesn't have TIOCGPGRP") +fcntl = import_module('fcntl') +termios = import_module('termios') +get_attribute(termios, 'TIOCGPGRP') #Can't run tests without this feature try: tty = open("/dev/tty", "r") Modified: python/trunk/Lib/test/test_multiprocessing.py ============================================================================== --- python/trunk/Lib/test/test_multiprocessing.py (original) +++ python/trunk/Lib/test/test_multiprocessing.py Tue Mar 31 01:05:48 2009 @@ -17,20 +17,19 @@ import socket import random import logging +import test_support +_multiprocessing = test_support.import_module('_multiprocessing') + # Work around broken sem_open implementations -try: - import multiprocessing.synchronize -except ImportError, e: - raise unittest.SkipTest(e) +test_support.import_module('multiprocessing.synchronize') import multiprocessing.dummy import multiprocessing.connection import multiprocessing.managers import multiprocessing.heap import multiprocessing.pool -import _multiprocessing from multiprocessing import util Modified: python/trunk/Lib/test/test_nis.py ============================================================================== --- python/trunk/Lib/test/test_nis.py (original) +++ python/trunk/Lib/test/test_nis.py Tue Mar 31 01:05:48 2009 @@ -1,6 +1,7 @@ from test import test_support import unittest -import nis + +nis = test_support.import_module('nis') class NisTests(unittest.TestCase): def test_maps(self): Modified: python/trunk/Lib/test/test_ossaudiodev.py ============================================================================== --- python/trunk/Lib/test/test_ossaudiodev.py (original) +++ python/trunk/Lib/test/test_ossaudiodev.py Tue Mar 31 01:05:48 2009 @@ -3,8 +3,9 @@ from test.test_support import findfile +ossaudiodev = test_support.import_module('ossaudiodev') + import errno -import ossaudiodev import sys import sunau import time Modified: python/trunk/Lib/test/test_resource.py ============================================================================== --- python/trunk/Lib/test/test_resource.py (original) +++ python/trunk/Lib/test/test_resource.py Tue Mar 31 01:05:48 2009 @@ -1,9 +1,9 @@ import unittest from test import test_support - -import resource import time +resource = test_support.import_module('resource') + # This test is checking a few specific problem spots with the resource module. class ResourceTest(unittest.TestCase): Modified: python/trunk/Lib/test/test_sqlite.py ============================================================================== --- python/trunk/Lib/test/test_sqlite.py (original) +++ python/trunk/Lib/test/test_sqlite.py Tue Mar 31 01:05:48 2009 @@ -1,10 +1,9 @@ import unittest -from test.test_support import run_unittest +from test.test_support import run_unittest, import_module + +#Skip test of _sqlite3 module not installed +import_module('_sqlite3') -try: - import _sqlite3 -except ImportError: - raise unittest.SkipTest('no sqlite available') from sqlite3.test import (dbapi, types, userfunctions, py25tests, factory, transactions, hooks, regression, dump) Modified: python/trunk/Lib/test/test_startfile.py ============================================================================== --- python/trunk/Lib/test/test_startfile.py (original) +++ python/trunk/Lib/test/test_startfile.py Tue Mar 31 01:05:48 2009 @@ -12,7 +12,7 @@ import os from os import path -startfile = test_support.import_function(os, 'startfile') +startfile = test_support.get_attribute(os, 'startfile') class TestCase(unittest.TestCase): Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Tue Mar 31 01:05:48 2009 @@ -12,6 +12,7 @@ import shutil import warnings import unittest +import importlib __all__ = ["Error", "TestFailed", "ResourceDenied", "import_module", "verbose", "use_resources", "max_memuse", "record_original_stdout", @@ -25,7 +26,7 @@ "run_with_locale", "set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner", "run_unittest", "run_doctest", "threading_setup", "threading_cleanup", "reap_children", "cpython_only", - "check_impl_detail"] + "check_impl_detail", "get_attribute"] class Error(Exception): """Base class for regression test exceptions.""" @@ -49,24 +50,26 @@ warnings.filterwarnings("ignore", ".+ (module|package)", DeprecationWarning) try: - module = __import__(name, level=0) + module = importlib.import_module(name) except ImportError: raise unittest.SkipTest("No module named " + name) else: return module -def import_function(module, name, deprecated=False): +def get_attribute(module, name, deprecated=False): + """Get an attribute from the module, raising SkipTest if it is + not available.""" with warnings.catch_warnings(): if deprecated: warnings.filterwarnings("ignore", ".+ (module|package)", DeprecationWarning) try: - function = getattr(module, name) + attribute = getattr(module, name) except AttributeError: - raise unittest.SkipTest("No function named %s in module %s" % ( - name, module.__name__)) + raise unittest.SkipTest("module %s has no attribute %s" % ( + module.__name__, name)) else: - return function + return attribute verbose = 1 # Flag set to 0 by regrtest.py Modified: python/trunk/Lib/test/test_xml_etree_c.py ============================================================================== --- python/trunk/Lib/test/test_xml_etree_c.py (original) +++ python/trunk/Lib/test/test_xml_etree_c.py Tue Mar 31 01:05:48 2009 @@ -5,7 +5,7 @@ from test import test_support -from xml.etree import cElementTree as ET +ET = test_support.import_module('xml.etree.cElementTree') SAMPLE_XML = """ Modified: python/trunk/Lib/test/test_zlib.py ============================================================================== --- python/trunk/Lib/test/test_zlib.py (original) +++ python/trunk/Lib/test/test_zlib.py Tue Mar 31 01:05:48 2009 @@ -1,9 +1,10 @@ import unittest from test import test_support -import zlib import binascii import random +zlib = test_support.import_module('zlib') + class ChecksumTestCase(unittest.TestCase): # checksum test cases From python-checkins at python.org Tue Mar 31 01:08:25 2009 From: python-checkins at python.org (andrew.kuchling) Date: Tue, 31 Mar 2009 01:08:25 +0200 (CEST) Subject: [Python-checkins] r70776 - python/trunk/Doc/library/itertools.rst Message-ID: <20090330230825.4998B1E4002@bag.python.org> Author: andrew.kuchling Date: Tue Mar 31 01:08:24 2009 New Revision: 70776 Log: typo fix Modified: python/trunk/Doc/library/itertools.rst Modified: python/trunk/Doc/library/itertools.rst ============================================================================== --- python/trunk/Doc/library/itertools.rst (original) +++ python/trunk/Doc/library/itertools.rst Tue Mar 31 01:08:24 2009 @@ -216,7 +216,7 @@ Make an iterator that filters elements from *data* returning only those that have a corresponding element in *selectors* that evaluates to ``True``. - Stops when either the *data* or *selectors* iterables have been exhausted. + Stops when either the *data* or *selectors* iterables has been exhausted. Equivalent to:: def compress(data, selectors): From python-checkins at python.org Tue Mar 31 01:09:46 2009 From: python-checkins at python.org (andrew.kuchling) Date: Tue, 31 Mar 2009 01:09:46 +0200 (CEST) Subject: [Python-checkins] r70777 - python/trunk/Doc/whatsnew/2.7.rst Message-ID: <20090330230946.C7E581E4002@bag.python.org> Author: andrew.kuchling Date: Tue Mar 31 01:09:46 2009 New Revision: 70777 Log: Add more items Modified: python/trunk/Doc/whatsnew/2.7.rst Modified: python/trunk/Doc/whatsnew/2.7.rst ============================================================================== --- python/trunk/Doc/whatsnew/2.7.rst (original) +++ python/trunk/Doc/whatsnew/2.7.rst Tue Mar 31 01:09:46 2009 @@ -56,19 +56,31 @@ .. Compare with previous release in 2 - 3 sentences here. add hyperlink when the documentation becomes available online. +Python 3.1 +================ + +Much as Python 2.6 incorporated features from Python 3.0, +version 2.7 is influenced by features from 3.1. + +XXX mention importlib; anything else? + +One porting change: the :option:`-3` switch now automatically +enables the :option:`-Qwarn` switch that causes warnings +about using classic division with integers and long integers. + .. ======================================================================== .. Large, PEP-level features and changes should be described here. .. ======================================================================== PEP 372: Adding an ordered dictionary to collections -============================= +==================================================== XXX write this Several modules will now use :class:`OrderedDict` by default. The :mod:`ConfigParser` module uses :class:`OrderedDict` for the list of sections and the options within a section. -The :method:`namedtuple._asdict` method returns an :class:`OrderedDict` +The :meth:`namedtuple._asdict` method returns an :class:`OrderedDict` as well. @@ -143,9 +155,12 @@ >>> sys.long_info sys.long_info(bits_per_digit=30, sizeof_digit=4) - (Contributed by Mark Dickinson; :issue:`4258`.) + Another set of changes made long objects a few bytes smaller: 2 bytes + smaller on 32-bit systems and 6 bytes on 64-bit. (: + (Contributed by Mark Dickinson; :issue:`5260`.) + * The division algorithm for long integers has been made faster by tightening the inner loop, doing shifts instead of multiplications, and fixing an unnecessary extra iteration. @@ -223,7 +238,31 @@ an invalid file descriptor. (Implemented by Benjamin Peterson; :issue:`4991`.) -* The :class:`itertools` +* New function: ``itertools.compress(*data*, *selectors*)`` takes two + iterators. Elements of *data* are returned if the corresponding + value in *selectors* is True:: + + itertools.compress('ABCDEF', [1,0,1,0,1,1]) => + A, C, E, F + + New function: ``itertools.combinations_with_replacement(*iter*, *r*)`` + returns all the possible *r*-length combinations of elements from the + iterable *iter*. Unlike :func:`combinations`, individual elements + can be repeated in the generated combinations:: + + itertools.combinations_with_replacement('abc', 2) => + ('a', 'a'), ('a', 'b'), ('a', 'c'), + ('b', 'b'), ('b', 'c'), ('c', 'c') + + Note that elements are treated as unique depending on their position + in the input, not their actual values. + + The :class:`itertools.count` function now has a *step* argument that + allows incrementing by values other than 1. :func:`count` also + now allows keyword arguments, and using non-integer values such as + floats or :class:`Decimal` instances. (Implemented by Raymond + Hettinger; :issue:`5032`.) + * The :mod:`json` module was upgraded to version 2.0.9 of the simplejson package, which includes a C extension that makes encoding and decoding faster. @@ -266,6 +305,9 @@ accept a file object, in addition to the path names accepted in earlier versions. (Contributed by Gabriel Genellina; :issue:`4756`.) + :mod:`zipfile` now supports archiving empty directories and + extracts them correctly. (Fixed by Kuba Wieczorek; :issue:`4710`.) + .. ====================================================================== .. whole new modules get described in subsections here From python-checkins at python.org Tue Mar 31 01:10:35 2009 From: python-checkins at python.org (ronald.oussoren) Date: Tue, 31 Mar 2009 01:10:35 +0200 (CEST) Subject: [Python-checkins] r70778 - in python/trunk: Lib/site.py Misc/NEWS Message-ID: <20090330231035.B40641E4002@bag.python.org> Author: ronald.oussoren Date: Tue Mar 31 01:10:35 2009 New Revision: 70778 Log: Fix issue #4865: add /Library/Python/2.7/site-packages to sys.path on OSX, to make it easier to share (some) installed packages between the system install and a user install. Modified: python/trunk/Lib/site.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/site.py ============================================================================== --- python/trunk/Lib/site.py (original) +++ python/trunk/Lib/site.py Tue Mar 31 01:10:35 2009 @@ -275,13 +275,15 @@ if sys.platform == "darwin": # for framework builds *only* we add the standard Apple - # locations. Currently only per-user, but /Library and - # /Network/Library could be added too + # locations. if 'Python.framework' in prefix: sitedirs.append( os.path.expanduser( os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"))) + sitedirs.append( + os.path.join("/Library", "Python", + sys.version[:3], "site-packages")) for sitedir in sitedirs: if os.path.isdir(sitedir): Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 31 01:10:35 2009 @@ -1,5 +1,4 @@ -+++++++++++ -Python News ++++++++++++ Python News +++++++++++ (editors: check NEWS.help for information about editing NEWS using ReST.) @@ -12,6 +11,9 @@ Core and Builtins ----------------- +- Issue #4865: On MacOSX /Library/Python/2.7/site-packages is added to + the end sys.path, for compatibility with the system install of Python. + - Issue #4688: Add a heuristic so that tuples and dicts containing only untrackable objects are not tracked by the garbage collector. This can reduce the size of collections and therefore the garbage collection overhead From python-checkins at python.org Tue Mar 31 01:10:38 2009 From: python-checkins at python.org (r.david.murray) Date: Tue, 31 Mar 2009 01:10:38 +0200 (CEST) Subject: [Python-checkins] r70779 - python/trunk/Lib/test/test_sundry.py Message-ID: <20090330231038.5578B1E4011@bag.python.org> Author: r.david.murray Date: Tue Mar 31 01:10:37 2009 New Revision: 70779 Log: Actually suppress warnings in test_at_least_import_untested_modules inside the catch_warnings context manager. Modified: python/trunk/Lib/test/test_sundry.py Modified: python/trunk/Lib/test/test_sundry.py ============================================================================== --- python/trunk/Lib/test/test_sundry.py (original) +++ python/trunk/Lib/test/test_sundry.py Tue Mar 31 01:10:37 2009 @@ -9,6 +9,7 @@ class TestUntestedModules(unittest.TestCase): def test_at_least_import_untested_modules(self): with warnings.catch_warnings(): + warnings.simplefilter("ignore") import CGIHTTPServer import aifc import audiodev From python-checkins at python.org Tue Mar 31 01:12:30 2009 From: python-checkins at python.org (barry.warsaw) Date: Tue, 31 Mar 2009 01:12:30 +0200 (CEST) Subject: [Python-checkins] r70780 - in python/branches/py3k: Doc/library/email.header.rst Lib/email/generator.py Lib/email/test/test_email.py Lib/email/test/test_email_codecs.py Lib/email/test/test_email_codecs_renamed.py Message-ID: <20090330231230.CDBDA1E4002@bag.python.org> Author: barry.warsaw Date: Tue Mar 31 01:12:30 2009 New Revision: 70780 Log: "Port" the fix for issue 1974 from the trunk (2.7). Because Python 3.x does things much better, less changes are necessary. This also shoves test_email_codecs_rename.py onto test_email_codecs.py even though the test needs to be ported to Python 3. Added: python/branches/py3k/Lib/email/test/test_email_codecs.py (props changed) - copied unchanged from r70773, /python/branches/py3k/Lib/email/test/test_email_codecs_renamed.py Removed: python/branches/py3k/Lib/email/test/test_email_codecs_renamed.py Modified: python/branches/py3k/Doc/library/email.header.rst python/branches/py3k/Lib/email/generator.py python/branches/py3k/Lib/email/test/test_email.py Modified: python/branches/py3k/Doc/library/email.header.rst ============================================================================== --- python/branches/py3k/Doc/library/email.header.rst (original) +++ python/branches/py3k/Doc/library/email.header.rst Tue Mar 31 01:12:30 2009 @@ -72,7 +72,7 @@ Optional *continuation_ws* must be :rfc:`2822`\ -compliant folding whitespace, and is usually either a space or a hard tab character. This character will be - prepended to continuation lines. + prepended to continuation lines. *continuation_ws* defaults to a single space character (" "). Optional *errors* is passed straight through to the :meth:`append` method. Modified: python/branches/py3k/Lib/email/generator.py ============================================================================== --- python/branches/py3k/Lib/email/generator.py (original) +++ python/branches/py3k/Lib/email/generator.py Tue Mar 31 01:12:30 2009 @@ -138,7 +138,7 @@ else: # Header's got lots of smarts, so use it. header = Header(v, maxlinelen=self._maxheaderlen, - header_name=h, continuation_ws='\t') + header_name=h) print(header.encode(), file=self._fp) # A blank line always separates headers from body print(file=self._fp) Modified: python/branches/py3k/Lib/email/test/test_email.py ============================================================================== --- python/branches/py3k/Lib/email/test/test_email.py (original) +++ python/branches/py3k/Lib/email/test/test_email.py Tue Mar 31 01:12:30 2009 @@ -769,7 +769,7 @@ msg['To'] = to eq(msg.as_string(maxheaderlen=78), '''\ To: "Someone Test #A" ,, -\t"Someone Test #B" , + "Someone Test #B" , "Someone Test #C" , "Someone Test #D" @@ -852,7 +852,7 @@ # snug against the field name. eq(msg.as_string(maxheaderlen=78), """\ Face-1:\x20 -\tiVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 + iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp Face-2:\x20 iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 Deleted: python/branches/py3k/Lib/email/test/test_email_codecs_renamed.py ============================================================================== --- python/branches/py3k/Lib/email/test/test_email_codecs_renamed.py Tue Mar 31 01:12:30 2009 +++ (empty file) @@ -1,77 +0,0 @@ -# Copyright (C) 2002-2006 Python Software Foundation -# Contact: email-sig at python.org -# email package unit tests for (optional) Asian codecs - -import unittest -from test.support import run_unittest - -from email.test.test_email import TestEmailBase -from email.charset import Charset -from email.header import Header, decode_header -from email.message import Message - -# We're compatible with Python 2.3, but it doesn't have the built-in Asian -# codecs, so we have to skip all these tests. -try: - str('foo', 'euc-jp') -except LookupError: - raise unittest.SkipTest - - - -class TestEmailAsianCodecs(TestEmailBase): - def test_japanese_codecs(self): - eq = self.ndiffAssertEqual - j = Charset("euc-jp") - g = Charset("iso-8859-1") - h = Header("Hello World!") - jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa' - ghello = 'Gr\xfc\xdf Gott!' - h.append(jhello, j) - h.append(ghello, g) - # BAW: This used to -- and maybe should -- fold the two iso-8859-1 - # chunks into a single encoded word. However it doesn't violate the - # standard to have them as two encoded chunks and maybe it's - # reasonable for each .append() call to result in a separate - # encoded word. - eq(h.encode(), """\ -Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?= - =?iso-8859-1?q?Gr=FC=DF?= =?iso-8859-1?q?_Gott!?=""") - eq(decode_header(h.encode()), - [('Hello World!', None), - ('\x1b$B%O%m!<%o!<%k%I!*\x1b(B', 'iso-2022-jp'), - ('Gr\xfc\xdf Gott!', 'iso-8859-1')]) - int = 'test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9' - h = Header(int, j, header_name="Subject") - # test a very long header - enc = h.encode() - # TK: splitting point may differ by codec design and/or Header encoding - eq(enc , """\ -=?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYSE8JWskTztKGyhC?= - =?iso-2022-jp?b?GyRCMnE8VCROPjVHJyRyQlQkQyRGJCQkXiQ5GyhC?=""") - # TK: full decode comparison - eq(h.__unicode__().encode('euc-jp'), int) - - def test_payload_encoding(self): - jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa' - jcode = 'euc-jp' - msg = Message() - msg.set_payload(jhello, jcode) - ustr = str(msg.get_payload(), msg.get_content_charset()) - self.assertEqual(jhello, ustr.encode(jcode)) - - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestEmailAsianCodecs)) - return suite - - -def test_main(): - run_unittest(TestEmailAsianCodecs) - - - -if __name__ == '__main__': - unittest.main(defaultTest='suite') From python-checkins at python.org Tue Mar 31 01:16:08 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 31 Mar 2009 01:16:08 +0200 (CEST) Subject: [Python-checkins] r70781 - in python/branches/py3k-short-float-repr: configure configure.in Message-ID: <20090330231608.7CF8E1E4002@bag.python.org> Author: mark.dickinson Date: Tue Mar 31 01:16:07 2009 New Revision: 70781 Log: Use SSE2 instructions in preference to the x87 FPU whenever possible. Modified: python/branches/py3k-short-float-repr/configure python/branches/py3k-short-float-repr/configure.in Modified: python/branches/py3k-short-float-repr/configure ============================================================================== --- python/branches/py3k-short-float-repr/configure (original) +++ python/branches/py3k-short-float-repr/configure Tue Mar 31 01:16:07 2009 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 70459 . +# From configure.in Revision: 70732 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 3.1. # @@ -4583,6 +4583,76 @@ BASECFLAGS="$BASECFLAGS -fno-strict-aliasing" fi + # On x86/x86-64, use the SSE2 instruction set when available. + { echo "$as_me:$LINENO: checking whether $CC accepts -msse2 -mfpmath=sse" >&5 +echo $ECHO_N "checking whether $CC accepts -msse2 -mfpmath=sse... $ECHO_C" >&6; } + ac_save_cc="$CC" + CC="$CC -msse2 -mfpmath=sse" + if test "$cross_compiling" = yes; then + ac_cv_msse2_ok=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int main() { return 0; } +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_msse2_ok=yes +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 ) +ac_cv_msse2_ok=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + CC="$ac_save_cc" + { echo "$as_me:$LINENO: result: $ac_cv_msse2_ok" >&5 +echo "${ECHO_T}$ac_cv_msse2_ok" >&6; } + { echo "$as_me:$LINENO: checking whether SSE2 instructions are already enabled for math" >&5 +echo $ECHO_N "checking whether SSE2 instructions are already enabled for math... $ECHO_C" >&6; } + if [ "`$CC -dM -E - &5 +echo "${ECHO_T}$ac_sse2_enabled" >&6; } + if test $ac_sse2_enabled = no + then + if test $ac_cv_msse2_ok = yes + then + BASECFLAGS="$BASECFLAGS -msse2 -mfpmath=sse" + fi + fi + # if using gcc on alpha, use -mieee to get (near) full IEEE 754 # support. Without this, treatment of subnormals doesn't follow # the standard. Modified: python/branches/py3k-short-float-repr/configure.in ============================================================================== --- python/branches/py3k-short-float-repr/configure.in (original) +++ python/branches/py3k-short-float-repr/configure.in Tue Mar 31 01:16:07 2009 @@ -849,6 +849,32 @@ BASECFLAGS="$BASECFLAGS -fno-strict-aliasing" fi + # On x86/x86-64, use the SSE2 instruction set when available. + AC_MSG_CHECKING(whether $CC accepts -msse2 -mfpmath=sse) + ac_save_cc="$CC" + CC="$CC -msse2 -mfpmath=sse" + AC_TRY_RUN([int main() { return 0; }], + ac_cv_msse2_ok=yes, + ac_cv_msse2_ok=no, + ac_cv_msse2_ok=no) + CC="$ac_save_cc" + AC_MSG_RESULT($ac_cv_msse2_ok) + AC_MSG_CHECKING(whether SSE2 instructions are already enabled for math) + if [[ "`$CC -dM -E - Author: ronald.oussoren Date: Tue Mar 31 01:16:10 2009 New Revision: 70782 Log: Merged revisions 70778 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70778 | ronald.oussoren | 2009-03-30 18:10:35 -0500 (Mon, 30 Mar 2009) | 4 lines Fix issue #4865: add /Library/Python/2.7/site-packages to sys.path on OSX, to make it easier to share (some) installed packages between the system install and a user install. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/site.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/site.py ============================================================================== --- python/branches/py3k/Lib/site.py (original) +++ python/branches/py3k/Lib/site.py Tue Mar 31 01:16:10 2009 @@ -268,13 +268,15 @@ if sys.platform == "darwin": # for framework builds *only* we add the standard Apple - # locations. Currently only per-user, but /Library and - # /Network/Library could be added too + # locations. if 'Python.framework' in prefix: sitedirs.append( os.path.expanduser( os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"))) + sitedirs.append( + os.path.join("/Library", "Python", + sys.version[:3], "site-packages")) for sitedir in sitedirs: if os.path.isdir(sitedir): Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 31 01:16:10 2009 @@ -1,5 +1,4 @@ -+++++++++++ -Python News ++++++++++++ Python News +++++++++++ (editors: check NEWS.help for information about editing NEWS using ReST.) @@ -18,6 +17,9 @@ - Issue #5126: str.isprintable() returned False for space characters. +- Issue #4865: On MacOSX /Library/Python/2.7/site-packages is added to + the end sys.path, for compatibility with the system install of Python. + - Issue #4688: Add a heuristic so that tuples and dicts containing only untrackable objects are not tracked by the garbage collector. This can reduce the size of collections and therefore the garbage collection overhead From python-checkins at python.org Tue Mar 31 01:29:31 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 01:29:31 +0200 (CEST) Subject: [Python-checkins] r70783 - in python/trunk: Lib/test/test_multiprocessing.py Misc/ACKS Misc/NEWS Modules/_multiprocessing/semaphore.c Message-ID: <20090330232931.839601E4002@bag.python.org> Author: jesse.noller Date: Tue Mar 31 01:29:31 2009 New Revision: 70783 Log: merge in patch from tim golden to fix contextmanager support for mp.Lock() Modified: python/trunk/Lib/test/test_multiprocessing.py python/trunk/Misc/ACKS python/trunk/Misc/NEWS python/trunk/Modules/_multiprocessing/semaphore.c Modified: python/trunk/Lib/test/test_multiprocessing.py ============================================================================== --- python/trunk/Lib/test/test_multiprocessing.py (original) +++ python/trunk/Lib/test/test_multiprocessing.py Tue Mar 31 01:29:31 2009 @@ -546,6 +546,10 @@ self.assertEqual(lock.release(), None) self.assertRaises((AssertionError, RuntimeError), lock.release) + def test_lock_context(self): + with self.Lock(): + pass + class _TestSemaphore(BaseTestCase): Modified: python/trunk/Misc/ACKS ============================================================================== --- python/trunk/Misc/ACKS (original) +++ python/trunk/Misc/ACKS Tue Mar 31 01:29:31 2009 @@ -256,6 +256,7 @@ Jonathan Giddy Johannes Gijsbers Michael Gilfix +Tim Golden Chris Gonnerman David Goodger Hans de Graaff @@ -789,4 +790,3 @@ Uwe Zessin Tarek Ziad? Peter ?strand -Jesse Noller Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 31 01:29:31 2009 @@ -199,6 +199,9 @@ Library ------- +- Issue #5261: Patch multiprocessing's semaphore.c to support context + manager use: "with multiprocessing.Lock()" works now. + - Issue #5177: Multiprocessing's SocketListener class now uses socket.SO_REUSEADDR on all connections so that the user no longer needs to wait 120 seconds for the socket to expire. Modified: python/trunk/Modules/_multiprocessing/semaphore.c ============================================================================== --- python/trunk/Modules/_multiprocessing/semaphore.c (original) +++ python/trunk/Modules/_multiprocessing/semaphore.c Tue Mar 31 01:29:31 2009 @@ -546,7 +546,7 @@ "acquire the semaphore/lock"}, {"release", (PyCFunction)semlock_release, METH_NOARGS, "release the semaphore/lock"}, - {"__enter__", (PyCFunction)semlock_acquire, METH_VARARGS, + {"__enter__", (PyCFunction)semlock_acquire, METH_VARARGS | METH_KEYWORDS, "enter the semaphore/lock"}, {"__exit__", (PyCFunction)semlock_release, METH_VARARGS, "exit the semaphore/lock"}, From python-checkins at python.org Tue Mar 31 01:38:36 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 01:38:36 +0200 (CEST) Subject: [Python-checkins] r70784 - in python/branches/release26-maint: Lib/test/test_multiprocessing.py Misc/ACKS Misc/NEWS Modules/_multiprocessing/semaphore.c Message-ID: <20090330233836.935AF1E4017@bag.python.org> Author: jesse.noller Date: Tue Mar 31 01:38:36 2009 New Revision: 70784 Log: merge 70783 back to 26maint Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_multiprocessing.py python/branches/release26-maint/Misc/ACKS python/branches/release26-maint/Misc/NEWS python/branches/release26-maint/Modules/_multiprocessing/semaphore.c Modified: python/branches/release26-maint/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_multiprocessing.py (original) +++ python/branches/release26-maint/Lib/test/test_multiprocessing.py Tue Mar 31 01:38:36 2009 @@ -548,6 +548,10 @@ self.assertEqual(lock.release(), None) self.assertRaises((AssertionError, RuntimeError), lock.release) + def test_lock_context(self): + with self.Lock(): + pass + class _TestSemaphore(BaseTestCase): Modified: python/branches/release26-maint/Misc/ACKS ============================================================================== --- python/branches/release26-maint/Misc/ACKS (original) +++ python/branches/release26-maint/Misc/ACKS Tue Mar 31 01:38:36 2009 @@ -251,6 +251,7 @@ Jonathan Giddy Johannes Gijsbers Michael Gilfix +Tim Golden Chris Gonnerman David Goodger Hans de Graaff Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Tue Mar 31 01:38:36 2009 @@ -92,6 +92,9 @@ Library ------- +- Issue #5261: Patch multiprocessing's semaphore.c to support context + manager use: "with multiprocessing.Lock()" works now. + - Issue #5177: Multiprocessing's SocketListener class now uses socket.SO_REUSEADDR on all connections so that the user no longer needs to wait 120 seconds for the socket to expire. Modified: python/branches/release26-maint/Modules/_multiprocessing/semaphore.c ============================================================================== --- python/branches/release26-maint/Modules/_multiprocessing/semaphore.c (original) +++ python/branches/release26-maint/Modules/_multiprocessing/semaphore.c Tue Mar 31 01:38:36 2009 @@ -546,7 +546,7 @@ "acquire the semaphore/lock"}, {"release", (PyCFunction)semlock_release, METH_NOARGS, "release the semaphore/lock"}, - {"__enter__", (PyCFunction)semlock_acquire, METH_VARARGS, + {"__enter__", (PyCFunction)semlock_acquire, METH_VARARGS | METH_KEYWORDS, "enter the semaphore/lock"}, {"__exit__", (PyCFunction)semlock_release, METH_VARARGS, "exit the semaphore/lock"}, From python-checkins at python.org Tue Mar 31 02:01:17 2009 From: python-checkins at python.org (eric.smith) Date: Tue, 31 Mar 2009 02:01:17 +0200 (CEST) Subject: [Python-checkins] r70785 - in python/branches/py3k-short-float-repr: Objects/complexobject.c Python/pystrtod.c Message-ID: <20090331000117.91A6C1E4002@bag.python.org> Author: eric.smith Date: Tue Mar 31 02:01:17 2009 New Revision: 70785 Log: Checkpoint. Memory management still needs work. Modified: python/branches/py3k-short-float-repr/Objects/complexobject.c python/branches/py3k-short-float-repr/Python/pystrtod.c Modified: python/branches/py3k-short-float-repr/Objects/complexobject.c ============================================================================== --- python/branches/py3k-short-float-repr/Objects/complexobject.c (original) +++ python/branches/py3k-short-float-repr/Objects/complexobject.c Tue Mar 31 02:01:17 2009 @@ -345,62 +345,107 @@ } -static void -complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int precision) +static int +complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int mode, + int precision) { - char format[32]; - if (v->cval.real == 0.) { - if (!Py_IS_FINITE(v->cval.imag)) { - if (Py_IS_NAN(v->cval.imag)) - strncpy(buf, "nan*j", 6); - else if (copysign(1, v->cval.imag) == 1) - strncpy(buf, "inf*j", 6); - else - strncpy(buf, "-inf*j", 7); - } - else { - PyOS_snprintf(format, sizeof(format), "%%.%ig", precision); - PyOS_ascii_formatd(buf, bufsz - 1, format, v->cval.imag); - strncat(buf, "j", 1); - } - } else { - char re[64], im[64]; - /* Format imaginary part with sign, real part without */ - if (!Py_IS_FINITE(v->cval.real)) { - if (Py_IS_NAN(v->cval.real)) - strncpy(re, "nan", 4); - /* else if (copysign(1, v->cval.real) == 1) */ - else if (v->cval.real > 0) - strncpy(re, "inf", 4); - else - strncpy(re, "-inf", 5); - } - else { - PyOS_snprintf(format, sizeof(format), "%%.%ig", precision); - PyOS_ascii_formatd(re, sizeof(re), format, v->cval.real); - } - if (!Py_IS_FINITE(v->cval.imag)) { - if (Py_IS_NAN(v->cval.imag)) - strncpy(im, "+nan*", 6); - /* else if (copysign(1, v->cval.imag) == 1) */ - else if (v->cval.imag > 0) - strncpy(im, "+inf*", 6); - else - strncpy(im, "-inf*", 6); - } - else { - PyOS_snprintf(format, sizeof(format), "%%+.%ig", precision); - PyOS_ascii_formatd(im, sizeof(im), format, v->cval.imag); - } - PyOS_snprintf(buf, bufsz, "(%s%sj)", re, im); - } + int result = -1; + char* p; + + /* If these are non-NULL, they'll need to be freed. */ + char* pre = NULL; + char* pim = NULL; + + /* These do not need to be freed. They're either aliases for pim + and pre, or pointers to constants. */ + char* re = NULL; + char* im = NULL; + char* lead = ""; + char* tail = ""; + + Py_ssize_t len; + + if (v->cval.real == 0.) { + re = ""; + if (!Py_IS_FINITE(v->cval.imag)) { + if (Py_IS_NAN(v->cval.imag)) + im = "nan*"; + else if (copysign(1, v->cval.imag) == 1) + im = "inf*"; + else + im = "-inf*"; + } + else { + pim = PyOS_double_to_string(v->cval.imag, mode, 'g', precision, 0, 0); + if (!pim) { + PyErr_NoMemory(); + goto done; + } + im = pim; + } + } else { + /* Format imaginary part with sign, real part without */ + if (!Py_IS_FINITE(v->cval.real)) { + if (Py_IS_NAN(v->cval.real)) + re = "nan"; + /* else if (copysign(1, v->cval.real) == 1) */ + else if (v->cval.real > 0) + re = "inf"; + else + re = "-inf"; + } + else { + pre = PyOS_double_to_string(v->cval.real, mode, 'g', precision, 0, 0); + if (!pre) { + PyErr_NoMemory(); + goto done; + } + re = pre; + } + + if (!Py_IS_FINITE(v->cval.imag)) { + if (Py_IS_NAN(v->cval.imag)) + im = "+nan*"; + /* else if (copysign(1, v->cval.imag) == 1) */ + else if (v->cval.imag > 0) + im = "+inf*"; + else + im = "-inf*"; + } + else { + pim = PyOS_double_to_string(v->cval.imag, mode, 'g', precision, 1, 0); + if (!pim) { + PyErr_NoMemory(); + goto done; + } + im = pim; + } + lead = "("; + tail = ")"; + } + /* Alloc the final buffer. Add one for the "j" in the format string. */ + len = strlen(lead) + strlen(re) + strlen(im) + strlen(tail) + 2; + p = PyMem_Malloc(len); + if (!p) { + PyErr_NoMemory(); + goto done; + } + PyOS_snprintf(p, len, "%s%s%sj%s", lead, re, im, tail); + strcpy(buf, p); + result = 0; +done: + PyMem_Free(pim); + PyMem_Free(pre); + + return result; } static PyObject * complex_repr(PyComplexObject *v) { char buf[100]; - complex_to_buf(buf, sizeof(buf), v, PREC_REPR); + if (complex_to_buf(buf, sizeof(buf), v, 0, 0) < 0) + return PyErr_NoMemory(); return PyUnicode_FromString(buf); } @@ -408,7 +453,8 @@ complex_str(PyComplexObject *v) { char buf[100]; - complex_to_buf(buf, sizeof(buf), v, PREC_STR); + if (complex_to_buf(buf, sizeof(buf), v, 2, PREC_STR) < 0) + return PyErr_NoMemory(); return PyUnicode_FromString(buf); } Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/pystrtod.c (original) +++ python/branches/py3k-short-float-repr/Python/pystrtod.c Tue Mar 31 02:01:17 2009 @@ -495,7 +495,7 @@ number of significant digits. */ static void -format_float_short(char *buf, size_t buflen, double d, int mode, int precision) +format_float_short(char *buf, size_t buflen, double d, int mode, int precision, int always_add_sign, int add_dot_0_if_integer) { char *digits, *digits_end; int decpt, sign, exp_len; @@ -515,6 +515,9 @@ if (sign == 1) { *buf++ = '-'; } + else if (always_add_sign) { + *buf++ = '+'; + } strncpy(buf, "inf", 3); buf += 3; } else { @@ -526,6 +529,8 @@ else if (-4 < decpt && decpt <= 17) { if (sign == 1) { *buf++ = '-'; + } else if (always_add_sign) { + *buf++ = '+'; } /* use fixed-point notation if 1e-4 <= value < 1e17 */ if (decpt <= 0) { @@ -551,8 +556,10 @@ buf += digits_len; for (i=0; i < decpt-digits_len; i++) *buf++ = '0'; - *buf++ = '.'; - *buf++ = '0'; + if (add_dot_0_if_integer) { + *buf++ = '.'; + *buf++ = '0'; + } } } else { @@ -560,6 +567,8 @@ at least 2 digits in exponent */ if (sign == 1) { *buf++ = '-'; + } else if (always_add_sign) { + *buf++ = '+'; } *buf++ = digits[0]; if (digits_len > 1) { @@ -578,7 +587,7 @@ int mode, char format_code, int precision, - int sign, + int always_add_sign, int add_dot_0_if_integer) { char fmt[32]; @@ -590,26 +599,7 @@ /* XXX validate format_code */ - format_float_short(buf, 512, val, mode, precision); - - if (add_dot_0_if_integer) { - /* If the result was just an integer, without a decimal, then - add ".0" to the end of the string. */ - char *cp = buf; - if (*cp == '-') - cp++; - for (; *cp != '\0'; cp++) { - /* Any non-digit means it's not an integer; - this takes care of NAN and INF as well. */ - if (!isdigit(Py_CHARMASK(*cp))) - break; - } - if (*cp == '\0') { - *cp++ = '.'; - *cp++ = '0'; - *cp++ = '\0'; - } - } + format_float_short(buf, 512, val, mode, precision, always_add_sign, add_dot_0_if_integer); return buf; } From python-checkins at python.org Tue Mar 31 02:33:15 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 02:33:15 +0200 (CEST) Subject: [Python-checkins] r70786 - in python/branches/py3k/Demo/distutils/test2to3: setup.py test test/runtests.py test/test_foo.py Message-ID: <20090331003315.454B21E4002@bag.python.org> Author: georg.brandl Date: Tue Mar 31 02:33:15 2009 New Revision: 70786 Log: Add example for new copydir_run_2to3(). Added: python/branches/py3k/Demo/distutils/test2to3/test/ python/branches/py3k/Demo/distutils/test2to3/test/runtests.py (contents, props changed) python/branches/py3k/Demo/distutils/test2to3/test/test_foo.py (contents, props changed) Modified: python/branches/py3k/Demo/distutils/test2to3/ (props changed) python/branches/py3k/Demo/distutils/test2to3/setup.py Modified: python/branches/py3k/Demo/distutils/test2to3/setup.py ============================================================================== --- python/branches/py3k/Demo/distutils/test2to3/setup.py (original) +++ python/branches/py3k/Demo/distutils/test2to3/setup.py Tue Mar 31 02:33:15 2009 @@ -20,7 +20,7 @@ license = "PSF license", packages = ["test2to3"], scripts = ["maintest.py"], - cmdclass = {'build_py':build_py, - 'build_scripts':build_scripts, + cmdclass = {'build_py': build_py, + 'build_scripts': build_scripts, } ) Added: python/branches/py3k/Demo/distutils/test2to3/test/runtests.py ============================================================================== --- (empty file) +++ python/branches/py3k/Demo/distutils/test2to3/test/runtests.py Tue Mar 31 02:33:15 2009 @@ -0,0 +1,19 @@ +# Fictitious test runner for the project + +import sys, os + +if sys.version_info > (3,): + # copy test suite over to "build/lib" and convert it + from distutils.util import copydir_run_2to3 + testroot = os.path.dirname(__file__) + newroot = os.path.join(testroot, '..', 'build/lib/test') + copydir_run_2to3(testroot, newroot) + # in the following imports, pick up the converted modules + sys.path[0] = newroot + +# run the tests here... + +from test_foo import FooTest + +import unittest +unittest.main() Added: python/branches/py3k/Demo/distutils/test2to3/test/test_foo.py ============================================================================== --- (empty file) +++ python/branches/py3k/Demo/distutils/test2to3/test/test_foo.py Tue Mar 31 02:33:15 2009 @@ -0,0 +1,8 @@ +import sys +import unittest + +class FooTest(unittest.TestCase): + def test_foo(self): + # use 2.6 syntax to demonstrate conversion + print 'In test_foo, using Python %s...' % (sys.version_info,) + self.assertTrue(False) From python-checkins at python.org Tue Mar 31 02:34:54 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 02:34:54 +0200 (CEST) Subject: [Python-checkins] r70787 - python/branches/py3k/Lib/distutils/util.py Message-ID: <20090331003454.E4B691E4002@bag.python.org> Author: georg.brandl Date: Tue Mar 31 02:34:54 2009 New Revision: 70787 Log: Add new copydir_run_2to3() function, for use e.g. in test runners to transparently convert and run tests written for Python 2. Modified: python/branches/py3k/Lib/distutils/util.py Modified: python/branches/py3k/Lib/distutils/util.py ============================================================================== --- python/branches/py3k/Lib/distutils/util.py (original) +++ python/branches/py3k/Lib/distutils/util.py Tue Mar 31 02:34:54 2009 @@ -571,6 +571,39 @@ r = DistutilsRefactoringTool(fixer_names, options=options) r.refactor(files, write=True) +def copydir_run_2to3(src, dest, template=None, fixer_names=None, + options=None, explicit=None): + """Recursively copy a directory, only copying new and changed files, + running run_2to3 over all newly copied Python modules afterward. + + If you give a template string, it's parsed like a MANIFEST.in. + """ + from distutils.dir_util import mkpath + from distutils.file_util import copy_file + from distutils.filelist import FileList + filelist = FileList() + curdir = os.getcwd() + os.chdir(src) + try: + filelist.findall() + finally: + os.chdir(curdir) + filelist.files[:] = filelist.allfiles + if template: + for line in template.splitlines(): + line = line.strip() + if not line: continue + filelist.process_template_line(line) + copied = [] + for filename in filelist.files: + outname = os.path.join(dest, filename) + mkpath(os.path.dirname(outname)) + res = copy_file(os.path.join(src, filename), outname, update=1) + if res[1]: copied.append(outname) + run_2to3([fn for fn in copied if fn.lower().endswith('.py')], + fixer_names=fixer_names, options=options, explicit=explicit) + return copied + class Mixin2to3: '''Mixin class for commands that run 2to3. To configure 2to3, setup scripts may either change From buildbot at python.org Tue Mar 31 03:04:47 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 01:04:47 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090331010447.F2AC11E4002@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/495 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: georg.brandl BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_time make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 03:21:01 2009 From: python-checkins at python.org (andrew.kuchling) Date: Tue, 31 Mar 2009 03:21:01 +0200 (CEST) Subject: [Python-checkins] r70788 - python/trunk/Doc/whatsnew/2.7.rst Message-ID: <20090331012101.B86561E4002@bag.python.org> Author: andrew.kuchling Date: Tue Mar 31 03:21:01 2009 New Revision: 70788 Log: Add various items Modified: python/trunk/Doc/whatsnew/2.7.rst Modified: python/trunk/Doc/whatsnew/2.7.rst ============================================================================== --- python/trunk/Doc/whatsnew/2.7.rst (original) +++ python/trunk/Doc/whatsnew/2.7.rst Tue Mar 31 03:21:01 2009 @@ -113,7 +113,13 @@ Optimizations ------------- -A few performance enhancements have been added: +Several performance enhancements have been added: + +.. * A new :program:`configure` option, :option:`--with-computed-gotos`, + compiles the main bytecode interpreter loop using a new dispatch + mechanism that gives speedups of up to 20%, depending on the system + and benchmark. The new mechanism is only supported on certain + compilers, such as gcc, SunPro, and icc. * The garbage collector now performs better when many objects are being allocated without deallocating any. A full garbage collection @@ -158,7 +164,7 @@ (Contributed by Mark Dickinson; :issue:`4258`.) Another set of changes made long objects a few bytes smaller: 2 bytes - smaller on 32-bit systems and 6 bytes on 64-bit. (: + smaller on 32-bit systems and 6 bytes on 64-bit. (Contributed by Mark Dickinson; :issue:`5260`.) * The division algorithm for long integers has been made faster @@ -168,6 +174,10 @@ integer divisions and modulo operations. (Contributed by Mark Dickinson; :issue:`5512`.) +* List comprehensions with an ``if`` condition are compiled into + faster bytecode. (Patch by Antoine Pitrou, back-ported to 2.7 + by Jeffrey Yasskin; :issue:`4715`.) + .. ====================================================================== New, Improved, and Deprecated Modules @@ -179,12 +189,6 @@ :file:`Misc/NEWS` file in the source tree for a more complete list of changes, or look through the Subversion logs for all the details. -* It is no longer mandatory to store clear-text passwords in the - :file:`.pypirc` file when registering and uploading packages to PyPI. As long - as the username is present in that file, the :mod:`distutils` package will - prompt for the password if not present. (Added by Tarek Ziade, - with the initial contribution by Nathan Van Gheem; :issue:`4394`.) - * The :mod:`bz2` module's :class:`BZ2File` now supports the context management protocol, so you can write ``with bz2.BZ2File(...) as f: ...``. (Contributed by Hagen Fuerstenau; :issue:`3860`.) @@ -224,7 +228,24 @@ Contributed by Raymond Hettinger; :issue:`1696199`. * In Distutils, :func:`distutils.sdist.add_defaults` now uses - *package_dir* and *data_files* to feed MANIFEST. + *package_dir* and *data_files* to create the MANIFEST file. + + It is no longer mandatory to store clear-text passwords in the + :file:`.pypirc` file when registering and uploading packages to PyPI. As long + as the username is present in that file, the :mod:`distutils` package will + prompt for the password if not present. (Added by Tarek Ziade, + with the initial contribution by Nathan Van Gheem; :issue:`4394`.) + +* New method: the :class:`Decimal` class gained a + :meth:`from_float` class method that performs an exact conversion + of a floating-point number to a :class:`Decimal`. + Note that this is an **exact** conversion that strives for the + closest decimal approximation to the floating-point representation's value; + the resulting decimal value will therefore still include the inaccuracy, + if any. + For example, ``Decimal.from_float(0.1)`` returns + ``Decimal('0.1000000000000000055511151231257827021181583404541015625')``. + (Implemented by Raymond Hettinger; :issue:`4796`.) * A new function in the :mod:`gc` module, :func:`is_tracked`, returns True if a given instance is tracked by the garbage collector, False @@ -233,6 +254,9 @@ * The :mod:`gzip` module's :class:`GzipFile` now supports the context management protocol, so you can write ``with gzip.GzipFile(...) as f: ...``. (Contributed by Hagen Fuerstenau; :issue:`3860`.) + It's now possible to override the modification time + recorded in a gzipped file by providing an optional timestamp to + the constructor. (Contributed by Jacques Frechet; :issue:`4272`.) * The :class:`io.FileIO` class now raises an :exc:`OSError` when passed an invalid file descriptor. (Implemented by Benjamin Peterson; @@ -263,6 +287,11 @@ floats or :class:`Decimal` instances. (Implemented by Raymond Hettinger; :issue:`5032`.) + :func:`itertools.combinations` and :func:`itertools.product` were + previously raising :exc:`ValueError` for values of *r* larger than + the input iterable. This was deemed a specification error, so they + now return an empty iterator. (Fixed by Raymond Hettinger; :issue:`4816`.) + * The :mod:`json` module was upgraded to version 2.0.9 of the simplejson package, which includes a C extension that makes encoding and decoding faster. @@ -351,6 +380,11 @@ is particularly useful for asynchronous IO operations. (Contributed by Kristjan Valur Jonsson; :issue:`4293`.) +* The :program:`configure` script now checks for floating-point rounding bugs + on certain 32-bit Intel chips and defines a :cmacro:`X87_DOUBLE_ROUNDING` + preprocessor definition. No code currently uses this definition, + but it's available if anyone wishes to use it. + (Added by Mark Dickinson; :issue:`2937`.) .. ====================================================================== @@ -373,10 +407,22 @@ Port-Specific Changes: Mac OS X ----------------------------------- +* The ``/Library/Python/2.7/site-packages`` is now appended to + ``sys.path``, in order to share added packages between the system + installation and a user-installed copy of the same version. + (Changed by Ronald Oussoren; :issue:`4865`.) + Other Changes and Fixes ======================= +* When importing a module from a :file:`.pyc` or :file:`.pyo` file + with an existing :file:`.py` counterpart, the :attr:`co_filename` + attributes of all code objects if the original filename is obsolete, + which can happen if the file has been renamed, moved, or is accessed + through different paths. (Patch by Ziga Seilnacht and Jean-Paul + Calderone; :issue:`1180193`.) + * The :file:`regrtest.py` script now takes a :option:`--randseed=` switch that takes an integer that will be used as the random seed for the :option:`-r` option that executes tests in random order. From python-checkins at python.org Tue Mar 31 03:25:16 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 03:25:16 +0200 (CEST) Subject: [Python-checkins] r70789 - python/trunk/Objects/genobject.c Message-ID: <20090331012516.105051E4002@bag.python.org> Author: georg.brandl Date: Tue Mar 31 03:25:15 2009 New Revision: 70789 Log: Fix a wrong struct field assignment (docstring as closure). Modified: python/trunk/Objects/genobject.c Modified: python/trunk/Objects/genobject.c ============================================================================== --- python/trunk/Objects/genobject.c (original) +++ python/trunk/Objects/genobject.c Tue Mar 31 03:25:15 2009 @@ -306,7 +306,7 @@ "Return the name of the generator's associated code object."); static PyGetSetDef gen_getsetlist[] = { - {"__name__", (getter)gen_get_name, NULL, NULL, gen__name__doc__}, + {"__name__", (getter)gen_get_name, NULL, gen__name__doc__}, {NULL} }; From buildbot at python.org Tue Mar 31 03:35:39 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 01:35:39 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090331013540.1C0A21E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/802 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: andrew.kuchling,barry.warsaw,georg.brandl,jesse.noller,martin.v.loewis,r.david.murray,ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: make: *** [buildbottest] Abort trap sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 05:00:48 2009 From: python-checkins at python.org (eric.smith) Date: Tue, 31 Mar 2009 05:00:48 +0200 (CEST) Subject: [Python-checkins] r70790 - python/branches/py3k-short-float-repr/Objects/complexobject.c Message-ID: <20090331030048.AE2EC1E4010@bag.python.org> Author: eric.smith Date: Tue Mar 31 05:00:48 2009 New Revision: 70790 Log: Finished memory management for complex formatting. Modified: python/branches/py3k-short-float-repr/Objects/complexobject.c Modified: python/branches/py3k-short-float-repr/Objects/complexobject.c ============================================================================== --- python/branches/py3k-short-float-repr/Objects/complexobject.c (original) +++ python/branches/py3k-short-float-repr/Objects/complexobject.c Tue Mar 31 05:00:48 2009 @@ -14,20 +14,13 @@ #ifndef WITHOUT_COMPLEX -/* Precisions used by repr() and str(), respectively. - - The repr() precision (17 significant decimal digits) is the minimal number - that is guaranteed to have enough precision so that if the number is read - back in the exact same binary value is recreated. This is true for IEEE - floating point by design, and also happens to work for all other modern - hardware. +/* Precision used by str(). The str() precision is chosen so that in most cases, the rounding noise created by various operations is suppressed, while giving plenty of precision for practical use. */ -#define PREC_REPR 17 #define PREC_STR 12 /* elementary operations on complex numbers */ @@ -345,25 +338,24 @@ } -static int -complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int mode, - int precision) +static PyObject * +complex_format(PyComplexObject *v, int mode, int precision) { - int result = -1; - char* p; + PyObject *result = NULL; + Py_ssize_t len; + char *buf; /* If these are non-NULL, they'll need to be freed. */ - char* pre = NULL; - char* pim = NULL; + char *pre = NULL; + char *pim = NULL; /* These do not need to be freed. They're either aliases for pim and pre, or pointers to constants. */ - char* re = NULL; - char* im = NULL; - char* lead = ""; - char* tail = ""; + char *re = NULL; + char *im = NULL; + char *lead = ""; + char *tail = ""; - Py_ssize_t len; if (v->cval.real == 0.) { re = ""; @@ -376,7 +368,8 @@ im = "-inf*"; } else { - pim = PyOS_double_to_string(v->cval.imag, mode, 'g', precision, 0, 0); + pim = PyOS_double_to_string(v->cval.imag, mode, 'g', precision, + 0, 0); if (!pim) { PyErr_NoMemory(); goto done; @@ -395,7 +388,8 @@ re = "-inf"; } else { - pre = PyOS_double_to_string(v->cval.real, mode, 'g', precision, 0, 0); + pre = PyOS_double_to_string(v->cval.real, mode, 'g', precision, + 0, 0); if (!pre) { PyErr_NoMemory(); goto done; @@ -413,7 +407,8 @@ im = "-inf*"; } else { - pim = PyOS_double_to_string(v->cval.imag, mode, 'g', precision, 1, 0); + pim = PyOS_double_to_string(v->cval.imag, mode, 'g', precision, + 1, 0); if (!pim) { PyErr_NoMemory(); goto done; @@ -423,16 +418,16 @@ lead = "("; tail = ")"; } - /* Alloc the final buffer. Add one for the "j" in the format string. */ + /* Alloc the final buffer. Add one for the "j" in the format string, and + one for the trailing zero. */ len = strlen(lead) + strlen(re) + strlen(im) + strlen(tail) + 2; - p = PyMem_Malloc(len); - if (!p) { + buf = PyMem_Malloc(len); + if (!buf) { PyErr_NoMemory(); goto done; } - PyOS_snprintf(p, len, "%s%s%sj%s", lead, re, im, tail); - strcpy(buf, p); - result = 0; + PyOS_snprintf(buf, len, "%s%s%sj%s", lead, re, im, tail); + result = PyUnicode_FromString(buf); done: PyMem_Free(pim); PyMem_Free(pre); @@ -443,19 +438,13 @@ static PyObject * complex_repr(PyComplexObject *v) { - char buf[100]; - if (complex_to_buf(buf, sizeof(buf), v, 0, 0) < 0) - return PyErr_NoMemory(); - return PyUnicode_FromString(buf); + return complex_format(v, 0, 0); } static PyObject * complex_str(PyComplexObject *v) { - char buf[100]; - if (complex_to_buf(buf, sizeof(buf), v, 2, PREC_STR) < 0) - return PyErr_NoMemory(); - return PyUnicode_FromString(buf); + return complex_format(v, 2, PREC_STR); } static long From python-checkins at python.org Tue Mar 31 05:25:08 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 05:25:08 +0200 (CEST) Subject: [Python-checkins] r70791 - in python/branches/py3k: Lib/test/test_multiprocessing.py Misc/ACKS Misc/NEWS Modules/_multiprocessing/semaphore.c Message-ID: <20090331032508.396471E4002@bag.python.org> Author: jesse.noller Date: Tue Mar 31 05:25:07 2009 New Revision: 70791 Log: merge 70783 to py3k Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_multiprocessing.py python/branches/py3k/Misc/ACKS python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_multiprocessing/semaphore.c Modified: python/branches/py3k/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/py3k/Lib/test/test_multiprocessing.py (original) +++ python/branches/py3k/Lib/test/test_multiprocessing.py Tue Mar 31 05:25:07 2009 @@ -548,6 +548,10 @@ self.assertEqual(lock.release(), None) self.assertRaises((AssertionError, RuntimeError), lock.release) + def test_lock_context(self): + with self.Lock(): + pass + class _TestSemaphore(BaseTestCase): Modified: python/branches/py3k/Misc/ACKS ============================================================================== --- python/branches/py3k/Misc/ACKS (original) +++ python/branches/py3k/Misc/ACKS Tue Mar 31 05:25:07 2009 @@ -257,6 +257,7 @@ Jonathan Giddy Johannes Gijsbers Michael Gilfix +Tim Golden Chris Gonnerman David Goodger Hans de Graaff @@ -794,4 +795,3 @@ Uwe Zessin Tarek Ziad? Peter ?strand -Jesse Noller Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 31 05:25:07 2009 @@ -49,6 +49,9 @@ Library ------- +- Issue #5261: Patch multiprocessing's semaphore.c to support context + manager use: "with multiprocessing.Lock()" works now. + - Issue #5236: Change time.strptime() to only take strings. Didn't work with bytes already but the failure was non-obvious. Modified: python/branches/py3k/Modules/_multiprocessing/semaphore.c ============================================================================== --- python/branches/py3k/Modules/_multiprocessing/semaphore.c (original) +++ python/branches/py3k/Modules/_multiprocessing/semaphore.c Tue Mar 31 05:25:07 2009 @@ -546,7 +546,7 @@ "acquire the semaphore/lock"}, {"release", (PyCFunction)semlock_release, METH_NOARGS, "release the semaphore/lock"}, - {"__enter__", (PyCFunction)semlock_acquire, METH_VARARGS, + {"__enter__", (PyCFunction)semlock_acquire, METH_VARARGS | METH_KEYWORDS, "enter the semaphore/lock"}, {"__exit__", (PyCFunction)semlock_release, METH_VARARGS, "exit the semaphore/lock"}, From python-checkins at python.org Tue Mar 31 05:31:16 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 05:31:16 +0200 (CEST) Subject: [Python-checkins] r70792 - python/trunk/Lib/multiprocessing/queues.py Message-ID: <20090331033116.E7C7F1E4002@bag.python.org> Author: jesse.noller Date: Tue Mar 31 05:31:16 2009 New Revision: 70792 Log: add JoinableQueue to __all__ Modified: python/trunk/Lib/multiprocessing/queues.py Modified: python/trunk/Lib/multiprocessing/queues.py ============================================================================== --- python/trunk/Lib/multiprocessing/queues.py (original) +++ python/trunk/Lib/multiprocessing/queues.py Tue Mar 31 05:31:16 2009 @@ -6,7 +6,7 @@ # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt # -__all__ = ['Queue', 'SimpleQueue'] +__all__ = ['Queue', 'SimpleQueue', 'JoinableQueue'] import sys import os From python-checkins at python.org Tue Mar 31 05:35:12 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 05:35:12 +0200 (CEST) Subject: [Python-checkins] r70793 - in python/branches/release26-maint: Lib/multiprocessing/queues.py Message-ID: <20090331033512.E24BF1E4002@bag.python.org> Author: jesse.noller Date: Tue Mar 31 05:35:12 2009 New Revision: 70793 Log: merge 70792 to 26 maint Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/multiprocessing/queues.py Modified: python/branches/release26-maint/Lib/multiprocessing/queues.py ============================================================================== --- python/branches/release26-maint/Lib/multiprocessing/queues.py (original) +++ python/branches/release26-maint/Lib/multiprocessing/queues.py Tue Mar 31 05:35:12 2009 @@ -6,7 +6,7 @@ # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt # -__all__ = ['Queue', 'SimpleQueue'] +__all__ = ['Queue', 'SimpleQueue', 'JoinableQueue'] import sys import os From python-checkins at python.org Tue Mar 31 05:37:07 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 05:37:07 +0200 (CEST) Subject: [Python-checkins] r70794 - in python/branches/py3k: Lib/multiprocessing/queues.py Message-ID: <20090331033707.F249E1E4002@bag.python.org> Author: jesse.noller Date: Tue Mar 31 05:37:07 2009 New Revision: 70794 Log: merge 70792 to py3k Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/multiprocessing/queues.py Modified: python/branches/py3k/Lib/multiprocessing/queues.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/queues.py (original) +++ python/branches/py3k/Lib/multiprocessing/queues.py Tue Mar 31 05:37:07 2009 @@ -6,7 +6,7 @@ # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt # -__all__ = ['Queue', 'SimpleQueue'] +__all__ = ['Queue', 'SimpleQueue', 'JoinableQueue'] import sys import os From buildbot at python.org Tue Mar 31 05:41:25 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 03:41:25 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090331034125.9D42B1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/589 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: jesse.noller BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_time make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 31 05:50:16 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 03:50:16 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.0 Message-ID: <20090331035016.B51A61E4002@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.0/builds/185 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: guido.van.rossum BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_doctest make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 05:52:44 2009 From: python-checkins at python.org (eric.smith) Date: Tue, 31 Mar 2009 05:52:44 +0200 (CEST) Subject: [Python-checkins] r70795 - python/branches/py3k-short-float-repr/Objects/floatobject.c Message-ID: <20090331035244.3C8831E4002@bag.python.org> Author: eric.smith Date: Tue Mar 31 05:52:44 2009 New Revision: 70795 Log: More work on removed PREC_STR. Now only _PyFloat_Repr() (used by marshal) remains. It too will be removed eventually. Modified: python/branches/py3k-short-float-repr/Objects/floatobject.c Modified: python/branches/py3k-short-float-repr/Objects/floatobject.c ============================================================================== --- python/branches/py3k-short-float-repr/Objects/floatobject.c (original) +++ python/branches/py3k-short-float-repr/Objects/floatobject.c Tue Mar 31 05:52:44 2009 @@ -444,8 +444,7 @@ static PyObject * float_repr(PyFloatObject *v) { - /* XXX change PREC_REPR to 0 when mode is supported */ - return float_str_or_repr(v, 0, PREC_REPR); + return float_str_or_repr(v, 0, 0); } static PyObject * @@ -1980,17 +1979,21 @@ i++, p++) { if (PyFloat_CheckExact(p) && Py_REFCNT(p) != 0) { - char buf[100]; - format_double(buf, sizeof(buf), - PyFloat_AS_DOUBLE(p), - PREC_STR); - /* XXX(twouters) cast refcount to - long until %zd is universally - available - */ - fprintf(stderr, + char *buf = PyOS_double_to_string( + PyFloat_AS_DOUBLE(p), 0, 'g', + 0, 0, 1); + if (buf) { + /* XXX(twouters) cast + refcount to long + until %zd is + universally + available + */ + fprintf(stderr, "# \n", p, (long)Py_REFCNT(p), buf); + PyMem_Free(buf); + } } } list = list->next; From python-checkins at python.org Tue Mar 31 05:58:04 2009 From: python-checkins at python.org (brett.cannon) Date: Tue, 31 Mar 2009 05:58:04 +0200 (CEST) Subject: [Python-checkins] r70796 - python/branches/py3k/Lib/_strptime.py Message-ID: <20090331035804.BB7D51E405A@bag.python.org> Author: brett.cannon Date: Tue Mar 31 05:58:04 2009 New Revision: 70796 Log: The message for the exception when time.strptime was passed something other than str did not output the type of the argument but the object itself. Modified: python/branches/py3k/Lib/_strptime.py Modified: python/branches/py3k/Lib/_strptime.py ============================================================================== --- python/branches/py3k/Lib/_strptime.py (original) +++ python/branches/py3k/Lib/_strptime.py Tue Mar 31 05:58:04 2009 @@ -298,7 +298,7 @@ for index, arg in enumerate([data_string, format]): if not isinstance(arg, str): msg = "strptime() argument {} must be str, not {}" - raise TypeError(msg.format(arg, index)) + raise TypeError(msg.format(index, type(arg))) global _TimeRE_cache, _regex_cache with _cache_lock: From python-checkins at python.org Tue Mar 31 06:16:11 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 06:16:11 +0200 (CEST) Subject: [Python-checkins] r70797 - in python/branches/py3k: Doc/c-api/exceptions.rst Lib/test/test_exceptions.py Misc/NEWS Objects/exceptions.c Message-ID: <20090331041611.212C01E4002@bag.python.org> Author: georg.brandl Date: Tue Mar 31 06:16:10 2009 New Revision: 70797 Log: Fix segfaults when running test_exceptions with coverage tracing, caused by wrongly defining Exception.__context__ as a T_OBJECT structmember which does not set the member to NULL on None assignment, and generally does not do type checks. This could be used to crash the interpreter by setting any object to __context__. The same applies to __cause__. Also document the PyException_* functions. Modified: python/branches/py3k/Doc/c-api/exceptions.rst python/branches/py3k/Lib/test/test_exceptions.py python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/exceptions.c Modified: python/branches/py3k/Doc/c-api/exceptions.rst ============================================================================== --- python/branches/py3k/Doc/c-api/exceptions.rst (original) +++ python/branches/py3k/Doc/c-api/exceptions.rst Tue Mar 31 06:16:10 2009 @@ -400,6 +400,52 @@ the warning message. +Exception Objects +================= + +.. cfunction:: PyObject* PyException_GetTraceback(PyObject *ex) + + Return the traceback associated with the exception as a new reference, as + accessible from Python through :attr:`__traceback__`. If there is no + traceback associated, this returns *NULL*. + + +.. cfunction:: int PyException_SetTraceback(PyObject *ex, PyObject *tb) + + Set the traceback associated with the exception to *tb*. Use ``Py_None`` to + clear it. + + +.. cfunction:: PyObject* PyException_GetContext(PyObject *ex) + + Return the context (another exception instance during whose handling *ex* was + raised) associated with the exception as a new reference, as accessible from + Python through :attr:`__context__`. If there is no context associated, this + returns *NULL*. + + +.. cfunction:: void PyException_SetContext(PyObject *ex, PyObject *ctx) + + Set the context associated with the exception to *ctx*. Use *NULL* to clear + it. There is no type check to make sure that *ctx* is an exception instance. + This steals a reference to *ctx*. + + +.. cfunction:: PyObject* PyException_GetCause(PyObject *ex) + + Return the cause (another exception instance set by ``raise ... from ...``) + associated with the exception as a new reference, as accessible from Python + through :attr:`__cause__`. If there is no cause associated, this returns + *NULL*. + + +.. cfunction:: void PyException_SetCause(PyObject *ex, PyObject *ctx) + + Set the cause associated with the exception to *ctx*. Use *NULL* to clear + it. There is no type check to make sure that *ctx* is an exception instance. + This steals a reference to *ctx*. + + .. _standardexceptions: Standard Exceptions Modified: python/branches/py3k/Lib/test/test_exceptions.py ============================================================================== --- python/branches/py3k/Lib/test/test_exceptions.py (original) +++ python/branches/py3k/Lib/test/test_exceptions.py Tue Mar 31 06:16:10 2009 @@ -341,6 +341,12 @@ else: self.fail("No exception raised") + def testInvalidAttrs(self): + self.assertRaises(TypeError, setattr, Exception(), '__cause__', 1) + self.assertRaises(TypeError, delattr, Exception(), '__cause__') + self.assertRaises(TypeError, setattr, Exception(), '__context__', 1) + self.assertRaises(TypeError, delattr, Exception(), '__context__') + def testNoneClearsTracebackAttr(self): try: raise IndexError(4) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 31 06:16:10 2009 @@ -1,4 +1,5 @@ -+++++++++++ Python News ++++++++++++ +Python News +++++++++++ (editors: check NEWS.help for information about editing NEWS using ReST.) @@ -11,6 +12,9 @@ Core and Builtins ----------------- +- Fix a segfault when running test_exceptions with coverage, caused by + insufficient checks in accessors of Exception.__context__. + - Issue #5604: non-ASCII characters in module name passed to imp.find_module() were converted to UTF-8 while the path is converted to the default filesystem encoding, causing nonsense. Modified: python/branches/py3k/Objects/exceptions.c ============================================================================== --- python/branches/py3k/Objects/exceptions.c (original) +++ python/branches/py3k/Objects/exceptions.c Tue Mar 31 06:16:10 2009 @@ -250,11 +250,67 @@ return 0; } +static PyObject * +BaseException_get_context(PyObject *self) { + PyObject *res = PyException_GetContext(self); + if (res) return res; /* new reference already returned above */ + Py_RETURN_NONE; +} + +static int +BaseException_set_context(PyObject *self, PyObject *arg) { + if (arg == NULL) { + PyErr_SetString(PyExc_TypeError, "__context__ may not be deleted"); + return -1; + } else if (arg == Py_None) { + arg = NULL; + } else if (!PyExceptionInstance_Check(arg)) { + PyErr_SetString(PyExc_TypeError, "exception context must be None " + "or derive from BaseException"); + return -1; + } else { + /* PyException_SetContext steals this reference */ + Py_INCREF(arg); + } + PyException_SetContext(self, arg); + return 0; +} + +static PyObject * +BaseException_get_cause(PyObject *self) { + PyObject *res = PyException_GetCause(self); + if (res) return res; /* new reference already returned above */ + Py_RETURN_NONE; +} + +static int +BaseException_set_cause(PyObject *self, PyObject *arg) { + if (arg == NULL) { + PyErr_SetString(PyExc_TypeError, "__cause__ may not be deleted"); + return -1; + } else if (arg == Py_None) { + arg = NULL; + } else if (!PyExceptionInstance_Check(arg)) { + PyErr_SetString(PyExc_TypeError, "exception cause must be None " + "or derive from BaseException"); + return -1; + } else { + /* PyException_SetCause steals this reference */ + Py_INCREF(arg); + } + PyException_SetCause(self, arg); + return 0; +} + static PyGetSetDef BaseException_getset[] = { {"__dict__", (getter)BaseException_get_dict, (setter)BaseException_set_dict}, {"args", (getter)BaseException_get_args, (setter)BaseException_set_args}, {"__traceback__", (getter)BaseException_get_tb, (setter)BaseException_set_tb}, + {"__context__", (getter)BaseException_get_context, + (setter)BaseException_set_context, PyDoc_STR("exception context")}, + {"__cause__", (getter)BaseException_get_cause, + (setter)BaseException_set_cause, PyDoc_STR("exception cause")}, {NULL}, }; @@ -303,14 +359,6 @@ } -static PyMemberDef BaseException_members[] = { - {"__context__", T_OBJECT, offsetof(PyBaseExceptionObject, context), 0, - PyDoc_STR("exception context")}, - {"__cause__", T_OBJECT, offsetof(PyBaseExceptionObject, cause), 0, - PyDoc_STR("exception cause")}, - {NULL} /* Sentinel */ -}; - static PyTypeObject _PyExc_BaseException = { PyVarObject_HEAD_INIT(NULL, 0) "BaseException", /*tp_name*/ @@ -341,7 +389,7 @@ 0, /* tp_iter */ 0, /* tp_iternext */ BaseException_methods, /* tp_methods */ - BaseException_members, /* tp_members */ + 0, /* tp_members */ BaseException_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ From buildbot at python.org Tue Mar 31 06:32:26 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 04:32:26 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu trunk Message-ID: <20090331043226.B4F7E1E402E@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%20trunk/builds/1177 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: andrew.kuchling,barry.warsaw,georg.brandl,jesse.noller,martin.v.loewis,r.david.murray,ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_ssl make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 31 06:41:16 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 04:41:16 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 2.6 Message-ID: <20090331044117.4C7571E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%202.6/builds/202 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: jesse.noller BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_ssl make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 31 07:04:50 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 05:04:50 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090331050450.F116C1E4002@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/477 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: barry.warsaw,georg.brandl,ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_time make: *** [buildbottest] Error 1 sincerely, -The Buildbot From buildbot at python.org Tue Mar 31 07:45:02 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 05:45:02 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090331054502.6A2EE1E4002@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/551 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: brett.cannon,georg.brandl BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Tue Mar 31 08:54:44 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 06:54:44 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 2.6 Message-ID: <20090331065447.221131E4019@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%202.6/builds/196 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: jesse.noller BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bsddb3 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 11:58:20 2009 From: python-checkins at python.org (eric.smith) Date: Tue, 31 Mar 2009 11:58:20 +0200 (CEST) Subject: [Python-checkins] r70798 - in python/branches/py3k-short-float-repr: Objects/floatobject.c Python/marshal.c Message-ID: <20090331095820.54A991E4002@bag.python.org> Author: eric.smith Date: Tue Mar 31 11:58:18 2009 New Revision: 70798 Log: Removed _PyFloat_Repr, which existed only for marshal. Have marshal format its strings directly. I need to verify this chchange with Mark. This change is also problematic (and currently incomplete) because marshal assumes that float->string conversions can never fail, but the new code calls malloc, so it is possible that it will fail. That surgery on marshal is pretty severe, though, so it will have to wait for another day. Modified: python/branches/py3k-short-float-repr/Objects/floatobject.c python/branches/py3k-short-float-repr/Python/marshal.c Modified: python/branches/py3k-short-float-repr/Objects/floatobject.c ============================================================================== --- python/branches/py3k-short-float-repr/Objects/floatobject.c (original) +++ python/branches/py3k-short-float-repr/Objects/floatobject.c Tue Mar 31 11:58:18 2009 @@ -320,65 +320,6 @@ return val; } -/* Methods */ - -static void -format_double(char *buf, size_t buflen, double ob_fval, int precision) -{ - register char *cp; - char format[32]; - int i; - - /* Subroutine for float_repr, float_str and float_print. - We want float numbers to be recognizable as such, - i.e., they should contain a decimal point or an exponent. - However, %g may print the number as an integer; - in such cases, we append ".0" to the string. */ - - PyOS_snprintf(format, 32, "%%.%ig", precision); - PyOS_ascii_formatd(buf, buflen, format, ob_fval); - cp = buf; - if (*cp == '-') - cp++; - for (; *cp != '\0'; cp++) { - /* Any non-digit means it's not an integer; - this takes care of NAN and INF as well. */ - if (!isdigit(Py_CHARMASK(*cp))) - break; - } - if (*cp == '\0') { - *cp++ = '.'; - *cp++ = '0'; - *cp++ = '\0'; - return; - } - /* Checking the next three chars should be more than enough to - * detect inf or nan, even on Windows. We check for inf or nan - * at last because they are rare cases. - */ - for (i=0; *cp != '\0' && i<3; cp++, i++) { - if (isdigit(Py_CHARMASK(*cp)) || *cp == '.') - continue; - /* found something that is neither a digit nor point - * it might be a NaN or INF - */ -#ifdef Py_NAN - if (Py_IS_NAN(ob_fval)) { - strcpy(buf, "nan"); - } - else -#endif - if (Py_IS_INFINITY(ob_fval)) { - cp = buf; - if (*cp == '-') - cp++; - strcpy(cp, "inf"); - } - break; - } - -} - /* Macro and helper that convert PyObject obj to a C double and store the value in dbl. If conversion to double raises an exception, obj is set to NULL, and the function invoking this macro returns NULL. If @@ -391,6 +332,8 @@ else if (convert_to_double(&(obj), &(dbl)) < 0) \ return obj; +/* Methods */ + static int convert_to_double(PyObject **v, double *dbl) { @@ -411,13 +354,7 @@ return 0; } -/* Precisions used by repr() and str(), respectively. - - The repr() precision (17 significant decimal digits) is the minimal number - that is guaranteed to have enough precision so that if the number is read - back in the exact same binary value is recreated. This is true for IEEE - floating point by design, and also happens to work for all other modern - hardware. +/* Precision used by str(). The str() precision is chosen so that in most cases, the rounding noise created by various operations is suppressed, while giving plenty of @@ -425,7 +362,6 @@ */ -#define PREC_REPR 17 #define PREC_STR 12 static PyObject * @@ -2238,14 +2174,6 @@ } } -/* Should only be used by marshal. */ -int -_PyFloat_Repr(double x, char *p, size_t len) -{ - format_double(p, len, x, PREC_REPR); - return (int)strlen(p); -} - double _PyFloat_Unpack4(const unsigned char *p, int le) { Modified: python/branches/py3k-short-float-repr/Python/marshal.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/marshal.c (original) +++ python/branches/py3k-short-float-repr/Python/marshal.c Tue Mar 31 11:58:18 2009 @@ -236,12 +236,15 @@ w_string((char*)buf, 8, p); } else { - char buf[256]; /* Plenty to format any double */ - n = _PyFloat_Repr(PyFloat_AS_DOUBLE(v), - buf, sizeof(buf)); + char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v), + 0, 'g', 0, 0, 1); + if (!buf) + return; + n = strlen(buf); w_byte(TYPE_FLOAT, p); w_byte((int)n, p); w_string(buf, (int)n, p); + PyMem_Free(buf); } } #ifndef WITHOUT_COMPLEX @@ -263,17 +266,24 @@ w_string((char*)buf, 8, p); } else { - char buf[256]; /* Plenty to format any double */ + char *buf; w_byte(TYPE_COMPLEX, p); - n = _PyFloat_Repr(PyComplex_RealAsDouble(v), - buf, sizeof(buf)); + buf = PyOS_double_to_string(PyComplex_RealAsDouble(v), + 0, 'g', 0, 0, 1); + if (!buf) + return; n = strlen(buf); w_byte((int)n, p); w_string(buf, (int)n, p); - n = _PyFloat_Repr(PyComplex_ImagAsDouble(v), - buf, sizeof(buf)); + PyMem_Free(buf); + buf = PyOS_double_to_string(PyComplex_ImagAsDouble(v), + 0, 'g', 0, 0, 1); + if (!buf) + return; + n = strlen(buf); w_byte((int)n, p); w_string(buf, (int)n, p); + PyMem_Free(buf); } } #endif From buildbot at python.org Tue Mar 31 12:50:59 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 10:50:59 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 3.x Message-ID: <20090331105059.9C7F51E400C@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%203.x/builds/479 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: The web-page 'force build' button was pressed by 'Eric Smith': Test repr change branch Build Source Stamp: [branch branches/py3k-short-float-repr] HEAD Blamelist: BUILD FAILED: failed svn sincerely, -The Buildbot From buildbot at python.org Tue Mar 31 12:54:02 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 10:54:02 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090331105402.6441D1E4002@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/592 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: The web-page 'force build' button was pressed by 'Eric Smith': Test repr change branch Build Source Stamp: [branch branches/py3k-short-float-repr] HEAD Blamelist: BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From buildbot at python.org Tue Mar 31 13:37:02 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 11:37:02 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090331113703.01E621E4013@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/522 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: The web-page 'force build' button was pressed by 'Eric Smith': Test repr change branch Build Source Stamp: [branch branches/py3k-short-float-repr] HEAD Blamelist: BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 15:08:12 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 31 Mar 2009 15:08:12 +0200 (CEST) Subject: [Python-checkins] r70799 - python/branches/py3k-short-float-repr/Python/pystrtod.c Message-ID: <20090331130812.EE28E1E4002@bag.python.org> Author: mark.dickinson Date: Tue Mar 31 15:08:12 2009 New Revision: 70799 Log: Add some debugging code for IA64 buildbot failure. Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/pystrtod.c (original) +++ python/branches/py3k-short-float-repr/Python/pystrtod.c Tue Mar 31 15:08:12 2009 @@ -520,11 +520,19 @@ } strncpy(buf, "inf", 3); buf += 3; - } else { - assert(digits[0] == 'n' || digits[0] == 'N'); + } + else if (digits[0] == 'n' || digits[0] == 'N') { strncpy(buf, "nan", 3); buf += 3; } + else { + /* shouldn't get here: Gay's code should always return + something starting with a digit, an 'I', or an + 'N' */ + printf("Help! dtoa returned: %.*s\n", + (int)digits_len, digits); + assert(0); + } } else if (-4 < decpt && decpt <= 17) { if (sign == 1) { From python-checkins at python.org Tue Mar 31 15:13:05 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 31 Mar 2009 15:13:05 +0200 (CEST) Subject: [Python-checkins] r70800 - in python/trunk: Lib/test/test_mmap.py Misc/NEWS Modules/mmapmodule.c Message-ID: <20090331131305.A4DDC1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 31 15:13:05 2009 New Revision: 70800 Log: Issue #5387: Fixed mmap.move crash by integer overflow. Modified: python/trunk/Lib/test/test_mmap.py python/trunk/Misc/NEWS python/trunk/Modules/mmapmodule.c Modified: python/trunk/Lib/test/test_mmap.py ============================================================================== --- python/trunk/Lib/test/test_mmap.py (original) +++ python/trunk/Lib/test/test_mmap.py Tue Mar 31 15:13:05 2009 @@ -339,6 +339,23 @@ mf.close() f.close() + # more excessive test + data = "0123456789" + for dest in range(len(data)): + for src in range(len(data)): + for count in range(len(data) - max(dest, src)): + expected = data[:dest] + data[src:src+count] + data[dest+count:] + m = mmap.mmap(-1, len(data)) + m[:] = data + m.move(dest, src, count) + self.assertEqual(m[:], expected) + m.close() + + # should not crash + m = mmap.mmap(-1, 1) + self.assertRaises(ValueError, m.move, 1, 1, -1) + m.close() + def test_anonymous(self): # anonymous mmap.mmap(-1, PAGE) m = mmap.mmap(-1, PAGESIZE) Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 31 15:13:05 2009 @@ -199,6 +199,8 @@ Library ------- +- Issue #5387: Fixed mmap.move crash by integer overflow. + - Issue #5261: Patch multiprocessing's semaphore.c to support context manager use: "with multiprocessing.Lock()" works now. Modified: python/trunk/Modules/mmapmodule.c ============================================================================== --- python/trunk/Modules/mmapmodule.c (original) +++ python/trunk/Modules/mmapmodule.c Tue Mar 31 15:13:05 2009 @@ -612,10 +612,8 @@ return NULL; } else { /* bounds check the values */ - if (/* end of source after end of data?? */ - ((src+count) > self->size) - /* dest will fit? */ - || (dest+count > self->size)) { + unsigned long pos = src > dest ? src : dest; + if (self->size >= pos && count > self->size - pos) { PyErr_SetString(PyExc_ValueError, "source or destination out of range"); return NULL; From python-checkins at python.org Tue Mar 31 15:17:03 2009 From: python-checkins at python.org (jeremy.hylton) Date: Tue, 31 Mar 2009 15:17:03 +0200 (CEST) Subject: [Python-checkins] r70801 - in python/trunk/Lib: symtable.py test/test_symtable.py Message-ID: <20090331131703.BDD941E4002@bag.python.org> Author: jeremy.hylton Date: Tue Mar 31 15:17:03 2009 New Revision: 70801 Log: Add is_declared_global() which distinguishes between implicit and explicit global variables. Modified: python/trunk/Lib/symtable.py python/trunk/Lib/test/test_symtable.py Modified: python/trunk/Lib/symtable.py ============================================================================== --- python/trunk/Lib/symtable.py (original) +++ python/trunk/Lib/symtable.py Tue Mar 31 15:17:03 2009 @@ -190,6 +190,9 @@ def is_global(self): return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)) + def is_declared_global(self): + return bool(self.__scope == GLOBAL_EXPLICIT) + def is_local(self): return bool(self.__flags & DEF_BOUND) Modified: python/trunk/Lib/test/test_symtable.py ============================================================================== --- python/trunk/Lib/test/test_symtable.py (original) +++ python/trunk/Lib/test/test_symtable.py Tue Mar 31 15:17:03 2009 @@ -98,7 +98,9 @@ def test_globals(self): self.assertTrue(self.spam.lookup("glob").is_global()) + self.assertFalse(self.spam.lookup("glob").is_declared_global()) self.assertTrue(self.spam.lookup("bar").is_global()) + self.assertTrue(self.spam.lookup("bar").is_declared_global()) self.assertFalse(self.internal.lookup("x").is_global()) self.assertFalse(self.Mine.lookup("instance_var").is_global()) From python-checkins at python.org Tue Mar 31 15:20:45 2009 From: python-checkins at python.org (ronald.oussoren) Date: Tue, 31 Mar 2009 15:20:45 +0200 (CEST) Subject: [Python-checkins] r70802 - python/trunk/Mac/BuildScript/build-installer.py Message-ID: <20090331132045.8C93F1E4011@bag.python.org> Author: ronald.oussoren Date: Tue Mar 31 15:20:45 2009 New Revision: 70802 Log: Minor update to OSX build-installer script, needed to ensure that the build will succeed in a clean checkout and with a non-default deployment target. Modified: python/trunk/Mac/BuildScript/build-installer.py Modified: python/trunk/Mac/BuildScript/build-installer.py ============================================================================== --- python/trunk/Mac/BuildScript/build-installer.py (original) +++ python/trunk/Mac/BuildScript/build-installer.py Tue Mar 31 15:20:45 2009 @@ -1018,7 +1018,18 @@ # Now build python itself buildPython() + + # And then build the documentation + # Remove the Deployment Target from the shell + # environment, it's no longer needed and + # an unexpected build target can cause problems + # when Sphinx and its dependencies need to + # be (re-)installed. + del os.environ['MACOSX_DEPLOYMENT_TARGET'] buildPythonDocs() + + + # Prepare the applications folder fn = os.path.join(WORKDIR, "_root", "Applications", "Python %s"%(getVersion(),), "Update Shell Profile.command") patchScript("scripts/postflight.patch-profile", fn) From buildbot at python.org Tue Mar 31 15:21:51 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 13:21:51 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.0 Message-ID: <20090331132151.9E4641E4002@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.0/builds/235 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: benjamin.peterson,guido.van.rossum BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/test/support.py", line 98, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.0.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.0.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 15:22:02 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 31 Mar 2009 15:22:02 +0200 (CEST) Subject: [Python-checkins] r70803 - in python/branches/release26-maint: Lib/test/test_mmap.py Misc/NEWS Modules/mmapmodule.c Message-ID: <20090331132202.278A81E4002@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 31 15:22:01 2009 New Revision: 70803 Log: Merged revisions 70800 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70800 | hirokazu.yamamoto | 2009-03-31 22:13:05 +0900 | 1 line Issue #5387: Fixed mmap.move crash by integer overflow. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_mmap.py python/branches/release26-maint/Misc/NEWS python/branches/release26-maint/Modules/mmapmodule.c Modified: python/branches/release26-maint/Lib/test/test_mmap.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_mmap.py (original) +++ python/branches/release26-maint/Lib/test/test_mmap.py Tue Mar 31 15:22:01 2009 @@ -338,6 +338,23 @@ mf.close() f.close() + # more excessive test + data = "0123456789" + for dest in range(len(data)): + for src in range(len(data)): + for count in range(len(data) - max(dest, src)): + expected = data[:dest] + data[src:src+count] + data[dest+count:] + m = mmap.mmap(-1, len(data)) + m[:] = data + m.move(dest, src, count) + self.assertEqual(m[:], expected) + m.close() + + # should not crash + m = mmap.mmap(-1, 1) + self.assertRaises(ValueError, m.move, 1, 1, -1) + m.close() + def test_anonymous(self): # anonymous mmap.mmap(-1, PAGE) m = mmap.mmap(-1, PAGESIZE) Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Tue Mar 31 15:22:01 2009 @@ -92,6 +92,8 @@ Library ------- +- Issue #5387: Fixed mmap.move crash by integer overflow. + - Issue #5261: Patch multiprocessing's semaphore.c to support context manager use: "with multiprocessing.Lock()" works now. Modified: python/branches/release26-maint/Modules/mmapmodule.c ============================================================================== --- python/branches/release26-maint/Modules/mmapmodule.c (original) +++ python/branches/release26-maint/Modules/mmapmodule.c Tue Mar 31 15:22:01 2009 @@ -612,10 +612,8 @@ return NULL; } else { /* bounds check the values */ - if (/* end of source after end of data?? */ - ((src+count) > self->size) - /* dest will fit? */ - || (dest+count > self->size)) { + unsigned long pos = src > dest ? src : dest; + if (self->size >= pos && count > self->size - pos) { PyErr_SetString(PyExc_ValueError, "source or destination out of range"); return NULL; From python-checkins at python.org Tue Mar 31 15:23:26 2009 From: python-checkins at python.org (ronald.oussoren) Date: Tue, 31 Mar 2009 15:23:26 +0200 (CEST) Subject: [Python-checkins] r70804 - in python/branches/release26-maint: Mac/BuildScript/build-installer.py Message-ID: <20090331132326.732401E4002@bag.python.org> Author: ronald.oussoren Date: Tue Mar 31 15:23:26 2009 New Revision: 70804 Log: Merged revisions 70802 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70802 | ronald.oussoren | 2009-03-31 08:20:45 -0500 (Tue, 31 Mar 2009) | 4 lines Minor update to OSX build-installer script, needed to ensure that the build will succeed in a clean checkout and with a non-default deployment target. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Mac/BuildScript/build-installer.py Modified: python/branches/release26-maint/Mac/BuildScript/build-installer.py ============================================================================== --- python/branches/release26-maint/Mac/BuildScript/build-installer.py (original) +++ python/branches/release26-maint/Mac/BuildScript/build-installer.py Tue Mar 31 15:23:26 2009 @@ -1018,7 +1018,18 @@ # Now build python itself buildPython() + + # And then build the documentation + # Remove the Deployment Target from the shell + # environment, it's no longer needed and + # an unexpected build target can cause problems + # when Sphinx and its dependencies need to + # be (re-)installed. + del os.environ['MACOSX_DEPLOYMENT_TARGET'] buildPythonDocs() + + + # Prepare the applications folder fn = os.path.join(WORKDIR, "_root", "Applications", "Python %s"%(getVersion(),), "Update Shell Profile.command") patchScript("scripts/postflight.patch-profile", fn) From python-checkins at python.org Tue Mar 31 15:24:23 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 31 Mar 2009 15:24:23 +0200 (CEST) Subject: [Python-checkins] r70805 - in python/branches/py3k-short-float-repr/Lib/test: test_multiprocessing.py xtest_multiprocessing.py Message-ID: <20090331132423.C71E21E4002@bag.python.org> Author: mark.dickinson Date: Tue Mar 31 15:24:23 2009 New Revision: 70805 Log: Temporarily rename test_multiprocessing, to allow test-suite to run Added: python/branches/py3k-short-float-repr/Lib/test/xtest_multiprocessing.py - copied unchanged from r70804, /python/branches/py3k-short-float-repr/Lib/test/test_multiprocessing.py Removed: python/branches/py3k-short-float-repr/Lib/test/test_multiprocessing.py Deleted: python/branches/py3k-short-float-repr/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/py3k-short-float-repr/Lib/test/test_multiprocessing.py Tue Mar 31 15:24:23 2009 +++ (empty file) @@ -1,1877 +0,0 @@ -#!/usr/bin/env python - -# -# Unit tests for the multiprocessing package -# - -import unittest -import threading -import queue as pyqueue -import time -import sys -import os -import gc -import signal -import array -import copy -import socket -import random -import logging - - -# Work around broken sem_open implementations -try: - import multiprocessing.synchronize -except ImportError as e: - raise unittest.SkipTest(e) - -import multiprocessing.dummy -import multiprocessing.connection -import multiprocessing.managers -import multiprocessing.heap -import multiprocessing.pool -import _multiprocessing - -from multiprocessing import util - -# -# -# - -def latin(s): - return s.encode('latin') - -# -# Constants -# - -LOG_LEVEL = util.SUBWARNING -#LOG_LEVEL = logging.WARNING - -DELTA = 0.1 -CHECK_TIMINGS = False # making true makes tests take a lot longer - # and can sometimes cause some non-serious - # failures because some calls block a bit - # longer than expected -if CHECK_TIMINGS: - TIMEOUT1, TIMEOUT2, TIMEOUT3 = 0.82, 0.35, 1.4 -else: - TIMEOUT1, TIMEOUT2, TIMEOUT3 = 0.1, 0.1, 0.1 - -HAVE_GETVALUE = not getattr(_multiprocessing, - 'HAVE_BROKEN_SEM_GETVALUE', False) - -WIN32 = (sys.platform == "win32") - -# -# Creates a wrapper for a function which records the time it takes to finish -# - -class TimingWrapper(object): - - def __init__(self, func): - self.func = func - self.elapsed = None - - def __call__(self, *args, **kwds): - t = time.time() - try: - return self.func(*args, **kwds) - finally: - self.elapsed = time.time() - t - -# -# Base class for test cases -# - -class BaseTestCase(object): - - ALLOWED_TYPES = ('processes', 'manager', 'threads') - - def assertTimingAlmostEqual(self, a, b): - if CHECK_TIMINGS: - self.assertAlmostEqual(a, b, 1) - - def assertReturnsIfImplemented(self, value, func, *args): - try: - res = func(*args) - except NotImplementedError: - pass - else: - return self.assertEqual(value, res) - -# -# Return the value of a semaphore -# - -def get_value(self): - try: - return self.get_value() - except AttributeError: - try: - return self._Semaphore__value - except AttributeError: - try: - return self._value - except AttributeError: - raise NotImplementedError - -# -# Testcases -# - -class _TestProcess(BaseTestCase): - - ALLOWED_TYPES = ('processes', 'threads') - - def test_current(self): - if self.TYPE == 'threads': - return - - current = self.current_process() - authkey = current.authkey - - self.assertTrue(current.is_alive()) - self.assertTrue(not current.daemon) - self.assertTrue(isinstance(authkey, bytes)) - self.assertTrue(len(authkey) > 0) - self.assertEqual(current.ident, os.getpid()) - self.assertEqual(current.exitcode, None) - - def _test(self, q, *args, **kwds): - current = self.current_process() - q.put(args) - q.put(kwds) - q.put(current.name) - if self.TYPE != 'threads': - q.put(bytes(current.authkey)) - q.put(current.pid) - - def test_process(self): - q = self.Queue(1) - e = self.Event() - args = (q, 1, 2) - kwargs = {'hello':23, 'bye':2.54} - name = 'SomeProcess' - p = self.Process( - target=self._test, args=args, kwargs=kwargs, name=name - ) - p.daemon = True - current = self.current_process() - - if self.TYPE != 'threads': - self.assertEquals(p.authkey, current.authkey) - self.assertEquals(p.is_alive(), False) - self.assertEquals(p.daemon, True) - self.assertTrue(p not in self.active_children()) - self.assertTrue(type(self.active_children()) is list) - self.assertEqual(p.exitcode, None) - - p.start() - - self.assertEquals(p.exitcode, None) - self.assertEquals(p.is_alive(), True) - self.assertTrue(p in self.active_children()) - - self.assertEquals(q.get(), args[1:]) - self.assertEquals(q.get(), kwargs) - self.assertEquals(q.get(), p.name) - if self.TYPE != 'threads': - self.assertEquals(q.get(), current.authkey) - self.assertEquals(q.get(), p.pid) - - p.join() - - self.assertEquals(p.exitcode, 0) - self.assertEquals(p.is_alive(), False) - self.assertTrue(p not in self.active_children()) - - def _test_terminate(self): - time.sleep(1000) - - def test_terminate(self): - if self.TYPE == 'threads': - return - - p = self.Process(target=self._test_terminate) - p.daemon = True - p.start() - - self.assertEqual(p.is_alive(), True) - self.assertTrue(p in self.active_children()) - self.assertEqual(p.exitcode, None) - - p.terminate() - - join = TimingWrapper(p.join) - self.assertEqual(join(), None) - self.assertTimingAlmostEqual(join.elapsed, 0.0) - - self.assertEqual(p.is_alive(), False) - self.assertTrue(p not in self.active_children()) - - p.join() - - # XXX sometimes get p.exitcode == 0 on Windows ... - #self.assertEqual(p.exitcode, -signal.SIGTERM) - - def test_cpu_count(self): - try: - cpus = multiprocessing.cpu_count() - except NotImplementedError: - cpus = 1 - self.assertTrue(type(cpus) is int) - self.assertTrue(cpus >= 1) - - def test_active_children(self): - self.assertEqual(type(self.active_children()), list) - - p = self.Process(target=time.sleep, args=(DELTA,)) - self.assertTrue(p not in self.active_children()) - - p.start() - self.assertTrue(p in self.active_children()) - - p.join() - self.assertTrue(p not in self.active_children()) - - def _test_recursion(self, wconn, id): - from multiprocessing import forking - wconn.send(id) - if len(id) < 2: - for i in range(2): - p = self.Process( - target=self._test_recursion, args=(wconn, id+[i]) - ) - p.start() - p.join() - - def test_recursion(self): - rconn, wconn = self.Pipe(duplex=False) - self._test_recursion(wconn, []) - - time.sleep(DELTA) - result = [] - while rconn.poll(): - result.append(rconn.recv()) - - expected = [ - [], - [0], - [0, 0], - [0, 1], - [1], - [1, 0], - [1, 1] - ] - self.assertEqual(result, expected) - -# -# -# - -class _UpperCaser(multiprocessing.Process): - - def __init__(self): - multiprocessing.Process.__init__(self) - self.child_conn, self.parent_conn = multiprocessing.Pipe() - - def run(self): - self.parent_conn.close() - for s in iter(self.child_conn.recv, None): - self.child_conn.send(s.upper()) - self.child_conn.close() - - def submit(self, s): - assert type(s) is str - self.parent_conn.send(s) - return self.parent_conn.recv() - - def stop(self): - self.parent_conn.send(None) - self.parent_conn.close() - self.child_conn.close() - -class _TestSubclassingProcess(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def test_subclassing(self): - uppercaser = _UpperCaser() - uppercaser.start() - self.assertEqual(uppercaser.submit('hello'), 'HELLO') - self.assertEqual(uppercaser.submit('world'), 'WORLD') - uppercaser.stop() - uppercaser.join() - -# -# -# - -def queue_empty(q): - if hasattr(q, 'empty'): - return q.empty() - else: - return q.qsize() == 0 - -def queue_full(q, maxsize): - if hasattr(q, 'full'): - return q.full() - else: - return q.qsize() == maxsize - - -class _TestQueue(BaseTestCase): - - - def _test_put(self, queue, child_can_start, parent_can_continue): - child_can_start.wait() - for i in range(6): - queue.get() - parent_can_continue.set() - - def test_put(self): - MAXSIZE = 6 - queue = self.Queue(maxsize=MAXSIZE) - child_can_start = self.Event() - parent_can_continue = self.Event() - - proc = self.Process( - target=self._test_put, - args=(queue, child_can_start, parent_can_continue) - ) - proc.daemon = True - proc.start() - - self.assertEqual(queue_empty(queue), True) - self.assertEqual(queue_full(queue, MAXSIZE), False) - - queue.put(1) - queue.put(2, True) - queue.put(3, True, None) - queue.put(4, False) - queue.put(5, False, None) - queue.put_nowait(6) - - # the values may be in buffer but not yet in pipe so sleep a bit - time.sleep(DELTA) - - self.assertEqual(queue_empty(queue), False) - self.assertEqual(queue_full(queue, MAXSIZE), True) - - put = TimingWrapper(queue.put) - put_nowait = TimingWrapper(queue.put_nowait) - - self.assertRaises(pyqueue.Full, put, 7, False) - self.assertTimingAlmostEqual(put.elapsed, 0) - - self.assertRaises(pyqueue.Full, put, 7, False, None) - self.assertTimingAlmostEqual(put.elapsed, 0) - - self.assertRaises(pyqueue.Full, put_nowait, 7) - self.assertTimingAlmostEqual(put_nowait.elapsed, 0) - - self.assertRaises(pyqueue.Full, put, 7, True, TIMEOUT1) - self.assertTimingAlmostEqual(put.elapsed, TIMEOUT1) - - self.assertRaises(pyqueue.Full, put, 7, False, TIMEOUT2) - self.assertTimingAlmostEqual(put.elapsed, 0) - - self.assertRaises(pyqueue.Full, put, 7, True, timeout=TIMEOUT3) - self.assertTimingAlmostEqual(put.elapsed, TIMEOUT3) - - child_can_start.set() - parent_can_continue.wait() - - self.assertEqual(queue_empty(queue), True) - self.assertEqual(queue_full(queue, MAXSIZE), False) - - proc.join() - - def _test_get(self, queue, child_can_start, parent_can_continue): - child_can_start.wait() - #queue.put(1) - queue.put(2) - queue.put(3) - queue.put(4) - queue.put(5) - parent_can_continue.set() - - def test_get(self): - queue = self.Queue() - child_can_start = self.Event() - parent_can_continue = self.Event() - - proc = self.Process( - target=self._test_get, - args=(queue, child_can_start, parent_can_continue) - ) - proc.daemon = True - proc.start() - - self.assertEqual(queue_empty(queue), True) - - child_can_start.set() - parent_can_continue.wait() - - time.sleep(DELTA) - self.assertEqual(queue_empty(queue), False) - - # Hangs unexpectedly, remove for now - #self.assertEqual(queue.get(), 1) - self.assertEqual(queue.get(True, None), 2) - self.assertEqual(queue.get(True), 3) - self.assertEqual(queue.get(timeout=1), 4) - self.assertEqual(queue.get_nowait(), 5) - - self.assertEqual(queue_empty(queue), True) - - get = TimingWrapper(queue.get) - get_nowait = TimingWrapper(queue.get_nowait) - - self.assertRaises(pyqueue.Empty, get, False) - self.assertTimingAlmostEqual(get.elapsed, 0) - - self.assertRaises(pyqueue.Empty, get, False, None) - self.assertTimingAlmostEqual(get.elapsed, 0) - - self.assertRaises(pyqueue.Empty, get_nowait) - self.assertTimingAlmostEqual(get_nowait.elapsed, 0) - - self.assertRaises(pyqueue.Empty, get, True, TIMEOUT1) - self.assertTimingAlmostEqual(get.elapsed, TIMEOUT1) - - self.assertRaises(pyqueue.Empty, get, False, TIMEOUT2) - self.assertTimingAlmostEqual(get.elapsed, 0) - - self.assertRaises(pyqueue.Empty, get, timeout=TIMEOUT3) - self.assertTimingAlmostEqual(get.elapsed, TIMEOUT3) - - proc.join() - - def _test_fork(self, queue): - for i in range(10, 20): - queue.put(i) - # note that at this point the items may only be buffered, so the - # process cannot shutdown until the feeder thread has finished - # pushing items onto the pipe. - - def test_fork(self): - # Old versions of Queue would fail to create a new feeder - # thread for a forked process if the original process had its - # own feeder thread. This test checks that this no longer - # happens. - - queue = self.Queue() - - # put items on queue so that main process starts a feeder thread - for i in range(10): - queue.put(i) - - # wait to make sure thread starts before we fork a new process - time.sleep(DELTA) - - # fork process - p = self.Process(target=self._test_fork, args=(queue,)) - p.start() - - # check that all expected items are in the queue - for i in range(20): - self.assertEqual(queue.get(), i) - self.assertRaises(pyqueue.Empty, queue.get, False) - - p.join() - - def test_qsize(self): - q = self.Queue() - try: - self.assertEqual(q.qsize(), 0) - except NotImplementedError: - return - q.put(1) - self.assertEqual(q.qsize(), 1) - q.put(5) - self.assertEqual(q.qsize(), 2) - q.get() - self.assertEqual(q.qsize(), 1) - q.get() - self.assertEqual(q.qsize(), 0) - - def _test_task_done(self, q): - for obj in iter(q.get, None): - time.sleep(DELTA) - q.task_done() - - def test_task_done(self): - queue = self.JoinableQueue() - - if sys.version_info < (2, 5) and not hasattr(queue, 'task_done'): - return - - workers = [self.Process(target=self._test_task_done, args=(queue,)) - for i in range(4)] - - for p in workers: - p.start() - - for i in range(10): - queue.put(i) - - queue.join() - - for p in workers: - queue.put(None) - - for p in workers: - p.join() - -# -# -# - -class _TestLock(BaseTestCase): - - def test_lock(self): - lock = self.Lock() - self.assertEqual(lock.acquire(), True) - self.assertEqual(lock.acquire(False), False) - self.assertEqual(lock.release(), None) - self.assertRaises((ValueError, threading.ThreadError), lock.release) - - def test_rlock(self): - lock = self.RLock() - self.assertEqual(lock.acquire(), True) - self.assertEqual(lock.acquire(), True) - self.assertEqual(lock.acquire(), True) - self.assertEqual(lock.release(), None) - self.assertEqual(lock.release(), None) - self.assertEqual(lock.release(), None) - self.assertRaises((AssertionError, RuntimeError), lock.release) - - -class _TestSemaphore(BaseTestCase): - - def _test_semaphore(self, sem): - self.assertReturnsIfImplemented(2, get_value, sem) - self.assertEqual(sem.acquire(), True) - self.assertReturnsIfImplemented(1, get_value, sem) - self.assertEqual(sem.acquire(), True) - self.assertReturnsIfImplemented(0, get_value, sem) - self.assertEqual(sem.acquire(False), False) - self.assertReturnsIfImplemented(0, get_value, sem) - self.assertEqual(sem.release(), None) - self.assertReturnsIfImplemented(1, get_value, sem) - self.assertEqual(sem.release(), None) - self.assertReturnsIfImplemented(2, get_value, sem) - - def test_semaphore(self): - sem = self.Semaphore(2) - self._test_semaphore(sem) - self.assertEqual(sem.release(), None) - self.assertReturnsIfImplemented(3, get_value, sem) - self.assertEqual(sem.release(), None) - self.assertReturnsIfImplemented(4, get_value, sem) - - def test_bounded_semaphore(self): - sem = self.BoundedSemaphore(2) - self._test_semaphore(sem) - # Currently fails on OS/X - #if HAVE_GETVALUE: - # self.assertRaises(ValueError, sem.release) - # self.assertReturnsIfImplemented(2, get_value, sem) - - def test_timeout(self): - if self.TYPE != 'processes': - return - - sem = self.Semaphore(0) - acquire = TimingWrapper(sem.acquire) - - self.assertEqual(acquire(False), False) - self.assertTimingAlmostEqual(acquire.elapsed, 0.0) - - self.assertEqual(acquire(False, None), False) - self.assertTimingAlmostEqual(acquire.elapsed, 0.0) - - self.assertEqual(acquire(False, TIMEOUT1), False) - self.assertTimingAlmostEqual(acquire.elapsed, 0) - - self.assertEqual(acquire(True, TIMEOUT2), False) - self.assertTimingAlmostEqual(acquire.elapsed, TIMEOUT2) - - self.assertEqual(acquire(timeout=TIMEOUT3), False) - self.assertTimingAlmostEqual(acquire.elapsed, TIMEOUT3) - - -class _TestCondition(BaseTestCase): - - def f(self, cond, sleeping, woken, timeout=None): - cond.acquire() - sleeping.release() - cond.wait(timeout) - woken.release() - cond.release() - - def check_invariant(self, cond): - # this is only supposed to succeed when there are no sleepers - if self.TYPE == 'processes': - try: - sleepers = (cond._sleeping_count.get_value() - - cond._woken_count.get_value()) - self.assertEqual(sleepers, 0) - self.assertEqual(cond._wait_semaphore.get_value(), 0) - except NotImplementedError: - pass - - def test_notify(self): - cond = self.Condition() - sleeping = self.Semaphore(0) - woken = self.Semaphore(0) - - p = self.Process(target=self.f, args=(cond, sleeping, woken)) - p.daemon = True - p.start() - - p = threading.Thread(target=self.f, args=(cond, sleeping, woken)) - p.daemon = True - p.start() - - # wait for both children to start sleeping - sleeping.acquire() - sleeping.acquire() - - # check no process/thread has woken up - time.sleep(DELTA) - self.assertReturnsIfImplemented(0, get_value, woken) - - # wake up one process/thread - cond.acquire() - cond.notify() - cond.release() - - # check one process/thread has woken up - time.sleep(DELTA) - self.assertReturnsIfImplemented(1, get_value, woken) - - # wake up another - cond.acquire() - cond.notify() - cond.release() - - # check other has woken up - time.sleep(DELTA) - self.assertReturnsIfImplemented(2, get_value, woken) - - # check state is not mucked up - self.check_invariant(cond) - p.join() - - def test_notify_all(self): - cond = self.Condition() - sleeping = self.Semaphore(0) - woken = self.Semaphore(0) - - # start some threads/processes which will timeout - for i in range(3): - p = self.Process(target=self.f, - args=(cond, sleeping, woken, TIMEOUT1)) - p.daemon = True - p.start() - - t = threading.Thread(target=self.f, - args=(cond, sleeping, woken, TIMEOUT1)) - t.daemon = True - t.start() - - # wait for them all to sleep - for i in range(6): - sleeping.acquire() - - # check they have all timed out - for i in range(6): - woken.acquire() - self.assertReturnsIfImplemented(0, get_value, woken) - - # check state is not mucked up - self.check_invariant(cond) - - # start some more threads/processes - for i in range(3): - p = self.Process(target=self.f, args=(cond, sleeping, woken)) - p.daemon = True - p.start() - - t = threading.Thread(target=self.f, args=(cond, sleeping, woken)) - t.daemon = True - t.start() - - # wait for them to all sleep - for i in range(6): - sleeping.acquire() - - # check no process/thread has woken up - time.sleep(DELTA) - self.assertReturnsIfImplemented(0, get_value, woken) - - # wake them all up - cond.acquire() - cond.notify_all() - cond.release() - - # check they have all woken - time.sleep(DELTA) - self.assertReturnsIfImplemented(6, get_value, woken) - - # check state is not mucked up - self.check_invariant(cond) - - def test_timeout(self): - cond = self.Condition() - wait = TimingWrapper(cond.wait) - cond.acquire() - res = wait(TIMEOUT1) - cond.release() - self.assertEqual(res, None) - self.assertTimingAlmostEqual(wait.elapsed, TIMEOUT1) - - -class _TestEvent(BaseTestCase): - - def _test_event(self, event): - time.sleep(TIMEOUT2) - event.set() - - def test_event(self): - event = self.Event() - wait = TimingWrapper(event.wait) - - # Removed temporaily, due to API shear, this does not - # work with threading._Event objects. is_set == isSet - #self.assertEqual(event.is_set(), False) - - self.assertEqual(wait(0.0), None) - self.assertTimingAlmostEqual(wait.elapsed, 0.0) - self.assertEqual(wait(TIMEOUT1), None) - self.assertTimingAlmostEqual(wait.elapsed, TIMEOUT1) - - event.set() - - # See note above on the API differences - # self.assertEqual(event.is_set(), True) - self.assertEqual(wait(), None) - self.assertTimingAlmostEqual(wait.elapsed, 0.0) - self.assertEqual(wait(TIMEOUT1), None) - self.assertTimingAlmostEqual(wait.elapsed, 0.0) - # self.assertEqual(event.is_set(), True) - - event.clear() - - #self.assertEqual(event.is_set(), False) - - self.Process(target=self._test_event, args=(event,)).start() - self.assertEqual(wait(), None) - -# -# -# - -class _TestValue(BaseTestCase): - - codes_values = [ - ('i', 4343, 24234), - ('d', 3.625, -4.25), - ('h', -232, 234), - ('c', latin('x'), latin('y')) - ] - - def _test(self, values): - for sv, cv in zip(values, self.codes_values): - sv.value = cv[2] - - - def test_value(self, raw=False): - if self.TYPE != 'processes': - return - - if raw: - values = [self.RawValue(code, value) - for code, value, _ in self.codes_values] - else: - values = [self.Value(code, value) - for code, value, _ in self.codes_values] - - for sv, cv in zip(values, self.codes_values): - self.assertEqual(sv.value, cv[1]) - - proc = self.Process(target=self._test, args=(values,)) - proc.start() - proc.join() - - for sv, cv in zip(values, self.codes_values): - self.assertEqual(sv.value, cv[2]) - - def test_rawvalue(self): - self.test_value(raw=True) - - def test_getobj_getlock(self): - if self.TYPE != 'processes': - return - - val1 = self.Value('i', 5) - lock1 = val1.get_lock() - obj1 = val1.get_obj() - - val2 = self.Value('i', 5, lock=None) - lock2 = val2.get_lock() - obj2 = val2.get_obj() - - lock = self.Lock() - val3 = self.Value('i', 5, lock=lock) - lock3 = val3.get_lock() - obj3 = val3.get_obj() - self.assertEqual(lock, lock3) - - arr4 = self.Value('i', 5, lock=False) - self.assertFalse(hasattr(arr4, 'get_lock')) - self.assertFalse(hasattr(arr4, 'get_obj')) - - self.assertRaises(AttributeError, self.Value, 'i', 5, lock='navalue') - - arr5 = self.RawValue('i', 5) - self.assertFalse(hasattr(arr5, 'get_lock')) - self.assertFalse(hasattr(arr5, 'get_obj')) - - -class _TestArray(BaseTestCase): - - def f(self, seq): - for i in range(1, len(seq)): - seq[i] += seq[i-1] - - def test_array(self, raw=False): - if self.TYPE != 'processes': - return - - seq = [680, 626, 934, 821, 150, 233, 548, 982, 714, 831] - if raw: - arr = self.RawArray('i', seq) - else: - arr = self.Array('i', seq) - - self.assertEqual(len(arr), len(seq)) - self.assertEqual(arr[3], seq[3]) - self.assertEqual(list(arr[2:7]), list(seq[2:7])) - - arr[4:8] = seq[4:8] = array.array('i', [1, 2, 3, 4]) - - self.assertEqual(list(arr[:]), seq) - - self.f(seq) - - p = self.Process(target=self.f, args=(arr,)) - p.start() - p.join() - - self.assertEqual(list(arr[:]), seq) - - def test_rawarray(self): - self.test_array(raw=True) - - def test_getobj_getlock_obj(self): - if self.TYPE != 'processes': - return - - arr1 = self.Array('i', list(range(10))) - lock1 = arr1.get_lock() - obj1 = arr1.get_obj() - - arr2 = self.Array('i', list(range(10)), lock=None) - lock2 = arr2.get_lock() - obj2 = arr2.get_obj() - - lock = self.Lock() - arr3 = self.Array('i', list(range(10)), lock=lock) - lock3 = arr3.get_lock() - obj3 = arr3.get_obj() - self.assertEqual(lock, lock3) - - arr4 = self.Array('i', range(10), lock=False) - self.assertFalse(hasattr(arr4, 'get_lock')) - self.assertFalse(hasattr(arr4, 'get_obj')) - self.assertRaises(AttributeError, - self.Array, 'i', range(10), lock='notalock') - - arr5 = self.RawArray('i', range(10)) - self.assertFalse(hasattr(arr5, 'get_lock')) - self.assertFalse(hasattr(arr5, 'get_obj')) - -# -# -# - -class _TestContainers(BaseTestCase): - - ALLOWED_TYPES = ('manager',) - - def test_list(self): - a = self.list(list(range(10))) - self.assertEqual(a[:], list(range(10))) - - b = self.list() - self.assertEqual(b[:], []) - - b.extend(list(range(5))) - self.assertEqual(b[:], list(range(5))) - - self.assertEqual(b[2], 2) - self.assertEqual(b[2:10], [2,3,4]) - - b *= 2 - self.assertEqual(b[:], [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]) - - self.assertEqual(b + [5, 6], [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6]) - - self.assertEqual(a[:], list(range(10))) - - d = [a, b] - e = self.list(d) - self.assertEqual( - e[:], - [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]] - ) - - f = self.list([a]) - a.append('hello') - self.assertEqual(f[:], [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'hello']]) - - def test_dict(self): - d = self.dict() - indices = list(range(65, 70)) - for i in indices: - d[i] = chr(i) - self.assertEqual(d.copy(), dict((i, chr(i)) for i in indices)) - self.assertEqual(sorted(d.keys()), indices) - self.assertEqual(sorted(d.values()), [chr(i) for i in indices]) - self.assertEqual(sorted(d.items()), [(i, chr(i)) for i in indices]) - - def test_namespace(self): - n = self.Namespace() - n.name = 'Bob' - n.job = 'Builder' - n._hidden = 'hidden' - self.assertEqual((n.name, n.job), ('Bob', 'Builder')) - del n.job - self.assertEqual(str(n), "Namespace(name='Bob')") - self.assertTrue(hasattr(n, 'name')) - self.assertTrue(not hasattr(n, 'job')) - -# -# -# - -def sqr(x, wait=0.0): - time.sleep(wait) - return x*x -class _TestPool(BaseTestCase): - - def test_apply(self): - papply = self.pool.apply - self.assertEqual(papply(sqr, (5,)), sqr(5)) - self.assertEqual(papply(sqr, (), {'x':3}), sqr(x=3)) - - def test_map(self): - pmap = self.pool.map - self.assertEqual(pmap(sqr, list(range(10))), list(map(sqr, list(range(10))))) - self.assertEqual(pmap(sqr, list(range(100)), chunksize=20), - list(map(sqr, list(range(100))))) - - def test_async(self): - res = self.pool.apply_async(sqr, (7, TIMEOUT1,)) - get = TimingWrapper(res.get) - self.assertEqual(get(), 49) - self.assertTimingAlmostEqual(get.elapsed, TIMEOUT1) - - def test_async_timeout(self): - res = self.pool.apply_async(sqr, (6, TIMEOUT2 + 0.2)) - get = TimingWrapper(res.get) - self.assertRaises(multiprocessing.TimeoutError, get, timeout=TIMEOUT2) - self.assertTimingAlmostEqual(get.elapsed, TIMEOUT2) - - def test_imap(self): - it = self.pool.imap(sqr, list(range(10))) - self.assertEqual(list(it), list(map(sqr, list(range(10))))) - - it = self.pool.imap(sqr, list(range(10))) - for i in range(10): - self.assertEqual(next(it), i*i) - self.assertRaises(StopIteration, it.__next__) - - it = self.pool.imap(sqr, list(range(1000)), chunksize=100) - for i in range(1000): - self.assertEqual(next(it), i*i) - self.assertRaises(StopIteration, it.__next__) - - def test_imap_unordered(self): - it = self.pool.imap_unordered(sqr, list(range(1000))) - self.assertEqual(sorted(it), list(map(sqr, list(range(1000))))) - - it = self.pool.imap_unordered(sqr, list(range(1000)), chunksize=53) - self.assertEqual(sorted(it), list(map(sqr, list(range(1000))))) - - def test_make_pool(self): - p = multiprocessing.Pool(3) - self.assertEqual(3, len(p._pool)) - p.close() - p.join() - - def test_terminate(self): - if self.TYPE == 'manager': - # On Unix a forked process increfs each shared object to - # which its parent process held a reference. If the - # forked process gets terminated then there is likely to - # be a reference leak. So to prevent - # _TestZZZNumberOfObjects from failing we skip this test - # when using a manager. - return - - result = self.pool.map_async( - time.sleep, [0.1 for i in range(10000)], chunksize=1 - ) - self.pool.terminate() - join = TimingWrapper(self.pool.join) - join() - self.assertTrue(join.elapsed < 0.2) -# -# Test that manager has expected number of shared objects left -# - -class _TestZZZNumberOfObjects(BaseTestCase): - # Because test cases are sorted alphabetically, this one will get - # run after all the other tests for the manager. It tests that - # there have been no "reference leaks" for the manager's shared - # objects. Note the comment in _TestPool.test_terminate(). - ALLOWED_TYPES = ('manager',) - - def test_number_of_objects(self): - EXPECTED_NUMBER = 1 # the pool object is still alive - multiprocessing.active_children() # discard dead process objs - gc.collect() # do garbage collection - refs = self.manager._number_of_objects() - debug_info = self.manager._debug_info() - if refs != EXPECTED_NUMBER: - print(self.manager._debug_info()) - print(debug_info) - - self.assertEqual(refs, EXPECTED_NUMBER) - -# -# Test of creating a customized manager class -# - -from multiprocessing.managers import BaseManager, BaseProxy, RemoteError - -class FooBar(object): - def f(self): - return 'f()' - def g(self): - raise ValueError - def _h(self): - return '_h()' - -def baz(): - for i in range(10): - yield i*i - -class IteratorProxy(BaseProxy): - _exposed_ = ('next', '__next__') - def __iter__(self): - return self - def __next__(self): - return self._callmethod('next') - def __next__(self): - return self._callmethod('__next__') - -class MyManager(BaseManager): - pass - -MyManager.register('Foo', callable=FooBar) -MyManager.register('Bar', callable=FooBar, exposed=('f', '_h')) -MyManager.register('baz', callable=baz, proxytype=IteratorProxy) - - -class _TestMyManager(BaseTestCase): - - ALLOWED_TYPES = ('manager',) - - def test_mymanager(self): - manager = MyManager() - manager.start() - - foo = manager.Foo() - bar = manager.Bar() - baz = manager.baz() - - foo_methods = [name for name in ('f', 'g', '_h') if hasattr(foo, name)] - bar_methods = [name for name in ('f', 'g', '_h') if hasattr(bar, name)] - - self.assertEqual(foo_methods, ['f', 'g']) - self.assertEqual(bar_methods, ['f', '_h']) - - self.assertEqual(foo.f(), 'f()') - self.assertRaises(ValueError, foo.g) - self.assertEqual(foo._callmethod('f'), 'f()') - self.assertRaises(RemoteError, foo._callmethod, '_h') - - self.assertEqual(bar.f(), 'f()') - self.assertEqual(bar._h(), '_h()') - self.assertEqual(bar._callmethod('f'), 'f()') - self.assertEqual(bar._callmethod('_h'), '_h()') - - self.assertEqual(list(baz), [i*i for i in range(10)]) - - manager.shutdown() - -# -# Test of connecting to a remote server and using xmlrpclib for serialization -# - -_queue = pyqueue.Queue() -def get_queue(): - return _queue - -class QueueManager(BaseManager): - '''manager class used by server process''' -QueueManager.register('get_queue', callable=get_queue) - -class QueueManager2(BaseManager): - '''manager class which specifies the same interface as QueueManager''' -QueueManager2.register('get_queue') - - -SERIALIZER = 'xmlrpclib' - -class _TestRemoteManager(BaseTestCase): - - ALLOWED_TYPES = ('manager',) - - def _putter(self, address, authkey): - manager = QueueManager2( - address=address, authkey=authkey, serializer=SERIALIZER - ) - manager.connect() - queue = manager.get_queue() - queue.put(('hello world', None, True, 2.25)) - - def test_remote(self): - authkey = os.urandom(32) - - manager = QueueManager( - address=('localhost', 0), authkey=authkey, serializer=SERIALIZER - ) - manager.start() - - p = self.Process(target=self._putter, args=(manager.address, authkey)) - p.start() - - manager2 = QueueManager2( - address=manager.address, authkey=authkey, serializer=SERIALIZER - ) - manager2.connect() - queue = manager2.get_queue() - - # Note that xmlrpclib will deserialize object as a list not a tuple - self.assertEqual(queue.get(), ['hello world', None, True, 2.25]) - - # Because we are using xmlrpclib for serialization instead of - # pickle this will cause a serialization error. - self.assertRaises(Exception, queue.put, time.sleep) - - # Make queue finalizer run before the server is stopped - del queue - manager.shutdown() - -class _TestManagerRestart(BaseTestCase): - - def _putter(self, address, authkey): - manager = QueueManager( - address=address, authkey=authkey, serializer=SERIALIZER) - manager.connect() - queue = manager.get_queue() - queue.put('hello world') - - def test_rapid_restart(self): - authkey = os.urandom(32) - manager = QueueManager( - address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) - manager.start() - - p = self.Process(target=self._putter, args=(manager.address, authkey)) - p.start() - queue = manager.get_queue() - self.assertEqual(queue.get(), 'hello world') - manager.shutdown() - manager = QueueManager( - address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) - manager.start() - -# -# -# - -SENTINEL = latin('') - -class _TestConnection(BaseTestCase): - - ALLOWED_TYPES = ('processes', 'threads') - - def _echo(self, conn): - for msg in iter(conn.recv_bytes, SENTINEL): - conn.send_bytes(msg) - conn.close() - - def test_connection(self): - conn, child_conn = self.Pipe() - - p = self.Process(target=self._echo, args=(child_conn,)) - p.daemon = True - p.start() - - seq = [1, 2.25, None] - msg = latin('hello world') - longmsg = msg * 10 - arr = array.array('i', list(range(4))) - - if self.TYPE == 'processes': - self.assertEqual(type(conn.fileno()), int) - - self.assertEqual(conn.send(seq), None) - self.assertEqual(conn.recv(), seq) - - self.assertEqual(conn.send_bytes(msg), None) - self.assertEqual(conn.recv_bytes(), msg) - - if self.TYPE == 'processes': - buffer = array.array('i', [0]*10) - expected = list(arr) + [0] * (10 - len(arr)) - self.assertEqual(conn.send_bytes(arr), None) - self.assertEqual(conn.recv_bytes_into(buffer), - len(arr) * buffer.itemsize) - self.assertEqual(list(buffer), expected) - - buffer = array.array('i', [0]*10) - expected = [0] * 3 + list(arr) + [0] * (10 - 3 - len(arr)) - self.assertEqual(conn.send_bytes(arr), None) - self.assertEqual(conn.recv_bytes_into(buffer, 3 * buffer.itemsize), - len(arr) * buffer.itemsize) - self.assertEqual(list(buffer), expected) - - buffer = bytearray(latin(' ' * 40)) - self.assertEqual(conn.send_bytes(longmsg), None) - try: - res = conn.recv_bytes_into(buffer) - except multiprocessing.BufferTooShort as e: - self.assertEqual(e.args, (longmsg,)) - else: - self.fail('expected BufferTooShort, got %s' % res) - - poll = TimingWrapper(conn.poll) - - self.assertEqual(poll(), False) - self.assertTimingAlmostEqual(poll.elapsed, 0) - - self.assertEqual(poll(TIMEOUT1), False) - self.assertTimingAlmostEqual(poll.elapsed, TIMEOUT1) - - conn.send(None) - - self.assertEqual(poll(TIMEOUT1), True) - self.assertTimingAlmostEqual(poll.elapsed, 0) - - self.assertEqual(conn.recv(), None) - - really_big_msg = latin('X') * (1024 * 1024 * 16) # 16Mb - conn.send_bytes(really_big_msg) - self.assertEqual(conn.recv_bytes(), really_big_msg) - - conn.send_bytes(SENTINEL) # tell child to quit - child_conn.close() - - if self.TYPE == 'processes': - self.assertEqual(conn.readable, True) - self.assertEqual(conn.writable, True) - self.assertRaises(EOFError, conn.recv) - self.assertRaises(EOFError, conn.recv_bytes) - - p.join() - - def test_duplex_false(self): - reader, writer = self.Pipe(duplex=False) - self.assertEqual(writer.send(1), None) - self.assertEqual(reader.recv(), 1) - if self.TYPE == 'processes': - self.assertEqual(reader.readable, True) - self.assertEqual(reader.writable, False) - self.assertEqual(writer.readable, False) - self.assertEqual(writer.writable, True) - self.assertRaises(IOError, reader.send, 2) - self.assertRaises(IOError, writer.recv) - self.assertRaises(IOError, writer.poll) - - def test_spawn_close(self): - # We test that a pipe connection can be closed by parent - # process immediately after child is spawned. On Windows this - # would have sometimes failed on old versions because - # child_conn would be closed before the child got a chance to - # duplicate it. - conn, child_conn = self.Pipe() - - p = self.Process(target=self._echo, args=(child_conn,)) - p.start() - child_conn.close() # this might complete before child initializes - - msg = latin('hello') - conn.send_bytes(msg) - self.assertEqual(conn.recv_bytes(), msg) - - conn.send_bytes(SENTINEL) - conn.close() - p.join() - - def test_sendbytes(self): - if self.TYPE != 'processes': - return - - msg = latin('abcdefghijklmnopqrstuvwxyz') - a, b = self.Pipe() - - a.send_bytes(msg) - self.assertEqual(b.recv_bytes(), msg) - - a.send_bytes(msg, 5) - self.assertEqual(b.recv_bytes(), msg[5:]) - - a.send_bytes(msg, 7, 8) - self.assertEqual(b.recv_bytes(), msg[7:7+8]) - - a.send_bytes(msg, 26) - self.assertEqual(b.recv_bytes(), latin('')) - - a.send_bytes(msg, 26, 0) - self.assertEqual(b.recv_bytes(), latin('')) - - self.assertRaises(ValueError, a.send_bytes, msg, 27) - - self.assertRaises(ValueError, a.send_bytes, msg, 22, 5) - - self.assertRaises(ValueError, a.send_bytes, msg, 26, 1) - - self.assertRaises(ValueError, a.send_bytes, msg, -1) - - self.assertRaises(ValueError, a.send_bytes, msg, 4, -1) - -class _TestListenerClient(BaseTestCase): - - ALLOWED_TYPES = ('processes', 'threads') - - def _test(self, address): - conn = self.connection.Client(address) - conn.send('hello') - conn.close() - - def test_listener_client(self): - for family in self.connection.families: - l = self.connection.Listener(family=family) - p = self.Process(target=self._test, args=(l.address,)) - p.daemon = True - p.start() - conn = l.accept() - self.assertEqual(conn.recv(), 'hello') - p.join() - l.close() -# -# Test of sending connection and socket objects between processes -# -""" -class _TestPicklingConnections(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def _listener(self, conn, families): - for fam in families: - l = self.connection.Listener(family=fam) - conn.send(l.address) - new_conn = l.accept() - conn.send(new_conn) - - if self.TYPE == 'processes': - l = socket.socket() - l.bind(('localhost', 0)) - conn.send(l.getsockname()) - l.listen(1) - new_conn, addr = l.accept() - conn.send(new_conn) - - conn.recv() - - def _remote(self, conn): - for (address, msg) in iter(conn.recv, None): - client = self.connection.Client(address) - client.send(msg.upper()) - client.close() - - if self.TYPE == 'processes': - address, msg = conn.recv() - client = socket.socket() - client.connect(address) - client.sendall(msg.upper()) - client.close() - - conn.close() - - def test_pickling(self): - try: - multiprocessing.allow_connection_pickling() - except ImportError: - return - - families = self.connection.families - - lconn, lconn0 = self.Pipe() - lp = self.Process(target=self._listener, args=(lconn0, families)) - lp.start() - lconn0.close() - - rconn, rconn0 = self.Pipe() - rp = self.Process(target=self._remote, args=(rconn0,)) - rp.start() - rconn0.close() - - for fam in families: - msg = ('This connection uses family %s' % fam).encode('ascii') - address = lconn.recv() - rconn.send((address, msg)) - new_conn = lconn.recv() - self.assertEqual(new_conn.recv(), msg.upper()) - - rconn.send(None) - - if self.TYPE == 'processes': - msg = latin('This connection uses a normal socket') - address = lconn.recv() - rconn.send((address, msg)) - if hasattr(socket, 'fromfd'): - new_conn = lconn.recv() - self.assertEqual(new_conn.recv(100), msg.upper()) - else: - # XXX On Windows with Py2.6 need to backport fromfd() - discard = lconn.recv_bytes() - - lconn.send(None) - - rconn.close() - lconn.close() - - lp.join() - rp.join() -""" -# -# -# - -class _TestHeap(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def test_heap(self): - iterations = 5000 - maxblocks = 50 - blocks = [] - - # create and destroy lots of blocks of different sizes - for i in range(iterations): - size = int(random.lognormvariate(0, 1) * 1000) - b = multiprocessing.heap.BufferWrapper(size) - blocks.append(b) - if len(blocks) > maxblocks: - i = random.randrange(maxblocks) - del blocks[i] - - # get the heap object - heap = multiprocessing.heap.BufferWrapper._heap - - # verify the state of the heap - all = [] - occupied = 0 - for L in list(heap._len_to_seq.values()): - for arena, start, stop in L: - all.append((heap._arenas.index(arena), start, stop, - stop-start, 'free')) - for arena, start, stop in heap._allocated_blocks: - all.append((heap._arenas.index(arena), start, stop, - stop-start, 'occupied')) - occupied += (stop-start) - - all.sort() - - for i in range(len(all)-1): - (arena, start, stop) = all[i][:3] - (narena, nstart, nstop) = all[i+1][:3] - self.assertTrue((arena != narena and nstart == 0) or - (stop == nstart)) - -# -# -# - -try: - from ctypes import Structure, Value, copy, c_int, c_double -except ImportError: - Structure = object - c_int = c_double = None - -class _Foo(Structure): - _fields_ = [ - ('x', c_int), - ('y', c_double) - ] - -class _TestSharedCTypes(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def _double(self, x, y, foo, arr, string): - x.value *= 2 - y.value *= 2 - foo.x *= 2 - foo.y *= 2 - string.value *= 2 - for i in range(len(arr)): - arr[i] *= 2 - - def test_sharedctypes(self, lock=False): - if c_int is None: - return - - x = Value('i', 7, lock=lock) - y = Value(ctypes.c_double, 1.0/3.0, lock=lock) - foo = Value(_Foo, 3, 2, lock=lock) - arr = Array('d', list(range(10)), lock=lock) - string = Array('c', 20, lock=lock) - string.value = 'hello' - - p = self.Process(target=self._double, args=(x, y, foo, arr, string)) - p.start() - p.join() - - self.assertEqual(x.value, 14) - self.assertAlmostEqual(y.value, 2.0/3.0) - self.assertEqual(foo.x, 6) - self.assertAlmostEqual(foo.y, 4.0) - for i in range(10): - self.assertAlmostEqual(arr[i], i*2) - self.assertEqual(string.value, latin('hellohello')) - - def test_synchronize(self): - self.test_sharedctypes(lock=True) - - def test_copy(self): - if c_int is None: - return - - foo = _Foo(2, 5.0) - bar = copy(foo) - foo.x = 0 - foo.y = 0 - self.assertEqual(bar.x, 2) - self.assertAlmostEqual(bar.y, 5.0) - -# -# -# - -class _TestFinalize(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def _test_finalize(self, conn): - class Foo(object): - pass - - a = Foo() - util.Finalize(a, conn.send, args=('a',)) - del a # triggers callback for a - - b = Foo() - close_b = util.Finalize(b, conn.send, args=('b',)) - close_b() # triggers callback for b - close_b() # does nothing because callback has already been called - del b # does nothing because callback has already been called - - c = Foo() - util.Finalize(c, conn.send, args=('c',)) - - d10 = Foo() - util.Finalize(d10, conn.send, args=('d10',), exitpriority=1) - - d01 = Foo() - util.Finalize(d01, conn.send, args=('d01',), exitpriority=0) - d02 = Foo() - util.Finalize(d02, conn.send, args=('d02',), exitpriority=0) - d03 = Foo() - util.Finalize(d03, conn.send, args=('d03',), exitpriority=0) - - util.Finalize(None, conn.send, args=('e',), exitpriority=-10) - - util.Finalize(None, conn.send, args=('STOP',), exitpriority=-100) - - # call mutliprocessing's cleanup function then exit process without - # garbage collecting locals - util._exit_function() - conn.close() - os._exit(0) - - def test_finalize(self): - conn, child_conn = self.Pipe() - - p = self.Process(target=self._test_finalize, args=(child_conn,)) - p.start() - p.join() - - result = [obj for obj in iter(conn.recv, 'STOP')] - self.assertEqual(result, ['a', 'b', 'd10', 'd03', 'd02', 'd01', 'e']) - -# -# Test that from ... import * works for each module -# - -class _TestImportStar(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def test_import(self): - modules = ( - 'multiprocessing', 'multiprocessing.connection', - 'multiprocessing.heap', 'multiprocessing.managers', - 'multiprocessing.pool', 'multiprocessing.process', - 'multiprocessing.reduction', 'multiprocessing.sharedctypes', - 'multiprocessing.synchronize', 'multiprocessing.util' - ) - - for name in modules: - __import__(name) - mod = sys.modules[name] - - for attr in getattr(mod, '__all__', ()): - self.assertTrue( - hasattr(mod, attr), - '%r does not have attribute %r' % (mod, attr) - ) - -# -# Quick test that logging works -- does not test logging output -# - -class _TestLogging(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def test_enable_logging(self): - logger = multiprocessing.get_logger() - logger.setLevel(util.SUBWARNING) - self.assertTrue(logger is not None) - logger.debug('this will not be printed') - logger.info('nor will this') - logger.setLevel(LOG_LEVEL) - - def _test_level(self, conn): - logger = multiprocessing.get_logger() - conn.send(logger.getEffectiveLevel()) - - def test_level(self): - LEVEL1 = 32 - LEVEL2 = 37 - - logger = multiprocessing.get_logger() - root_logger = logging.getLogger() - root_level = root_logger.level - - reader, writer = multiprocessing.Pipe(duplex=False) - - logger.setLevel(LEVEL1) - self.Process(target=self._test_level, args=(writer,)).start() - self.assertEqual(LEVEL1, reader.recv()) - - logger.setLevel(logging.NOTSET) - root_logger.setLevel(LEVEL2) - self.Process(target=self._test_level, args=(writer,)).start() - self.assertEqual(LEVEL2, reader.recv()) - - root_logger.setLevel(root_level) - logger.setLevel(level=LOG_LEVEL) - -# -# Test to verify handle verification, see issue 3321 -# - -class TestInvalidHandle(unittest.TestCase): - - def test_invalid_handles(self): - if WIN32: - return - conn = _multiprocessing.Connection(44977608) - self.assertRaises(IOError, conn.poll) - self.assertRaises(IOError, _multiprocessing.Connection, -1) -# -# Functions used to create test cases from the base ones in this module -# - -def get_attributes(Source, names): - d = {} - for name in names: - obj = getattr(Source, name) - if type(obj) == type(get_attributes): - obj = staticmethod(obj) - d[name] = obj - return d - -def create_test_cases(Mixin, type): - result = {} - glob = globals() - Type = type[0].upper() + type[1:] - - for name in list(glob.keys()): - if name.startswith('_Test'): - base = glob[name] - if type in base.ALLOWED_TYPES: - newname = 'With' + Type + name[1:] - class Temp(base, unittest.TestCase, Mixin): - pass - result[newname] = Temp - Temp.__name__ = newname - Temp.__module__ = Mixin.__module__ - return result - -# -# Create test cases -# - -class ProcessesMixin(object): - TYPE = 'processes' - Process = multiprocessing.Process - locals().update(get_attributes(multiprocessing, ( - 'Queue', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', - 'Condition', 'Event', 'Value', 'Array', 'RawValue', - 'RawArray', 'current_process', 'active_children', 'Pipe', - 'connection', 'JoinableQueue' - ))) - -testcases_processes = create_test_cases(ProcessesMixin, type='processes') -globals().update(testcases_processes) - - -class ManagerMixin(object): - TYPE = 'manager' - Process = multiprocessing.Process - manager = object.__new__(multiprocessing.managers.SyncManager) - locals().update(get_attributes(manager, ( - 'Queue', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', - 'Condition', 'Event', 'Value', 'Array', 'list', 'dict', - 'Namespace', 'JoinableQueue' - ))) - -testcases_manager = create_test_cases(ManagerMixin, type='manager') -globals().update(testcases_manager) - - -class ThreadsMixin(object): - TYPE = 'threads' - Process = multiprocessing.dummy.Process - locals().update(get_attributes(multiprocessing.dummy, ( - 'Queue', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', - 'Condition', 'Event', 'Value', 'Array', 'current_process', - 'active_children', 'Pipe', 'connection', 'dict', 'list', - 'Namespace', 'JoinableQueue' - ))) - -testcases_threads = create_test_cases(ThreadsMixin, type='threads') -globals().update(testcases_threads) - -class OtherTest(unittest.TestCase): - # TODO: add more tests for deliver/answer challenge. - def test_deliver_challenge_auth_failure(self): - class _FakeConnection(object): - def recv_bytes(self, size): - return b'something bogus' - def send_bytes(self, data): - pass - self.assertRaises(multiprocessing.AuthenticationError, - multiprocessing.connection.deliver_challenge, - _FakeConnection(), b'abc') - - def test_answer_challenge_auth_failure(self): - class _FakeConnection(object): - def __init__(self): - self.count = 0 - def recv_bytes(self, size): - self.count += 1 - if self.count == 1: - return multiprocessing.connection.CHALLENGE - elif self.count == 2: - return b'something bogus' - return b'' - def send_bytes(self, data): - pass - self.assertRaises(multiprocessing.AuthenticationError, - multiprocessing.connection.answer_challenge, - _FakeConnection(), b'abc') - -testcases_other = [OtherTest, TestInvalidHandle] - -# -# -# - -def test_main(run=None): - if sys.platform.startswith("linux"): - try: - lock = multiprocessing.RLock() - except OSError: - from test.support import TestSkipped - raise unittest.SkipTest("OSError raises on RLock creation, see issue 3111!") - - if run is None: - from test.support import run_unittest as run - - util.get_temp_dir() # creates temp directory for use by all processes - - multiprocessing.get_logger().setLevel(LOG_LEVEL) - - ProcessesMixin.pool = multiprocessing.Pool(4) - ThreadsMixin.pool = multiprocessing.dummy.Pool(4) - ManagerMixin.manager.__init__() - ManagerMixin.manager.start() - ManagerMixin.pool = ManagerMixin.manager.Pool(4) - - testcases = ( - sorted(testcases_processes.values(), key=lambda tc:tc.__name__) + - sorted(testcases_threads.values(), key=lambda tc:tc.__name__) + - sorted(testcases_manager.values(), key=lambda tc:tc.__name__) + - testcases_other - ) - - loadTestsFromTestCase = unittest.defaultTestLoader.loadTestsFromTestCase - suite = unittest.TestSuite(loadTestsFromTestCase(tc) for tc in testcases) - run(suite) - - ThreadsMixin.pool.terminate() - ProcessesMixin.pool.terminate() - ManagerMixin.pool.terminate() - ManagerMixin.manager.shutdown() - - del ProcessesMixin.pool, ThreadsMixin.pool, ManagerMixin.pool - -def main(): - test_main(unittest.TextTestRunner(verbosity=2).run) - -if __name__ == '__main__': - main() From python-checkins at python.org Tue Mar 31 15:25:17 2009 From: python-checkins at python.org (ronald.oussoren) Date: Tue, 31 Mar 2009 15:25:17 +0200 (CEST) Subject: [Python-checkins] r70806 - in python/branches/py3k: Mac/BuildScript/build-installer.py Message-ID: <20090331132517.CE2831E4002@bag.python.org> Author: ronald.oussoren Date: Tue Mar 31 15:25:17 2009 New Revision: 70806 Log: Merged revisions 70802 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70802 | ronald.oussoren | 2009-03-31 08:20:45 -0500 (Tue, 31 Mar 2009) | 4 lines Minor update to OSX build-installer script, needed to ensure that the build will succeed in a clean checkout and with a non-default deployment target. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Mac/BuildScript/build-installer.py Modified: python/branches/py3k/Mac/BuildScript/build-installer.py ============================================================================== --- python/branches/py3k/Mac/BuildScript/build-installer.py (original) +++ python/branches/py3k/Mac/BuildScript/build-installer.py Tue Mar 31 15:25:17 2009 @@ -1020,7 +1020,18 @@ # Now build python itself buildPython() + + # And then build the documentation + # Remove the Deployment Target from the shell + # environment, it's no longer needed and + # an unexpected build target can cause problems + # when Sphinx and its dependencies need to + # be (re-)installed. + del os.environ['MACOSX_DEPLOYMENT_TARGET'] buildPythonDocs() + + + # Prepare the applications folder fn = os.path.join(WORKDIR, "_root", "Applications", "Python %s"%(getVersion(),), "Update Shell Profile.command") patchScript("scripts/postflight.patch-profile", fn) From python-checkins at python.org Tue Mar 31 15:31:00 2009 From: python-checkins at python.org (jeremy.hylton) Date: Tue, 31 Mar 2009 15:31:00 +0200 (CEST) Subject: [Python-checkins] r70807 - python/trunk/Makefile.pre.in Message-ID: <20090331133100.4E2761E4002@bag.python.org> Author: jeremy.hylton Date: Tue Mar 31 15:31:00 2009 New Revision: 70807 Log: Update quicktest to match Python 3 branch Modified: python/trunk/Makefile.pre.in Modified: python/trunk/Makefile.pre.in ============================================================================== --- python/trunk/Makefile.pre.in (original) +++ python/trunk/Makefile.pre.in Tue Mar 31 15:31:00 2009 @@ -709,9 +709,10 @@ fi $(TESTPYTHON) $(TESTPROG) $(TESTOPTS) -uall -rw -QUICKTESTOPTS= $(TESTOPTS) -x test_thread test_signal test_strftime \ - test_unicodedata test_re test_sre test_select test_poll \ - test_linuxaudiodev test_struct test_sunaudiodev test_zlib +QUICKTESTOPTS= $(TESTOPTS) -x test_subprocess test_io test_lib2to3 \ + test_multibytecodec test_urllib2_localnet test_itertools \ + test_multiprocessing test_mailbox test_socket test_poll \ + test_select test_zipfile quicktest: all platform -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f -$(TESTPYTHON) $(TESTPROG) $(QUICKTESTOPTS) From python-checkins at python.org Tue Mar 31 15:44:06 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 31 Mar 2009 15:44:06 +0200 (CEST) Subject: [Python-checkins] r70808 - in python/branches/py3k: Lib/test/test_mmap.py Misc/NEWS Modules/mmapmodule.c Message-ID: <20090331134406.B82EF1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 31 15:44:06 2009 New Revision: 70808 Log: Merged revisions 70800 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70800 | hirokazu.yamamoto | 2009-03-31 22:13:05 +0900 | 1 line Issue #5387: Fixed mmap.move crash by integer overflow. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_mmap.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/mmapmodule.c Modified: python/branches/py3k/Lib/test/test_mmap.py ============================================================================== --- python/branches/py3k/Lib/test/test_mmap.py (original) +++ python/branches/py3k/Lib/test/test_mmap.py Tue Mar 31 15:44:06 2009 @@ -335,6 +335,23 @@ mf.close() f.close() + # more excessive test + data = b"0123456789" + for dest in range(len(data)): + for src in range(len(data)): + for count in range(len(data) - max(dest, src)): + expected = data[:dest] + data[src:src+count] + data[dest+count:] + m = mmap.mmap(-1, len(data)) + m[:] = data + m.move(dest, src, count) + self.assertEqual(m[:], expected) + m.close() + + # should not crash + m = mmap.mmap(-1, 1) + self.assertRaises(ValueError, m.move, 1, 1, -1) + m.close() + def test_anonymous(self): # anonymous mmap.mmap(-1, PAGE) m = mmap.mmap(-1, PAGESIZE) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 31 15:44:06 2009 @@ -53,6 +53,8 @@ Library ------- +- Issue #5387: Fixed mmap.move crash by integer overflow. + - Issue #5261: Patch multiprocessing's semaphore.c to support context manager use: "with multiprocessing.Lock()" works now. Modified: python/branches/py3k/Modules/mmapmodule.c ============================================================================== --- python/branches/py3k/Modules/mmapmodule.c (original) +++ python/branches/py3k/Modules/mmapmodule.c Tue Mar 31 15:44:06 2009 @@ -623,10 +623,8 @@ return NULL; } else { /* bounds check the values */ - if (/* end of source after end of data?? */ - ((src+count) > self->size) - /* dest will fit? */ - || (dest+count > self->size)) { + unsigned long pos = src > dest ? src : dest; + if (self->size >= pos && count > self->size - pos) { PyErr_SetString(PyExc_ValueError, "source or destination out of range"); return NULL; From python-checkins at python.org Tue Mar 31 15:48:16 2009 From: python-checkins at python.org (jeremy.hylton) Date: Tue, 31 Mar 2009 15:48:16 +0200 (CEST) Subject: [Python-checkins] r70809 - in python/trunk: Lib/test/test_scope.py Python/symtable.c Message-ID: <20090331134816.775FD1E4021@bag.python.org> Author: jeremy.hylton Date: Tue Mar 31 15:48:15 2009 New Revision: 70809 Log: Global statements from one function leaked into parallel functions. Re http://bugs.python.org/issue4315 The symbol table used the same name dictionaries to recursively analyze each of its child blocks, even though the dictionaries are modified during analysis. The fix is to create new temporary dictionaries via the analyze_child_block(). The only information that needs to propagate back up is the names of the free variables. Add more comments and break out a helper function. This code doesn't get any easier to understand when you only look at it once a year. Modified: python/trunk/Lib/test/test_scope.py python/trunk/Python/symtable.c Modified: python/trunk/Lib/test/test_scope.py ============================================================================== --- python/trunk/Lib/test/test_scope.py (original) +++ python/trunk/Lib/test/test_scope.py Tue Mar 31 15:48:15 2009 @@ -632,6 +632,30 @@ f() # used to crash the interpreter... + def testGlobalInParallelNestedFunctions(self): + # A symbol table bug leaked the global statement from one + # function to other nested functions in the same block. + # This test verifies that a global statement in the first + # function does not affect the second function. + CODE = """def f(): + y = 1 + def g(): + global y + return y + def h(): + return y + 1 + return g, h + +y = 9 +g, h = f() +result9 = g() +result2 = h() +""" + local_ns = {} + global_ns = {} + exec CODE in local_ns, global_ns + self.assertEqual(2, global_ns["result2"]) + self.assertEqual(9, global_ns["result9"]) def test_main(): Modified: python/trunk/Python/symtable.c ============================================================================== --- python/trunk/Python/symtable.c (original) +++ python/trunk/Python/symtable.c Tue Mar 31 15:48:15 2009 @@ -361,8 +361,9 @@ /* Decide on scope of name, given flags. - The dicts passed in as arguments are modified as necessary. - ste is passed so that flags can be updated. + The namespace dictionaries may be modified to record information + about the new name. For example, a new global will add an entry to + global. A name that was global can be changed to local. */ static int @@ -415,7 +416,7 @@ explicit? It could also be global implicit. */ else if (global && PyDict_GetItem(global, name)) { - SET_SCOPE(dict, name, GLOBAL_EXPLICIT); + SET_SCOPE(dict, name, GLOBAL_IMPLICIT); return 1; } else { @@ -424,7 +425,10 @@ SET_SCOPE(dict, name, GLOBAL_IMPLICIT); return 1; } - return 0; /* Can't get here */ + /* Should never get here. */ + PyErr_Format(PyExc_SystemError, "failed to set scope for %s", + PyString_AS_STRING(name)); + return 0; } #undef SET_SCOPE @@ -588,43 +592,68 @@ } /* Make final symbol table decisions for block of ste. + Arguments: ste -- current symtable entry (input/output) - bound -- set of variables bound in enclosing scopes (input) + bound -- set of variables bound in enclosing scopes (input). bound + is NULL for module blocks. free -- set of free variables in enclosed scopes (output) globals -- set of declared global variables in enclosing scopes (input) + + The implementation uses two mutually recursive functions, + analyze_block() and analyze_child_block(). analyze_block() is + responsible for analyzing the individual names defined in a block. + analyze_child_block() prepares temporary namespace dictionaries + used to evaluated nested blocks. + + The two functions exist because a child block should see the name + bindings of its enclosing blocks, but those bindings should not + propagate back to a parent block. */ static int +analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, + PyObject *global, PyObject* child_free); + +static int analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, PyObject *global) { - PyObject *name, *v, *local = NULL, *scope = NULL, *newbound = NULL; - PyObject *newglobal = NULL, *newfree = NULL; + PyObject *name, *v, *local = NULL, *scope = NULL; + PyObject *newbound = NULL, *newglobal = NULL; + PyObject *newfree = NULL, *allfree = NULL; int i, success = 0; Py_ssize_t pos = 0; - local = PyDict_New(); + local = PyDict_New(); /* collect new names bound in block */ if (!local) goto error; - scope = PyDict_New(); + scope = PyDict_New(); /* collect scopes defined for each name */ if (!scope) goto error; + + /* Allocate new global and bound variable dictionaries. These + dictionaries hold the names visible in nested blocks. For + ClassBlocks, the bound and global names are initialized + before analyzing names, because class bindings aren't + visible in methods. For other blocks, they are initialized + after names are analyzed. + */ + + /* TODO(jhylton): Package these dicts in a struct so that we + can write reasonable helper functions? + */ newglobal = PyDict_New(); if (!newglobal) goto error; - newfree = PyDict_New(); - if (!newfree) - goto error; newbound = PyDict_New(); if (!newbound) goto error; + newfree = PyDict_New(); + if (!newfree) + goto error; if (ste->ste_type == ClassBlock) { - /* make a copy of globals before calling analyze_name(), - because global statements in the class have no effect - on nested functions. - */ if (PyDict_Update(newglobal, global) < 0) goto error; if (bound) @@ -632,12 +661,10 @@ goto error; } - assert(PySTEntry_Check(ste)); - assert(PyDict_Check(ste->ste_symbols)); while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) { long flags = PyInt_AS_LONG(v); - if (!analyze_name(ste, scope, name, flags, bound, local, free, - global)) + if (!analyze_name(ste, scope, name, flags, + bound, local, free, global)) goto error; } @@ -654,18 +681,28 @@ goto error; } - /* Recursively call analyze_block() on each child block */ + /* Recursively call analyze_block() on each child block. + + newbound, newglobal now contain the names visible in + nested blocks. The free variables in the children will + be collected in allfree. + */ + allfree = PyDict_New(); + if (!allfree) + goto error; for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) { PyObject *c = PyList_GET_ITEM(ste->ste_children, i); PySTEntryObject* entry; assert(c && PySTEntry_Check(c)); entry = (PySTEntryObject*)c; - if (!analyze_block(entry, newbound, newfree, newglobal)) + if (!analyze_child_block(entry, newbound, newfree, newglobal, + allfree)) goto error; if (entry->ste_free || entry->ste_child_free) ste->ste_child_free = 1; } + PyDict_Update(newfree, allfree); if (ste->ste_type == FunctionBlock && !analyze_cells(scope, newfree)) goto error; if (!update_symbols(ste->ste_symbols, scope, bound, newfree, @@ -683,12 +720,54 @@ Py_XDECREF(newbound); Py_XDECREF(newglobal); Py_XDECREF(newfree); + Py_XDECREF(allfree); if (!success) assert(PyErr_Occurred()); return success; } static int +analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, + PyObject *global, PyObject* child_free) +{ + PyObject *temp_bound = NULL, *temp_global = NULL, *temp_free = NULL; + int success = 0; + + /* Copy the bound and global dictionaries. + + These dictionary are used by all blocks enclosed by the + current block. The analyze_block() call modifies these + dictionaries. + + */ + temp_bound = PyDict_New(); + if (!temp_bound) + goto error; + if (PyDict_Update(temp_bound, bound) < 0) + goto error; + temp_free = PyDict_New(); + if (!temp_free) + goto error; + if (PyDict_Update(temp_free, free) < 0) + goto error; + temp_global = PyDict_New(); + if (!temp_global) + goto error; + if (PyDict_Update(temp_global, global) < 0) + goto error; + + if (!analyze_block(entry, temp_bound, temp_free, temp_global)) + goto error; + success = PyDict_Update(child_free, temp_free) >= 0; + success = 1; + error: + Py_XDECREF(temp_bound); + Py_XDECREF(temp_free); + Py_XDECREF(temp_global); + return success; +} + +static int symtable_analyze(struct symtable *st) { PyObject *free, *global; From python-checkins at python.org Tue Mar 31 15:51:05 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 31 Mar 2009 15:51:05 +0200 (CEST) Subject: [Python-checkins] r70810 - in python/branches/py3k-short-float-repr/Lib/test: test_multiprocessing.py xtest_multiprocessing.py Message-ID: <20090331135105.DC3871E4101@bag.python.org> Author: mark.dickinson Date: Tue Mar 31 15:51:03 2009 New Revision: 70810 Log: Restore test_multiprocessing Added: python/branches/py3k-short-float-repr/Lib/test/test_multiprocessing.py - copied unchanged from r70805, /python/branches/py3k-short-float-repr/Lib/test/xtest_multiprocessing.py Removed: python/branches/py3k-short-float-repr/Lib/test/xtest_multiprocessing.py Deleted: python/branches/py3k-short-float-repr/Lib/test/xtest_multiprocessing.py ============================================================================== --- python/branches/py3k-short-float-repr/Lib/test/xtest_multiprocessing.py Tue Mar 31 15:51:03 2009 +++ (empty file) @@ -1,1877 +0,0 @@ -#!/usr/bin/env python - -# -# Unit tests for the multiprocessing package -# - -import unittest -import threading -import queue as pyqueue -import time -import sys -import os -import gc -import signal -import array -import copy -import socket -import random -import logging - - -# Work around broken sem_open implementations -try: - import multiprocessing.synchronize -except ImportError as e: - raise unittest.SkipTest(e) - -import multiprocessing.dummy -import multiprocessing.connection -import multiprocessing.managers -import multiprocessing.heap -import multiprocessing.pool -import _multiprocessing - -from multiprocessing import util - -# -# -# - -def latin(s): - return s.encode('latin') - -# -# Constants -# - -LOG_LEVEL = util.SUBWARNING -#LOG_LEVEL = logging.WARNING - -DELTA = 0.1 -CHECK_TIMINGS = False # making true makes tests take a lot longer - # and can sometimes cause some non-serious - # failures because some calls block a bit - # longer than expected -if CHECK_TIMINGS: - TIMEOUT1, TIMEOUT2, TIMEOUT3 = 0.82, 0.35, 1.4 -else: - TIMEOUT1, TIMEOUT2, TIMEOUT3 = 0.1, 0.1, 0.1 - -HAVE_GETVALUE = not getattr(_multiprocessing, - 'HAVE_BROKEN_SEM_GETVALUE', False) - -WIN32 = (sys.platform == "win32") - -# -# Creates a wrapper for a function which records the time it takes to finish -# - -class TimingWrapper(object): - - def __init__(self, func): - self.func = func - self.elapsed = None - - def __call__(self, *args, **kwds): - t = time.time() - try: - return self.func(*args, **kwds) - finally: - self.elapsed = time.time() - t - -# -# Base class for test cases -# - -class BaseTestCase(object): - - ALLOWED_TYPES = ('processes', 'manager', 'threads') - - def assertTimingAlmostEqual(self, a, b): - if CHECK_TIMINGS: - self.assertAlmostEqual(a, b, 1) - - def assertReturnsIfImplemented(self, value, func, *args): - try: - res = func(*args) - except NotImplementedError: - pass - else: - return self.assertEqual(value, res) - -# -# Return the value of a semaphore -# - -def get_value(self): - try: - return self.get_value() - except AttributeError: - try: - return self._Semaphore__value - except AttributeError: - try: - return self._value - except AttributeError: - raise NotImplementedError - -# -# Testcases -# - -class _TestProcess(BaseTestCase): - - ALLOWED_TYPES = ('processes', 'threads') - - def test_current(self): - if self.TYPE == 'threads': - return - - current = self.current_process() - authkey = current.authkey - - self.assertTrue(current.is_alive()) - self.assertTrue(not current.daemon) - self.assertTrue(isinstance(authkey, bytes)) - self.assertTrue(len(authkey) > 0) - self.assertEqual(current.ident, os.getpid()) - self.assertEqual(current.exitcode, None) - - def _test(self, q, *args, **kwds): - current = self.current_process() - q.put(args) - q.put(kwds) - q.put(current.name) - if self.TYPE != 'threads': - q.put(bytes(current.authkey)) - q.put(current.pid) - - def test_process(self): - q = self.Queue(1) - e = self.Event() - args = (q, 1, 2) - kwargs = {'hello':23, 'bye':2.54} - name = 'SomeProcess' - p = self.Process( - target=self._test, args=args, kwargs=kwargs, name=name - ) - p.daemon = True - current = self.current_process() - - if self.TYPE != 'threads': - self.assertEquals(p.authkey, current.authkey) - self.assertEquals(p.is_alive(), False) - self.assertEquals(p.daemon, True) - self.assertTrue(p not in self.active_children()) - self.assertTrue(type(self.active_children()) is list) - self.assertEqual(p.exitcode, None) - - p.start() - - self.assertEquals(p.exitcode, None) - self.assertEquals(p.is_alive(), True) - self.assertTrue(p in self.active_children()) - - self.assertEquals(q.get(), args[1:]) - self.assertEquals(q.get(), kwargs) - self.assertEquals(q.get(), p.name) - if self.TYPE != 'threads': - self.assertEquals(q.get(), current.authkey) - self.assertEquals(q.get(), p.pid) - - p.join() - - self.assertEquals(p.exitcode, 0) - self.assertEquals(p.is_alive(), False) - self.assertTrue(p not in self.active_children()) - - def _test_terminate(self): - time.sleep(1000) - - def test_terminate(self): - if self.TYPE == 'threads': - return - - p = self.Process(target=self._test_terminate) - p.daemon = True - p.start() - - self.assertEqual(p.is_alive(), True) - self.assertTrue(p in self.active_children()) - self.assertEqual(p.exitcode, None) - - p.terminate() - - join = TimingWrapper(p.join) - self.assertEqual(join(), None) - self.assertTimingAlmostEqual(join.elapsed, 0.0) - - self.assertEqual(p.is_alive(), False) - self.assertTrue(p not in self.active_children()) - - p.join() - - # XXX sometimes get p.exitcode == 0 on Windows ... - #self.assertEqual(p.exitcode, -signal.SIGTERM) - - def test_cpu_count(self): - try: - cpus = multiprocessing.cpu_count() - except NotImplementedError: - cpus = 1 - self.assertTrue(type(cpus) is int) - self.assertTrue(cpus >= 1) - - def test_active_children(self): - self.assertEqual(type(self.active_children()), list) - - p = self.Process(target=time.sleep, args=(DELTA,)) - self.assertTrue(p not in self.active_children()) - - p.start() - self.assertTrue(p in self.active_children()) - - p.join() - self.assertTrue(p not in self.active_children()) - - def _test_recursion(self, wconn, id): - from multiprocessing import forking - wconn.send(id) - if len(id) < 2: - for i in range(2): - p = self.Process( - target=self._test_recursion, args=(wconn, id+[i]) - ) - p.start() - p.join() - - def test_recursion(self): - rconn, wconn = self.Pipe(duplex=False) - self._test_recursion(wconn, []) - - time.sleep(DELTA) - result = [] - while rconn.poll(): - result.append(rconn.recv()) - - expected = [ - [], - [0], - [0, 0], - [0, 1], - [1], - [1, 0], - [1, 1] - ] - self.assertEqual(result, expected) - -# -# -# - -class _UpperCaser(multiprocessing.Process): - - def __init__(self): - multiprocessing.Process.__init__(self) - self.child_conn, self.parent_conn = multiprocessing.Pipe() - - def run(self): - self.parent_conn.close() - for s in iter(self.child_conn.recv, None): - self.child_conn.send(s.upper()) - self.child_conn.close() - - def submit(self, s): - assert type(s) is str - self.parent_conn.send(s) - return self.parent_conn.recv() - - def stop(self): - self.parent_conn.send(None) - self.parent_conn.close() - self.child_conn.close() - -class _TestSubclassingProcess(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def test_subclassing(self): - uppercaser = _UpperCaser() - uppercaser.start() - self.assertEqual(uppercaser.submit('hello'), 'HELLO') - self.assertEqual(uppercaser.submit('world'), 'WORLD') - uppercaser.stop() - uppercaser.join() - -# -# -# - -def queue_empty(q): - if hasattr(q, 'empty'): - return q.empty() - else: - return q.qsize() == 0 - -def queue_full(q, maxsize): - if hasattr(q, 'full'): - return q.full() - else: - return q.qsize() == maxsize - - -class _TestQueue(BaseTestCase): - - - def _test_put(self, queue, child_can_start, parent_can_continue): - child_can_start.wait() - for i in range(6): - queue.get() - parent_can_continue.set() - - def test_put(self): - MAXSIZE = 6 - queue = self.Queue(maxsize=MAXSIZE) - child_can_start = self.Event() - parent_can_continue = self.Event() - - proc = self.Process( - target=self._test_put, - args=(queue, child_can_start, parent_can_continue) - ) - proc.daemon = True - proc.start() - - self.assertEqual(queue_empty(queue), True) - self.assertEqual(queue_full(queue, MAXSIZE), False) - - queue.put(1) - queue.put(2, True) - queue.put(3, True, None) - queue.put(4, False) - queue.put(5, False, None) - queue.put_nowait(6) - - # the values may be in buffer but not yet in pipe so sleep a bit - time.sleep(DELTA) - - self.assertEqual(queue_empty(queue), False) - self.assertEqual(queue_full(queue, MAXSIZE), True) - - put = TimingWrapper(queue.put) - put_nowait = TimingWrapper(queue.put_nowait) - - self.assertRaises(pyqueue.Full, put, 7, False) - self.assertTimingAlmostEqual(put.elapsed, 0) - - self.assertRaises(pyqueue.Full, put, 7, False, None) - self.assertTimingAlmostEqual(put.elapsed, 0) - - self.assertRaises(pyqueue.Full, put_nowait, 7) - self.assertTimingAlmostEqual(put_nowait.elapsed, 0) - - self.assertRaises(pyqueue.Full, put, 7, True, TIMEOUT1) - self.assertTimingAlmostEqual(put.elapsed, TIMEOUT1) - - self.assertRaises(pyqueue.Full, put, 7, False, TIMEOUT2) - self.assertTimingAlmostEqual(put.elapsed, 0) - - self.assertRaises(pyqueue.Full, put, 7, True, timeout=TIMEOUT3) - self.assertTimingAlmostEqual(put.elapsed, TIMEOUT3) - - child_can_start.set() - parent_can_continue.wait() - - self.assertEqual(queue_empty(queue), True) - self.assertEqual(queue_full(queue, MAXSIZE), False) - - proc.join() - - def _test_get(self, queue, child_can_start, parent_can_continue): - child_can_start.wait() - #queue.put(1) - queue.put(2) - queue.put(3) - queue.put(4) - queue.put(5) - parent_can_continue.set() - - def test_get(self): - queue = self.Queue() - child_can_start = self.Event() - parent_can_continue = self.Event() - - proc = self.Process( - target=self._test_get, - args=(queue, child_can_start, parent_can_continue) - ) - proc.daemon = True - proc.start() - - self.assertEqual(queue_empty(queue), True) - - child_can_start.set() - parent_can_continue.wait() - - time.sleep(DELTA) - self.assertEqual(queue_empty(queue), False) - - # Hangs unexpectedly, remove for now - #self.assertEqual(queue.get(), 1) - self.assertEqual(queue.get(True, None), 2) - self.assertEqual(queue.get(True), 3) - self.assertEqual(queue.get(timeout=1), 4) - self.assertEqual(queue.get_nowait(), 5) - - self.assertEqual(queue_empty(queue), True) - - get = TimingWrapper(queue.get) - get_nowait = TimingWrapper(queue.get_nowait) - - self.assertRaises(pyqueue.Empty, get, False) - self.assertTimingAlmostEqual(get.elapsed, 0) - - self.assertRaises(pyqueue.Empty, get, False, None) - self.assertTimingAlmostEqual(get.elapsed, 0) - - self.assertRaises(pyqueue.Empty, get_nowait) - self.assertTimingAlmostEqual(get_nowait.elapsed, 0) - - self.assertRaises(pyqueue.Empty, get, True, TIMEOUT1) - self.assertTimingAlmostEqual(get.elapsed, TIMEOUT1) - - self.assertRaises(pyqueue.Empty, get, False, TIMEOUT2) - self.assertTimingAlmostEqual(get.elapsed, 0) - - self.assertRaises(pyqueue.Empty, get, timeout=TIMEOUT3) - self.assertTimingAlmostEqual(get.elapsed, TIMEOUT3) - - proc.join() - - def _test_fork(self, queue): - for i in range(10, 20): - queue.put(i) - # note that at this point the items may only be buffered, so the - # process cannot shutdown until the feeder thread has finished - # pushing items onto the pipe. - - def test_fork(self): - # Old versions of Queue would fail to create a new feeder - # thread for a forked process if the original process had its - # own feeder thread. This test checks that this no longer - # happens. - - queue = self.Queue() - - # put items on queue so that main process starts a feeder thread - for i in range(10): - queue.put(i) - - # wait to make sure thread starts before we fork a new process - time.sleep(DELTA) - - # fork process - p = self.Process(target=self._test_fork, args=(queue,)) - p.start() - - # check that all expected items are in the queue - for i in range(20): - self.assertEqual(queue.get(), i) - self.assertRaises(pyqueue.Empty, queue.get, False) - - p.join() - - def test_qsize(self): - q = self.Queue() - try: - self.assertEqual(q.qsize(), 0) - except NotImplementedError: - return - q.put(1) - self.assertEqual(q.qsize(), 1) - q.put(5) - self.assertEqual(q.qsize(), 2) - q.get() - self.assertEqual(q.qsize(), 1) - q.get() - self.assertEqual(q.qsize(), 0) - - def _test_task_done(self, q): - for obj in iter(q.get, None): - time.sleep(DELTA) - q.task_done() - - def test_task_done(self): - queue = self.JoinableQueue() - - if sys.version_info < (2, 5) and not hasattr(queue, 'task_done'): - return - - workers = [self.Process(target=self._test_task_done, args=(queue,)) - for i in range(4)] - - for p in workers: - p.start() - - for i in range(10): - queue.put(i) - - queue.join() - - for p in workers: - queue.put(None) - - for p in workers: - p.join() - -# -# -# - -class _TestLock(BaseTestCase): - - def test_lock(self): - lock = self.Lock() - self.assertEqual(lock.acquire(), True) - self.assertEqual(lock.acquire(False), False) - self.assertEqual(lock.release(), None) - self.assertRaises((ValueError, threading.ThreadError), lock.release) - - def test_rlock(self): - lock = self.RLock() - self.assertEqual(lock.acquire(), True) - self.assertEqual(lock.acquire(), True) - self.assertEqual(lock.acquire(), True) - self.assertEqual(lock.release(), None) - self.assertEqual(lock.release(), None) - self.assertEqual(lock.release(), None) - self.assertRaises((AssertionError, RuntimeError), lock.release) - - -class _TestSemaphore(BaseTestCase): - - def _test_semaphore(self, sem): - self.assertReturnsIfImplemented(2, get_value, sem) - self.assertEqual(sem.acquire(), True) - self.assertReturnsIfImplemented(1, get_value, sem) - self.assertEqual(sem.acquire(), True) - self.assertReturnsIfImplemented(0, get_value, sem) - self.assertEqual(sem.acquire(False), False) - self.assertReturnsIfImplemented(0, get_value, sem) - self.assertEqual(sem.release(), None) - self.assertReturnsIfImplemented(1, get_value, sem) - self.assertEqual(sem.release(), None) - self.assertReturnsIfImplemented(2, get_value, sem) - - def test_semaphore(self): - sem = self.Semaphore(2) - self._test_semaphore(sem) - self.assertEqual(sem.release(), None) - self.assertReturnsIfImplemented(3, get_value, sem) - self.assertEqual(sem.release(), None) - self.assertReturnsIfImplemented(4, get_value, sem) - - def test_bounded_semaphore(self): - sem = self.BoundedSemaphore(2) - self._test_semaphore(sem) - # Currently fails on OS/X - #if HAVE_GETVALUE: - # self.assertRaises(ValueError, sem.release) - # self.assertReturnsIfImplemented(2, get_value, sem) - - def test_timeout(self): - if self.TYPE != 'processes': - return - - sem = self.Semaphore(0) - acquire = TimingWrapper(sem.acquire) - - self.assertEqual(acquire(False), False) - self.assertTimingAlmostEqual(acquire.elapsed, 0.0) - - self.assertEqual(acquire(False, None), False) - self.assertTimingAlmostEqual(acquire.elapsed, 0.0) - - self.assertEqual(acquire(False, TIMEOUT1), False) - self.assertTimingAlmostEqual(acquire.elapsed, 0) - - self.assertEqual(acquire(True, TIMEOUT2), False) - self.assertTimingAlmostEqual(acquire.elapsed, TIMEOUT2) - - self.assertEqual(acquire(timeout=TIMEOUT3), False) - self.assertTimingAlmostEqual(acquire.elapsed, TIMEOUT3) - - -class _TestCondition(BaseTestCase): - - def f(self, cond, sleeping, woken, timeout=None): - cond.acquire() - sleeping.release() - cond.wait(timeout) - woken.release() - cond.release() - - def check_invariant(self, cond): - # this is only supposed to succeed when there are no sleepers - if self.TYPE == 'processes': - try: - sleepers = (cond._sleeping_count.get_value() - - cond._woken_count.get_value()) - self.assertEqual(sleepers, 0) - self.assertEqual(cond._wait_semaphore.get_value(), 0) - except NotImplementedError: - pass - - def test_notify(self): - cond = self.Condition() - sleeping = self.Semaphore(0) - woken = self.Semaphore(0) - - p = self.Process(target=self.f, args=(cond, sleeping, woken)) - p.daemon = True - p.start() - - p = threading.Thread(target=self.f, args=(cond, sleeping, woken)) - p.daemon = True - p.start() - - # wait for both children to start sleeping - sleeping.acquire() - sleeping.acquire() - - # check no process/thread has woken up - time.sleep(DELTA) - self.assertReturnsIfImplemented(0, get_value, woken) - - # wake up one process/thread - cond.acquire() - cond.notify() - cond.release() - - # check one process/thread has woken up - time.sleep(DELTA) - self.assertReturnsIfImplemented(1, get_value, woken) - - # wake up another - cond.acquire() - cond.notify() - cond.release() - - # check other has woken up - time.sleep(DELTA) - self.assertReturnsIfImplemented(2, get_value, woken) - - # check state is not mucked up - self.check_invariant(cond) - p.join() - - def test_notify_all(self): - cond = self.Condition() - sleeping = self.Semaphore(0) - woken = self.Semaphore(0) - - # start some threads/processes which will timeout - for i in range(3): - p = self.Process(target=self.f, - args=(cond, sleeping, woken, TIMEOUT1)) - p.daemon = True - p.start() - - t = threading.Thread(target=self.f, - args=(cond, sleeping, woken, TIMEOUT1)) - t.daemon = True - t.start() - - # wait for them all to sleep - for i in range(6): - sleeping.acquire() - - # check they have all timed out - for i in range(6): - woken.acquire() - self.assertReturnsIfImplemented(0, get_value, woken) - - # check state is not mucked up - self.check_invariant(cond) - - # start some more threads/processes - for i in range(3): - p = self.Process(target=self.f, args=(cond, sleeping, woken)) - p.daemon = True - p.start() - - t = threading.Thread(target=self.f, args=(cond, sleeping, woken)) - t.daemon = True - t.start() - - # wait for them to all sleep - for i in range(6): - sleeping.acquire() - - # check no process/thread has woken up - time.sleep(DELTA) - self.assertReturnsIfImplemented(0, get_value, woken) - - # wake them all up - cond.acquire() - cond.notify_all() - cond.release() - - # check they have all woken - time.sleep(DELTA) - self.assertReturnsIfImplemented(6, get_value, woken) - - # check state is not mucked up - self.check_invariant(cond) - - def test_timeout(self): - cond = self.Condition() - wait = TimingWrapper(cond.wait) - cond.acquire() - res = wait(TIMEOUT1) - cond.release() - self.assertEqual(res, None) - self.assertTimingAlmostEqual(wait.elapsed, TIMEOUT1) - - -class _TestEvent(BaseTestCase): - - def _test_event(self, event): - time.sleep(TIMEOUT2) - event.set() - - def test_event(self): - event = self.Event() - wait = TimingWrapper(event.wait) - - # Removed temporaily, due to API shear, this does not - # work with threading._Event objects. is_set == isSet - #self.assertEqual(event.is_set(), False) - - self.assertEqual(wait(0.0), None) - self.assertTimingAlmostEqual(wait.elapsed, 0.0) - self.assertEqual(wait(TIMEOUT1), None) - self.assertTimingAlmostEqual(wait.elapsed, TIMEOUT1) - - event.set() - - # See note above on the API differences - # self.assertEqual(event.is_set(), True) - self.assertEqual(wait(), None) - self.assertTimingAlmostEqual(wait.elapsed, 0.0) - self.assertEqual(wait(TIMEOUT1), None) - self.assertTimingAlmostEqual(wait.elapsed, 0.0) - # self.assertEqual(event.is_set(), True) - - event.clear() - - #self.assertEqual(event.is_set(), False) - - self.Process(target=self._test_event, args=(event,)).start() - self.assertEqual(wait(), None) - -# -# -# - -class _TestValue(BaseTestCase): - - codes_values = [ - ('i', 4343, 24234), - ('d', 3.625, -4.25), - ('h', -232, 234), - ('c', latin('x'), latin('y')) - ] - - def _test(self, values): - for sv, cv in zip(values, self.codes_values): - sv.value = cv[2] - - - def test_value(self, raw=False): - if self.TYPE != 'processes': - return - - if raw: - values = [self.RawValue(code, value) - for code, value, _ in self.codes_values] - else: - values = [self.Value(code, value) - for code, value, _ in self.codes_values] - - for sv, cv in zip(values, self.codes_values): - self.assertEqual(sv.value, cv[1]) - - proc = self.Process(target=self._test, args=(values,)) - proc.start() - proc.join() - - for sv, cv in zip(values, self.codes_values): - self.assertEqual(sv.value, cv[2]) - - def test_rawvalue(self): - self.test_value(raw=True) - - def test_getobj_getlock(self): - if self.TYPE != 'processes': - return - - val1 = self.Value('i', 5) - lock1 = val1.get_lock() - obj1 = val1.get_obj() - - val2 = self.Value('i', 5, lock=None) - lock2 = val2.get_lock() - obj2 = val2.get_obj() - - lock = self.Lock() - val3 = self.Value('i', 5, lock=lock) - lock3 = val3.get_lock() - obj3 = val3.get_obj() - self.assertEqual(lock, lock3) - - arr4 = self.Value('i', 5, lock=False) - self.assertFalse(hasattr(arr4, 'get_lock')) - self.assertFalse(hasattr(arr4, 'get_obj')) - - self.assertRaises(AttributeError, self.Value, 'i', 5, lock='navalue') - - arr5 = self.RawValue('i', 5) - self.assertFalse(hasattr(arr5, 'get_lock')) - self.assertFalse(hasattr(arr5, 'get_obj')) - - -class _TestArray(BaseTestCase): - - def f(self, seq): - for i in range(1, len(seq)): - seq[i] += seq[i-1] - - def test_array(self, raw=False): - if self.TYPE != 'processes': - return - - seq = [680, 626, 934, 821, 150, 233, 548, 982, 714, 831] - if raw: - arr = self.RawArray('i', seq) - else: - arr = self.Array('i', seq) - - self.assertEqual(len(arr), len(seq)) - self.assertEqual(arr[3], seq[3]) - self.assertEqual(list(arr[2:7]), list(seq[2:7])) - - arr[4:8] = seq[4:8] = array.array('i', [1, 2, 3, 4]) - - self.assertEqual(list(arr[:]), seq) - - self.f(seq) - - p = self.Process(target=self.f, args=(arr,)) - p.start() - p.join() - - self.assertEqual(list(arr[:]), seq) - - def test_rawarray(self): - self.test_array(raw=True) - - def test_getobj_getlock_obj(self): - if self.TYPE != 'processes': - return - - arr1 = self.Array('i', list(range(10))) - lock1 = arr1.get_lock() - obj1 = arr1.get_obj() - - arr2 = self.Array('i', list(range(10)), lock=None) - lock2 = arr2.get_lock() - obj2 = arr2.get_obj() - - lock = self.Lock() - arr3 = self.Array('i', list(range(10)), lock=lock) - lock3 = arr3.get_lock() - obj3 = arr3.get_obj() - self.assertEqual(lock, lock3) - - arr4 = self.Array('i', range(10), lock=False) - self.assertFalse(hasattr(arr4, 'get_lock')) - self.assertFalse(hasattr(arr4, 'get_obj')) - self.assertRaises(AttributeError, - self.Array, 'i', range(10), lock='notalock') - - arr5 = self.RawArray('i', range(10)) - self.assertFalse(hasattr(arr5, 'get_lock')) - self.assertFalse(hasattr(arr5, 'get_obj')) - -# -# -# - -class _TestContainers(BaseTestCase): - - ALLOWED_TYPES = ('manager',) - - def test_list(self): - a = self.list(list(range(10))) - self.assertEqual(a[:], list(range(10))) - - b = self.list() - self.assertEqual(b[:], []) - - b.extend(list(range(5))) - self.assertEqual(b[:], list(range(5))) - - self.assertEqual(b[2], 2) - self.assertEqual(b[2:10], [2,3,4]) - - b *= 2 - self.assertEqual(b[:], [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]) - - self.assertEqual(b + [5, 6], [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6]) - - self.assertEqual(a[:], list(range(10))) - - d = [a, b] - e = self.list(d) - self.assertEqual( - e[:], - [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]] - ) - - f = self.list([a]) - a.append('hello') - self.assertEqual(f[:], [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'hello']]) - - def test_dict(self): - d = self.dict() - indices = list(range(65, 70)) - for i in indices: - d[i] = chr(i) - self.assertEqual(d.copy(), dict((i, chr(i)) for i in indices)) - self.assertEqual(sorted(d.keys()), indices) - self.assertEqual(sorted(d.values()), [chr(i) for i in indices]) - self.assertEqual(sorted(d.items()), [(i, chr(i)) for i in indices]) - - def test_namespace(self): - n = self.Namespace() - n.name = 'Bob' - n.job = 'Builder' - n._hidden = 'hidden' - self.assertEqual((n.name, n.job), ('Bob', 'Builder')) - del n.job - self.assertEqual(str(n), "Namespace(name='Bob')") - self.assertTrue(hasattr(n, 'name')) - self.assertTrue(not hasattr(n, 'job')) - -# -# -# - -def sqr(x, wait=0.0): - time.sleep(wait) - return x*x -class _TestPool(BaseTestCase): - - def test_apply(self): - papply = self.pool.apply - self.assertEqual(papply(sqr, (5,)), sqr(5)) - self.assertEqual(papply(sqr, (), {'x':3}), sqr(x=3)) - - def test_map(self): - pmap = self.pool.map - self.assertEqual(pmap(sqr, list(range(10))), list(map(sqr, list(range(10))))) - self.assertEqual(pmap(sqr, list(range(100)), chunksize=20), - list(map(sqr, list(range(100))))) - - def test_async(self): - res = self.pool.apply_async(sqr, (7, TIMEOUT1,)) - get = TimingWrapper(res.get) - self.assertEqual(get(), 49) - self.assertTimingAlmostEqual(get.elapsed, TIMEOUT1) - - def test_async_timeout(self): - res = self.pool.apply_async(sqr, (6, TIMEOUT2 + 0.2)) - get = TimingWrapper(res.get) - self.assertRaises(multiprocessing.TimeoutError, get, timeout=TIMEOUT2) - self.assertTimingAlmostEqual(get.elapsed, TIMEOUT2) - - def test_imap(self): - it = self.pool.imap(sqr, list(range(10))) - self.assertEqual(list(it), list(map(sqr, list(range(10))))) - - it = self.pool.imap(sqr, list(range(10))) - for i in range(10): - self.assertEqual(next(it), i*i) - self.assertRaises(StopIteration, it.__next__) - - it = self.pool.imap(sqr, list(range(1000)), chunksize=100) - for i in range(1000): - self.assertEqual(next(it), i*i) - self.assertRaises(StopIteration, it.__next__) - - def test_imap_unordered(self): - it = self.pool.imap_unordered(sqr, list(range(1000))) - self.assertEqual(sorted(it), list(map(sqr, list(range(1000))))) - - it = self.pool.imap_unordered(sqr, list(range(1000)), chunksize=53) - self.assertEqual(sorted(it), list(map(sqr, list(range(1000))))) - - def test_make_pool(self): - p = multiprocessing.Pool(3) - self.assertEqual(3, len(p._pool)) - p.close() - p.join() - - def test_terminate(self): - if self.TYPE == 'manager': - # On Unix a forked process increfs each shared object to - # which its parent process held a reference. If the - # forked process gets terminated then there is likely to - # be a reference leak. So to prevent - # _TestZZZNumberOfObjects from failing we skip this test - # when using a manager. - return - - result = self.pool.map_async( - time.sleep, [0.1 for i in range(10000)], chunksize=1 - ) - self.pool.terminate() - join = TimingWrapper(self.pool.join) - join() - self.assertTrue(join.elapsed < 0.2) -# -# Test that manager has expected number of shared objects left -# - -class _TestZZZNumberOfObjects(BaseTestCase): - # Because test cases are sorted alphabetically, this one will get - # run after all the other tests for the manager. It tests that - # there have been no "reference leaks" for the manager's shared - # objects. Note the comment in _TestPool.test_terminate(). - ALLOWED_TYPES = ('manager',) - - def test_number_of_objects(self): - EXPECTED_NUMBER = 1 # the pool object is still alive - multiprocessing.active_children() # discard dead process objs - gc.collect() # do garbage collection - refs = self.manager._number_of_objects() - debug_info = self.manager._debug_info() - if refs != EXPECTED_NUMBER: - print(self.manager._debug_info()) - print(debug_info) - - self.assertEqual(refs, EXPECTED_NUMBER) - -# -# Test of creating a customized manager class -# - -from multiprocessing.managers import BaseManager, BaseProxy, RemoteError - -class FooBar(object): - def f(self): - return 'f()' - def g(self): - raise ValueError - def _h(self): - return '_h()' - -def baz(): - for i in range(10): - yield i*i - -class IteratorProxy(BaseProxy): - _exposed_ = ('next', '__next__') - def __iter__(self): - return self - def __next__(self): - return self._callmethod('next') - def __next__(self): - return self._callmethod('__next__') - -class MyManager(BaseManager): - pass - -MyManager.register('Foo', callable=FooBar) -MyManager.register('Bar', callable=FooBar, exposed=('f', '_h')) -MyManager.register('baz', callable=baz, proxytype=IteratorProxy) - - -class _TestMyManager(BaseTestCase): - - ALLOWED_TYPES = ('manager',) - - def test_mymanager(self): - manager = MyManager() - manager.start() - - foo = manager.Foo() - bar = manager.Bar() - baz = manager.baz() - - foo_methods = [name for name in ('f', 'g', '_h') if hasattr(foo, name)] - bar_methods = [name for name in ('f', 'g', '_h') if hasattr(bar, name)] - - self.assertEqual(foo_methods, ['f', 'g']) - self.assertEqual(bar_methods, ['f', '_h']) - - self.assertEqual(foo.f(), 'f()') - self.assertRaises(ValueError, foo.g) - self.assertEqual(foo._callmethod('f'), 'f()') - self.assertRaises(RemoteError, foo._callmethod, '_h') - - self.assertEqual(bar.f(), 'f()') - self.assertEqual(bar._h(), '_h()') - self.assertEqual(bar._callmethod('f'), 'f()') - self.assertEqual(bar._callmethod('_h'), '_h()') - - self.assertEqual(list(baz), [i*i for i in range(10)]) - - manager.shutdown() - -# -# Test of connecting to a remote server and using xmlrpclib for serialization -# - -_queue = pyqueue.Queue() -def get_queue(): - return _queue - -class QueueManager(BaseManager): - '''manager class used by server process''' -QueueManager.register('get_queue', callable=get_queue) - -class QueueManager2(BaseManager): - '''manager class which specifies the same interface as QueueManager''' -QueueManager2.register('get_queue') - - -SERIALIZER = 'xmlrpclib' - -class _TestRemoteManager(BaseTestCase): - - ALLOWED_TYPES = ('manager',) - - def _putter(self, address, authkey): - manager = QueueManager2( - address=address, authkey=authkey, serializer=SERIALIZER - ) - manager.connect() - queue = manager.get_queue() - queue.put(('hello world', None, True, 2.25)) - - def test_remote(self): - authkey = os.urandom(32) - - manager = QueueManager( - address=('localhost', 0), authkey=authkey, serializer=SERIALIZER - ) - manager.start() - - p = self.Process(target=self._putter, args=(manager.address, authkey)) - p.start() - - manager2 = QueueManager2( - address=manager.address, authkey=authkey, serializer=SERIALIZER - ) - manager2.connect() - queue = manager2.get_queue() - - # Note that xmlrpclib will deserialize object as a list not a tuple - self.assertEqual(queue.get(), ['hello world', None, True, 2.25]) - - # Because we are using xmlrpclib for serialization instead of - # pickle this will cause a serialization error. - self.assertRaises(Exception, queue.put, time.sleep) - - # Make queue finalizer run before the server is stopped - del queue - manager.shutdown() - -class _TestManagerRestart(BaseTestCase): - - def _putter(self, address, authkey): - manager = QueueManager( - address=address, authkey=authkey, serializer=SERIALIZER) - manager.connect() - queue = manager.get_queue() - queue.put('hello world') - - def test_rapid_restart(self): - authkey = os.urandom(32) - manager = QueueManager( - address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) - manager.start() - - p = self.Process(target=self._putter, args=(manager.address, authkey)) - p.start() - queue = manager.get_queue() - self.assertEqual(queue.get(), 'hello world') - manager.shutdown() - manager = QueueManager( - address=('localhost', 9999), authkey=authkey, serializer=SERIALIZER) - manager.start() - -# -# -# - -SENTINEL = latin('') - -class _TestConnection(BaseTestCase): - - ALLOWED_TYPES = ('processes', 'threads') - - def _echo(self, conn): - for msg in iter(conn.recv_bytes, SENTINEL): - conn.send_bytes(msg) - conn.close() - - def test_connection(self): - conn, child_conn = self.Pipe() - - p = self.Process(target=self._echo, args=(child_conn,)) - p.daemon = True - p.start() - - seq = [1, 2.25, None] - msg = latin('hello world') - longmsg = msg * 10 - arr = array.array('i', list(range(4))) - - if self.TYPE == 'processes': - self.assertEqual(type(conn.fileno()), int) - - self.assertEqual(conn.send(seq), None) - self.assertEqual(conn.recv(), seq) - - self.assertEqual(conn.send_bytes(msg), None) - self.assertEqual(conn.recv_bytes(), msg) - - if self.TYPE == 'processes': - buffer = array.array('i', [0]*10) - expected = list(arr) + [0] * (10 - len(arr)) - self.assertEqual(conn.send_bytes(arr), None) - self.assertEqual(conn.recv_bytes_into(buffer), - len(arr) * buffer.itemsize) - self.assertEqual(list(buffer), expected) - - buffer = array.array('i', [0]*10) - expected = [0] * 3 + list(arr) + [0] * (10 - 3 - len(arr)) - self.assertEqual(conn.send_bytes(arr), None) - self.assertEqual(conn.recv_bytes_into(buffer, 3 * buffer.itemsize), - len(arr) * buffer.itemsize) - self.assertEqual(list(buffer), expected) - - buffer = bytearray(latin(' ' * 40)) - self.assertEqual(conn.send_bytes(longmsg), None) - try: - res = conn.recv_bytes_into(buffer) - except multiprocessing.BufferTooShort as e: - self.assertEqual(e.args, (longmsg,)) - else: - self.fail('expected BufferTooShort, got %s' % res) - - poll = TimingWrapper(conn.poll) - - self.assertEqual(poll(), False) - self.assertTimingAlmostEqual(poll.elapsed, 0) - - self.assertEqual(poll(TIMEOUT1), False) - self.assertTimingAlmostEqual(poll.elapsed, TIMEOUT1) - - conn.send(None) - - self.assertEqual(poll(TIMEOUT1), True) - self.assertTimingAlmostEqual(poll.elapsed, 0) - - self.assertEqual(conn.recv(), None) - - really_big_msg = latin('X') * (1024 * 1024 * 16) # 16Mb - conn.send_bytes(really_big_msg) - self.assertEqual(conn.recv_bytes(), really_big_msg) - - conn.send_bytes(SENTINEL) # tell child to quit - child_conn.close() - - if self.TYPE == 'processes': - self.assertEqual(conn.readable, True) - self.assertEqual(conn.writable, True) - self.assertRaises(EOFError, conn.recv) - self.assertRaises(EOFError, conn.recv_bytes) - - p.join() - - def test_duplex_false(self): - reader, writer = self.Pipe(duplex=False) - self.assertEqual(writer.send(1), None) - self.assertEqual(reader.recv(), 1) - if self.TYPE == 'processes': - self.assertEqual(reader.readable, True) - self.assertEqual(reader.writable, False) - self.assertEqual(writer.readable, False) - self.assertEqual(writer.writable, True) - self.assertRaises(IOError, reader.send, 2) - self.assertRaises(IOError, writer.recv) - self.assertRaises(IOError, writer.poll) - - def test_spawn_close(self): - # We test that a pipe connection can be closed by parent - # process immediately after child is spawned. On Windows this - # would have sometimes failed on old versions because - # child_conn would be closed before the child got a chance to - # duplicate it. - conn, child_conn = self.Pipe() - - p = self.Process(target=self._echo, args=(child_conn,)) - p.start() - child_conn.close() # this might complete before child initializes - - msg = latin('hello') - conn.send_bytes(msg) - self.assertEqual(conn.recv_bytes(), msg) - - conn.send_bytes(SENTINEL) - conn.close() - p.join() - - def test_sendbytes(self): - if self.TYPE != 'processes': - return - - msg = latin('abcdefghijklmnopqrstuvwxyz') - a, b = self.Pipe() - - a.send_bytes(msg) - self.assertEqual(b.recv_bytes(), msg) - - a.send_bytes(msg, 5) - self.assertEqual(b.recv_bytes(), msg[5:]) - - a.send_bytes(msg, 7, 8) - self.assertEqual(b.recv_bytes(), msg[7:7+8]) - - a.send_bytes(msg, 26) - self.assertEqual(b.recv_bytes(), latin('')) - - a.send_bytes(msg, 26, 0) - self.assertEqual(b.recv_bytes(), latin('')) - - self.assertRaises(ValueError, a.send_bytes, msg, 27) - - self.assertRaises(ValueError, a.send_bytes, msg, 22, 5) - - self.assertRaises(ValueError, a.send_bytes, msg, 26, 1) - - self.assertRaises(ValueError, a.send_bytes, msg, -1) - - self.assertRaises(ValueError, a.send_bytes, msg, 4, -1) - -class _TestListenerClient(BaseTestCase): - - ALLOWED_TYPES = ('processes', 'threads') - - def _test(self, address): - conn = self.connection.Client(address) - conn.send('hello') - conn.close() - - def test_listener_client(self): - for family in self.connection.families: - l = self.connection.Listener(family=family) - p = self.Process(target=self._test, args=(l.address,)) - p.daemon = True - p.start() - conn = l.accept() - self.assertEqual(conn.recv(), 'hello') - p.join() - l.close() -# -# Test of sending connection and socket objects between processes -# -""" -class _TestPicklingConnections(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def _listener(self, conn, families): - for fam in families: - l = self.connection.Listener(family=fam) - conn.send(l.address) - new_conn = l.accept() - conn.send(new_conn) - - if self.TYPE == 'processes': - l = socket.socket() - l.bind(('localhost', 0)) - conn.send(l.getsockname()) - l.listen(1) - new_conn, addr = l.accept() - conn.send(new_conn) - - conn.recv() - - def _remote(self, conn): - for (address, msg) in iter(conn.recv, None): - client = self.connection.Client(address) - client.send(msg.upper()) - client.close() - - if self.TYPE == 'processes': - address, msg = conn.recv() - client = socket.socket() - client.connect(address) - client.sendall(msg.upper()) - client.close() - - conn.close() - - def test_pickling(self): - try: - multiprocessing.allow_connection_pickling() - except ImportError: - return - - families = self.connection.families - - lconn, lconn0 = self.Pipe() - lp = self.Process(target=self._listener, args=(lconn0, families)) - lp.start() - lconn0.close() - - rconn, rconn0 = self.Pipe() - rp = self.Process(target=self._remote, args=(rconn0,)) - rp.start() - rconn0.close() - - for fam in families: - msg = ('This connection uses family %s' % fam).encode('ascii') - address = lconn.recv() - rconn.send((address, msg)) - new_conn = lconn.recv() - self.assertEqual(new_conn.recv(), msg.upper()) - - rconn.send(None) - - if self.TYPE == 'processes': - msg = latin('This connection uses a normal socket') - address = lconn.recv() - rconn.send((address, msg)) - if hasattr(socket, 'fromfd'): - new_conn = lconn.recv() - self.assertEqual(new_conn.recv(100), msg.upper()) - else: - # XXX On Windows with Py2.6 need to backport fromfd() - discard = lconn.recv_bytes() - - lconn.send(None) - - rconn.close() - lconn.close() - - lp.join() - rp.join() -""" -# -# -# - -class _TestHeap(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def test_heap(self): - iterations = 5000 - maxblocks = 50 - blocks = [] - - # create and destroy lots of blocks of different sizes - for i in range(iterations): - size = int(random.lognormvariate(0, 1) * 1000) - b = multiprocessing.heap.BufferWrapper(size) - blocks.append(b) - if len(blocks) > maxblocks: - i = random.randrange(maxblocks) - del blocks[i] - - # get the heap object - heap = multiprocessing.heap.BufferWrapper._heap - - # verify the state of the heap - all = [] - occupied = 0 - for L in list(heap._len_to_seq.values()): - for arena, start, stop in L: - all.append((heap._arenas.index(arena), start, stop, - stop-start, 'free')) - for arena, start, stop in heap._allocated_blocks: - all.append((heap._arenas.index(arena), start, stop, - stop-start, 'occupied')) - occupied += (stop-start) - - all.sort() - - for i in range(len(all)-1): - (arena, start, stop) = all[i][:3] - (narena, nstart, nstop) = all[i+1][:3] - self.assertTrue((arena != narena and nstart == 0) or - (stop == nstart)) - -# -# -# - -try: - from ctypes import Structure, Value, copy, c_int, c_double -except ImportError: - Structure = object - c_int = c_double = None - -class _Foo(Structure): - _fields_ = [ - ('x', c_int), - ('y', c_double) - ] - -class _TestSharedCTypes(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def _double(self, x, y, foo, arr, string): - x.value *= 2 - y.value *= 2 - foo.x *= 2 - foo.y *= 2 - string.value *= 2 - for i in range(len(arr)): - arr[i] *= 2 - - def test_sharedctypes(self, lock=False): - if c_int is None: - return - - x = Value('i', 7, lock=lock) - y = Value(ctypes.c_double, 1.0/3.0, lock=lock) - foo = Value(_Foo, 3, 2, lock=lock) - arr = Array('d', list(range(10)), lock=lock) - string = Array('c', 20, lock=lock) - string.value = 'hello' - - p = self.Process(target=self._double, args=(x, y, foo, arr, string)) - p.start() - p.join() - - self.assertEqual(x.value, 14) - self.assertAlmostEqual(y.value, 2.0/3.0) - self.assertEqual(foo.x, 6) - self.assertAlmostEqual(foo.y, 4.0) - for i in range(10): - self.assertAlmostEqual(arr[i], i*2) - self.assertEqual(string.value, latin('hellohello')) - - def test_synchronize(self): - self.test_sharedctypes(lock=True) - - def test_copy(self): - if c_int is None: - return - - foo = _Foo(2, 5.0) - bar = copy(foo) - foo.x = 0 - foo.y = 0 - self.assertEqual(bar.x, 2) - self.assertAlmostEqual(bar.y, 5.0) - -# -# -# - -class _TestFinalize(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def _test_finalize(self, conn): - class Foo(object): - pass - - a = Foo() - util.Finalize(a, conn.send, args=('a',)) - del a # triggers callback for a - - b = Foo() - close_b = util.Finalize(b, conn.send, args=('b',)) - close_b() # triggers callback for b - close_b() # does nothing because callback has already been called - del b # does nothing because callback has already been called - - c = Foo() - util.Finalize(c, conn.send, args=('c',)) - - d10 = Foo() - util.Finalize(d10, conn.send, args=('d10',), exitpriority=1) - - d01 = Foo() - util.Finalize(d01, conn.send, args=('d01',), exitpriority=0) - d02 = Foo() - util.Finalize(d02, conn.send, args=('d02',), exitpriority=0) - d03 = Foo() - util.Finalize(d03, conn.send, args=('d03',), exitpriority=0) - - util.Finalize(None, conn.send, args=('e',), exitpriority=-10) - - util.Finalize(None, conn.send, args=('STOP',), exitpriority=-100) - - # call mutliprocessing's cleanup function then exit process without - # garbage collecting locals - util._exit_function() - conn.close() - os._exit(0) - - def test_finalize(self): - conn, child_conn = self.Pipe() - - p = self.Process(target=self._test_finalize, args=(child_conn,)) - p.start() - p.join() - - result = [obj for obj in iter(conn.recv, 'STOP')] - self.assertEqual(result, ['a', 'b', 'd10', 'd03', 'd02', 'd01', 'e']) - -# -# Test that from ... import * works for each module -# - -class _TestImportStar(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def test_import(self): - modules = ( - 'multiprocessing', 'multiprocessing.connection', - 'multiprocessing.heap', 'multiprocessing.managers', - 'multiprocessing.pool', 'multiprocessing.process', - 'multiprocessing.reduction', 'multiprocessing.sharedctypes', - 'multiprocessing.synchronize', 'multiprocessing.util' - ) - - for name in modules: - __import__(name) - mod = sys.modules[name] - - for attr in getattr(mod, '__all__', ()): - self.assertTrue( - hasattr(mod, attr), - '%r does not have attribute %r' % (mod, attr) - ) - -# -# Quick test that logging works -- does not test logging output -# - -class _TestLogging(BaseTestCase): - - ALLOWED_TYPES = ('processes',) - - def test_enable_logging(self): - logger = multiprocessing.get_logger() - logger.setLevel(util.SUBWARNING) - self.assertTrue(logger is not None) - logger.debug('this will not be printed') - logger.info('nor will this') - logger.setLevel(LOG_LEVEL) - - def _test_level(self, conn): - logger = multiprocessing.get_logger() - conn.send(logger.getEffectiveLevel()) - - def test_level(self): - LEVEL1 = 32 - LEVEL2 = 37 - - logger = multiprocessing.get_logger() - root_logger = logging.getLogger() - root_level = root_logger.level - - reader, writer = multiprocessing.Pipe(duplex=False) - - logger.setLevel(LEVEL1) - self.Process(target=self._test_level, args=(writer,)).start() - self.assertEqual(LEVEL1, reader.recv()) - - logger.setLevel(logging.NOTSET) - root_logger.setLevel(LEVEL2) - self.Process(target=self._test_level, args=(writer,)).start() - self.assertEqual(LEVEL2, reader.recv()) - - root_logger.setLevel(root_level) - logger.setLevel(level=LOG_LEVEL) - -# -# Test to verify handle verification, see issue 3321 -# - -class TestInvalidHandle(unittest.TestCase): - - def test_invalid_handles(self): - if WIN32: - return - conn = _multiprocessing.Connection(44977608) - self.assertRaises(IOError, conn.poll) - self.assertRaises(IOError, _multiprocessing.Connection, -1) -# -# Functions used to create test cases from the base ones in this module -# - -def get_attributes(Source, names): - d = {} - for name in names: - obj = getattr(Source, name) - if type(obj) == type(get_attributes): - obj = staticmethod(obj) - d[name] = obj - return d - -def create_test_cases(Mixin, type): - result = {} - glob = globals() - Type = type[0].upper() + type[1:] - - for name in list(glob.keys()): - if name.startswith('_Test'): - base = glob[name] - if type in base.ALLOWED_TYPES: - newname = 'With' + Type + name[1:] - class Temp(base, unittest.TestCase, Mixin): - pass - result[newname] = Temp - Temp.__name__ = newname - Temp.__module__ = Mixin.__module__ - return result - -# -# Create test cases -# - -class ProcessesMixin(object): - TYPE = 'processes' - Process = multiprocessing.Process - locals().update(get_attributes(multiprocessing, ( - 'Queue', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', - 'Condition', 'Event', 'Value', 'Array', 'RawValue', - 'RawArray', 'current_process', 'active_children', 'Pipe', - 'connection', 'JoinableQueue' - ))) - -testcases_processes = create_test_cases(ProcessesMixin, type='processes') -globals().update(testcases_processes) - - -class ManagerMixin(object): - TYPE = 'manager' - Process = multiprocessing.Process - manager = object.__new__(multiprocessing.managers.SyncManager) - locals().update(get_attributes(manager, ( - 'Queue', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', - 'Condition', 'Event', 'Value', 'Array', 'list', 'dict', - 'Namespace', 'JoinableQueue' - ))) - -testcases_manager = create_test_cases(ManagerMixin, type='manager') -globals().update(testcases_manager) - - -class ThreadsMixin(object): - TYPE = 'threads' - Process = multiprocessing.dummy.Process - locals().update(get_attributes(multiprocessing.dummy, ( - 'Queue', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', - 'Condition', 'Event', 'Value', 'Array', 'current_process', - 'active_children', 'Pipe', 'connection', 'dict', 'list', - 'Namespace', 'JoinableQueue' - ))) - -testcases_threads = create_test_cases(ThreadsMixin, type='threads') -globals().update(testcases_threads) - -class OtherTest(unittest.TestCase): - # TODO: add more tests for deliver/answer challenge. - def test_deliver_challenge_auth_failure(self): - class _FakeConnection(object): - def recv_bytes(self, size): - return b'something bogus' - def send_bytes(self, data): - pass - self.assertRaises(multiprocessing.AuthenticationError, - multiprocessing.connection.deliver_challenge, - _FakeConnection(), b'abc') - - def test_answer_challenge_auth_failure(self): - class _FakeConnection(object): - def __init__(self): - self.count = 0 - def recv_bytes(self, size): - self.count += 1 - if self.count == 1: - return multiprocessing.connection.CHALLENGE - elif self.count == 2: - return b'something bogus' - return b'' - def send_bytes(self, data): - pass - self.assertRaises(multiprocessing.AuthenticationError, - multiprocessing.connection.answer_challenge, - _FakeConnection(), b'abc') - -testcases_other = [OtherTest, TestInvalidHandle] - -# -# -# - -def test_main(run=None): - if sys.platform.startswith("linux"): - try: - lock = multiprocessing.RLock() - except OSError: - from test.support import TestSkipped - raise unittest.SkipTest("OSError raises on RLock creation, see issue 3111!") - - if run is None: - from test.support import run_unittest as run - - util.get_temp_dir() # creates temp directory for use by all processes - - multiprocessing.get_logger().setLevel(LOG_LEVEL) - - ProcessesMixin.pool = multiprocessing.Pool(4) - ThreadsMixin.pool = multiprocessing.dummy.Pool(4) - ManagerMixin.manager.__init__() - ManagerMixin.manager.start() - ManagerMixin.pool = ManagerMixin.manager.Pool(4) - - testcases = ( - sorted(testcases_processes.values(), key=lambda tc:tc.__name__) + - sorted(testcases_threads.values(), key=lambda tc:tc.__name__) + - sorted(testcases_manager.values(), key=lambda tc:tc.__name__) + - testcases_other - ) - - loadTestsFromTestCase = unittest.defaultTestLoader.loadTestsFromTestCase - suite = unittest.TestSuite(loadTestsFromTestCase(tc) for tc in testcases) - run(suite) - - ThreadsMixin.pool.terminate() - ProcessesMixin.pool.terminate() - ManagerMixin.pool.terminate() - ManagerMixin.manager.shutdown() - - del ProcessesMixin.pool, ThreadsMixin.pool, ManagerMixin.pool - -def main(): - test_main(unittest.TextTestRunner(verbosity=2).run) - -if __name__ == '__main__': - main() From python-checkins at python.org Tue Mar 31 16:07:51 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 31 Mar 2009 16:07:51 +0200 (CEST) Subject: [Python-checkins] r70811 - in python/branches/release30-maint: Lib/test/test_mmap.py Misc/NEWS Modules/mmapmodule.c Message-ID: <20090331140751.F0CB11E4035@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 31 16:07:51 2009 New Revision: 70811 Log: Merged revisions 70808 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70808 | hirokazu.yamamoto | 2009-03-31 22:44:06 +0900 | 9 lines Merged revisions 70800 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70800 | hirokazu.yamamoto | 2009-03-31 22:13:05 +0900 | 1 line Issue #5387: Fixed mmap.move crash by integer overflow. ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/test/test_mmap.py python/branches/release30-maint/Misc/NEWS python/branches/release30-maint/Modules/mmapmodule.c Modified: python/branches/release30-maint/Lib/test/test_mmap.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_mmap.py (original) +++ python/branches/release30-maint/Lib/test/test_mmap.py Tue Mar 31 16:07:51 2009 @@ -335,6 +335,23 @@ mf.close() f.close() + # more excessive test + data = b"0123456789" + for dest in range(len(data)): + for src in range(len(data)): + for count in range(len(data) - max(dest, src)): + expected = data[:dest] + data[src:src+count] + data[dest+count:] + m = mmap.mmap(-1, len(data)) + m[:] = data + m.move(dest, src, count) + self.assertEqual(m[:], expected) + m.close() + + # should not crash + m = mmap.mmap(-1, 1) + self.assertRaises(ValueError, m.move, 1, 1, -1) + m.close() + def test_anonymous(self): # anonymous mmap.mmap(-1, PAGE) m = mmap.mmap(-1, PAGESIZE) Modified: python/branches/release30-maint/Misc/NEWS ============================================================================== --- python/branches/release30-maint/Misc/NEWS (original) +++ python/branches/release30-maint/Misc/NEWS Tue Mar 31 16:07:51 2009 @@ -30,6 +30,8 @@ Library ------- +- Issue #5387: Fixed mmap.move crash by integer overflow. + - Issue #5595: Fix UnboundedLocalError in ntpath.ismount(). - Issue #1174606: Calling read() without arguments of an unbounded file Modified: python/branches/release30-maint/Modules/mmapmodule.c ============================================================================== --- python/branches/release30-maint/Modules/mmapmodule.c (original) +++ python/branches/release30-maint/Modules/mmapmodule.c Tue Mar 31 16:07:51 2009 @@ -623,10 +623,8 @@ return NULL; } else { /* bounds check the values */ - if (/* end of source after end of data?? */ - ((src+count) > self->size) - /* dest will fit? */ - || (dest+count > self->size)) { + unsigned long pos = src > dest ? src : dest; + if (self->size >= pos && count > self->size - pos) { PyErr_SetString(PyExc_ValueError, "source or destination out of range"); return NULL; From python-checkins at python.org Tue Mar 31 16:17:58 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 31 Mar 2009 16:17:58 +0200 (CEST) Subject: [Python-checkins] r70812 - python/branches/py3k-short-float-repr/Python/dtoa.c Message-ID: <20090331141758.D16511E402A@bag.python.org> Author: mark.dickinson Date: Tue Mar 31 16:17:58 2009 New Revision: 70812 Log: Hook up Python's defines to the dtoa.c defines for integer types. Modified: python/branches/py3k-short-float-repr/Python/dtoa.c Modified: python/branches/py3k-short-float-repr/Python/dtoa.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/dtoa.c (original) +++ python/branches/py3k-short-float-repr/Python/dtoa.c Tue Mar 31 16:17:58 2009 @@ -194,13 +194,23 @@ #define IEEE_8087 #endif -#ifndef Long -#define Long long +#if SIZEOF_LONG==8 && SIZEOF_INT==4 +typedef int Long; +typedef unsigned int ULong; +#elif SIZEOF_LONG==4 +typedef long Long; +typedef unsigned long ULong; +#else +#error "Failed to find an exact-width 32-bit integer type" #endif -#ifndef ULong -typedef unsigned Long ULong; + +#ifndef HAVE_LONG_LONG +#define NO_LONG_LONG #endif +/* End Python #define linking */ + + #ifdef DEBUG #include "stdio.h" #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} From buildbot at python.org Tue Mar 31 16:28:47 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 14:28:47 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo 3.x Message-ID: <20090331142847.D29881E4022@bag.python.org> The Buildbot has detected a new failure of amd64 gentoo 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/amd64%20gentoo%203.x/builds/499 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed failed slave lost sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 16:30:06 2009 From: python-checkins at python.org (jeremy.hylton) Date: Tue, 31 Mar 2009 16:30:06 +0200 (CEST) Subject: [Python-checkins] r70813 - in python/branches/release26-maint: Lib/symtable.py Lib/test/test_scope.py Lib/test/test_symtable.py Python/symtable.c Message-ID: <20090331143006.49D4D1E4022@bag.python.org> Author: jeremy.hylton Date: Tue Mar 31 16:30:05 2009 New Revision: 70813 Log: Merged revisions 70801,70809 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70801 | jeremy.hylton | 2009-03-31 09:17:03 -0400 (Tue, 31 Mar 2009) | 3 lines Add is_declared_global() which distinguishes between implicit and explicit global variables. ........ r70809 | jeremy.hylton | 2009-03-31 09:48:15 -0400 (Tue, 31 Mar 2009) | 14 lines Global statements from one function leaked into parallel functions. Re http://bugs.python.org/issue4315 The symbol table used the same name dictionaries to recursively analyze each of its child blocks, even though the dictionaries are modified during analysis. The fix is to create new temporary dictionaries via the analyze_child_block(). The only information that needs to propagate back up is the names of the free variables. Add more comments and break out a helper function. This code doesn't get any easier to understand when you only look at it once a year. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/symtable.py python/branches/release26-maint/Lib/test/test_scope.py python/branches/release26-maint/Lib/test/test_symtable.py python/branches/release26-maint/Python/symtable.c Modified: python/branches/release26-maint/Lib/symtable.py ============================================================================== --- python/branches/release26-maint/Lib/symtable.py (original) +++ python/branches/release26-maint/Lib/symtable.py Tue Mar 31 16:30:05 2009 @@ -201,6 +201,9 @@ DeprecationWarning, 2) return False + def is_declared_global(self): + return bool(self.__scope == GLOBAL_EXPLICIT) + def is_local(self): return bool(self.__flags & DEF_BOUND) Modified: python/branches/release26-maint/Lib/test/test_scope.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_scope.py (original) +++ python/branches/release26-maint/Lib/test/test_scope.py Tue Mar 31 16:30:05 2009 @@ -632,6 +632,30 @@ f() # used to crash the interpreter... + def testGlobalInParallelNestedFunctions(self): + # A symbol table bug leaked the global statement from one + # function to other nested functions in the same block. + # This test verifies that a global statement in the first + # function does not affect the second function. + CODE = """def f(): + y = 1 + def g(): + global y + return y + def h(): + return y + 1 + return g, h + +y = 9 +g, h = f() +result9 = g() +result2 = h() +""" + local_ns = {} + global_ns = {} + exec CODE in local_ns, global_ns + self.assertEqual(2, global_ns["result2"]) + self.assertEqual(9, global_ns["result9"]) def test_main(): Modified: python/branches/release26-maint/Lib/test/test_symtable.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_symtable.py (original) +++ python/branches/release26-maint/Lib/test/test_symtable.py Tue Mar 31 16:30:05 2009 @@ -114,7 +114,9 @@ def test_globals(self): self.assertTrue(self.spam.lookup("glob").is_global()) + self.assertFalse(self.spam.lookup("glob").is_declared_global()) self.assertTrue(self.spam.lookup("bar").is_global()) + self.assertTrue(self.spam.lookup("bar").is_declared_global()) self.assertFalse(self.internal.lookup("x").is_global()) self.assertFalse(self.Mine.lookup("instance_var").is_global()) Modified: python/branches/release26-maint/Python/symtable.c ============================================================================== --- python/branches/release26-maint/Python/symtable.c (original) +++ python/branches/release26-maint/Python/symtable.c Tue Mar 31 16:30:05 2009 @@ -361,8 +361,9 @@ /* Decide on scope of name, given flags. - The dicts passed in as arguments are modified as necessary. - ste is passed so that flags can be updated. + The namespace dictionaries may be modified to record information + about the new name. For example, a new global will add an entry to + global. A name that was global can be changed to local. */ static int @@ -415,7 +416,7 @@ explicit? It could also be global implicit. */ else if (global && PyDict_GetItem(global, name)) { - SET_SCOPE(dict, name, GLOBAL_EXPLICIT); + SET_SCOPE(dict, name, GLOBAL_IMPLICIT); return 1; } else { @@ -424,7 +425,10 @@ SET_SCOPE(dict, name, GLOBAL_IMPLICIT); return 1; } - return 0; /* Can't get here */ + /* Should never get here. */ + PyErr_Format(PyExc_SystemError, "failed to set scope for %s", + PyString_AS_STRING(name)); + return 0; } #undef SET_SCOPE @@ -588,43 +592,68 @@ } /* Make final symbol table decisions for block of ste. + Arguments: ste -- current symtable entry (input/output) - bound -- set of variables bound in enclosing scopes (input) + bound -- set of variables bound in enclosing scopes (input). bound + is NULL for module blocks. free -- set of free variables in enclosed scopes (output) globals -- set of declared global variables in enclosing scopes (input) + + The implementation uses two mutually recursive functions, + analyze_block() and analyze_child_block(). analyze_block() is + responsible for analyzing the individual names defined in a block. + analyze_child_block() prepares temporary namespace dictionaries + used to evaluated nested blocks. + + The two functions exist because a child block should see the name + bindings of its enclosing blocks, but those bindings should not + propagate back to a parent block. */ static int +analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, + PyObject *global, PyObject* child_free); + +static int analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, PyObject *global) { - PyObject *name, *v, *local = NULL, *scope = NULL, *newbound = NULL; - PyObject *newglobal = NULL, *newfree = NULL; + PyObject *name, *v, *local = NULL, *scope = NULL; + PyObject *newbound = NULL, *newglobal = NULL; + PyObject *newfree = NULL, *allfree = NULL; int i, success = 0; Py_ssize_t pos = 0; - local = PyDict_New(); + local = PyDict_New(); /* collect new names bound in block */ if (!local) goto error; - scope = PyDict_New(); + scope = PyDict_New(); /* collect scopes defined for each name */ if (!scope) goto error; + + /* Allocate new global and bound variable dictionaries. These + dictionaries hold the names visible in nested blocks. For + ClassBlocks, the bound and global names are initialized + before analyzing names, because class bindings aren't + visible in methods. For other blocks, they are initialized + after names are analyzed. + */ + + /* TODO(jhylton): Package these dicts in a struct so that we + can write reasonable helper functions? + */ newglobal = PyDict_New(); if (!newglobal) goto error; - newfree = PyDict_New(); - if (!newfree) - goto error; newbound = PyDict_New(); if (!newbound) goto error; + newfree = PyDict_New(); + if (!newfree) + goto error; if (ste->ste_type == ClassBlock) { - /* make a copy of globals before calling analyze_name(), - because global statements in the class have no effect - on nested functions. - */ if (PyDict_Update(newglobal, global) < 0) goto error; if (bound) @@ -632,12 +661,10 @@ goto error; } - assert(PySTEntry_Check(ste)); - assert(PyDict_Check(ste->ste_symbols)); while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) { long flags = PyInt_AS_LONG(v); - if (!analyze_name(ste, scope, name, flags, bound, local, free, - global)) + if (!analyze_name(ste, scope, name, flags, + bound, local, free, global)) goto error; } @@ -654,18 +681,28 @@ goto error; } - /* Recursively call analyze_block() on each child block */ + /* Recursively call analyze_block() on each child block. + + newbound, newglobal now contain the names visible in + nested blocks. The free variables in the children will + be collected in allfree. + */ + allfree = PyDict_New(); + if (!allfree) + goto error; for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) { PyObject *c = PyList_GET_ITEM(ste->ste_children, i); PySTEntryObject* entry; assert(c && PySTEntry_Check(c)); entry = (PySTEntryObject*)c; - if (!analyze_block(entry, newbound, newfree, newglobal)) + if (!analyze_child_block(entry, newbound, newfree, newglobal, + allfree)) goto error; if (entry->ste_free || entry->ste_child_free) ste->ste_child_free = 1; } + PyDict_Update(newfree, allfree); if (ste->ste_type == FunctionBlock && !analyze_cells(scope, newfree)) goto error; if (!update_symbols(ste->ste_symbols, scope, bound, newfree, @@ -683,12 +720,54 @@ Py_XDECREF(newbound); Py_XDECREF(newglobal); Py_XDECREF(newfree); + Py_XDECREF(allfree); if (!success) assert(PyErr_Occurred()); return success; } static int +analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, + PyObject *global, PyObject* child_free) +{ + PyObject *temp_bound = NULL, *temp_global = NULL, *temp_free = NULL; + int success = 0; + + /* Copy the bound and global dictionaries. + + These dictionary are used by all blocks enclosed by the + current block. The analyze_block() call modifies these + dictionaries. + + */ + temp_bound = PyDict_New(); + if (!temp_bound) + goto error; + if (PyDict_Update(temp_bound, bound) < 0) + goto error; + temp_free = PyDict_New(); + if (!temp_free) + goto error; + if (PyDict_Update(temp_free, free) < 0) + goto error; + temp_global = PyDict_New(); + if (!temp_global) + goto error; + if (PyDict_Update(temp_global, global) < 0) + goto error; + + if (!analyze_block(entry, temp_bound, temp_free, temp_global)) + goto error; + success = PyDict_Update(child_free, temp_free) >= 0; + success = 1; + error: + Py_XDECREF(temp_bound); + Py_XDECREF(temp_free); + Py_XDECREF(temp_global); + return success; +} + +static int symtable_analyze(struct symtable *st) { PyObject *free, *global; From python-checkins at python.org Tue Mar 31 16:35:13 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 16:35:13 +0200 (CEST) Subject: [Python-checkins] r70814 - in python/branches/release26-maint: Modules/_multiprocessing/pipe_connection.c Message-ID: <20090331143513.77D6D1E402A@bag.python.org> Author: jesse.noller Date: Tue Mar 31 16:35:13 2009 New Revision: 70814 Log: Merged revisions 68787 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r68787 | jesse.noller | 2009-01-19 18:16:38 -0600 (Mon, 19 Jan 2009) | 1 line issue 5002: fix windows warning that I intro'ed with r68768 ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Modules/_multiprocessing/pipe_connection.c Modified: python/branches/release26-maint/Modules/_multiprocessing/pipe_connection.c ============================================================================== --- python/branches/release26-maint/Modules/_multiprocessing/pipe_connection.c (original) +++ python/branches/release26-maint/Modules/_multiprocessing/pipe_connection.c Tue Mar 31 16:35:13 2009 @@ -83,10 +83,8 @@ * Check whether any data is available for reading */ -#define conn_poll(conn, timeout) conn_poll_save(conn, timeout, _save) - static int -conn_poll_save(ConnectionObject *conn, double timeout, PyThreadState *_save) +conn_poll(ConnectionObject *conn, double timeout, PyThreadState *_save) { DWORD bytes, deadline, delay; int difference, res; From python-checkins at python.org Tue Mar 31 16:35:53 2009 From: python-checkins at python.org (jeremy.hylton) Date: Tue, 31 Mar 2009 16:35:53 +0200 (CEST) Subject: [Python-checkins] r70815 - in python/branches/py3k/Lib: http/client.py test/test_http_cookiejar.py test/test_urllib2.py urllib/request.py Message-ID: <20090331143553.EFB3B1E4022@bag.python.org> Author: jeremy.hylton Date: Tue Mar 31 16:35:53 2009 New Revision: 70815 Log: Simplify the Request class. The basic components of the parsed Request are now available as public attributes, e.g. full_url and host. The accessor methods are deprecated. The implementation replace the complicated __getattr__ machinery with a _parse() method. The response from an HTTP request is now an HTTPResponse instance instead of an addinfourl() wrapper instance. The wrapper provided minimal extract functionality and was undocumented. The API of addinfourl() was preserved, except for close hooks, by adding a few methods and public attributes to the HTTPResponse class. Modified: python/branches/py3k/Lib/http/client.py python/branches/py3k/Lib/test/test_http_cookiejar.py python/branches/py3k/Lib/test/test_urllib2.py python/branches/py3k/Lib/urllib/request.py Modified: python/branches/py3k/Lib/http/client.py ============================================================================== --- python/branches/py3k/Lib/http/client.py (original) +++ python/branches/py3k/Lib/http/client.py Tue Mar 31 16:35:53 2009 @@ -204,6 +204,12 @@ MAXAMOUNT = 1048576 class HTTPMessage(email.message.Message): + # XXX The only usage of this method is in + # http.server.CGIHTTPRequestHandler. Maybe move the code there so + # that it doesn't need to be part of the public API. The API has + # never been defined so this could cause backwards compatibility + # issues. + def getallmatchingheaders(self, name): """Find all header lines matching a given header name. @@ -261,20 +267,26 @@ # text following RFC 2047. The basic status line parsing only # accepts iso-8859-1. - def __init__(self, sock, debuglevel=0, strict=0, method=None): - # If the response includes a content-length header, we - # need to make sure that the client doesn't read more than the + def __init__(self, sock, debuglevel=0, strict=0, method=None, url=None): + # If the response includes a content-length header, we need to + # make sure that the client doesn't read more than the # specified number of bytes. If it does, it will block until - # the server times out and closes the connection. (The only - # applies to HTTP/1.1 connections.) This will happen if a self.fp.read() - # is done (without a size) whether self.fp is buffered or not. - # So, no self.fp.read() by clients unless they know what they are doing. + # the server times out and closes the connection. This will + # happen if a self.fp.read() is done (without a size) whether + # self.fp is buffered or not. So, no self.fp.read() by + # clients unless they know what they are doing. self.fp = sock.makefile("rb") self.debuglevel = debuglevel self.strict = strict self._method = method - self.msg = None + # The HTTPResponse object is returned via urllib. The clients + # of http and urllib expect different attributes for the + # headers. headers is used here and supports urllib. msg is + # provided as a backwards compatibility layer for http + # clients. + + self.headers = self.msg = None # from the Status-Line of the response self.version = _UNKNOWN # HTTP-Version @@ -326,7 +338,7 @@ return version, status, reason def begin(self): - if self.msg is not None: + if self.headers is not None: # we've already started reading the response return @@ -343,7 +355,7 @@ if self.debuglevel > 0: print("header:", skip) - self.status = status + self.code = self.status = status self.reason = reason.strip() if version == "HTTP/1.0": self.version = 10 @@ -358,17 +370,17 @@ self.length = None self.chunked = False self.will_close = True - self.msg = email.message_from_string('') + self.headers = self.msg = email.message_from_string('') return - self.msg = parse_headers(self.fp) + self.headers = self.msg = parse_headers(self.fp) if self.debuglevel > 0: - for hdr in self.msg: + for hdr in self.headers: print("header:", hdr, end=" ") # are we using the chunked-style of transfer encoding? - tr_enc = self.msg.get("transfer-encoding") + tr_enc = self.headers.get("transfer-encoding") if tr_enc and tr_enc.lower() == "chunked": self.chunked = True self.chunk_left = None @@ -381,10 +393,10 @@ # do we have a Content-Length? # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked" self.length = None - length = self.msg.get("content-length") + length = self.headers.get("content-length") # are we using the chunked-style of transfer encoding? - tr_enc = self.msg.get("transfer-encoding") + tr_enc = self.headers.get("transfer-encoding") if length and not self.chunked: try: self.length = int(length) @@ -411,11 +423,11 @@ self.will_close = True def _check_close(self): - conn = self.msg.get("connection") + conn = self.headers.get("connection") if self.version == 11: # An HTTP/1.1 proxy is assumed to stay open unless # explicitly closed. - conn = self.msg.get("connection") + conn = self.headers.get("connection") if conn and "close" in conn.lower(): return True return False @@ -424,7 +436,7 @@ # connections, using rules different than HTTP/1.1. # For older HTTP, Keep-Alive indicates persistent connection. - if self.msg.get("keep-alive"): + if self.headers.get("keep-alive"): return False # At least Akamai returns a "Connection: Keep-Alive" header, @@ -433,7 +445,7 @@ return False # Proxy-Connection is a netscape hack. - pconn = self.msg.get("proxy-connection") + pconn = self.headers.get("proxy-connection") if pconn and "keep-alive" in pconn.lower(): return False @@ -584,21 +596,31 @@ return self.fp.fileno() def getheader(self, name, default=None): - if self.msg is None: + if self.headers is None: raise ResponseNotReady() - return ', '.join(self.msg.get_all(name, default)) + return ', '.join(self.headers.get_all(name, default)) def getheaders(self): """Return list of (header, value) tuples.""" - if self.msg is None: + if self.headers is None: raise ResponseNotReady() - return list(self.msg.items()) + return list(self.headers.items()) # We override IOBase.__iter__ so that it doesn't check for closed-ness def __iter__(self): return self + # For compatibility with old-style urllib responses. + + def info(self): + return self.headers + + def geturl(self): + return self.url + + def getcode(self): + return self.status class HTTPConnection: @@ -757,7 +779,7 @@ if self.__state == _CS_IDLE: self.__state = _CS_REQ_STARTED else: - raise CannotSendRequest() + raise CannotSendRequest(self.__state) # Save the method we use, we need it later in the response phase self._method = method @@ -906,13 +928,23 @@ self.endheaders(body) def getresponse(self): - """Get the response from the server.""" + """Get the response from the server. + + If the HTTPConnection is in the correct state, returns an + instance of HTTPResponse or of whatever object is returned by + class the response_class variable. + + If a request has not been sent or if a previous response has + not be handled, ResponseNotReady is raised. If the HTTP + response indicates that the connection should be closed, then + it will be closed before the response is returned. When the + connection is closed, the underlying socket is closed. + """ # if a prior response has been completed, then forget about it. if self.__response and self.__response.isclosed(): self.__response = None - # # if a prior response exists, then it must be completed (otherwise, we # cannot read this response's header to determine the connection-close # behavior) @@ -929,7 +961,7 @@ # isclosed() status to become true. # if self.__state != _CS_REQ_SENT or self.__response: - raise ResponseNotReady() + raise ResponseNotReady(self.__state) if self.debuglevel > 0: response = self.response_class(self.sock, self.debuglevel, Modified: python/branches/py3k/Lib/test/test_http_cookiejar.py ============================================================================== --- python/branches/py3k/Lib/test/test_http_cookiejar.py (original) +++ python/branches/py3k/Lib/test/test_http_cookiejar.py Tue Mar 31 16:35:53 2009 @@ -583,11 +583,6 @@ req = urllib.request.Request("http://www.acme.com/", headers={"Host": "irrelevant.com"}) self.assertEquals(request_host(req), "www.acme.com") - # not actually sure this one is valid Request object, so maybe should - # remove test for no host in url in request_host function? - req = urllib.request.Request("/resource.html", - headers={"Host": "www.acme.com"}) - self.assertEquals(request_host(req), "www.acme.com") # port shouldn't be in request-host req = urllib.request.Request("http://www.acme.com:2345/resource.html", headers={"Host": "www.acme.com:5432"}) Modified: python/branches/py3k/Lib/test/test_urllib2.py ============================================================================== --- python/branches/py3k/Lib/test/test_urllib2.py (original) +++ python/branches/py3k/Lib/test/test_urllib2.py Tue Mar 31 16:35:53 2009 @@ -683,8 +683,13 @@ self.msg = msg self.status = status self.reason = reason + self.code = 200 def read(self): return '' + def info(self): + return {} + def geturl(self): + return self.url class MockHTTPClass: def __init__(self): self.level = 0 Modified: python/branches/py3k/Lib/urllib/request.py ============================================================================== --- python/branches/py3k/Lib/urllib/request.py (original) +++ python/branches/py3k/Lib/urllib/request.py Tue Mar 31 16:35:53 2009 @@ -1,6 +1,3 @@ -# Issues in merging urllib and urllib2: -# 1. They both define a function named urlopen() - """An extensible library for opening URLs using a variety of protocols The simplest way to use this module is to call the urlopen function, @@ -83,6 +80,7 @@ # abstract factory for opener import base64 +import bisect import email import hashlib import http.client @@ -94,7 +92,6 @@ import socket import sys import time -import bisect from urllib.error import URLError, HTTPError, ContentTooShortError from urllib.parse import ( @@ -149,7 +146,7 @@ comparison. """ - url = request.get_full_url() + url = request.full_url host = urlparse(url)[1] if host == "": host = request.get_header("Host", "") @@ -163,11 +160,7 @@ def __init__(self, url, data=None, headers={}, origin_req_host=None, unverifiable=False): # unwrap('') --> 'type://host/path' - self.__original = unwrap(url) - self.type = None - # self.__r_type is what's left after doing the splittype - self.host = None - self.port = None + self.full_url = unwrap(url) self.data = data self.headers = {} for key, value in headers.items(): @@ -177,26 +170,23 @@ origin_req_host = request_host(self) self.origin_req_host = origin_req_host self.unverifiable = unverifiable + self._parse() - def __getattr__(self, attr): - # XXX this is a fallback mechanism to guard against these - # methods getting called in a non-standard order. this may be - # too complicated and/or unnecessary. - # XXX should the __r_XXX attributes be public? - if attr[:12] == '_Request__r_': - name = attr[12:] - if hasattr(Request, 'get_' + name): - getattr(self, 'get_' + name)() - return getattr(self, attr) - raise AttributeError(attr) + def _parse(self): + self.type, rest = splittype(self.full_url) + if self.type is None: + raise ValueError("unknown url type: %s" % self.full_url) + self.host, self.selector = splithost(rest) + if self.host: + self.host = unquote(self.host) def get_method(self): - if self.has_data(): + if self.data is not None: return "POST" else: return "GET" - # XXX these helper methods are lame + # Begin deprecated methods def add_data(self, data): self.data = data @@ -208,37 +198,31 @@ return self.data def get_full_url(self): - return self.__original + return self.full_url def get_type(self): - if self.type is None: - self.type, self.__r_type = splittype(self.__original) - if self.type is None: - raise ValueError("unknown url type: %s" % self.__original) return self.type def get_host(self): - if self.host is None: - self.host, self.__r_host = splithost(self.__r_type) - if self.host: - self.host = unquote(self.host) return self.host def get_selector(self): - return self.__r_host + return self.selector - def set_proxy(self, host, type): - self.host, self.type = host, type - self.__r_host = self.__original - - def has_proxy(self): - return self.__r_host == self.__original + def is_unverifiable(self): + return self.unverifiable def get_origin_req_host(self): return self.origin_req_host - def is_unverifiable(self): - return self.unverifiable + # End deprecated methods + + def set_proxy(self, host, type): + self.host, self.type = host, type + self.selector = self.full_url + + def has_proxy(self): + return self.selector == self.full_url def add_header(self, key, val): # useful for something like authentication @@ -344,10 +328,10 @@ else: req = fullurl if data is not None: - req.add_data(data) + req.data = data req.timeout = timeout - protocol = req.get_type() + protocol = req.type # pre-process request meth_name = protocol+"_request" @@ -371,7 +355,7 @@ if result: return result - protocol = req.get_type() + protocol = req.type result = self._call_chain(self.handle_open, protocol, protocol + '_open', req) if result: @@ -481,7 +465,7 @@ class HTTPDefaultErrorHandler(BaseHandler): def http_error_default(self, req, fp, code, msg, hdrs): - raise HTTPError(req.get_full_url(), code, msg, hdrs, fp) + raise HTTPError(req.full_url, code, msg, hdrs, fp) class HTTPRedirectHandler(BaseHandler): # maximum number of redirections to any single URL @@ -504,7 +488,7 @@ m = req.get_method() if (not (code in (301, 302, 303, 307) and m in ("GET", "HEAD") or code in (301, 302, 303) and m == "POST")): - raise HTTPError(req.get_full_url(), code, msg, headers, fp) + raise HTTPError(req.full_url, code, msg, headers, fp) # Strictly (according to RFC 2616), 301 or 302 in response to # a POST MUST NOT cause a redirection without confirmation @@ -518,7 +502,7 @@ if k.lower() not in CONTENT_HEADERS) return Request(newurl, headers=newheaders, - origin_req_host=req.get_origin_req_host(), + origin_req_host=req.origin_req_host, unverifiable=True) # Implementation note: To avoid the server sending us into an @@ -542,7 +526,7 @@ urlparts[2] = "/" newurl = urlunparse(urlparts) - newurl = urljoin(req.get_full_url(), newurl) + newurl = urljoin(req.full_url, newurl) # XXX Probably want to forget about the state of the current # request, although that might interact poorly with other @@ -557,7 +541,7 @@ visited = new.redirect_dict = req.redirect_dict if (visited.get(newurl, 0) >= self.max_repeats or len(visited) >= self.max_redirections): - raise HTTPError(req.get_full_url(), code, + raise HTTPError(req.full_url, code, self.inf_msg + msg, headers, fp) else: visited = new.redirect_dict = req.redirect_dict = {} @@ -664,7 +648,7 @@ meth(r, proxy, type)) def proxy_open(self, req, proxy, type): - orig_type = req.get_type() + orig_type = req.type proxy_type, user, password, hostport = _parse_proxy(proxy) if proxy_type is None: proxy_type = orig_type @@ -811,7 +795,7 @@ auth_header = 'Authorization' def http_error_401(self, req, fp, code, msg, headers): - url = req.get_full_url() + url = req.full_url return self.http_error_auth_reqed('www-authenticate', url, req, headers) @@ -825,7 +809,7 @@ # authority. Assume there isn't one, since urllib.request does not (and # should not, RFC 3986 s. 3.2.1) support requests for URLs containing # userinfo. - authority = req.get_host() + authority = req.host return self.http_error_auth_reqed('proxy-authenticate', authority, req, headers) @@ -864,7 +848,7 @@ # prompting for the information. Crap. This isn't great # but it's better than the current 'repeat until recursion # depth exceeded' approach - raise HTTPError(req.get_full_url(), 401, "digest auth failed", + raise HTTPError(req.full_url, 401, "digest auth failed", headers, None) else: self.retried += 1 @@ -912,20 +896,20 @@ if H is None: return None - user, pw = self.passwd.find_user_password(realm, req.get_full_url()) + user, pw = self.passwd.find_user_password(realm, req.full_url) if user is None: return None # XXX not implemented yet - if req.has_data(): - entdig = self.get_entity_digest(req.get_data(), chal) + if req.data is not None: + entdig = self.get_entity_digest(req.data, chal) else: entdig = None A1 = "%s:%s:%s" % (user, realm, pw) A2 = "%s:%s" % (req.get_method(), # XXX selector: what about proxies and full urls - req.get_selector()) + req.selector) if qop == 'auth': self.nonce_count += 1 ncvalue = '%08x' % self.nonce_count @@ -941,7 +925,7 @@ # XXX should the partial digests be encoded too? base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \ - 'response="%s"' % (user, realm, nonce, req.get_selector(), + 'response="%s"' % (user, realm, nonce, req.selector, respdig) if opaque: base += ', opaque="%s"' % opaque @@ -978,7 +962,7 @@ handler_order = 490 # before Basic auth def http_error_401(self, req, fp, code, msg, headers): - host = urlparse(req.get_full_url())[1] + host = urlparse(req.full_url)[1] retry = self.http_error_auth_reqed('www-authenticate', host, req, headers) self.reset_retry_count() @@ -991,7 +975,7 @@ handler_order = 490 # before Basic auth def http_error_407(self, req, fp, code, msg, headers): - host = req.get_host() + host = req.host retry = self.http_error_auth_reqed('proxy-authenticate', host, req, headers) self.reset_retry_count() @@ -1006,12 +990,12 @@ self._debuglevel = level def do_request_(self, request): - host = request.get_host() + host = request.host if not host: raise URLError('no host given') - if request.has_data(): # POST - data = request.get_data() + if request.data is not None: # POST + data = request.data if not request.has_header('Content-type'): request.add_unredirected_header( 'Content-type', @@ -1022,7 +1006,7 @@ sel_host = host if request.has_proxy(): - scheme, sel = splittype(request.get_selector()) + scheme, sel = splittype(request.selector) sel_host, sel_path = splithost(sel) if not request.has_header('Host'): request.add_unredirected_header('Host', sel_host) @@ -1034,16 +1018,11 @@ return request def do_open(self, http_class, req): - """Return an addinfourl object for the request, using http_class. + """Return an HTTPResponse object for the request, using http_class. http_class must implement the HTTPConnection API from http.client. - The addinfourl return value is a file-like object. It also - has methods and attributes including: - - info(): return a email Message object for the headers - - geturl(): return the original request URL - - code: HTTP status code """ - host = req.get_host() + host = req.host if not host: raise URLError('no host given') @@ -1061,19 +1040,21 @@ # So make sure the connection gets closed after the (only) # request. headers["Connection"] = "close" - headers = dict( - (name.title(), val) for name, val in headers.items()) + headers = dict((name.title(), val) for name, val in headers.items()) try: - h.request(req.get_method(), req.get_selector(), req.data, headers) - r = h.getresponse() - except socket.error as err: # XXX what error? + h.request(req.get_method(), req.selector, req.data, headers) + r = h.getresponse() # an HTTPResponse instance + except socket.error as err: raise URLError(err) -## resp = addinfourl(r.fp, r.msg, req.get_full_url()) - resp = addinfourl(r, r.msg, req.get_full_url()) - resp.code = r.status - resp.msg = r.reason - return resp + r.url = req.full_url + # This line replaces the .msg attribute of the HTTPResponse + # with .headers, because urllib clients expect the response to + # have the reason in .msg. It would be good to mark this + # attribute is deprecated and get then to use info() or + # .headers. + r.msg = r.reason + return r class HTTPHandler(AbstractHTTPHandler): @@ -1111,7 +1092,7 @@ class UnknownHandler(BaseHandler): def unknown_open(self, req): - type = req.get_type() + type = req.type raise URLError('unknown url type: %s' % type) def parse_keqv_list(l): @@ -1170,7 +1151,7 @@ class FileHandler(BaseHandler): # Use local file or FTP depending on form of URL def file_open(self, req): - url = req.get_selector() + url = req.selector if url[:2] == '//' and url[2:3] != '/': req.type = 'ftp' return self.parent.open(req) @@ -1192,8 +1173,8 @@ def open_local_file(self, req): import email.utils import mimetypes - host = req.get_host() - file = req.get_selector() + host = req.host + file = req.selector localfile = url2pathname(file) try: stats = os.stat(localfile) @@ -1223,7 +1204,7 @@ def ftp_open(self, req): import ftplib import mimetypes - host = req.get_host() + host = req.host if not host: raise URLError('ftp error: no host given') host, port = splitport(host) @@ -1246,7 +1227,7 @@ host = socket.gethostbyname(host) except socket.error as msg: raise URLError(msg) - path, attrs = splitattr(req.get_selector()) + path, attrs = splitattr(req.selector) dirs = path.split('/') dirs = list(map(unquote, dirs)) dirs, file = dirs[:-1], dirs[-1] @@ -1262,13 +1243,13 @@ type = value.upper() fp, retrlen = fw.retrfile(file, type) headers = "" - mtype = mimetypes.guess_type(req.get_full_url())[0] + mtype = mimetypes.guess_type(req.full_url)[0] if mtype: headers += "Content-type: %s\n" % mtype if retrlen is not None and retrlen >= 0: headers += "Content-length: %d\n" % retrlen headers = email.message_from_string(headers) - return addinfourl(fp, headers, req.get_full_url()) + return addinfourl(fp, headers, req.full_url) except ftplib.all_errors as msg: exc = URLError('ftp error: %s' % msg) raise exc.with_traceback(sys.exc_info()[2]) @@ -1581,9 +1562,9 @@ else: auth = None http_conn = connection_factory(host) - # XXX We should fix urllib so that it works with HTTP/1.1. - http_conn._http_vsn = 10 - http_conn._http_vsn_str = "HTTP/1.0" +## # XXX We should fix urllib so that it works with HTTP/1.1. +## http_conn._http_vsn = 10 +## http_conn._http_vsn_str = "HTTP/1.0" headers = {} if proxy_auth: From python-checkins at python.org Tue Mar 31 16:37:44 2009 From: python-checkins at python.org (jeremy.hylton) Date: Tue, 31 Mar 2009 16:37:44 +0200 (CEST) Subject: [Python-checkins] r70816 - python/branches/py3k/Doc/library/urllib.error.rst Message-ID: <20090331143744.6E7381E4022@bag.python.org> Author: jeremy.hylton Date: Tue Mar 31 16:37:44 2009 New Revision: 70816 Log: Change email address. Modified: python/branches/py3k/Doc/library/urllib.error.rst Modified: python/branches/py3k/Doc/library/urllib.error.rst ============================================================================== --- python/branches/py3k/Doc/library/urllib.error.rst (original) +++ python/branches/py3k/Doc/library/urllib.error.rst Tue Mar 31 16:37:44 2009 @@ -3,7 +3,7 @@ .. module:: urllib.error :synopsis: Exception classes raised by urllib.request. -.. moduleauthor:: Jeremy Hylton +.. moduleauthor:: Jeremy Hylton .. sectionauthor:: Senthil Kumaran From python-checkins at python.org Tue Mar 31 16:38:13 2009 From: python-checkins at python.org (jeremy.hylton) Date: Tue, 31 Mar 2009 16:38:13 +0200 (CEST) Subject: [Python-checkins] r70817 - python/branches/py3k/Doc/library/urllib.request.rst Message-ID: <20090331143813.CC10C1E4022@bag.python.org> Author: jeremy.hylton Date: Tue Mar 31 16:38:13 2009 New Revision: 70817 Log: Document public attributes of urllib.request.Request. Modified: python/branches/py3k/Doc/library/urllib.request.rst Modified: python/branches/py3k/Doc/library/urllib.request.rst ============================================================================== --- python/branches/py3k/Doc/library/urllib.request.rst (original) +++ python/branches/py3k/Doc/library/urllib.request.rst Tue Mar 31 16:38:13 2009 @@ -3,7 +3,7 @@ .. module:: urllib.request :synopsis: Next generation URL opening library. -.. moduleauthor:: Jeremy Hylton +.. moduleauthor:: Jeremy Hylton .. sectionauthor:: Moshe Zadka @@ -16,26 +16,28 @@ .. function:: urlopen(url[, data][, timeout]) - Open the URL *url*, which can be either a string or a :class:`Request` object. + Open the URL *url*, which can be either a string or a + :class:`Request` object. - *data* may be a string specifying additional data to send to the server, or - ``None`` if no such data is needed. Currently HTTP requests are the only ones - that use *data*; the HTTP request will be a POST instead of a GET when the - *data* parameter is provided. *data* should be a buffer in the standard + *data* may be a string specifying additional data to send to the + server, or ``None`` if no such data is needed. Currently HTTP + requests are the only ones that use *data*; the HTTP request will + be a POST instead of a GET when the *data* parameter is provided. + *data* should be a buffer in the standard :mimetype:`application/x-www-form-urlencoded` format. The :func:`urllib.parse.urlencode` function takes a mapping or sequence of 2-tuples and returns a string in this format. - The optional *timeout* parameter specifies a timeout in seconds for blocking - operations like the connection attempt (if not specified, the global default - timeout setting will be used). This actually only works for HTTP, HTTPS, - FTP and FTPS connections. + The optional *timeout* parameter specifies a timeout in seconds for + blocking operations like the connection attempt (if not specified, + the global default timeout setting will be used). This actually + only works for HTTP, HTTPS, FTP and FTPS connections. This function returns a file-like object with two additional methods from the :mod:`urllib.response` module - * :meth:`geturl` --- return the URL of the resource retrieved, commonly used to - determine if a redirect was followed + * :meth:`geturl` --- return the URL of the resource retrieved, + commonly used to determine if a redirect was followed * :meth:`info` --- return the meta-information of the page, such as headers, in the form of an ``http.client.HTTPMessage`` instance (see `Quick @@ -52,7 +54,6 @@ Proxy handling, which was done by passing a dictionary parameter to ``urllib.urlopen``, can be obtained by using :class:`ProxyHandler` objects. - .. function:: install_opener(opener) Install an :class:`OpenerDirector` instance as the default global opener. @@ -167,37 +168,42 @@ *url* should be a string containing a valid URL. - *data* may be a string specifying additional data to send to the server, or - ``None`` if no such data is needed. Currently HTTP requests are the only ones - that use *data*; the HTTP request will be a POST instead of a GET when the - *data* parameter is provided. *data* should be a buffer in the standard + *data* may be a string specifying additional data to send to the + server, or ``None`` if no such data is needed. Currently HTTP + requests are the only ones that use *data*; the HTTP request will + be a POST instead of a GET when the *data* parameter is provided. + *data* should be a buffer in the standard :mimetype:`application/x-www-form-urlencoded` format. The :func:`urllib.parse.urlencode` function takes a mapping or sequence of 2-tuples and returns a string in this format. - *headers* should be a dictionary, and will be treated as if :meth:`add_header` - was called with each key and value as arguments. This is often used to "spoof" - the ``User-Agent`` header, which is used by a browser to identify itself -- - some HTTP servers only allow requests coming from common browsers as opposed - to scripts. For example, Mozilla Firefox may identify itself as ``"Mozilla/5.0 - (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11"``, while :mod:`urllib`'s - default user agent string is ``"Python-urllib/2.6"`` (on Python 2.6). - - The final two arguments are only of interest for correct handling of third-party - HTTP cookies: - - *origin_req_host* should be the request-host of the origin transaction, as - defined by :rfc:`2965`. It defaults to ``http.cookiejar.request_host(self)``. - This is the host name or IP address of the original request that was - initiated by the user. For example, if the request is for an image in an - HTML document, this should be the request-host of the request for the page + *headers* should be a dictionary, and will be treated as if + :meth:`add_header` was called with each key and value as arguments. + This is often used to "spoof" the ``User-Agent`` header, which is + used by a browser to identify itself -- some HTTP servers only + allow requests coming from common browsers as opposed to scripts. + For example, Mozilla Firefox may identify itself as ``"Mozilla/5.0 + (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11"``, while + :mod:`urllib`'s default user agent string is + ``"Python-urllib/2.6"`` (on Python 2.6). + + The final two arguments are only of interest for correct handling + of third-party HTTP cookies: + + *origin_req_host* should be the request-host of the origin + transaction, as defined by :rfc:`2965`. It defaults to + ``http.cookiejar.request_host(self)``. This is the host name or IP + address of the original request that was initiated by the user. + For example, if the request is for an image in an HTML document, + this should be the request-host of the request for the page containing the image. - *unverifiable* should indicate whether the request is unverifiable, as defined - by RFC 2965. It defaults to False. An unverifiable request is one whose URL - the user did not have the option to approve. For example, if the request is for - an image in an HTML document, and the user had no option to approve the - automatic fetching of the image, this should be true. + *unverifiable* should indicate whether the request is unverifiable, + as defined by RFC 2965. It defaults to False. An unverifiable + request is one whose URL the user did not have the option to + approve. For example, if the request is for an image in an HTML + document, and the user had no option to approve the automatic + fetching of the image, this should be true. .. class:: URLopener([proxies[, **x509]]) @@ -441,9 +447,41 @@ Request Objects --------------- -The following methods describe all of :class:`Request`'s public interface, and -so all must be overridden in subclasses. +The following methods describe :class:`Request`'s public interface, +and so all may be overridden in subclasses. It also defines several +public attributes that can be used by clients to inspect the parsed +request. + +.. attribute:: Request.full_url + + The original URL passed to the constructor. + +.. attribute:: Request.type + + The URI scheme. + +.. attribute:: Request.host + + The URI authority, typically a host, but may also contain a port + separated by a colon. + +.. attribute:: Request.origin_req_host + + The original host for the request, without port. + +.. attribute:: Request.selector + + The URI path. If the :class:`Request` uses a proxy, then selector + will be the full url that is passed to the proxy. + +.. attribute:: Request.data + + The entity body for the request, or None if not specified. + +.. attribute:: Request.unverifiable + boolean, indicates whether the request is unverifiable as defined + by RFC 2965. .. method:: Request.add_data(data) From python-checkins at python.org Tue Mar 31 16:40:19 2009 From: python-checkins at python.org (jeremy.hylton) Date: Tue, 31 Mar 2009 16:40:19 +0200 (CEST) Subject: [Python-checkins] r70818 - python/branches/py3k/Doc/library/http.client.rst Message-ID: <20090331144019.655521E4022@bag.python.org> Author: jeremy.hylton Date: Tue Mar 31 16:40:19 2009 New Revision: 70818 Log: Update HTTPResponse documentation and add placeholder for HTTPMessage. Modified: python/branches/py3k/Doc/library/http.client.rst Modified: python/branches/py3k/Doc/library/http.client.rst ============================================================================== --- python/branches/py3k/Doc/library/http.client.rst (original) +++ python/branches/py3k/Doc/library/http.client.rst Tue Mar 31 16:40:19 2009 @@ -59,8 +59,8 @@ .. class:: HTTPResponse(sock[, debuglevel=0][, strict=0]) - Class whose instances are returned upon successful connection. Not instantiated - directly by user. + Class whose instances are returned upon successful connection. Not + instantiated directly by user. The following exceptions are raised as appropriate: @@ -433,7 +433,10 @@ HTTPResponse Objects -------------------- -:class:`HTTPResponse` instances have the following methods and attributes: +An :class:`HTTPResponse` instance wraps the HTTP response from the +server. It provides access to the request headers and the entity +body. The response is an iterable object and can be used in a with +statement. .. method:: HTTPResponse.read([amt]) @@ -454,7 +457,9 @@ .. attribute:: HTTPResponse.msg - An :class:`email.message.Message` instance containing the response headers. + A :class:`http.client.HTTPMessage` instance containing the response + headers. :class:`http.client.HTTPMessage` is a subclass of + :class:`email.message.Message`. .. attribute:: HTTPResponse.version @@ -472,6 +477,12 @@ Reason phrase returned by server. +.. attribute:: HTTPResponse.debuglevel + + A debugging hook. If `debuglevel` is greater than zero, messages + will be printed to stdout as the response is read and parsed. + + Examples -------- @@ -505,3 +516,14 @@ >>> data = response.read() >>> conn.close() + +.. _httpmessage-objects: + +HTTPMessage Objects +------------------- + +An :class:`http.client.HTTPMessage` instance holds the headers from an +HTTP response. It is implemented using the +:class:`email.message.Message' class. + +XXX Define the methods that clients can depend upon between versions. \ No newline at end of file From python-checkins at python.org Tue Mar 31 16:51:33 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 31 Mar 2009 16:51:33 +0200 (CEST) Subject: [Python-checkins] r70819 - python/branches/py3k-short-float-repr/Python/atof.c Message-ID: <20090331145133.058C41E4022@bag.python.org> Author: mark.dickinson Date: Tue Mar 31 16:50:47 2009 New Revision: 70819 Log: Remove unneeded atof.c implementation Removed: python/branches/py3k-short-float-repr/Python/atof.c Deleted: python/branches/py3k-short-float-repr/Python/atof.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/atof.c Tue Mar 31 16:50:47 2009 +++ (empty file) @@ -1,50 +0,0 @@ - -/* Just in case you haven't got an atof() around... - This one doesn't check for bad syntax or overflow, - and is slow and inaccurate. - But it's good enough for the occasional string literal... */ - -#include "pyconfig.h" - -#include - -double atof(char *s) -{ - double a = 0.0; - int e = 0; - int c; - while ((c = *s++) != '\0' && isdigit(c)) { - a = a*10.0 + (c - '0'); - } - if (c == '.') { - while ((c = *s++) != '\0' && isdigit(c)) { - a = a*10.0 + (c - '0'); - e = e-1; - } - } - if (c == 'e' || c == 'E') { - int sign = 1; - int i = 0; - c = *s++; - if (c == '+') - c = *s++; - else if (c == '-') { - c = *s++; - sign = -1; - } - while (isdigit(c)) { - i = i*10 + (c - '0'); - c = *s++; - } - e += i*sign; - } - while (e > 0) { - a *= 10.0; - e--; - } - while (e < 0) { - a *= 0.1; - e++; - } - return a; -} From buildbot at python.org Tue Mar 31 16:53:11 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 14:53:11 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.x Message-ID: <20090331145311.8E6E91E4137@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.x/builds/554 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Tue Mar 31 16:55:50 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 14:55:50 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu trunk Message-ID: <20090331145550.938601E4022@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%20trunk/builds/1033 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 17:01:45 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 17:01:45 +0200 (CEST) Subject: [Python-checkins] r70820 - in python/branches/release26-maint: Doc/library/multiprocessing.rst Lib/multiprocessing/__init__.py Lib/multiprocessing/util.py Misc/ACKS Misc/NEWS Message-ID: <20090331150145.63F9A1E4022@bag.python.org> Author: jesse.noller Date: Tue Mar 31 17:01:45 2009 New Revision: 70820 Log: Merged revisions 68915 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r68915 | jesse.noller | 2009-01-24 21:36:13 -0600 (Sat, 24 Jan 2009) | 1 line Properly document multiprocessing's logging support, resolve outstanding issues with the custom levels ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/library/multiprocessing.rst python/branches/release26-maint/Lib/multiprocessing/__init__.py python/branches/release26-maint/Lib/multiprocessing/util.py python/branches/release26-maint/Misc/ACKS python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Doc/library/multiprocessing.rst ============================================================================== --- python/branches/release26-maint/Doc/library/multiprocessing.rst (original) +++ python/branches/release26-maint/Doc/library/multiprocessing.rst Tue Mar 31 17:01:45 2009 @@ -1857,30 +1857,74 @@ Returns the logger used by :mod:`multiprocessing`. If necessary, a new one will be created. - When first created the logger has level :data:`logging.NOTSET` and has a - handler which sends output to :data:`sys.stderr` using format - ``'[%(levelname)s/%(processName)s] %(message)s'``. (The logger allows use of - the non-standard ``'%(processName)s'`` format.) Message sent to this logger - will not by default propagate to the root logger. + When first created the logger has level :data:`logging.NOTSET` and no + default handler. Messages sent to this logger will not by default propagate + to the root logger. Note that on Windows child processes will only inherit the level of the parent process's logger -- any other customization of the logger will not be inherited. +.. currentmodule:: multiprocessing +.. function:: log_to_stderr() + + This function performs a call to :func:`get_logger` but in addition to + returning the logger created by get_logger, it adds a handler which sends + output to :data:`sys.stderr` using format + ``'[%(levelname)s/%(processName)s] %(message)s'``. + Below is an example session with logging turned on:: >>> import multiprocessing, logging - >>> logger = multiprocessing.get_logger() + >>> logger = multiprocessing.log_to_stderr() >>> logger.setLevel(logging.INFO) >>> logger.warning('doomed') [WARNING/MainProcess] doomed >>> m = multiprocessing.Manager() [INFO/SyncManager-1] child process calling self.run() - [INFO/SyncManager-1] manager bound to '\\\\.\\pipe\\pyc-2776-0-lj0tfa' + [INFO/SyncManager-1] created temp directory /.../pymp-Wh47O_ + [INFO/SyncManager-1] manager serving at '/.../listener-lWsERs' >>> del m [INFO/MainProcess] sending shutdown message to manager [INFO/SyncManager-1] manager exiting with exitcode 0 +In addition to having these two logging functions, the multiprocessing also +exposes two additional logging level attributes. These are :const:`SUBWARNING` +and :const:`SUBDEBUG`. The table below illustrates where theses fit in the +normal level hierarchy. + ++----------------+----------------+ +| Level | Numeric value | ++================+================+ +| ``SUBWARNING`` | 25 | ++----------------+----------------+ +| ``SUBDEBUG`` | 5 | ++----------------+----------------+ + +For a full table of logging levels, see the :mod:`logging` module. + +These additional logging levels are used primarily for certain debug messages +within the multiprocessing module. Below is the same example as above, except +with :const:`SUBDEBUG` enabled:: + + >>> import multiprocessing, logging + >>> logger = multiprocessing.log_to_stderr() + >>> logger.setLevel(multiprocessing.SUBDEBUG) + >>> logger.warning('doomed') + [WARNING/MainProcess] doomed + >>> m = multiprocessing.Manager() + [INFO/SyncManager-1] child process calling self.run() + [INFO/SyncManager-1] created temp directory /.../pymp-djGBXN + [INFO/SyncManager-1] manager serving at '/.../pymp-djGBXN/listener-knBYGe' + >>> del m + [SUBDEBUG/MainProcess] finalizer calling ... + [INFO/MainProcess] sending shutdown message to manager + [DEBUG/SyncManager-1] manager received shutdown message + [SUBDEBUG/SyncManager-1] calling ... + [SUBDEBUG/SyncManager-1] calling + [SUBDEBUG/SyncManager-1] finalizer calling ... + [INFO/SyncManager-1] manager exiting with exitcode 0 The :mod:`multiprocessing.dummy` module ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Modified: python/branches/release26-maint/Lib/multiprocessing/__init__.py ============================================================================== --- python/branches/release26-maint/Lib/multiprocessing/__init__.py (original) +++ python/branches/release26-maint/Lib/multiprocessing/__init__.py Tue Mar 31 17:01:45 2009 @@ -48,7 +48,7 @@ 'allow_connection_pickling', 'BufferTooShort', 'TimeoutError', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Condition', 'Event', 'Queue', 'JoinableQueue', 'Pool', 'Value', 'Array', - 'RawValue', 'RawArray' + 'RawValue', 'RawArray', 'SUBDEBUG', 'SUBWARNING', ] __author__ = 'R. Oudkerk (r.m.oudkerk at gmail.com)' @@ -61,6 +61,7 @@ import sys from multiprocessing.process import Process, current_process, active_children +from multiprocessing.util import SUBDEBUG, SUBWARNING # # Exceptions Modified: python/branches/release26-maint/Lib/multiprocessing/util.py ============================================================================== --- python/branches/release26-maint/Lib/multiprocessing/util.py (original) +++ python/branches/release26-maint/Lib/multiprocessing/util.py Tue Mar 31 17:01:45 2009 @@ -17,7 +17,8 @@ __all__ = [ 'sub_debug', 'debug', 'info', 'sub_warning', 'get_logger', 'log_to_stderr', 'get_temp_dir', 'register_after_fork', - 'is_exiting', 'Finalize', 'ForkAwareThreadLock', 'ForkAwareLocal' + 'is_exiting', 'Finalize', 'ForkAwareThreadLock', 'ForkAwareLocal', + 'SUBDEBUG', 'SUBWARNING', ] # @@ -57,19 +58,27 @@ Returns logger used by multiprocessing ''' global _logger + import logging, atexit - if not _logger: - import logging, atexit + logging._acquireLock() + try: + if not _logger: + + _logger = logging.getLogger(LOGGER_NAME) + _logger.propagate = 0 + logging.addLevelName(SUBDEBUG, 'SUBDEBUG') + logging.addLevelName(SUBWARNING, 'SUBWARNING') + + # XXX multiprocessing should cleanup before logging + if hasattr(atexit, 'unregister'): + atexit.unregister(_exit_function) + atexit.register(_exit_function) + else: + atexit._exithandlers.remove((_exit_function, (), {})) + atexit._exithandlers.append((_exit_function, (), {})) - # XXX multiprocessing should cleanup before logging - if hasattr(atexit, 'unregister'): - atexit.unregister(_exit_function) - atexit.register(_exit_function) - else: - atexit._exithandlers.remove((_exit_function, (), {})) - atexit._exithandlers.append((_exit_function, (), {})) - - _logger = logging.getLogger(LOGGER_NAME) + finally: + logging._releaseLock() return _logger @@ -79,14 +88,17 @@ ''' global _log_to_stderr import logging + logger = get_logger() formatter = logging.Formatter(DEFAULT_LOGGING_FORMAT) handler = logging.StreamHandler() handler.setFormatter(formatter) logger.addHandler(handler) - if level is not None: + + if level: logger.setLevel(level) _log_to_stderr = True + return _logger # # Function returning a temp directory which will be removed on exit Modified: python/branches/release26-maint/Misc/ACKS ============================================================================== --- python/branches/release26-maint/Misc/ACKS (original) +++ python/branches/release26-maint/Misc/ACKS Tue Mar 31 17:01:45 2009 @@ -778,3 +778,4 @@ Uwe Zessin Tarek Ziad? Peter ?strand +Jesse Noller Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Tue Mar 31 17:01:45 2009 @@ -92,6 +92,10 @@ Library ------- +- Fix and properly document the multiprocessing module's logging + support, expose the internal levels and provide proper usage + examples. + - Issue #5387: Fixed mmap.move crash by integer overflow. - Issue #5261: Patch multiprocessing's semaphore.c to support context From python-checkins at python.org Tue Mar 31 17:04:15 2009 From: python-checkins at python.org (jeremy.hylton) Date: Tue, 31 Mar 2009 17:04:15 +0200 (CEST) Subject: [Python-checkins] r70821 - python/trunk/Python/symtable.c Message-ID: <20090331150415.4F9DF1E4022@bag.python.org> Author: jeremy.hylton Date: Tue Mar 31 17:04:15 2009 New Revision: 70821 Log: Add check for PyDict_Update() error. Modified: python/trunk/Python/symtable.c Modified: python/trunk/Python/symtable.c ============================================================================== --- python/trunk/Python/symtable.c (original) +++ python/trunk/Python/symtable.c Tue Mar 31 17:04:15 2009 @@ -702,7 +702,8 @@ ste->ste_child_free = 1; } - PyDict_Update(newfree, allfree); + if (PyDict_Update(newfree, allfree) < 0) + goto error; if (ste->ste_type == FunctionBlock && !analyze_cells(scope, newfree)) goto error; if (!update_symbols(ste->ste_symbols, scope, bound, newfree, From python-checkins at python.org Tue Mar 31 17:12:44 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 31 Mar 2009 17:12:44 +0200 (CEST) Subject: [Python-checkins] r70822 - in python/branches/py3k-short-float-repr: Objects/floatobject.c Python/ast.c Python/marshal.c Message-ID: <20090331151244.C00131E403F@bag.python.org> Author: mark.dickinson Date: Tue Mar 31 17:12:44 2009 New Revision: 70822 Log: Use PyOS_ascii_strtod instead of PyOS_ascii_atof in core code. Modified: python/branches/py3k-short-float-repr/Objects/floatobject.c python/branches/py3k-short-float-repr/Python/ast.c python/branches/py3k-short-float-repr/Python/marshal.c Modified: python/branches/py3k-short-float-repr/Objects/floatobject.c ============================================================================== --- python/branches/py3k-short-float-repr/Objects/floatobject.c (original) +++ python/branches/py3k-short-float-repr/Objects/floatobject.c Tue Mar 31 17:12:44 2009 @@ -262,8 +262,8 @@ if (x == 0.0) { /* See above -- may have been strtod being anal about denorms. */ - PyFPE_START_PROTECT("atof", goto error) - x = PyOS_ascii_atof(s); + PyFPE_START_PROTECT("strtod", goto error) + x = PyOS_ascii_strtod(s, NULL); PyFPE_END_PROTECT(x) errno = 0; /* whether atof ever set errno is undefined */ } Modified: python/branches/py3k-short-float-repr/Python/ast.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/ast.c (original) +++ python/branches/py3k-short-float-repr/Python/ast.c Tue Mar 31 17:12:44 2009 @@ -3162,16 +3162,16 @@ #ifndef WITHOUT_COMPLEX if (imflag) { compl.real = 0.; - PyFPE_START_PROTECT("atof", return 0) - compl.imag = PyOS_ascii_atof(s); + PyFPE_START_PROTECT("strtod", return 0) + compl.imag = PyOS_ascii_strtod(s, NULL); PyFPE_END_PROTECT(c) return PyComplex_FromCComplex(compl); } else #endif { - PyFPE_START_PROTECT("atof", return 0) - dx = PyOS_ascii_atof(s); + PyFPE_START_PROTECT("strtod", return 0) + dx = PyOS_ascii_strtod(s, NULL); PyFPE_END_PROTECT(dx) return PyFloat_FromDouble(dx); } Modified: python/branches/py3k-short-float-repr/Python/marshal.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/marshal.c (original) +++ python/branches/py3k-short-float-repr/Python/marshal.c Tue Mar 31 17:12:44 2009 @@ -666,8 +666,8 @@ } buf[n] = '\0'; retval = NULL; - PyFPE_START_PROTECT("atof", break) - dx = PyOS_ascii_atof(buf); + PyFPE_START_PROTECT("strtod", break) + dx = PyOS_ascii_strtod(buf, NULL); PyFPE_END_PROTECT(dx) retval = PyFloat_FromDouble(dx); break; @@ -706,8 +706,8 @@ } buf[n] = '\0'; retval = NULL; - PyFPE_START_PROTECT("atof", break;) - c.real = PyOS_ascii_atof(buf); + PyFPE_START_PROTECT("strtod", break;) + c.real = PyOS_ascii_strtod(buf, NULL); PyFPE_END_PROTECT(c) n = r_byte(p); if (n == EOF || r_string(buf, (int)n, p) != n) { @@ -717,8 +717,8 @@ break; } buf[n] = '\0'; - PyFPE_START_PROTECT("atof", break) - c.imag = PyOS_ascii_atof(buf); + PyFPE_START_PROTECT("strtod", break) + c.imag = PyOS_ascii_strtod(buf, NULL); PyFPE_END_PROTECT(c) retval = PyComplex_FromCComplex(c); break; From python-checkins at python.org Tue Mar 31 17:26:38 2009 From: python-checkins at python.org (jeremy.hylton) Date: Tue, 31 Mar 2009 17:26:38 +0200 (CEST) Subject: [Python-checkins] r70823 - in python/branches/py3k: Lib/symtable.py Lib/test/test_scope.py Lib/test/test_symtable.py Python/symtable.c Message-ID: <20090331152638.0E8611E4034@bag.python.org> Author: jeremy.hylton Date: Tue Mar 31 17:26:37 2009 New Revision: 70823 Log: Merged revisions 70801,70809 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk The merge ran into a lot of conflicts because dicts were replaced with sets in the Python 3 version of the symbol table. ........ r70801 | jeremy.hylton | 2009-03-31 09:17:03 -0400 (Tue, 31 Mar 2009) | 3 lines Add is_declared_global() which distinguishes between implicit and explicit global variables. ........ r70809 | jeremy.hylton | 2009-03-31 09:48:15 -0400 (Tue, 31 Mar 2009) | 14 lines Global statements from one function leaked into parallel functions. Re http://bugs.python.org/issue4315 The symbol table used the same name dictionaries to recursively analyze each of its child blocks, even though the dictionaries are modified during analysis. The fix is to create new temporary dictionaries via the analyze_child_block(). The only information that needs to propagate back up is the names of the free variables. Add more comments and break out a helper function. This code doesn't get any easier to understand when you only look at it once a year. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/symtable.py python/branches/py3k/Lib/test/test_scope.py python/branches/py3k/Lib/test/test_symtable.py python/branches/py3k/Python/symtable.c Modified: python/branches/py3k/Lib/symtable.py ============================================================================== --- python/branches/py3k/Lib/symtable.py (original) +++ python/branches/py3k/Lib/symtable.py Tue Mar 31 17:26:37 2009 @@ -191,6 +191,9 @@ def is_global(self): return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)) + def is_declared_global(self): + return bool(self.__scope == GLOBAL_EXPLICIT) + def is_local(self): return bool(self.__flags & DEF_BOUND) Modified: python/branches/py3k/Lib/test/test_scope.py ============================================================================== --- python/branches/py3k/Lib/test/test_scope.py (original) +++ python/branches/py3k/Lib/test/test_scope.py Tue Mar 31 17:26:37 2009 @@ -618,7 +618,6 @@ self.assertEqual(dec(), 0) def testNonLocalMethod(self): - def f(x): class c: def inc(self): @@ -630,13 +629,36 @@ x -= 1 return x return c() - c = f(0) self.assertEqual(c.inc(), 1) self.assertEqual(c.inc(), 2) self.assertEqual(c.dec(), 1) self.assertEqual(c.dec(), 0) + def testGlobalInParallelNestedFunctions(self): + # A symbol table bug leaked the global statement from one + # function to other nested functions in the same block. + # This test verifies that a global statement in the first + # function does not affect the second function. + CODE = """def f(): + y = 1 + def g(): + global y + return y + def h(): + return y + 1 + return g, h +y = 9 +g, h = f() +result9 = g() +result2 = h() +""" + local_ns = {} + global_ns = {} + exec(CODE, local_ns, global_ns) + self.assertEqual(2, global_ns["result2"]) + self.assertEqual(9, global_ns["result9"]) + def testNonLocalClass(self): def f(x): Modified: python/branches/py3k/Lib/test/test_symtable.py ============================================================================== --- python/branches/py3k/Lib/test/test_symtable.py (original) +++ python/branches/py3k/Lib/test/test_symtable.py Tue Mar 31 17:26:37 2009 @@ -88,7 +88,9 @@ def test_globals(self): self.assertTrue(self.spam.lookup("glob").is_global()) + self.assertFalse(self.spam.lookup("glob").is_declared_global()) self.assertTrue(self.spam.lookup("bar").is_global()) + self.assertTrue(self.spam.lookup("bar").is_declared_global()) self.assertFalse(self.internal.lookup("x").is_global()) self.assertFalse(self.Mine.lookup("instance_var").is_global()) Modified: python/branches/py3k/Python/symtable.c ============================================================================== --- python/branches/py3k/Python/symtable.c (original) +++ python/branches/py3k/Python/symtable.c Tue Mar 31 17:26:37 2009 @@ -377,8 +377,9 @@ /* Decide on scope of name, given flags. - The dicts passed in as arguments are modified as necessary. - ste is passed so that flags can be updated. + The namespace dictionaries may be modified to record information + about the new name. For example, a new global will add an entry to + global. A name that was global can be changed to local. */ static int @@ -454,7 +455,7 @@ explicit? It could also be global implicit. */ if (global && PySet_Contains(global, name)) { - SET_SCOPE(scopes, name, GLOBAL_EXPLICIT); + SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); return 1; } if (ste->ste_nested) @@ -628,28 +629,56 @@ } /* Make final symbol table decisions for block of ste. + Arguments: ste -- current symtable entry (input/output) - bound -- set of variables bound in enclosing scopes (input) + bound -- set of variables bound in enclosing scopes (input). bound + is NULL for module blocks. free -- set of free variables in enclosed scopes (output) globals -- set of declared global variables in enclosing scopes (input) + + The implementation uses two mutually recursive functions, + analyze_block() and analyze_child_block(). analyze_block() is + responsible for analyzing the individual names defined in a block. + analyze_child_block() prepares temporary namespace dictionaries + used to evaluated nested blocks. + + The two functions exist because a child block should see the name + bindings of its enclosing blocks, but those bindings should not + propagate back to a parent block. */ static int +analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, + PyObject *global, PyObject* child_free); + +static int analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, PyObject *global) { PyObject *name, *v, *local = NULL, *scopes = NULL, *newbound = NULL; - PyObject *newglobal = NULL, *newfree = NULL; + PyObject *newglobal = NULL, *newfree = NULL, *allfree = NULL; int i, success = 0; Py_ssize_t pos = 0; - scopes = PyDict_New(); - if (!scopes) - goto error; - local = PySet_New(NULL); + local = PySet_New(NULL); /* collect new names bound in block */ if (!local) goto error; + scopes = PyDict_New(); /* collect scopes defined for each name */ + if (!scopes) + goto error; + + /* Allocate new global and bound variable dictionaries. These + dictionaries hold the names visible in nested blocks. For + ClassBlocks, the bound and global names are initialized + before analyzing names, because class bindings aren't + visible in methods. For other blocks, they are initialized + after names are analyzed. + */ + + /* TODO(jhylton): Package these dicts in a struct so that we + can write reasonable helper functions? + */ newglobal = PySet_New(NULL); if (!newglobal) goto error; @@ -666,25 +695,22 @@ this one. */ if (ste->ste_type == ClassBlock) { + /* Pass down known globals */ + if (!PyNumber_InPlaceOr(newglobal, global)) + goto error; + Py_DECREF(newglobal); /* Pass down previously bound symbols */ if (bound) { if (!PyNumber_InPlaceOr(newbound, bound)) goto error; Py_DECREF(newbound); } - /* Pass down known globals */ - if (!PyNumber_InPlaceOr(newglobal, global)) - goto error; - Py_DECREF(newglobal); } - /* Analyze symbols in current scope */ - assert(PySTEntry_Check(ste)); - assert(PyDict_Check(ste->ste_symbols)); while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) { long flags = PyLong_AS_LONG(v); - if (!analyze_name(ste, scopes, name, flags, bound, local, free, - global)) + if (!analyze_name(ste, scopes, name, flags, + bound, local, free, global)) goto error; } @@ -716,19 +742,31 @@ goto error; } - /* Recursively call analyze_block() on each child block */ + /* Recursively call analyze_block() on each child block. + + newbound, newglobal now contain the names visible in + nested blocks. The free variables in the children will + be collected in allfree. + */ + allfree = PySet_New(NULL); + if (!allfree) + goto error; for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) { PyObject *c = PyList_GET_ITEM(ste->ste_children, i); PySTEntryObject* entry; assert(c && PySTEntry_Check(c)); entry = (PySTEntryObject*)c; - if (!analyze_block(entry, newbound, newfree, newglobal)) + if (!analyze_child_block(entry, newbound, newfree, newglobal, + allfree)) goto error; /* Check if any children have free variables */ if (entry->ste_free || entry->ste_child_free) ste->ste_child_free = 1; } + if (PyNumber_InPlaceOr(newfree, allfree) < 0) + goto error; + /* Check if any local variables must be converted to cell variables */ if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree, NULL)) @@ -753,12 +791,48 @@ Py_XDECREF(newbound); Py_XDECREF(newglobal); Py_XDECREF(newfree); + Py_XDECREF(allfree); if (!success) assert(PyErr_Occurred()); return success; } static int +analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, + PyObject *global, PyObject* child_free) +{ + PyObject *temp_bound = NULL, *temp_global = NULL, *temp_free = NULL; + int success = 0; + + /* Copy the bound and global dictionaries. + + These dictionary are used by all blocks enclosed by the + current block. The analyze_block() call modifies these + dictionaries. + + */ + temp_bound = PySet_New(bound); + if (!temp_bound) + goto error; + temp_free = PySet_New(free); + if (!temp_free) + goto error; + temp_global = PySet_New(global); + if (!temp_global) + goto error; + + if (!analyze_block(entry, temp_bound, temp_free, temp_global)) + goto error; + success = PyNumber_InPlaceOr(child_free, temp_free) >= 0; + success = 1; + error: + Py_XDECREF(temp_bound); + Py_XDECREF(temp_free); + Py_XDECREF(temp_global); + return success; +} + +static int symtable_analyze(struct symtable *st) { PyObject *free, *global; From buildbot at python.org Tue Mar 31 17:35:34 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 15:35:34 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc 3.x Message-ID: <20090331153549.8915A1E4098@bag.python.org> The Buildbot has detected a new failure of sparc solaris10 gcc 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/sparc%20solaris10%20gcc%203.x/builds/437 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: ronald.oussoren BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/test_posix.py", line 252, in test_getcwd_long_pathnames support.rmtree(base_path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/test/support.py", line 88, in rmtree shutil.rmtree(path) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/3.x.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/3.x.loewis-sun/build/@test.getcwd/@test.getcwd' sincerely, -The Buildbot From buildbot at python.org Tue Mar 31 17:37:37 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 15:37:37 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090331153737.B29C61E4052@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/806 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: Traceback (most recent call last): File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/threading.py", line 522, in __bootstrap_inner self.run() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_poplib.py", line 131, in run asyncore.loop(timeout=0.1, count=1) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 204, in loop poll_fun(timeout, map) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 141, in poll read(obj) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 78, in read obj.handle_error() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 74, in read obj.handle_read_event() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 413, in handle_read_event self.handle_read() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/test/test_ssl.py", line 408, in handle_read self.send(data.lower()) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 519, in send self.initiate_send() File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 506, in initiate_send num_sent = dispatcher.send(self, self.out_buffer[:512]) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/asyncore.py", line 349, in send result = self.socket.send(data) File "/Users/buildbot/buildarea/trunk.heller-x86-osx5/build/Lib/socket.py", line 165, in _dummy raise error(EBADF, 'Bad file descriptor') error: [Errno 9] Bad file descriptor sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 17:43:21 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 17:43:21 +0200 (CEST) Subject: [Python-checkins] r70824 - python/trunk/Doc/library/re.rst Message-ID: <20090331154321.229931E4052@bag.python.org> Author: georg.brandl Date: Tue Mar 31 17:43:20 2009 New Revision: 70824 Log: #5519: remove reference to Kodos, which seems dead. Modified: python/trunk/Doc/library/re.rst Modified: python/trunk/Doc/library/re.rst ============================================================================== --- python/trunk/Doc/library/re.rst (original) +++ python/trunk/Doc/library/re.rst Tue Mar 31 17:43:20 2009 @@ -8,12 +8,9 @@ .. sectionauthor:: Andrew M. Kuchling - - This module provides regular expression matching operations similar to those found in Perl. Both patterns and strings to be searched can be -Unicode strings as well as 8-bit strings. The :mod:`re` module is -always available. +Unicode strings as well as 8-bit strings. Regular expressions use the backslash character (``'\'``) to indicate special forms or to allow special characters to be used without invoking @@ -43,9 +40,6 @@ second edition of the book no longer covers Python at all, but the first edition covered writing good regular expression patterns in great detail. - `Kodos `_ - is a graphical regular expression debugger written in Python. - .. _re-syntax: From python-checkins at python.org Tue Mar 31 17:46:30 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 17:46:30 +0200 (CEST) Subject: [Python-checkins] r70825 - python/trunk/Doc/c-api/long.rst Message-ID: <20090331154630.5C2911E4052@bag.python.org> Author: georg.brandl Date: Tue Mar 31 17:46:30 2009 New Revision: 70825 Log: #5566: fix versionadded from PyLong ssize_t functions. Modified: python/trunk/Doc/c-api/long.rst Modified: python/trunk/Doc/c-api/long.rst ============================================================================== --- python/trunk/Doc/c-api/long.rst (original) +++ python/trunk/Doc/c-api/long.rst Tue Mar 31 17:46:30 2009 @@ -54,7 +54,7 @@ Return a new :ctype:`PyLongObject` object from a C :ctype:`Py_ssize_t`, or *NULL* on failure. - .. versionadded:: 2.5 + .. versionadded:: 2.6 .. cfunction:: PyObject* PyLong_FromSize_t(size_t v) @@ -62,7 +62,7 @@ Return a new :ctype:`PyLongObject` object from a C :ctype:`size_t`, or *NULL* on failure. - .. versionadded:: 2.5 + .. versionadded:: 2.6 .. cfunction:: PyObject* PyLong_FromLongLong(PY_LONG_LONG v) @@ -139,7 +139,7 @@ *pylong* is greater than :const:`PY_SSIZE_T_MAX`, an :exc:`OverflowError` is raised and ``-1`` will be returned. - .. versionadded:: 2.5 + .. versionadded:: 2.6 .. cfunction:: unsigned long PyLong_AsUnsignedLong(PyObject *pylong) From python-checkins at python.org Tue Mar 31 17:48:12 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 17:48:12 +0200 (CEST) Subject: [Python-checkins] r70826 - python/branches/py3k Message-ID: <20090331154813.0156E1E411B@bag.python.org> Author: georg.brandl Date: Tue Mar 31 17:48:12 2009 New Revision: 70826 Log: Blocked revisions 70825 via svnmerge ........ r70825 | georg.brandl | 2009-03-31 10:46:30 -0500 (Di, 31 M?r 2009) | 1 line #5566: fix versionadded from PyLong ssize_t functions. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Tue Mar 31 17:49:02 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 17:49:02 +0200 (CEST) Subject: [Python-checkins] r70827 - python/branches/py3k/Doc/c-api/long.rst Message-ID: <20090331154902.513DD1E411B@bag.python.org> Author: georg.brandl Date: Tue Mar 31 17:49:02 2009 New Revision: 70827 Log: #5566: remove duplicate entry. Modified: python/branches/py3k/Doc/c-api/long.rst Modified: python/branches/py3k/Doc/c-api/long.rst ============================================================================== --- python/branches/py3k/Doc/c-api/long.rst (original) +++ python/branches/py3k/Doc/c-api/long.rst Tue Mar 31 17:49:02 2009 @@ -133,9 +133,9 @@ single: PY_SSIZE_T_MAX single: OverflowError (built-in exception) - Return a C :ctype:`Py_ssize_t` representation of the contents of *pylong*. If - *pylong* is greater than :const:`PY_SSIZE_T_MAX`, an :exc:`OverflowError` is raised - and ``-1`` will be returned. + Return a C :ctype:`Py_ssize_t` representation of the contents of *pylong*. + If *pylong* is greater than :const:`PY_SSIZE_T_MAX`, an :exc:`OverflowError` + is raised and ``-1`` will be returned. .. cfunction:: unsigned long PyLong_AsUnsignedLong(PyObject *pylong) @@ -149,16 +149,6 @@ raised. -.. cfunction:: Py_ssize_t PyLong_AsSsize_t(PyObject *pylong) - - .. index:: - single: PY_SSIZE_T_MAX - - Return a :ctype:`Py_ssize_t` representation of the contents of *pylong*. If - *pylong* is greater than :const:`PY_SSIZE_T_MAX`, an :exc:`OverflowError` is - raised. - - .. cfunction:: size_t PyLong_AsSize_t(PyObject *pylong) Return a :ctype:`size_t` representation of the contents of *pylong*. If From python-checkins at python.org Tue Mar 31 17:50:16 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 17:50:16 +0200 (CEST) Subject: [Python-checkins] r70828 - python/trunk/Doc/library/abc.rst Message-ID: <20090331155016.413291E4105@bag.python.org> Author: georg.brandl Date: Tue Mar 31 17:50:16 2009 New Revision: 70828 Log: #5581: fget argument of abstractproperty is optional as well. Modified: python/trunk/Doc/library/abc.rst Modified: python/trunk/Doc/library/abc.rst ============================================================================== --- python/trunk/Doc/library/abc.rst (original) +++ python/trunk/Doc/library/abc.rst Tue Mar 31 17:50:16 2009 @@ -161,7 +161,7 @@ multiple-inheritance. -.. function:: abstractproperty(fget[, fset[, fdel[, doc]]]) +.. function:: abstractproperty([fget[, fset[, fdel[, doc]]]]) A subclass of the built-in :func:`property`, indicating an abstract property. @@ -189,6 +189,7 @@ def setx(self, value): ... x = abstractproperty(getx, setx) + .. rubric:: Footnotes .. [#] C++ programmers should note that Python's virtual base class From python-checkins at python.org Tue Mar 31 17:52:41 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 17:52:41 +0200 (CEST) Subject: [Python-checkins] r70829 - in python/branches/py3k/Doc/extending: extending.rst newtypes.rst Message-ID: <20090331155241.E07CD1E4167@bag.python.org> Author: georg.brandl Date: Tue Mar 31 17:52:41 2009 New Revision: 70829 Log: #5548: do return the new module from PyMODINIT_FUNC functions. Modified: python/branches/py3k/Doc/extending/extending.rst python/branches/py3k/Doc/extending/newtypes.rst Modified: python/branches/py3k/Doc/extending/extending.rst ============================================================================== --- python/branches/py3k/Doc/extending/extending.rst (original) +++ python/branches/py3k/Doc/extending/extending.rst Tue Mar 31 17:52:41 2009 @@ -1266,12 +1266,13 @@ { PyObject *m; - m = Py_InitModule("client", ClientMethods); + m = PyModule_Create(&clientmodule); if (m == NULL) - return; + return NULL; if (import_spam() < 0) - return; + return NULL; /* additional initialization can happen here */ + return m; } The main disadvantage of this approach is that the file :file:`spammodule.h` is Modified: python/branches/py3k/Doc/extending/newtypes.rst ============================================================================== --- python/branches/py3k/Doc/extending/newtypes.rst (original) +++ python/branches/py3k/Doc/extending/newtypes.rst Tue Mar 31 17:52:41 2009 @@ -871,6 +871,7 @@ Py_INCREF(&ShoddyType); PyModule_AddObject(m, "Shoddy", (PyObject *) &ShoddyType); + return m; } Before calling :cfunc:`PyType_Ready`, the type structure must have the From buildbot at python.org Tue Mar 31 17:55:25 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 15:55:25 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 2.6 Message-ID: <20090331155526.55D111E4105@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%202.6/builds/210 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 18:11:46 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 18:11:46 +0200 (CEST) Subject: [Python-checkins] r70830 - in python/trunk/Doc: glossary.rst library/sys.rst reference/simple_stmts.rst Message-ID: <20090331161146.BA88A1E4028@bag.python.org> Author: georg.brandl Date: Tue Mar 31 18:11:45 2009 New Revision: 70830 Log: #5529: backport new docs of import semantics written by Brett to 2.x. Modified: python/trunk/Doc/glossary.rst python/trunk/Doc/library/sys.rst python/trunk/Doc/reference/simple_stmts.rst Modified: python/trunk/Doc/glossary.rst ============================================================================== --- python/trunk/Doc/glossary.rst (original) +++ python/trunk/Doc/glossary.rst Tue Mar 31 18:11:45 2009 @@ -185,6 +185,11 @@ A module written in C or C++, using Python's C API to interact with the core and with user code. + finder + An object that tries to find the :term:`loader` for a module. It must + implement a method named :meth:`find_module`. See :pep:`302` for + details. + function A series of statements which returns some value to a caller. It can also be passed zero or more arguments which may be used in the execution of @@ -288,6 +293,10 @@ fraction. Integer division can be forced by using the ``//`` operator instead of the ``/`` operator. See also :term:`__future__`. + importer + An object that both finds and loads a module; both a + :term:`finder` and :term:`loader` object. + interactive Python has an interactive interpreter which means you can enter statements and expressions at the interpreter prompt, immediately @@ -368,6 +377,11 @@ clause is optional. If omitted, all elements in ``range(256)`` are processed. + loader + An object that loads a module. It must define a method named + :meth:`load_module`. A loader is typically returned by a + :term:`finder`. See :pep:`302` for details. + mapping A container object (such as :class:`dict`) which supports arbitrary key lookups using the special method :meth:`__getitem__`. Modified: python/trunk/Doc/library/sys.rst ============================================================================== --- python/trunk/Doc/library/sys.rst (original) +++ python/trunk/Doc/library/sys.rst Tue Mar 31 18:11:45 2009 @@ -554,6 +554,22 @@ characters are stored as UCS-2 or UCS-4. +.. data:: meta_path + + A list of :term:`finder` objects that have their :meth:`find_module` + methods called to see if one of the objects can find the module to be + imported. The :meth:`find_module` method is called at least with the + absolute name of the module being imported. If the module to be imported is + contained in package then the parent package's :attr:`__path__` attribute + is passed in as a second argument. The method returns :keyword:`None` if + the module cannot be found, else returns a :term:`loader`. + + :data:`sys.meta_path` is searched before any implicit default finders or + :data:`sys.path`. + + See :pep:`302` for the original specification. + + .. data:: modules .. index:: builtin: reload @@ -590,6 +606,27 @@ :data:`sys.path`. +.. data:: path_hooks + + A list of callables that take a path argument to try to create a + :term:`finder` for the path. If a finder can be created, it is to be + returned by the callable, else raise :exc:`ImportError`. + + Originally specified in :pep:`302`. + + +.. data:: path_importer_cache + + A dictionary acting as a cache for :term:`finder` objects. The keys are + paths that have been passed to :data:`sys.path_hooks` and the values are + the finders that are found. If a path is a valid file system path but no + explicit finder is found on :data:`sys.path_hooks` then :keyword:`None` is + stored to represent the implicit default finder should be used. If the path + is not an existing path then :class:`imp.NullImporter` is set. + + Originally specified in :pep:`302`. + + .. data:: platform This string contains a platform identifier that can be used to append Modified: python/trunk/Doc/reference/simple_stmts.rst ============================================================================== --- python/trunk/Doc/reference/simple_stmts.rst (original) +++ python/trunk/Doc/reference/simple_stmts.rst Tue Mar 31 18:11:45 2009 @@ -653,48 +653,124 @@ Import statements are executed in two steps: (1) find a module, and initialize it if necessary; (2) define a name or names in the local namespace (of the scope -where the :keyword:`import` statement occurs). The first form (without -:keyword:`from`) repeats these steps for each identifier in the list. The form -with :keyword:`from` performs step (1) once, and then performs step (2) -repeatedly. - -In this context, to "initialize" a built-in or extension module means to call an -initialization function that the module must provide for the purpose (in the -reference implementation, the function's name is obtained by prepending string -"init" to the module's name); to "initialize" a Python-coded module means to -execute the module's body. - -.. index:: - single: modules (in module sys) - single: sys.modules - pair: module; name - pair: built-in; module - pair: user-defined; module - module: sys - pair: filename; extension - triple: module; search; path - -The system maintains a table of modules that have been or are being initialized, -indexed by module name. This table is accessible as ``sys.modules``. When a -module name is found in this table, step (1) is finished. If not, a search for -a module definition is started. When a module is found, it is loaded. Details -of the module searching and loading process are implementation and platform -specific. It generally involves searching for a "built-in" module with the -given name and then searching a list of locations given as ``sys.path``. +where the :keyword:`import` statement occurs). The statement comes in two +forms differing on whether it uses the :keyword:`from` keyword. The first form +(without :keyword:`from`) repeats these steps for each identifier in the list. +The form with :keyword:`from` performs step (1) once, and then performs step +(2) repeatedly. .. index:: - pair: module; initialization - exception: ImportError - single: code block - exception: SyntaxError + single: package + +To understand how step (1) occurs, one must first understand how Python handles +hierarchical naming of modules. To help organize modules and provide a +hierarchy in naming, Python has a concept of packages. A package can contain +other packages and modules while modules cannot contain other modules or +packages. From a file system perspective, packages are directories and modules +are files. The original `specification for packages +`_ is still available to read, +although minor details have changed since the writing of that document. -If a built-in module is found, its built-in initialization code is executed and -step (1) is finished. If no matching file is found, :exc:`ImportError` is -raised. If a file is found, it is parsed, yielding an executable code block. If -a syntax error occurs, :exc:`SyntaxError` is raised. Otherwise, an empty module -of the given name is created and inserted in the module table, and then the code -block is executed in the context of this module. Exceptions during this -execution terminate step (1). +.. index:: + single: sys.modules + +Once the name of the module is known (unless otherwise specified, the term +"module" will refer to both packages and modules), searching +for the module or package can begin. The first place checked is +:data:`sys.modules`, the cache of all modules that have been imported +previously. If the module is found there then it is used in step (2) of import. + +.. index:: + single: sys.meta_path + single: finder + pair: finder; find_module + single: __path__ + +If the module is not found in the cache, then :data:`sys.meta_path` is searched +(the specification for :data:`sys.meta_path` can be found in :pep:`302`). +The object is a list of :term:`finder` objects which are queried in order as to +whether they know how to load the module by calling their :meth:`find_module` +method with the name of the module. If the module happens to be contained +within a package (as denoted by the existence of a dot in the name), then a +second argument to :meth:`find_module` is given as the value of the +:attr:`__path__` attribute from the parent package (everything up to the last +dot in the name of the module being imported). If a finder can find the module +it returns a :term:`loader` (discussed later) or returns :keyword:`None`. + +.. index:: + single: sys.path_hooks + single: sys.path_importer_cache + single: sys.path + +If none of the finders on :data:`sys.meta_path` are able to find the module +then some implicitly defined finders are queried. Implementations of Python +vary in what implicit meta path finders are defined. The one they all do +define, though, is one that handles :data:`sys.path_hooks`, +:data:`sys.path_importer_cache`, and :data:`sys.path`. + +The implicit finder searches for the requested module in the "paths" specified +in one of two places ("paths" do not have to be file system paths). If the +module being imported is supposed to be contained within a package then the +second argument passed to :meth:`find_module`, :attr:`__path__` on the parent +package, is used as the source of paths. If the module is not contained in a +package then :data:`sys.path` is used as the source of paths. + +Once the source of paths is chosen it is iterated over to find a finder that +can handle that path. The dict at :data:`sys.path_importer_cache` caches +finders for paths and is checked for a finder. If the path does not have a +finder cached then :data:`sys.path_hooks` is searched by calling each object in +the list with a single argument of the path, returning a finder or raises +:exc:`ImportError`. If a finder is returned then it is cached in +:data:`sys.path_importer_cache` and then used for that path entry. If no finder +can be found but the path exists then a value of :keyword:`None` is +stored in :data:`sys.path_importer_cache` to signify that an implicit, +file-based finder that handles modules stored as individual files should be +used for that path. If the path does not exist then a finder which always +returns :keyword:`None` is placed in the cache for the path. + +.. index:: + single: loader + pair: loader; load_module + exception: ImportError + +If no finder can find the module then :exc:`ImportError` is raised. Otherwise +some finder returned a loader whose :meth:`load_module` method is called with +the name of the module to load (see :pep:`302` for the original definition of +loaders). A loader has several responsibilities to perform on a module it +loads. First, if the module already exists in :data:`sys.modules` (a +possibility if the loader is called outside of the import machinery) then it +is to use that module for initialization and not a new module. But if the +module does not exist in :data:`sys.modules` then it is to be added to that +dict before initialization begins. If an error occurs during loading of the +module and it was added to :data:`sys.modules` it is to be removed from the +dict. If an error occurs but the module was already in :data:`sys.modules` it +is left in the dict. + +.. index:: + single: __name__ + single: __file__ + single: __path__ + single: __package__ + single: __loader__ + +The loader must set several attributes on the module. :data:`__name__` is to be +set to the name of the module. :data:`__file__` is to be the "path" to the file +unless the module is built-in (and thus listed in +:data:`sys.builtin_module_names`) in which case the attribute is not set. +If what is being imported is a package then :data:`__path__` is to be set to a +list of paths to be searched when looking for modules and packages contained +within the package being imported. :data:`__package__` is optional but should +be set to the name of package that contains the module or package (the empty +string is used for module not contained in a package). :data:`__loader__` is +also optional but should be set to the loader object that is loading the +module. + +.. index:: + exception: ImportError + +If an error occurs during loading then the loader raises :exc:`ImportError` if +some other exception is not already being propagated. Otherwise the loader +returns the module that was loaded and initialized. When step (1) finishes without raising an exception, step (2) can begin. @@ -734,23 +810,21 @@ raise a :exc:`SyntaxError`. .. index:: - keyword: from - statement: from - triple: hierarchical; module; names - single: packages - single: __init__.py - -**Hierarchical module names:** when the module names contains one or more dots, -the module search path is carried out differently. The sequence of identifiers -up to the last dot is used to find a "package"; the final identifier is then -searched inside the package. A package is generally a subdirectory of a -directory on ``sys.path`` that has a file :file:`__init__.py`. - -.. - [XXX Can't be - bothered to spell this out right now; see the URL - http://www.python.org/doc/essays/packages.html for more details, also about how - the module search works from inside a package.] + single: relative; import + +When specifying what module to import you do not have to specify the absolute +name of the module. When a module or package is contained within another +package it is possible to make a relative import within the same top package +without having to mention the package name. By using leading dots in the +specified module or package after :keyword:`from` you can specify how high to +traverse up the current package hierarchy without specifying exact names. One +leading dot means the current package where the module making the import +exists. Two dots means up one package level. Three dots is up two levels, etc. +So if you execute ``from . import mod`` from a module in the ``pkg`` package +then you will end up importing ``pkg.mod``. If you execute ``from ..subpkg2 +imprt mod`` from within ``pkg.subpkg1`` you will import ``pkg.subpkg2.mod``. +The specification for relative imports is contained within :pep:`328`. + .. index:: builtin: __import__ From python-checkins at python.org Tue Mar 31 18:17:07 2009 From: python-checkins at python.org (jeremy.hylton) Date: Tue, 31 Mar 2009 18:17:07 +0200 (CEST) Subject: [Python-checkins] r70831 - in python/branches/release30-maint: Lib/symtable.py Lib/test/test_scope.py Lib/test/test_symtable.py Python/symtable.c Message-ID: <20090331161707.15FE81E4052@bag.python.org> Author: jeremy.hylton Date: Tue Mar 31 18:17:06 2009 New Revision: 70831 Log: Merged revisions 70823 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70823 | jeremy.hylton | 2009-03-31 11:26:37 -0400 (Tue, 31 Mar 2009) | 29 lines Merged revisions 70801,70809 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk The merge ran into a lot of conflicts because dicts were replaced with sets in the Python 3 version of the symbol table. ........ r70801 | jeremy.hylton | 2009-03-31 09:17:03 -0400 (Tue, 31 Mar 2009) | 3 lines Add is_declared_global() which distinguishes between implicit and explicit global variables. ........ r70809 | jeremy.hylton | 2009-03-31 09:48:15 -0400 (Tue, 31 Mar 2009) | 14 lines Global statements from one function leaked into parallel functions. Re http://bugs.python.org/issue4315 The symbol table used the same name dictionaries to recursively analyze each of its child blocks, even though the dictionaries are modified during analysis. The fix is to create new temporary dictionaries via the analyze_child_block(). The only information that needs to propagate back up is the names of the free variables. Add more comments and break out a helper function. This code doesn't get any easier to understand when you only look at it once a year. ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/symtable.py python/branches/release30-maint/Lib/test/test_scope.py python/branches/release30-maint/Lib/test/test_symtable.py python/branches/release30-maint/Python/symtable.c Modified: python/branches/release30-maint/Lib/symtable.py ============================================================================== --- python/branches/release30-maint/Lib/symtable.py (original) +++ python/branches/release30-maint/Lib/symtable.py Tue Mar 31 18:17:06 2009 @@ -191,6 +191,9 @@ def is_global(self): return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)) + def is_declared_global(self): + return bool(self.__scope == GLOBAL_EXPLICIT) + def is_local(self): return bool(self.__flags & DEF_BOUND) Modified: python/branches/release30-maint/Lib/test/test_scope.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_scope.py (original) +++ python/branches/release30-maint/Lib/test/test_scope.py Tue Mar 31 18:17:06 2009 @@ -618,7 +618,6 @@ self.assertEqual(dec(), 0) def testNonLocalMethod(self): - def f(x): class c: def inc(self): @@ -630,13 +629,36 @@ x -= 1 return x return c() - c = f(0) self.assertEqual(c.inc(), 1) self.assertEqual(c.inc(), 2) self.assertEqual(c.dec(), 1) self.assertEqual(c.dec(), 0) + def testGlobalInParallelNestedFunctions(self): + # A symbol table bug leaked the global statement from one + # function to other nested functions in the same block. + # This test verifies that a global statement in the first + # function does not affect the second function. + CODE = """def f(): + y = 1 + def g(): + global y + return y + def h(): + return y + 1 + return g, h +y = 9 +g, h = f() +result9 = g() +result2 = h() +""" + local_ns = {} + global_ns = {} + exec(CODE, local_ns, global_ns) + self.assertEqual(2, global_ns["result2"]) + self.assertEqual(9, global_ns["result9"]) + def testNonLocalClass(self): def f(x): Modified: python/branches/release30-maint/Lib/test/test_symtable.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_symtable.py (original) +++ python/branches/release30-maint/Lib/test/test_symtable.py Tue Mar 31 18:17:06 2009 @@ -88,7 +88,9 @@ def test_globals(self): self.assertTrue(self.spam.lookup("glob").is_global()) + self.assertFalse(self.spam.lookup("glob").is_declared_global()) self.assertTrue(self.spam.lookup("bar").is_global()) + self.assertTrue(self.spam.lookup("bar").is_declared_global()) self.assertFalse(self.internal.lookup("x").is_global()) self.assertFalse(self.Mine.lookup("instance_var").is_global()) Modified: python/branches/release30-maint/Python/symtable.c ============================================================================== --- python/branches/release30-maint/Python/symtable.c (original) +++ python/branches/release30-maint/Python/symtable.c Tue Mar 31 18:17:06 2009 @@ -376,8 +376,9 @@ /* Decide on scope of name, given flags. - The dicts passed in as arguments are modified as necessary. - ste is passed so that flags can be updated. + The namespace dictionaries may be modified to record information + about the new name. For example, a new global will add an entry to + global. A name that was global can be changed to local. */ static int @@ -453,7 +454,7 @@ explicit? It could also be global implicit. */ if (global && PySet_Contains(global, name)) { - SET_SCOPE(scopes, name, GLOBAL_EXPLICIT); + SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); return 1; } if (ste->ste_nested) @@ -627,28 +628,56 @@ } /* Make final symbol table decisions for block of ste. + Arguments: ste -- current symtable entry (input/output) - bound -- set of variables bound in enclosing scopes (input) + bound -- set of variables bound in enclosing scopes (input). bound + is NULL for module blocks. free -- set of free variables in enclosed scopes (output) globals -- set of declared global variables in enclosing scopes (input) + + The implementation uses two mutually recursive functions, + analyze_block() and analyze_child_block(). analyze_block() is + responsible for analyzing the individual names defined in a block. + analyze_child_block() prepares temporary namespace dictionaries + used to evaluated nested blocks. + + The two functions exist because a child block should see the name + bindings of its enclosing blocks, but those bindings should not + propagate back to a parent block. */ static int +analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, + PyObject *global, PyObject* child_free); + +static int analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, PyObject *global) { PyObject *name, *v, *local = NULL, *scopes = NULL, *newbound = NULL; - PyObject *newglobal = NULL, *newfree = NULL; + PyObject *newglobal = NULL, *newfree = NULL, *allfree = NULL; int i, success = 0; Py_ssize_t pos = 0; - scopes = PyDict_New(); - if (!scopes) - goto error; - local = PySet_New(NULL); + local = PySet_New(NULL); /* collect new names bound in block */ if (!local) goto error; + scopes = PyDict_New(); /* collect scopes defined for each name */ + if (!scopes) + goto error; + + /* Allocate new global and bound variable dictionaries. These + dictionaries hold the names visible in nested blocks. For + ClassBlocks, the bound and global names are initialized + before analyzing names, because class bindings aren't + visible in methods. For other blocks, they are initialized + after names are analyzed. + */ + + /* TODO(jhylton): Package these dicts in a struct so that we + can write reasonable helper functions? + */ newglobal = PySet_New(NULL); if (!newglobal) goto error; @@ -665,25 +694,22 @@ this one. */ if (ste->ste_type == ClassBlock) { + /* Pass down known globals */ + if (!PyNumber_InPlaceOr(newglobal, global)) + goto error; + Py_DECREF(newglobal); /* Pass down previously bound symbols */ if (bound) { if (!PyNumber_InPlaceOr(newbound, bound)) goto error; Py_DECREF(newbound); } - /* Pass down known globals */ - if (!PyNumber_InPlaceOr(newglobal, global)) - goto error; - Py_DECREF(newglobal); } - /* Analyze symbols in current scope */ - assert(PySTEntry_Check(ste)); - assert(PyDict_Check(ste->ste_symbols)); while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) { long flags = PyLong_AS_LONG(v); - if (!analyze_name(ste, scopes, name, flags, bound, local, free, - global)) + if (!analyze_name(ste, scopes, name, flags, + bound, local, free, global)) goto error; } @@ -715,19 +741,31 @@ goto error; } - /* Recursively call analyze_block() on each child block */ + /* Recursively call analyze_block() on each child block. + + newbound, newglobal now contain the names visible in + nested blocks. The free variables in the children will + be collected in allfree. + */ + allfree = PySet_New(NULL); + if (!allfree) + goto error; for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) { PyObject *c = PyList_GET_ITEM(ste->ste_children, i); PySTEntryObject* entry; assert(c && PySTEntry_Check(c)); entry = (PySTEntryObject*)c; - if (!analyze_block(entry, newbound, newfree, newglobal)) + if (!analyze_child_block(entry, newbound, newfree, newglobal, + allfree)) goto error; /* Check if any children have free variables */ if (entry->ste_free || entry->ste_child_free) ste->ste_child_free = 1; } + if (PyNumber_InPlaceOr(newfree, allfree) < 0) + goto error; + /* Check if any local variables must be converted to cell variables */ if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree, NULL)) @@ -752,12 +790,48 @@ Py_XDECREF(newbound); Py_XDECREF(newglobal); Py_XDECREF(newfree); + Py_XDECREF(allfree); if (!success) assert(PyErr_Occurred()); return success; } static int +analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, + PyObject *global, PyObject* child_free) +{ + PyObject *temp_bound = NULL, *temp_global = NULL, *temp_free = NULL; + int success = 0; + + /* Copy the bound and global dictionaries. + + These dictionary are used by all blocks enclosed by the + current block. The analyze_block() call modifies these + dictionaries. + + */ + temp_bound = PySet_New(bound); + if (!temp_bound) + goto error; + temp_free = PySet_New(free); + if (!temp_free) + goto error; + temp_global = PySet_New(global); + if (!temp_global) + goto error; + + if (!analyze_block(entry, temp_bound, temp_free, temp_global)) + goto error; + success = PyNumber_InPlaceOr(child_free, temp_free) >= 0; + success = 1; + error: + Py_XDECREF(temp_bound); + Py_XDECREF(temp_free); + Py_XDECREF(temp_global); + return success; +} + +static int symtable_analyze(struct symtable *st) { PyObject *free, *global; From python-checkins at python.org Tue Mar 31 18:31:12 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 18:31:12 +0200 (CEST) Subject: [Python-checkins] r70832 - python/trunk/Doc/library/_winreg.rst Message-ID: <20090331163112.13B861E4052@bag.python.org> Author: georg.brandl Date: Tue Mar 31 18:31:11 2009 New Revision: 70832 Log: #1386675: specify WindowsError as the exception, because it has a winerror attribute that EnvironmentError doesnt have. Modified: python/trunk/Doc/library/_winreg.rst Modified: python/trunk/Doc/library/_winreg.rst ============================================================================== --- python/trunk/Doc/library/_winreg.rst (original) +++ python/trunk/Doc/library/_winreg.rst Tue Mar 31 18:31:11 2009 @@ -1,4 +1,3 @@ - :mod:`_winreg` -- Windows registry access ========================================= @@ -47,8 +46,8 @@ *key* is the predefined handle to connect to. - The return value is the handle of the opened key. If the function fails, an - :exc:`EnvironmentError` exception is raised. + The return value is the handle of the opened key. If the function fails, a + :exc:`WindowsError` exception is raised. .. function:: CreateKey(key, sub_key) @@ -65,8 +64,8 @@ If the key already exists, this function opens the existing key. - The return value is the handle of the opened key. If the function fails, an - :exc:`EnvironmentError` exception is raised. + The return value is the handle of the opened key. If the function fails, a + :exc:`WindowsError` exception is raised. .. function:: DeleteKey(key, sub_key) @@ -82,7 +81,7 @@ *This method can not delete keys with subkeys.* If the method succeeds, the entire key, including all of its values, is removed. - If the method fails, an :exc:`EnvironmentError` exception is raised. + If the method fails, a :exc:`WindowsError` exception is raised. .. function:: DeleteValue(key, value) @@ -105,7 +104,7 @@ *index* is an integer that identifies the index of the key to retrieve. The function retrieves the name of one subkey each time it is called. It is - typically called repeatedly until an :exc:`EnvironmentError` exception is + typically called repeatedly until a :exc:`WindowsError` exception is raised, indicating, no more values are available. @@ -119,7 +118,7 @@ *index* is an integer that identifies the index of the value to retrieve. The function retrieves the name of one subkey each time it is called. It is - typically called repeatedly, until an :exc:`EnvironmentError` exception is + typically called repeatedly, until a :exc:`WindowsError` exception is raised, indicating no more values. The result is a tuple of 3 items: @@ -209,7 +208,7 @@ The result is a new handle to the specified key. - If the function fails, :exc:`EnvironmentError` is raised. + If the function fails, :exc:`WindowsError` is raised. .. function:: OpenKeyEx() From python-checkins at python.org Tue Mar 31 18:37:16 2009 From: python-checkins at python.org (jeremy.hylton) Date: Tue, 31 Mar 2009 18:37:16 +0200 (CEST) Subject: [Python-checkins] r70833 - python/branches/py3k/Lib/urllib/request.py Message-ID: <20090331163716.6B72E1E4052@bag.python.org> Author: jeremy.hylton Date: Tue Mar 31 18:37:16 2009 New Revision: 70833 Log: Make urllib use HTTP/1.1. It seems to work now, but hasn't been carefully tested. Modified: python/branches/py3k/Lib/urllib/request.py Modified: python/branches/py3k/Lib/urllib/request.py ============================================================================== --- python/branches/py3k/Lib/urllib/request.py (original) +++ python/branches/py3k/Lib/urllib/request.py Tue Mar 31 18:37:16 2009 @@ -1562,10 +1562,6 @@ else: auth = None http_conn = connection_factory(host) -## # XXX We should fix urllib so that it works with HTTP/1.1. -## http_conn._http_vsn = 10 -## http_conn._http_vsn_str = "HTTP/1.0" - headers = {} if proxy_auth: headers["Proxy-Authorization"] = "Basic %s" % proxy_auth From python-checkins at python.org Tue Mar 31 18:38:55 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 31 Mar 2009 18:38:55 +0200 (CEST) Subject: [Python-checkins] r70834 - python/branches/py3k-short-float-repr/Python/dtoa.c Message-ID: <20090331163855.8F4941E4052@bag.python.org> Author: mark.dickinson Date: Tue Mar 31 18:38:55 2009 New Revision: 70834 Log: Turn off recognition of hexadecimal floats in dtoa.c, and fix associated 'undeclared variable' bug. Modified: python/branches/py3k-short-float-repr/Python/dtoa.c Modified: python/branches/py3k-short-float-repr/Python/dtoa.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/dtoa.c (original) +++ python/branches/py3k-short-float-repr/Python/dtoa.c Tue Mar 31 18:38:55 2009 @@ -183,6 +183,8 @@ #include "Python.h" +#define NO_HEX_FP + /* use WORDS_BIGENDIAN to determine float endianness. This assumes that ints and floats share the same endianness on the target machine, which appears to be true for every platform that Python currently cares about. We're @@ -1632,7 +1634,6 @@ #endif /*No_Hex_NaN*/ #endif /* INFNAN_CHECK */ -#ifndef NO_HEX_FP /*{*/ #ifdef Pack_32 #define ULbits 32 #define kshift 5 @@ -1643,6 +1644,8 @@ #define kmask 15 #endif +#ifndef NO_HEX_FP /*{*/ + static void #ifdef KR_headers rshift(b, k) Bigint *b; int k; From python-checkins at python.org Tue Mar 31 18:45:45 2009 From: python-checkins at python.org (mark.dickinson) Date: Tue, 31 Mar 2009 18:45:45 +0200 (CEST) Subject: [Python-checkins] r70835 - python/branches/py3k-short-float-repr/Python/pystrtod.c Message-ID: <20090331164545.EE1781E40A8@bag.python.org> Author: mark.dickinson Date: Tue Mar 31 18:45:45 2009 New Revision: 70835 Log: Use strtod from dtoa.c instead of platform strtod. Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/pystrtod.c (original) +++ python/branches/py3k-short-float-repr/Python/pystrtod.c Tue Mar 31 18:45:45 2009 @@ -40,6 +40,16 @@ double PyOS_ascii_strtod(const char *nptr, char **endptr) { + assert(nptr != NULL); + /* Set errno to zero, so that we can distinguish zero results + and underflows */ + errno = 0; + return _Py_dg_strtod(nptr, endptr); +} + +double +PyOS_ascii_strtod_fallback(const char *nptr, char **endptr) +{ char *fail_pos; double val = -1.0; struct lconv *locale_data; From buildbot at python.org Tue Mar 31 18:48:28 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 16:48:28 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.x Message-ID: <20090331164829.281821E406D@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.x/builds/597 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 18:50:26 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 18:50:26 +0200 (CEST) Subject: [Python-checkins] r70836 - python/trunk/Doc/extending/extending.rst Message-ID: <20090331165026.683061E41B1@bag.python.org> Author: georg.brandl Date: Tue Mar 31 18:50:25 2009 New Revision: 70836 Log: #5417: replace references to undocumented functions by ones to documented functions. Modified: python/trunk/Doc/extending/extending.rst Modified: python/trunk/Doc/extending/extending.rst ============================================================================== --- python/trunk/Doc/extending/extending.rst (original) +++ python/trunk/Doc/extending/extending.rst Tue Mar 31 18:50:25 2009 @@ -465,10 +465,10 @@ (but note that *temp* will not be *NULL* in this context). More info on them in section :ref:`refcounts`. -.. index:: single: PyEval_CallObject() +.. index:: single: PyObject_CallObject() Later, when it is time to call the function, you call the C function -:cfunc:`PyEval_CallObject`. This function has two arguments, both pointers to +:cfunc:`PyObject_CallObject`. This function has two arguments, both pointers to arbitrary Python objects: the Python function, and the argument list. The argument list must always be a tuple object, whose length is the number of arguments. To call the Python function with no arguments, pass in NULL, or @@ -484,16 +484,16 @@ ... /* Time to call the callback */ arglist = Py_BuildValue("(i)", arg); - result = PyEval_CallObject(my_callback, arglist); + result = PyObject_CallObject(my_callback, arglist); Py_DECREF(arglist); -:cfunc:`PyEval_CallObject` returns a Python object pointer: this is the return -value of the Python function. :cfunc:`PyEval_CallObject` is +:cfunc:`PyObject_CallObject` returns a Python object pointer: this is the return +value of the Python function. :cfunc:`PyObject_CallObject` is "reference-count-neutral" with respect to its arguments. In the example a new tuple was created to serve as the argument list, which is :cfunc:`Py_DECREF`\ -ed immediately after the call. -The return value of :cfunc:`PyEval_CallObject` is "new": either it is a brand +The return value of :cfunc:`PyObject_CallObject` is "new": either it is a brand new object, or it is an existing object whose reference count has been incremented. So, unless you want to save it in a global variable, you should somehow :cfunc:`Py_DECREF` the result, even (especially!) if you are not @@ -501,7 +501,7 @@ Before you do this, however, it is important to check that the return value isn't *NULL*. If it is, the Python function terminated by raising an exception. -If the C code that called :cfunc:`PyEval_CallObject` is called from Python, it +If the C code that called :cfunc:`PyObject_CallObject` is called from Python, it should now return an error indication to its Python caller, so the interpreter can print a stack trace, or the calling Python code can handle the exception. If this is not possible or desirable, the exception should be cleared by calling @@ -513,7 +513,7 @@ Py_DECREF(result); Depending on the desired interface to the Python callback function, you may also -have to provide an argument list to :cfunc:`PyEval_CallObject`. In some cases +have to provide an argument list to :cfunc:`PyObject_CallObject`. In some cases the argument list is also provided by the Python program, through the same interface that specified the callback function. It can then be saved and used in the same manner as the function object. In other cases, you may have to @@ -524,7 +524,7 @@ PyObject *arglist; ... arglist = Py_BuildValue("(l)", eventcode); - result = PyEval_CallObject(my_callback, arglist); + result = PyObject_CallObject(my_callback, arglist); Py_DECREF(arglist); if (result == NULL) return NULL; /* Pass error back */ @@ -536,19 +536,20 @@ :cfunc:`Py_BuildValue` may run out of memory, and this should be checked. You may also call a function with keyword arguments by using -:cfunc:`PyEval_CallObjectWithKeywords`. As in the above example, we use -:cfunc:`Py_BuildValue` to construct the dictionary. :: +:cfunc:`PyObject_Call`, which supports arguments and keyword arguments. As in +the above example, we use :cfunc:`Py_BuildValue` to construct the dictionary. :: PyObject *dict; ... dict = Py_BuildValue("{s:i}", "name", val); - result = PyEval_CallObjectWithKeywords(my_callback, NULL, dict); + result = PyObject_Call(my_callback, NULL, dict); Py_DECREF(dict); if (result == NULL) return NULL; /* Pass error back */ /* Here maybe use the result */ Py_DECREF(result); + .. _parsetuple: Extracting Parameters in Extension Functions From python-checkins at python.org Tue Mar 31 18:54:10 2009 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 31 Mar 2009 18:54:10 +0200 (CEST) Subject: [Python-checkins] r70837 - in python/trunk: Doc/library/unittest.rst Lib/test/test_gc.py Lib/test/test_struct.py Lib/test/test_unittest.py Lib/unittest.py Misc/NEWS Message-ID: <20090331165410.9F3A41E406D@bag.python.org> Author: gregory.p.smith Date: Tue Mar 31 18:54:10 2009 New Revision: 70837 Log: The unittest.TestCase.assertEqual() now displays the differences in lists, tuples, dicts and sets on failure. Many new handy type and comparison specific assert* methods have been added that fail with error messages actually useful for debugging. Contributed in by Google and completed with help from mfoord and GvR at PyCon 2009 sprints. Discussion lives in http://bugs.python.org/issue2578. Modified: python/trunk/Doc/library/unittest.rst python/trunk/Lib/test/test_gc.py python/trunk/Lib/test/test_struct.py python/trunk/Lib/test/test_unittest.py python/trunk/Lib/unittest.py python/trunk/Misc/NEWS Modified: python/trunk/Doc/library/unittest.rst ============================================================================== --- python/trunk/Doc/library/unittest.rst (original) +++ python/trunk/Doc/library/unittest.rst Tue Mar 31 18:54:10 2009 @@ -209,8 +209,8 @@ widget = Widget('The widget') self.assertEqual(widget.size(), (50, 50), 'incorrect default size') -Note that in order to test something, we use the one of the :meth:`assert\*` or -:meth:`fail\*` methods provided by the :class:`TestCase` base class. If the +Note that in order to test something, we use the one of the :meth:`assert\*` +methods provided by the :class:`TestCase` base class. If the test fails, an exception will be raised, and :mod:`unittest` will identify the test case as a :dfn:`failure`. Any other exceptions will be treated as :dfn:`errors`. This helps you identify where the problem is: :dfn:`failures` are @@ -240,13 +240,13 @@ class DefaultWidgetSizeTestCase(SimpleWidgetTestCase): def runTest(self): - self.failUnless(self.widget.size() == (50,50), + self.assertTrue(self.widget.size() == (50,50), 'incorrect default size') class WidgetResizeTestCase(SimpleWidgetTestCase): def runTest(self): self.widget.resize(100,150) - self.failUnless(self.widget.size() == (100,150), + self.assertTrue(self.widget.size() == (100,150), 'wrong size after resize') If the :meth:`~TestCase.setUp` method raises an exception while the test is @@ -288,12 +288,12 @@ self.widget = None def testDefaultSize(self): - self.failUnless(self.widget.size() == (50,50), + self.assertTrue(self.widget.size() == (50,50), 'incorrect default size') def testResize(self): self.widget.resize(100,150) - self.failUnless(self.widget.size() == (100,150), + self.assertTrue(self.widget.size() == (100,150), 'wrong size after resize') Here we have not provided a :meth:`~TestCase.runTest` method, but have instead @@ -606,9 +606,9 @@ failures. - .. method:: assert_(expr[, msg]) + .. method:: assertTrue(expr[, msg]) + assert_(expr[, msg]) failUnless(expr[, msg]) - assertTrue(expr[, msg]) Signal a test failure if *expr* is false; the explanation for the error will be *msg* if given, otherwise it will be :const:`None`. @@ -619,10 +619,18 @@ Test that *first* and *second* are equal. If the values do not compare equal, the test will fail with the explanation given by *msg*, or - :const:`None`. Note that using :meth:`failUnlessEqual` improves upon - doing the comparison as the first parameter to :meth:`failUnless`: the - default value for *msg* can be computed to include representations of both - *first* and *second*. + :const:`None`. Note that using :meth:`assertEqual` improves upon + doing the comparison as the first parameter to :meth:`assertTrue`: the + default value for *msg* include representations of both *first* and + *second*. + + In addition, if *first* and *second* are the exact same type and one of + list, tuple, dict, set, or frozenset or any type that a subclass + registers :meth:`addTypeEqualityFunc` the type specific equality function + will be called in order to generate a more useful default error message. + + .. versionchanged:: 2.7 + Added the automatic calling of type specific equality function. .. method:: assertNotEqual(first, second[, msg]) @@ -630,8 +638,8 @@ Test that *first* and *second* are not equal. If the values do compare equal, the test will fail with the explanation given by *msg*, or - :const:`None`. Note that using :meth:`failIfEqual` improves upon doing - the comparison as the first parameter to :meth:`failUnless` is that the + :const:`None`. Note that using :meth:`assertNotEqual` improves upon doing + the comparison as the first parameter to :meth:`assertTrue` is that the default value for *msg* can be computed to include representations of both *first* and *second*. @@ -662,6 +670,125 @@ :const:`None`. + .. method:: assertGreater(first, second, msg=None) + assertGreaterEqual(first, second, msg=None) + assertLess(first, second, msg=None) + assertLessEqual(first, second, msg=None) + + Test that *first* is respectively >, >=, < or <= than *second* depending + on the method name. If not, the test will fail with the nice explanation + or with the explanation given by *msg*:: + + >>> self.assertGreaterEqual(3, 4) + AssertionError: "3" unexpectedly not greater than or equal to "4" + + .. versionadded:: 2.7 + + + .. method:: assertMultiLineEqual(self, first, second, msg=None) + + Test that the multiline string *first* is equal to the string *second*. + When not equal a diff of the two strings highlighting the differences + will be included in the error message. + + If specified *msg* will be used as the error message on failure. + + .. versionadded:: 2.7 + + + .. method:: assertRegexpMatches(text, regexp[, msg=None]): + + Verifies that a *regexp* search matches *text*. Fails with an error + message including the pattern and the *text*. *regexp* may be + a regular expression object or a string containing a regular expression + suitable for use by :func:`re.search`. + + .. versionadded:: 2.7 + + + .. method:: assertIn(first, second, msg=None) + assertNotIn(first, second, msg=None) + + Tests that *first* is or is not in *second* with a nice explanitory error + message as appropriate. + + If specified *msg* will be used as the error message on failure. + + .. versionadded:: 2.7 + + + .. method:: assertSameElements(expected, actual, msg=None) + + Test that sequence *expected* contains the same elements as *actual*. + When they don't an error message listing the differences between the + sequences will be generated. + + If specified *msg* will be used as the error message on failure. + + .. versionadded:: 2.7 + + + .. method:: assertSetEqual(set1, set2, msg=None) + + Tests that two sets are equal. If not, an error message is constructed + that lists the differences between the sets. + + Fails if either of *set1* or *set2* does not have a :meth:`set.difference` + method. + + If specified *msg* will be used as the error message on failure. + + .. versionadded:: 2.7 + + + .. method:: assertDictEqual(expected, actual, msg=None) + + Test that two dictionaries are equal. If not, an error message is + constructed that shows the differences in the dictionaries. + + If specified *msg* will be used as the error message on failure. + + .. versionadded:: 2.7 + + + .. method:: assertDictContainsSubset(expected, actual, msg=None) + + Tests whether the key value pairs in dictionary *actual* are a + superset of those in *expected*. If not, an error message listing + the missing keys and mismatched values is generated. + + If specified *msg* will be used as the error message on failure. + + .. versionadded:: 2.7 + + + .. method:: assertListEqual(list1, list2, msg=None) + assertTupleEqual(tuple1, tuple2, msg=None) + + Tests that two lists or tuples are equal. If not an error message is + constructed that shows only the differences between the two. An error + is also raised if either of the parameters are of the wrong type. + + If specified *msg* will be used as the error message on failure. + + .. versionadded:: 2.7 + + + .. method:: assertSequenceEqual(seq1, seq2, msg=None, seq_type=None) + + Tests that two sequences are equal. If a *seq_type* is supplied, both + *seq1* and *seq2* must be instances of *seq_type* or a failure will + be raised. If the sequences are different an error message is + constructed that shows the difference between the two. + + If specified *msg* will be used as the error message on failure. + + This method is used to implement :meth:`assertListEqual` and + :meth:`assertTupleEqual`. + + .. versionadded:: 2.7 + + .. method:: assertRaises(exception[, callable, ...]) failUnlessRaises(exception[, callable, ...]) @@ -682,10 +809,43 @@ Added the ability to use :meth:`assertRaises` as a context manager. - .. method:: failIf(expr[, msg]) - assertFalse(expr[, msg]) + .. method:: assertRaisesRegexp(exception, regexp[, callable, ...]) + + Like :meth:`assertRaises` but also tests that *regexp* matches + on the string representation of the raised exception. *regexp* may be + a regular expression object or a string containing a regular expression + suitable for use by :func:`re.search`. Examples:: + + self.assertRaisesRegexp(ValueError, 'invalid literal for.*XYZ$', + int, 'XYZ') - The inverse of the :meth:`failUnless` method is the :meth:`failIf` method. + or:: + + with self.assertRaisesRegexp(ValueError, 'literal'): + int('XYZ') + + .. versionadded:: 2.7 + + + .. method:: assertIsNone(expr[, msg]) + + This signals a test failure if *expr* is not None. + + .. versionadded:: 2.7 + + + .. method:: assertIsNotNone(expr[, msg]) + + The inverse of the :meth:`assertIsNone` method. + This signals a test failure if *expr* is None. + + .. versionadded:: 2.7 + + + .. method:: assertFalse(expr[, msg]) + failIf(expr[, msg]) + + The inverse of the :meth:`assertTrue` method is the :meth:`assertFalse` method. This signals a test failure if *expr* is true, with *msg* or :const:`None` for the error message. @@ -733,10 +893,34 @@ .. method:: shortDescription() - Returns a one-line description of the test, or :const:`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 - :const:`None`. + Returns a description of the test, or :const:`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, + along with the method name. + + .. versionchanged:: 2.7 + + In earlier versions this only returned the first line of the test + method's docstring, if available or the :const:`None`. That led to + undesirable behavior of not printing the test name when someone was + thoughtful enough to write a docstring. + + + .. method:: addTypeEqualityFunc(typeobj, function) + + Registers a type specific :meth:`assertEqual` equality checking + function to be called by :meth:`assertEqual` when both objects it has + been asked to compare are exactly *typeobj* (not subclasses). + *function* must take two positional arguments and a third msg=None + keyword argument just as :meth:`assertEqual` does. It must raise + self.failureException when inequality between the first two + parameters is detected. + + One good use of custom equality checking functions for a type + is to raise self.failureException with an error message useful + for debugging the by explaining the inequalities in detail. + + .. versionadded:: 2.7 .. class:: FunctionTestCase(testFunc[, setUp[, tearDown[, description]]]) Modified: python/trunk/Lib/test/test_gc.py ============================================================================== --- python/trunk/Lib/test/test_gc.py (original) +++ python/trunk/Lib/test/test_gc.py Tue Mar 31 18:54:10 2009 @@ -244,7 +244,7 @@ # - the call to assertEqual somehow avoids building its args tuple def test_get_count(self): # Avoid future allocation of method object - assertEqual = self.assertEqual + assertEqual = self._baseAssertEqual gc.collect() assertEqual(gc.get_count(), (0, 0, 0)) a = dict() Modified: python/trunk/Lib/test/test_struct.py ============================================================================== --- python/trunk/Lib/test/test_struct.py (original) +++ python/trunk/Lib/test/test_struct.py Tue Mar 31 18:54:10 2009 @@ -227,6 +227,7 @@ BUGGY_RANGE_CHECK = "bBhHiIlL" def __init__(self, formatpair, bytesize): + super(IntTester, self).__init__(methodName='test_one') self.assertEqual(len(formatpair), 2) self.formatpair = formatpair for direction in "<>!=": Modified: python/trunk/Lib/test/test_unittest.py ============================================================================== --- python/trunk/Lib/test/test_unittest.py (original) +++ python/trunk/Lib/test/test_unittest.py Tue Mar 31 18:54:10 2009 @@ -6,6 +6,7 @@ TestCase.{assert,fail}* methods (some are tested implicitly) """ +import re from test import test_support import unittest from unittest import TestCase @@ -70,21 +71,20 @@ def test_hash(self): for obj_1, obj_2 in self.eq_pairs: try: - assert hash(obj_1) == hash(obj_2) + if not hash(obj_1) == hash(obj_2): + self.fail("%r and %r do not hash equal" % (obj_1, obj_2)) except KeyboardInterrupt: raise - except AssertionError: - self.fail("%s and %s do not hash equal" % (obj_1, obj_2)) except Exception, e: - self.fail("Problem hashing %s and %s: %s" % (obj_1, obj_2, e)) + self.fail("Problem hashing %r and %r: %s" % (obj_1, obj_2, e)) for obj_1, obj_2 in self.ne_pairs: try: - assert hash(obj_1) != hash(obj_2) + if hash(obj_1) == hash(obj_2): + self.fail("%s and %s hash equal, but shouldn't" % + (obj_1, obj_2)) except KeyboardInterrupt: raise - except AssertionError: - self.fail("%s and %s hash equal, but shouldn't" % (obj_1, obj_2)) except Exception, e: self.fail("Problem hashing %s and %s: %s" % (obj_1, obj_2, e)) @@ -2237,39 +2237,6 @@ 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): @@ -2288,6 +2255,409 @@ expected = ['startTest', 'test', 'addSuccess', 'stopTest'] self.assertEqual(events, expected) + def testShortDescriptionWithoutDocstring(self): + self.assertEqual( + self.shortDescription(), + 'testShortDescriptionWithoutDocstring (' + __name__ + + '.Test_TestCase)') + + def testShortDescriptionWithOneLineDocstring(self): + """Tests shortDescription() for a method with a docstring.""" + self.assertEqual( + self.shortDescription(), + ('testShortDescriptionWithOneLineDocstring ' + '(' + __name__ + '.Test_TestCase)\n' + 'Tests shortDescription() for a method with a docstring.')) + + def testShortDescriptionWithMultiLineDocstring(self): + """Tests shortDescription() for a method with a longer docstring. + + This method ensures that only the first line of a docstring is + returned used in the short description, no matter how long the + whole thing is. + """ + self.assertEqual( + self.shortDescription(), + ('testShortDescriptionWithMultiLineDocstring ' + '(' + __name__ + '.Test_TestCase)\n' + 'Tests shortDescription() for a method with a longer ' + 'docstring.')) + + + def testAddTypeEqualityFunc(self): + class SadSnake(object): + """Dummy class for test_addTypeEqualityFunc.""" + s1, s2 = SadSnake(), SadSnake() + self.assertFalse(s1 == s2) + def AllSnakesCreatedEqual(a, b, msg=None): + return type(a) == type(b) == SadSnake + self.addTypeEqualityFunc(SadSnake, AllSnakesCreatedEqual) + self.assertEqual(s1, s2) + # No this doesn't clean up and remove the SadSnake equality func + # from this TestCase instance but since its a local nothing else + # will ever notice that. + + def testAssertIn(self): + animals = {'monkey': 'banana', 'cow': 'grass', 'seal': 'fish'} + + self.assertIn('a', 'abc') + self.assertIn(2, [1, 2, 3]) + self.assertIn('monkey', animals) + + self.assertNotIn('d', 'abc') + self.assertNotIn(0, [1, 2, 3]) + self.assertNotIn('otter', animals) + + self.assertRaises(self.failureException, self.assertIn, 'x', 'abc') + self.assertRaises(self.failureException, self.assertIn, 4, [1, 2, 3]) + self.assertRaises(self.failureException, self.assertIn, 'elephant', + animals) + + self.assertRaises(self.failureException, self.assertNotIn, 'c', 'abc') + self.assertRaises(self.failureException, self.assertNotIn, 1, [1, 2, 3]) + self.assertRaises(self.failureException, self.assertNotIn, 'cow', + animals) + + def testAssertDictContainsSubset(self): + self.assertDictContainsSubset({}, {}) + self.assertDictContainsSubset({}, {'a': 1}) + self.assertDictContainsSubset({'a': 1}, {'a': 1}) + self.assertDictContainsSubset({'a': 1}, {'a': 1, 'b': 2}) + self.assertDictContainsSubset({'a': 1, 'b': 2}, {'a': 1, 'b': 2}) + + self.assertRaises(unittest.TestCase.failureException, + self.assertDictContainsSubset, {'a': 2}, {'a': 1}, + '.*Mismatched values:.*') + + self.assertRaises(unittest.TestCase.failureException, + self.assertDictContainsSubset, {'c': 1}, {'a': 1}, + '.*Missing:.*') + + self.assertRaises(unittest.TestCase.failureException, + self.assertDictContainsSubset, {'a': 1, 'c': 1}, + {'a': 1}, '.*Missing:.*') + + self.assertRaises(unittest.TestCase.failureException, + self.assertDictContainsSubset, {'a': 1, 'c': 1}, + {'a': 1}, '.*Missing:.*Mismatched values:.*') + + def testAssertEqual(self): + equal_pairs = [ + ((), ()), + ({}, {}), + ([], []), + (set(), set()), + (frozenset(), frozenset())] + for a, b in equal_pairs: + # This mess of try excepts is to test the assertEqual behavior + # itself. + try: + self.assertEqual(a, b) + except self.failureException: + self.fail('assertEqual(%r, %r) failed' % (a, b)) + try: + self.assertEqual(a, b, msg='foo') + except self.failureException: + self.fail('assertEqual(%r, %r) with msg= failed' % (a, b)) + try: + self.assertEqual(a, b, 'foo') + except self.failureException: + self.fail('assertEqual(%r, %r) with third parameter failed' % + (a, b)) + + unequal_pairs = [ + ((), []), + ({}, set()), + (set([4,1]), frozenset([4,2])), + (frozenset([4,5]), set([2,3])), + (set([3,4]), set([5,4]))] + for a, b in unequal_pairs: + self.assertRaises(self.failureException, self.assertEqual, a, b) + self.assertRaises(self.failureException, self.assertEqual, a, b, + 'foo') + self.assertRaises(self.failureException, self.assertEqual, a, b, + msg='foo') + + def testEquality(self): + self.assertListEqual([], []) + self.assertTupleEqual((), ()) + self.assertSequenceEqual([], ()) + + a = [0, 'a', []] + b = [] + self.assertRaises(unittest.TestCase.failureException, + self.assertListEqual, a, b) + self.assertRaises(unittest.TestCase.failureException, + self.assertListEqual, tuple(a), tuple(b)) + self.assertRaises(unittest.TestCase.failureException, + self.assertSequenceEqual, a, tuple(b)) + + b.extend(a) + self.assertListEqual(a, b) + self.assertTupleEqual(tuple(a), tuple(b)) + self.assertSequenceEqual(a, tuple(b)) + self.assertSequenceEqual(tuple(a), b) + + self.assertRaises(self.failureException, self.assertListEqual, + a, tuple(b)) + self.assertRaises(self.failureException, self.assertTupleEqual, + tuple(a), b) + self.assertRaises(self.failureException, self.assertListEqual, None, b) + self.assertRaises(self.failureException, self.assertTupleEqual, None, + tuple(b)) + self.assertRaises(self.failureException, self.assertSequenceEqual, + None, tuple(b)) + self.assertRaises(self.failureException, self.assertListEqual, 1, 1) + self.assertRaises(self.failureException, self.assertTupleEqual, 1, 1) + self.assertRaises(self.failureException, self.assertSequenceEqual, + 1, 1) + + self.assertDictEqual({}, {}) + + c = { 'x': 1 } + d = {} + self.assertRaises(unittest.TestCase.failureException, + self.assertDictEqual, c, d) + + d.update(c) + self.assertDictEqual(c, d) + + d['x'] = 0 + self.assertRaises(unittest.TestCase.failureException, + self.assertDictEqual, c, d, 'These are unequal') + + self.assertRaises(self.failureException, self.assertDictEqual, None, d) + self.assertRaises(self.failureException, self.assertDictEqual, [], d) + self.assertRaises(self.failureException, self.assertDictEqual, 1, 1) + + self.assertSameElements([1, 2, 3], [3, 2, 1]) + self.assertSameElements([1, 2] + [3] * 100, [1] * 100 + [2, 3]) + self.assertSameElements(['foo', 'bar', 'baz'], ['bar', 'baz', 'foo']) + self.assertRaises(self.failureException, self.assertSameElements, + [10], [10, 11]) + self.assertRaises(self.failureException, self.assertSameElements, + [10, 11], [10]) + + # Test that sequences of unhashable objects can be tested for sameness: + self.assertSameElements([[1, 2], [3, 4]], [[3, 4], [1, 2]]) + self.assertSameElements([{'a': 1}, {'b': 2}], [{'b': 2}, {'a': 1}]) + self.assertRaises(self.failureException, self.assertSameElements, + [[1]], [[2]]) + + def testAssertSetEqual(self): + set1 = set() + set2 = set() + self.assertSetEqual(set1, set2) + + self.assertRaises(self.failureException, self.assertSetEqual, None, set2) + self.assertRaises(self.failureException, self.assertSetEqual, [], set2) + self.assertRaises(self.failureException, self.assertSetEqual, set1, None) + self.assertRaises(self.failureException, self.assertSetEqual, set1, []) + + set1 = set(['a']) + set2 = set() + self.assertRaises(self.failureException, self.assertSetEqual, set1, set2) + + set1 = set(['a']) + set2 = set(['a']) + self.assertSetEqual(set1, set2) + + set1 = set(['a']) + set2 = set(['a', 'b']) + self.assertRaises(self.failureException, self.assertSetEqual, set1, set2) + + set1 = set(['a']) + set2 = frozenset(['a', 'b']) + self.assertRaises(self.failureException, self.assertSetEqual, set1, set2) + + set1 = set(['a', 'b']) + set2 = frozenset(['a', 'b']) + self.assertSetEqual(set1, set2) + + set1 = set() + set2 = "foo" + self.assertRaises(self.failureException, self.assertSetEqual, set1, set2) + self.assertRaises(self.failureException, self.assertSetEqual, set2, set1) + + # make sure any string formatting is tuple-safe + set1 = set([(0, 1), (2, 3)]) + set2 = set([(4, 5)]) + self.assertRaises(self.failureException, self.assertSetEqual, set1, set2) + + def testInequality(self): + # Try ints + self.assertGreater(2, 1) + self.assertGreaterEqual(2, 1) + self.assertGreaterEqual(1, 1) + self.assertLess(1, 2) + self.assertLessEqual(1, 2) + self.assertLessEqual(1, 1) + self.assertRaises(self.failureException, self.assertGreater, 1, 2) + self.assertRaises(self.failureException, self.assertGreater, 1, 1) + self.assertRaises(self.failureException, self.assertGreaterEqual, 1, 2) + self.assertRaises(self.failureException, self.assertLess, 2, 1) + self.assertRaises(self.failureException, self.assertLess, 1, 1) + self.assertRaises(self.failureException, self.assertLessEqual, 2, 1) + + # Try Floats + self.assertGreater(1.1, 1.0) + self.assertGreaterEqual(1.1, 1.0) + self.assertGreaterEqual(1.0, 1.0) + self.assertLess(1.0, 1.1) + self.assertLessEqual(1.0, 1.1) + self.assertLessEqual(1.0, 1.0) + self.assertRaises(self.failureException, self.assertGreater, 1.0, 1.1) + self.assertRaises(self.failureException, self.assertGreater, 1.0, 1.0) + self.assertRaises(self.failureException, self.assertGreaterEqual, 1.0, 1.1) + self.assertRaises(self.failureException, self.assertLess, 1.1, 1.0) + self.assertRaises(self.failureException, self.assertLess, 1.0, 1.0) + self.assertRaises(self.failureException, self.assertLessEqual, 1.1, 1.0) + + # Try Strings + self.assertGreater('bug', 'ant') + self.assertGreaterEqual('bug', 'ant') + self.assertGreaterEqual('ant', 'ant') + self.assertLess('ant', 'bug') + self.assertLessEqual('ant', 'bug') + self.assertLessEqual('ant', 'ant') + self.assertRaises(self.failureException, self.assertGreater, 'ant', 'bug') + self.assertRaises(self.failureException, self.assertGreater, 'ant', 'ant') + self.assertRaises(self.failureException, self.assertGreaterEqual, 'ant', 'bug') + self.assertRaises(self.failureException, self.assertLess, 'bug', 'ant') + self.assertRaises(self.failureException, self.assertLess, 'ant', 'ant') + self.assertRaises(self.failureException, self.assertLessEqual, 'bug', 'ant') + + # Try Unicode + self.assertGreater(u'bug', u'ant') + self.assertGreaterEqual(u'bug', u'ant') + self.assertGreaterEqual(u'ant', u'ant') + self.assertLess(u'ant', u'bug') + self.assertLessEqual(u'ant', u'bug') + self.assertLessEqual(u'ant', u'ant') + self.assertRaises(self.failureException, self.assertGreater, u'ant', u'bug') + self.assertRaises(self.failureException, self.assertGreater, u'ant', u'ant') + self.assertRaises(self.failureException, self.assertGreaterEqual, u'ant', + u'bug') + self.assertRaises(self.failureException, self.assertLess, u'bug', u'ant') + self.assertRaises(self.failureException, self.assertLess, u'ant', u'ant') + self.assertRaises(self.failureException, self.assertLessEqual, u'bug', u'ant') + + # Try Mixed String/Unicode + self.assertGreater('bug', u'ant') + self.assertGreater(u'bug', 'ant') + self.assertGreaterEqual('bug', u'ant') + self.assertGreaterEqual(u'bug', 'ant') + self.assertGreaterEqual('ant', u'ant') + self.assertGreaterEqual(u'ant', 'ant') + self.assertLess('ant', u'bug') + self.assertLess(u'ant', 'bug') + self.assertLessEqual('ant', u'bug') + self.assertLessEqual(u'ant', 'bug') + self.assertLessEqual('ant', u'ant') + self.assertLessEqual(u'ant', 'ant') + self.assertRaises(self.failureException, self.assertGreater, 'ant', u'bug') + self.assertRaises(self.failureException, self.assertGreater, u'ant', 'bug') + self.assertRaises(self.failureException, self.assertGreater, 'ant', u'ant') + self.assertRaises(self.failureException, self.assertGreater, u'ant', 'ant') + self.assertRaises(self.failureException, self.assertGreaterEqual, 'ant', + u'bug') + self.assertRaises(self.failureException, self.assertGreaterEqual, u'ant', + 'bug') + self.assertRaises(self.failureException, self.assertLess, 'bug', u'ant') + self.assertRaises(self.failureException, self.assertLess, u'bug', 'ant') + self.assertRaises(self.failureException, self.assertLess, 'ant', u'ant') + self.assertRaises(self.failureException, self.assertLess, u'ant', 'ant') + self.assertRaises(self.failureException, self.assertLessEqual, 'bug', u'ant') + self.assertRaises(self.failureException, self.assertLessEqual, u'bug', 'ant') + + def testAssertMultiLineEqual(self): + sample_text = b"""\ +http://www.python.org/doc/2.3/lib/module-unittest.html +test case + A test case is the smallest unit of testing. [...] +""" + revised_sample_text = b"""\ +http://www.python.org/doc/2.4.1/lib/module-unittest.html +test case + A test case is the smallest unit of testing. [...] You may provide your + own implementation that does not subclass from TestCase, of course. +""" + sample_text_error = b""" +- http://www.python.org/doc/2.3/lib/module-unittest.html +? ^ ++ http://www.python.org/doc/2.4.1/lib/module-unittest.html +? ^^^ + test case +- A test case is the smallest unit of testing. [...] ++ A test case is the smallest unit of testing. [...] You may provide your +? +++++++++++++++++++++ ++ own implementation that does not subclass from TestCase, of course. +""" + + for type_changer in (lambda x: x, lambda x: x.decode('utf8')): + try: + self.assertMultiLineEqual(type_changer(sample_text), + type_changer(revised_sample_text)) + except self.failureException, e: + # no fair testing ourself with ourself, use assertEqual.. + self.assertEqual(sample_text_error, str(e).encode('utf8')) + + def testAssertIsNone(self): + self.assertIsNone(None) + self.assertRaises(self.failureException, self.assertIsNone, False) + self.assertIsNotNone('DjZoPloGears on Rails') + self.assertRaises(self.failureException, self.assertIsNotNone, None) + + def testAssertRegexpMatches(self): + self.assertRegexpMatches('asdfabasdf', r'ab+') + self.assertRaises(self.failureException, self.assertRegexpMatches, + 'saaas', r'aaaa') + + def testAssertRaisesRegexp(self): + class ExceptionMock(Exception): + pass + + def Stub(): + raise ExceptionMock('We expect') + + self.assertRaisesRegexp(ExceptionMock, re.compile('expect$'), Stub) + self.assertRaisesRegexp(ExceptionMock, 'expect$', Stub) + self.assertRaisesRegexp(ExceptionMock, u'expect$', Stub) + + def testAssertNotRaisesRegexp(self): + self.assertRaisesRegexp( + self.failureException, '^Exception not raised$', + self.assertRaisesRegexp, Exception, re.compile('x'), + lambda: None) + self.assertRaisesRegexp( + self.failureException, '^Exception not raised$', + self.assertRaisesRegexp, Exception, 'x', + lambda: None) + self.assertRaisesRegexp( + self.failureException, '^Exception not raised$', + self.assertRaisesRegexp, Exception, u'x', + lambda: None) + + def testAssertRaisesRegexpMismatch(self): + def Stub(): + raise Exception('Unexpected') + + self.assertRaisesRegexp( + self.failureException, + r'"\^Expected\$" does not match "Unexpected"', + self.assertRaisesRegexp, Exception, '^Expected$', + Stub) + self.assertRaisesRegexp( + self.failureException, + r'"\^Expected\$" does not match "Unexpected"', + self.assertRaisesRegexp, Exception, u'^Expected$', + Stub) + self.assertRaisesRegexp( + self.failureException, + r'"\^Expected\$" does not match "Unexpected"', + self.assertRaisesRegexp, Exception, + re.compile('^Expected$'), Stub) + class Test_TestSkipping(TestCase): @@ -2386,20 +2756,20 @@ def test_AlmostEqual(self): self.failUnlessAlmostEqual(1.00000001, 1.0) self.failIfAlmostEqual(1.0000001, 1.0) - self.assertRaises(AssertionError, + self.assertRaises(self.failureException, self.failUnlessAlmostEqual, 1.0000001, 1.0) - self.assertRaises(AssertionError, + self.assertRaises(self.failureException, self.failIfAlmostEqual, 1.00000001, 1.0) self.failUnlessAlmostEqual(1.1, 1.0, places=0) - self.assertRaises(AssertionError, + self.assertRaises(self.failureException, self.failUnlessAlmostEqual, 1.1, 1.0, places=1) self.failUnlessAlmostEqual(0, .1+.1j, places=0) self.failIfAlmostEqual(0, .1+.1j, places=1) - self.assertRaises(AssertionError, + self.assertRaises(self.failureException, self.failUnlessAlmostEqual, 0, .1+.1j, places=1) - self.assertRaises(AssertionError, + self.assertRaises(self.failureException, self.failIfAlmostEqual, 0, .1+.1j, places=0) def test_assertRaises(self): @@ -2409,7 +2779,7 @@ self.assertRaises(KeyError, _raise, KeyError("key")) try: self.assertRaises(KeyError, lambda: None) - except AssertionError as e: + except self.failureException as e: self.assert_("KeyError not raised" in e, str(e)) else: self.fail("assertRaises() didn't fail") @@ -2426,7 +2796,7 @@ try: with self.assertRaises(KeyError): pass - except AssertionError as e: + except self.failureException as e: self.assert_("KeyError not raised" in e, str(e)) else: self.fail("assertRaises() didn't fail") Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Tue Mar 31 18:54:10 2009 @@ -14,11 +14,11 @@ class IntegerArithmenticTestCase(unittest.TestCase): def testAdd(self): ## test method names begin 'test*' - self.assertEquals((1 + 2), 3) - self.assertEquals(0 + 1, 1) + self.assertEqual((1 + 2), 3) + self.assertEqual(0 + 1, 1) def testMultiply(self): - self.assertEquals((0 * 10), 0) - self.assertEquals((5 * 8), 40) + self.assertEqual((0 * 10), 0) + self.assertEqual((5 * 8), 40) if __name__ == '__main__': unittest.main() @@ -45,12 +45,15 @@ SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ''' -import time +import difflib +import functools +import os +import pprint +import re import sys +import time import traceback -import os import types -import functools ############################################################################## # Exported classes and functions @@ -251,11 +254,13 @@ len(self.failures)) -class AssertRaisesContext(object): +class _AssertRaisesContext(object): + """A context manager used to implement TestCase.assertRaises* methods.""" - def __init__(self, expected, test_case): + def __init__(self, expected, test_case, expected_regexp=None): self.expected = expected self.failureException = test_case.failureException + self.expected_regex = expected_regexp def __enter__(self): pass @@ -268,10 +273,20 @@ exc_name = str(self.expected) raise self.failureException( "{0} not raised".format(exc_name)) - if issubclass(exc_type, self.expected): + if not issubclass(exc_type, self.expected): + # let unexpexted exceptions pass through + return False + if self.expected_regex is None: return True - # Let unexpected exceptions skip through - return False + + expected_regexp = self.expected_regex + if isinstance(expected_regexp, basestring): + expected_regexp = re.compile(expected_regexp) + if not expected_regexp.search(str(exc_value)): + raise self.failureException('"%s" does not match "%s"' % + (expected_regexp.pattern, str(exc_value))) + return True + class TestCase(object): @@ -315,6 +330,31 @@ (self.__class__, methodName)) self._testMethodDoc = testMethod.__doc__ + # Map types to custom assertEqual functions that will compare + # instances of said type in more detail to generate a more useful + # error message. + self.__type_equality_funcs = {} + self.addTypeEqualityFunc(dict, self.assertDictEqual) + self.addTypeEqualityFunc(list, self.assertListEqual) + self.addTypeEqualityFunc(tuple, self.assertTupleEqual) + self.addTypeEqualityFunc(set, self.assertSetEqual) + self.addTypeEqualityFunc(frozenset, self.assertSetEqual) + + def addTypeEqualityFunc(self, typeobj, function): + """Add a type specific assertEqual style function to compare a type. + + This method is for use by TestCase subclasses that need to register + their own type equality functions to provide nicer error messages. + + Args: + typeobj: The data type to call this function on when both values + are of the same type in assertEqual(). + function: The callable taking two arguments and an optional + msg= argument that raises self.failureException with a + useful error message when the two arguments are not equal. + """ + self.__type_equality_funcs[typeobj] = function + def setUp(self): "Hook method for setting up the test fixture before exercising it." pass @@ -330,14 +370,22 @@ return TestResult() def shortDescription(self): - """Returns a one-line description of the test, or None if no - description has been provided. + """Returns both the test method name and first line of its docstring. - The default implementation of this method returns the first line of - the specified test method's docstring. + If no docstring is given, only returns the method name. + + This method overrides unittest.TestCase.shortDescription(), which + only returns the first line of the docstring, obscuring the name + of the test upon failure. """ - doc = self._testMethodDoc - return doc and doc.split("\n")[0].strip() or None + desc = str(self) + doc_first_line = None + + if self._testMethodDoc: + doc_first_line = self._testMethodDoc.split("\n")[0].strip() + if doc_first_line: + desc = '\n'.join((desc, doc_first_line)) + return desc def id(self): return "%s.%s" % (_strclass(self.__class__), self._testMethodName) @@ -443,18 +491,45 @@ with self.failUnlessRaises(some_error_class): do_something() """ - context = AssertRaisesContext(excClass, self) + context = _AssertRaisesContext(excClass, self) if callableObj is None: return context with context: callableObj(*args, **kwargs) + def _getAssertEqualityFunc(self, first, second): + """Get a detailed comparison function for the types of the two args. + + Returns: A callable accepting (first, second, msg=None) that will + raise a failure exception if first != second with a useful human + readable error message for those types. + """ + # + # NOTE(gregory.p.smith): I considered isinstance(first, type(second)) + # and vice versa. I opted for the conservative approach in case + # subclasses are not intended to be compared in detail to their super + # class instances using a type equality func. This means testing + # subtypes won't automagically use the detailed comparison. Callers + # should use their type specific assertSpamEqual method to compare + # subclasses if the detailed comparison is desired and appropriate. + # See the discussion in http://bugs.python.org/issue2578. + # + if type(first) is type(second): + return self.__type_equality_funcs.get(type(first), + self._baseAssertEqual) + return self._baseAssertEqual + + def _baseAssertEqual(self, first, second, msg=None): + """The default assertEqual implementation, not type specific.""" + if not first == second: + raise self.failureException(msg or '%r != %r' % (first, second)) + def failUnlessEqual(self, first, second, msg=None): """Fail if the two objects are unequal as determined by the '==' operator. """ - if not first == second: - raise self.failureException(msg or '%r != %r' % (first, second)) + assertion_func = self._getAssertEqualityFunc(first, second) + assertion_func(first, second, msg=msg) def failIfEqual(self, first, second, msg=None): """Fail if the two objects are equal as determined by the '==' @@ -504,6 +579,356 @@ assertFalse = failIf + def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None): + """An equality assertion for ordered sequences (like lists and tuples). + + For the purposes of this function, a valid orderd sequence type is one + which can be indexed, has a length, and has an equality operator. + + Args: + seq1: The first sequence to compare. + seq2: The second sequence to compare. + seq_type: The expected datatype of the sequences, or None if no + datatype should be enforced. + msg: Optional message to use on failure instead of a list of + differences. + """ + if seq_type != None: + seq_type_name = seq_type.__name__ + if not isinstance(seq1, seq_type): + raise self.failureException('First sequence is not a %s: %r' + % (seq_type_name, seq1)) + if not isinstance(seq2, seq_type): + raise self.failureException('Second sequence is not a %s: %r' + % (seq_type_name, seq2)) + else: + seq_type_name = "sequence" + + differing = None + try: + len1 = len(seq1) + except (TypeError, NotImplementedError): + differing = 'First %s has no length. Non-sequence?' % ( + seq_type_name) + + if differing is None: + try: + len2 = len(seq2) + except (TypeError, NotImplementedError): + differing = 'Second %s has no length. Non-sequence?' % ( + seq_type_name) + + if differing is None: + if seq1 == seq2: + return + + for i in xrange(min(len1, len2)): + try: + item1 = seq1[i] + except (TypeError, IndexError, NotImplementedError): + differing = ('Unable to index element %d of first %s\n' % + (i, seq_type_name)) + break + + try: + item2 = seq2[i] + except (TypeError, IndexError, NotImplementedError): + differing = ('Unable to index element %d of second %s\n' % + (i, seq_type_name)) + break + + if item1 != item2: + differing = ('First differing element %d:\n%s\n%s\n' % + (i, item1, item2)) + break + else: + if (len1 == len2 and seq_type is None and + type(seq1) != type(seq2)): + # The sequences are the same, but have differing types. + return + # A catch-all message for handling arbitrary user-defined + # sequences. + differing = '%ss differ:\n' % seq_type_name.capitalize() + if len1 > len2: + differing = ('First %s contains %d additional ' + 'elements.\n' % (seq_type_name, len1 - len2)) + try: + differing += ('First extra element %d:\n%s\n' % + (len2, seq1[len2])) + except (TypeError, IndexError, NotImplementedError): + differing += ('Unable to index element %d ' + 'of first %s\n' % (len2, seq_type_name)) + elif len1 < len2: + differing = ('Second %s contains %d additional ' + 'elements.\n' % (seq_type_name, len2 - len1)) + try: + differing += ('First extra element %d:\n%s\n' % + (len1, seq2[len1])) + except (TypeError, IndexError, NotImplementedError): + differing += ('Unable to index element %d ' + 'of second %s\n' % (len1, seq_type_name)) + if not msg: + msg = '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(), + pprint.pformat(seq2).splitlines())) + self.fail(differing + msg) + + def assertListEqual(self, list1, list2, msg=None): + """A list-specific equality assertion. + + Args: + list1: The first list to compare. + list2: The second list to compare. + msg: Optional message to use on failure instead of a list of + differences. + + """ + self.assertSequenceEqual(list1, list2, msg, seq_type=list) + + def assertTupleEqual(self, tuple1, tuple2, msg=None): + """A tuple-specific equality assertion. + + Args: + tuple1: The first tuple to compare. + tuple2: The second tuple to compare. + msg: Optional message to use on failure instead of a list of + differences. + """ + self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple) + + def assertSetEqual(self, set1, set2, msg=None): + """A set-specific equality assertion. + + Args: + set1: The first set to compare. + set2: The second set to compare. + msg: Optional message to use on failure instead of a list of + differences. + + For more general containership equality, assertSameElements will work + with things other than sets. This uses ducktyping to support + different types of sets, and is optimized for sets specifically + (parameters must support a difference method). + """ + try: + difference1 = set1.difference(set2) + except TypeError, e: + self.fail('invalid type when attempting set difference: %s' % e) + except AttributeError, e: + self.fail('first argument does not support set difference: %s' % e) + + try: + difference2 = set2.difference(set1) + except TypeError, e: + self.fail('invalid type when attempting set difference: %s' % e) + except AttributeError, e: + self.fail('second argument does not support set difference: %s' % e) + + if not (difference1 or difference2): + return + + if msg is not None: + self.fail(msg) + + lines = [] + if difference1: + lines.append('Items in the first set but not the second:') + for item in difference1: + lines.append(repr(item)) + if difference2: + lines.append('Items in the second set but not the first:') + for item in difference2: + lines.append(repr(item)) + self.fail('\n'.join(lines)) + + def assertIn(self, a, b, msg=None): + """Just like self.assert_(a in b), but with a nicer default message.""" + if msg is None: + msg = '"%s" not found in "%s"' % (a, b) + self.assert_(a in b, msg) + + def assertNotIn(self, a, b, msg=None): + """Just like self.assert_(a not in b), but with a nicer default message.""" + if msg is None: + msg = '"%s" unexpectedly found in "%s"' % (a, b) + self.assert_(a not in b, msg) + + def assertDictEqual(self, d1, d2, msg=None): + self.assert_(isinstance(d1, dict), 'First argument is not a dictionary') + self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary') + + if d1 != d2: + self.fail(msg or ('\n' + '\n'.join(difflib.ndiff( + pprint.pformat(d1).splitlines(), + pprint.pformat(d2).splitlines())))) + + def assertDictContainsSubset(self, expected, actual, msg=None): + """Checks whether actual is a superset of expected.""" + missing = [] + mismatched = [] + for key, value in expected.iteritems(): + if key not in actual: + missing.append(key) + elif value != actual[key]: + mismatched.append('%s, expected: %s, actual: %s' % (key, value, + actual[key])) + + if not (missing or mismatched): + return + + missing_msg = mismatched_msg = '' + if missing: + missing_msg = 'Missing: %s' % ','.join(missing) + if mismatched: + mismatched_msg = 'Mismatched values: %s' % ','.join(mismatched) + + if msg: + msg = '%s: %s; %s' % (msg, missing_msg, mismatched_msg) + else: + msg = '%s; %s' % (missing_msg, mismatched_msg) + self.fail(msg) + + def assertSameElements(self, expected_seq, actual_seq, msg=None): + """An unordered sequence specific comparison. + + Raises with an error message listing which elements of expected_seq + are missing from actual_seq and vice versa if any. + """ + try: + expected = set(expected_seq) + actual = set(actual_seq) + missing = list(expected.difference(actual)) + unexpected = list(actual.difference(expected)) + missing.sort() + unexpected.sort() + except TypeError: + # Fall back to slower list-compare if any of the objects are + # not hashable. + expected = list(expected_seq) + actual = list(actual_seq) + expected.sort() + actual.sort() + missing, unexpected = _SortedListDifference(expected, actual) + errors = [] + if missing: + errors.append('Expected, but missing:\n %r\n' % missing) + if unexpected: + errors.append('Unexpected, but present:\n %r\n' % unexpected) + if errors: + self.fail(msg or ''.join(errors)) + + def assertMultiLineEqual(self, first, second, msg=None): + """Assert that two multi-line strings are equal.""" + self.assert_(isinstance(first, types.StringTypes), ( + 'First argument is not a string')) + self.assert_(isinstance(second, types.StringTypes), ( + 'Second argument is not a string')) + + if first != second: + raise self.failureException( + msg or '\n' + ''.join(difflib.ndiff(first.splitlines(True), + second.splitlines(True)))) + + def assertLess(self, a, b, msg=None): + """Just like self.assert_(a < b), but with a nicer default message.""" + if msg is None: + msg = '"%r" unexpectedly not less than "%r"' % (a, b) + self.assert_(a < b, msg) + + def assertLessEqual(self, a, b, msg=None): + """Just like self.assert_(a <= b), but with a nicer default message.""" + if msg is None: + msg = '"%r" unexpectedly not less than or equal to "%r"' % (a, b) + self.assert_(a <= b, msg) + + def assertGreater(self, a, b, msg=None): + """Just like self.assert_(a > b), but with a nicer default message.""" + if msg is None: + msg = '"%r" unexpectedly not greater than "%r"' % (a, b) + self.assert_(a > b, msg) + + def assertGreaterEqual(self, a, b, msg=None): + """Just like self.assert_(a >= b), but with a nicer default message.""" + if msg is None: + msg = '"%r" unexpectedly not greater than or equal to "%r"' % (a, b) + self.assert_(a >= b, msg) + + def assertIsNone(self, obj, msg=None): + """Same as self.assert_(obj is None), with a nicer default message.""" + if msg is None: + msg = '"%s" unexpectedly not None' % obj + self.assert_(obj is None, msg) + + def assertIsNotNone(self, obj, msg='unexpectedly None'): + """Included for symmetry with assertIsNone.""" + self.assert_(obj is not None, msg) + + def assertRaisesRegexp(self, expected_exception, expected_regexp, + callable_obj=None, *args, **kwargs): + """Asserts that the message in a raised exception matches a regexp. + + Args: + expected_exception: Exception class expected to be raised. + expected_regexp: Regexp (re pattern object or string) expected + to be found in error message. + callable_obj: Function to be called. + args: Extra args. + kwargs: Extra kwargs. + """ + context = _AssertRaisesContext(expected_exception, self, expected_regexp) + if callable_obj is None: + return context + with context: + callable_obj(*args, **kwargs) + + def assertRegexpMatches(self, text, expected_regex, msg=None): + if isinstance(expected_regex, basestring): + expected_regex = re.compile(expected_regex) + if not expected_regex.search(text): + msg = msg or "Regexp didn't match" + msg = '%s: %r not found in %r' % (msg, expected_regex.pattern, text) + raise self.failureException(msg) + + +def _SortedListDifference(expected, actual): + """Finds elements in only one or the other of two, sorted input lists. + + Returns a two-element tuple of lists. The first list contains those + elements in the "expected" list but not in the "actual" list, and the + second contains those elements in the "actual" list but not in the + "expected" list. Duplicate elements in either input list are ignored. + """ + i = j = 0 + missing = [] + unexpected = [] + while True: + try: + e = expected[i] + a = actual[j] + if e < a: + missing.append(e) + i += 1 + while expected[i] == e: + i += 1 + elif e > a: + unexpected.append(a) + j += 1 + while actual[j] == a: + j += 1 + else: + i += 1 + try: + while expected[i] == e: + i += 1 + finally: + j += 1 + while actual[j] == a: + j += 1 + except IndexError: + missing.extend(expected[i:]) + unexpected.extend(actual[j:]) + break + return missing, unexpected + class TestSuite(object): """A test suite is a composite test consisting of a number of TestCases. Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 31 18:54:10 2009 @@ -217,6 +217,15 @@ - Issue #1034053: unittest now supports skipping tests and expected failures. +- The unittest.TestCase.assertRaises() method now returns a context manager when + not given a callable so that code to be tested can be written inline using + a with statement. + +- The unittest.TestCase.assertEqual() now displays the differences in lists, + tuples, dicts and sets on failure. Many new handy type and comparison + specific assert* methods have been added that fail with error messages + actually useful for debugging. Contributed in part by Google. [Issue #2578] + - Issue #5068: Fixed the tarfile._BZ2Proxy.read() method that would loop forever on incomplete input. That caused tarfile.open() to hang when used with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or From python-checkins at python.org Tue Mar 31 18:54:38 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 18:54:38 +0200 (CEST) Subject: [Python-checkins] r70838 - python/trunk/Doc/reference/simple_stmts.rst Message-ID: <20090331165438.7B7161E406D@bag.python.org> Author: georg.brandl Date: Tue Mar 31 18:54:38 2009 New Revision: 70838 Log: #992207: document that the parser only accepts \\n newlines. Modified: python/trunk/Doc/reference/simple_stmts.rst Modified: python/trunk/Doc/reference/simple_stmts.rst ============================================================================== --- python/trunk/Doc/reference/simple_stmts.rst (original) +++ python/trunk/Doc/reference/simple_stmts.rst Tue Mar 31 18:54:38 2009 @@ -966,7 +966,7 @@ This statement supports dynamic execution of Python code. The first expression should evaluate to either a string, an open file object, or a code object. If it is a string, the string is parsed as a suite of Python statements which is -then executed (unless a syntax error occurs). If it is an open file, the file +then executed (unless a syntax error occurs). [#]_ If it is an open file, the file is parsed until EOF and executed. If it is a code object, it is simply executed. In all cases, the code that's executed is expected to be valid as file input (see section :ref:`file-input`). Be aware that the @@ -1004,3 +1004,8 @@ which may be useful to pass around for use by :keyword:`exec`. +.. rubric:: Footnotes + +.. [#] Note that the parser only accepts the Unix-style end of line convention. + If you are reading the code from a file, make sure to use universal + newline mode to convert Windows or Mac-style newlines. From python-checkins at python.org Tue Mar 31 18:55:13 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 18:55:13 +0200 (CEST) Subject: [Python-checkins] r70839 - python/branches/py3k Message-ID: <20090331165513.407F41E406D@bag.python.org> Author: georg.brandl Date: Tue Mar 31 18:55:13 2009 New Revision: 70839 Log: Blocked revisions 70838 via svnmerge ........ r70838 | georg.brandl | 2009-03-31 11:54:38 -0500 (Di, 31 M?r 2009) | 1 line #992207: document that the parser only accepts \\n newlines. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Tue Mar 31 18:57:13 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 18:57:13 +0200 (CEST) Subject: [Python-checkins] r70840 - python/branches/py3k/Doc/library/functions.rst Message-ID: <20090331165713.40D461E403C@bag.python.org> Author: georg.brandl Date: Tue Mar 31 18:57:13 2009 New Revision: 70840 Log: Forward-port of #992207 fix: document that the parser only accepts \\n newlines. (And remove a leftover footnote.) Modified: python/branches/py3k/Doc/library/functions.rst Modified: python/branches/py3k/Doc/library/functions.rst ============================================================================== --- python/branches/py3k/Doc/library/functions.rst (original) +++ python/branches/py3k/Doc/library/functions.rst Tue Mar 31 18:57:13 2009 @@ -334,12 +334,12 @@ This function supports dynamic execution of Python code. *object* must be either a string or a code object. If it is a string, the string is parsed as a suite of Python statements which is then executed (unless a syntax error - occurs). If it is a code object, it is simply executed. In all cases, the - code that's executed is expected to be valid as file input (see the section - "File input" in the Reference Manual). Be aware that the :keyword:`return` - and :keyword:`yield` statements may not be used outside of function - definitions even within the context of code passed to the :func:`exec` - function. The return value is ``None``. + occurs). [#]_ If it is a code object, it is simply executed. In all cases, + the code that's executed is expected to be valid as file input (see the + section "File input" in the Reference Manual). Be aware that the + :keyword:`return` and :keyword:`yield` statements may not be used outside of + function definitions even within the context of code passed to the + :func:`exec` function. The return value is ``None``. In all cases, if the optional parts are omitted, the code is executed in the current scope. If only *globals* is provided, it must be a dictionary, which @@ -1275,13 +1275,10 @@ .. rubric:: Footnotes -.. [#] Specifying a buffer size currently has no effect on systems that don't have - :cfunc:`setvbuf`. The interface to specify the buffer size is not done using a - method that calls :cfunc:`setvbuf`, because that may dump core when called after - any I/O has been performed, and there's no reliable way to determine whether - this is the case. +.. [#] Note that the parser only accepts the Unix-style end of line convention. + If you are reading the code from a file, make sure to use newline conversion + mode to convert Windows or Mac-style newlines. .. [#] In the current implementation, local variable bindings cannot normally be affected this way, but variables retrieved from other scopes (such as modules) can be. This may change. - From python-checkins at python.org Tue Mar 31 19:06:58 2009 From: python-checkins at python.org (eric.smith) Date: Tue, 31 Mar 2009 19:06:58 +0200 (CEST) Subject: [Python-checkins] r70841 - in python/branches/py3k-short-float-repr: Include/pystrtod.h Lib/test/test_format.py Lib/test/test_types.py Modules/_pickle.c Objects/complexobject.c Objects/floatobject.c Objects/unicodeobject.c Python/marshal.c Python/pystrtod.c Message-ID: <20090331170658.E92201E40DF@bag.python.org> Author: eric.smith Date: Tue Mar 31 19:06:57 2009 New Revision: 70841 Log: Checkpoint so Mark and I can continue working. Changes: Hooked up unicodeobject.c so that %-formatting works. Added trailing zeros. Added as single 'flags' param to PyOS_decimal_to_string instead of individual flag parameters. Added upper and lower case format codes g/G e/E f/F. This addresses issue 3382, also. Many tests still fail, but I'll work on them next. Modified: python/branches/py3k-short-float-repr/Include/pystrtod.h python/branches/py3k-short-float-repr/Lib/test/test_format.py python/branches/py3k-short-float-repr/Lib/test/test_types.py python/branches/py3k-short-float-repr/Modules/_pickle.c python/branches/py3k-short-float-repr/Objects/complexobject.c python/branches/py3k-short-float-repr/Objects/floatobject.c python/branches/py3k-short-float-repr/Objects/unicodeobject.c python/branches/py3k-short-float-repr/Python/marshal.c python/branches/py3k-short-float-repr/Python/pystrtod.c Modified: python/branches/py3k-short-float-repr/Include/pystrtod.h ============================================================================== --- python/branches/py3k-short-float-repr/Include/pystrtod.h (original) +++ python/branches/py3k-short-float-repr/Include/pystrtod.h Tue Mar 31 19:06:57 2009 @@ -13,10 +13,13 @@ int mode, char format_code, int precision, - int sign, - int add_dot_0_if_integer); + int flags); +#define Py_DTSF_SIGN 0x01 /* always add the sign */ +#define Py_DTSF_ADD_DOT_0 0x02 /* if the result is an integer add ".0" */ +#define Py_DTSF_ALT 0x04 /* "alternate" formatting. it's format_code + specific */ #ifdef __cplusplus } Modified: python/branches/py3k-short-float-repr/Lib/test/test_format.py ============================================================================== --- python/branches/py3k-short-float-repr/Lib/test/test_format.py (original) +++ python/branches/py3k-short-float-repr/Lib/test/test_format.py Tue Mar 31 19:06:57 2009 @@ -220,6 +220,11 @@ testformat("%a", "\u0378", "'\\u0378'") # non printable testformat("%r", "\u0374", "'\u0374'") # printable testformat("%a", "\u0374", "'\\u0374'") # printable + + # alternate float formatting + testformat('%g', 1.1, '1.1') + testformat('%#g', 1.1, '1.10000') + # Test exception for unknown format characters if verbose: print('Testing exceptions') Modified: python/branches/py3k-short-float-repr/Lib/test/test_types.py ============================================================================== --- python/branches/py3k-short-float-repr/Lib/test/test_types.py (original) +++ python/branches/py3k-short-float-repr/Lib/test/test_types.py Tue Mar 31 19:06:57 2009 @@ -113,6 +113,9 @@ self.assertEqual(1.5e-101.__format__('e'), '1.500000e-101') self.assertEqual('%e' % 1.5e-101, '1.500000e-101') + self.assertEqual('%g' % 1.0, '1') + self.assertEqual('%#g' % 1.0, '1.00000') + def test_normal_integers(self): # Ensure the first 256 integers are shared a = 256 Modified: python/branches/py3k-short-float-repr/Modules/_pickle.c ============================================================================== --- python/branches/py3k-short-float-repr/Modules/_pickle.c (original) +++ python/branches/py3k-short-float-repr/Modules/_pickle.c Tue Mar 31 19:06:57 2009 @@ -1016,7 +1016,7 @@ return -1; if (pickler_write(self, pdata, 9) < 0) return -1; - } + } else { int result = -1; char *buf = NULL; @@ -1025,7 +1025,7 @@ if (pickler_write(self, &op, 1) < 0) goto done; - buf = PyOS_double_to_string(x, 2, 'g', 17, 0, 0); + buf = PyOS_double_to_string(x, 2, 'g', 17, 0); if (!buf) { PyErr_NoMemory(); goto done; Modified: python/branches/py3k-short-float-repr/Objects/complexobject.c ============================================================================== --- python/branches/py3k-short-float-repr/Objects/complexobject.c (original) +++ python/branches/py3k-short-float-repr/Objects/complexobject.c Tue Mar 31 19:06:57 2009 @@ -368,8 +368,7 @@ im = "-inf*"; } else { - pim = PyOS_double_to_string(v->cval.imag, mode, 'g', precision, - 0, 0); + pim = PyOS_double_to_string(v->cval.imag, mode, 'g', precision, 0); if (!pim) { PyErr_NoMemory(); goto done; @@ -388,8 +387,7 @@ re = "-inf"; } else { - pre = PyOS_double_to_string(v->cval.real, mode, 'g', precision, - 0, 0); + pre = PyOS_double_to_string(v->cval.real, mode, 'g', precision, 0); if (!pre) { PyErr_NoMemory(); goto done; @@ -408,7 +406,7 @@ } else { pim = PyOS_double_to_string(v->cval.imag, mode, 'g', precision, - 1, 0); + Py_DTSF_SIGN); if (!pim) { PyErr_NoMemory(); goto done; Modified: python/branches/py3k-short-float-repr/Objects/floatobject.c ============================================================================== --- python/branches/py3k-short-float-repr/Objects/floatobject.c (original) +++ python/branches/py3k-short-float-repr/Objects/floatobject.c Tue Mar 31 19:06:57 2009 @@ -369,7 +369,7 @@ { PyObject *result; char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v), - mode, 'g', precision, 0, 1); + mode, 'g', precision, Py_DTSF_ADD_DOT_0); if (!buf) return PyErr_NoMemory(); result = PyUnicode_FromString(buf); @@ -1917,7 +1917,7 @@ Py_REFCNT(p) != 0) { char *buf = PyOS_double_to_string( PyFloat_AS_DOUBLE(p), 0, 'g', - 0, 0, 1); + 0, Py_DTSF_ADD_DOT_0); if (buf) { /* XXX(twouters) cast refcount to long Modified: python/branches/py3k-short-float-repr/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k-short-float-repr/Objects/unicodeobject.c (original) +++ python/branches/py3k-short-float-repr/Objects/unicodeobject.c Tue Mar 31 19:06:57 2009 @@ -8792,43 +8792,14 @@ return NULL; } -static Py_ssize_t -strtounicode(Py_UNICODE *buffer, const char *charbuffer) +static void +strtounicode(Py_UNICODE *buffer, const char *charbuffer, Py_ssize_t len) { register Py_ssize_t i; - Py_ssize_t len = strlen(charbuffer); for (i = len - 1; i >= 0; i--) buffer[i] = (Py_UNICODE) charbuffer[i]; - - return len; -} - -static int -doubletounicode(Py_UNICODE *buffer, size_t len, const char *format, double x) -{ - Py_ssize_t result; - - PyOS_ascii_formatd((char *)buffer, len, format, x); - result = strtounicode(buffer, (char *)buffer); - return Py_SAFE_DOWNCAST(result, Py_ssize_t, int); } -#if 0 -static int -longtounicode(Py_UNICODE *buffer, size_t len, const char *format, long x) -{ - Py_ssize_t result; - - PyOS_snprintf((char *)buffer, len, format, x); - result = strtounicode(buffer, (char *)buffer); - return Py_SAFE_DOWNCAST(result, Py_ssize_t, int); -} -#endif - -/* XXX To save some code duplication, formatfloat/long/int could have been - shared with stringobject.c, converting from 8-bit to Unicode after the - formatting is done. */ - static int formatfloat(Py_UNICODE *buf, size_t buflen, @@ -8837,54 +8808,56 @@ int type, PyObject *v) { - /* fmt = '%#.' + `prec` + `type` - worst case length = 3 + 10 (len of INT_MAX) + 1 = 14 (use 20)*/ - char fmt[20]; + /* eric.smith: To minimize disturbances in PyUnicode_Format (the + only caller of this routine), I'm going to keep the existing + API to this function. That means that we'll allocate memory and + then copy back into the supplied buffer. But that's better than + all of the changes that would be required in PyUnicode_Format + because it does lots of memory management tricks. */ + + char* p = NULL; + int result = -1; double x; + Py_ssize_t len; x = PyFloat_AsDouble(v); if (x == -1.0 && PyErr_Occurred()) - return -1; + goto done; if (prec < 0) prec = 6; + /* make sure that the decimal representation of precision really does need at most 10 digits: platforms with sizeof(int) == 8 exist! */ if (prec > 0x7fffffffL) { PyErr_SetString(PyExc_OverflowError, "outrageously large precision " "for formatted float"); - return -1; + goto done; } - if (type == 'f' && fabs(x) >= 1e50) - type = 'g'; - /* Worst case length calc to ensure no buffer overrun: - - 'g' formats: - fmt = %#.g - buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp - for any double rep.) - len = 1 + prec + 1 + 2 + 5 = 9 + prec - - 'f' formats: - buf = '-' + [0-9]*x + '.' + [0-9]*prec (with x < 50) - len = 1 + 50 + 1 + prec = 52 + prec - - If prec=0 the effective precision is 1 (the leading digit is - always given), therefore increase the length by one. - - */ if (((type == 'g' || type == 'G') && buflen <= (size_t)10 + (size_t)prec) || - (type == 'f' && buflen <= (size_t)53 + (size_t)prec)) { + ((type == 'f' || type == 'F') && + buflen <= (size_t)53 + (size_t)prec)) { PyErr_SetString(PyExc_OverflowError, "formatted float is too long (precision too large?)"); - return -1; + goto done; } - PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%d%c", - (flags&F_ALT) ? "#" : "", - prec, type); - return doubletounicode(buf, buflen, fmt, x); + + p = PyOS_double_to_string(x, 2, type, prec, + (flags & F_ALT) ? Py_DTSF_ALT : 0); + len = strlen(p); + if (len+1 >= buflen) { + /* Caller supplied buffer is not large enough. */ + PyErr_NoMemory(); + goto done; + } + strtounicode(buf, p, len); + result = Py_SAFE_DOWNCAST(len, Py_ssize_t, int); + +done: + PyMem_Free(p); + return result; } static PyObject* @@ -8903,84 +8876,6 @@ return result; } -#if 0 -static int -formatint(Py_UNICODE *buf, - size_t buflen, - int flags, - int prec, - int type, - PyObject *v) -{ - /* fmt = '%#.' + `prec` + 'l' + `type` - * worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine) - * + 1 + 1 - * = 24 - */ - char fmt[64]; /* plenty big enough! */ - char *sign; - long x; - - x = PyLong_AsLong(v); - if (x == -1 && PyErr_Occurred()) - return -1; - if (x < 0 && type == 'u') { - type = 'd'; - } - if (x < 0 && (type == 'x' || type == 'X' || type == 'o')) - sign = "-"; - else - sign = ""; - if (prec < 0) - prec = 1; - - /* buf = '+'/'-'/'' + '0'/'0x'/'' + '[0-9]'*max(prec, len(x in octal)) - * worst case buf = '-0x' + [0-9]*prec, where prec >= 11 - */ - if (buflen <= 14 || buflen <= (size_t)3 + (size_t)prec) { - PyErr_SetString(PyExc_OverflowError, - "formatted integer is too long (precision too large?)"); - return -1; - } - - if ((flags & F_ALT) && - (type == 'x' || type == 'X' || type == 'o')) { - /* When converting under %#o, %#x or %#X, there are a number - * of issues that cause pain: - * - for %#o, we want a different base marker than C - * - when 0 is being converted, the C standard leaves off - * the '0x' or '0X', which is inconsistent with other - * %#x/%#X conversions and inconsistent with Python's - * hex() function - * - there are platforms that violate the standard and - * convert 0 with the '0x' or '0X' - * (Metrowerks, Compaq Tru64) - * - there are platforms that give '0x' when converting - * under %#X, but convert 0 in accordance with the - * standard (OS/2 EMX) - * - * We can achieve the desired consistency by inserting our - * own '0x' or '0X' prefix, and substituting %x/%X in place - * of %#x/%#X. - * - * Note that this is the same approach as used in - * formatint() in stringobject.c - */ - PyOS_snprintf(fmt, sizeof(fmt), "%s0%c%%.%dl%c", - sign, type, prec, type); - } - else { - PyOS_snprintf(fmt, sizeof(fmt), "%s%%%s.%dl%c", - sign, (flags&F_ALT) ? "#" : "", - prec, type); - } - if (sign[0]) - return longtounicode(buf, buflen, fmt, -x); - else - return longtounicode(buf, buflen, fmt, x); -} -#endif - static int formatchar(Py_UNICODE *buf, size_t buflen, @@ -9359,8 +9254,6 @@ case 'F': case 'g': case 'G': - if (c == 'F') - c = 'f'; pbuf = formatbuf; len = formatfloat(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE), flags, prec, c, v); Modified: python/branches/py3k-short-float-repr/Python/marshal.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/marshal.c (original) +++ python/branches/py3k-short-float-repr/Python/marshal.c Tue Mar 31 19:06:57 2009 @@ -237,7 +237,7 @@ } else { char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v), - 0, 'g', 0, 0, 1); + 0, 'g', 0, Py_DTSF_ADD_DOT_0); if (!buf) return; n = strlen(buf); @@ -269,7 +269,7 @@ char *buf; w_byte(TYPE_COMPLEX, p); buf = PyOS_double_to_string(PyComplex_RealAsDouble(v), - 0, 'g', 0, 0, 1); + 0, 'g', 0, Py_DTSF_ADD_DOT_0); if (!buf) return; n = strlen(buf); @@ -277,7 +277,7 @@ w_string(buf, (int)n, p); PyMem_Free(buf); buf = PyOS_double_to_string(PyComplex_ImagAsDouble(v), - 0, 'g', 0, 0, 1); + 0, 'g', 0, Py_DTSF_ADD_DOT_0); if (!buf) return; n = strlen(buf); Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/pystrtod.c (original) +++ python/branches/py3k-short-float-repr/Python/pystrtod.c Tue Mar 31 19:06:57 2009 @@ -500,16 +500,36 @@ } +/* I'm using a lookup table here so that I don't have to invent a non-locale + specific way to convert to uppercase */ +#define OFS_INF 0 +#define OFS_NAN 1 +#define OFS_E 2 + +/* The lengths of these are known to the code below, so don't change them */ +static char *lc_float_strings[] = { + "inf", + "nan", + "e", +}; +static char *uc_float_strings[] = { + "INF", + "NAN", + "E", +}; + + /* convert a Python float to a minimal string that evaluates back to that float. The output is minimal in the sense of having the least possible number of significant digits. */ static void -format_float_short(char *buf, size_t buflen, double d, int mode, int precision, int always_add_sign, int add_dot_0_if_integer) +format_float_short(char *buf, size_t buflen, double d, char format_code, int mode, int precision, int always_add_sign, int add_dot_0_if_integer, char **float_strings) { char *digits, *digits_end; int decpt, sign, exp_len; - size_t digits_len, i; + Py_ssize_t digits_len, i; + int use_exp; /* _Py_dg_dtoa returns a digit string (no decimal point or exponent) */ @@ -528,11 +548,11 @@ else if (always_add_sign) { *buf++ = '+'; } - strncpy(buf, "inf", 3); + strncpy(buf, float_strings[OFS_INF], 3); buf += 3; } else if (digits[0] == 'n' || digits[0] == 'N') { - strncpy(buf, "nan", 3); + strncpy(buf, float_strings[OFS_NAN], 3); buf += 3; } else { @@ -543,19 +563,55 @@ (int)digits_len, digits); assert(0); } + *buf = '\0'; + return; } - else if (-4 < decpt && decpt <= 17) { - if (sign == 1) { - *buf++ = '-'; - } else if (always_add_sign) { - *buf++ = '+'; - } - /* use fixed-point notation if 1e-4 <= value < 1e17 */ + + /* this replaces the various tests in other places like: + if (type == 'f' && fabs(x) >= 1e50) + type = 'g'; + over time, those tests should be deleted + */ + if (decpt > 50 && format_code == 'f') + format_code = 'g'; + + /* detect if we're using exponents or not */ + if (format_code == 'e') + use_exp = 1; + else { + int min_decpt = -4; + int max_decpt = 17; + if (format_code == 'g') + max_decpt = 6; + if (min_decpt < decpt && decpt <= max_decpt) + use_exp = 0; + else + use_exp = 1; + } + + /* we got digits back, format them */ + + if (sign == 1) { + *buf++ = '-'; + } else if (always_add_sign) { + *buf++ = '+'; + } + + if (use_exp) { + /* exponential notation: d[.dddd]e(+|-)ee; + at least 2 digits in exponent */ + *buf++ = digits[0]; + *buf++ = '.'; + strncpy(buf, digits+1, digits_len-1); + buf += digits_len-1; + + } else { + /* use fixed-point notation */ if (decpt <= 0) { /* output: 0.00...00dd...dd */ *buf++ = '0'; *buf++ = '.'; - for (i=0; i < -decpt; i++) + for (i = 0; i < -decpt; i++) *buf++ = '0'; strncpy(buf, digits, digits_len); buf += digits_len; @@ -572,52 +628,84 @@ /* decpt >= digits_len. output: dd...dd00...00.0 */ strncpy(buf, digits, digits_len); buf += digits_len; - for (i=0; i < decpt-digits_len; i++) - *buf++ = '0'; - if (add_dot_0_if_integer) { - *buf++ = '.'; + for (i = 0; i < decpt-digits_len; i++) *buf++ = '0'; - } + *buf++ = '.'; } } - else { - /* exponential notation: d[.dddd]e(+|-)ee; - at least 2 digits in exponent */ - if (sign == 1) { - *buf++ = '-'; - } else if (always_add_sign) { - *buf++ = '+'; - } - *buf++ = digits[0]; - if (digits_len > 1) { - *buf++ = '.'; - strncpy(buf, digits+1, digits_len-1); - buf += digits_len-1; + + /* Add trailing non-significant zeros for non-mode 0 and non-code g */ + if (mode != 0 && format_code != 'g') { + Py_ssize_t nzeros = precision - digits_len; + + /* It should never be the case that nzeros is negative, but + check anyway. And while we're at it, skip 0 zeros. */ + if (nzeros > 0) { + for (i = 0; i < nzeros; i++) + *buf++ = '0'; } - *buf++ = 'e'; + } + + /* See if we want to have the trailing decimal or not */ + if (format_code == 'g' && buf[-1] == '.') + buf--; + + /* Now that we've done zero padding, add an exponent if needed. */ + if (use_exp) { + *buf++ = float_strings[OFS_E][0]; exp_len = sprintf(buf, "%+.02d", decpt-1); buf += exp_len; } + *buf++ = '\0'; } + PyAPI_FUNC(char *) PyOS_double_to_string(double val, int mode, char format_code, int precision, - int always_add_sign, - int add_dot_0_if_integer) + int flags) { - char fmt[32]; char* buf = (char *)PyMem_Malloc(512); + char lc_format_code = format_code; + char** float_strings = lc_float_strings; + + switch (format_code) { + case 'e': + case 'f': + case 'g': + break; + case 'E': + lc_format_code = 'e'; + break; + case 'F': + lc_format_code = 'f'; + break; + case 'G': + lc_format_code = 'g'; + break; + default: + PyErr_BadInternalCall(); + return NULL; + } + + if (format_code != lc_format_code) + float_strings = uc_float_strings; + + /* don't touch precision if we're in mode 0, it should stay 0. if + we're not using 'g', add one to the precision because we need to + include the digit before the decimal. */ + if (mode != 0 && lc_format_code != 'g') + precision += 1; -// printf("in PyOS_double_to_string\n"); +// printf("in PyOS_double_to_string %c %c\n", format_code, lc_format_code); if (!buf) return NULL; /* XXX validate format_code */ - format_float_short(buf, 512, val, mode, precision, always_add_sign, add_dot_0_if_integer); + format_float_short(buf, 512, val, lc_format_code, mode, precision, flags & Py_DTSF_SIGN, flags & Py_DTSF_ADD_DOT_0, float_strings); return buf; } From python-checkins at python.org Tue Mar 31 19:13:06 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 19:13:06 +0200 (CEST) Subject: [Python-checkins] r70842 - python/trunk/Doc/c-api/object.rst Message-ID: <20090331171306.D9E121E410A@bag.python.org> Author: georg.brandl Date: Tue Mar 31 19:13:06 2009 New Revision: 70842 Log: #970783: document PyObject_Generic[GS]etAttr. Modified: python/trunk/Doc/c-api/object.rst Modified: python/trunk/Doc/c-api/object.rst ============================================================================== --- python/trunk/Doc/c-api/object.rst (original) +++ python/trunk/Doc/c-api/object.rst Tue Mar 31 19:13:06 2009 @@ -42,6 +42,16 @@ expression ``o.attr_name``. +.. cfunction:: PyObject* PyObject_GenericGetAttr(PyObject *o, PyObject *name) + + Generic attribute getter function that is meant to be put into a type + object's ``tp_getattro`` slot. It looks for a descriptor in the dictionary + of classes in the object's MRO as well as an attribute in the object's + :attr:`__dict__` (if present). As outlined in :ref:`descriptors`, data + descriptors take preference over instance attributes, while non-data + descriptors don't. Otherwise, an :exc:`AttributeError` is raised. + + .. cfunction:: int PyObject_SetAttr(PyObject *o, PyObject *attr_name, PyObject *v) Set the value of the attribute named *attr_name*, for object *o*, to the value @@ -56,6 +66,17 @@ ``o.attr_name = v``. +.. cfunction:: int PyObject_GenericSetAttr(PyObject *o, PyObject *name, PyObject +*value) + + Generic attribute setter function that is meant to be put into a type + object's ``tp_setattro`` slot. It looks for a data descriptor in the + dictionary of classes in the object's MRO, and if found it takes preference + over setting the attribute in the instance dictionary. Otherwise, the + attribute is set in the object's :attr:`__dict__` (if present). Otherwise, + an :exc:`AttributeError` is raised and ``-1`` is returned. + + .. cfunction:: int PyObject_DelAttr(PyObject *o, PyObject *attr_name) Delete attribute named *attr_name*, for object *o*. Returns ``-1`` on failure. From buildbot at python.org Tue Mar 31 19:27:22 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 17:27:22 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu 2.6 Message-ID: <20090331172723.1D02F1E4061@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%202.6/builds/196 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: jeremy.hylton,jesse.noller BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_urlparse make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 19:43:39 2009 From: python-checkins at python.org (kristjan.jonsson) Date: Tue, 31 Mar 2009 19:43:39 +0200 (CEST) Subject: [Python-checkins] r70843 - python/branches/py3k/Python/import.c Message-ID: <20090331174339.902881E404A@bag.python.org> Author: kristjan.jonsson Date: Tue Mar 31 19:43:39 2009 New Revision: 70843 Log: get_file() no longer leaks a FILE structure. If given a file descriptor, it calls dup() to get a new handle. Then both the FILE object and the fd can be closed. This is important, because otherwise, the leaked FILE object will be closed on process exit, causing assertions on Windows, e.g. in the test_multiprocessing.py regression test. Modified: python/branches/py3k/Python/import.c Modified: python/branches/py3k/Python/import.c ============================================================================== --- python/branches/py3k/Python/import.c (original) +++ python/branches/py3k/Python/import.c Tue Mar 31 19:43:39 2009 @@ -3023,13 +3023,21 @@ int fd = PyObject_AsFileDescriptor(fob); if (fd == -1) return NULL; - /* XXX This will leak a FILE struct. Fix this!!!! - (But it doesn't leak a file descrioptor!) */ + if (!_PyVerify_fd(fd)) + goto error; + /* the FILE struct gets a new fd, so that it can be closed + * independently of the file descriptor given + */ + fd = dup(fd); + if (fd == -1) + goto error; fp = fdopen(fd, mode); } - if (fp == NULL) - PyErr_SetFromErrno(PyExc_IOError); - return fp; + if (fp) + return fp; +error: + PyErr_SetFromErrno(PyExc_IOError); + return NULL; } static PyObject * @@ -3051,8 +3059,7 @@ return NULL; } m = load_compiled_module(name, pathname, fp); - if (fob == NULL) - fclose(fp); + fclose(fp); PyMem_Free(pathname); return m; } @@ -3081,6 +3088,8 @@ } m = _PyImport_LoadDynamicModule(name, pathname, fp); PyMem_Free(pathname); + if (fp) + fclose(fp); return m; } @@ -3105,8 +3114,7 @@ return NULL; } m = load_source_module(name, pathname, fp); - if (fob == NULL) - fclose(fp); + fclose(fp); return m; } @@ -3150,6 +3158,8 @@ } ret = load_module(name, fp, pathname, type, NULL); PyMem_Free(pathname); + if (fp) + fclose(fp); return ret; } From python-checkins at python.org Tue Mar 31 19:47:06 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 31 Mar 2009 19:47:06 +0200 (CEST) Subject: [Python-checkins] r70844 - python/trunk/Lib/bisect.py Message-ID: <20090331174706.924041E405D@bag.python.org> Author: raymond.hettinger Date: Tue Mar 31 19:47:06 2009 New Revision: 70844 Log: Per the language summit, the optional fastpath imports should use from-import-star. Modified: python/trunk/Lib/bisect.py Modified: python/trunk/Lib/bisect.py ============================================================================== --- python/trunk/Lib/bisect.py (original) +++ python/trunk/Lib/bisect.py Tue Mar 31 19:47:06 2009 @@ -87,6 +87,6 @@ # Overwrite above definitions with a fast C implementation try: - from _bisect import bisect_right, bisect_left, insort_left, insort_right, insort, bisect + from _bisect import * except ImportError: pass From python-checkins at python.org Tue Mar 31 19:47:50 2009 From: python-checkins at python.org (kristjan.jonsson) Date: Tue, 31 Mar 2009 19:47:50 +0200 (CEST) Subject: [Python-checkins] r70845 - python/branches/py3k/Python/import.c Message-ID: <20090331174750.62D141E405D@bag.python.org> Author: kristjan.jonsson Date: Tue Mar 31 19:47:50 2009 New Revision: 70845 Log: Fix a leaking "pathname" in import.c Modified: python/branches/py3k/Python/import.c Modified: python/branches/py3k/Python/import.c ============================================================================== --- python/branches/py3k/Python/import.c (original) +++ python/branches/py3k/Python/import.c Tue Mar 31 19:47:50 2009 @@ -3114,6 +3114,7 @@ return NULL; } m = load_source_module(name, pathname, fp); + PyMem_Free(pathname); fclose(fp); return m; } From python-checkins at python.org Tue Mar 31 19:51:52 2009 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 31 Mar 2009 19:51:52 +0200 (CEST) Subject: [Python-checkins] r70846 - python/branches/py3k/Lib/bisect.py Message-ID: <20090331175152.50E401E422F@bag.python.org> Author: raymond.hettinger Date: Tue Mar 31 19:51:51 2009 New Revision: 70846 Log: Per the language summit, the optional fastpath imports should use from-import-star. Modified: python/branches/py3k/Lib/bisect.py Modified: python/branches/py3k/Lib/bisect.py ============================================================================== --- python/branches/py3k/Lib/bisect.py (original) +++ python/branches/py3k/Lib/bisect.py Tue Mar 31 19:51:51 2009 @@ -87,6 +87,6 @@ # Overwrite above definitions with a fast C implementation try: - from _bisect import bisect_right, bisect_left, insort_left, insort_right, insort, bisect + from _bisect import * except ImportError: pass From buildbot at python.org Tue Mar 31 19:55:24 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 17:55:24 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu 3.0 Message-ID: <20090331175525.0E6941E400C@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%203.0/builds/262 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 19:56:41 2009 From: python-checkins at python.org (brett.cannon) Date: Tue, 31 Mar 2009 19:56:41 +0200 (CEST) Subject: [Python-checkins] r70847 - peps/trunk/pep-0374.txt Message-ID: <20090331175641.16AC91E400C@bag.python.org> Author: brett.cannon Date: Tue Mar 31 19:56:40 2009 New Revision: 70847 Log: Update PEP 374 that Mercurial has been chosen (no details yet, though). Modified: peps/trunk/pep-0374.txt Modified: peps/trunk/pep-0374.txt ============================================================================== --- peps/trunk/pep-0374.txt (original) +++ peps/trunk/pep-0374.txt Tue Mar 31 19:56:40 2009 @@ -15,7 +15,8 @@ .. warning:: This PEP is in the draft stages and is still under active - development. + development in terms of the transition plan even though Hg is the + chosen DVCS. Rationale @@ -1457,11 +1458,11 @@ Chosen DVCS =========== -XXX -:: +The `decision +`_ +was made at PyCon 2009 to go with Mercurial_. - import random - print(random.choice(['svn', 'bzr', 'hg', 'git'])) +XXX details as to why Transition Plan From python-checkins at python.org Tue Mar 31 20:11:50 2009 From: python-checkins at python.org (brett.cannon) Date: Tue, 31 Mar 2009 20:11:50 +0200 (CEST) Subject: [Python-checkins] r70848 - in peps/trunk: pep-0374.txt pep-0380.txt pep-3143.txt Message-ID: <20090331181150.3F78B1E403E@bag.python.org> Author: brett.cannon Date: Tue Mar 31 20:11:49 2009 New Revision: 70848 Log: Fix svn properties on a couple of PEPs. Modified: peps/trunk/pep-0374.txt (contents, props changed) peps/trunk/pep-0380.txt (props changed) peps/trunk/pep-3143.txt (contents, props changed) Modified: peps/trunk/pep-0374.txt ============================================================================== --- peps/trunk/pep-0374.txt (original) +++ peps/trunk/pep-0374.txt Tue Mar 31 20:11:49 2009 @@ -1,7 +1,7 @@ PEP: 374 Title: Migrating from svn to a distributed VCS -Version: $Revision: 65628 $ -Last-Modified: $Date: 2008-08-10 06:59:20 -0700 (Sun, 10 Aug 2008) $ +Version: $Revision$ +Last-Modified: $Date$ Author: Brett Cannon , Stephen J. Turnbull , Alexandre Vassalotti , Modified: peps/trunk/pep-3143.txt ============================================================================== --- peps/trunk/pep-3143.txt (original) +++ peps/trunk/pep-3143.txt Tue Mar 31 20:11:49 2009 @@ -1,7 +1,7 @@ PEP: 3143 Title: Standard daemon process library -Version: $Revision: 1.1 $ -Last-Modified: $Date: 2009-03-19 12:51 $ +Version: $Revision$ +Last-Modified: $Date$ Author: Ben Finney Status: Draft Type: Standards Track From python-checkins at python.org Tue Mar 31 20:12:36 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 20:12:36 +0200 (CEST) Subject: [Python-checkins] r70849 - in python/trunk: Modules/mmapmodule.c Modules/socketmodule.c setup.py Message-ID: <20090331181236.3D4051E403E@bag.python.org> Author: jesse.noller Date: Tue Mar 31 20:12:35 2009 New Revision: 70849 Log: Apply patch for netbsd multiprocessing support Modified: python/trunk/Modules/mmapmodule.c python/trunk/Modules/socketmodule.c python/trunk/setup.py Modified: python/trunk/Modules/mmapmodule.c ============================================================================== --- python/trunk/Modules/mmapmodule.c (original) +++ python/trunk/Modules/mmapmodule.c Tue Mar 31 20:12:35 2009 @@ -509,7 +509,11 @@ #ifdef MREMAP_MAYMOVE newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE); #else - newmap = mremap(self->data, self->size, new_size, 0); + #if defined(__NetBSD__) + newmap = mremap(self->data, self->size, self->data, new_size, 0); + #else + newmap = mremap(self->data, self->size, new_size, 0); + #endif /* __NetBSD__ */ #endif if (newmap == (void *)-1) { Modified: python/trunk/Modules/socketmodule.c ============================================================================== --- python/trunk/Modules/socketmodule.c (original) +++ python/trunk/Modules/socketmodule.c Tue Mar 31 20:12:35 2009 @@ -379,7 +379,7 @@ #define SOCKETCLOSE close #endif -#if defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H) +#if defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H) && !defined(__NetBSD__) #define USE_BLUETOOTH 1 #if defined(__FreeBSD__) #define BTPROTO_L2CAP BLUETOOTH_PROTO_L2CAP Modified: python/trunk/setup.py ============================================================================== --- python/trunk/setup.py (original) +++ python/trunk/setup.py Tue Mar 31 20:12:35 2009 @@ -1280,6 +1280,15 @@ ) libraries = [] + elif platform.startswith('netbsd'): + macros = dict( # at least NetBSD 5 + HAVE_SEM_OPEN=1, + HAVE_SEM_TIMEDWAIT=0, + HAVE_FD_TRANSFER=1, + HAVE_BROKEN_SEM_GETVALUE=1 + ) + libraries = [] + else: # Linux and other unices macros = dict( HAVE_SEM_OPEN=1, From buildbot at python.org Tue Mar 31 20:17:14 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 18:17:14 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 3.0 Message-ID: <20090331181714.436241E40C8@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 3.0. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%203.0/builds/234 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch branches/release30-maint] HEAD Blamelist: jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From buildbot at python.org Tue Mar 31 20:17:43 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 18:17:43 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 3.x Message-ID: <20090331181743.E08D51E40C8@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 3.x. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%203.x/builds/525 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/py3k] HEAD Blamelist: hirokazu.yamamoto,jeremy.hylton BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 20:20:48 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 20:20:48 +0200 (CEST) Subject: [Python-checkins] r70850 - in python/branches/release26-maint: Modules/mmapmodule.c Modules/socketmodule.c setup.py Message-ID: <20090331182048.701821E42AC@bag.python.org> Author: jesse.noller Date: Tue Mar 31 20:20:48 2009 New Revision: 70850 Log: Merged revisions 70849 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70849 | jesse.noller | 2009-03-31 13:12:35 -0500 (Tue, 31 Mar 2009) | 1 line Apply patch for netbsd multiprocessing support ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Modules/mmapmodule.c python/branches/release26-maint/Modules/socketmodule.c python/branches/release26-maint/setup.py Modified: python/branches/release26-maint/Modules/mmapmodule.c ============================================================================== --- python/branches/release26-maint/Modules/mmapmodule.c (original) +++ python/branches/release26-maint/Modules/mmapmodule.c Tue Mar 31 20:20:48 2009 @@ -509,7 +509,11 @@ #ifdef MREMAP_MAYMOVE newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE); #else - newmap = mremap(self->data, self->size, new_size, 0); + #if defined(__NetBSD__) + newmap = mremap(self->data, self->size, self->data, new_size, 0); + #else + newmap = mremap(self->data, self->size, new_size, 0); + #endif /* __NetBSD__ */ #endif if (newmap == (void *)-1) { Modified: python/branches/release26-maint/Modules/socketmodule.c ============================================================================== --- python/branches/release26-maint/Modules/socketmodule.c (original) +++ python/branches/release26-maint/Modules/socketmodule.c Tue Mar 31 20:20:48 2009 @@ -379,7 +379,7 @@ #define SOCKETCLOSE close #endif -#if defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H) +#if defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H) && !defined(__NetBSD__) #define USE_BLUETOOTH 1 #if defined(__FreeBSD__) #define BTPROTO_L2CAP BLUETOOTH_PROTO_L2CAP Modified: python/branches/release26-maint/setup.py ============================================================================== --- python/branches/release26-maint/setup.py (original) +++ python/branches/release26-maint/setup.py Tue Mar 31 20:20:48 2009 @@ -1291,6 +1291,15 @@ ) libraries = [] + elif platform.startswith('netbsd'): + macros = dict( # at least NetBSD 5 + HAVE_SEM_OPEN=1, + HAVE_SEM_TIMEDWAIT=0, + HAVE_FD_TRANSFER=1, + HAVE_BROKEN_SEM_GETVALUE=1 + ) + libraries = [] + else: # Linux and other unices macros = dict( HAVE_SEM_OPEN=1, From python-checkins at python.org Tue Mar 31 20:26:55 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 20:26:55 +0200 (CEST) Subject: [Python-checkins] r70851 - python/trunk/Doc/library/os.rst Message-ID: <20090331182655.865171E402A@bag.python.org> Author: georg.brandl Date: Tue Mar 31 20:26:55 2009 New Revision: 70851 Log: #837577: note cryptic return value of spawn*e on invalid env dicts. Modified: python/trunk/Doc/library/os.rst Modified: python/trunk/Doc/library/os.rst ============================================================================== --- python/trunk/Doc/library/os.rst (original) +++ python/trunk/Doc/library/os.rst Tue Mar 31 20:26:55 2009 @@ -1753,7 +1753,9 @@ which is used to define the environment variables for the new process (they are used instead of the current process' environment); the functions :func:`spawnl`, :func:`spawnlp`, :func:`spawnv`, and :func:`spawnvp` all cause - the new process to inherit the environment of the current process. + the new process to inherit the environment of the current process. Note that + keys and values in the *env* dictionary must be strings; invalid keys or + values will cause the function to fail, with a return value of ``127``. As an example, the following calls to :func:`spawnlp` and :func:`spawnvpe` are equivalent:: From python-checkins at python.org Tue Mar 31 20:27:15 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 20:27:15 +0200 (CEST) Subject: [Python-checkins] r70852 - in python/trunk/Misc: ACKS NEWS Message-ID: <20090331182715.0F4D81E402A@bag.python.org> Author: jesse.noller Date: Tue Mar 31 20:27:14 2009 New Revision: 70852 Log: missed the news/acks for netbsd patch Modified: python/trunk/Misc/ACKS python/trunk/Misc/NEWS Modified: python/trunk/Misc/ACKS ============================================================================== --- python/trunk/Misc/ACKS (original) +++ python/trunk/Misc/ACKS Tue Mar 31 20:27:14 2009 @@ -489,6 +489,7 @@ Sjoerd Mullender Sape Mullender Michael Muller +Piotr Meyer John Nagle Takahiro Nakayama Travers Naran Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 31 20:27:14 2009 @@ -199,6 +199,8 @@ Library ------- +- Issue #5400: Added patch for multiprocessing on netbsd compilation/support + - Issue #5387: Fixed mmap.move crash by integer overflow. - Issue #5261: Patch multiprocessing's semaphore.c to support context From python-checkins at python.org Tue Mar 31 20:27:51 2009 From: python-checkins at python.org (r.david.murray) Date: Tue, 31 Mar 2009 20:27:51 +0200 (CEST) Subject: [Python-checkins] r70853 - in python/branches/py3k: Lib/test/test_sundry.py Message-ID: <20090331182751.7E4CD1E402A@bag.python.org> Author: r.david.murray Date: Tue Mar 31 20:27:51 2009 New Revision: 70853 Log: Merged revisions 70779 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70779 | r.david.murray | 2009-03-30 19:10:37 -0400 (Mon, 30 Mar 2009) | 3 lines Actually suppress warnings in test_at_least_import_untested_modules inside the catch_warnings context manager. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_sundry.py Modified: python/branches/py3k/Lib/test/test_sundry.py ============================================================================== --- python/branches/py3k/Lib/test/test_sundry.py (original) +++ python/branches/py3k/Lib/test/test_sundry.py Tue Mar 31 20:27:51 2009 @@ -8,6 +8,7 @@ class TestUntestedModules(unittest.TestCase): def test_at_least_import_untested_modules(self): with warnings.catch_warnings(): + warnings.simplefilter("ignore") import aifc import bdb import cgitb From python-checkins at python.org Tue Mar 31 20:29:45 2009 From: python-checkins at python.org (eric.smith) Date: Tue, 31 Mar 2009 20:29:45 +0200 (CEST) Subject: [Python-checkins] r70854 - python/branches/py3k-short-float-repr/Python/pystrtod.c Message-ID: <20090331182945.17F4A1E402A@bag.python.org> Author: eric.smith Date: Tue Mar 31 20:29:44 2009 New Revision: 70854 Log: Exponent calculations. Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/pystrtod.c (original) +++ python/branches/py3k-short-float-repr/Python/pystrtod.c Tue Mar 31 20:29:44 2009 @@ -529,7 +529,7 @@ char *digits, *digits_end; int decpt, sign, exp_len; Py_ssize_t digits_len, i; - int use_exp; + int use_exp = 0; /* _Py_dg_dtoa returns a digit string (no decimal point or exponent) */ @@ -576,17 +576,21 @@ format_code = 'g'; /* detect if we're using exponents or not */ - if (format_code == 'e') + switch (format_code) { + case 'e': use_exp = 1; - else { + break; + case 'f': + use_exp = 0; + break; + case 'g': { int min_decpt = -4; - int max_decpt = 17; - if (format_code == 'g') - max_decpt = 6; - if (min_decpt < decpt && decpt <= max_decpt) - use_exp = 0; - else + + if (decpt > precision || decpt < min_decpt) use_exp = 1; + else + use_exp = 0; + } } /* we got digits back, format them */ From python-checkins at python.org Tue Mar 31 20:30:37 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 20:30:37 +0200 (CEST) Subject: [Python-checkins] r70855 - python/trunk/Doc/c-api/veryhigh.rst Message-ID: <20090331183037.9DA8E1E400C@bag.python.org> Author: georg.brandl Date: Tue Mar 31 20:30:37 2009 New Revision: 70855 Log: #5245: note that PyRun_SimpleString doesnt return on SystemExit. Modified: python/trunk/Doc/c-api/veryhigh.rst Modified: python/trunk/Doc/c-api/veryhigh.rst ============================================================================== --- python/trunk/Doc/c-api/veryhigh.rst (original) +++ python/trunk/Doc/c-api/veryhigh.rst Tue Mar 31 20:30:37 2009 @@ -78,6 +78,10 @@ there was an error, there is no way to get the exception information. For the meaning of *flags*, see below. + Note that if an otherwise unhandled :exc:`SystemError` is raised, this + function will not return ``-1``, but exit the process, as long as + ``Py_InspectFlag`` is not set. + .. cfunction:: int PyRun_SimpleFile(FILE *fp, const char *filename) From python-checkins at python.org Tue Mar 31 20:32:17 2009 From: python-checkins at python.org (r.david.murray) Date: Tue, 31 Mar 2009 20:32:17 +0200 (CEST) Subject: [Python-checkins] r70856 - in python/trunk/Lib/test: test_bsddb.py test_bsddb3.py test_fcntl.py test_scriptpackages.py test_support.py test_tcl.py test_tk.py test_ttk_guionly.py test_ttk_textonly.py test_winreg.py Message-ID: <20090331183217.E267E1E400C@bag.python.org> Author: r.david.murray Date: Tue Mar 31 20:32:17 2009 New Revision: 70856 Log: A few more test skips via import_module, and change import_module to return the error message produced by importlib, so that if an import in the package whose import is being wrapped is what failed the skip message will contain the name of that module instead of the name of the wrapped module. Also fixed formatting of some previous comments. Modified: python/trunk/Lib/test/test_bsddb.py python/trunk/Lib/test/test_bsddb3.py python/trunk/Lib/test/test_fcntl.py python/trunk/Lib/test/test_scriptpackages.py python/trunk/Lib/test/test_support.py python/trunk/Lib/test/test_tcl.py python/trunk/Lib/test/test_tk.py python/trunk/Lib/test/test_ttk_guionly.py python/trunk/Lib/test/test_ttk_textonly.py python/trunk/Lib/test/test_winreg.py Modified: python/trunk/Lib/test/test_bsddb.py ============================================================================== --- python/trunk/Lib/test/test_bsddb.py (original) +++ python/trunk/Lib/test/test_bsddb.py Tue Mar 31 20:32:17 2009 @@ -4,11 +4,16 @@ """ import os, sys import copy -import bsddb -import dbhash # Just so we know it's imported import unittest from test import test_support +# Skip test if _bsddb wasn't built. +test_support.import_module('_bsddb') + +import bsddb +import dbhash # Just so we know it's imported + + class TestBSDDB(unittest.TestCase): openflag = 'c' Modified: python/trunk/Lib/test/test_bsddb3.py ============================================================================== --- python/trunk/Lib/test/test_bsddb3.py (original) +++ python/trunk/Lib/test/test_bsddb3.py Tue Mar 31 20:32:17 2009 @@ -10,8 +10,8 @@ from test.test_support import (requires, verbose, run_unittest, unlink, rmtree, import_module) -#Skip test if bsddb cannot import _bsddb. -import_module('bsddb') +# Skip test if _bsddb module was not built. +import_module('_bsddb') # When running as a script instead of within the regrtest framework, skip the # requires test, since it's obvious we want to run them. Modified: python/trunk/Lib/test/test_fcntl.py ============================================================================== --- python/trunk/Lib/test/test_fcntl.py (original) +++ python/trunk/Lib/test/test_fcntl.py Tue Mar 31 20:32:17 2009 @@ -3,12 +3,16 @@ OS/2+EMX doesn't support the file locking operations. """ -import fcntl import os import struct import sys import unittest -from test.test_support import verbose, TESTFN, unlink, run_unittest +from test.test_support import (verbose, TESTFN, unlink, run_unittest, + import_module) + +# Skip test if no fnctl module. +fcntl = import_module('fcntl') + # TODO - Write tests for flock() and lockf(). Modified: python/trunk/Lib/test/test_scriptpackages.py ============================================================================== --- python/trunk/Lib/test/test_scriptpackages.py (original) +++ python/trunk/Lib/test/test_scriptpackages.py Tue Mar 31 20:32:17 2009 @@ -3,7 +3,8 @@ import unittest from test import test_support -aetools = test_support.import_module('aetools') +# Skip this test if aetools does not exist. +test_support.import_module('aetools') class TestScriptpackages(unittest.TestCase): Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Tue Mar 31 20:32:17 2009 @@ -51,8 +51,8 @@ DeprecationWarning) try: module = importlib.import_module(name) - except ImportError: - raise unittest.SkipTest("No module named " + name) + except ImportError, msg: + raise unittest.SkipTest(str(msg)) else: return module Modified: python/trunk/Lib/test/test_tcl.py ============================================================================== --- python/trunk/Lib/test/test_tcl.py (original) +++ python/trunk/Lib/test/test_tcl.py Tue Mar 31 20:32:17 2009 @@ -2,8 +2,11 @@ import unittest import os -import _tkinter from test import test_support + +# Skip this test if the _tkinter module wasn't built. +_tkinter = test_support.import_module('_tkinter') + from Tkinter import Tcl from _tkinter import TclError Modified: python/trunk/Lib/test/test_tk.py ============================================================================== --- python/trunk/Lib/test/test_tk.py (original) +++ python/trunk/Lib/test/test_tk.py Tue Mar 31 20:32:17 2009 @@ -1,9 +1,13 @@ import os import sys import unittest -import Tkinter from test import test_support +# Skip test if _tkinter wasn't built. +test_support.import_module('_tkinter') + +import Tkinter + try: Tkinter.Button() except Tkinter.TclError, msg: Modified: python/trunk/Lib/test/test_ttk_guionly.py ============================================================================== --- python/trunk/Lib/test/test_ttk_guionly.py (original) +++ python/trunk/Lib/test/test_ttk_guionly.py Tue Mar 31 20:32:17 2009 @@ -3,8 +3,10 @@ import unittest from test import test_support -ttk = test_support.import_module('ttk') -#If ttk exists _tkinter must exist. +# Skip this test if _tkinter wasn't built. +test_support.import_module('_tkinter') + +import ttk from _tkinter import TclError try: Modified: python/trunk/Lib/test/test_ttk_textonly.py ============================================================================== --- python/trunk/Lib/test/test_ttk_textonly.py (original) +++ python/trunk/Lib/test/test_ttk_textonly.py Tue Mar 31 20:32:17 2009 @@ -2,6 +2,9 @@ import sys from test import test_support +# Skip this test if _tkinter does not exist. +test_support.import_module('_tkinter') + this_dir = os.path.dirname(os.path.abspath(__file__)) lib_tk_test = os.path.abspath(os.path.join(this_dir, '..', 'lib-tk', 'test')) if lib_tk_test not in sys.path: Modified: python/trunk/Lib/test/test_winreg.py ============================================================================== --- python/trunk/Lib/test/test_winreg.py (original) +++ python/trunk/Lib/test/test_winreg.py Tue Mar 31 20:32:17 2009 @@ -5,9 +5,9 @@ import unittest from test import test_support -#Do this first so test will be skipped if module doesn't exist +# Do this first so test will be skipped if module doesn't exist test_support.import_module('_winreg') -#Now import everything +# Now import everything from _winreg import * test_key_name = "SOFTWARE\\Python Registry Test Key - Delete Me" From python-checkins at python.org Tue Mar 31 20:33:10 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 20:33:10 +0200 (CEST) Subject: [Python-checkins] r70857 - python/trunk/Doc/c-api/veryhigh.rst Message-ID: <20090331183310.313FD1E400C@bag.python.org> Author: georg.brandl Date: Tue Mar 31 20:33:10 2009 New Revision: 70857 Log: #5227: note that Py_Main doesnt return on SystemExit. Modified: python/trunk/Doc/c-api/veryhigh.rst Modified: python/trunk/Doc/c-api/veryhigh.rst ============================================================================== --- python/trunk/Doc/c-api/veryhigh.rst (original) +++ python/trunk/Doc/c-api/veryhigh.rst Tue Mar 31 20:33:10 2009 @@ -36,6 +36,10 @@ interpreter exits due to an exception, or ``2`` if the parameter list does not represent a valid Python command line. + Note that if an otherwise unhandled :exc:`SystemError` is raised, this + function will not return ``1``, but exit the process, as long as + ``Py_InspectFlag`` is not set. + .. cfunction:: int PyRun_AnyFile(FILE *fp, const char *filename) From python-checkins at python.org Tue Mar 31 20:38:57 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 20:38:57 +0200 (CEST) Subject: [Python-checkins] r70858 - python/trunk/Doc/howto/regex.rst Message-ID: <20090331183857.2EAFE1E400C@bag.python.org> Author: georg.brandl Date: Tue Mar 31 20:38:56 2009 New Revision: 70858 Log: #5241: document missing U in regex howto. Modified: python/trunk/Doc/howto/regex.rst Modified: python/trunk/Doc/howto/regex.rst ============================================================================== --- python/trunk/Doc/howto/regex.rst (original) +++ python/trunk/Doc/howto/regex.rst Tue Mar 31 20:38:56 2009 @@ -540,6 +540,10 @@ | :const:`VERBOSE`, :const:`X` | Enable verbose REs, which can be organized | | | more cleanly and understandably. | +---------------------------------+--------------------------------------------+ +| :const:`UNICODE`, :const:`U` | Makes several escapes like ``\w``, ``\b``, | +| | ``\s`` and ``\d`` dependent on the Unicode | +| | character database. | ++---------------------------------+--------------------------------------------+ .. data:: I @@ -594,6 +598,14 @@ newline; without this flag, ``'.'`` will match anything *except* a newline. +.. data:: U + UNICODE + :index: + + Make ``\w``, ``\W``, ``\b``, ``\B``, ``\d``, ``\D``, ``\s`` and ``\S`` + dependent on the Unicode character properties database. + + .. data:: X VERBOSE :noindex: From python-checkins at python.org Tue Mar 31 20:39:40 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 20:39:40 +0200 (CEST) Subject: [Python-checkins] r70859 - in python/branches/release26-maint: Misc/ACKS Misc/NEWS Message-ID: <20090331183940.1173B1E400C@bag.python.org> Author: jesse.noller Date: Tue Mar 31 20:39:39 2009 New Revision: 70859 Log: Merged revisions 70852 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70852 | jesse.noller | 2009-03-31 13:27:14 -0500 (Tue, 31 Mar 2009) | 1 line missed the news/acks for netbsd patch ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Misc/ACKS python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Misc/ACKS ============================================================================== --- python/branches/release26-maint/Misc/ACKS (original) +++ python/branches/release26-maint/Misc/ACKS Tue Mar 31 20:39:39 2009 @@ -479,6 +479,7 @@ Sjoerd Mullender Sape Mullender Michael Muller +Piotr Meyer John Nagle Takahiro Nakayama Travers Naran Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Tue Mar 31 20:39:39 2009 @@ -92,6 +92,8 @@ Library ------- +- Issue #5400: Added patch for multiprocessing on netbsd compilation/support + - Fix and properly document the multiprocessing module's logging support, expose the internal levels and provide proper usage examples. From python-checkins at python.org Tue Mar 31 20:40:41 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 20:40:41 +0200 (CEST) Subject: [Python-checkins] r70860 - python/branches/py3k Message-ID: <20090331184041.E80501E400C@bag.python.org> Author: georg.brandl Date: Tue Mar 31 20:40:41 2009 New Revision: 70860 Log: Blocked revisions 70858 via svnmerge ........ r70858 | georg.brandl | 2009-03-31 13:38:56 -0500 (Di, 31 M?r 2009) | 1 line #5241: document missing U in regex howto. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Tue Mar 31 20:41:03 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 20:41:03 +0200 (CEST) Subject: [Python-checkins] r70861 - python/branches/py3k/Doc/howto/regex.rst Message-ID: <20090331184103.C1B141E402A@bag.python.org> Author: georg.brandl Date: Tue Mar 31 20:41:03 2009 New Revision: 70861 Log: #5241: document missing A in regex howto. Modified: python/branches/py3k/Doc/howto/regex.rst Modified: python/branches/py3k/Doc/howto/regex.rst ============================================================================== --- python/branches/py3k/Doc/howto/regex.rst (original) +++ python/branches/py3k/Doc/howto/regex.rst Tue Mar 31 20:41:03 2009 @@ -540,6 +540,10 @@ | :const:`VERBOSE`, :const:`X` | Enable verbose REs, which can be organized | | | more cleanly and understandably. | +---------------------------------+--------------------------------------------+ +| :const:`ASCII`, :const:`A` | Makes several escapes like ``\w``, ``\b``, | +| | ``\s`` and ``\d`` match only on ASCII | +| | characters with the respective property. | ++---------------------------------+--------------------------------------------+ .. data:: I @@ -594,6 +598,15 @@ newline; without this flag, ``'.'`` will match anything *except* a newline. +.. data:: A + ASCII + :noindex: + + Make ``\w``, ``\W``, ``\b``, ``\B``, ``\s`` and ``\S`` perform ASCII-only + matching instead of full Unicode matching. This is only meaningful for + Unicode patterns, and is ignored for byte patterns. + + .. data:: X VERBOSE :noindex: From python-checkins at python.org Tue Mar 31 20:48:42 2009 From: python-checkins at python.org (jesse.noller) Date: Tue, 31 Mar 2009 20:48:42 +0200 (CEST) Subject: [Python-checkins] r70862 - in python/branches/py3k: Misc/ACKS Misc/NEWS Modules/mmapmodule.c Modules/socketmodule.c setup.py Message-ID: <20090331184842.A87FD1E402A@bag.python.org> Author: jesse.noller Date: Tue Mar 31 20:48:42 2009 New Revision: 70862 Log: Merged revisions 70849,70852 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70849 | jesse.noller | 2009-03-31 13:12:35 -0500 (Tue, 31 Mar 2009) | 1 line Apply patch for netbsd multiprocessing support ........ r70852 | jesse.noller | 2009-03-31 13:27:14 -0500 (Tue, 31 Mar 2009) | 1 line missed the news/acks for netbsd patch ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Misc/ACKS python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/mmapmodule.c python/branches/py3k/Modules/socketmodule.c python/branches/py3k/setup.py Modified: python/branches/py3k/Misc/ACKS ============================================================================== --- python/branches/py3k/Misc/ACKS (original) +++ python/branches/py3k/Misc/ACKS Tue Mar 31 20:48:42 2009 @@ -492,6 +492,7 @@ Sjoerd Mullender Sape Mullender Michael Muller +Piotr Meyer John Nagle Takahiro Nakayama Travers Naran Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Mar 31 20:48:42 2009 @@ -53,6 +53,8 @@ Library ------- +- Issue #5400: Added patch for multiprocessing on netbsd compilation/support + - Issue #5387: Fixed mmap.move crash by integer overflow. - Issue #5261: Patch multiprocessing's semaphore.c to support context Modified: python/branches/py3k/Modules/mmapmodule.c ============================================================================== --- python/branches/py3k/Modules/mmapmodule.c (original) +++ python/branches/py3k/Modules/mmapmodule.c Tue Mar 31 20:48:42 2009 @@ -520,7 +520,11 @@ #ifdef MREMAP_MAYMOVE newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE); #else - newmap = mremap(self->data, self->size, new_size, 0); + #if defined(__NetBSD__) + newmap = mremap(self->data, self->size, self->data, new_size, 0); + #else + newmap = mremap(self->data, self->size, new_size, 0); + #endif /* __NetBSD__ */ #endif if (newmap == (void *)-1) { Modified: python/branches/py3k/Modules/socketmodule.c ============================================================================== --- python/branches/py3k/Modules/socketmodule.c (original) +++ python/branches/py3k/Modules/socketmodule.c Tue Mar 31 20:48:42 2009 @@ -382,7 +382,7 @@ #define SOCKETCLOSE close #endif -#if defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H) +#if defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H) && !defined(__NetBSD__) #define USE_BLUETOOTH 1 #if defined(__FreeBSD__) #define BTPROTO_L2CAP BLUETOOTH_PROTO_L2CAP Modified: python/branches/py3k/setup.py ============================================================================== --- python/branches/py3k/setup.py (original) +++ python/branches/py3k/setup.py Tue Mar 31 20:48:42 2009 @@ -1023,6 +1023,15 @@ ) libraries = [] + elif platform.startswith('netbsd'): + macros = dict( # at least NetBSD 5 + HAVE_SEM_OPEN=1, + HAVE_SEM_TIMEDWAIT=0, + HAVE_FD_TRANSFER=1, + HAVE_BROKEN_SEM_GETVALUE=1 + ) + libraries = [] + else: # Linux and other unices macros = dict( HAVE_SEM_OPEN=1, From buildbot at python.org Tue Mar 31 20:54:49 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 18:54:49 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu trunk Message-ID: <20090331185450.053921E402A@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%20trunk/builds/1036 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl,gregory.p.smith BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_poll make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 20:56:40 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 20:56:40 +0200 (CEST) Subject: [Python-checkins] r70863 - python/branches/py3k/Doc/extending/newtypes.rst Message-ID: <20090331185640.1F4411E402A@bag.python.org> Author: georg.brandl Date: Tue Mar 31 20:56:38 2009 New Revision: 70863 Log: #1717: fix-up docs for comparison in newtypes document. Modified: python/branches/py3k/Doc/extending/newtypes.rst Modified: python/branches/py3k/Doc/extending/newtypes.rst ============================================================================== --- python/branches/py3k/Doc/extending/newtypes.rst (original) +++ python/branches/py3k/Doc/extending/newtypes.rst Tue Mar 31 20:56:38 2009 @@ -1231,50 +1231,53 @@ return -1; } -.. XXX tp_compare is dead; need to rewrite for tp_richcompare! +Object Comparison +----------------- - Object Comparison - ----------------- +:: + + richcmpfunc tp_richcompare; + +The :attr:`tp_richcompare` handler is called when comparisons are needed. It is +analogous to the :ref:`rich comparison methods `, like +:meth:`__lt__`, and also called by :cfunc:`PyObject_RichCompare` and +:cfunc:`PyObject_RichCompareBool`. + +This function is called with two Python objects and the operator as arguments, +where the operator is one of ``Py_EQ``, ``Py_NE``, ``Py_LE``, ``Py_GT``, +``Py_LT`` or ``Py_GT``. It should compare the two objects with respect to the +specified operator and return ``Py_True`` or ``Py_False`` if the comparison is +successfull, ``Py_NotImplemented`` to indicate that comparison is not +implemented and the other object's comparison method should be tried, or *NULL* +if an exception was set. - :: +Here is a sample implementation, for a datatype that is considered equal if the +size of an internal pointer is equal:: - cmpfunc tp_compare; + static int + newdatatype_richcmp(PyObject *obj1, PyObject *obj2, int op) + { + PyObject *result; + int c, size1, size2; - The :attr:`tp_compare` handler is called when comparisons are needed and the - object does not implement the specific rich comparison method which matches the - requested comparison. (It is always used if defined and the - :cfunc:`PyObject_Compare` or :cfunc:`PyObject_Cmp` functions are used, or if - :func:`cmp` is used from Python.) It is analogous to the :meth:`__cmp__` method. - This function should return ``-1`` if *obj1* is less than *obj2*, ``0`` if they - are equal, and ``1`` if *obj1* is greater than *obj2*. (It was previously - allowed to return arbitrary negative or positive integers for less than and - greater than, respectively; as of Python 2.2, this is no longer allowed. In the - future, other return values may be assigned a different meaning.) - - A :attr:`tp_compare` handler may raise an exception. In this case it should - return a negative value. The caller has to test for the exception using - :cfunc:`PyErr_Occurred`. - - Here is a sample implementation:: - - static int - newdatatype_compare(newdatatypeobject * obj1, newdatatypeobject * obj2) - { - long result; - - if (obj1->obj_UnderlyingDatatypePtr->size < - obj2->obj_UnderlyingDatatypePtr->size) { - result = -1; - } - else if (obj1->obj_UnderlyingDatatypePtr->size > - obj2->obj_UnderlyingDatatypePtr->size) { - result = 1; - } - else { - result = 0; - } - return result; - } + /* code to make sure that both arguments are of type + newdatatype omitted */ + + size1 = obj1->obj_UnderlyingDatatypePtr->size; + size2 = obj2->obj_UnderlyingDatatypePtr->size; + + switch (op) { + case Py_LT: c = size1 < size2; break; + case Py_LE: c = size1 <= size2; break; + case Py_EQ: c = size1 == size2; break; + case Py_NE: c = size1 != size2; break; + case Py_GT: c = size1 > size2; break; + case Py_GE: c = size1 >= size2; break; + } + result = c ? Py_True : Py_False; + Py_INCREF(result); + return result; + } Abstract Protocol Support From python-checkins at python.org Tue Mar 31 21:03:29 2009 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 31 Mar 2009 21:03:29 +0200 (CEST) Subject: [Python-checkins] r70864 - in python/trunk/Lib: test/test_unittest.py unittest.py Message-ID: <20090331190329.48FB41E402A@bag.python.org> Author: gregory.p.smith Date: Tue Mar 31 21:03:28 2009 New Revision: 70864 Log: Rename the actual method definitions to the official assertFoo names. Adds unittests to make sure the old fail* names continue to work now and adds a comment that they are pending deprecation. Also adds a test to confirm that the plural Equals method variants continue to exist even though we're unlikely to deprecate those. http://bugs.python.org/issue2578 Modified: python/trunk/Lib/test/test_unittest.py python/trunk/Lib/unittest.py Modified: python/trunk/Lib/test/test_unittest.py ============================================================================== --- python/trunk/Lib/test/test_unittest.py (original) +++ python/trunk/Lib/test/test_unittest.py Tue Mar 31 21:03:28 2009 @@ -2283,7 +2283,6 @@ 'Tests shortDescription() for a method with a longer ' 'docstring.')) - def testAddTypeEqualityFunc(self): class SadSnake(object): """Dummy class for test_addTypeEqualityFunc.""" @@ -2658,6 +2657,33 @@ self.assertRaisesRegexp, Exception, re.compile('^Expected$'), Stub) + def testSynonymAssertMethodNames(self): + """Test undocumented method name synonyms. + + Please do not use these methods names in your own code. + + This test confirms their continued existence and functionality + in order to avoid breaking existing code. + """ + self.assertNotEquals(3, 5) + self.assertEquals(3, 3) + self.assertAlmostEquals(2.0, 2.0) + self.assertNotAlmostEquals(3.0, 5.0) + self.assert_(True) + + def testPendingDeprecationMethodNames(self): + """Test fail* methods pending deprecation, they will warn in 3.2. + + Do not use these methods. They will go away in 3.3. + """ + self.failIfEqual(3, 5) + self.failUnlessEqual(3, 3) + self.failUnlessAlmostEqual(2.0, 2.0) + self.failIfAlmostEqual(3.0, 5.0) + self.failUnless(True) + self.failUnlessRaises(TypeError, lambda _: 3.14 + u'spam') + self.failIf(False) + class Test_TestSkipping(TestCase): Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Tue Mar 31 21:03:28 2009 @@ -467,17 +467,17 @@ """Fail immediately, with the given message.""" raise self.failureException(msg) - def failIf(self, expr, msg=None): + def assertFalse(self, expr, msg=None): "Fail the test if the expression is true." if expr: raise self.failureException(msg) - def failUnless(self, expr, msg=None): + def assertTrue(self, expr, msg=None): """Fail the test unless the expression is true.""" if not expr: raise self.failureException(msg) - def failUnlessRaises(self, excClass, callableObj=None, *args, **kwargs): + def assertRaises(self, excClass, callableObj=None, *args, **kwargs): """Fail unless an exception of class excClass is thrown by callableObj when invoked with arguments args and keyword arguments kwargs. If a different type of exception is @@ -488,7 +488,7 @@ If called with callableObj omitted or None, will return a context object used like this:: - with self.failUnlessRaises(some_error_class): + with self.assertRaises(some_error_class): do_something() """ context = _AssertRaisesContext(excClass, self) @@ -524,21 +524,21 @@ if not first == second: raise self.failureException(msg or '%r != %r' % (first, second)) - def failUnlessEqual(self, first, second, msg=None): + def assertEqual(self, first, second, msg=None): """Fail if the two objects are unequal as determined by the '==' operator. """ assertion_func = self._getAssertEqualityFunc(first, second) assertion_func(first, second, msg=msg) - def failIfEqual(self, first, second, msg=None): + def assertNotEqual(self, first, second, msg=None): """Fail if the two objects are equal as determined by the '==' operator. """ if first == second: raise self.failureException(msg or '%r == %r' % (first, second)) - def failUnlessAlmostEqual(self, first, second, places=7, msg=None): + def assertAlmostEqual(self, first, second, places=7, msg=None): """Fail if the two objects are unequal as determined by their difference rounded to the given number of decimal places (default 7) and comparing to zero. @@ -550,7 +550,7 @@ raise self.failureException( msg or '%r != %r within %r places' % (first, second, places)) - def failIfAlmostEqual(self, first, second, places=7, msg=None): + def assertNotAlmostEqual(self, first, second, places=7, msg=None): """Fail if the two objects are equal as determined by their difference rounded to the given number of decimal places (default 7) and comparing to zero. @@ -564,19 +564,24 @@ # Synonyms for assertion methods - assertEqual = assertEquals = failUnlessEqual - - assertNotEqual = assertNotEquals = failIfEqual - - assertAlmostEqual = assertAlmostEquals = failUnlessAlmostEqual - - assertNotAlmostEqual = assertNotAlmostEquals = failIfAlmostEqual - - assertRaises = failUnlessRaises - - assert_ = assertTrue = failUnless - - assertFalse = failIf + # The plurals are undocumented. Keep them that way to discourage use. + # Do not add more. Do not remove. + # Going through a deprecation cycle on these would annoy many people. + assertEquals = assertEqual + assertNotEquals = assertNotEqual + assertAlmostEquals = assertAlmostEqual + assertNotAlmostEquals = assertNotAlmostEqual + assert_ = assertTrue + + # These fail* assertion method names are pending deprecation and will + # be a deprecation warning in 3.2; http://bugs.python.org/issue2578 + failUnlessEqual = assertEqual + failIfEqual = assertNotEqual + failUnlessAlmostEqual = assertAlmostEqual + failIfAlmostEqual = assertNotAlmostEqual + failUnless = assertTrue + failUnlessRaises = assertRaises + failIf = assertFalse def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None): From python-checkins at python.org Tue Mar 31 21:06:37 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 21:06:37 +0200 (CEST) Subject: [Python-checkins] r70865 - python/branches/py3k/Doc/reference/datamodel.rst Message-ID: <20090331190637.CD6201E4033@bag.python.org> Author: georg.brandl Date: Tue Mar 31 21:06:37 2009 New Revision: 70865 Log: Add missing label. Modified: python/branches/py3k/Doc/reference/datamodel.rst Modified: python/branches/py3k/Doc/reference/datamodel.rst ============================================================================== --- python/branches/py3k/Doc/reference/datamodel.rst (original) +++ python/branches/py3k/Doc/reference/datamodel.rst Tue Mar 31 21:06:37 2009 @@ -1160,6 +1160,7 @@ The return value must be a string object. +.. _richcmpfuncs: .. method:: object.__lt__(self, other) object.__le__(self, other) object.__eq__(self, other) From python-checkins at python.org Tue Mar 31 21:06:57 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 21:06:57 +0200 (CEST) Subject: [Python-checkins] r70866 - python/trunk/Doc/library/re.rst Message-ID: <20090331190657.4E66C1E4033@bag.python.org> Author: georg.brandl Date: Tue Mar 31 21:06:57 2009 New Revision: 70866 Log: #4882: document named group behavior a bit better. Modified: python/trunk/Doc/library/re.rst Modified: python/trunk/Doc/library/re.rst ============================================================================== --- python/trunk/Doc/library/re.rst (original) +++ python/trunk/Doc/library/re.rst Tue Mar 31 21:06:57 2009 @@ -231,16 +231,18 @@ ``(?P...)`` Similar to regular parentheses, but the substring matched by the group is - accessible via the symbolic group name *name*. Group names must be valid Python - identifiers, and each group name must be defined only once within a regular - expression. A symbolic group is also a numbered group, just as if the group - were not named. So the group named 'id' in the example below can also be - referenced as the numbered group 1. + accessible within the rest of the regular expression via the symbolic group + name *name*. Group names must be valid Python identifiers, and each group + name must be defined only once within a regular expression. A symbolic group + is also a numbered group, just as if the group were not named. So the group + named ``id`` in the example below can also be referenced as the numbered group + ``1``. For example, if the pattern is ``(?P[a-zA-Z_]\w*)``, the group can be referenced by its name in arguments to methods of match objects, such as - ``m.group('id')`` or ``m.end('id')``, and also by name in pattern text (for - example, ``(?P=id)``) and replacement text (such as ``\g``). + ``m.group('id')`` or ``m.end('id')``, and also by name in the regular + expression itself (using ``(?P=id)``) and replacement text given to + ``.sub()`` (using ``\g``). ``(?P=name)`` Matches whatever text was matched by the earlier group named *name*. From python-checkins at python.org Tue Mar 31 21:10:36 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 21:10:36 +0200 (CEST) Subject: [Python-checkins] r70867 - python/trunk/Doc/library/sys.rst Message-ID: <20090331191036.042961E4271@bag.python.org> Author: georg.brandl Date: Tue Mar 31 21:10:35 2009 New Revision: 70867 Log: #1096310: document usage of sys.__std*__ a bit better. Modified: python/trunk/Doc/library/sys.rst Modified: python/trunk/Doc/library/sys.rst ============================================================================== --- python/trunk/Doc/library/sys.rst (original) +++ python/trunk/Doc/library/sys.rst Tue Mar 31 21:10:35 2009 @@ -871,9 +871,14 @@ __stderr__ These objects contain the original values of ``stdin``, ``stderr`` and - ``stdout`` at the start of the program. They are used during finalization, and - could be useful to restore the actual files to known working file objects in - case they have been overwritten with a broken object. + ``stdout`` at the start of the program. They are used during finalization, + and could be useful to print to the actual standard stream no matter if the + ``sys.std*`` object has been redirected. + + It can also be used to restore the actual files to known working file objects + in case they have been overwritten with a broken object. However, the + preferred way to do this is to explicitly save the previous stream before + replacing it, and restore the saved object. .. data:: tracebacklimit From python-checkins at python.org Tue Mar 31 21:12:17 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 21:12:17 +0200 (CEST) Subject: [Python-checkins] r70868 - python/trunk/Lib/optparse.py Message-ID: <20090331191217.5E77C1E4228@bag.python.org> Author: georg.brandl Date: Tue Mar 31 21:12:17 2009 New Revision: 70868 Log: #5190: export make_option in __all__. Modified: python/trunk/Lib/optparse.py Modified: python/trunk/Lib/optparse.py ============================================================================== --- python/trunk/Lib/optparse.py (original) +++ python/trunk/Lib/optparse.py Tue Mar 31 21:12:17 2009 @@ -11,6 +11,7 @@ __version__ = "1.5.3" __all__ = ['Option', + 'make_option', 'SUPPRESS_HELP', 'SUPPRESS_USAGE', 'Values', From python-checkins at python.org Tue Mar 31 21:14:42 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 21:14:42 +0200 (CEST) Subject: [Python-checkins] r70869 - python/trunk/Doc/reference/datamodel.rst Message-ID: <20090331191442.41D371E402A@bag.python.org> Author: georg.brandl Date: Tue Mar 31 21:14:42 2009 New Revision: 70869 Log: Fix-up unwanted change. Modified: python/trunk/Doc/reference/datamodel.rst Modified: python/trunk/Doc/reference/datamodel.rst ============================================================================== --- python/trunk/Doc/reference/datamodel.rst (original) +++ python/trunk/Doc/reference/datamodel.rst Tue Mar 31 21:14:42 2009 @@ -382,7 +382,7 @@ The extension module :mod:`array` provides an additional example of a mutable sequence type. -Set types../ +Set types .. index:: builtin: len object: set type From buildbot at python.org Tue Mar 31 21:19:59 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 19:19:59 +0000 Subject: [Python-checkins] buildbot failure in sparc solaris10 gcc trunk Message-ID: <20090331191959.76D7A1E402A@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%20solaris10%20gcc%20trunk/builds/231 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: loewis-sun Build Reason: The web-page 'force build' button was pressed by 'christian.heimes': test of new autoconf code , The web-page 'force build' button was pressed by 'christian.heimes': another test of mp autoconf Build Source Stamp: [branch branches/multiprocessing-autoconf] HEAD Blamelist: BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_posix ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_posix.py", line 270, in test_getcwd_long_pathnames shutil.rmtree(base_path) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/shutil.py", line 225, in rmtree onerror(os.rmdir, path, sys.exc_info()) File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/shutil.py", line 223, in rmtree os.rmdir(path) OSError: [Errno 22] Invalid argument: '/home2/buildbot/slave/trunk.loewis-sun/build/@test.getcwd/@test.getcwd' ====================================================================== ERROR: test_getcwd_long_pathnames (test.test_posix.PosixTester) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home2/buildbot/slave/trunk.loewis-sun/build/Lib/test/test_posix.py", line 27, in tearDown os.unlink(test_support.TESTFN) OSError: [Errno 2] No such file or directory: '@test' sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 21:26:24 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 21:26:24 +0200 (CEST) Subject: [Python-checkins] r70870 - python/trunk/Doc/library/stdtypes.rst Message-ID: <20090331192624.891171E402A@bag.python.org> Author: georg.brandl Date: Tue Mar 31 21:26:24 2009 New Revision: 70870 Log: #4411: document mro() and __mro__. (I hope I got it right.) Modified: python/trunk/Doc/library/stdtypes.rst Modified: python/trunk/Doc/library/stdtypes.rst ============================================================================== --- python/trunk/Doc/library/stdtypes.rst (original) +++ python/trunk/Doc/library/stdtypes.rst Tue Mar 31 21:26:24 2009 @@ -2675,9 +2675,24 @@ The name of the class or type. +The following attributes are only supported by :term:`new-style class`\ es. + +.. attribute:: class.__mro__ + + This attribute is a tuple of classes that are considered when looking for + base classes during method resolution. + + +.. method:: class.mro() + + This method can be overridden by a metaclass to customize the method + resolution order for its instances. It is called at class instantiation, and + its result is stored in :attr:`__mro__`. + + .. method:: class.__subclasses__ - :term:`New-style class`\ es keep a list of weak references to their immediate + Each new-style class keeps a list of weak references to its immediate subclasses. This method returns a list of all those references still alive. Example:: From python-checkins at python.org Tue Mar 31 21:30:56 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 21:30:56 +0200 (CEST) Subject: [Python-checkins] r70871 - python/trunk/Doc/c-api/structures.rst Message-ID: <20090331193056.6A6401E402A@bag.python.org> Author: georg.brandl Date: Tue Mar 31 21:30:56 2009 New Revision: 70871 Log: #5618: fix typo. Modified: python/trunk/Doc/c-api/structures.rst Modified: python/trunk/Doc/c-api/structures.rst ============================================================================== --- python/trunk/Doc/c-api/structures.rst (original) +++ python/trunk/Doc/c-api/structures.rst Tue Mar 31 21:30:56 2009 @@ -247,7 +247,7 @@ T_OBJECT_EX PyObject \* T_CHAR char T_BYTE char - T_UNBYTE unsigned char + T_UBYTE unsigned char T_UINT unsigned int T_USHORT unsigned short T_ULONG unsigned long From python-checkins at python.org Tue Mar 31 21:31:18 2009 From: python-checkins at python.org (r.david.murray) Date: Tue, 31 Mar 2009 21:31:18 +0200 (CEST) Subject: [Python-checkins] r70872 - python/trunk/Lib/test/README Message-ID: <20090331193118.2565B1E4033@bag.python.org> Author: r.david.murray Date: Tue Mar 31 21:31:17 2009 New Revision: 70872 Log: Delete out-of-date and little-known README from the test directory by consensus of devs at pycon sprint. Removed: python/trunk/Lib/test/README Deleted: python/trunk/Lib/test/README ============================================================================== --- python/trunk/Lib/test/README Tue Mar 31 21:31:17 2009 +++ (empty file) @@ -1,413 +0,0 @@ -+++++++++++++++++++++++++++++++ -Writing Python Regression Tests -+++++++++++++++++++++++++++++++ - -:Author: Skip Montanaro -:Contact: skip at pobox.com - -Introduction -============ - -If you add a new module to Python or modify the functionality of an existing -module, you should write one or more test cases to exercise that new -functionality. There are different ways to do this within the regression -testing facility provided with Python; any particular test should use only -one of these options. Each option requires writing a test module using the -conventions of the selected option: - - - unittest_ based tests - - doctest_ based tests - - "traditional" Python test modules - -Regardless of the mechanics of the testing approach you choose, -you will be writing unit tests (isolated tests of functions and objects -defined by the module) using white box techniques. Unlike black box -testing, where you only have the external interfaces to guide your test case -writing, in white box testing you can see the code being tested and tailor -your test cases to exercise it more completely. In particular, you will be -able to refer to the C and Python code in the CVS repository when writing -your regression test cases. - -.. _unittest: http://www.python.org/doc/current/lib/module-unittest.html -.. _doctest: http://www.python.org/doc/current/lib/module-doctest.html - -unittest-based tests ------------------- -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 unittest-based 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. - -All test methods in the Python regression framework have names that -start with "``test_``" and use lower-case names with words separated with -underscores. - -Test methods should *not* have docstrings! The unittest module prints -the docstring if there is one, but otherwise prints the function name -and the full class name. When there's a problem with a test, the -latter information makes it easier to find the source for the test -than the docstring. - -All unittest-based tests in the Python test suite use boilerplate that -looks like this (with minor variations):: - - import unittest - from test import test_support - - class MyTestCase1(unittest.TestCase): - - # Define setUp and tearDown only if needed - - def setUp(self): - unittest.TestCase.setUp(self) - ... additional initialization... - - def tearDown(self): - ... additional finalization... - unittest.TestCase.tearDown(self) - - def test_feature_one(self): - # Testing feature one - ...unit test for feature one... - - def test_feature_two(self): - # Testing feature two - ...unit test for feature two... - - ...etc... - - class MyTestCase2(unittest.TestCase): - ...same structure as MyTestCase1... - - ...etc... - - def test_main(): - test_support.run_unittest(__name__) - - if __name__ == "__main__": - test_main() - -This has the advantage that it allows the unittest module to be used -as a script to run individual tests as well as working well with the -regrtest framework. - -.. _Extreme Programming: http://www.extremeprogramming.org/ -.. _JUnit: http://www.junit.org/ - -doctest based tests -------------------- -Tests written to use doctest_ are actually part of the docstrings for -the module being tested. Each test is written as a display of an -interactive session, including the Python prompts, statements that would -be typed by the user, and the output of those statements (including -tracebacks, although only the exception msg needs to be retained then). -The module in the test package is simply a wrapper that causes doctest -to run over the tests in the module. The test for the difflib module -provides a convenient example:: - - import difflib - from test import test_support - test_support.run_doctest(difflib) - -If the test is successful, nothing is written to stdout (so you should not -create a corresponding output/test_difflib file), but running regrtest -with -v will give a detailed report, the same as if passing -v to doctest. - -A second argument can be passed to run_doctest to tell doctest to search -``sys.argv`` for -v instead of using test_support's idea of verbosity. This -is useful for writing doctest-based tests that aren't simply running a -doctest'ed Lib module, but contain the doctests themselves. Then at -times you may want to run such a test directly as a doctest, independent -of the regrtest framework. The tail end of test_descrtut.py is a good -example:: - - def test_main(verbose=None): - from test import test_support, test_descrtut - test_support.run_doctest(test_descrtut, verbose) - - if __name__ == "__main__": - test_main(1) - -If run via regrtest, ``test_main()`` is called (by regrtest) without -specifying verbose, and then test_support's idea of verbosity is used. But -when run directly, ``test_main(1)`` is called, and then doctest's idea of -verbosity is used. - -See the documentation for the doctest module for information on -writing tests using the doctest framework. - -"traditional" Python test modules ---------------------------------- -The mechanics of how the "traditional" test system operates are fairly -straightforward. When a test case is run, the output is compared with the -expected output that is stored in .../Lib/test/output. If the test runs to -completion and the actual and expected outputs match, the test succeeds, if -not, it fails. If an ``ImportError`` or ``test_support.TestSkipped`` error -is raised, the test is not run. - -Executing Test Cases -==================== -If you are writing test cases for module spam, you need to create a file -in .../Lib/test named test_spam.py. In addition, if the tests are expected -to write to stdout during a successful run, you also need to create an -expected output file in .../Lib/test/output named test_spam ("..." -represents the top-level directory in the Python source tree, the directory -containing the configure script). If needed, generate the initial version -of the test output file by executing:: - - ./python Lib/test/regrtest.py -g test_spam.py - -from the top-level directory. - -Any time you modify test_spam.py you need to generate a new expected -output file. Don't forget to desk check the generated output to make sure -it's really what you expected to find! All in all it's usually better -not to have an expected-out file (note that doctest- and unittest-based -tests do not). - -To run a single test after modifying a module, simply run regrtest.py -without the -g flag:: - - ./python Lib/test/regrtest.py test_spam.py - -While debugging a regression test, you can of course execute it -independently of the regression testing framework and see what it prints:: - - ./python Lib/test/test_spam.py - -To run the entire test suite: - -- [UNIX, + other platforms where "make" works] Make the "test" target at the - top level:: - - make test - -- [WINDOWS] Run rt.bat from your PCBuild directory. Read the comments at - the top of rt.bat for the use of special -d, -O and -q options processed - by rt.bat. - -- [OTHER] You can simply execute the two runs of regrtest (optimized and - non-optimized) directly:: - - ./python Lib/test/regrtest.py - ./python -O Lib/test/regrtest.py - -But note that this way picks up whatever .pyc and .pyo files happen to be -around. The makefile and rt.bat ways run the tests twice, the first time -removing all .pyc and .pyo files from the subtree rooted at Lib/. - -Test cases generate output based upon values computed by the test code. -When executed, regrtest.py compares the actual output generated by executing -the test case with the expected output and reports success or failure. It -stands to reason that if the actual and expected outputs are to match, they -must not contain any machine dependencies. This means your test cases -should not print out absolute machine addresses (e.g. the return value of -the id() builtin function) or floating point numbers with large numbers of -significant digits (unless you understand what you are doing!). - - -Test Case Writing Tips -====================== -Writing good test cases is a skilled task and is too complex to discuss in -detail in this short document. Many books have been written on the subject. -I'll show my age by suggesting that Glenford Myers' `"The Art of Software -Testing"`_, published in 1979, is still the best introduction to the subject -available. It is short (177 pages), easy to read, and discusses the major -elements of software testing, though its publication predates the -object-oriented software revolution, so doesn't cover that subject at all. -Unfortunately, it is very expensive (about $100 new). If you can borrow it -or find it used (around $20), I strongly urge you to pick up a copy. - -The most important goal when writing test cases is to break things. A test -case that doesn't uncover a bug is much less valuable than one that does. -In designing test cases you should pay attention to the following: - - * Your test cases should exercise all the functions and objects defined - in the module, not just the ones meant to be called by users of your - module. This may require you to write test code that uses the module - in ways you don't expect (explicitly calling internal functions, for - example - see test_atexit.py). - - * You should consider any boundary values that may tickle exceptional - conditions (e.g. if you were writing regression tests for division, - you might well want to generate tests with numerators and denominators - at the limits of floating point and integer numbers on the machine - performing the tests as well as a denominator of zero). - - * You should exercise as many paths through the code as possible. This - may not always be possible, but is a goal to strive for. In - particular, when considering if statements (or their equivalent), you - want to create test cases that exercise both the true and false - branches. For loops, you should create test cases that exercise the - loop zero, one and multiple times. - - * You should test with obviously invalid input. If you know that a - function requires an integer input, try calling it with other types of - objects to see how it responds. - - * You should test with obviously out-of-range input. If the domain of a - function is only defined for positive integers, try calling it with a - negative integer. - - * If you are going to fix a bug that wasn't uncovered by an existing - test, try to write a test case that exposes the bug (preferably before - fixing it). - - * If you need to create a temporary file, you can use the filename in - ``test_support.TESTFN`` to do so. It is important to remove the file - when done; other tests should be able to use the name without cleaning - up after your test. - -.. _"The Art of Software Testing": - http://www.amazon.com/exec/obidos/ISBN=0471043281 - -Regression Test Writing Rules -============================= -Each test case is different. There is no "standard" form for a Python -regression test case, though there are some general rules (note that -these mostly apply only to the "classic" tests; unittest_- and doctest_- -based tests should follow the conventions natural to those frameworks):: - - * If your test case detects a failure, raise ``TestFailed`` (found in - ``test.test_support``). - - * Import everything you'll need as early as possible. - - * If you'll be importing objects from a module that is at least - partially platform-dependent, only import those objects you need for - the current test case to avoid spurious ``ImportError`` exceptions - that prevent the test from running to completion. - - * Print all your test case results using the ``print`` statement. For - non-fatal errors, print an error message (or omit a successful - completion print) to indicate the failure, but proceed instead of - raising ``TestFailed``. - - * Use ``assert`` sparingly, if at all. It's usually better to just print - what you got, and rely on regrtest's got-vs-expected comparison to - catch deviations from what you expect. ``assert`` statements aren't - executed at all when regrtest is run in -O mode; and, because they - cause the test to stop immediately, can lead to a long & tedious - test-fix, test-fix, test-fix, ... cycle when things are badly broken - (and note that "badly broken" often includes running the test suite - for the first time on new platforms or under new implementations of - the language). - -Miscellaneous -============= -There is a test_support module in the test package you can import for -your test case. Import this module using either:: - - import test.test_support - -or:: - - from test import test_support - -test_support provides the following useful objects: - - * ``TestFailed`` - raise this exception when your regression test detects - a failure. - - * ``TestSkipped`` - raise this if the test could not be run because the - platform doesn't offer all the required facilities (like large - file support), even if all the required modules are available. - - * ``ResourceDenied`` - this is raised when a test requires a resource that - is not available. Primarily used by 'requires'. - - * ``verbose`` - you can use this variable to control print output. Many - modules use it. Search for "verbose" in the test_*.py files to see - lots of examples. - - * ``forget(module_name)`` - attempts to cause Python to "forget" that it - loaded a module and erase any PYC files. - - * ``is_resource_enabled(resource)`` - Returns a boolean based on whether - the resource is enabled or not. - - * ``requires(resource [, msg])`` - if the required resource is not - available the ResourceDenied exception is raised. - - * ``verify(condition, reason='test failed')``. Use this instead of:: - - assert condition[, reason] - - ``verify()`` has two advantages over ``assert``: it works even in -O - mode, and it raises ``TestFailed`` on failure instead of - ``AssertionError``. - - * ``have_unicode`` - true if Unicode is available, false otherwise. - - * ``is_jython`` - true if the interpreter is Jython, false otherwise. - - * ``TESTFN`` - a string that should always be used as the filename when - you need to create a temp file. Also use ``try``/``finally`` to - ensure that your temp files are deleted before your test completes. - Note that you cannot unlink an open file on all operating systems, so - also be sure to close temp files before trying to unlink them. - - * ``sortdict(dict)`` - acts like ``repr(dict.items())``, but sorts the - items first. This is important when printing a dict value, because - the order of items produced by ``dict.items()`` is not defined by the - language. - - * ``findfile(file)`` - you can call this function to locate a file - somewhere along sys.path or in the Lib/test tree - see - test_linuxaudiodev.py for an example of its use. - - * ``fcmp(x,y)`` - you can call this function to compare two floating - point numbers when you expect them to only be approximately equal - withing a fuzz factor (``test_support.FUZZ``, which defaults to 1e-6). - - * ``check_syntax_error(testcase, statement)`` - make sure that the - statement is *not* correct Python syntax. - - -Some Non-Obvious regrtest Features -================================== - * Automagic test detection: When you create a new test file - test_spam.py, you do not need to modify regrtest (or anything else) - to advertise its existence. regrtest searches for and runs all - modules in the test directory with names of the form test_xxx.py. - - * Miranda output: If, when running test_spam.py, regrtest does not - find an expected-output file test/output/test_spam, regrtest - pretends that it did find one, containing the single line - - test_spam - - This allows new tests that don't expect to print anything to stdout - to not bother creating expected-output files. - - * Two-stage testing: To run test_spam.py, regrtest imports test_spam - as a module. Most tests run to completion as a side-effect of - getting imported. After importing test_spam, regrtest also executes - ``test_spam.test_main()``, if test_spam has a ``test_main`` attribute. - 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 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 - with the unittest.py-as-a-script approach, allowing a developer - to run specific tests from the command line. From python-checkins at python.org Tue Mar 31 21:32:35 2009 From: python-checkins at python.org (josiah.carlson) Date: Tue, 31 Mar 2009 21:32:35 +0200 (CEST) Subject: [Python-checkins] r70873 - python/trunk/Lib/asyncore.py Message-ID: <20090331193235.0E80D1E402A@bag.python.org> Author: josiah.carlson Date: Tue Mar 31 21:32:34 2009 New Revision: 70873 Log: This resolves issue 1161031. Tests pass. Modified: python/trunk/Lib/asyncore.py Modified: python/trunk/Lib/asyncore.py ============================================================================== --- python/trunk/Lib/asyncore.py (original) +++ python/trunk/Lib/asyncore.py Tue Mar 31 21:32:34 2009 @@ -69,10 +69,12 @@ class ExitNow(Exception): pass +_reraised_exceptions = (ExitNow, KeyboardInterrupt, SystemExit) + def read(obj): try: obj.handle_read_event() - except (ExitNow, KeyboardInterrupt, SystemExit): + except _reraised_exceptions: raise except: obj.handle_error() @@ -80,7 +82,7 @@ def write(obj): try: obj.handle_write_event() - except (ExitNow, KeyboardInterrupt, SystemExit): + except _reraised_exceptions: raise except: obj.handle_error() @@ -88,22 +90,22 @@ def _exception(obj): try: obj.handle_expt_event() - except (ExitNow, KeyboardInterrupt, SystemExit): + except _reraised_exceptions: raise except: obj.handle_error() def readwrite(obj, flags): try: - if flags & (select.POLLIN | select.POLLPRI): + if flags & select.POLLPRI: + obj.handle_expt_event() + if flags & select.POLLIN: obj.handle_read_event() if flags & select.POLLOUT: obj.handle_write_event() - if flags & (select.POLLERR | select.POLLNVAL): - obj.handle_expt_event() - if flags & select.POLLHUP: + if flags & (select.POLLHUP | select.POLLERR | select.POLLNVAL): obj.handle_close() - except (ExitNow, KeyboardInterrupt, SystemExit): + except _reraised_exceptions: raise except: obj.handle_error() @@ -211,6 +213,7 @@ accepting = False closing = False addr = None + ignore_log_types = frozenset(['warning']) def __init__(self, sock=None, map=None): if map is None: @@ -398,7 +401,7 @@ sys.stderr.write('log: %s\n' % str(message)) def log_info(self, message, type='info'): - if __debug__ or type != 'info': + if __debug__ or type not in self.ignore_log_types: print '%s: %s' % (type, message) def handle_read_event(self): @@ -432,22 +435,17 @@ self.handle_write() def handle_expt_event(self): - # if the handle_expt is the same default worthless method, - # we'll not even bother calling it, we'll instead generate - # a useful error - x = True - try: - y1 = self.__class__.handle_expt.im_func - y2 = dispatcher.handle_expt.im_func - x = y1 is y2 - except AttributeError: - pass - - if x: - err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) - msg = _strerror(err) - - raise socket.error(err, msg) + # handle_expt_event() is called if there might be an error on the + # socket, or if there is OOB data + # check for the error condition first + err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) + if err != 0: + # we can get here when select.select() says that there is an + # exceptional condition on the socket + # since there is an error, we'll go ahead and close the socket + # like we would in a subclassed handle_read() that received no + # data + self.handle_close() else: self.handle_expt() @@ -472,7 +470,7 @@ self.handle_close() def handle_expt(self): - self.log_info('unhandled exception', 'warning') + self.log_info('unhandled incoming priority event', 'warning') def handle_read(self): self.log_info('unhandled read event', 'warning') @@ -553,7 +551,7 @@ pass elif not ignore_all: raise - except (ExitNow, KeyboardInterrupt, SystemExit): + except _reraised_exceptions: raise except: if not ignore_all: From python-checkins at python.org Tue Mar 31 21:33:15 2009 From: python-checkins at python.org (r.david.murray) Date: Tue, 31 Mar 2009 21:33:15 +0200 (CEST) Subject: [Python-checkins] r70874 - python/trunk/Lib/test/test_support.py Message-ID: <20090331193315.C1DE11E42B0@bag.python.org> Author: r.david.murray Date: Tue Mar 31 21:33:15 2009 New Revision: 70874 Log: Improve test_support.import_module docstring, remove deprecated flag from get_attribute since it isn't likely to do anything useful. Modified: python/trunk/Lib/test/test_support.py Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Tue Mar 31 21:33:15 2009 @@ -43,8 +43,11 @@ """ def import_module(name, deprecated=False): - """Import the module to be tested, raising SkipTest if it is not - available.""" + """Import and return the module to be tested, raising SkipTest if + it is not available. + + If deprecated is True, any module or package deprecation messages + will be suppressed.""" with warnings.catch_warnings(): if deprecated: warnings.filterwarnings("ignore", ".+ (module|package)", @@ -56,20 +59,15 @@ else: return module -def get_attribute(module, name, deprecated=False): - """Get an attribute from the module, raising SkipTest if it is - not available.""" - with warnings.catch_warnings(): - if deprecated: - warnings.filterwarnings("ignore", ".+ (module|package)", - DeprecationWarning) - try: - attribute = getattr(module, name) - except AttributeError: - raise unittest.SkipTest("module %s has no attribute %s" % ( - module.__name__, name)) - else: - return attribute +def get_attribute(obj, name): + """Get an attribute, raising SkipTest if AttributeError is raised.""" + try: + attribute = getattr(obj, name) + except AttributeError: + raise unittest.SkipTest("module %s has no attribute %s" % ( + obj.__name__, name)) + else: + return attribute verbose = 1 # Flag set to 0 by regrtest.py From python-checkins at python.org Tue Mar 31 21:44:42 2009 From: python-checkins at python.org (eric.smith) Date: Tue, 31 Mar 2009 21:44:42 +0200 (CEST) Subject: [Python-checkins] r70875 - python/branches/py3k-short-float-repr/Python/pystrtod.c Message-ID: <20090331194442.F1AB31E4033@bag.python.org> Author: eric.smith Date: Tue Mar 31 21:44:42 2009 New Revision: 70875 Log: Take into account the mode when deciding to switch to exponential notiation. This fixes the complex tests. Add alt formatting, specifically for padding. Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/pystrtod.c (original) +++ python/branches/py3k-short-float-repr/Python/pystrtod.c Tue Mar 31 21:44:42 2009 @@ -524,7 +524,10 @@ number of significant digits. */ static void -format_float_short(char *buf, size_t buflen, double d, char format_code, int mode, int precision, int always_add_sign, int add_dot_0_if_integer, char **float_strings) +format_float_short(char *buf, size_t buflen, double d, char format_code, + int mode, int precision, int always_add_sign, + int add_dot_0_if_integer, int use_alt_formatting, + char **float_strings) { char *digits, *digits_end; int decpt, sign, exp_len; @@ -586,7 +589,7 @@ case 'g': { int min_decpt = -4; - if (decpt > precision || decpt < min_decpt) + if ((mode != 0) && (decpt > precision || decpt < min_decpt)) use_exp = 1; else use_exp = 0; @@ -638,8 +641,17 @@ } } - /* Add trailing non-significant zeros for non-mode 0 and non-code g */ - if (mode != 0 && format_code != 'g') { + /* Add trailing non-significant zeros for non-mode 0 and non-code g, unless doing alt formatting */ + int pad = 0; + if (mode != 0) + if (format_code == 'g') { + if (use_alt_formatting) + pad = 1; + } + else + pad = 1; + + if (pad) { Py_ssize_t nzeros = precision - digits_len; /* It should never be the case that nzeros is negative, but @@ -709,7 +721,7 @@ /* XXX validate format_code */ - format_float_short(buf, 512, val, lc_format_code, mode, precision, flags & Py_DTSF_SIGN, flags & Py_DTSF_ADD_DOT_0, float_strings); + format_float_short(buf, 512, val, lc_format_code, mode, precision, flags & Py_DTSF_SIGN, flags & Py_DTSF_ADD_DOT_0, flags & Py_DTSF_ALT, float_strings); return buf; } From python-checkins at python.org Tue Mar 31 21:49:15 2009 From: python-checkins at python.org (r.david.murray) Date: Tue, 31 Mar 2009 21:49:15 +0200 (CEST) Subject: [Python-checkins] r70876 - python/trunk/Lib/test/regrtest.py Message-ID: <20090331194916.0007A1E4033@bag.python.org> Author: r.david.murray Date: Tue Mar 31 21:49:15 2009 New Revision: 70876 Log: Remove the regrtest check that turns any ImportError into a skipped test. Hopefully all modules whose imports legitimately result in a skipped test have been properly wrapped by the previous commits. Modified: python/trunk/Lib/test/regrtest.py Modified: python/trunk/Lib/test/regrtest.py ============================================================================== --- python/trunk/Lib/test/regrtest.py (original) +++ python/trunk/Lib/test/regrtest.py Tue Mar 31 21:49:15 2009 @@ -580,7 +580,7 @@ print test, "skipped --", msg sys.stdout.flush() return -2 - except (ImportError, unittest.SkipTest), msg: + except unittest.SkipTest, msg: if not quiet: print test, "skipped --", msg sys.stdout.flush() From python-checkins at python.org Tue Mar 31 21:57:24 2009 From: python-checkins at python.org (r.david.murray) Date: Tue, 31 Mar 2009 21:57:24 +0200 (CEST) Subject: [Python-checkins] r70877 - python/trunk/Misc/NEWS Message-ID: <20090331195724.AE96C1E40CE@bag.python.org> Author: r.david.murray Date: Tue Mar 31 21:57:24 2009 New Revision: 70877 Log: Add NEWS entry for regrtest change. Modified: python/trunk/Misc/NEWS Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 31 21:57:24 2009 @@ -704,6 +704,10 @@ Tests ----- +- regrtest no longer treats ImportError as equivalent to SkipTest. Imports + that should cause a test to be skipped are now done using import_module + from test support, which does the conversion. + - Issue #5083: New 'gui' resource for regrtest. From buildbot at python.org Tue Mar 31 21:57:27 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 19:57:27 +0000 Subject: [Python-checkins] buildbot failure in x86 osx.5 trunk Message-ID: <20090331195727.AE4751E40D8@bag.python.org> The Buildbot has detected a new failure of x86 osx.5 trunk. Full details are available at: http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/808 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: heller-x86-osx5 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl,gregory.p.smith BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_bz2 make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 21:59:14 2009 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 31 Mar 2009 21:59:14 +0200 (CEST) Subject: [Python-checkins] r70878 - in python/trunk: Doc/library/unittest.rst Lib/unittest.py Message-ID: <20090331195914.B25EA1E40D2@bag.python.org> Author: gregory.p.smith Date: Tue Mar 31 21:59:14 2009 New Revision: 70878 Log: Issue an actual PendingDeprecationWarning for the TestCase.fail* methods. Document the deprecation. Modified: python/trunk/Doc/library/unittest.rst python/trunk/Lib/unittest.py Modified: python/trunk/Doc/library/unittest.rst ============================================================================== --- python/trunk/Doc/library/unittest.rst (original) +++ python/trunk/Doc/library/unittest.rst Tue Mar 31 21:59:14 2009 @@ -613,6 +613,9 @@ Signal a test failure if *expr* is false; the explanation for the error will be *msg* if given, otherwise it will be :const:`None`. + .. deprecated:: 2.7 + :meth:`failUnless`. + .. method:: assertEqual(first, second[, msg]) failUnlessEqual(first, second[, msg]) @@ -632,6 +635,9 @@ .. versionchanged:: 2.7 Added the automatic calling of type specific equality function. + .. deprecated:: 2.7 + :meth:`failUnlessEqual`. + .. method:: assertNotEqual(first, second[, msg]) failIfEqual(first, second[, msg]) @@ -643,6 +649,9 @@ default value for *msg* can be computed to include representations of both *first* and *second*. + .. deprecated:: 2.7 + :meth:`failIfEqual`. + .. method:: assertAlmostEqual(first, second[, places[, msg]]) failUnlessAlmostEqual(first, second[, places[, msg]]) @@ -656,6 +665,9 @@ compare equal, the test will fail with the explanation given by *msg*, or :const:`None`. + .. deprecated:: 2.7 + :meth:`failUnlessAlmostEqual`. + .. method:: assertNotAlmostEqual(first, second[, places[, msg]]) failIfAlmostEqual(first, second[, places[, msg]]) @@ -669,6 +681,9 @@ compare equal, the test will fail with the explanation given by *msg*, or :const:`None`. + .. deprecated:: 2.7 + :meth:`failIfAlmostEqual`. + .. method:: assertGreater(first, second, msg=None) assertGreaterEqual(first, second, msg=None) @@ -808,6 +823,9 @@ .. versionchanged:: 2.7 Added the ability to use :meth:`assertRaises` as a context manager. + .. deprecated:: 2.7 + :meth:`failUnlessRaises`. + .. method:: assertRaisesRegexp(exception, regexp[, callable, ...]) @@ -849,6 +867,9 @@ This signals a test failure if *expr* is true, with *msg* or :const:`None` for the error message. + .. deprecated:: 2.7 + :meth:`failIf`. + .. method:: fail([msg]) Modified: python/trunk/Lib/unittest.py ============================================================================== --- python/trunk/Lib/unittest.py (original) +++ python/trunk/Lib/unittest.py Tue Mar 31 21:59:14 2009 @@ -54,6 +54,7 @@ import time import traceback import types +import warnings ############################################################################## # Exported classes and functions @@ -574,15 +575,22 @@ assert_ = assertTrue # These fail* assertion method names are pending deprecation and will - # be a deprecation warning in 3.2; http://bugs.python.org/issue2578 - failUnlessEqual = assertEqual - failIfEqual = assertNotEqual - failUnlessAlmostEqual = assertAlmostEqual - failIfAlmostEqual = assertNotAlmostEqual - failUnless = assertTrue - failUnlessRaises = assertRaises - failIf = assertFalse - + # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578 + def __deprecate(original_func): + def deprecated_func(*args, **kwargs): + warnings.warn( + 'Please use {0} instead.'.format(original_func.__name__), + PendingDeprecationWarning, 2) + return original_func(*args, **kwargs) + return deprecated_func + + failUnlessEqual = __deprecate(assertEqual) + failIfEqual = __deprecate(assertNotEqual) + failUnlessAlmostEqual = __deprecate(assertAlmostEqual) + failIfAlmostEqual = __deprecate(assertNotAlmostEqual) + failUnless = __deprecate(assertTrue) + failUnlessRaises = __deprecate(assertRaises) + failIf = __deprecate(assertFalse) def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None): """An equality assertion for ordered sequences (like lists and tuples). From buildbot at python.org Tue Mar 31 22:11:50 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 20:11:50 +0000 Subject: [Python-checkins] buildbot failure in ppc Debian unstable 2.6 Message-ID: <20090331201150.320E41E40CE@bag.python.org> The Buildbot has detected a new failure of ppc Debian unstable 2.6. Full details are available at: http://www.python.org/dev/buildbot/all/ppc%20Debian%20unstable%202.6/builds/199 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ppc Build Reason: Build Source Stamp: [branch branches/release26-maint] HEAD Blamelist: jesse.noller BUILD FAILED: failed test Excerpt from the test logfile: sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 22:14:04 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 31 Mar 2009 22:14:04 +0200 (CEST) Subject: [Python-checkins] r70879 - in python/trunk: Lib/test/test_mmap.py Modules/mmapmodule.c Message-ID: <20090331201404.8FED71E4054@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 31 22:14:04 2009 New Revision: 70879 Log: Issue #5387: Fixed mmap.move crash by integer overflow. (take2) Modified: python/trunk/Lib/test/test_mmap.py python/trunk/Modules/mmapmodule.c Modified: python/trunk/Lib/test/test_mmap.py ============================================================================== --- python/trunk/Lib/test/test_mmap.py (original) +++ python/trunk/Lib/test/test_mmap.py Tue Mar 31 22:14:04 2009 @@ -1,6 +1,6 @@ from test.test_support import TESTFN, run_unittest, import_module import unittest -import os, re +import os, re, itertools mmap = import_module('mmap') @@ -351,9 +351,21 @@ self.assertEqual(m[:], expected) m.close() - # should not crash - m = mmap.mmap(-1, 1) - self.assertRaises(ValueError, m.move, 1, 1, -1) + # segfault test (Issue 5387) + m = mmap.mmap(-1, 100) + offsets = [-100, -1, 0, 1, 100] + for source, dest, size in itertools.product(offsets, offsets, offsets): + try: + m.move(source, dest, size) + except ValueError: + pass + self.assertRaises(ValueError, m.move, -1, -1, -1) + self.assertRaises(ValueError, m.move, -1, -1, 0) + self.assertRaises(ValueError, m.move, -1, 0, -1) + self.assertRaises(ValueError, m.move, 0, -1, -1) + self.assertRaises(ValueError, m.move, -1, 0, 0) + self.assertRaises(ValueError, m.move, 0, -1, 0) + self.assertRaises(ValueError, m.move, 0, 0, -1) m.close() def test_anonymous(self): Modified: python/trunk/Modules/mmapmodule.c ============================================================================== --- python/trunk/Modules/mmapmodule.c (original) +++ python/trunk/Modules/mmapmodule.c Tue Mar 31 22:14:04 2009 @@ -617,7 +617,7 @@ } else { /* bounds check the values */ unsigned long pos = src > dest ? src : dest; - if (self->size >= pos && count > self->size - pos) { + if (self->size < pos || count > self->size - pos) { PyErr_SetString(PyExc_ValueError, "source or destination out of range"); return NULL; From jackdied at gmail.com Tue Mar 31 22:20:55 2009 From: jackdied at gmail.com (Jack diederich) Date: Tue, 31 Mar 2009 16:20:55 -0400 Subject: [Python-checkins] r70879 - in python/trunk: Lib/test/test_mmap.py Modules/mmapmodule.c In-Reply-To: <20090331201404.8FED71E4054@bag.python.org> References: <20090331201404.8FED71E4054@bag.python.org> Message-ID: FYI, PEP-8 Imports should usually be on separate lines, e.g.: Yes: import os import sys No: import sys, os On Tue, Mar 31, 2009 at 4:14 PM, hirokazu.yamamoto wrote: > Author: hirokazu.yamamoto > Date: Tue Mar 31 22:14:04 2009 > New Revision: 70879 > > Log: > Issue #5387: Fixed mmap.move crash by integer overflow. (take2) > > Modified: > ? python/trunk/Lib/test/test_mmap.py > ? python/trunk/Modules/mmapmodule.c > > Modified: python/trunk/Lib/test/test_mmap.py > ============================================================================== > --- python/trunk/Lib/test/test_mmap.py ?(original) > +++ python/trunk/Lib/test/test_mmap.py ?Tue Mar 31 22:14:04 2009 > @@ -1,6 +1,6 @@ > ?from test.test_support import TESTFN, run_unittest, import_module > ?import unittest > -import os, re > +import os, re, itertools > > ?mmap = import_module('mmap') > > @@ -351,9 +351,21 @@ > ? ? ? ? ? ? ? ? ? ? self.assertEqual(m[:], expected) > ? ? ? ? ? ? ? ? ? ? m.close() > > - ? ? ? ?# should not crash > - ? ? ? ?m = mmap.mmap(-1, 1) > - ? ? ? ?self.assertRaises(ValueError, m.move, 1, 1, -1) > + ? ? ? ?# segfault test (Issue 5387) > + ? ? ? ?m = mmap.mmap(-1, 100) > + ? ? ? ?offsets = [-100, -1, 0, 1, 100] > + ? ? ? ?for source, dest, size in itertools.product(offsets, offsets, offsets): > + ? ? ? ? ? ?try: > + ? ? ? ? ? ? ? ?m.move(source, dest, size) > + ? ? ? ? ? ?except ValueError: > + ? ? ? ? ? ? ? ?pass > + ? ? ? ?self.assertRaises(ValueError, m.move, -1, -1, -1) > + ? ? ? ?self.assertRaises(ValueError, m.move, -1, -1, 0) > + ? ? ? ?self.assertRaises(ValueError, m.move, -1, 0, -1) > + ? ? ? ?self.assertRaises(ValueError, m.move, 0, -1, -1) > + ? ? ? ?self.assertRaises(ValueError, m.move, -1, 0, 0) > + ? ? ? ?self.assertRaises(ValueError, m.move, 0, -1, 0) > + ? ? ? ?self.assertRaises(ValueError, m.move, 0, 0, -1) > ? ? ? ? m.close() > > ? ? def test_anonymous(self): > > Modified: python/trunk/Modules/mmapmodule.c > ============================================================================== > --- python/trunk/Modules/mmapmodule.c ? (original) > +++ python/trunk/Modules/mmapmodule.c ? Tue Mar 31 22:14:04 2009 > @@ -617,7 +617,7 @@ > ? ? ? ?} else { > ? ? ? ? ? ? ? ?/* bounds check the values */ > ? ? ? ? ? ? ? ?unsigned long pos = src > dest ? src : dest; > - ? ? ? ? ? ? ? if (self->size >= pos && count > self->size - pos) { > + ? ? ? ? ? ? ? if (self->size < pos || count > self->size - pos) { > ? ? ? ? ? ? ? ? ? ? ? ?PyErr_SetString(PyExc_ValueError, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"source or destination out of range"); > ? ? ? ? ? ? ? ? ? ? ? ?return NULL; > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > From python-checkins at python.org Tue Mar 31 22:21:51 2009 From: python-checkins at python.org (eric.smith) Date: Tue, 31 Mar 2009 22:21:51 +0200 (CEST) Subject: [Python-checkins] r70880 - python/branches/py3k-short-float-repr/Python/pystrtod.c Message-ID: <20090331202151.CF2F11E407C@bag.python.org> Author: eric.smith Date: Tue Mar 31 22:21:51 2009 New Revision: 70880 Log: Fixed more tests by adding back in the 'add .0 if the output looks like an integer' flag. Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/pystrtod.c (original) +++ python/branches/py3k-short-float-repr/Python/pystrtod.c Tue Mar 31 22:21:51 2009 @@ -529,10 +529,12 @@ int add_dot_0_if_integer, int use_alt_formatting, char **float_strings) { + char *start = buf; char *digits, *digits_end; int decpt, sign, exp_len; Py_ssize_t digits_len, i; int use_exp = 0; + int is_integer = 1; /* is the output produced so far just an integer? */ /* _Py_dg_dtoa returns a digit string (no decimal point or exponent) */ @@ -609,6 +611,7 @@ at least 2 digits in exponent */ *buf++ = digits[0]; *buf++ = '.'; + is_integer = 0; strncpy(buf, digits+1, digits_len-1); buf += digits_len-1; @@ -618,6 +621,7 @@ /* output: 0.00...00dd...dd */ *buf++ = '0'; *buf++ = '.'; + is_integer = 0; for (i = 0; i < -decpt; i++) *buf++ = '0'; strncpy(buf, digits, digits_len); @@ -628,6 +632,7 @@ strncpy(buf, digits, decpt); buf += decpt; *buf++ = '.'; + is_integer = 0; strncpy(buf, digits+decpt, digits_len-decpt); buf += digits_len-decpt; } @@ -638,18 +643,20 @@ for (i = 0; i < decpt-digits_len; i++) *buf++ = '0'; *buf++ = '.'; + is_integer = 0; } } /* Add trailing non-significant zeros for non-mode 0 and non-code g, unless doing alt formatting */ int pad = 0; - if (mode != 0) + if (mode != 0) { if (format_code == 'g') { if (use_alt_formatting) pad = 1; } else pad = 1; + } if (pad) { Py_ssize_t nzeros = precision - digits_len; @@ -663,14 +670,23 @@ } /* See if we want to have the trailing decimal or not */ - if (format_code == 'g' && buf[-1] == '.') + if (format_code == 'g' && buf[-1] == '.') { buf--; + is_integer = 1; /* XXX not sure if this is correct, should probably change this to detect this case and not add it to begin with */ + } /* Now that we've done zero padding, add an exponent if needed. */ if (use_exp) { *buf++ = float_strings[OFS_E][0]; exp_len = sprintf(buf, "%+.02d", decpt-1); buf += exp_len; + is_integer = 0; + } + + /* Add ".0" if we're an integer? */ + if (add_dot_0_if_integer && is_integer) { + *buf++ = '.'; + *buf++ = '0'; } *buf++ = '\0'; From python-checkins at python.org Tue Mar 31 22:22:13 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 31 Mar 2009 22:22:13 +0200 (CEST) Subject: [Python-checkins] r70881 - in python/branches/release26-maint: Lib/test/test_mmap.py Modules/mmapmodule.c Message-ID: <20090331202213.8CAFB1E407C@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 31 22:22:13 2009 New Revision: 70881 Log: Merged revisions 70879 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70879 | hirokazu.yamamoto | 2009-04-01 05:14:04 +0900 | 1 line Issue #5387: Fixed mmap.move crash by integer overflow. (take2) ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_mmap.py python/branches/release26-maint/Modules/mmapmodule.c Modified: python/branches/release26-maint/Lib/test/test_mmap.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_mmap.py (original) +++ python/branches/release26-maint/Lib/test/test_mmap.py Tue Mar 31 22:22:13 2009 @@ -1,7 +1,7 @@ from test.test_support import TESTFN, run_unittest import mmap import unittest -import os, re +import os, re, itertools PAGESIZE = mmap.PAGESIZE @@ -350,9 +350,21 @@ self.assertEqual(m[:], expected) m.close() - # should not crash - m = mmap.mmap(-1, 1) - self.assertRaises(ValueError, m.move, 1, 1, -1) + # segfault test (Issue 5387) + m = mmap.mmap(-1, 100) + offsets = [-100, -1, 0, 1, 100] + for source, dest, size in itertools.product(offsets, offsets, offsets): + try: + m.move(source, dest, size) + except ValueError: + pass + self.assertRaises(ValueError, m.move, -1, -1, -1) + self.assertRaises(ValueError, m.move, -1, -1, 0) + self.assertRaises(ValueError, m.move, -1, 0, -1) + self.assertRaises(ValueError, m.move, 0, -1, -1) + self.assertRaises(ValueError, m.move, -1, 0, 0) + self.assertRaises(ValueError, m.move, 0, -1, 0) + self.assertRaises(ValueError, m.move, 0, 0, -1) m.close() def test_anonymous(self): Modified: python/branches/release26-maint/Modules/mmapmodule.c ============================================================================== --- python/branches/release26-maint/Modules/mmapmodule.c (original) +++ python/branches/release26-maint/Modules/mmapmodule.c Tue Mar 31 22:22:13 2009 @@ -617,7 +617,7 @@ } else { /* bounds check the values */ unsigned long pos = src > dest ? src : dest; - if (self->size >= pos && count > self->size - pos) { + if (self->size < pos || count > self->size - pos) { PyErr_SetString(PyExc_ValueError, "source or destination out of range"); return NULL; From python-checkins at python.org Tue Mar 31 22:40:45 2009 From: python-checkins at python.org (eric.smith) Date: Tue, 31 Mar 2009 22:40:45 +0200 (CEST) Subject: [Python-checkins] r70882 - python/branches/py3k-short-float-repr/Python/pystrtod.c Message-ID: <20090331204045.86E071E407C@bag.python.org> Author: eric.smith Date: Tue Mar 31 22:40:44 2009 New Revision: 70882 Log: Reformat and add comments. Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c ============================================================================== --- python/branches/py3k-short-float-repr/Python/pystrtod.c (original) +++ python/branches/py3k-short-float-repr/Python/pystrtod.c Tue Mar 31 22:40:44 2009 @@ -529,15 +529,15 @@ int add_dot_0_if_integer, int use_alt_formatting, char **float_strings) { - char *start = buf; char *digits, *digits_end; int decpt, sign, exp_len; Py_ssize_t digits_len, i; int use_exp = 0; - int is_integer = 1; /* is the output produced so far just an integer? */ + int is_integer = 1; /* is the output produced so far + just an integer? */ - /* _Py_dg_dtoa returns a digit string (no decimal point - or exponent) */ + /* _Py_dg_dtoa returns a digit string (no decimal point or + exponent) */ digits = _Py_dg_dtoa(d, mode, precision, &decpt, &sign, &digits_end); assert(digits_end != NULL && digits_end > digits); digits_len = digits_end - digits; @@ -703,6 +703,7 @@ char lc_format_code = format_code; char** float_strings = lc_float_strings; + /* Validate format_code, and map upper and lower case */ switch (format_code) { case 'e': case 'f': From python-checkins at python.org Tue Mar 31 22:41:09 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 22:41:09 +0200 (CEST) Subject: [Python-checkins] r70883 - in python/trunk: Doc/library/threading.rst Lib/test/test_threading.py Lib/threading.py Message-ID: <20090331204109.688721E407C@bag.python.org> Author: georg.brandl Date: Tue Mar 31 22:41:08 2009 New Revision: 70883 Log: #1674032: return value of flag from Event.wait(). OKed by Guido. Modified: python/trunk/Doc/library/threading.rst python/trunk/Lib/test/test_threading.py python/trunk/Lib/threading.py Modified: python/trunk/Doc/library/threading.rst ============================================================================== --- python/trunk/Doc/library/threading.rst (original) +++ python/trunk/Doc/library/threading.rst Tue Mar 31 22:41:08 2009 @@ -696,14 +696,20 @@ .. method:: Event.wait([timeout]) - Block until the internal flag is true. If the internal flag is true on entry, - return immediately. Otherwise, block until another thread calls :meth:`set` to - set the flag to true, or until the optional timeout occurs. + Block until the internal flag is true. If the internal flag is true on entry, + return immediately. Otherwise, block until another thread calls :meth:`set` + to set the flag to true, or until the optional timeout occurs. When the timeout argument is present and not ``None``, it should be a floating point number specifying a timeout for the operation in seconds (or fractions thereof). + This method returns the internal flag on exit, so it will always return + ``True`` except if a timeout is given and the operation times out. + + .. versionchanged:: 2.7 + Previously, the method always returned ``None``. + .. _timer-objects: Modified: python/trunk/Lib/test/test_threading.py ============================================================================== --- python/trunk/Lib/test/test_threading.py (original) +++ python/trunk/Lib/test/test_threading.py Tue Mar 31 22:41:08 2009 @@ -186,7 +186,8 @@ # Now raise an exception in the worker thread. if verbose: print " waiting for worker thread to get started" - worker_started.wait() + ret = worker_started.wait() + self.assertTrue(ret) if verbose: print " verifying worker hasn't exited" self.assert_(not t.finished) Modified: python/trunk/Lib/threading.py ============================================================================== --- python/trunk/Lib/threading.py (original) +++ python/trunk/Lib/threading.py Tue Mar 31 22:41:08 2009 @@ -391,6 +391,7 @@ try: if not self.__flag: self.__cond.wait(timeout) + return self.__flag finally: self.__cond.release() From python-checkins at python.org Tue Mar 31 22:43:56 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 31 Mar 2009 22:43:56 +0200 (CEST) Subject: [Python-checkins] r70884 - in python/branches/py3k: Lib/test/test_mmap.py Modules/mmapmodule.c Message-ID: <20090331204356.BCF031E41AA@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 31 22:43:56 2009 New Revision: 70884 Log: Merged revisions 70879 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70879 | hirokazu.yamamoto | 2009-04-01 05:14:04 +0900 | 1 line Issue #5387: Fixed mmap.move crash by integer overflow. (take2) ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_mmap.py python/branches/py3k/Modules/mmapmodule.c Modified: python/branches/py3k/Lib/test/test_mmap.py ============================================================================== --- python/branches/py3k/Lib/test/test_mmap.py (original) +++ python/branches/py3k/Lib/test/test_mmap.py Tue Mar 31 22:43:56 2009 @@ -1,7 +1,7 @@ from test.support import TESTFN, run_unittest import mmap import unittest -import os, re +import os, re, itertools PAGESIZE = mmap.PAGESIZE @@ -347,9 +347,21 @@ self.assertEqual(m[:], expected) m.close() - # should not crash - m = mmap.mmap(-1, 1) - self.assertRaises(ValueError, m.move, 1, 1, -1) + # segfault test (Issue 5387) + m = mmap.mmap(-1, 100) + offsets = [-100, -1, 0, 1, 100] + for source, dest, size in itertools.product(offsets, offsets, offsets): + try: + m.move(source, dest, size) + except ValueError: + pass + self.assertRaises(ValueError, m.move, -1, -1, -1) + self.assertRaises(ValueError, m.move, -1, -1, 0) + self.assertRaises(ValueError, m.move, -1, 0, -1) + self.assertRaises(ValueError, m.move, 0, -1, -1) + self.assertRaises(ValueError, m.move, -1, 0, 0) + self.assertRaises(ValueError, m.move, 0, -1, 0) + self.assertRaises(ValueError, m.move, 0, 0, -1) m.close() def test_anonymous(self): Modified: python/branches/py3k/Modules/mmapmodule.c ============================================================================== --- python/branches/py3k/Modules/mmapmodule.c (original) +++ python/branches/py3k/Modules/mmapmodule.c Tue Mar 31 22:43:56 2009 @@ -628,7 +628,7 @@ } else { /* bounds check the values */ unsigned long pos = src > dest ? src : dest; - if (self->size >= pos && count > self->size - pos) { + if (self->size < pos || count > self->size - pos) { PyErr_SetString(PyExc_ValueError, "source or destination out of range"); return NULL; From python-checkins at python.org Tue Mar 31 22:48:31 2009 From: python-checkins at python.org (tarek.ziade) Date: Tue, 31 Mar 2009 22:48:31 +0200 (CEST) Subject: [Python-checkins] r70885 - in python/trunk/Lib/distutils: cmd.py log.py Message-ID: <20090331204831.CB9321E407C@bag.python.org> Author: tarek.ziade Date: Tue Mar 31 22:48:31 2009 New Revision: 70885 Log: using log.warn for sys.stderr Modified: python/trunk/Lib/distutils/cmd.py python/trunk/Lib/distutils/log.py Modified: python/trunk/Lib/distutils/cmd.py ============================================================================== --- python/trunk/Lib/distutils/cmd.py (original) +++ python/trunk/Lib/distutils/cmd.py Tue Mar 31 22:48:31 2009 @@ -352,9 +352,8 @@ # -- External world manipulation ----------------------------------- def warn (self, msg): - sys.stderr.write("warning: %s: %s\n" % - (self.get_command_name(), msg)) - + log.warn("warning: %s: %s\n" % + (self.get_command_name(), msg)) def execute (self, func, args, msg=None, level=1): util.execute(func, args, msg, dry_run=self.dry_run) Modified: python/trunk/Lib/distutils/log.py ============================================================================== --- python/trunk/Lib/distutils/log.py (original) +++ python/trunk/Lib/distutils/log.py Tue Mar 31 22:48:31 2009 @@ -18,13 +18,14 @@ def _log(self, level, msg, args): if level >= self.threshold: - if not args: - # msg may contain a '%'. If args is empty, - # don't even try to string-format - print msg + if args: + msg = msg % args + if level in (WARN, ERROR, FATAL): + stream = sys.stderr else: - print msg % args - sys.stdout.flush() + stream = sys.stdout + stream.write('%s\n' % msg) + stream.flush() def log(self, level, msg, *args): self._log(level, msg, args) From buildbot at python.org Tue Mar 31 22:50:47 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 20:50:47 +0000 Subject: [Python-checkins] buildbot failure in i386 Ubuntu trunk Message-ID: <20090331205050.AA6371E41F0@bag.python.org> The Buildbot has detected a new failure of i386 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/i386%20Ubuntu%20trunk/builds/1038 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-ubuntu-i386 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl,gregory.p.smith,josiah.carlson,r.david.murray BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_asyncore ====================================================================== FAIL: test_readwrite (test.test_asyncore.HelperFunctionTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-ubuntu-i386/build/Lib/test/test_asyncore.py", line 144, in test_readwrite self.assertEqual(tobj.read, True) AssertionError: False != True ====================================================================== FAIL: test_unhandled (test.test_asyncore.DispatcherTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-ubuntu-i386/build/Lib/test/test_asyncore.py", line 321, in test_unhandled self.assertEquals(lines, expected) AssertionError: First differing element 0: make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 22:51:00 2009 From: python-checkins at python.org (tarek.ziade) Date: Tue, 31 Mar 2009 22:51:00 +0200 (CEST) Subject: [Python-checkins] r70886 - in python/trunk/Lib/distutils: command/clean.py tests/support.py tests/test_clean.py Message-ID: <20090331205100.13B141E41FF@bag.python.org> Author: tarek.ziade Date: Tue Mar 31 22:50:59 2009 New Revision: 70886 Log: added tests for the clean command Added: python/trunk/Lib/distutils/tests/test_clean.py (contents, props changed) Modified: python/trunk/Lib/distutils/command/clean.py python/trunk/Lib/distutils/tests/support.py Modified: python/trunk/Lib/distutils/command/clean.py ============================================================================== --- python/trunk/Lib/distutils/command/clean.py (original) +++ python/trunk/Lib/distutils/command/clean.py Tue Mar 31 22:50:59 2009 @@ -11,7 +11,7 @@ from distutils.dir_util import remove_tree from distutils import log -class clean (Command): +class clean(Command): description = "clean up temporary files from 'build' command" user_options = [ Modified: python/trunk/Lib/distutils/tests/support.py ============================================================================== --- python/trunk/Lib/distutils/tests/support.py (original) +++ python/trunk/Lib/distutils/tests/support.py Tue Mar 31 22:50:59 2009 @@ -4,7 +4,7 @@ import tempfile from distutils import log - +from distutils.core import Distribution class LoggingSilencer(object): @@ -42,7 +42,7 @@ self.tempdirs.append(d) return d - def write_file(self, path, content): + def write_file(self, path, content='xxx'): """Writes a file in the given path. @@ -56,6 +56,23 @@ finally: f.close() + def create_dist(self, pkg_name='foo', **kw): + """Will generate a test environment. + + This function creates: + - a Distribution instance using keywords + - a temporary directory with a package structure + + It returns the package directory and the distribution + instance. + """ + tmp_dir = self.mkdtemp() + pkg_dir = os.path.join(tmp_dir, pkg_name) + os.mkdir(pkg_dir) + dist = Distribution(attrs=kw) + + return pkg_dir, dist + class DummyCommand: """Class to store options for retrieval via set_undefined_options().""" Added: python/trunk/Lib/distutils/tests/test_clean.py ============================================================================== --- (empty file) +++ python/trunk/Lib/distutils/tests/test_clean.py Tue Mar 31 22:50:59 2009 @@ -0,0 +1,49 @@ +"""Tests for distutils.command.clean.""" +import sys +import os +import unittest +import getpass + +from distutils.command.clean import clean +from distutils.tests import support + +class cleanTestCase(support.TempdirManager, + unittest.TestCase): + + def test_simple_run(self): + pkg_dir, dist = self.create_dist() + cmd = clean(dist) + + # let's add some elements clean should remove + dirs = [(d, os.path.join(pkg_dir, d)) + for d in ('build_temp', 'build_lib', 'bdist_base', + 'build_scripts', 'build_base')] + + for name, path in dirs: + os.mkdir(path) + setattr(cmd, name, path) + if name == 'build_base': + continue + for f in ('one', 'two', 'three'): + self.write_file(os.path.join(path, f)) + + # let's run the command + cmd.all = 1 + cmd.ensure_finalized() + cmd.run() + + # make sure the files where removed + for name, path in dirs: + self.assert_(not os.path.exists(path), + '%s was not removed' % path) + + # let's run the command again (should spit warnings but suceed) + cmd.all = 1 + cmd.ensure_finalized() + cmd.run() + +def test_suite(): + return unittest.makeSuite(cleanTestCase) + +if __name__ == "__main__": + unittest.main(defaultTest="test_suite") From python-checkins at python.org Tue Mar 31 22:51:44 2009 From: python-checkins at python.org (hirokazu.yamamoto) Date: Tue, 31 Mar 2009 22:51:44 +0200 (CEST) Subject: [Python-checkins] r70887 - in python/branches/release30-maint: Lib/test/test_mmap.py Modules/mmapmodule.c Message-ID: <20090331205144.79B031E4314@bag.python.org> Author: hirokazu.yamamoto Date: Tue Mar 31 22:51:44 2009 New Revision: 70887 Log: Merged revisions 70884 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r70884 | hirokazu.yamamoto | 2009-04-01 05:43:56 +0900 | 9 lines Merged revisions 70879 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70879 | hirokazu.yamamoto | 2009-04-01 05:14:04 +0900 | 1 line Issue #5387: Fixed mmap.move crash by integer overflow. (take2) ........ ................ Modified: python/branches/release30-maint/ (props changed) python/branches/release30-maint/Lib/test/test_mmap.py python/branches/release30-maint/Modules/mmapmodule.c Modified: python/branches/release30-maint/Lib/test/test_mmap.py ============================================================================== --- python/branches/release30-maint/Lib/test/test_mmap.py (original) +++ python/branches/release30-maint/Lib/test/test_mmap.py Tue Mar 31 22:51:44 2009 @@ -1,7 +1,7 @@ from test.support import TESTFN, run_unittest import mmap import unittest -import os, re +import os, re, itertools PAGESIZE = mmap.PAGESIZE @@ -347,9 +347,21 @@ self.assertEqual(m[:], expected) m.close() - # should not crash - m = mmap.mmap(-1, 1) - self.assertRaises(ValueError, m.move, 1, 1, -1) + # segfault test (Issue 5387) + m = mmap.mmap(-1, 100) + offsets = [-100, -1, 0, 1, 100] + for source, dest, size in itertools.product(offsets, offsets, offsets): + try: + m.move(source, dest, size) + except ValueError: + pass + self.assertRaises(ValueError, m.move, -1, -1, -1) + self.assertRaises(ValueError, m.move, -1, -1, 0) + self.assertRaises(ValueError, m.move, -1, 0, -1) + self.assertRaises(ValueError, m.move, 0, -1, -1) + self.assertRaises(ValueError, m.move, -1, 0, 0) + self.assertRaises(ValueError, m.move, 0, -1, 0) + self.assertRaises(ValueError, m.move, 0, 0, -1) m.close() def test_anonymous(self): Modified: python/branches/release30-maint/Modules/mmapmodule.c ============================================================================== --- python/branches/release30-maint/Modules/mmapmodule.c (original) +++ python/branches/release30-maint/Modules/mmapmodule.c Tue Mar 31 22:51:44 2009 @@ -624,7 +624,7 @@ } else { /* bounds check the values */ unsigned long pos = src > dest ? src : dest; - if (self->size >= pos && count > self->size - pos) { + if (self->size < pos || count > self->size - pos) { PyErr_SetString(PyExc_ValueError, "source or destination out of range"); return NULL; From python-checkins at python.org Tue Mar 31 22:53:14 2009 From: python-checkins at python.org (tarek.ziade) Date: Tue, 31 Mar 2009 22:53:14 +0200 (CEST) Subject: [Python-checkins] r70888 - in python/trunk/Lib/distutils: command/register.py tests/test_register.py Message-ID: <20090331205314.19ECF1E407C@bag.python.org> Author: tarek.ziade Date: Tue Mar 31 22:53:13 2009 New Revision: 70888 Log: more tests for the register command Modified: python/trunk/Lib/distutils/command/register.py python/trunk/Lib/distutils/tests/test_register.py Modified: python/trunk/Lib/distutils/command/register.py ============================================================================== --- python/trunk/Lib/distutils/command/register.py (original) +++ python/trunk/Lib/distutils/command/register.py Tue Mar 31 22:53:13 2009 @@ -90,14 +90,14 @@ ''' Fetch the list of classifiers from the server. ''' response = urllib2.urlopen(self.repository+'?:action=list_classifiers') - print response.read() + log.info(response.read()) def verify_metadata(self): ''' Send the metadata to the package index server to be checked. ''' # send the info to the server and report the result (code, result) = self.post_to_server(self.build_post_data('verify')) - print 'Server response (%s): %s'%(code, result) + log.info('Server response (%s): %s' % (code, result)) def send_metadata(self): @@ -210,17 +210,18 @@ data['email'] = raw_input(' EMail: ') code, result = self.post_to_server(data) if code != 200: - print 'Server response (%s): %s'%(code, result) + log.info('Server response (%s): %s' % (code, result)) else: - print 'You will receive an email shortly.' - print 'Follow the instructions in it to complete registration.' + log.info('You will receive an email shortly.') + log.info(('Follow the instructions in it to ' + 'complete registration.')) elif choice == '3': data = {':action': 'password_reset'} data['email'] = '' while not data['email']: data['email'] = raw_input('Your email address: ') code, result = self.post_to_server(data) - print 'Server response (%s): %s'%(code, result) + log.info('Server response (%s): %s' % (code, result)) def build_post_data(self, action): # figure the data to send - the metadata plus some additional @@ -253,8 +254,10 @@ def post_to_server(self, data, auth=None): ''' Post a query to the server, and return a string response. ''' - self.announce('Registering %s to %s' % (data['name'], - self.repository), log.INFO) + if 'name' in data: + self.announce('Registering %s to %s' % (data['name'], + self.repository), + log.INFO) # Build up the MIME payload for the urllib2 POST data boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' sep_boundary = '\n--' + boundary @@ -301,5 +304,7 @@ data = result.read() result = 200, 'OK' if self.show_response: - print '-'*75, data, '-'*75 + dashes = '-' * 75 + self.announce('%s%s%s' % (dashes, data, dashes)) + return result Modified: python/trunk/Lib/distutils/tests/test_register.py ============================================================================== --- python/trunk/Lib/distutils/tests/test_register.py (original) +++ python/trunk/Lib/distutils/tests/test_register.py Tue Mar 31 22:53:13 2009 @@ -3,7 +3,9 @@ import os import unittest import getpass +import urllib2 +from distutils.command import register as register_module from distutils.command.register import register from distutils.core import Distribution @@ -42,18 +44,20 @@ finally: self.index += 1 -class FakeServer(object): +class FakeOpener(object): """Fakes a PyPI server""" def __init__(self): - self.calls = [] + self.reqs = [] def __call__(self, *args): - # we want to compare them, so let's store - # something comparable - els = args[0].items() - els.sort() - self.calls.append(tuple(els)) - return 200, 'OK' + return self + + def open(self, req): + self.reqs.append(req) + return self + + def read(self): + return 'xxx' class registerTestCase(PyPIRCCommandTestCase): @@ -64,24 +68,27 @@ def _getpass(prompt): return 'password' getpass.getpass = _getpass + self.old_opener = urllib2.build_opener + self.conn = urllib2.build_opener = FakeOpener() def tearDown(self): getpass.getpass = self._old_getpass + urllib2.build_opener = self.old_opener PyPIRCCommandTestCase.tearDown(self) + def _get_cmd(self): + metadata = {'url': 'xxx', 'author': 'xxx', + 'author_email': 'xxx', + 'name': 'xxx', 'version': 'xxx'} + pkg_info, dist = self.create_dist(**metadata) + return register(dist) + def test_create_pypirc(self): # this test makes sure a .pypirc file # is created when requested. - # let's create a fake distribution - # and a register instance - dist = Distribution() - dist.metadata.url = 'xxx' - dist.metadata.author = 'xxx' - dist.metadata.author_email = 'xxx' - dist.metadata.name = 'xxx' - dist.metadata.version = 'xxx' - cmd = register(dist) + # let's create a register instance + cmd = self._get_cmd() # we shouldn't have a .pypirc file yet self.assert_(not os.path.exists(self.rc)) @@ -95,13 +102,12 @@ # Password : 'password' # Save your login (y/N)? : 'y' inputs = RawInputs('1', 'tarek', 'y') - from distutils.command import register as register_module register_module.raw_input = inputs.__call__ - - cmd.post_to_server = pypi_server = FakeServer() - # let's run the command - cmd.run() + try: + cmd.run() + finally: + del register_module.raw_input # we should have a brand new .pypirc file self.assert_(os.path.exists(self.rc)) @@ -117,30 +123,66 @@ raise AssertionError(prompt) register_module.raw_input = _no_way + cmd.show_response = 1 cmd.run() # let's see what the server received : we should # have 2 similar requests - self.assert_(len(pypi_server.calls), 2) - self.assert_(pypi_server.calls[0], pypi_server.calls[1]) + self.assert_(self.conn.reqs, 2) + req1 = dict(self.conn.reqs[0].headers) + req2 = dict(self.conn.reqs[1].headers) + + self.assertEquals(req1['Content-length'], '1374') + self.assertEquals(req2['Content-length'], '1374') + self.assert_('xxx' in self.conn.reqs[1].data) def test_password_not_in_file(self): - f = open(self.rc, 'w') - f.write(PYPIRC_NOPASSWORD) - f.close() - - dist = Distribution() - cmd = register(dist) - cmd.post_to_server = FakeServer() - + self.write_file(self.rc, PYPIRC_NOPASSWORD) + cmd = self._get_cmd() cmd._set_config() cmd.finalize_options() cmd.send_metadata() # dist.password should be set # therefore used afterwards by other commands - self.assertEquals(dist.password, 'password') + self.assertEquals(cmd.distribution.password, 'password') + + def test_registering(self): + # this test runs choice 2 + cmd = self._get_cmd() + inputs = RawInputs('2', 'tarek', 'tarek at ziade.org') + register_module.raw_input = inputs.__call__ + try: + # let's run the command + cmd.run() + finally: + del register_module.raw_input + + # we should have send a request + self.assert_(self.conn.reqs, 1) + req = self.conn.reqs[0] + headers = dict(req.headers) + self.assertEquals(headers['Content-length'], '608') + self.assert_('tarek' in req.data) + + def test_password_reset(self): + # this test runs choice 3 + cmd = self._get_cmd() + inputs = RawInputs('3', 'tarek at ziade.org') + register_module.raw_input = inputs.__call__ + try: + # let's run the command + cmd.run() + finally: + del register_module.raw_input + + # we should have send a request + self.assert_(self.conn.reqs, 1) + req = self.conn.reqs[0] + headers = dict(req.headers) + self.assertEquals(headers['Content-length'], '290') + self.assert_('tarek' in req.data) def test_suite(): return unittest.makeSuite(registerTestCase) From python-checkins at python.org Tue Mar 31 22:53:55 2009 From: python-checkins at python.org (tarek.ziade) Date: Tue, 31 Mar 2009 22:53:55 +0200 (CEST) Subject: [Python-checkins] r70889 - in python/trunk/Lib/distutils: command/upload.py tests/test_upload.py Message-ID: <20090331205355.699411E407C@bag.python.org> Author: tarek.ziade Date: Tue Mar 31 22:53:55 2009 New Revision: 70889 Log: more tests for the upload command Modified: python/trunk/Lib/distutils/command/upload.py python/trunk/Lib/distutils/tests/test_upload.py Modified: python/trunk/Lib/distutils/command/upload.py ============================================================================== --- python/trunk/Lib/distutils/command/upload.py (original) +++ python/trunk/Lib/distutils/command/upload.py Tue Mar 31 22:53:55 2009 @@ -192,4 +192,4 @@ self.announce('Upload failed (%s): %s' % (r.status, r.reason), log.ERROR) if self.show_response: - print '-'*75, r.read(), '-'*75 + self.announce('-'*75, r.read(), '-'*75) Modified: python/trunk/Lib/distutils/tests/test_upload.py ============================================================================== --- python/trunk/Lib/distutils/tests/test_upload.py (original) +++ python/trunk/Lib/distutils/tests/test_upload.py Tue Mar 31 22:53:55 2009 @@ -2,6 +2,7 @@ import sys import os import unittest +import httplib from distutils.command.upload import upload from distutils.core import Distribution @@ -18,17 +19,52 @@ [server1] username:me """ +class Response(object): + def __init__(self, status=200, reason='OK'): + self.status = status + self.reason = reason +class FakeConnection(object): + + def __init__(self): + self.requests = [] + self.headers = [] + self.body = '' + + def __call__(self, netloc): + return self + + def connect(self): + pass + endheaders = connect + + def putrequest(self, method, url): + self.requests.append((method, url)) + + def putheader(self, name, value): + self.headers.append((name, value)) + + def send(self, body): + self.body = body + + def getresponse(self): + return Response() class uploadTestCase(PyPIRCCommandTestCase): + def setUp(self): + super(uploadTestCase, self).setUp() + self.old_class = httplib.HTTPConnection + self.conn = httplib.HTTPConnection = FakeConnection() + + def tearDown(self): + httplib.HTTPConnection = self.old_class + super(uploadTestCase, self).tearDown() + def test_finalize_options(self): # new format - f = open(self.rc, 'w') - f.write(PYPIRC) - f.close() - + self.write_file(self.rc, PYPIRC) dist = Distribution() cmd = upload(dist) cmd.finalize_options() @@ -39,9 +75,7 @@ def test_saved_password(self): # file with no password - f = open(self.rc, 'w') - f.write(PYPIRC_NOPASSWORD) - f.close() + self.write_file(self.rc, PYPIRC_NOPASSWORD) # make sure it passes dist = Distribution() @@ -56,6 +90,28 @@ cmd.finalize_options() self.assertEquals(cmd.password, 'xxx') + def test_upload(self): + tmp = self.mkdtemp() + path = os.path.join(tmp, 'xxx') + self.write_file(path) + command, pyversion, filename = 'xxx', '2.6', path + dist_files = [(command, pyversion, filename)] + self.write_file(self.rc, PYPIRC) + + # lets run it + pkg_dir, dist = self.create_dist(dist_files=dist_files) + cmd = upload(dist) + cmd.ensure_finalized() + cmd.run() + + # what did we send ? + headers = dict(self.conn.headers) + self.assertEquals(headers['Content-length'], '2086') + self.assert_(headers['Content-type'].startswith('multipart/form-data')) + + self.assertEquals(self.conn.requests, [('POST', '/pypi')]) + self.assert_('xxx' in self.conn.body) + def test_suite(): return unittest.makeSuite(uploadTestCase) From python-checkins at python.org Tue Mar 31 22:54:39 2009 From: python-checkins at python.org (tarek.ziade) Date: Tue, 31 Mar 2009 22:54:39 +0200 (CEST) Subject: [Python-checkins] r70890 - in python/trunk/Lib/distutils: command/install_data.py tests/test_install_data.py Message-ID: <20090331205439.29C921E407C@bag.python.org> Author: tarek.ziade Date: Tue Mar 31 22:54:38 2009 New Revision: 70890 Log: added test to the install_data command Added: python/trunk/Lib/distutils/tests/test_install_data.py (contents, props changed) Modified: python/trunk/Lib/distutils/command/install_data.py Modified: python/trunk/Lib/distutils/command/install_data.py ============================================================================== --- python/trunk/Lib/distutils/command/install_data.py (original) +++ python/trunk/Lib/distutils/command/install_data.py Tue Mar 31 22:54:38 2009 @@ -12,7 +12,7 @@ from distutils.core import Command from distutils.util import change_root, convert_path -class install_data (Command): +class install_data(Command): description = "install data files" @@ -27,12 +27,11 @@ boolean_options = ['force'] - def initialize_options (self): + def initialize_options(self): self.install_dir = None self.outfiles = [] self.root = None self.force = 0 - self.data_files = self.distribution.data_files self.warn_dir = 1 @@ -43,7 +42,7 @@ ('force', 'force'), ) - def run (self): + def run(self): self.mkpath(self.install_dir) for f in self.data_files: if type(f) is StringType: @@ -76,8 +75,8 @@ (out, _) = self.copy_file(data, dir) self.outfiles.append(out) - def get_inputs (self): + def get_inputs(self): return self.data_files or [] - def get_outputs (self): + def get_outputs(self): return self.outfiles Added: python/trunk/Lib/distutils/tests/test_install_data.py ============================================================================== --- (empty file) +++ python/trunk/Lib/distutils/tests/test_install_data.py Tue Mar 31 22:54:38 2009 @@ -0,0 +1,75 @@ +"""Tests for distutils.command.install_data.""" +import sys +import os +import unittest +import getpass + +from distutils.command.install_data import install_data +from distutils.tests import support + +class InstallDataTestCase(support.TempdirManager, + support.LoggingSilencer, + unittest.TestCase): + + def test_simple_run(self): + pkg_dir, dist = self.create_dist() + cmd = install_data(dist) + cmd.install_dir = inst = os.path.join(pkg_dir, 'inst') + + # data_files can contain + # - simple files + # - a tuple with a path, and a list of file + one = os.path.join(pkg_dir, 'one') + self.write_file(one, 'xxx') + inst2 = os.path.join(pkg_dir, 'inst2') + two = os.path.join(pkg_dir, 'two') + self.write_file(two, 'xxx') + + cmd.data_files = [one, (inst2, [two])] + self.assertEquals(cmd.get_inputs(), [one, (inst2, [two])]) + + # let's run the command + cmd.ensure_finalized() + cmd.run() + + # let's check the result + self.assertEquals(len(cmd.get_outputs()), 2) + rtwo = os.path.split(two)[-1] + self.assert_(os.path.exists(os.path.join(inst2, rtwo))) + rone = os.path.split(one)[-1] + self.assert_(os.path.exists(os.path.join(inst, rone))) + cmd.outfiles = [] + + # let's try with warn_dir one + cmd.warn_dir = 1 + cmd.ensure_finalized() + cmd.run() + + # let's check the result + self.assertEquals(len(cmd.get_outputs()), 2) + self.assert_(os.path.exists(os.path.join(inst2, rtwo))) + self.assert_(os.path.exists(os.path.join(inst, rone))) + cmd.outfiles = [] + + # now using root and empty dir + cmd.root = os.path.join(pkg_dir, 'root') + inst3 = os.path.join(cmd.install_dir, 'inst3') + inst4 = os.path.join(pkg_dir, 'inst4') + three = os.path.join(cmd.install_dir, 'three') + self.write_file(three, 'xx') + cmd.data_files = [one, (inst2, [two]), + ('inst3', [three]), + (inst4, [])] + cmd.ensure_finalized() + cmd.run() + + # let's check the result + self.assertEquals(len(cmd.get_outputs()), 4) + self.assert_(os.path.exists(os.path.join(inst2, rtwo))) + self.assert_(os.path.exists(os.path.join(inst, rone))) + +def test_suite(): + return unittest.makeSuite(InstallDataTestCase) + +if __name__ == "__main__": + unittest.main(defaultTest="test_suite") From python-checkins at python.org Tue Mar 31 22:55:21 2009 From: python-checkins at python.org (tarek.ziade) Date: Tue, 31 Mar 2009 22:55:21 +0200 (CEST) Subject: [Python-checkins] r70891 - in python/trunk/Lib/distutils: command/install_headers.py tests/test_install_headers.py Message-ID: <20090331205521.EBC6B1E432E@bag.python.org> Author: tarek.ziade Date: Tue Mar 31 22:55:21 2009 New Revision: 70891 Log: added tests to the install_headers command Added: python/trunk/Lib/distutils/tests/test_install_headers.py (contents, props changed) Modified: python/trunk/Lib/distutils/command/install_headers.py Modified: python/trunk/Lib/distutils/command/install_headers.py ============================================================================== --- python/trunk/Lib/distutils/command/install_headers.py (original) +++ python/trunk/Lib/distutils/command/install_headers.py Tue Mar 31 22:55:21 2009 @@ -8,7 +8,8 @@ from distutils.core import Command -class install_headers (Command): +# XXX force is never used +class install_headers(Command): description = "install C/C++ header files" @@ -20,18 +21,18 @@ boolean_options = ['force'] - def initialize_options (self): + def initialize_options(self): self.install_dir = None self.force = 0 self.outfiles = [] - def finalize_options (self): + def finalize_options(self): self.set_undefined_options('install', ('install_headers', 'install_dir'), ('force', 'force')) - def run (self): + def run(self): headers = self.distribution.headers if not headers: return @@ -41,10 +42,10 @@ (out, _) = self.copy_file(header, self.install_dir) self.outfiles.append(out) - def get_inputs (self): + def get_inputs(self): return self.distribution.headers or [] - def get_outputs (self): + def get_outputs(self): return self.outfiles # class install_headers Added: python/trunk/Lib/distutils/tests/test_install_headers.py ============================================================================== --- (empty file) +++ python/trunk/Lib/distutils/tests/test_install_headers.py Tue Mar 31 22:55:21 2009 @@ -0,0 +1,39 @@ +"""Tests for distutils.command.install_headers.""" +import sys +import os +import unittest +import getpass + +from distutils.command.install_headers import install_headers +from distutils.tests import support + +class InstallHeadersTestCase(support.TempdirManager, + support.LoggingSilencer, + unittest.TestCase): + + def test_simple_run(self): + # we have two headers + header_list = self.mkdtemp() + header1 = os.path.join(header_list, 'header1') + header2 = os.path.join(header_list, 'header2') + self.write_file(header1) + self.write_file(header2) + headers = [header1, header2] + + pkg_dir, dist = self.create_dist(headers=headers) + cmd = install_headers(dist) + self.assertEquals(cmd.get_inputs(), headers) + + # let's run the command + cmd.install_dir = os.path.join(pkg_dir, 'inst') + cmd.ensure_finalized() + cmd.run() + + # let's check the results + self.assertEquals(len(cmd.get_outputs()), 2) + +def test_suite(): + return unittest.makeSuite(InstallHeadersTestCase) + +if __name__ == "__main__": + unittest.main(defaultTest="test_suite") From python-checkins at python.org Tue Mar 31 22:56:11 2009 From: python-checkins at python.org (tarek.ziade) Date: Tue, 31 Mar 2009 22:56:11 +0200 (CEST) Subject: [Python-checkins] r70892 - in python/trunk/Lib/distutils/tests: test_config.py test_sdist.py Message-ID: <20090331205611.F1A4A1E40FC@bag.python.org> Author: tarek.ziade Date: Tue Mar 31 22:56:11 2009 New Revision: 70892 Log: making sdist and config test silents Modified: python/trunk/Lib/distutils/tests/test_config.py python/trunk/Lib/distutils/tests/test_sdist.py Modified: python/trunk/Lib/distutils/tests/test_config.py ============================================================================== --- python/trunk/Lib/distutils/tests/test_config.py (original) +++ python/trunk/Lib/distutils/tests/test_config.py Tue Mar 31 22:56:11 2009 @@ -47,7 +47,9 @@ """ -class PyPIRCCommandTestCase(support.TempdirManager, unittest.TestCase): +class PyPIRCCommandTestCase(support.TempdirManager, + support.LoggingSilencer, + unittest.TestCase): def setUp(self): """Patches the environment.""" Modified: python/trunk/Lib/distutils/tests/test_sdist.py ============================================================================== --- python/trunk/Lib/distutils/tests/test_sdist.py (original) +++ python/trunk/Lib/distutils/tests/test_sdist.py Tue Mar 31 22:56:11 2009 @@ -34,7 +34,7 @@ somecode%(sep)sdoc.txt """ -class sdistTestCase(support.LoggingSilencer, PyPIRCCommandTestCase): +class sdistTestCase(PyPIRCCommandTestCase): def setUp(self): # PyPIRCCommandTestCase creates a temp dir already From python-checkins at python.org Tue Mar 31 22:56:32 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 22:56:32 +0200 (CEST) Subject: [Python-checkins] r70893 - python/trunk/Doc/tutorial/introduction.rst Message-ID: <20090331205632.CC01A1E407C@bag.python.org> Author: georg.brandl Date: Tue Mar 31 22:56:32 2009 New Revision: 70893 Log: #1530012: move TQS section before raw strings. Modified: python/trunk/Doc/tutorial/introduction.rst Modified: python/trunk/Doc/tutorial/introduction.rst ============================================================================== --- python/trunk/Doc/tutorial/introduction.rst (original) +++ python/trunk/Doc/tutorial/introduction.rst Tue Mar 31 22:56:32 2009 @@ -199,21 +199,6 @@ several lines of text just as you would do in C. Note that whitespace at the beginning of the line is significant. -If we make the string literal a "raw" string, however, the ``\n`` sequences are -not converted to newlines, but the backslash at the end of the line, and the -newline character in the source, are both included in the string as data. Thus, -the example:: - - hello = r"This is a rather long string containing\n\ - several lines of text much as you would do in C." - - print hello - -would print:: - - This is a rather long string containing\n\ - several lines of text much as you would do in C. - Or, strings can be surrounded in a pair of matching triple-quotes: ``"""`` or ``'''``. End of lines do not need to be escaped when using triple-quotes, but they will be included in the string. :: @@ -230,6 +215,20 @@ -h Display this usage message -H hostname Hostname to connect to +If we make the string literal a "raw" string, ``\n`` sequences are not converted +to newlines, but the backslash at the end of the line, and the newline character +in the source, are both included in the string as data. Thus, the example:: + + hello = r"This is a rather long string containing\n\ + several lines of text much as you would do in C." + + print hello + +would print:: + + This is a rather long string containing\n\ + several lines of text much as you would do in C. + The interpreter prints the result of string operations in the same way as they are typed for input: inside quotes, and with quotes and other funny characters escaped by backslashes, to show the precise value. The string is enclosed in From python-checkins at python.org Tue Mar 31 23:06:30 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 31 Mar 2009 23:06:30 +0200 (CEST) Subject: [Python-checkins] r70894 - python/trunk/Lib/threading.py Message-ID: <20090331210630.9B7481E407C@bag.python.org> Author: benjamin.peterson Date: Tue Mar 31 23:06:30 2009 New Revision: 70894 Log: take the usual lock precautions around _active_limbo_lock Modified: python/trunk/Lib/threading.py Modified: python/trunk/Lib/threading.py ============================================================================== --- python/trunk/Lib/threading.py (original) +++ python/trunk/Lib/threading.py Tue Mar 31 23:06:30 2009 @@ -466,9 +466,8 @@ raise RuntimeError("thread already started") if __debug__: self._note("%s.start(): starting thread", self) - _active_limbo_lock.acquire() - _limbo[self] = self - _active_limbo_lock.release() + with _active_limbo_lock: + _limbo[self] = self _start_new_thread(self.__bootstrap, ()) self.__started.wait() @@ -505,10 +504,9 @@ try: self.__ident = _get_ident() self.__started.set() - _active_limbo_lock.acquire() - _active[self.__ident] = self - del _limbo[self] - _active_limbo_lock.release() + with _active_limbo_lock: + _active[self.__ident] = self + del _limbo[self] if __debug__: self._note("%s.__bootstrap(): thread started", self) @@ -735,9 +733,8 @@ def __init__(self): Thread.__init__(self, name="MainThread") self._Thread__started.set() - _active_limbo_lock.acquire() - _active[_get_ident()] = self - _active_limbo_lock.release() + with _active_limbo_lock: + _active[_get_ident()] = self def _set_daemon(self): return False @@ -781,9 +778,8 @@ del self._Thread__block self._Thread__started.set() - _active_limbo_lock.acquire() - _active[_get_ident()] = self - _active_limbo_lock.release() + with _active_limbo_lock: + _active[_get_ident()] = self def _set_daemon(self): return True @@ -804,18 +800,14 @@ current_thread = currentThread def activeCount(): - _active_limbo_lock.acquire() - count = len(_active) + len(_limbo) - _active_limbo_lock.release() - return count + with _active_limbo_lock: + return len(_active) + len(_limbo) active_count = activeCount def enumerate(): - _active_limbo_lock.acquire() - active = _active.values() + _limbo.values() - _active_limbo_lock.release() - return active + with _active_limbo_lock: + return _active.values() + _limbo.values() from thread import stack_size From python-checkins at python.org Tue Mar 31 23:06:56 2009 From: python-checkins at python.org (tarek.ziade) Date: Tue, 31 Mar 2009 23:06:56 +0200 (CEST) Subject: [Python-checkins] r70895 - python/branches/release26-maint Message-ID: <20090331210656.E43DE1E407C@bag.python.org> Author: tarek.ziade Date: Tue Mar 31 23:06:56 2009 New Revision: 70895 Log: Blocked revisions 70886,70888-70892 via svnmerge ........ r70886 | tarek.ziade | 2009-03-31 15:50:59 -0500 (Tue, 31 Mar 2009) | 1 line added tests for the clean command ........ r70888 | tarek.ziade | 2009-03-31 15:53:13 -0500 (Tue, 31 Mar 2009) | 1 line more tests for the register command ........ r70889 | tarek.ziade | 2009-03-31 15:53:55 -0500 (Tue, 31 Mar 2009) | 1 line more tests for the upload command ........ r70890 | tarek.ziade | 2009-03-31 15:54:38 -0500 (Tue, 31 Mar 2009) | 1 line added test to the install_data command ........ r70891 | tarek.ziade | 2009-03-31 15:55:21 -0500 (Tue, 31 Mar 2009) | 1 line added tests to the install_headers command ........ r70892 | tarek.ziade | 2009-03-31 15:56:11 -0500 (Tue, 31 Mar 2009) | 1 line making sdist and config test silents ........ Modified: python/branches/release26-maint/ (props changed) From ocean-city at m2.ccsnet.ne.jp Tue Mar 31 22:35:39 2009 From: ocean-city at m2.ccsnet.ne.jp (Hirokazu Yamamoto) Date: Wed, 01 Apr 2009 05:35:39 +0900 Subject: [Python-checkins] r70879 - in python/trunk: Lib/test/test_mmap.py Modules/mmapmodule.c In-Reply-To: References: <20090331201404.8FED71E4054@bag.python.org> Message-ID: <49D27E9B.5020007@m2.ccsnet.ne.jp> >FYI, PEP-8 > >Imports should usually be on separate lines, e.g.: > > Yes: import os > import sys > > No: import sys, os Yes, but "import os, re" was already there, I followed to it. I don't think it is so big deal... is it? Really required modification was, movement of m.close(). >>> import mmap >>> m = mmap.mmap(-1, 100) >>> m.close() >>> m.move(0, 0, 1) Traceback (most recent call last): File "", line 1, in ValueError: mmap closed or invalid m.move() raises ValueError, but its meaning differs. From buildbot at python.org Tue Mar 31 23:13:55 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 21:13:55 +0000 Subject: [Python-checkins] buildbot failure in amd64 gentoo trunk Message-ID: <20090331211355.34D3E1E407C@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%20gentoo%20trunk/builds/2044 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: norwitz-amd64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl,gregory.p.smith,josiah.carlson,r.david.murray BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_asyncore ====================================================================== FAIL: test_readwrite (test.test_asyncore.HelperFunctionTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_asyncore.py", line 144, in test_readwrite self.assertEqual(tobj.read, True) AssertionError: False != True ====================================================================== FAIL: test_unhandled (test.test_asyncore.DispatcherTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave/py-build/trunk.norwitz-amd64/build/Lib/test/test_asyncore.py", line 321, in test_unhandled self.assertEquals(lines, expected) AssertionError: First differing element 0: make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 23:15:33 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 23:15:33 +0200 (CEST) Subject: [Python-checkins] r70896 - python/trunk/Doc/library/doctest.rst Message-ID: <20090331211533.E4C241E407C@bag.python.org> Author: georg.brandl Date: Tue Mar 31 23:15:33 2009 New Revision: 70896 Log: #5598: document DocFileSuite *args argument. Modified: python/trunk/Doc/library/doctest.rst Modified: python/trunk/Doc/library/doctest.rst ============================================================================== --- python/trunk/Doc/library/doctest.rst (original) +++ python/trunk/Doc/library/doctest.rst Tue Mar 31 23:15:33 2009 @@ -965,7 +965,7 @@ from text files and modules with doctests: -.. function:: DocFileSuite([module_relative][, package][, setUp][, tearDown][, globs][, optionflags][, parser][, encoding]) +.. function:: DocFileSuite(*paths, [module_relative][, package][, setUp][, tearDown][, globs][, optionflags][, parser][, encoding]) Convert doctest tests from one or more text files to a :class:`unittest.TestSuite`. @@ -983,45 +983,47 @@ Optional argument *module_relative* specifies how the filenames in *paths* should be interpreted: - * If *module_relative* is ``True`` (the default), then each filename specifies - an OS-independent module-relative path. By default, this path is relative to - the calling module's directory; but if the *package* argument is specified, then - it is relative to that package. To ensure OS-independence, each filename should - use ``/`` characters to separate path segments, and may not be an absolute path - (i.e., it may not begin with ``/``). - - * If *module_relative* is ``False``, then each filename specifies an OS-specific - path. The path may be absolute or relative; relative paths are resolved with - respect to the current working directory. - - Optional argument *package* is a Python package or the name of a Python package - whose directory should be used as the base directory for module-relative - filenames. If no package is specified, then the calling module's directory is - used as the base directory for module-relative filenames. It is an error to - specify *package* if *module_relative* is ``False``. - - Optional argument *setUp* specifies a set-up function for the test suite. This - is called before running the tests in each file. The *setUp* function will be - passed a :class:`DocTest` object. The setUp function can access the test - globals as the *globs* attribute of the test passed. + * If *module_relative* is ``True`` (the default), then each filename in + *paths* specifies an OS-independent module-relative path. By default, this + path is relative to the calling module's directory; but if the *package* + argument is specified, then it is relative to that package. To ensure + OS-independence, each filename should use ``/`` characters to separate path + segments, and may not be an absolute path (i.e., it may not begin with + ``/``). + + * If *module_relative* is ``False``, then each filename in *paths* specifies + an OS-specific path. The path may be absolute or relative; relative paths + are resolved with respect to the current working directory. + + Optional argument *package* is a Python package or the name of a Python + package whose directory should be used as the base directory for + module-relative filenames in *paths*. If no package is specified, then the + calling module's directory is used as the base directory for module-relative + filenames. It is an error to specify *package* if *module_relative* is + ``False``. - Optional argument *tearDown* specifies a tear-down function for the test suite. - This is called after running the tests in each file. The *tearDown* function + Optional argument *setUp* specifies a set-up function for the test suite. + This is called before running the tests in each file. The *setUp* function will be passed a :class:`DocTest` object. The setUp function can access the test globals as the *globs* attribute of the test passed. + Optional argument *tearDown* specifies a tear-down function for the test + suite. This is called after running the tests in each file. The *tearDown* + function will be passed a :class:`DocTest` object. The setUp function can + access the test globals as the *globs* attribute of the test passed. + Optional argument *globs* is a dictionary containing the initial global variables for the tests. A new copy of this dictionary is created for each test. By default, *globs* is a new empty dictionary. Optional argument *optionflags* specifies the default doctest options for the tests, created by or-ing together individual option flags. See section - :ref:`doctest-options`. See function :func:`set_unittest_reportflags` below for - a better way to set reporting options. + :ref:`doctest-options`. See function :func:`set_unittest_reportflags` below + for a better way to set reporting options. - Optional argument *parser* specifies a :class:`DocTestParser` (or subclass) that - should be used to extract tests from the files. It defaults to a normal parser - (i.e., ``DocTestParser()``). + Optional argument *parser* specifies a :class:`DocTestParser` (or subclass) + that should be used to extract tests from the files. It defaults to a normal + parser (i.e., ``DocTestParser()``). Optional argument *encoding* specifies an encoding that should be used to convert the file to unicode. @@ -1029,8 +1031,8 @@ .. versionadded:: 2.4 .. versionchanged:: 2.5 - The global ``__file__`` was added to the globals provided to doctests loaded - from a text file using :func:`DocFileSuite`. + The global ``__file__`` was added to the globals provided to doctests + loaded from a text file using :func:`DocFileSuite`. .. versionchanged:: 2.5 The parameter *encoding* was added. From buildbot at python.org Tue Mar 31 23:25:33 2009 From: buildbot at python.org (buildbot at python.org) Date: Tue, 31 Mar 2009 21:25:33 +0000 Subject: [Python-checkins] buildbot failure in ia64 Ubuntu trunk Message-ID: <20090331212533.9DD1B1E4094@bag.python.org> The Buildbot has detected a new failure of ia64 Ubuntu trunk. Full details are available at: http://www.python.org/dev/buildbot/all/ia64%20Ubuntu%20trunk/builds/1182 Buildbot URL: http://www.python.org/dev/buildbot/all/ Buildslave for this Build: klose-debian-ia64 Build Reason: Build Source Stamp: [branch trunk] HEAD Blamelist: georg.brandl,gregory.p.smith,jesse.noller,josiah.carlson,r.david.murray,raymond.hettinger BUILD FAILED: failed test Excerpt from the test logfile: 1 test failed: test_asyncore ====================================================================== FAIL: test_readwrite (test.test_asyncore.HelperFunctionTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_asyncore.py", line 144, in test_readwrite self.assertEqual(tobj.read, True) AssertionError: False != True ====================================================================== FAIL: test_unhandled (test.test_asyncore.DispatcherTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pybot/buildarea/trunk.klose-debian-ia64/build/Lib/test/test_asyncore.py", line 321, in test_unhandled self.assertEquals(lines, expected) AssertionError: First differing element 0: make: *** [buildbottest] Error 1 sincerely, -The Buildbot From python-checkins at python.org Tue Mar 31 23:34:42 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 31 Mar 2009 23:34:42 +0200 (CEST) Subject: [Python-checkins] r70897 - in python/trunk: Lib/test/test_threading.py Lib/threading.py Misc/NEWS Message-ID: <20090331213442.C21571E4033@bag.python.org> Author: benjamin.peterson Date: Tue Mar 31 23:34:42 2009 New Revision: 70897 Log: fix Thread.ident when it is the main thread or a dummy thread #5632 Modified: python/trunk/Lib/test/test_threading.py python/trunk/Lib/threading.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/test/test_threading.py ============================================================================== --- python/trunk/Lib/test/test_threading.py (original) +++ python/trunk/Lib/test/test_threading.py Tue Mar 31 23:34:42 2009 @@ -83,11 +83,24 @@ t.join(NUMTASKS) self.assert_(not t.is_alive()) self.failIfEqual(t.ident, 0) + self.assertFalse(t.ident is None) self.assert_(re.match('', repr(t))) if verbose: print 'all tasks done' self.assertEqual(numrunning.get(), 0) + def test_ident_of_no_threading_threads(self): + # The ident still must work for the main thread and dummy threads. + self.assertFalse(threading.currentThread().ident is None) + def f(): + ident.append(threading.currentThread().ident) + done.set() + done = threading.Event() + ident = [] + thread.start_new_thread(f, ()) + done.wait() + self.assertFalse(ident[0] is None) + # run with a small(ish) thread stack size (256kB) def test_various_ops_small_stack(self): if verbose: Modified: python/trunk/Lib/threading.py ============================================================================== --- python/trunk/Lib/threading.py (original) +++ python/trunk/Lib/threading.py Tue Mar 31 23:34:42 2009 @@ -500,9 +500,12 @@ return raise + def _set_ident(self): + self.__ident = _get_ident() + def __bootstrap_inner(self): try: - self.__ident = _get_ident() + self._set_ident() self.__started.set() with _active_limbo_lock: _active[self.__ident] = self @@ -733,6 +736,7 @@ def __init__(self): Thread.__init__(self, name="MainThread") self._Thread__started.set() + self._set_ident() with _active_limbo_lock: _active[_get_ident()] = self @@ -778,6 +782,7 @@ del self._Thread__block self._Thread__started.set() + self._set_ident() with _active_limbo_lock: _active[_get_ident()] = self Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Tue Mar 31 23:34:42 2009 @@ -199,6 +199,9 @@ Library ------- +- Issue #5632: Thread.ident was None for the main thread and threads not created + with the threading module. + - Issue #5400: Added patch for multiprocessing on netbsd compilation/support - Issue #5387: Fixed mmap.move crash by integer overflow. From python-checkins at python.org Tue Mar 31 23:37:16 2009 From: python-checkins at python.org (tarek.ziade) Date: Tue, 31 Mar 2009 23:37:16 +0200 (CEST) Subject: [Python-checkins] r70898 - in python/branches/py3k: Lib/distutils/cmd.py Lib/distutils/command/install_data.py Lib/distutils/command/install_headers.py Lib/distutils/command/register.py Lib/distutils/command/upload.py Lib/distutils/tests/support.py Lib/distutils/tests/test_clean.py Lib/distutils/tests/test_config.py Lib/distutils/tests/test_install_data.py Lib/distutils/tests/test_install_headers.py Lib/distutils/tests/test_register.py Lib/distutils/tests/test_sdist.py Lib/distutils/tests/test_upload.py Message-ID: <20090331213716.996521E4033@bag.python.org> Author: tarek.ziade Date: Tue Mar 31 23:37:16 2009 New Revision: 70898 Log: Merged revisions 70886,70888-70892 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70886 | tarek.ziade | 2009-03-31 15:50:59 -0500 (Tue, 31 Mar 2009) | 1 line added tests for the clean command ........ r70888 | tarek.ziade | 2009-03-31 15:53:13 -0500 (Tue, 31 Mar 2009) | 1 line more tests for the register command ........ r70889 | tarek.ziade | 2009-03-31 15:53:55 -0500 (Tue, 31 Mar 2009) | 1 line more tests for the upload command ........ r70890 | tarek.ziade | 2009-03-31 15:54:38 -0500 (Tue, 31 Mar 2009) | 1 line added test to the install_data command ........ r70891 | tarek.ziade | 2009-03-31 15:55:21 -0500 (Tue, 31 Mar 2009) | 1 line added tests to the install_headers command ........ r70892 | tarek.ziade | 2009-03-31 15:56:11 -0500 (Tue, 31 Mar 2009) | 1 line making sdist and config test silents ........ Added: python/branches/py3k/Lib/distutils/tests/test_clean.py - copied unchanged from r70892, /python/trunk/Lib/distutils/tests/test_clean.py python/branches/py3k/Lib/distutils/tests/test_install_data.py - copied unchanged from r70892, /python/trunk/Lib/distutils/tests/test_install_data.py python/branches/py3k/Lib/distutils/tests/test_install_headers.py - copied unchanged from r70892, /python/trunk/Lib/distutils/tests/test_install_headers.py Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/distutils/cmd.py python/branches/py3k/Lib/distutils/command/install_data.py python/branches/py3k/Lib/distutils/command/install_headers.py python/branches/py3k/Lib/distutils/command/register.py python/branches/py3k/Lib/distutils/command/upload.py python/branches/py3k/Lib/distutils/tests/support.py python/branches/py3k/Lib/distutils/tests/test_config.py python/branches/py3k/Lib/distutils/tests/test_register.py python/branches/py3k/Lib/distutils/tests/test_sdist.py python/branches/py3k/Lib/distutils/tests/test_upload.py Modified: python/branches/py3k/Lib/distutils/cmd.py ============================================================================== --- python/branches/py3k/Lib/distutils/cmd.py (original) +++ python/branches/py3k/Lib/distutils/cmd.py Tue Mar 31 23:37:16 2009 @@ -333,7 +333,7 @@ # -- External world manipulation ----------------------------------- def warn(self, msg): - sys.stderr.write("warning: %s: %s\n" % (self.get_command_name(), msg)) + log.warn("warning: %s: %s\n" % (self.get_command_name(), msg)) def execute(self, func, args, msg=None, level=1): util.execute(func, args, msg, dry_run=self.dry_run) Modified: python/branches/py3k/Lib/distutils/command/install_data.py ============================================================================== --- python/branches/py3k/Lib/distutils/command/install_data.py (original) +++ python/branches/py3k/Lib/distutils/command/install_data.py Tue Mar 31 23:37:16 2009 @@ -31,7 +31,6 @@ self.outfiles = [] self.root = None self.force = 0 - self.data_files = self.distribution.data_files self.warn_dir = 1 Modified: python/branches/py3k/Lib/distutils/command/install_headers.py ============================================================================== --- python/branches/py3k/Lib/distutils/command/install_headers.py (original) +++ python/branches/py3k/Lib/distutils/command/install_headers.py Tue Mar 31 23:37:16 2009 @@ -8,6 +8,7 @@ from distutils.core import Command +# XXX force is never used class install_headers(Command): description = "install C/C++ header files" Modified: python/branches/py3k/Lib/distutils/command/register.py ============================================================================== --- python/branches/py3k/Lib/distutils/command/register.py (original) +++ python/branches/py3k/Lib/distutils/command/register.py Tue Mar 31 23:37:16 2009 @@ -92,15 +92,14 @@ ''' url = self.repository+'?:action=list_classifiers' response = urllib.request.urlopen(url) - print(response.read()) + log.info(response.read()) def verify_metadata(self): ''' Send the metadata to the package index server to be checked. ''' # send the info to the server and report the result (code, result) = self.post_to_server(self.build_post_data('verify')) - print('Server response (%s): %s'%(code, result)) - + log.info('Server response (%s): %s' % (code, result)) def send_metadata(self): ''' Send the metadata to the package index server. @@ -211,17 +210,18 @@ data['email'] = input(' EMail: ') code, result = self.post_to_server(data) if code != 200: - print('Server response (%s): %s'%(code, result)) + log.info('Server response (%s): %s' % (code, result)) else: - print('You will receive an email shortly.') - print('Follow the instructions in it to complete registration.') + log.info('You will receive an email shortly.') + log.info(('Follow the instructions in it to ' + 'complete registration.')) elif choice == '3': data = {':action': 'password_reset'} data['email'] = '' while not data['email']: data['email'] = input('Your email address: ') code, result = self.post_to_server(data) - print('Server response (%s): %s'%(code, result)) + log.info('Server response (%s): %s' % (code, result)) def build_post_data(self, action): # figure the data to send - the metadata plus some additional @@ -254,8 +254,10 @@ def post_to_server(self, data, auth=None): ''' Post a query to the server, and return a string response. ''' - self.announce('Registering %s to %s' % (data['name'], - self.repository), log.INFO) + if 'name' in data: + self.announce('Registering %s to %s' % (data['name'], + self.repository), + log.INFO) # Build up the MIME payload for the urllib2 POST data boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' sep_boundary = '\n--' + boundary @@ -302,5 +304,6 @@ data = result.read() result = 200, 'OK' if self.show_response: - print('-'*75, data, '-'*75) + dashes = '-' * 75 + self.announce('%s%s%s' % (dashes, data, dashes)) return result Modified: python/branches/py3k/Lib/distutils/command/upload.py ============================================================================== --- python/branches/py3k/Lib/distutils/command/upload.py (original) +++ python/branches/py3k/Lib/distutils/command/upload.py Tue Mar 31 23:37:16 2009 @@ -194,4 +194,4 @@ self.announce('Upload failed (%s): %s' % (r.status, r.reason), log.ERROR) if self.show_response: - print('-'*75, r.read(), '-'*75) + self.announce('-'*75, r.read(), '-'*75) Modified: python/branches/py3k/Lib/distutils/tests/support.py ============================================================================== --- python/branches/py3k/Lib/distutils/tests/support.py (original) +++ python/branches/py3k/Lib/distutils/tests/support.py Tue Mar 31 23:37:16 2009 @@ -4,7 +4,7 @@ import tempfile from distutils import log - +from distutils.core import Distribution class LoggingSilencer(object): @@ -42,7 +42,7 @@ self.tempdirs.append(d) return d - def write_file(self, path, content): + def write_file(self, path, content='xxx'): """Writes a file in the given path. @@ -56,6 +56,23 @@ finally: f.close() + def create_dist(self, pkg_name='foo', **kw): + """Will generate a test environment. + + This function creates: + - a Distribution instance using keywords + - a temporary directory with a package structure + + It returns the package directory and the distribution + instance. + """ + tmp_dir = self.mkdtemp() + pkg_dir = os.path.join(tmp_dir, pkg_name) + os.mkdir(pkg_dir) + dist = Distribution(attrs=kw) + + return pkg_dir, dist + class DummyCommand: """Class to store options for retrieval via set_undefined_options().""" Modified: python/branches/py3k/Lib/distutils/tests/test_config.py ============================================================================== --- python/branches/py3k/Lib/distutils/tests/test_config.py (original) +++ python/branches/py3k/Lib/distutils/tests/test_config.py Tue Mar 31 23:37:16 2009 @@ -46,7 +46,9 @@ """ -class PyPIRCCommandTestCase(support.TempdirManager, unittest.TestCase): +class PyPIRCCommandTestCase(support.TempdirManager, + support.LoggingSilencer, + unittest.TestCase): def setUp(self): """Patches the environment.""" Modified: python/branches/py3k/Lib/distutils/tests/test_register.py ============================================================================== --- python/branches/py3k/Lib/distutils/tests/test_register.py (original) +++ python/branches/py3k/Lib/distutils/tests/test_register.py Tue Mar 31 23:37:16 2009 @@ -3,7 +3,9 @@ import os import unittest import getpass +import urllib +from distutils.command import register as register_module from distutils.command.register import register from distutils.core import Distribution @@ -42,18 +44,20 @@ finally: self.index += 1 -class FakeServer(object): +class FakeOpener(object): """Fakes a PyPI server""" def __init__(self): - self.calls = [] + self.reqs = [] def __call__(self, *args): - # we want to compare them, so let's store - # something comparable - els = list(args[0].items()) - els.sort() - self.calls.append(tuple(els)) - return 200, 'OK' + return self + + def open(self, req): + self.reqs.append(req) + return self + + def read(self): + return 'xxx' class registerTestCase(PyPIRCCommandTestCase): @@ -64,24 +68,27 @@ def _getpass(prompt): return 'password' getpass.getpass = _getpass + self.old_opener = urllib.request.build_opener + self.conn = urllib.request.build_opener = FakeOpener() def tearDown(self): getpass.getpass = self._old_getpass + urllib.request.build_opener = self.old_opener PyPIRCCommandTestCase.tearDown(self) + def _get_cmd(self): + metadata = {'url': 'xxx', 'author': 'xxx', + 'author_email': 'xxx', + 'name': 'xxx', 'version': 'xxx'} + pkg_info, dist = self.create_dist(**metadata) + return register(dist) + def test_create_pypirc(self): # this test makes sure a .pypirc file # is created when requested. - # let's create a fake distribution - # and a register instance - dist = Distribution() - dist.metadata.url = 'xxx' - dist.metadata.author = 'xxx' - dist.metadata.author_email = 'xxx' - dist.metadata.name = 'xxx' - dist.metadata.version = 'xxx' - cmd = register(dist) + # let's create a register instance + cmd = self._get_cmd() # we shouldn't have a .pypirc file yet self.assert_(not os.path.exists(self.rc)) @@ -95,13 +102,12 @@ # Password : 'password' # Save your login (y/N)? : 'y' inputs = Inputs('1', 'tarek', 'y') - from distutils.command import register as register_module register_module.input = inputs.__call__ - - cmd.post_to_server = pypi_server = FakeServer() - # let's run the command - cmd.run() + try: + cmd.run() + finally: + del register_module.input # we should have a brand new .pypirc file self.assert_(os.path.exists(self.rc)) @@ -115,32 +121,68 @@ # if we run the command again def _no_way(prompt=''): raise AssertionError(prompt) - register_module.raw_input = _no_way + register_module.input = _no_way + cmd.show_response = 1 cmd.run() # let's see what the server received : we should # have 2 similar requests - self.assert_(len(pypi_server.calls), 2) - self.assert_(pypi_server.calls[0], pypi_server.calls[1]) + self.assert_(self.conn.reqs, 2) + req1 = dict(self.conn.reqs[0].headers) + req2 = dict(self.conn.reqs[1].headers) + + self.assertEquals(req1['Content-length'], '1374') + self.assertEquals(req2['Content-length'], '1374') + self.assert_((b'xxx') in self.conn.reqs[1].data) def test_password_not_in_file(self): - f = open(self.rc, 'w') - f.write(PYPIRC_NOPASSWORD) - f.close() - - dist = Distribution() - cmd = register(dist) - cmd.post_to_server = FakeServer() - + self.write_file(self.rc, PYPIRC_NOPASSWORD) + cmd = self._get_cmd() cmd._set_config() cmd.finalize_options() cmd.send_metadata() # dist.password should be set # therefore used afterwards by other commands - self.assertEquals(dist.password, 'password') + self.assertEquals(cmd.distribution.password, 'password') + + def test_registering(self): + # this test runs choice 2 + cmd = self._get_cmd() + inputs = Inputs('2', 'tarek', 'tarek at ziade.org') + register_module.input = inputs.__call__ + try: + # let's run the command + cmd.run() + finally: + del register_module.input + + # we should have send a request + self.assert_(self.conn.reqs, 1) + req = self.conn.reqs[0] + headers = dict(req.headers) + self.assertEquals(headers['Content-length'], '608') + self.assert_((b'tarek') in req.data) + + def test_password_reset(self): + # this test runs choice 3 + cmd = self._get_cmd() + inputs = Inputs('3', 'tarek at ziade.org') + register_module.input = inputs.__call__ + try: + # let's run the command + cmd.run() + finally: + del register_module.input + + # we should have send a request + self.assert_(self.conn.reqs, 1) + req = self.conn.reqs[0] + headers = dict(req.headers) + self.assertEquals(headers['Content-length'], '290') + self.assert_((b'tarek') in req.data) def test_suite(): return unittest.makeSuite(registerTestCase) Modified: python/branches/py3k/Lib/distutils/tests/test_sdist.py ============================================================================== --- python/branches/py3k/Lib/distutils/tests/test_sdist.py (original) +++ python/branches/py3k/Lib/distutils/tests/test_sdist.py Tue Mar 31 23:37:16 2009 @@ -34,7 +34,7 @@ somecode%(sep)sdoc.txt """ -class sdistTestCase(support.LoggingSilencer, PyPIRCCommandTestCase): +class sdistTestCase(PyPIRCCommandTestCase): def setUp(self): # PyPIRCCommandTestCase creates a temp dir already Modified: python/branches/py3k/Lib/distutils/tests/test_upload.py ============================================================================== --- python/branches/py3k/Lib/distutils/tests/test_upload.py (original) +++ python/branches/py3k/Lib/distutils/tests/test_upload.py Tue Mar 31 23:37:16 2009 @@ -2,6 +2,7 @@ import sys import os import unittest +import http.client as httpclient from distutils.command.upload import upload from distutils.core import Distribution @@ -18,17 +19,52 @@ [server1] username:me """ +class Response(object): + def __init__(self, status=200, reason='OK'): + self.status = status + self.reason = reason +class FakeConnection(object): + + def __init__(self): + self.requests = [] + self.headers = [] + self.body = '' + + def __call__(self, netloc): + return self + + def connect(self): + pass + endheaders = connect + + def putrequest(self, method, url): + self.requests.append((method, url)) + + def putheader(self, name, value): + self.headers.append((name, value)) + + def send(self, body): + self.body = body + + def getresponse(self): + return Response() class uploadTestCase(PyPIRCCommandTestCase): + def setUp(self): + super(uploadTestCase, self).setUp() + self.old_class = httpclient.HTTPConnection + self.conn = httpclient.HTTPConnection = FakeConnection() + + def tearDown(self): + httpclient.HTTPConnection = self.old_class + super(uploadTestCase, self).tearDown() + def test_finalize_options(self): # new format - f = open(self.rc, 'w') - f.write(PYPIRC) - f.close() - + self.write_file(self.rc, PYPIRC) dist = Distribution() cmd = upload(dist) cmd.finalize_options() @@ -39,9 +75,7 @@ def test_saved_password(self): # file with no password - f = open(self.rc, 'w') - f.write(PYPIRC_NOPASSWORD) - f.close() + self.write_file(self.rc, PYPIRC_NOPASSWORD) # make sure it passes dist = Distribution() @@ -56,6 +90,28 @@ cmd.finalize_options() self.assertEquals(cmd.password, 'xxx') + def test_upload(self): + tmp = self.mkdtemp() + path = os.path.join(tmp, 'xxx') + self.write_file(path) + command, pyversion, filename = 'xxx', '2.6', path + dist_files = [(command, pyversion, filename)] + self.write_file(self.rc, PYPIRC) + + # lets run it + pkg_dir, dist = self.create_dist(dist_files=dist_files) + cmd = upload(dist) + cmd.ensure_finalized() + cmd.run() + + # what did we send ? + headers = dict(self.conn.headers) + self.assertEquals(headers['Content-length'], '2087') + self.assert_(headers['Content-type'].startswith('multipart/form-data')) + + self.assertEquals(self.conn.requests, [('POST', '/pypi')]) + self.assert_((b'xxx') in self.conn.body) + def test_suite(): return unittest.makeSuite(uploadTestCase) From python-checkins at python.org Tue Mar 31 23:40:00 2009 From: python-checkins at python.org (tarek.ziade) Date: Tue, 31 Mar 2009 23:40:00 +0200 (CEST) Subject: [Python-checkins] r70899 - python/branches/release30-maint Message-ID: <20090331214000.017D71E4033@bag.python.org> Author: tarek.ziade Date: Tue Mar 31 23:39:59 2009 New Revision: 70899 Log: Blocked revisions 70898 via svnmerge ................ r70898 | tarek.ziade | 2009-03-31 16:37:16 -0500 (Tue, 31 Mar 2009) | 29 lines Merged revisions 70886,70888-70892 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70886 | tarek.ziade | 2009-03-31 15:50:59 -0500 (Tue, 31 Mar 2009) | 1 line added tests for the clean command ........ r70888 | tarek.ziade | 2009-03-31 15:53:13 -0500 (Tue, 31 Mar 2009) | 1 line more tests for the register command ........ r70889 | tarek.ziade | 2009-03-31 15:53:55 -0500 (Tue, 31 Mar 2009) | 1 line more tests for the upload command ........ r70890 | tarek.ziade | 2009-03-31 15:54:38 -0500 (Tue, 31 Mar 2009) | 1 line added test to the install_data command ........ r70891 | tarek.ziade | 2009-03-31 15:55:21 -0500 (Tue, 31 Mar 2009) | 1 line added tests to the install_headers command ........ r70892 | tarek.ziade | 2009-03-31 15:56:11 -0500 (Tue, 31 Mar 2009) | 1 line making sdist and config test silents ........ ................ Modified: python/branches/release30-maint/ (props changed) From python-checkins at python.org Tue Mar 31 23:40:18 2009 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 31 Mar 2009 23:40:18 +0200 (CEST) Subject: [Python-checkins] r70900 - in python/branches/release26-maint: Lib/test/test_threading.py Lib/threading.py Misc/NEWS Message-ID: <20090331214018.B68C41E4365@bag.python.org> Author: benjamin.peterson Date: Tue Mar 31 23:40:18 2009 New Revision: 70900 Log: Merged revisions 70897 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r70897 | benjamin.peterson | 2009-03-31 16:34:42 -0500 (Tue, 31 Mar 2009) | 1 line fix Thread.ident when it is the main thread or a dummy thread #5632 ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_threading.py python/branches/release26-maint/Lib/threading.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/test/test_threading.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_threading.py (original) +++ python/branches/release26-maint/Lib/test/test_threading.py Tue Mar 31 23:40:18 2009 @@ -83,11 +83,24 @@ t.join(NUMTASKS) self.assert_(not t.is_alive()) self.failIfEqual(t.ident, 0) + self.assertFalse(t.ident is None) self.assert_(re.match('', repr(t))) if verbose: print 'all tasks done' self.assertEqual(numrunning.get(), 0) + def test_ident_of_no_threading_threads(self): + # The ident still must work for the main thread and dummy threads. + self.assertFalse(threading.currentThread().ident is None) + def f(): + ident.append(threading.currentThread().ident) + done.set() + done = threading.Event() + ident = [] + thread.start_new_thread(f, ()) + done.wait() + self.assertFalse(ident[0] is None) + # run with a small(ish) thread stack size (256kB) def test_various_ops_small_stack(self): if verbose: Modified: python/branches/release26-maint/Lib/threading.py ============================================================================== --- python/branches/release26-maint/Lib/threading.py (original) +++ python/branches/release26-maint/Lib/threading.py Tue Mar 31 23:40:18 2009 @@ -500,9 +500,12 @@ return raise + def _set_ident(self): + self.__ident = _get_ident() + def __bootstrap_inner(self): try: - self.__ident = _get_ident() + self._set_ident() self.__started.set() _active_limbo_lock.acquire() _active[self.__ident] = self @@ -734,6 +737,7 @@ def __init__(self): Thread.__init__(self, name="MainThread") self._Thread__started.set() + self._set_ident() _active_limbo_lock.acquire() _active[_get_ident()] = self _active_limbo_lock.release() @@ -780,6 +784,7 @@ del self._Thread__block self._Thread__started.set() + self._set_ident() _active_limbo_lock.acquire() _active[_get_ident()] = self _active_limbo_lock.release() Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Tue Mar 31 23:40:18 2009 @@ -92,6 +92,9 @@ Library ------- +- Issue #5632: Thread.ident was None for the main thread and threads not created + with the threading module. + - Issue #5400: Added patch for multiprocessing on netbsd compilation/support - Fix and properly document the multiprocessing module's logging From python-checkins at python.org Tue Mar 31 23:40:24 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 23:40:24 +0200 (CEST) Subject: [Python-checkins] r70901 - python/trunk/README Message-ID: <20090331214024.E4A0A1E4329@bag.python.org> Author: georg.brandl Date: Tue Mar 31 23:40:24 2009 New Revision: 70901 Log: Remove warning about pending Win9x support removal. Modified: python/trunk/README Modified: python/trunk/README ============================================================================== --- python/trunk/README (original) +++ python/trunk/README Tue Mar 31 23:40:24 2009 @@ -248,24 +248,9 @@ - Systems using --with-dl-dld - Systems using --without-universal-newlines - MacOS 9 - -The following systems are still supported in Python 2.5, but -support will be dropped in 2.6: - Systems using --with-wctype-functions - Win9x, WinME -Warning on install in Windows 98 and Windows Me ------------------------------------------------ - -Following Microsoft's closing of Extended Support for -Windows 98/ME (July 11, 2006), Python 2.6 will stop -supporting these platforms. Python development and -maintainability becomes easier (and more reliable) when -platform specific code targeting OSes with few users -and no dedicated expert developers is taken out. The -vendor also warns that the OS versions listed above -"can expose customers to security risks" and recommends -upgrade. Platform specific notes ----------------------- From python-checkins at python.org Tue Mar 31 23:43:03 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 23:43:03 +0200 (CEST) Subject: [Python-checkins] r70902 - python/trunk/README Message-ID: <20090331214303.AB5711E407C@bag.python.org> Author: georg.brandl Date: Tue Mar 31 23:43:03 2009 New Revision: 70902 Log: #1675026: add a note about a strange Windows problem, and remove notes about AtheOS. Modified: python/trunk/README Modified: python/trunk/README ============================================================================== --- python/trunk/README (original) +++ python/trunk/README Tue Mar 31 23:43:03 2009 @@ -647,75 +647,10 @@ News regarding these platforms with more recent Cygwin versions would be appreciated! -AtheOS: Official support has been stopped as of Python 2.6. All code will be - removed in Python 2.7 unless a maintainer steps forward for this - platform. - - From Octavian Cerna : - - Before building: - - Make sure you have shared versions of the libraries you - want to use with Python. You will have to compile them - yourself, or download precompiled packages. - - Recommended libraries: - - ncurses-4.2 - readline-4.2a - zlib-1.1.4 - - Build: - - $ ./configure --prefix=/usr/python - $ make - - Python is always built as a shared library, otherwise - dynamic loading would not work. - - Testing: - - $ make test - - Install: - - # make install - # pkgmanager -a /usr/python - - - AtheOS issues: - - - large file support: due to a stdio bug in glibc/libio, - access to large files may not work correctly. fseeko() - tries to seek to a negative offset. ftello() returns a - negative offset, it looks like a 32->64bit - sign-extension issue. The lowlevel functions (open, - lseek, etc) are OK. - - sockets: AF_UNIX is defined in the C library and in - Python, but not implemented in the system. - - select: poll is available in the C library, but does not - work (It does not return POLLNVAL for bad fds and - hangs). - - posix: statvfs and fstatvfs always return ENOSYS. - - disabled modules: - - mmap: not yet implemented in AtheOS - - nis: broken (on an unconfigured system - yp_get_default_domain() returns junk instead of - error) - - dl: dynamic loading doesn't work via dlopen() - - resource: getrimit and setrlimit are not yet - implemented - - - if you are getting segmentation faults, you probably are - low on memory. AtheOS doesn't handle very well an - out-of-memory condition and simply SEGVs the process. - - Tested on: - - AtheOS-0.3.7 - gcc-2.95 - binutils-2.10 - make-3.78 +Windows: When executing Python scripts on the command line using file type + associations (i.e. starting "script.py" instead of "python script.py"), + redirects may not work unless you set a specific registry key. See + the Knowledge Base article . Configuring the bsddb and dbm modules From python-checkins at python.org Tue Mar 31 23:45:19 2009 From: python-checkins at python.org (georg.brandl) Date: Tue, 31 Mar 2009 23:45:19 +0200 (CEST) Subject: [Python-checkins] r70903 - in python/trunk: configure configure.in Message-ID: <20090331214519.250791E43B0@bag.python.org> Author: georg.brandl Date: Tue Mar 31 23:45:18 2009 New Revision: 70903 Log: #1676135: remove trailing slashes from --prefix argument. Modified: python/trunk/configure python/trunk/configure.in Modified: python/trunk/configure ============================================================================== --- python/trunk/configure (original) +++ python/trunk/configure Tue Mar 31 23:45:18 2009 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 70479 . +# From configure.in Revision: 70730 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 2.7. # @@ -1807,6 +1807,11 @@ +if test "$prefix" != "/"; then + prefix=`echo "$prefix" | sed -e 's/\/$//g'` +fi + + Modified: python/trunk/configure.in ============================================================================== --- python/trunk/configure.in (original) +++ python/trunk/configure.in Tue Mar 31 23:45:18 2009 @@ -12,6 +12,15 @@ AC_CONFIG_SRCDIR([Include/object.h]) AC_CONFIG_HEADER(pyconfig.h) +dnl Ensure that if prefix is specified, it does not end in a slash. If +dnl it does, we get path names containing '//' which is both ugly and +dnl can cause trouble. + +dnl Last slash shouldn't be stripped if prefix=/ +if test "$prefix" != "/"; then + prefix=`echo "$prefix" | sed -e 's/\/$//g'` +fi + dnl This is for stuff that absolutely must end up in pyconfig.h. dnl Please use pyport.h instead, if possible. AH_TOP([ From python-checkins at python.org Tue Mar 31 23:49:36 2009 From: python-checkins at python.org (josiah.carlson) Date: Tue, 31 Mar 2009 23:49:36 +0200 (CEST) Subject: [Python-checkins] r70904 - python/trunk/Lib/asyncore.py Message-ID: <20090331214936.684741E43B1@bag.python.org> Author: josiah.carlson Date: Tue Mar 31 23:49:36 2009 New Revision: 70904 Log: Made handle_expt_event() be called last, so that we don't accidentally read after closing the socket. Modified: python/trunk/Lib/asyncore.py Modified: python/trunk/Lib/asyncore.py ============================================================================== --- python/trunk/Lib/asyncore.py (original) +++ python/trunk/Lib/asyncore.py Tue Mar 31 23:49:36 2009 @@ -97,14 +97,14 @@ def readwrite(obj, flags): try: - if flags & select.POLLPRI: - obj.handle_expt_event() if flags & select.POLLIN: obj.handle_read_event() if flags & select.POLLOUT: obj.handle_write_event() if flags & (select.POLLHUP | select.POLLERR | select.POLLNVAL): obj.handle_close() + if flags & select.POLLPRI: + obj.handle_expt_event() except _reraised_exceptions: raise except: From nnorwitz at gmail.com Tue Mar 31 23:00:43 2009 From: nnorwitz at gmail.com (Neal Norwitz) Date: Tue, 31 Mar 2009 16:00:43 -0500 Subject: [Python-checkins] Python Regression Test Failures doc (1) Message-ID: <20090331210043.GA15834@python.psfb.org> svn update tools/sphinx svn: PROPFIND request failed on '/projects/doctools/trunk/sphinx' svn: PROPFIND of '/projects/doctools/trunk/sphinx': Could not resolve hostname `svn.python.org': Host not found (http://svn.python.org) make: *** [update] Error 1
        Messages
        Messages
        Nosy count:
        Message count:
        No Sort or group: - +