Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
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
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
fecf254c
Commit
fecf254c
authored
Aug 09, 2011
by
Benjamin Peterson
Browse files
Options
Browse Files
Download
Plain Diff
merge heads
parents
0d51e5d7
83d783e6
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
932 additions
and
15 deletions
+932
-15
Doc/c-api/typeobj.rst
Doc/c-api/typeobj.rst
+5
-0
Include/Python-ast.h
Include/Python-ast.h
+2
-2
Include/asdl.h
Include/asdl.h
+1
-0
Include/ast.h
Include/ast.h
+1
-0
Lib/test/test_ast.py
Lib/test/test_ast.py
+408
-2
Misc/NEWS
Misc/NEWS
+2
-0
Parser/Python.asdl
Parser/Python.asdl
+2
-2
Parser/asdl.py
Parser/asdl.py
+1
-1
Parser/asdl_c.py
Parser/asdl_c.py
+10
-0
Python/Python-ast.c
Python/Python-ast.c
+14
-4
Python/ast.c
Python/ast.c
+482
-4
Python/bltinmodule.c
Python/bltinmodule.c
+4
-0
No files found.
Doc/c-api/typeobj.rst
View file @
fecf254c
...
@@ -745,6 +745,11 @@ type objects) *must* have the :attr:`ob_size` field.
...
@@ -745,6 +745,11 @@ type objects) *must* have the :attr:`ob_size` field.
This field is not inherited by subtypes (though the attributes defined in here
This field is not inherited by subtypes (though the attributes defined in here
are inherited through a different mechanism).
are inherited through a different mechanism).
.. warning::
It is not safe to use :c:func:`PyDict_SetItem` on or otherwise modify
:attr:`tp_dict` with the dictionary C-API.
.. c:member:: descrgetfunc PyTypeObject.tp_descr_get
.. c:member:: descrgetfunc PyTypeObject.tp_descr_get
...
...
Include/Python-ast.h
View file @
fecf254c
...
@@ -271,7 +271,7 @@ struct _expr {
...
@@ -271,7 +271,7 @@ struct _expr {
}
Str
;
}
Str
;
struct
{
struct
{
string
s
;
bytes
s
;
}
Bytes
;
}
Bytes
;
struct
{
struct
{
...
@@ -501,7 +501,7 @@ expr_ty _Py_Num(object n, int lineno, int col_offset, PyArena *arena);
...
@@ -501,7 +501,7 @@ expr_ty _Py_Num(object n, int lineno, int col_offset, PyArena *arena);
#define Str(a0, a1, a2, a3) _Py_Str(a0, a1, a2, a3)
#define Str(a0, a1, a2, a3) _Py_Str(a0, a1, a2, a3)
expr_ty
_Py_Str
(
string
s
,
int
lineno
,
int
col_offset
,
PyArena
*
arena
);
expr_ty
_Py_Str
(
string
s
,
int
lineno
,
int
col_offset
,
PyArena
*
arena
);
#define Bytes(a0, a1, a2, a3) _Py_Bytes(a0, a1, a2, a3)
#define Bytes(a0, a1, a2, a3) _Py_Bytes(a0, a1, a2, a3)
expr_ty
_Py_Bytes
(
string
s
,
int
lineno
,
int
col_offset
,
PyArena
*
arena
);
expr_ty
_Py_Bytes
(
bytes
s
,
int
lineno
,
int
col_offset
,
PyArena
*
arena
);
#define Ellipsis(a0, a1, a2) _Py_Ellipsis(a0, a1, a2)
#define Ellipsis(a0, a1, a2) _Py_Ellipsis(a0, a1, a2)
expr_ty
_Py_Ellipsis
(
int
lineno
,
int
col_offset
,
PyArena
*
arena
);
expr_ty
_Py_Ellipsis
(
int
lineno
,
int
col_offset
,
PyArena
*
arena
);
#define Attribute(a0, a1, a2, a3, a4, a5) _Py_Attribute(a0, a1, a2, a3, a4, a5)
#define Attribute(a0, a1, a2, a3, a4, a5) _Py_Attribute(a0, a1, a2, a3, a4, a5)
...
...
Include/asdl.h
View file @
fecf254c
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
typedef
PyObject
*
identifier
;
typedef
PyObject
*
identifier
;
typedef
PyObject
*
string
;
typedef
PyObject
*
string
;
typedef
PyObject
*
bytes
;
typedef
PyObject
*
object
;
typedef
PyObject
*
object
;
/* It would be nice if the code generated by asdl_c.py was completely
/* It would be nice if the code generated by asdl_c.py was completely
...
...
Include/ast.h
View file @
fecf254c
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
extern
"C"
{
extern
"C"
{
#endif
#endif
PyAPI_FUNC
(
int
)
PyAST_Validate
(
mod_ty
);
PyAPI_FUNC
(
mod_ty
)
PyAST_FromNode
(
PyAPI_FUNC
(
mod_ty
)
PyAST_FromNode
(
const
node
*
n
,
const
node
*
n
,
PyCompilerFlags
*
flags
,
PyCompilerFlags
*
flags
,
...
...
Lib/test/test_ast.py
View file @
fecf254c
import
sys
,
unittest
import
os
import
sys
import
unittest
from
test
import
support
from
test
import
support
import
ast
import
ast
...
@@ -490,8 +492,412 @@ class ASTHelpers_Test(unittest.TestCase):
...
@@ -490,8 +492,412 @@ class ASTHelpers_Test(unittest.TestCase):
self
.
assertEqual
(
ast
.
literal_eval
(
'1.5 - 2j'
),
1.5
-
2j
)
self
.
assertEqual
(
ast
.
literal_eval
(
'1.5 - 2j'
),
1.5
-
2j
)
class
ASTValidatorTests
(
unittest
.
TestCase
):
def
mod
(
self
,
mod
,
msg
=
None
,
mode
=
"exec"
,
*
,
exc
=
ValueError
):
mod
.
lineno
=
mod
.
col_offset
=
0
ast
.
fix_missing_locations
(
mod
)
with
self
.
assertRaises
(
exc
)
as
cm
:
compile
(
mod
,
"<test>"
,
mode
)
if
msg
is
not
None
:
self
.
assertIn
(
msg
,
str
(
cm
.
exception
))
def
expr
(
self
,
node
,
msg
=
None
,
*
,
exc
=
ValueError
):
mod
=
ast
.
Module
([
ast
.
Expr
(
node
)])
self
.
mod
(
mod
,
msg
,
exc
=
exc
)
def
stmt
(
self
,
stmt
,
msg
=
None
):
mod
=
ast
.
Module
([
stmt
])
self
.
mod
(
mod
,
msg
)
def
test_module
(
self
):
m
=
ast
.
Interactive
([
ast
.
Expr
(
ast
.
Name
(
"x"
,
ast
.
Store
()))])
self
.
mod
(
m
,
"must have Load context"
,
"single"
)
m
=
ast
.
Expression
(
ast
.
Name
(
"x"
,
ast
.
Store
()))
self
.
mod
(
m
,
"must have Load context"
,
"eval"
)
def
_check_arguments
(
self
,
fac
,
check
):
def
arguments
(
args
=
None
,
vararg
=
None
,
varargannotation
=
None
,
kwonlyargs
=
None
,
kwarg
=
None
,
kwargannotation
=
None
,
defaults
=
None
,
kw_defaults
=
None
):
if
args
is
None
:
args
=
[]
if
kwonlyargs
is
None
:
kwonlyargs
=
[]
if
defaults
is
None
:
defaults
=
[]
if
kw_defaults
is
None
:
kw_defaults
=
[]
args
=
ast
.
arguments
(
args
,
vararg
,
varargannotation
,
kwonlyargs
,
kwarg
,
kwargannotation
,
defaults
,
kw_defaults
)
return
fac
(
args
)
args
=
[
ast
.
arg
(
"x"
,
ast
.
Name
(
"x"
,
ast
.
Store
()))]
check
(
arguments
(
args
=
args
),
"must have Load context"
)
check
(
arguments
(
varargannotation
=
ast
.
Num
(
3
)),
"varargannotation but no vararg"
)
check
(
arguments
(
varargannotation
=
ast
.
Name
(
"x"
,
ast
.
Store
()),
vararg
=
"x"
),
"must have Load context"
)
check
(
arguments
(
kwonlyargs
=
args
),
"must have Load context"
)
check
(
arguments
(
kwargannotation
=
ast
.
Num
(
42
)),
"kwargannotation but no kwarg"
)
check
(
arguments
(
kwargannotation
=
ast
.
Name
(
"x"
,
ast
.
Store
()),
kwarg
=
"x"
),
"must have Load context"
)
check
(
arguments
(
defaults
=
[
ast
.
Num
(
3
)]),
"more positional defaults than args"
)
check
(
arguments
(
kw_defaults
=
[
ast
.
Num
(
4
)]),
"length of kwonlyargs is not the same as kw_defaults"
)
args
=
[
ast
.
arg
(
"x"
,
ast
.
Name
(
"x"
,
ast
.
Load
()))]
check
(
arguments
(
args
=
args
,
defaults
=
[
ast
.
Name
(
"x"
,
ast
.
Store
())]),
"must have Load context"
)
args
=
[
ast
.
arg
(
"a"
,
ast
.
Name
(
"x"
,
ast
.
Load
())),
ast
.
arg
(
"b"
,
ast
.
Name
(
"y"
,
ast
.
Load
()))]
check
(
arguments
(
kwonlyargs
=
args
,
kw_defaults
=
[
None
,
ast
.
Name
(
"x"
,
ast
.
Store
())]),
"must have Load context"
)
def
test_funcdef
(
self
):
a
=
ast
.
arguments
([],
None
,
None
,
[],
None
,
None
,
[],
[])
f
=
ast
.
FunctionDef
(
"x"
,
a
,
[],
[],
None
)
self
.
stmt
(
f
,
"empty body on FunctionDef"
)
f
=
ast
.
FunctionDef
(
"x"
,
a
,
[
ast
.
Pass
()],
[
ast
.
Name
(
"x"
,
ast
.
Store
())],
None
)
self
.
stmt
(
f
,
"must have Load context"
)
f
=
ast
.
FunctionDef
(
"x"
,
a
,
[
ast
.
Pass
()],
[],
ast
.
Name
(
"x"
,
ast
.
Store
()))
self
.
stmt
(
f
,
"must have Load context"
)
def
fac
(
args
):
return
ast
.
FunctionDef
(
"x"
,
args
,
[
ast
.
Pass
()],
[],
None
)
self
.
_check_arguments
(
fac
,
self
.
stmt
)
def
test_classdef
(
self
):
def
cls
(
bases
=
None
,
keywords
=
None
,
starargs
=
None
,
kwargs
=
None
,
body
=
None
,
decorator_list
=
None
):
if
bases
is
None
:
bases
=
[]
if
keywords
is
None
:
keywords
=
[]
if
body
is
None
:
body
=
[
ast
.
Pass
()]
if
decorator_list
is
None
:
decorator_list
=
[]
return
ast
.
ClassDef
(
"myclass"
,
bases
,
keywords
,
starargs
,
kwargs
,
body
,
decorator_list
)
self
.
stmt
(
cls
(
bases
=
[
ast
.
Name
(
"x"
,
ast
.
Store
())]),
"must have Load context"
)
self
.
stmt
(
cls
(
keywords
=
[
ast
.
keyword
(
"x"
,
ast
.
Name
(
"x"
,
ast
.
Store
()))]),
"must have Load context"
)
self
.
stmt
(
cls
(
starargs
=
ast
.
Name
(
"x"
,
ast
.
Store
())),
"must have Load context"
)
self
.
stmt
(
cls
(
kwargs
=
ast
.
Name
(
"x"
,
ast
.
Store
())),
"must have Load context"
)
self
.
stmt
(
cls
(
body
=
[]),
"empty body on ClassDef"
)
self
.
stmt
(
cls
(
body
=
[
None
]),
"None disallowed"
)
self
.
stmt
(
cls
(
decorator_list
=
[
ast
.
Name
(
"x"
,
ast
.
Store
())]),
"must have Load context"
)
def
test_delete
(
self
):
self
.
stmt
(
ast
.
Delete
([]),
"empty targets on Delete"
)
self
.
stmt
(
ast
.
Delete
([
None
]),
"None disallowed"
)
self
.
stmt
(
ast
.
Delete
([
ast
.
Name
(
"x"
,
ast
.
Load
())]),
"must have Del context"
)
def
test_assign
(
self
):
self
.
stmt
(
ast
.
Assign
([],
ast
.
Num
(
3
)),
"empty targets on Assign"
)
self
.
stmt
(
ast
.
Assign
([
None
],
ast
.
Num
(
3
)),
"None disallowed"
)
self
.
stmt
(
ast
.
Assign
([
ast
.
Name
(
"x"
,
ast
.
Load
())],
ast
.
Num
(
3
)),
"must have Store context"
)
self
.
stmt
(
ast
.
Assign
([
ast
.
Name
(
"x"
,
ast
.
Store
())],
ast
.
Name
(
"y"
,
ast
.
Store
())),
"must have Load context"
)
def
test_augassign
(
self
):
aug
=
ast
.
AugAssign
(
ast
.
Name
(
"x"
,
ast
.
Load
()),
ast
.
Add
(),
ast
.
Name
(
"y"
,
ast
.
Load
()))
self
.
stmt
(
aug
,
"must have Store context"
)
aug
=
ast
.
AugAssign
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
ast
.
Add
(),
ast
.
Name
(
"y"
,
ast
.
Store
()))
self
.
stmt
(
aug
,
"must have Load context"
)
def
test_for
(
self
):
x
=
ast
.
Name
(
"x"
,
ast
.
Store
())
y
=
ast
.
Name
(
"y"
,
ast
.
Load
())
p
=
ast
.
Pass
()
self
.
stmt
(
ast
.
For
(
x
,
y
,
[],
[]),
"empty body on For"
)
self
.
stmt
(
ast
.
For
(
ast
.
Name
(
"x"
,
ast
.
Load
()),
y
,
[
p
],
[]),
"must have Store context"
)
self
.
stmt
(
ast
.
For
(
x
,
ast
.
Name
(
"y"
,
ast
.
Store
()),
[
p
],
[]),
"must have Load context"
)
e
=
ast
.
Expr
(
ast
.
Name
(
"x"
,
ast
.
Store
()))
self
.
stmt
(
ast
.
For
(
x
,
y
,
[
e
],
[]),
"must have Load context"
)
self
.
stmt
(
ast
.
For
(
x
,
y
,
[
p
],
[
e
]),
"must have Load context"
)
def
test_while
(
self
):
self
.
stmt
(
ast
.
While
(
ast
.
Num
(
3
),
[],
[]),
"empty body on While"
)
self
.
stmt
(
ast
.
While
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
[
ast
.
Pass
()],
[]),
"must have Load context"
)
self
.
stmt
(
ast
.
While
(
ast
.
Num
(
3
),
[
ast
.
Pass
()],
[
ast
.
Expr
(
ast
.
Name
(
"x"
,
ast
.
Store
()))]),
"must have Load context"
)
def
test_if
(
self
):
self
.
stmt
(
ast
.
If
(
ast
.
Num
(
3
),
[],
[]),
"empty body on If"
)
i
=
ast
.
If
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
[
ast
.
Pass
()],
[])
self
.
stmt
(
i
,
"must have Load context"
)
i
=
ast
.
If
(
ast
.
Num
(
3
),
[
ast
.
Expr
(
ast
.
Name
(
"x"
,
ast
.
Store
()))],
[])
self
.
stmt
(
i
,
"must have Load context"
)
i
=
ast
.
If
(
ast
.
Num
(
3
),
[
ast
.
Pass
()],
[
ast
.
Expr
(
ast
.
Name
(
"x"
,
ast
.
Store
()))])
self
.
stmt
(
i
,
"must have Load context"
)
def
test_with
(
self
):
p
=
ast
.
Pass
()
self
.
stmt
(
ast
.
With
([],
[
p
]),
"empty items on With"
)
i
=
ast
.
withitem
(
ast
.
Num
(
3
),
None
)
self
.
stmt
(
ast
.
With
([
i
],
[]),
"empty body on With"
)
i
=
ast
.
withitem
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
None
)
self
.
stmt
(
ast
.
With
([
i
],
[
p
]),
"must have Load context"
)
i
=
ast
.
withitem
(
ast
.
Num
(
3
),
ast
.
Name
(
"x"
,
ast
.
Load
()))
self
.
stmt
(
ast
.
With
([
i
],
[
p
]),
"must have Store context"
)
def
test_raise
(
self
):
r
=
ast
.
Raise
(
None
,
ast
.
Num
(
3
))
self
.
stmt
(
r
,
"Raise with cause but no exception"
)
r
=
ast
.
Raise
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
None
)
self
.
stmt
(
r
,
"must have Load context"
)
r
=
ast
.
Raise
(
ast
.
Num
(
4
),
ast
.
Name
(
"x"
,
ast
.
Store
()))
self
.
stmt
(
r
,
"must have Load context"
)
def
test_try
(
self
):
p
=
ast
.
Pass
()
t
=
ast
.
Try
([],
[],
[],
[
p
])
self
.
stmt
(
t
,
"empty body on Try"
)
t
=
ast
.
Try
([
ast
.
Expr
(
ast
.
Name
(
"x"
,
ast
.
Store
()))],
[],
[],
[
p
])
self
.
stmt
(
t
,
"must have Load context"
)
t
=
ast
.
Try
([
p
],
[],
[],
[])
self
.
stmt
(
t
,
"Try has neither except handlers nor finalbody"
)
t
=
ast
.
Try
([
p
],
[],
[
p
],
[
p
])
self
.
stmt
(
t
,
"Try has orelse but no except handlers"
)
t
=
ast
.
Try
([
p
],
[
ast
.
ExceptHandler
(
None
,
"x"
,
[])],
[],
[])
self
.
stmt
(
t
,
"empty body on ExceptHandler"
)
e
=
[
ast
.
ExceptHandler
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
"y"
,
[
p
])]
self
.
stmt
(
ast
.
Try
([
p
],
e
,
[],
[]),
"must have Load context"
)
e
=
[
ast
.
ExceptHandler
(
None
,
"x"
,
[
p
])]
t
=
ast
.
Try
([
p
],
e
,
[
ast
.
Expr
(
ast
.
Name
(
"x"
,
ast
.
Store
()))],
[
p
])
self
.
stmt
(
t
,
"must have Load context"
)
t
=
ast
.
Try
([
p
],
e
,
[
p
],
[
ast
.
Expr
(
ast
.
Name
(
"x"
,
ast
.
Store
()))])
self
.
stmt
(
t
,
"must have Load context"
)
def
test_assert
(
self
):
self
.
stmt
(
ast
.
Assert
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
None
),
"must have Load context"
)
assrt
=
ast
.
Assert
(
ast
.
Name
(
"x"
,
ast
.
Load
()),
ast
.
Name
(
"y"
,
ast
.
Store
()))
self
.
stmt
(
assrt
,
"must have Load context"
)
def
test_import
(
self
):
self
.
stmt
(
ast
.
Import
([]),
"empty names on Import"
)
def
test_importfrom
(
self
):
imp
=
ast
.
ImportFrom
(
None
,
[
ast
.
alias
(
"x"
,
None
)],
-
42
)
self
.
stmt
(
imp
,
"level less than -1"
)
self
.
stmt
(
ast
.
ImportFrom
(
None
,
[],
0
),
"empty names on ImportFrom"
)
def
test_global
(
self
):
self
.
stmt
(
ast
.
Global
([]),
"empty names on Global"
)
def
test_nonlocal
(
self
):
self
.
stmt
(
ast
.
Nonlocal
([]),
"empty names on Nonlocal"
)
def
test_expr
(
self
):
e
=
ast
.
Expr
(
ast
.
Name
(
"x"
,
ast
.
Store
()))
self
.
stmt
(
e
,
"must have Load context"
)
def
test_boolop
(
self
):
b
=
ast
.
BoolOp
(
ast
.
And
(),
[])
self
.
expr
(
b
,
"less than 2 values"
)
b
=
ast
.
BoolOp
(
ast
.
And
(),
[
ast
.
Num
(
3
)])
self
.
expr
(
b
,
"less than 2 values"
)
b
=
ast
.
BoolOp
(
ast
.
And
(),
[
ast
.
Num
(
4
),
None
])
self
.
expr
(
b
,
"None disallowed"
)
b
=
ast
.
BoolOp
(
ast
.
And
(),
[
ast
.
Num
(
4
),
ast
.
Name
(
"x"
,
ast
.
Store
())])
self
.
expr
(
b
,
"must have Load context"
)
def
test_unaryop
(
self
):
u
=
ast
.
UnaryOp
(
ast
.
Not
(),
ast
.
Name
(
"x"
,
ast
.
Store
()))
self
.
expr
(
u
,
"must have Load context"
)
def
test_lambda
(
self
):
a
=
ast
.
arguments
([],
None
,
None
,
[],
None
,
None
,
[],
[])
self
.
expr
(
ast
.
Lambda
(
a
,
ast
.
Name
(
"x"
,
ast
.
Store
())),
"must have Load context"
)
def
fac
(
args
):
return
ast
.
Lambda
(
args
,
ast
.
Name
(
"x"
,
ast
.
Load
()))
self
.
_check_arguments
(
fac
,
self
.
expr
)
def
test_ifexp
(
self
):
l
=
ast
.
Name
(
"x"
,
ast
.
Load
())
s
=
ast
.
Name
(
"y"
,
ast
.
Store
())
for
args
in
(
s
,
l
,
l
),
(
l
,
s
,
l
),
(
l
,
l
,
s
):
self
.
expr
(
ast
.
IfExp
(
*
args
),
"must have Load context"
)
def
test_dict
(
self
):
d
=
ast
.
Dict
([],
[
ast
.
Name
(
"x"
,
ast
.
Load
())])
self
.
expr
(
d
,
"same number of keys as values"
)
d
=
ast
.
Dict
([
None
],
[
ast
.
Name
(
"x"
,
ast
.
Load
())])
self
.
expr
(
d
,
"None disallowed"
)
d
=
ast
.
Dict
([
ast
.
Name
(
"x"
,
ast
.
Load
())],
[
None
])
self
.
expr
(
d
,
"None disallowed"
)
def
test_set
(
self
):
self
.
expr
(
ast
.
Set
([
None
]),
"None disallowed"
)
s
=
ast
.
Set
([
ast
.
Name
(
"x"
,
ast
.
Store
())])
self
.
expr
(
s
,
"must have Load context"
)
def
_check_comprehension
(
self
,
fac
):
self
.
expr
(
fac
([]),
"comprehension with no generators"
)
g
=
ast
.
comprehension
(
ast
.
Name
(
"x"
,
ast
.
Load
()),
ast
.
Name
(
"x"
,
ast
.
Load
()),
[])
self
.
expr
(
fac
([
g
]),
"must have Store context"
)
g
=
ast
.
comprehension
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
ast
.
Name
(
"x"
,
ast
.
Store
()),
[])
self
.
expr
(
fac
([
g
]),
"must have Load context"
)
x
=
ast
.
Name
(
"x"
,
ast
.
Store
())
y
=
ast
.
Name
(
"y"
,
ast
.
Load
())
g
=
ast
.
comprehension
(
x
,
y
,
[
None
])
self
.
expr
(
fac
([
g
]),
"None disallowed"
)
g
=
ast
.
comprehension
(
x
,
y
,
[
ast
.
Name
(
"x"
,
ast
.
Store
())])
self
.
expr
(
fac
([
g
]),
"must have Load context"
)
def
_simple_comp
(
self
,
fac
):
g
=
ast
.
comprehension
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
ast
.
Name
(
"x"
,
ast
.
Load
()),
[])
self
.
expr
(
fac
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
[
g
]),
"must have Load context"
)
def
wrap
(
gens
):
return
fac
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
gens
)
self
.
_check_comprehension
(
wrap
)
def
test_listcomp
(
self
):
self
.
_simple_comp
(
ast
.
ListComp
)
def
test_setcomp
(
self
):
self
.
_simple_comp
(
ast
.
SetComp
)
def
test_generatorexp
(
self
):
self
.
_simple_comp
(
ast
.
GeneratorExp
)
def
test_dictcomp
(
self
):
g
=
ast
.
comprehension
(
ast
.
Name
(
"y"
,
ast
.
Store
()),
ast
.
Name
(
"p"
,
ast
.
Load
()),
[])
c
=
ast
.
DictComp
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
ast
.
Name
(
"y"
,
ast
.
Load
()),
[
g
])
self
.
expr
(
c
,
"must have Load context"
)
c
=
ast
.
DictComp
(
ast
.
Name
(
"x"
,
ast
.
Load
()),
ast
.
Name
(
"y"
,
ast
.
Store
()),
[
g
])
self
.
expr
(
c
,
"must have Load context"
)
def
factory
(
comps
):
k
=
ast
.
Name
(
"x"
,
ast
.
Load
())
v
=
ast
.
Name
(
"y"
,
ast
.
Load
())
return
ast
.
DictComp
(
k
,
v
,
comps
)
self
.
_check_comprehension
(
factory
)
def
test_yield
(
self
):
self
.
expr
(
ast
.
Yield
(
ast
.
Name
(
"x"
,
ast
.
Store
())),
"must have Load"
)
def
test_compare
(
self
):
left
=
ast
.
Name
(
"x"
,
ast
.
Load
())
comp
=
ast
.
Compare
(
left
,
[
ast
.
In
()],
[])
self
.
expr
(
comp
,
"no comparators"
)
comp
=
ast
.
Compare
(
left
,
[
ast
.
In
()],
[
ast
.
Num
(
4
),
ast
.
Num
(
5
)])
self
.
expr
(
comp
,
"different number of comparators and operands"
)
comp
=
ast
.
Compare
(
ast
.
Num
(
"blah"
),
[
ast
.
In
()],
[
left
])
self
.
expr
(
comp
,
"non-numeric"
,
exc
=
TypeError
)
comp
=
ast
.
Compare
(
left
,
[
ast
.
In
()],
[
ast
.
Num
(
"blah"
)])
self
.
expr
(
comp
,
"non-numeric"
,
exc
=
TypeError
)
def
test_call
(
self
):
func
=
ast
.
Name
(
"x"
,
ast
.
Load
())
args
=
[
ast
.
Name
(
"y"
,
ast
.
Load
())]
keywords
=
[
ast
.
keyword
(
"w"
,
ast
.
Name
(
"z"
,
ast
.
Load
()))]
stararg
=
ast
.
Name
(
"p"
,
ast
.
Load
())
kwarg
=
ast
.
Name
(
"q"
,
ast
.
Load
())
call
=
ast
.
Call
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
args
,
keywords
,
stararg
,
kwarg
)
self
.
expr
(
call
,
"must have Load context"
)
call
=
ast
.
Call
(
func
,
[
None
],
keywords
,
stararg
,
kwarg
)
self
.
expr
(
call
,
"None disallowed"
)
bad_keywords
=
[
ast
.
keyword
(
"w"
,
ast
.
Name
(
"z"
,
ast
.
Store
()))]
call
=
ast
.
Call
(
func
,
args
,
bad_keywords
,
stararg
,
kwarg
)
self
.
expr
(
call
,
"must have Load context"
)
call
=
ast
.
Call
(
func
,
args
,
keywords
,
ast
.
Name
(
"z"
,
ast
.
Store
()),
kwarg
)
self
.
expr
(
call
,
"must have Load context"
)
call
=
ast
.
Call
(
func
,
args
,
keywords
,
stararg
,
ast
.
Name
(
"w"
,
ast
.
Store
()))
self
.
expr
(
call
,
"must have Load context"
)
def
test_num
(
self
):
class
subint
(
int
):
pass
class
subfloat
(
float
):
pass
class
subcomplex
(
complex
):
pass
for
obj
in
"0"
,
"hello"
,
subint
(),
subfloat
(),
subcomplex
():
self
.
expr
(
ast
.
Num
(
obj
),
"non-numeric"
,
exc
=
TypeError
)
def
test_attribute
(
self
):
attr
=
ast
.
Attribute
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
"y"
,
ast
.
Load
())
self
.
expr
(
attr
,
"must have Load context"
)
def
test_subscript
(
self
):
sub
=
ast
.
Subscript
(
ast
.
Name
(
"x"
,
ast
.
Store
()),
ast
.
Index
(
ast
.
Num
(
3
)),
ast
.
Load
())
self
.
expr
(
sub
,
"must have Load context"
)
x
=
ast
.
Name
(
"x"
,
ast
.
Load
())
sub
=
ast
.
Subscript
(
x
,
ast
.
Index
(
ast
.
Name
(
"y"
,
ast
.
Store
())),
ast
.
Load
())
self
.
expr
(
sub
,
"must have Load context"
)
s
=
ast
.
Name
(
"x"
,
ast
.
Store
())
for
args
in
(
s
,
None
,
None
),
(
None
,
s
,
None
),
(
None
,
None
,
s
):
sl
=
ast
.
Slice
(
*
args
)
self
.
expr
(
ast
.
Subscript
(
x
,
sl
,
ast
.
Load
()),
"must have Load context"
)
sl
=
ast
.
ExtSlice
([])
self
.
expr
(
ast
.
Subscript
(
x
,
sl
,
ast
.
Load
()),
"empty dims on ExtSlice"
)
sl
=
ast
.
ExtSlice
([
ast
.
Index
(
s
)])
self
.
expr
(
ast
.
Subscript
(
x
,
sl
,
ast
.
Load
()),
"must have Load context"
)
def
test_starred
(
self
):
left
=
ast
.
List
([
ast
.
Starred
(
ast
.
Name
(
"x"
,
ast
.
Load
()),
ast
.
Store
())],
ast
.
Store
())
assign
=
ast
.
Assign
([
left
],
ast
.
Num
(
4
))
self
.
stmt
(
assign
,
"must have Store context"
)
def
_sequence
(
self
,
fac
):
self
.
expr
(
fac
([
None
],
ast
.
Load
()),
"None disallowed"
)
self
.
expr
(
fac
([
ast
.
Name
(
"x"
,
ast
.
Store
())],
ast
.
Load
()),
"must have Load context"
)
def
test_list
(
self
):
self
.
_sequence
(
ast
.
List
)
def
test_tuple
(
self
):
self
.
_sequence
(
ast
.
Tuple
)
def
test_stdlib_validates
(
self
):
stdlib
=
os
.
path
.
dirname
(
ast
.
__file__
)
tests
=
[
fn
for
fn
in
os
.
listdir
(
stdlib
)
if
fn
.
endswith
(
".py"
)]
tests
.
extend
([
"test/test_grammar.py"
,
"test/test_unpack_ex.py"
])
for
module
in
tests
:
fn
=
os
.
path
.
join
(
stdlib
,
module
)
with
open
(
fn
,
"r"
,
encoding
=
"utf-8"
)
as
fp
:
source
=
fp
.
read
()
mod
=
ast
.
parse
(
source
)
compile
(
mod
,
fn
,
"exec"
)
def
test_main
():
def
test_main
():
support
.
run_unittest
(
AST_Tests
,
ASTHelpers_Test
)
support
.
run_unittest
(
AST_Tests
,
ASTHelpers_Test
,
ASTValidatorTests
)
def
main
():
def
main
():
if
__name__
!=
'__main__'
:
if
__name__
!=
'__main__'
:
...
...
Misc/NEWS
View file @
fecf254c
...
@@ -10,6 +10,8 @@ What's New in Python 3.3 Alpha 1?
...
@@ -10,6 +10,8 @@ What's New in Python 3.3 Alpha 1?
Core and Builtins
Core and Builtins
-----------------
-----------------
- Issue #12575: Validate user-generated AST before it is compiled.
- Make type(None), type(Ellipsis), and type(NotImplemented) callable. They
- Make type(None), type(Ellipsis), and type(NotImplemented) callable. They
return the respective singleton instances.
return the respective singleton instances.
...
...
Parser/Python.asdl
View file @
fecf254c
-- ASDL's f
our builtin types are identifier, int, string
, object
-- ASDL's f
ive builtin types are identifier, int, string, bytes
, object
module Python
module Python
{
{
...
@@ -67,7 +67,7 @@ module Python
...
@@ -67,7 +67,7 @@ module Python
expr? starargs, expr? kwargs)
expr? starargs, expr? kwargs)
| Num(object n) -- a number as a PyObject.
| Num(object n) -- a number as a PyObject.
| Str(string s) -- need to specify raw, unicode, etc?
| Str(string s) -- need to specify raw, unicode, etc?
| Bytes(
string
s)
| Bytes(
bytes
s)
| Ellipsis
| Ellipsis
-- other literals? bools?
-- other literals? bools?
...
...
Parser/asdl.py
View file @
fecf254c
...
@@ -228,7 +228,7 @@ class ASDLParser(spark.GenericParser, object):
...
@@ -228,7 +228,7 @@ class ASDLParser(spark.GenericParser, object):
" field ::= Id ? "
" field ::= Id ? "
return
Field
(
type
[
0
],
opt
=
True
)
return
Field
(
type
[
0
],
opt
=
True
)
builtin_types
=
(
"identifier"
,
"string"
,
"
int"
,
"bool
"
,
"object"
)
builtin_types
=
(
"identifier"
,
"string"
,
"
bytes"
,
"int
"
,
"object"
)
# below is a collection of classes to capture the AST of an AST :-)
# below is a collection of classes to capture the AST of an AST :-)
# not sure if any of the methods are useful yet, but I'm adding them
# not sure if any of the methods are useful yet, but I'm adding them
...
...
Parser/asdl_c.py
View file @
fecf254c
...
@@ -776,6 +776,7 @@ static PyObject* ast2obj_object(void *o)
...
@@ -776,6 +776,7 @@ static PyObject* ast2obj_object(void *o)
}
}
#define ast2obj_identifier ast2obj_object
#define ast2obj_identifier ast2obj_object
#define ast2obj_string ast2obj_object
#define ast2obj_string ast2obj_object
#define ast2obj_bytes ast2obj_object
static PyObject* ast2obj_int(long b)
static PyObject* ast2obj_int(long b)
{
{
...
@@ -813,6 +814,15 @@ static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena)
...
@@ -813,6 +814,15 @@ static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena)
return obj2ast_object(obj, out, arena);
return obj2ast_object(obj, out, arena);
}
}
static int obj2ast_bytes(PyObject* obj, PyObject** out, PyArena* arena)
{
if (!PyBytes_CheckExact(obj)) {
PyErr_SetString(PyExc_TypeError, "AST bytes must be of type bytes");
return 1;
}
return obj2ast_object(obj, out, arena);
}
static int obj2ast_int(PyObject* obj, int* out, PyArena* arena)
static int obj2ast_int(PyObject* obj, int* out, PyArena* arena)
{
{
int i;
int i;
...
...
Python/Python-ast.c
View file @
fecf254c
...
@@ -573,6 +573,7 @@ static PyObject* ast2obj_object(void *o)
...
@@ -573,6 +573,7 @@ static PyObject* ast2obj_object(void *o)
}
}
#define ast2obj_identifier ast2obj_object
#define ast2obj_identifier ast2obj_object
#define ast2obj_string ast2obj_object
#define ast2obj_string ast2obj_object
#define ast2obj_bytes ast2obj_object
static
PyObject
*
ast2obj_int
(
long
b
)
static
PyObject
*
ast2obj_int
(
long
b
)
{
{
...
@@ -610,6 +611,15 @@ static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena)
...
@@ -610,6 +611,15 @@ static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena)
return
obj2ast_object
(
obj
,
out
,
arena
);
return
obj2ast_object
(
obj
,
out
,
arena
);
}
}
static
int
obj2ast_bytes
(
PyObject
*
obj
,
PyObject
**
out
,
PyArena
*
arena
)
{
if
(
!
PyBytes_CheckExact
(
obj
))
{
PyErr_SetString
(
PyExc_TypeError
,
"AST bytes must be of type bytes"
);
return
1
;
}
return
obj2ast_object
(
obj
,
out
,
arena
);
}
static
int
obj2ast_int
(
PyObject
*
obj
,
int
*
out
,
PyArena
*
arena
)
static
int
obj2ast_int
(
PyObject
*
obj
,
int
*
out
,
PyArena
*
arena
)
{
{
int
i
;
int
i
;
...
@@ -1773,7 +1783,7 @@ Str(string s, int lineno, int col_offset, PyArena *arena)
...
@@ -1773,7 +1783,7 @@ Str(string s, int lineno, int col_offset, PyArena *arena)
}
}
expr_ty
expr_ty
Bytes
(
string
s
,
int
lineno
,
int
col_offset
,
PyArena
*
arena
)
Bytes
(
bytes
s
,
int
lineno
,
int
col_offset
,
PyArena
*
arena
)
{
{
expr_ty
p
;
expr_ty
p
;
if
(
!
s
)
{
if
(
!
s
)
{
...
@@ -2804,7 +2814,7 @@ ast2obj_expr(void* _o)
...
@@ -2804,7 +2814,7 @@ ast2obj_expr(void* _o)
case
Bytes_kind
:
case
Bytes_kind
:
result
=
PyType_GenericNew
(
Bytes_type
,
NULL
,
NULL
);
result
=
PyType_GenericNew
(
Bytes_type
,
NULL
,
NULL
);
if
(
!
result
)
goto
failed
;
if
(
!
result
)
goto
failed
;
value
=
ast2obj_
string
(
o
->
v
.
Bytes
.
s
);
value
=
ast2obj_
bytes
(
o
->
v
.
Bytes
.
s
);
if
(
!
value
)
goto
failed
;
if
(
!
value
)
goto
failed
;
if
(
PyObject_SetAttrString
(
result
,
"s"
,
value
)
==
-
1
)
if
(
PyObject_SetAttrString
(
result
,
"s"
,
value
)
==
-
1
)
goto
failed
;
goto
failed
;
...
@@ -5509,13 +5519,13 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
...
@@ -5509,13 +5519,13 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
return
1
;
return
1
;
}
}
if
(
isinstance
)
{
if
(
isinstance
)
{
string
s
;
bytes
s
;
if
(
PyObject_HasAttrString
(
obj
,
"s"
))
{
if
(
PyObject_HasAttrString
(
obj
,
"s"
))
{
int
res
;
int
res
;
tmp
=
PyObject_GetAttrString
(
obj
,
"s"
);
tmp
=
PyObject_GetAttrString
(
obj
,
"s"
);
if
(
tmp
==
NULL
)
goto
failed
;
if
(
tmp
==
NULL
)
goto
failed
;
res
=
obj2ast_
string
(
tmp
,
&
s
,
arena
);
res
=
obj2ast_
bytes
(
tmp
,
&
s
,
arena
);
if
(
res
!=
0
)
goto
failed
;
if
(
res
!=
0
)
goto
failed
;
Py_XDECREF
(
tmp
);
Py_XDECREF
(
tmp
);
tmp
=
NULL
;
tmp
=
NULL
;
...
...
Python/ast.c
View file @
fecf254c
/*
/*
* This file includes functions to transform a concrete syntax tree (CST) to
* This file includes functions to transform a concrete syntax tree (CST) to
* an abstract syntax tree (AST).
The main function is PyAST_FromNode().
* an abstract syntax tree (AST). The main function is PyAST_FromNode().
*
*
*/
*/
#include "Python.h"
#include "Python.h"
#include "Python-ast.h"
#include "Python-ast.h"
#include "grammar.h"
#include "node.h"
#include "node.h"
#include "ast.h"
#include "ast.h"
#include "token.h"
#include "token.h"
#include "parsetok.h"
#include "graminit.h"
#include <assert.h>
#include <assert.h>
static
int
validate_stmts
(
asdl_seq
*
);
static
int
validate_exprs
(
asdl_seq
*
,
expr_context_ty
,
int
);
static
int
validate_nonempty_seq
(
asdl_seq
*
,
const
char
*
,
const
char
*
);
static
int
validate_stmt
(
stmt_ty
);
static
int
validate_expr
(
expr_ty
,
expr_context_ty
);
static
int
validate_comprehension
(
asdl_seq
*
gens
)
{
int
i
;
if
(
!
asdl_seq_LEN
(
gens
))
{
PyErr_SetString
(
PyExc_ValueError
,
"comprehension with no generators"
);
return
0
;
}
for
(
i
=
0
;
i
<
asdl_seq_LEN
(
gens
);
i
++
)
{
comprehension_ty
comp
=
asdl_seq_GET
(
gens
,
i
);
if
(
!
validate_expr
(
comp
->
target
,
Store
)
||
!
validate_expr
(
comp
->
iter
,
Load
)
||
!
validate_exprs
(
comp
->
ifs
,
Load
,
0
))
return
0
;
}
return
1
;
}
static
int
validate_slice
(
slice_ty
slice
)
{
switch
(
slice
->
kind
)
{
case
Slice_kind
:
return
(
!
slice
->
v
.
Slice
.
lower
||
validate_expr
(
slice
->
v
.
Slice
.
lower
,
Load
))
&&
(
!
slice
->
v
.
Slice
.
upper
||
validate_expr
(
slice
->
v
.
Slice
.
upper
,
Load
))
&&
(
!
slice
->
v
.
Slice
.
step
||
validate_expr
(
slice
->
v
.
Slice
.
step
,
Load
));
case
ExtSlice_kind
:
{
int
i
;
if
(
!
validate_nonempty_seq
(
slice
->
v
.
ExtSlice
.
dims
,
"dims"
,
"ExtSlice"
))
return
0
;
for
(
i
=
0
;
i
<
asdl_seq_LEN
(
slice
->
v
.
ExtSlice
.
dims
);
i
++
)
if
(
!
validate_slice
(
asdl_seq_GET
(
slice
->
v
.
ExtSlice
.
dims
,
i
)))
return
0
;
return
1
;
}
case
Index_kind
:
return
validate_expr
(
slice
->
v
.
Index
.
value
,
Load
);
default:
PyErr_SetString
(
PyExc_SystemError
,
"unknown slice node"
);
return
0
;
}
}
static
int
validate_keywords
(
asdl_seq
*
keywords
)
{
int
i
;
for
(
i
=
0
;
i
<
asdl_seq_LEN
(
keywords
);
i
++
)
if
(
!
validate_expr
(((
keyword_ty
)
asdl_seq_GET
(
keywords
,
i
))
->
value
,
Load
))
return
0
;
return
1
;
}
static
int
validate_args
(
asdl_seq
*
args
)
{
int
i
;
for
(
i
=
0
;
i
<
asdl_seq_LEN
(
args
);
i
++
)
{
arg_ty
arg
=
asdl_seq_GET
(
args
,
i
);
if
(
arg
->
annotation
&&
!
validate_expr
(
arg
->
annotation
,
Load
))
return
0
;
}
return
1
;
}
static
const
char
*
expr_context_name
(
expr_context_ty
ctx
)
{
switch
(
ctx
)
{
case
Load
:
return
"Load"
;
case
Store
:
return
"Store"
;
case
Del
:
return
"Del"
;
case
AugLoad
:
return
"AugLoad"
;
case
AugStore
:
return
"AugStore"
;
case
Param
:
return
"Param"
;
default:
assert
(
0
);
return
"(unknown)"
;
}
}
static
int
validate_arguments
(
arguments_ty
args
)
{
if
(
!
validate_args
(
args
->
args
))
return
0
;
if
(
args
->
varargannotation
)
{
if
(
!
args
->
vararg
)
{
PyErr_SetString
(
PyExc_ValueError
,
"varargannotation but no vararg on arguments"
);
return
0
;
}
if
(
!
validate_expr
(
args
->
varargannotation
,
Load
))
return
0
;
}
if
(
!
validate_args
(
args
->
kwonlyargs
))
return
0
;
if
(
args
->
kwargannotation
)
{
if
(
!
args
->
kwarg
)
{
PyErr_SetString
(
PyExc_ValueError
,
"kwargannotation but no kwarg on arguments"
);
return
0
;
}
if
(
!
validate_expr
(
args
->
kwargannotation
,
Load
))
return
0
;
}
if
(
asdl_seq_LEN
(
args
->
defaults
)
>
asdl_seq_LEN
(
args
->
args
))
{
PyErr_SetString
(
PyExc_ValueError
,
"more positional defaults than args on arguments"
);
return
0
;
}
if
(
asdl_seq_LEN
(
args
->
kw_defaults
)
!=
asdl_seq_LEN
(
args
->
kwonlyargs
))
{
PyErr_SetString
(
PyExc_ValueError
,
"length of kwonlyargs is not the same as "
"kw_defaults on arguments"
);
return
0
;
}
return
validate_exprs
(
args
->
defaults
,
Load
,
0
)
&&
validate_exprs
(
args
->
kw_defaults
,
Load
,
1
);
}
static
int
validate_expr
(
expr_ty
exp
,
expr_context_ty
ctx
)
{
int
check_ctx
=
1
;
expr_context_ty
actual_ctx
;
/* First check expression context. */
switch
(
exp
->
kind
)
{
case
Attribute_kind
:
actual_ctx
=
exp
->
v
.
Attribute
.
ctx
;
break
;
case
Subscript_kind
:
actual_ctx
=
exp
->
v
.
Subscript
.
ctx
;
break
;
case
Starred_kind
:
actual_ctx
=
exp
->
v
.
Starred
.
ctx
;
break
;
case
Name_kind
:
actual_ctx
=
exp
->
v
.
Name
.
ctx
;
break
;
case
List_kind
:
actual_ctx
=
exp
->
v
.
List
.
ctx
;
break
;
case
Tuple_kind
:
actual_ctx
=
exp
->
v
.
Tuple
.
ctx
;
break
;
default:
if
(
ctx
!=
Load
)
{
PyErr_Format
(
PyExc_ValueError
,
"expression which can't be "
"assigned to in %s context"
,
expr_context_name
(
ctx
));
return
0
;
}
check_ctx
=
0
;
}
if
(
check_ctx
&&
actual_ctx
!=
ctx
)
{
PyErr_Format
(
PyExc_ValueError
,
"expression must have %s context but has %s instead"
,
expr_context_name
(
ctx
),
expr_context_name
(
actual_ctx
));
return
0
;
}
/* Now validate expression. */
switch
(
exp
->
kind
)
{
case
BoolOp_kind
:
if
(
asdl_seq_LEN
(
exp
->
v
.
BoolOp
.
values
)
<
2
)
{
PyErr_SetString
(
PyExc_ValueError
,
"BoolOp with less than 2 values"
);
return
0
;
}
return
validate_exprs
(
exp
->
v
.
BoolOp
.
values
,
Load
,
0
);
case
BinOp_kind
:
return
validate_expr
(
exp
->
v
.
BinOp
.
left
,
Load
)
&&
validate_expr
(
exp
->
v
.
BinOp
.
right
,
Load
);
case
UnaryOp_kind
:
return
validate_expr
(
exp
->
v
.
UnaryOp
.
operand
,
Load
);
case
Lambda_kind
:
return
validate_arguments
(
exp
->
v
.
Lambda
.
args
)
&&
validate_expr
(
exp
->
v
.
Lambda
.
body
,
Load
);
case
IfExp_kind
:
return
validate_expr
(
exp
->
v
.
IfExp
.
test
,
Load
)
&&
validate_expr
(
exp
->
v
.
IfExp
.
body
,
Load
)
&&
validate_expr
(
exp
->
v
.
IfExp
.
orelse
,
Load
);
case
Dict_kind
:
if
(
asdl_seq_LEN
(
exp
->
v
.
Dict
.
keys
)
!=
asdl_seq_LEN
(
exp
->
v
.
Dict
.
values
))
{
PyErr_SetString
(
PyExc_ValueError
,
"Dict doesn't have the same number of keys as values"
);
return
0
;
}
return
validate_exprs
(
exp
->
v
.
Dict
.
keys
,
Load
,
0
)
&&
validate_exprs
(
exp
->
v
.
Dict
.
values
,
Load
,
0
);
case
Set_kind
:
return
validate_exprs
(
exp
->
v
.
Set
.
elts
,
Load
,
0
);
#define COMP(NAME) \
case NAME ## _kind: \
return validate_comprehension(exp->v.NAME.generators) && \
validate_expr(exp->v.NAME.elt, Load);
COMP
(
ListComp
)
COMP
(
SetComp
)
COMP
(
GeneratorExp
)
#undef COMP
case
DictComp_kind
:
return
validate_comprehension
(
exp
->
v
.
DictComp
.
generators
)
&&
validate_expr
(
exp
->
v
.
DictComp
.
key
,
Load
)
&&
validate_expr
(
exp
->
v
.
DictComp
.
value
,
Load
);
case
Yield_kind
:
return
!
exp
->
v
.
Yield
.
value
||
validate_expr
(
exp
->
v
.
Yield
.
value
,
Load
);
case
Compare_kind
:
if
(
!
asdl_seq_LEN
(
exp
->
v
.
Compare
.
comparators
))
{
PyErr_SetString
(
PyExc_ValueError
,
"Compare with no comparators"
);
return
0
;
}
if
(
asdl_seq_LEN
(
exp
->
v
.
Compare
.
comparators
)
!=
asdl_seq_LEN
(
exp
->
v
.
Compare
.
ops
))
{
PyErr_SetString
(
PyExc_ValueError
,
"Compare has a different number "
"of comparators and operands"
);
return
0
;
}
return
validate_exprs
(
exp
->
v
.
Compare
.
comparators
,
Load
,
0
)
&&
validate_expr
(
exp
->
v
.
Compare
.
left
,
Load
);
case
Call_kind
:
return
validate_expr
(
exp
->
v
.
Call
.
func
,
Load
)
&&
validate_exprs
(
exp
->
v
.
Call
.
args
,
Load
,
0
)
&&
validate_keywords
(
exp
->
v
.
Call
.
keywords
)
&&
(
!
exp
->
v
.
Call
.
starargs
||
validate_expr
(
exp
->
v
.
Call
.
starargs
,
Load
))
&&
(
!
exp
->
v
.
Call
.
kwargs
||
validate_expr
(
exp
->
v
.
Call
.
kwargs
,
Load
));
case
Num_kind
:
{
PyObject
*
n
=
exp
->
v
.
Num
.
n
;
if
(
!
PyLong_CheckExact
(
n
)
&&
!
PyFloat_CheckExact
(
n
)
&&
!
PyComplex_CheckExact
(
n
))
{
PyErr_SetString
(
PyExc_TypeError
,
"non-numeric type in Num"
);
return
0
;
}
return
1
;
}
case
Str_kind
:
{
PyObject
*
s
=
exp
->
v
.
Str
.
s
;
if
(
!
PyUnicode_CheckExact
(
s
))
{
PyErr_SetString
(
PyExc_TypeError
,
"non-string type in Str"
);
return
0
;
}
return
1
;
}
case
Bytes_kind
:
{
PyObject
*
b
=
exp
->
v
.
Bytes
.
s
;
if
(
!
PyBytes_CheckExact
(
b
))
{
PyErr_SetString
(
PyExc_TypeError
,
"non-bytes type in Bytes"
);
return
0
;
}
return
1
;
}
case
Attribute_kind
:
return
validate_expr
(
exp
->
v
.
Attribute
.
value
,
Load
);
case
Subscript_kind
:
return
validate_slice
(
exp
->
v
.
Subscript
.
slice
)
&&
validate_expr
(
exp
->
v
.
Subscript
.
value
,
Load
);
case
Starred_kind
:
return
validate_expr
(
exp
->
v
.
Starred
.
value
,
ctx
);
case
List_kind
:
return
validate_exprs
(
exp
->
v
.
List
.
elts
,
ctx
,
0
);
case
Tuple_kind
:
return
validate_exprs
(
exp
->
v
.
Tuple
.
elts
,
ctx
,
0
);
/* These last cases don't have any checking. */
case
Name_kind
:
case
Ellipsis_kind
:
return
1
;
default:
PyErr_SetString
(
PyExc_SystemError
,
"unexpected expression"
);
return
0
;
}
}
static
int
validate_nonempty_seq
(
asdl_seq
*
seq
,
const
char
*
what
,
const
char
*
owner
)
{
if
(
asdl_seq_LEN
(
seq
))
return
1
;
PyErr_Format
(
PyExc_ValueError
,
"empty %s on %s"
,
what
,
owner
);
return
0
;
}
static
int
validate_assignlist
(
asdl_seq
*
targets
,
expr_context_ty
ctx
)
{
return
validate_nonempty_seq
(
targets
,
"targets"
,
ctx
==
Del
?
"Delete"
:
"Assign"
)
&&
validate_exprs
(
targets
,
ctx
,
0
);
}
static
int
validate_body
(
asdl_seq
*
body
,
const
char
*
owner
)
{
return
validate_nonempty_seq
(
body
,
"body"
,
owner
)
&&
validate_stmts
(
body
);
}
static
int
validate_stmt
(
stmt_ty
stmt
)
{
int
i
;
switch
(
stmt
->
kind
)
{
case
FunctionDef_kind
:
return
validate_body
(
stmt
->
v
.
FunctionDef
.
body
,
"FunctionDef"
)
&&
validate_arguments
(
stmt
->
v
.
FunctionDef
.
args
)
&&
validate_exprs
(
stmt
->
v
.
FunctionDef
.
decorator_list
,
Load
,
0
)
&&
(
!
stmt
->
v
.
FunctionDef
.
returns
||
validate_expr
(
stmt
->
v
.
FunctionDef
.
returns
,
Load
));
case
ClassDef_kind
:
return
validate_body
(
stmt
->
v
.
ClassDef
.
body
,
"ClassDef"
)
&&
validate_exprs
(
stmt
->
v
.
ClassDef
.
bases
,
Load
,
0
)
&&
validate_keywords
(
stmt
->
v
.
ClassDef
.
keywords
)
&&
validate_exprs
(
stmt
->
v
.
ClassDef
.
decorator_list
,
Load
,
0
)
&&
(
!
stmt
->
v
.
ClassDef
.
starargs
||
validate_expr
(
stmt
->
v
.
ClassDef
.
starargs
,
Load
))
&&
(
!
stmt
->
v
.
ClassDef
.
kwargs
||
validate_expr
(
stmt
->
v
.
ClassDef
.
kwargs
,
Load
));
case
Return_kind
:
return
!
stmt
->
v
.
Return
.
value
||
validate_expr
(
stmt
->
v
.
Return
.
value
,
Load
);
case
Delete_kind
:
return
validate_assignlist
(
stmt
->
v
.
Delete
.
targets
,
Del
);
case
Assign_kind
:
return
validate_assignlist
(
stmt
->
v
.
Assign
.
targets
,
Store
)
&&
validate_expr
(
stmt
->
v
.
Assign
.
value
,
Load
);
case
AugAssign_kind
:
return
validate_expr
(
stmt
->
v
.
AugAssign
.
target
,
Store
)
&&
validate_expr
(
stmt
->
v
.
AugAssign
.
value
,
Load
);
case
For_kind
:
return
validate_expr
(
stmt
->
v
.
For
.
target
,
Store
)
&&
validate_expr
(
stmt
->
v
.
For
.
iter
,
Load
)
&&
validate_body
(
stmt
->
v
.
For
.
body
,
"For"
)
&&
validate_stmts
(
stmt
->
v
.
For
.
orelse
);
case
While_kind
:
return
validate_expr
(
stmt
->
v
.
While
.
test
,
Load
)
&&
validate_body
(
stmt
->
v
.
While
.
body
,
"While"
)
&&
validate_stmts
(
stmt
->
v
.
While
.
orelse
);
case
If_kind
:
return
validate_expr
(
stmt
->
v
.
If
.
test
,
Load
)
&&
validate_body
(
stmt
->
v
.
If
.
body
,
"If"
)
&&
validate_stmts
(
stmt
->
v
.
If
.
orelse
);
case
With_kind
:
if
(
!
validate_nonempty_seq
(
stmt
->
v
.
With
.
items
,
"items"
,
"With"
))
return
0
;
for
(
i
=
0
;
i
<
asdl_seq_LEN
(
stmt
->
v
.
With
.
items
);
i
++
)
{
withitem_ty
item
=
asdl_seq_GET
(
stmt
->
v
.
With
.
items
,
i
);
if
(
!
validate_expr
(
item
->
context_expr
,
Load
)
||
(
item
->
optional_vars
&&
!
validate_expr
(
item
->
optional_vars
,
Store
)))
return
0
;
}
return
validate_body
(
stmt
->
v
.
With
.
body
,
"With"
);
case
Raise_kind
:
if
(
stmt
->
v
.
Raise
.
exc
)
{
return
validate_expr
(
stmt
->
v
.
Raise
.
exc
,
Load
)
&&
(
!
stmt
->
v
.
Raise
.
cause
||
validate_expr
(
stmt
->
v
.
Raise
.
cause
,
Load
));
}
if
(
stmt
->
v
.
Raise
.
cause
)
{
PyErr_SetString
(
PyExc_ValueError
,
"Raise with cause but no exception"
);
return
0
;
}
return
1
;
case
Try_kind
:
if
(
!
validate_body
(
stmt
->
v
.
Try
.
body
,
"Try"
))
return
0
;
if
(
!
asdl_seq_LEN
(
stmt
->
v
.
Try
.
handlers
)
&&
!
asdl_seq_LEN
(
stmt
->
v
.
Try
.
finalbody
))
{
PyErr_SetString
(
PyExc_ValueError
,
"Try has neither except handlers nor finalbody"
);
return
0
;
}
if
(
!
asdl_seq_LEN
(
stmt
->
v
.
Try
.
handlers
)
&&
asdl_seq_LEN
(
stmt
->
v
.
Try
.
orelse
))
{
PyErr_SetString
(
PyExc_ValueError
,
"Try has orelse but no except handlers"
);
return
0
;
}
for
(
i
=
0
;
i
<
asdl_seq_LEN
(
stmt
->
v
.
Try
.
handlers
);
i
++
)
{
excepthandler_ty
handler
=
asdl_seq_GET
(
stmt
->
v
.
Try
.
handlers
,
i
);
if
((
handler
->
v
.
ExceptHandler
.
type
&&
!
validate_expr
(
handler
->
v
.
ExceptHandler
.
type
,
Load
))
||
!
validate_body
(
handler
->
v
.
ExceptHandler
.
body
,
"ExceptHandler"
))
return
0
;
}
return
(
!
asdl_seq_LEN
(
stmt
->
v
.
Try
.
finalbody
)
||
validate_stmts
(
stmt
->
v
.
Try
.
finalbody
))
&&
(
!
asdl_seq_LEN
(
stmt
->
v
.
Try
.
orelse
)
||
validate_stmts
(
stmt
->
v
.
Try
.
orelse
));
case
Assert_kind
:
return
validate_expr
(
stmt
->
v
.
Assert
.
test
,
Load
)
&&
(
!
stmt
->
v
.
Assert
.
msg
||
validate_expr
(
stmt
->
v
.
Assert
.
msg
,
Load
));
case
Import_kind
:
return
validate_nonempty_seq
(
stmt
->
v
.
Import
.
names
,
"names"
,
"Import"
);
case
ImportFrom_kind
:
if
(
stmt
->
v
.
ImportFrom
.
level
<
-
1
)
{
PyErr_SetString
(
PyExc_ValueError
,
"ImportFrom level less than -1"
);
return
0
;
}
return
validate_nonempty_seq
(
stmt
->
v
.
ImportFrom
.
names
,
"names"
,
"ImportFrom"
);
case
Global_kind
:
return
validate_nonempty_seq
(
stmt
->
v
.
Global
.
names
,
"names"
,
"Global"
);
case
Nonlocal_kind
:
return
validate_nonempty_seq
(
stmt
->
v
.
Nonlocal
.
names
,
"names"
,
"Nonlocal"
);
case
Expr_kind
:
return
validate_expr
(
stmt
->
v
.
Expr
.
value
,
Load
);
case
Pass_kind
:
case
Break_kind
:
case
Continue_kind
:
return
1
;
default:
PyErr_SetString
(
PyExc_SystemError
,
"unexpected statement"
);
return
0
;
}
}
static
int
validate_stmts
(
asdl_seq
*
seq
)
{
int
i
;
for
(
i
=
0
;
i
<
asdl_seq_LEN
(
seq
);
i
++
)
{
stmt_ty
stmt
=
asdl_seq_GET
(
seq
,
i
);
if
(
stmt
)
{
if
(
!
validate_stmt
(
stmt
))
return
0
;
}
else
{
PyErr_SetString
(
PyExc_ValueError
,
"None disallowed in statement list"
);
return
0
;
}
}
return
1
;
}
static
int
validate_exprs
(
asdl_seq
*
exprs
,
expr_context_ty
ctx
,
int
null_ok
)
{
int
i
;
for
(
i
=
0
;
i
<
asdl_seq_LEN
(
exprs
);
i
++
)
{
expr_ty
expr
=
asdl_seq_GET
(
exprs
,
i
);
if
(
expr
)
{
if
(
!
validate_expr
(
expr
,
ctx
))
return
0
;
}
else
if
(
!
null_ok
)
{
PyErr_SetString
(
PyExc_ValueError
,
"None disallowed in expression list"
);
return
0
;
}
}
return
1
;
}
int
PyAST_Validate
(
mod_ty
mod
)
{
int
res
=
0
;
switch
(
mod
->
kind
)
{
case
Module_kind
:
res
=
validate_stmts
(
mod
->
v
.
Module
.
body
);
break
;
case
Interactive_kind
:
res
=
validate_stmts
(
mod
->
v
.
Interactive
.
body
);
break
;
case
Expression_kind
:
res
=
validate_expr
(
mod
->
v
.
Expression
.
body
,
Load
);
break
;
case
Suite_kind
:
PyErr_SetString
(
PyExc_ValueError
,
"Suite is not valid in the CPython compiler"
);
break
;
default:
PyErr_SetString
(
PyExc_SystemError
,
"impossible module node"
);
res
=
0
;
break
;
}
return
res
;
}
/* This is down here, so defines like "test" don't intefere with access AST above. */
#include "grammar.h"
#include "parsetok.h"
#include "graminit.h"
/* Data structure used internally */
/* Data structure used internally */
struct
compiling
{
struct
compiling
{
char
*
c_encoding
;
/* source encoding */
char
*
c_encoding
;
/* source encoding */
...
...
Python/bltinmodule.c
View file @
fecf254c
...
@@ -604,6 +604,10 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
...
@@ -604,6 +604,10 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
PyArena_Free
(
arena
);
PyArena_Free
(
arena
);
goto
error
;
goto
error
;
}
}
if
(
!
PyAST_Validate
(
mod
))
{
PyArena_Free
(
arena
);
goto
error
;
}
result
=
(
PyObject
*
)
PyAST_CompileEx
(
mod
,
filename
,
result
=
(
PyObject
*
)
PyAST_CompileEx
(
mod
,
filename
,
&
cf
,
optimize
,
arena
);
&
cf
,
optimize
,
arena
);
PyArena_Free
(
arena
);
PyArena_Free
(
arena
);
...
...
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