Commit c1bbe81a authored by Stefan Behnel's avatar Stefan Behnel

enable except-as target deletion only when language level is 3

parent f49d1f6f
...@@ -1573,7 +1573,8 @@ def p_except_clause(s): ...@@ -1573,7 +1573,8 @@ def p_except_clause(s):
exc_type = exc_type.args exc_type = exc_type.args
else: else:
exc_type = [exc_type] exc_type = [exc_type]
if s.sy == ',': if s.sy == ',' or (s.sy == 'IDENT' and s.systring == 'as'
and s.context.language_level == 2):
s.next() s.next()
exc_value = p_test(s) exc_value = p_test(s)
elif s.sy == 'IDENT' and s.systring == 'as': elif s.sy == 'IDENT' and s.systring == 'as':
......
# cython: language_level=3 # cython: language_level=3
# mode: run # mode: run
# tag: generators, python3 # tag: generators, python3, exceptions
cimport cython cimport cython
...@@ -11,6 +11,11 @@ __doc__ = """ ...@@ -11,6 +11,11 @@ __doc__ = """
a = 1 a = 1
b = 2 b = 2
x = u'abc' x = u'abc'
>>> except_as_deletes
True
>>> no_match_does_not_touch_target
True
""" """
import sys import sys
...@@ -22,6 +27,115 @@ def locals_function(a, b=2): ...@@ -22,6 +27,115 @@ def locals_function(a, b=2):
return locals() return locals()
### module level except-as tests
exc = [None]
e = None
try:
raise KeyError
except AttributeError as e:
exc[0] = e
except KeyError as e:
exc[0] = e
except IndexError as e:
exc[0] = e
except:
exc[0] = 'SOMETHING ELSE'
try:
e
except NameError:
except_as_deletes = True
else:
except_as_deletes = False
e = 123
try:
raise TypeError
except NameError as e:
pass
except TypeError:
pass
no_match_does_not_touch_target = (e == 123)
### more except-as tests
def except_as_raise_deletes_target(x, a):
"""
>>> except_as_raise_deletes_target(None, TypeError)
1
1
>>> except_as_raise_deletes_target(TypeError('test'), TypeError)
Traceback (most recent call last):
UnboundLocalError: local variable 'b' referenced before assignment
>>> except_as_raise_deletes_target(ValueError('test'), TypeError)
Traceback (most recent call last):
ValueError: test
>>> except_as_raise_deletes_target(None, TypeError)
1
1
"""
b = 1
try:
i = 1
if x:
raise x
except a as b:
i = 2
assert isinstance(b, a)
print(b) # raises UnboundLocalError if except clause was executed
return i
def except_as_raise_with_empty_except(x, a):
"""
>>> except_as_raise_with_empty_except(None, TypeError)
>>> except_as_raise_with_empty_except(TypeError('test'), TypeError)
>>> except_as_raise_with_empty_except(ValueError('test'), TypeError)
Traceback (most recent call last):
ValueError: test
>>> except_as_raise_with_empty_except(None, TypeError)
"""
try:
if x:
raise x
b = 1
except a as b: # previously raised UnboundLocalError
pass
def except_as_deletes_target_in_gen(x, a):
"""
>>> list(except_as_deletes_target_in_gen(None, TypeError))
[(1, 1), (2, 1), (5, 1)]
>>> list(except_as_deletes_target_in_gen(TypeError('test'), TypeError))
[(1, 1), 3, 6]
>>> list(except_as_deletes_target_in_gen(ValueError('test'), TypeError))
[(1, 1), (4, 1), (5, 1)]
"""
b = 1
try:
i = 1
yield (1, b)
if x:
raise x
yield (2, b)
except a as b:
i = 2
assert isinstance(b, a)
yield 3
except:
yield (4, b)
try:
yield (5, b)
except UnboundLocalError:
yield 6
### Py3 feature tests
def print_function(*args): def print_function(*args):
""" """
>>> print_function(1,2,3) >>> print_function(1,2,3)
...@@ -29,6 +143,7 @@ def print_function(*args): ...@@ -29,6 +143,7 @@ def print_function(*args):
""" """
print(*args) # this isn't valid Py2 syntax print(*args) # this isn't valid Py2 syntax
def exec3_function(cmd): def exec3_function(cmd):
""" """
>>> exec3_function('a = 1+1')['a'] >>> exec3_function('a = 1+1')['a']
......
...@@ -14,9 +14,9 @@ __doc__ = u""" ...@@ -14,9 +14,9 @@ __doc__ = u"""
>>> exc[3] is val >>> exc[3] is val
True True
>>> except_as_deletes >>> except_as_deletes # Py2 behaviour
True False
>>> no_match_does_not_delete >>> no_match_does_not_touch_target
True True
""" """
...@@ -81,7 +81,7 @@ except NameError as e: ...@@ -81,7 +81,7 @@ except NameError as e:
pass pass
except TypeError: except TypeError:
pass pass
no_match_does_not_delete = (e == 123) no_match_does_not_touch_target = (e == 123)
try: try:
raise IndexError raise IndexError
......
...@@ -358,19 +358,16 @@ def except_as_no_raise_does_not_touch_target(a): ...@@ -358,19 +358,16 @@ def except_as_no_raise_does_not_touch_target(a):
i = 2 i = 2
return i, b return i, b
def except_as_raise_deletes_target(x, a): def except_as_raise_does_not_delete_target(x, a):
""" """
>>> except_as_raise_deletes_target(None, TypeError) >>> except_as_raise_does_not_delete_target(None, TypeError)
1 1
1 >>> except_as_raise_does_not_delete_target(TypeError('test'), TypeError)
>>> except_as_raise_deletes_target(TypeError('test'), TypeError) 2
Traceback (most recent call last): >>> except_as_raise_does_not_delete_target(ValueError('test'), TypeError)
UnboundLocalError: local variable 'b' referenced before assignment
>>> except_as_raise_deletes_target(ValueError('test'), TypeError)
Traceback (most recent call last): Traceback (most recent call last):
ValueError: test ValueError: test
>>> except_as_raise_deletes_target(None, TypeError) >>> except_as_raise_does_not_delete_target(None, TypeError)
1
1 1
""" """
b = 1 b = 1
...@@ -381,7 +378,12 @@ def except_as_raise_deletes_target(x, a): ...@@ -381,7 +378,12 @@ def except_as_raise_deletes_target(x, a):
except a as b: except a as b:
i = 2 i = 2
assert isinstance(b, a) assert isinstance(b, a)
print(b) # raises UnboundLocalError if except clause was executed
# exception variable leaks with Py2 except-as semantics
if x:
assert isinstance(b, a)
else:
assert b == 1
return i return i
def except_as_raise_with_empty_except(x, a): def except_as_raise_with_empty_except(x, a):
...@@ -397,35 +399,12 @@ def except_as_raise_with_empty_except(x, a): ...@@ -397,35 +399,12 @@ def except_as_raise_with_empty_except(x, a):
if x: if x:
raise x raise x
b = 1 b = 1
except a as b: # previously raised UnboundLocalError
pass
def except_as_deletes_target_in_gen(x, a):
"""
>>> list(except_as_deletes_target_in_gen(None, TypeError))
[(1, 1), (2, 1), (5, 1)]
>>> list(except_as_deletes_target_in_gen(TypeError('test'), TypeError))
[(1, 1), 3, 6]
>>> list(except_as_deletes_target_in_gen(ValueError('test'), TypeError))
[(1, 1), (4, 1), (5, 1)]
"""
b = 1
try:
i = 1
yield (1, b)
if x:
raise x
yield (2, b)
except a as b: except a as b:
i = 2 pass
if x:
assert isinstance(b, a) assert isinstance(b, a)
yield 3 else:
except: assert b == 1
yield (4, b)
try:
yield (5, b)
except UnboundLocalError:
yield 6
def complete_except_as_no_raise(a, b): def complete_except_as_no_raise(a, b):
""" """
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment