[Python-checkins] r67633 - in python/branches/release26-maint: Doc/documenting/rest.rst Doc/glossary.rst Doc/library/functions.rst Doc/library/getopt.rst Doc/library/operator.rst Doc/library/os.rst Doc/library/shutil.rst Doc/library/subprocess.rst Doc/reference/datamodel.rst Doc/tools/sphinxext/layout.html Lib/test/test_parser.py Lib/textwrap.py Misc/NEWS Modules/parsermodule.c

georg.brandl python-checkins at python.org
Sun Dec 7 15:47:13 CET 2008


Author: georg.brandl
Date: Sun Dec  7 15:47:12 2008
New Revision: 67633

Log:
Merged revisions 67571,67574-67576,67579-67581,67583,67591,67597,67608,67631 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r67571 | georg.brandl | 2008-12-05 10:13:45 +0100 (Fri, 05 Dec 2008) | 2 lines
  
  Use markup.
........
  r67574 | georg.brandl | 2008-12-05 10:25:32 +0100 (Fri, 05 Dec 2008) | 2 lines
  
  #4441 followup: Add link to open() docs for Windows.
........
  r67575 | georg.brandl | 2008-12-05 12:34:51 +0100 (Fri, 05 Dec 2008) | 2 lines
  
  #4544: add `dedent` to textwrap.__all__.
........
  r67576 | georg.brandl | 2008-12-05 13:09:41 +0100 (Fri, 05 Dec 2008) | 2 lines
  
  #4529: fix parser's validation for try-except-finally statements.
........
  r67579 | georg.brandl | 2008-12-05 16:29:39 +0100 (Fri, 05 Dec 2008) | 2 lines
  
  #4517: add "special method" glossary entry and clarify when __getattribute__ is bypassed.
........
  r67580 | georg.brandl | 2008-12-05 16:32:29 +0100 (Fri, 05 Dec 2008) | 2 lines
  
  #4478: document that copyfile() can raise Error.
........
  r67581 | georg.brandl | 2008-12-05 16:42:03 +0100 (Fri, 05 Dec 2008) | 2 lines
  
  #3171: document that *slice are removed in 3k.
........
  r67583 | georg.brandl | 2008-12-05 16:52:20 +0100 (Fri, 05 Dec 2008) | 4 lines
  
  Move __import__ to the bottom of the functions list.
  It doesn't make sense for such a fundamental document to have
  the most obscure function listed at the top.
........
  r67591 | georg.brandl | 2008-12-05 19:00:06 +0100 (Fri, 05 Dec 2008) | 2 lines
  
  Followup to #4511: add link from decorator glossary entry to definition.
........
  r67597 | georg.brandl | 2008-12-05 20:03:19 +0100 (Fri, 05 Dec 2008) | 2 lines
  
  Remove confusing sentence part.
........
  r67608 | georg.brandl | 2008-12-06 12:57:12 +0100 (Sat, 06 Dec 2008) | 2 lines
  
  Follow-up to #4488: document PIPE and STDOUT properly.
........
  r67631 | georg.brandl | 2008-12-07 12:54:07 +0100 (Sun, 07 Dec 2008) | 2 lines
  
  Add link to the favicon to the docs.
........


Modified:
   python/branches/release26-maint/   (props changed)
   python/branches/release26-maint/Doc/documenting/rest.rst
   python/branches/release26-maint/Doc/glossary.rst
   python/branches/release26-maint/Doc/library/functions.rst
   python/branches/release26-maint/Doc/library/getopt.rst
   python/branches/release26-maint/Doc/library/operator.rst
   python/branches/release26-maint/Doc/library/os.rst
   python/branches/release26-maint/Doc/library/shutil.rst
   python/branches/release26-maint/Doc/library/subprocess.rst
   python/branches/release26-maint/Doc/reference/datamodel.rst
   python/branches/release26-maint/Doc/tools/sphinxext/layout.html
   python/branches/release26-maint/Lib/test/test_parser.py
   python/branches/release26-maint/Lib/textwrap.py
   python/branches/release26-maint/Misc/NEWS
   python/branches/release26-maint/Modules/parsermodule.c

Modified: python/branches/release26-maint/Doc/documenting/rest.rst
==============================================================================
--- python/branches/release26-maint/Doc/documenting/rest.rst	(original)
+++ python/branches/release26-maint/Doc/documenting/rest.rst	Sun Dec  7 15:47:12 2008
@@ -98,7 +98,7 @@
 -----------
 
 Literal code blocks are introduced by ending a paragraph with the special marker
-``::``.  The literal block must be indented, to be able to include blank lines::
+``::``.  The literal block must be indented::
 
    This is a normal text paragraph. The next paragraph is a code sample::
 

Modified: python/branches/release26-maint/Doc/glossary.rst
==============================================================================
--- python/branches/release26-maint/Doc/glossary.rst	(original)
+++ python/branches/release26-maint/Doc/glossary.rst	Sun Dec  7 15:47:12 2008
@@ -123,6 +123,9 @@
          def f(...):
              ...
 
+      See :ref:`the documentation for function definition <function>` for more
+      about decorators.
+
    descriptor
       Any *new-style* object which defines the methods :meth:`__get__`,
       :meth:`__set__`, or :meth:`__delete__`.  When a class attribute is a
@@ -498,6 +501,12 @@
       (subscript) notation uses :class:`slice` objects internally (or in older
       versions, :meth:`__getslice__` and :meth:`__setslice__`).
 
+   special method
+      A method that is called implicitly by Python to execute a certain
+      operation on a type, such as addition.  Such methods have names starting
+      and ending with double underscores.  Special methods are documented in
+      :ref:`specialnames`.
+
    statement
       A statement is part of a suite (a "block" of code).  A statement is either
       an :term:`expression` or a one of several constructs with a keyword, such

Modified: python/branches/release26-maint/Doc/library/functions.rst
==============================================================================
--- python/branches/release26-maint/Doc/library/functions.rst	(original)
+++ python/branches/release26-maint/Doc/library/functions.rst	Sun Dec  7 15:47:12 2008
@@ -8,67 +8,6 @@
 available.  They are listed here in alphabetical order.
 
 
-.. function:: __import__(name[, globals[, locals[, fromlist[, level]]]])
-
-   .. index::
-      statement: import
-      module: ihooks
-      module: rexec
-      module: imp
-
-   .. note::
-
-      This is an advanced function that is not needed in everyday Python
-      programming.
-
-   The function is invoked by the :keyword:`import` statement.  It mainly exists
-   so that you can replace it with another function that has a compatible
-   interface, in order to change the semantics of the :keyword:`import` statement.
-   See the built-in module :mod:`imp`, which defines some useful operations out
-   of which you can build your own :func:`__import__` function.
-
-   For example, the statement ``import spam`` results in the following call:
-   ``__import__('spam', globals(), locals(), [], -1)``; the statement
-   ``from spam.ham import eggs`` results in ``__import__('spam.ham', globals(),
-   locals(), ['eggs'], -1)``.  Note that even though ``locals()`` and ``['eggs']``
-   are passed in as arguments, the :func:`__import__` function does not set the
-   local variable named ``eggs``; this is done by subsequent code that is generated
-   for the import statement.  (In fact, the standard implementation does not use
-   its *locals* argument at all, and uses its *globals* only to determine the
-   package context of the :keyword:`import` statement.)
-
-   When the *name* variable is of the form ``package.module``, normally, the
-   top-level package (the name up till the first dot) is returned, *not* the
-   module named by *name*.  However, when a non-empty *fromlist* argument is
-   given, the module named by *name* is returned.  This is done for
-   compatibility with the :term:`bytecode` generated for the different kinds of import
-   statement; when using ``import spam.ham.eggs``, the top-level package
-   :mod:`spam` must be placed in the importing namespace, but when using ``from
-   spam.ham import eggs``, the ``spam.ham`` subpackage must be used to find the
-   ``eggs`` variable.  As a workaround for this behavior, use :func:`getattr` to
-   extract the desired components.  For example, you could define the following
-   helper::
-
-      def my_import(name):
-          mod = __import__(name)
-          components = name.split('.')
-          for comp in components[1:]:
-              mod = getattr(mod, comp)
-          return mod
-
-   *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* indicate
-   the number of parent directories to search relative to the directory of the
-   module calling :func:`__import__`.
-
-   .. versionchanged:: 2.5
-      The level parameter was added.
-
-   .. versionchanged:: 2.5
-      Keyword support for parameters was added.
-
-
 .. function:: abs(x)
 
    Return the absolute value of a number.  The argument may be a plain or long
@@ -1419,6 +1358,67 @@
       Formerly, :func:`zip` required at least one argument and ``zip()`` raised a
       :exc:`TypeError` instead of returning an empty list.
 
