Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cython
Commits
f0e8dd9d
Commit
f0e8dd9d
authored
5 years ago
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update grammar tests from Py3.8 master branch.
parent
57436e0b
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
296 additions
and
47 deletions
+296
-47
Cython/Compiler/Tests/TestGrammar.py
Cython/Compiler/Tests/TestGrammar.py
+35
-16
tests/run/test_grammar.py
tests/run/test_grammar.py
+261
-31
No files found.
Cython/Compiler/Tests/TestGrammar.py
View file @
f0e8dd9d
...
...
@@ -27,7 +27,15 @@ VALID_UNDERSCORE_LITERALS = [
'1e1_0'
,
'.1_4'
,
'.1_4e1'
,
'0b_0'
,
'0x_f'
,
'0o_5'
,
'1_00_00j'
,
'1_00_00.5j'
,
'1_00_00e5_1j'
,
'.1_4j'
,
'(1_2.5+3_3j)'
,
'(.5_6j)'
,
]
# Copied from CPython's test_grammar.py
...
...
@@ -36,22 +44,29 @@ INVALID_UNDERSCORE_LITERALS = [
'0_'
,
'42_'
,
'1.4j_'
,
'0x_'
,
'0b1_'
,
'0xf_'
,
'0o5_'
,
'0 if 1_Else 1'
,
# Underscores in the base selector:
'0_b0'
,
'0_xf'
,
'0_o5'
,
# Underscore right after the base selector:
'0b_0'
,
'0x_f'
,
'0o_5'
,
# Old-style octal, still disallowed:
# FIXME: still need to support PY_VERSION_HEX < 3
#'0_7',
#'09_99',
# Special case with exponent:
'0 if 1_Else 1'
,
# Multiple consecutive underscores:
'4_______2'
,
'0.1__4'
,
'0.1__4j'
,
'0b1001__0100'
,
'0xffff__ffff'
,
'0x___'
,
'0o5__77'
,
'1e1__0'
,
'1e1__0j'
,
# Underscore right before a dot:
'1_.4'
,
'1_.4j'
,
...
...
@@ -59,24 +74,24 @@ INVALID_UNDERSCORE_LITERALS = [
'1._4'
,
'1._4j'
,
'._5'
,
'._5j'
,
# Underscore right after a sign:
'1.0e+_1'
,
# Multiple consecutive underscores:
'4_______2'
,
'0.1__4'
,
'0b1001__0100'
,
'0xffff__ffff'
,
'0o5__77'
,
'1e1__0'
,
'1.0e+_1j'
,
# Underscore right before j:
'1.4_j'
,
'1.4e5_j'
,
# Underscore right before e:
'1_e1'
,
'1.4_e1'
,
'1.4_e1j'
,
# Underscore right after e:
'1e_1'
,
'1.4e_1'
,
'1.4e_1j'
,
# Complex cases with parens:
'(1+1.5_j_)'
,
'(1+1.5_j)'
,
# Whitespace in literals
'1_ 2'
,
'1 _2'
,
...
...
@@ -117,11 +132,15 @@ class TestGrammar(CythonTest):
# Add/MulNode() -> literal is first or second operand
literal_node
=
literal_node
.
operand2
if
i
%
2
else
literal_node
.
operand1
if
'j'
in
literal
or
'J'
in
literal
:
assert
isinstance
(
literal_node
,
ExprNodes
.
ImagNode
)
if
'+'
in
literal
:
# FIXME: tighten this test
assert
isinstance
(
literal_node
,
ExprNodes
.
AddNode
),
(
literal
,
literal_node
)
else
:
assert
isinstance
(
literal_node
,
ExprNodes
.
ImagNode
),
(
literal
,
literal_node
)
elif
'.'
in
literal
or
'e'
in
literal
or
'E'
in
literal
and
not
(
'0x'
in
literal
or
'0X'
in
literal
):
assert
isinstance
(
literal_node
,
ExprNodes
.
FloatNode
)
assert
isinstance
(
literal_node
,
ExprNodes
.
FloatNode
)
,
(
literal
,
literal_node
)
else
:
assert
isinstance
(
literal_node
,
ExprNodes
.
IntNode
)
assert
isinstance
(
literal_node
,
ExprNodes
.
IntNode
)
,
(
literal
,
literal_node
)
if
__name__
==
"__main__"
:
...
...
This diff is collapsed.
Click to expand it.
tests/run/test_grammar.py
View file @
f0e8dd9d
### COPIED FROM CPython 3.5 - ADDED PART FOLLOWS ###
# cython: language_level=3
import
cython
import
contextlib
from
tempfile
import
NamedTemporaryFile
from
Cython.Compiler.Main
import
compile
as
cython_compile
from
Cython.Compiler.Main
import
compile
as
cython_compile
,
CompileError
from
Cython.Build.Inline
import
cython_inline
def
_compile
(
code
):
with
NamedTemporaryFile
(
suffix
=
'.py'
)
as
f
:
f
.
write
(
code
.
encode
(
'utf8'
))
f
.
flush
()
@
contextlib
.
contextmanager
def
hidden_stderr
():
try
:
from
StringIO
import
StringIO
except
ImportError
:
...
...
@@ -19,29 +18,45 @@ def _compile(code):
old_stderr
=
sys
.
stderr
try
:
sys
.
stderr
=
StringIO
()
result
=
cython_compile
(
f
.
name
,
language_level
=
3
)
yield
finally
:
sys
.
stderr
=
old_stderr
def
_compile
(
code
):
with
NamedTemporaryFile
(
suffix
=
'.py'
)
as
f
:
f
.
write
(
code
.
encode
(
'utf8'
))
f
.
flush
()
with
hidden_stderr
():
result
=
cython_compile
(
f
.
name
,
language_level
=
3
)
return
result
def
check_syntax_error
(
test
,
code
):
def
check_syntax_error
(
test
,
code
,
msg
=
None
):
result
=
_compile
(
code
)
assert
not
result
.
c_file
def
compile
(
code
,
name
,
what
):
if
cython
.
compiled
:
def
compile
(
code
,
name
,
what
):
assert
what
==
'exec'
result
=
_compile
(
code
)
if
not
result
.
c_file
:
raise
SyntaxError
(
'unexpected EOF'
)
# see usage of compile() below
def
exec
(
code
):
def
exec
(
code
):
result
=
_compile
(
code
)
if
not
result
.
c_file
:
raise
SyntaxError
(
'unexpected EOF'
)
# see usage of compile() below
def
eval
(
code
):
try
:
with
hidden_stderr
():
return
cython_inline
(
code
)
except
CompileError
as
exc
:
raise
SyntaxError
(
str
(
exc
))
import
unittest
...
...
@@ -76,12 +91,104 @@ skip = unittest.skip
import
inspect
import
unittest
import
sys
import
warnings
# testing import *
from
sys
import
*
# different import patterns to check that __annotations__ does not interfere
# with import machinery
#import test.ann_module as ann_module
import
typing
from
collections
import
ChainMap
#from test import ann_module2
#import test
# These are shared with test_tokenize and other test modules.
#
# Note: since several test cases filter out floats by looking for "e" and ".",
# don't add hexadecimal literals that contain "e" or "E".
VALID_UNDERSCORE_LITERALS
=
[
'0_0_0'
,
'4_2'
,
'1_0000_0000'
,
'0b1001_0100'
,
'0xffff_ffff'
,
'0o5_7_7'
,
'1_00_00.5'
,
'1_00_00.5e5'
,
'1_00_00e5_1'
,
'1e1_0'
,
'.1_4'
,
'.1_4e1'
,
'0b_0'
,
'0x_f'
,
'0o_5'
,
'1_00_00j'
,
'1_00_00.5j'
,
'1_00_00e5_1j'
,
'.1_4j'
,
'(1_2.5+3_3j)'
,
'(.5_6j)'
,
]
INVALID_UNDERSCORE_LITERALS
=
[
# Trailing underscores:
'0_'
,
'42_'
,
'1.4j_'
,
'0x_'
,
'0b1_'
,
'0xf_'
,
'0o5_'
,
'0 if 1_Else 1'
,
# Underscores in the base selector:
'0_b0'
,
'0_xf'
,
'0_o5'
,
# Old-style octal, still disallowed:
'0_7'
,
'09_99'
,
# Multiple consecutive underscores:
'4_______2'
,
'0.1__4'
,
'0.1__4j'
,
'0b1001__0100'
,
'0xffff__ffff'
,
'0x___'
,
'0o5__77'
,
'1e1__0'
,
'1e1__0j'
,
# Underscore right before a dot:
'1_.4'
,
'1_.4j'
,
# Underscore right after a dot:
'1._4'
,
'1._4j'
,
'._5'
,
'._5j'
,
# Underscore right after a sign:
'1.0e+_1'
,
'1.0e+_1j'
,
# Underscore right before j:
'1.4_j'
,
'1.4e5_j'
,
# Underscore right before e:
'1_e1'
,
'1.4_e1'
,
'1.4_e1j'
,
# Underscore right after e:
'1e_1'
,
'1.4e_1'
,
'1.4e_1j'
,
# Complex cases with parens:
'(1+1.5_j_)'
,
'(1+1.5_j)'
,
]
class
TokenTests
(
unittest
.
TestCase
):
check_syntax_error
=
check_syntax_error
def
test_backslash
(
self
):
# Backslash means line continuation:
x
=
1
\
...
...
@@ -158,6 +265,38 @@ class TokenTests(unittest.TestCase):
self
.
assertEqual
(
1
if
0
else
0
,
0
)
self
.
assertRaises
(
SyntaxError
,
eval
,
"0 if 1Else 0"
)
@
skip
(
"Done more efficiently in TestGrammar"
)
def
test_underscore_literals
(
self
):
for
lit
in
VALID_UNDERSCORE_LITERALS
:
self
.
assertEqual
(
eval
(
lit
),
eval
(
lit
.
replace
(
'_'
,
''
)))
for
lit
in
INVALID_UNDERSCORE_LITERALS
:
self
.
assertRaises
(
SyntaxError
,
eval
,
lit
)
# Sanity check: no literal begins with an underscore
self
.
assertRaises
(
NameError
,
eval
,
"_0"
)
def
test_bad_numerical_literals
(
self
):
check
=
self
.
check_syntax_error
check
(
"0b12"
,
"invalid digit '2' in binary literal"
)
check
(
"0b1_2"
,
"invalid digit '2' in binary literal"
)
check
(
"0b2"
,
"invalid digit '2' in binary literal"
)
check
(
"0b1_"
,
"invalid binary literal"
)
check
(
"0b"
,
"invalid binary literal"
)
check
(
"0o18"
,
"invalid digit '8' in octal literal"
)
check
(
"0o1_8"
,
"invalid digit '8' in octal literal"
)
check
(
"0o8"
,
"invalid digit '8' in octal literal"
)
check
(
"0o1_"
,
"invalid octal literal"
)
check
(
"0o"
,
"invalid octal literal"
)
check
(
"0x1_"
,
"invalid hexadecimal literal"
)
check
(
"0x"
,
"invalid hexadecimal literal"
)
check
(
"1_"
,
"invalid decimal literal"
)
# FIXME: must still support PY_VERSION_HEX < 3 :(
#check("012",
# "leading zeros in decimal integer literals are not permitted; "
# "use an 0o prefix for octal integers")
check
(
"1.2_"
,
"invalid decimal literal"
)
check
(
"1e2_"
,
"invalid decimal literal"
)
check
(
"1e+"
,
"invalid decimal literal"
)
def
test_string_literals
(
self
):
x
=
''
;
y
=
""
;
self
.
assertTrue
(
len
(
x
)
==
0
and
x
==
y
)
x
=
'
\
'
'
;
y
=
"'"
;
self
.
assertTrue
(
len
(
x
)
==
1
and
x
==
y
and
ord
(
x
)
==
39
)
...
...
@@ -201,7 +340,8 @@ the \'lazy\' dog.\n\
def
test_ellipsis
(
self
):
x
=
...
self
.
assertTrue
(
x
is
Ellipsis
)
self
.
assertRaises
(
SyntaxError
,
eval
,
".. ."
)
# FIXME: why is this not rejected ???
#self.assertRaises(SyntaxError, eval, ".. .")
def
test_eof_error
(
self
):
samples
=
(
"def foo("
,
"
\
n
def foo("
,
"def foo(
\
n
"
)
...
...
@@ -225,6 +365,8 @@ class CNS:
class
GrammarTests
(
unittest
.
TestCase
):
check_syntax_error
=
check_syntax_error
# single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
# XXX can't test in a script -- this rule is only used when interactive
...
...
@@ -403,6 +545,16 @@ class GrammarTests(unittest.TestCase):
exec
(
'X: str'
,
{},
CNS2
())
self
.
assertEqual
(
nonloc_ns
[
'__annotations__'
][
'x'
],
str
)
@
skip
(
"Depends on 3-args compiled exec()"
)
def
test_var_annot_rhs
(
self
):
ns
=
{}
exec
(
'x: tuple = 1, 2'
,
ns
)
self
.
assertEqual
(
ns
[
'x'
],
(
1
,
2
))
stmt
=
(
'def f():
\
n
'
' x: int = yield'
)
exec
(
stmt
,
ns
)
self
.
assertEqual
(
list
(
ns
[
'f'
]()),
[
None
])
def
test_funcdef
(
self
):
### [decorators] 'def' NAME parameters ['->' test] ':' suite
### decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
...
...
@@ -598,7 +750,7 @@ class GrammarTests(unittest.TestCase):
def
f
(
x
)
->
list
:
pass
self
.
assertEqual
(
f
.
__annotations__
,
{
'return'
:
list
})
# test
MAKE_CLOSURE with a variety of oparg'
s
# test
closures with a variety of oparg
s
closure
=
1
def
f
():
return
closure
def
f
(
x
=
1
):
return
closure
...
...
@@ -848,6 +1000,59 @@ class GrammarTests(unittest.TestCase):
break
self
.
assertEqual
(
count
,
0
)
def
test_continue_in_finally
(
self
):
count
=
0
while
count
<
2
:
count
+=
1
try
:
pass
finally
:
continue
break
self
.
assertEqual
(
count
,
2
)
count
=
0
while
count
<
2
:
count
+=
1
try
:
break
finally
:
continue
self
.
assertEqual
(
count
,
2
)
count
=
0
while
count
<
2
:
count
+=
1
try
:
1
/
0
finally
:
continue
break
self
.
assertEqual
(
count
,
2
)
for
count
in
[
0
,
1
]:
try
:
pass
finally
:
continue
break
self
.
assertEqual
(
count
,
1
)
for
count
in
[
0
,
1
]:
try
:
break
finally
:
continue
self
.
assertEqual
(
count
,
1
)
for
count
in
[
0
,
1
]:
try
:
1
/
0
finally
:
continue
break
self
.
assertEqual
(
count
,
1
)
def
test_return_in_finally
(
self
):
def
g1
():
try
:
...
...
@@ -895,7 +1100,7 @@ class GrammarTests(unittest.TestCase):
def
g
():
f
((
yield
from
()),
1
)
# Do not require parenthesis for tuple unpacking
def
g
():
rest
=
4
,
5
,
6
;
yield
1
,
2
,
3
,
*
rest
self
.
assertEqual
s
(
list
(
g
()),
[(
1
,
2
,
3
,
4
,
5
,
6
)])
self
.
assertEqual
(
list
(
g
()),
[(
1
,
2
,
3
,
4
,
5
,
6
)])
check_syntax_error
(
self
,
"def g(): f(yield 1)"
)
check_syntax_error
(
self
,
"def g(): f(yield 1, 1)"
)
check_syntax_error
(
self
,
"def g(): f(yield from ())"
)
...
...
@@ -1132,11 +1337,34 @@ class GrammarTests(unittest.TestCase):
if
1
>
1
:
pass
if
1
<=
1
:
pass
if
1
>=
1
:
pass
if
1
is
1
:
pass
if
1
is
not
1
:
pass
if
x
is
x
:
pass
if
x
is
not
x
:
pass
if
1
in
():
pass
if
1
not
in
():
pass
if
1
<
1
>
1
==
1
>=
1
<=
1
!=
1
in
1
not
in
1
is
1
is
not
1
:
pass
if
1
<
1
>
1
==
1
>=
1
<=
1
!=
1
in
1
not
in
x
is
x
is
not
x
:
pass
@
skip
(
"DeprecationWarning not implemented"
)
def
test_comparison_is_literal
(
self
):
def
check
(
test
,
msg
=
'"is" with a literal'
):
with
self
.
assertWarnsRegex
(
SyntaxWarning
,
msg
):
compile
(
test
,
'<testcase>'
,
'exec'
)
with
warnings
.
catch_warnings
():
warnings
.
filterwarnings
(
'error'
,
category
=
SyntaxWarning
)
with
self
.
assertRaisesRegex
(
SyntaxError
,
msg
):
compile
(
test
,
'<testcase>'
,
'exec'
)
check
(
'x is 1'
)
check
(
'x is "thing"'
)
check
(
'1 is x'
)
check
(
'x is y is 1'
)
check
(
'x is not 1'
,
'"is not" with a literal'
)
with
warnings
.
catch_warnings
():
warnings
.
filterwarnings
(
'error'
,
category
=
SyntaxWarning
)
compile
(
'x is None'
,
'<testcase>'
,
'exec'
)
compile
(
'x is False'
,
'<testcase>'
,
'exec'
)
compile
(
'x is True'
,
'<testcase>'
,
'exec'
)
compile
(
'x is ...'
,
'<testcase>'
,
'exec'
)
def
test_binary_mask_ops
(
self
):
x
=
1
&
1
...
...
@@ -1399,7 +1627,7 @@ class GrammarTests(unittest.TestCase):
# Test ifelse expressions in various cases
def
_checkeval
(
msg
,
ret
):
"helper to check that evaluation of expressions is done correctly"
print
(
x
)
print
(
msg
)
return
ret
# the next line is not allowed anymore
...
...
@@ -1426,9 +1654,11 @@ class GrammarTests(unittest.TestCase):
self
.
assertEqual
(
16
//
(
4
//
2
),
8
)
self
.
assertEqual
((
16
//
4
)
//
2
,
2
)
self
.
assertEqual
(
16
//
4
//
2
,
2
)
self
.
assertTrue
(
False
is
(
2
is
3
))
self
.
assertFalse
((
False
is
2
)
is
3
)
self
.
assertFalse
(
False
is
2
is
3
)
x
=
2
y
=
3
self
.
assertTrue
(
False
is
(
x
is
y
))
self
.
assertFalse
((
False
is
x
)
is
y
)
self
.
assertFalse
(
False
is
x
is
y
)
def
test_matrix_mul
(
self
):
# This is not intended to be a comprehensive test, rather just to be few
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment