diff --git a/Lib/getopt.py b/Lib/getopt.py index 93777b4937f..13ef4d623ec 100644 --- a/Lib/getopt.py +++ b/Lib/getopt.py @@ -130,7 +130,7 @@ def gnu_getopt(args, shortopts, longopts = []): if args[0][:2] == '--': opts, args = do_longs(opts, args[0][2:], longopts, args[1:]) - elif args[0][:1] == '-': + elif args[0][:1] == '-' and args[0] != '-': opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:]) else: if all_options_first: diff --git a/Lib/test/test_getopt.py b/Lib/test/test_getopt.py index de3325d7ee9..11ae163c6d0 100644 --- a/Lib/test/test_getopt.py +++ b/Lib/test/test_getopt.py @@ -124,6 +124,11 @@ class GetoptTests(unittest.TestCase): self.assertEqual(opts, [('-a', ''), ('-b', '1'), ('--alpha', ''), ('--beta', '2')]) + # recognize "-" as an argument + opts, args = getopt.gnu_getopt(['-a', '-', '-b', '-'], 'ab:', []) + self.assertEqual(args, ['-']) + self.assertEqual(opts, [('-a', ''), ('-b', '-')]) + # Posix style via + opts, args = getopt.gnu_getopt(cmdline, '+ab:', ['alpha', 'beta=']) self.assertEqual(opts, [('-a', '')]) diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 17d19886cde..2f1310b4a31 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -193,6 +193,16 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase): 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. diff --git a/Misc/NEWS b/Misc/NEWS index 81b0900b633..19581d68d57 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -31,6 +31,15 @@ Library - Issue #4483: _dbm module now builds on systems with gdbm & gdbm_compat libs. +- 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 #4542: On Windows, binascii.crc32 still accepted str as binary input; the corresponding tests now pass. diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c index 51660aaad05..6778fb41d4e 100644 --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -1862,6 +1862,7 @@ validate_for(node *tree) /* try_stmt: * 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite] + ['finally' ':' suite] * | 'try' ':' suite 'finally' ':' suite * */ @@ -1887,35 +1888,34 @@ validate_try(node *tree) 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); } diff --git a/configure.in b/configure.in index bf064583411..5acc141857e 100644 --- a/configure.in +++ b/configure.in @@ -1770,7 +1770,7 @@ AC_MSG_RESULT($SHLIBS) AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX -# only check for sem_ini if thread support is requested +# only check for sem_init if thread support is requested if test "$with_threads" = "yes" -o -z "$with_threads"; then AC_SEARCH_LIBS(sem_init, pthread rt posix4) # 'Real Time' functions on Solaris # posix4 on Solaris 2.6