+
+.. function:: __import__(name[, globals[, locals[, fromlist[, level]]]])
+
+   .. index::
+      statement: import
+      module: ihooks
+      module: rexec
+      module: imp
+
+   .. note::
+
+      This is an advanced function that is not needed in everyday Python
+      programming.
+
+   The function is invoked by the :keyword:`import` statement.  It mainly exists
+   so that you can replace it with another function that has a compatible
+   interface, in order to change the semantics of the :keyword:`import` statement.
+   See the built-in module :mod:`imp`, which defines some useful operations out
+   of which you can build your own :func:`__import__` function.
+
+   For example, the statement ``import spam`` results in the following call:
+   ``__import__('spam', globals(), locals(), [], -1)``; the statement
+   ``from spam.ham import eggs`` results in ``__import__('spam.ham', globals(),
+   locals(), ['eggs'], -1)``.  Note that even though ``locals()`` and ``['eggs']``
+   are passed in as arguments, the :func:`__import__` function does not set the
+   local variable named ``eggs``; this is done by subsequent code that is generated
+   for the import statement.  (In fact, the standard implementation does not use
+   its *locals* argument at all, and uses its *globals* only to determine the
+   package context of the :keyword:`import` statement.)
+
+   When the *name* variable is of the form ``package.module``, normally, the
+   top-level package (the name up till the first dot) is returned, *not* the
+   module named by *name*.  However, when a non-empty *fromlist* argument is
+   given, the module named by *name* is returned.  This is done for
+   compatibility with the :term:`bytecode` generated for the different kinds of import
+   statement; when using ``import spam.ham.eggs``, the top-level package
+   :mod:`spam` must be placed in the importing namespace, but when using ``from
+   spam.ham import eggs``, the ``spam.ham`` subpackage must be used to find the
+   ``eggs`` variable.  As a workaround for this behavior, use :func:`getattr` to
+   extract the desired components.  For example, you could define the following
+   helper::
+
+      def my_import(name):
+          mod = __import__(name)
+          components = name.split('.')
+          for comp in components[1:]:
+              mod = getattr(mod, comp)
+          return mod
+
+   *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* indicate
+   the number of parent directories to search relative to the directory of the
+   module calling :func:`__import__`.
+
+   .. versionchanged:: 2.5
+      The level parameter was added.
+
+   .. versionchanged:: 2.5
+      Keyword support for parameters was added.
+
 ..  ---------------------------------------------------------------------------
 
 

Modified: python/branches/release26-maint/Doc/library/getopt.rst
==============================================================================
--- python/branches/release26-maint/Doc/library/getopt.rst	(original)
+++ python/branches/release26-maint/Doc/library/getopt.rst	Sun Dec  7 15:47:12 2008
@@ -63,8 +63,8 @@
    non-option argument is encountered.
 
    If the first character of the option string is '+', or if the environment
-   variable POSIXLY_CORRECT is set, then option processing stops as soon as a
-   non-option argument is encountered.
+   variable :envvar:`POSIXLY_CORRECT` is set, then option processing stops as
+   soon as a non-option argument is encountered.
 
    .. versionadded:: 2.3
 

Modified: python/branches/release26-maint/Doc/library/operator.rst
==============================================================================
--- python/branches/release26-maint/Doc/library/operator.rst	(original)
+++ python/branches/release26-maint/Doc/library/operator.rst	Sun Dec  7 15:47:12 2008
@@ -240,6 +240,10 @@
 
    Delete the slice of *a* from index *b* to index *c-1*.
 
+   .. deprecated:: 2.6
+      This function is removed in Python 3.x.  Use :func:`delitem` with a slice
+      index.
+
 
 .. function:: getitem(a, b)
               __getitem__(a, b)
@@ -252,6 +256,10 @@
 
    Return the slice of *a* from index *b* to index *c-1*.
 
+   .. deprecated:: 2.6
+      This function is removed in Python 3.x.  Use :func:`getitem` with a slice
+      index.
+
 
 .. function:: indexOf(a, b)
 
@@ -283,6 +291,11 @@
 
    Set the slice of *a* from index *b* to index *c-1* to the sequence *v*.
 
+   .. deprecated:: 2.6
+      This function is removed in Python 3.x.  Use :func:`setitem` with a slice
+      index.
+
+
 Many operations have an "in-place" version.  The following functions provide a
 more primitive access to in-place operators than the usual syntax does; for
 example, the :term:`statement` ``x += y`` is equivalent to

Modified: python/branches/release26-maint/Doc/library/os.rst
==============================================================================
--- python/branches/release26-maint/Doc/library/os.rst	(original)
+++ python/branches/release26-maint/Doc/library/os.rst	Sun Dec  7 15:47:12 2008
@@ -684,8 +684,8 @@
 The following constants are options for the *flags* parameter to the
 :func:`open` function.  They can be combined using the bitwise OR operator
 ``|``.  Some of them are not available on all platforms.  For descriptions of
-their availability and use, consult the :manpage:`open(2)` manual page or the
-respective documentation for your operating system.
+their availability and use, consult the :manpage:`open(2)` manual page on Unix
+or `the MSDN <http://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>` on Windows.
 
 
 .. data:: O_RDONLY

Modified: python/branches/release26-maint/Doc/library/shutil.rst
==============================================================================
--- python/branches/release26-maint/Doc/library/shutil.rst	(original)
+++ python/branches/release26-maint/Doc/library/shutil.rst	Sun Dec  7 15:47:12 2008
@@ -43,7 +43,8 @@
 
    Copy the contents (no metadata) of the file named *src* to a file named *dst*.
    *dst* must be the complete target file name; look at :func:`copy` for a copy that
-   accepts a target directory path.
+   accepts a target directory path.  If *src* and *dst* are the same files,
+   :exc:`Error` is raised.
    The destination location must be writable; otherwise,  an :exc:`IOError` exception
    will be raised. If *dst* already exists, it will be replaced.   Special files
    such as character or block devices and pipes cannot be copied with this

Modified: python/branches/release26-maint/Doc/library/subprocess.rst
==============================================================================
--- python/branches/release26-maint/Doc/library/subprocess.rst	(original)
+++ python/branches/release26-maint/Doc/library/subprocess.rst	Sun Dec  7 15:47:12 2008
@@ -73,13 +73,13 @@
    specified by the :envvar:`COMSPEC` environment variable.
 
    *stdin*, *stdout* and *stderr* specify the executed programs' standard input,
-   standard output and standard error file handles, respectively.  Valid values are
-   ``PIPE``, an existing file descriptor (a positive integer), an existing file
-   object, and ``None``.  ``PIPE`` indicates that a new pipe to the child should be
-   created.  With ``None``, no redirection will occur; the child's file handles
-   will be inherited from the parent.  Additionally, *stderr* can be ``STDOUT``,
-   which indicates that the stderr data from the applications should be captured
-   into the same file handle as for stdout.
+   standard output and standard error file handles, respectively.  Valid values
+   are :data:`PIPE`, an existing file descriptor (a positive integer), an
+   existing file object, and ``None``.  :data:`PIPE` indicates that a new pipe
+   to the child should be created.  With ``None``, no redirection will occur;
+   the child's file handles will be inherited from the parent.  Additionally,
+   *stderr* can be :data:`STDOUT`, which indicates that the stderr data from the
+   applications should be captured into the same file handle as for stdout.
 
    If *preexec_fn* is set to a callable object, this object will be called in the
    child process just before the child is executed. (Unix only)
@@ -119,6 +119,20 @@
    of the main window and priority for the new process.  (Windows only)
 
 
+.. data:: PIPE
+
+   Special value that can be used as the *stdin*, *stdout* or *stderr* argument
+   to :class:`Popen` and indicates that a pipe to the standard stream should be
+   opened.
+
+
+.. data:: STDOUT
+
+   Special value that can be used as the *stderr* argument to :class:`Popen` and
+   indicates that standard error should go into the same handle as standard
+   output.
+   
+
 Convenience Functions
 ^^^^^^^^^^^^^^^^^^^^^
 
@@ -261,20 +275,21 @@
 
 .. attribute:: Popen.stdin
 
-   If the *stdin* argument is ``PIPE``, this attribute is a file object that
-   provides input to the child process.  Otherwise, it is ``None``.
+   If the *stdin* argument was :data:`PIPE`, this attribute is a file object
+   that provides input to the child process.  Otherwise, it is ``None``.
 
 
 .. attribute:: Popen.stdout
 
-   If the *stdout* argument is ``PIPE``, this attribute is a file object that
-   provides output from the child process.  Otherwise, it is ``None``.
+   If the *stdout* argument was :data:`PIPE`, this attribute is a file object
+   that provides output from the child process.  Otherwise, it is ``None``.
 
 
 .. attribute:: Popen.stderr
 
-   If the *stderr* argument is ``PIPE``, this attribute is file object that
-   provides error output from the child process.  Otherwise, it is ``None``.
+   If the *stderr* argument was :data:`PIPE`, this attribute is a file object
+   that provides error output from the child process.  Otherwise, it is
+   ``None``.
 
 
 .. attribute:: Popen.pid
@@ -454,15 +469,15 @@
              stdin=PIPE, stdout=PIPE, close_fds=True)
    (child_stdout, child_stdin) = (p.stdout, p.stdin)
 
-The popen2.Popen3 and popen2.Popen4 basically works as subprocess.Popen, except
-that:
+:class:`popen2.Popen3` and :class:`popen2.Popen4` basically work as
+:class:`subprocess.Popen`, except that:
 
-* subprocess.Popen raises an exception if the execution fails
+* :class:`Popen` raises an exception if the execution fails.
 
 * the *capturestderr* argument is replaced with the *stderr* argument.
 
-* stdin=PIPE and stdout=PIPE must be specified.
+* ``stdin=PIPE`` and ``stdout=PIPE`` must be specified.
 
 * popen2 closes all file descriptors by default, but you have to specify
-  close_fds=True with subprocess.Popen.
+  ``close_fds=True`` with :class:`Popen`.
 

Modified: python/branches/release26-maint/Doc/reference/datamodel.rst
==============================================================================
--- python/branches/release26-maint/Doc/reference/datamodel.rst	(original)
+++ python/branches/release26-maint/Doc/reference/datamodel.rst	Sun Dec  7 15:47:12 2008
@@ -2370,7 +2370,7 @@
    True
 
 In addition to bypassing any instance attributes in the interest of
-correctness, implicit special method lookup may also bypass the
+correctness, implicit special method lookup generally also bypasses the
 :meth:`__getattribute__` method even of the object's metaclass::
 
    >>> class Meta(type):

Modified: python/branches/release26-maint/Doc/tools/sphinxext/layout.html
==============================================================================
--- python/branches/release26-maint/Doc/tools/sphinxext/layout.html	(original)
+++ python/branches/release26-maint/Doc/tools/sphinxext/layout.html	Sun Dec  7 15:47:12 2008
@@ -1,4 +1,10 @@
 {% extends "!layout.html" %}
 {% block rootrellink %}
-<li><img src="{{ pathto('_static/py.png', 1) }}" alt="" style="vertical-align: middle; margin-top: -1px"/></li><li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li>
+        <li><img src="{{ pathto('_static/py.png', 1) }}" alt=""
+                 style="vertical-align: middle; margin-top: -1px"/></li>
+        <li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li>
+{% endblock %}
+{% block extrahead %}
+    <link rel="shortcut icon" type="image/png" href="{{ pathto('_static/py.png', 1) }}" />
+{{ super() }}
 {% endblock %}

Modified: python/branches/release26-maint/Lib/test/test_parser.py
==============================================================================
--- python/branches/release26-maint/Lib/test/test_parser.py	(original)
+++ python/branches/release26-maint/Lib/test/test_parser.py	Sun Dec  7 15:47:12 2008
@@ -200,6 +200,16 @@
         self.check_suite("with open('x'): pass\n")
         self.check_suite("with open('x') as f: pass\n")
 
+    def test_try_stmt(self):
+        self.check_suite("try: pass\nexcept: pass\n")
+        self.check_suite("try: pass\nfinally: pass\n")
+        self.check_suite("try: pass\nexcept A: pass\nfinally: pass\n")
+        self.check_suite("try: pass\nexcept A: pass\nexcept: pass\n"
+                         "finally: pass\n")
+        self.check_suite("try: pass\nexcept: pass\nelse: pass\n")
+        self.check_suite("try: pass\nexcept: pass\nelse: pass\n"
+                         "finally: pass\n")
+
     def test_position(self):
         # An absolutely minimal test of position information.  Better
         # tests would be a big project.

Modified: python/branches/release26-maint/Lib/textwrap.py
==============================================================================
--- python/branches/release26-maint/Lib/textwrap.py	(original)
+++ python/branches/release26-maint/Lib/textwrap.py	Sun Dec  7 15:47:12 2008
@@ -17,7 +17,7 @@
 #except NameError:
 #    (True, False) = (1, 0)
 
-__all__ = ['TextWrapper', 'wrap', 'fill']
+__all__ = ['TextWrapper', 'wrap', 'fill', 'dedent']
 
 # Hardcode the recognized whitespace characters to the US-ASCII
 # whitespace characters.  The main reason for doing this is that in

Modified: python/branches/release26-maint/Misc/NEWS
==============================================================================
--- python/branches/release26-maint/Misc/NEWS	(original)
+++ python/branches/release26-maint/Misc/NEWS	Sun Dec  7 15:47:12 2008
@@ -80,6 +80,15 @@
 Library
 -------
 
+- Issue #4529: fix the parser module's validation of try-except-finally
+  statements.
+
+- Issue #4458: getopt.gnu_getopt() now recognizes a single "-" as an argument,
+  not a malformed option.
+
+- Added the subprocess.check_output() convenience function to get output
+  from a subprocess on success or raise an exception on error.
+
 - Issue #1055234: cgi.parse_header(): Fixed parsing of header parameters to
   support unusual filenames (such as those containing semi-colons) in
   Content-Disposition headers.

Modified: python/branches/release26-maint/Modules/parsermodule.c
==============================================================================
--- python/branches/release26-maint/Modules/parsermodule.c	(original)
+++ python/branches/release26-maint/Modules/parsermodule.c	Sun Dec  7 15:47:12 2008
@@ -2057,6 +2057,7 @@
 
 /*  try_stmt:
  *      'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
+                                                   ['finally' ':' suite]
  *    | 'try' ':' suite 'finally' ':' suite
  *
  */
@@ -2082,35 +2083,34 @@
         PyErr_Format(parser_error,
                      "Illegal number of children for try/%s node.", name);
     }
-    /*  Skip past except_clause sections:  */
+    /* Handle try/finally statement */
+    if (res && (TYPE(CHILD(tree, pos)) == NAME) &&
+        (strcmp(STR(CHILD(tree, pos)), "finally") == 0)) {
+        res = (validate_numnodes(tree, 6, "try/finally")
+               && validate_colon(CHILD(tree, 4))
+               && validate_suite(CHILD(tree, 5)));
+        return (res);
+    }
+    /* try/except statement: skip past except_clause sections */
     while (res && (TYPE(CHILD(tree, pos)) == except_clause)) {
         res = (validate_except_clause(CHILD(tree, pos))
                && validate_colon(CHILD(tree, pos + 1))
                && validate_suite(CHILD(tree, pos + 2)));
         pos += 3;
     }
-    if (res && (pos < nch)) {
-        res = validate_ntype(CHILD(tree, pos), NAME);
-        if (res && (strcmp(STR(CHILD(tree, pos)), "finally") == 0))
-            res = (validate_numnodes(tree, 6, "try/finally")
-                   && validate_colon(CHILD(tree, 4))
-                   && validate_suite(CHILD(tree, 5)));
-        else if (res) {
-            if (nch == (pos + 3)) {
-                res = ((strcmp(STR(CHILD(tree, pos)), "except") == 0)
-                       || (strcmp(STR(CHILD(tree, pos)), "else") == 0));
-                if (!res)
-                    err_string("illegal trailing triple in try statement");
-            }
-            else if (nch == (pos + 6)) {
-                res = (validate_name(CHILD(tree, pos), "except")
-                       && validate_colon(CHILD(tree, pos + 1))
-                       && validate_suite(CHILD(tree, pos + 2))
-                       && validate_name(CHILD(tree, pos + 3), "else"));
-            }
-            else
-                res = validate_numnodes(tree, pos + 3, "try/except");
-        }
+    /* skip else clause */
+    if (res && (TYPE(CHILD(tree, pos)) == NAME) &&
+        (strcmp(STR(CHILD(tree, pos)), "else") == 0)) {
+        res = (validate_colon(CHILD(tree, pos + 1))
+               && validate_suite(CHILD(tree, pos + 2)));
+        pos += 3;
+    }
+    if (res && pos < nch) {
+        /* last clause must be a finally */
+        res = (validate_name(CHILD(tree, pos), "finally")
+               && validate_numnodes(tree, pos + 3, "try/except/finally")
+               && validate_colon(CHILD(tree, pos + 1))
+               && validate_suite(CHILD(tree, pos + 2)));
     }
     return (res);
 }


More information about the Python-checkins mailing list