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
400cbc3a
Commit
400cbc3a
authored
Feb 28, 2006
by
Tim Peters
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Set EOL style to native.
parent
85b1052e
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
969 additions
and
969 deletions
+969
-969
Demo/parser/unparse.py
Demo/parser/unparse.py
+158
-158
Lib/test/contextmanager.py
Lib/test/contextmanager.py
+33
-33
Lib/test/nested.py
Lib/test/nested.py
+40
-40
Lib/test/test_ast.py
Lib/test/test_ast.py
+178
-178
Lib/test/test_with.py
Lib/test/test_with.py
+560
-560
No files found.
Demo/parser/unparse.py
View file @
400cbc3a
"Usage: unparse.py <path to source file>"
import
sys
class
Unparser
:
"""Methods in this class recursively traverse an AST and
output source code for the abstract syntax; original formatting
is disregarged. """
def
__init__
(
self
,
tree
,
file
=
sys
.
stdout
):
"""Unparser(tree, file=sys.stdout) -> None.
Print the source for tree to file."""
self
.
f
=
file
self
.
_indent
=
0
self
.
dispatch
(
tree
)
self
.
f
.
flush
()
def
fill
(
self
,
text
=
""
):
"Indent a piece of text, according to the current indentation level"
self
.
f
.
write
(
"
\
n
"
+
" "
*
self
.
_indent
+
text
)
def
write
(
self
,
text
):
"Append a piece of text to the current line."
self
.
f
.
write
(
text
)
def
enter
(
self
):
"Print ':', and increase the indentation."
self
.
write
(
":"
)
self
.
_indent
+=
1
def
leave
(
self
):
"Decrease the indentation level."
self
.
_indent
-=
1
def
dispatch
(
self
,
tree
):
"Dispatcher function, dispatching tree type T to method _T."
if
isinstance
(
tree
,
list
):
for
t
in
tree
:
self
.
dispatch
(
t
)
return
meth
=
getattr
(
self
,
"_"
+
tree
.
__class__
.
__name__
)
meth
(
tree
)
############### Unparsing methods ######################
# There should be one method per concrete grammar type #
# Constructors should be grouped by sum type. Ideally, #
# this would follow the order in the grammar, but #
# currently doesn't. #
########################################################
def
_Module
(
self
,
tree
):
for
stmt
in
tree
.
body
:
self
.
dispatch
(
stmt
)
# stmt
def
_Expr
(
self
,
tree
):
self
.
fill
()
self
.
dispatch
(
tree
.
value
)
def
_Import
(
self
,
t
):
self
.
fill
(
"import "
)
first
=
True
for
a
in
t
.
names
:
if
first
:
first
=
False
else
:
self
.
write
(
", "
)
self
.
write
(
a
.
name
)
if
a
.
asname
:
self
.
write
(
" as "
+
a
.
asname
)
def
_Assign
(
self
,
t
):
self
.
fill
()
for
target
in
t
.
targets
:
self
.
dispatch
(
target
)
self
.
write
(
" = "
)
self
.
dispatch
(
t
.
value
)
def
_ClassDef
(
self
,
t
):
self
.
write
(
"
\
n
"
)
self
.
fill
(
"class "
+
t
.
name
)
if
t
.
bases
:
self
.
write
(
"("
)
for
a
in
t
.
bases
:
self
.
dispatch
(
a
)
self
.
write
(
", "
)
self
.
write
(
")"
)
self
.
enter
()
self
.
dispatch
(
t
.
body
)
self
.
leave
()
def
_FunctionDef
(
self
,
t
):
self
.
write
(
"
\
n
"
)
self
.
fill
(
"def "
+
t
.
name
+
"("
)
self
.
dispatch
(
t
.
args
)
self
.
enter
()
self
.
dispatch
(
t
.
body
)
self
.
leave
()
def
_If
(
self
,
t
):
self
.
fill
(
"if "
)
self
.
dispatch
(
t
.
test
)
self
.
enter
()
# XXX elif?
self
.
dispatch
(
t
.
body
)
self
.
leave
()
if
t
.
orelse
:
self
.
fill
(
"else"
)
self
.
enter
()
self
.
dispatch
(
t
.
orelse
)
self
.
leave
()
# expr
def
_Str
(
self
,
tree
):
self
.
write
(
repr
(
tree
.
s
))
def
_Name
(
self
,
t
):
self
.
write
(
t
.
id
)
def
_List
(
self
,
t
):
self
.
write
(
"["
)
for
e
in
t
.
elts
:
self
.
dispatch
(
e
)
self
.
write
(
", "
)
self
.
write
(
"]"
)
unop
=
{
"Invert"
:
"~"
,
"Not"
:
"not"
,
"UAdd"
:
"+"
,
"USub"
:
"-"
}
def
_UnaryOp
(
self
,
t
):
self
.
write
(
self
.
unop
[
t
.
op
.
__class__
.
__name__
])
self
.
write
(
"("
)
self
.
dispatch
(
t
.
operand
)
self
.
write
(
")"
)
# others
def
_arguments
(
self
,
t
):
first
=
True
# XXX t.defaults
for
a
in
t
.
args
:
if
first
:
first
=
False
else
:
self
.
write
(
", "
)
self
.
dispatch
(
a
)
if
t
.
vararg
:
if
first
:
first
=
False
else
:
self
.
write
(
", "
)
self
.
write
(
"*"
+
t
.
vararg
)
if
t
.
kwarg
:
if
first
:
first
=
False
else
:
self
.
write
(
", "
)
self
.
write
(
"**"
+
self
.
kwarg
)
self
.
write
(
")"
)
def
roundtrip
(
filename
):
source
=
open
(
filename
).
read
()
tree
=
compile
(
source
,
filename
,
"exec"
,
0x400
)
Unparser
(
tree
)
if
__name__
==
'__main__'
:
roundtrip
(
sys
.
argv
[
1
])
"Usage: unparse.py <path to source file>"
import
sys
class
Unparser
:
"""Methods in this class recursively traverse an AST and
output source code for the abstract syntax; original formatting
is disregarged. """
def
__init__
(
self
,
tree
,
file
=
sys
.
stdout
):
"""Unparser(tree, file=sys.stdout) -> None.
Print the source for tree to file."""
self
.
f
=
file
self
.
_indent
=
0
self
.
dispatch
(
tree
)
self
.
f
.
flush
()
def
fill
(
self
,
text
=
""
):
"Indent a piece of text, according to the current indentation level"
self
.
f
.
write
(
"
\
n
"
+
" "
*
self
.
_indent
+
text
)
def
write
(
self
,
text
):
"Append a piece of text to the current line."
self
.
f
.
write
(
text
)
def
enter
(
self
):
"Print ':', and increase the indentation."
self
.
write
(
":"
)
self
.
_indent
+=
1
def
leave
(
self
):
"Decrease the indentation level."
self
.
_indent
-=
1
def
dispatch
(
self
,
tree
):
"Dispatcher function, dispatching tree type T to method _T."
if
isinstance
(
tree
,
list
):
for
t
in
tree
:
self
.
dispatch
(
t
)
return
meth
=
getattr
(
self
,
"_"
+
tree
.
__class__
.
__name__
)
meth
(
tree
)
############### Unparsing methods ######################
# There should be one method per concrete grammar type #
# Constructors should be grouped by sum type. Ideally, #
# this would follow the order in the grammar, but #
# currently doesn't. #
########################################################
def
_Module
(
self
,
tree
):
for
stmt
in
tree
.
body
:
self
.
dispatch
(
stmt
)
# stmt
def
_Expr
(
self
,
tree
):
self
.
fill
()
self
.
dispatch
(
tree
.
value
)
def
_Import
(
self
,
t
):
self
.
fill
(
"import "
)
first
=
True
for
a
in
t
.
names
:
if
first
:
first
=
False
else
:
self
.
write
(
", "
)
self
.
write
(
a
.
name
)
if
a
.
asname
:
self
.
write
(
" as "
+
a
.
asname
)
def
_Assign
(
self
,
t
):
self
.
fill
()
for
target
in
t
.
targets
:
self
.
dispatch
(
target
)
self
.
write
(
" = "
)
self
.
dispatch
(
t
.
value
)
def
_ClassDef
(
self
,
t
):
self
.
write
(
"
\
n
"
)
self
.
fill
(
"class "
+
t
.
name
)
if
t
.
bases
:
self
.
write
(
"("
)
for
a
in
t
.
bases
:
self
.
dispatch
(
a
)
self
.
write
(
", "
)
self
.
write
(
")"
)
self
.
enter
()
self
.
dispatch
(
t
.
body
)
self
.
leave
()
def
_FunctionDef
(
self
,
t
):
self
.
write
(
"
\
n
"
)
self
.
fill
(
"def "
+
t
.
name
+
"("
)
self
.
dispatch
(
t
.
args
)
self
.
enter
()
self
.
dispatch
(
t
.
body
)
self
.
leave
()
def
_If
(
self
,
t
):
self
.
fill
(
"if "
)
self
.
dispatch
(
t
.
test
)
self
.
enter
()
# XXX elif?
self
.
dispatch
(
t
.
body
)
self
.
leave
()
if
t
.
orelse
:
self
.
fill
(
"else"
)
self
.
enter
()
self
.
dispatch
(
t
.
orelse
)
self
.
leave
()
# expr
def
_Str
(
self
,
tree
):
self
.
write
(
repr
(
tree
.
s
))
def
_Name
(
self
,
t
):
self
.
write
(
t
.
id
)
def
_List
(
self
,
t
):
self
.
write
(
"["
)
for
e
in
t
.
elts
:
self
.
dispatch
(
e
)
self
.
write
(
", "
)
self
.
write
(
"]"
)
unop
=
{
"Invert"
:
"~"
,
"Not"
:
"not"
,
"UAdd"
:
"+"
,
"USub"
:
"-"
}
def
_UnaryOp
(
self
,
t
):
self
.
write
(
self
.
unop
[
t
.
op
.
__class__
.
__name__
])
self
.
write
(
"("
)
self
.
dispatch
(
t
.
operand
)
self
.
write
(
")"
)
# others
def
_arguments
(
self
,
t
):
first
=
True
# XXX t.defaults
for
a
in
t
.
args
:
if
first
:
first
=
False
else
:
self
.
write
(
", "
)
self
.
dispatch
(
a
)
if
t
.
vararg
:
if
first
:
first
=
False
else
:
self
.
write
(
", "
)
self
.
write
(
"*"
+
t
.
vararg
)
if
t
.
kwarg
:
if
first
:
first
=
False
else
:
self
.
write
(
", "
)
self
.
write
(
"**"
+
self
.
kwarg
)
self
.
write
(
")"
)
def
roundtrip
(
filename
):
source
=
open
(
filename
).
read
()
tree
=
compile
(
source
,
filename
,
"exec"
,
0x400
)
Unparser
(
tree
)
if
__name__
==
'__main__'
:
roundtrip
(
sys
.
argv
[
1
])
Lib/test/contextmanager.py
View file @
400cbc3a
class
GeneratorContextManager
(
object
):
def
__init__
(
self
,
gen
):
self
.
gen
=
gen
def
__context__
(
self
):
return
self
def
__enter__
(
self
):
try
:
return
self
.
gen
.
next
()
except
StopIteration
:
raise
RuntimeError
(
"generator didn't yield"
)
def
__exit__
(
self
,
type
,
value
,
traceback
):
if
type
is
None
:
try
:
self
.
gen
.
next
()
except
StopIteration
:
return
else
:
raise
RuntimeError
(
"generator didn't stop"
)
else
:
try
:
self
.
gen
.
throw
(
type
,
value
,
traceback
)
except
(
type
,
StopIteration
):
return
else
:
raise
RuntimeError
(
"generator caught exception"
)
def
contextmanager
(
func
):
def
helper
(
*
args
,
**
kwds
):
return
GeneratorContextManager
(
func
(
*
args
,
**
kwds
))
return
helper
class
GeneratorContextManager
(
object
):
def
__init__
(
self
,
gen
):
self
.
gen
=
gen
def
__context__
(
self
):
return
self
def
__enter__
(
self
):
try
:
return
self
.
gen
.
next
()
except
StopIteration
:
raise
RuntimeError
(
"generator didn't yield"
)
def
__exit__
(
self
,
type
,
value
,
traceback
):
if
type
is
None
:
try
:
self
.
gen
.
next
()
except
StopIteration
:
return
else
:
raise
RuntimeError
(
"generator didn't stop"
)
else
:
try
:
self
.
gen
.
throw
(
type
,
value
,
traceback
)
except
(
type
,
StopIteration
):
return
else
:
raise
RuntimeError
(
"generator caught exception"
)
def
contextmanager
(
func
):
def
helper
(
*
args
,
**
kwds
):
return
GeneratorContextManager
(
func
(
*
args
,
**
kwds
))
return
helper
Lib/test/nested.py
View file @
400cbc3a
import
sys
from
collections
import
deque
class
nested
(
object
):
def
__init__
(
self
,
*
contexts
):
self
.
contexts
=
contexts
self
.
entered
=
None
def
__context__
(
self
):
return
self
def
__enter__
(
self
):
if
self
.
entered
is
not
None
:
raise
RuntimeError
(
"Context is not reentrant"
)
self
.
entered
=
deque
()
vars
=
[]
try
:
for
context
in
self
.
contexts
:
mgr
=
context
.
__context__
()
vars
.
append
(
mgr
.
__enter__
())
self
.
entered
.
appendleft
(
mgr
)
except
:
self
.
__exit__
(
*
sys
.
exc_info
())
raise
return
vars
def
__exit__
(
self
,
*
exc_info
):
# Behave like nested with statements
# first in, last out
# New exceptions override old ones
ex
=
exc_info
for
mgr
in
self
.
entered
:
try
:
mgr
.
__exit__
(
*
ex
)
except
:
ex
=
sys
.
exc_info
()
self
.
entered
=
None
if
ex
is
not
exc_info
:
raise
ex
[
0
],
ex
[
1
],
ex
[
2
]
import
sys
from
collections
import
deque
class
nested
(
object
):
def
__init__
(
self
,
*
contexts
):
self
.
contexts
=
contexts
self
.
entered
=
None
def
__context__
(
self
):
return
self
def
__enter__
(
self
):
if
self
.
entered
is
not
None
:
raise
RuntimeError
(
"Context is not reentrant"
)
self
.
entered
=
deque
()
vars
=
[]
try
:
for
context
in
self
.
contexts
:
mgr
=
context
.
__context__
()
vars
.
append
(
mgr
.
__enter__
())
self
.
entered
.
appendleft
(
mgr
)
except
:
self
.
__exit__
(
*
sys
.
exc_info
())
raise
return
vars
def
__exit__
(
self
,
*
exc_info
):
# Behave like nested with statements
# first in, last out
# New exceptions override old ones
ex
=
exc_info
for
mgr
in
self
.
entered
:
try
:
mgr
.
__exit__
(
*
ex
)
except
:
ex
=
sys
.
exc_info
()
self
.
entered
=
None
if
ex
is
not
exc_info
:
raise
ex
[
0
],
ex
[
1
],
ex
[
2
]
Lib/test/test_ast.py
View file @
400cbc3a
import
sys
,
itertools
def
to_tuple
(
t
):
if
t
is
None
or
isinstance
(
t
,
(
basestring
,
int
,
long
,
complex
)):
return
t
elif
isinstance
(
t
,
list
):
return
[
to_tuple
(
e
)
for
e
in
t
]
result
=
[
t
.
__class__
.
__name__
]
if
t
.
_fields
is
None
:
return
tuple
(
result
)
for
f
in
t
.
_fields
:
result
.
append
(
to_tuple
(
getattr
(
t
,
f
)))
return
tuple
(
result
)
# These tests are compiled through "exec"
# There should be atleast one test per statement
exec_tests
=
[
# FunctionDef
"def f(): pass"
,
# ClassDef
"class C:pass"
,
# Return
"def f():return 1"
,
# Delete
"del v"
,
# Assign
"v = 1"
,
# AugAssign
"v += 1"
,
# Print
"print >>f, 1, "
,
# For
"for v in v:pass"
,
# While
"while v:pass"
,
# If
"if v:pass"
,
# Raise
"raise Exception, 'string'"
,
# TryExcept
"try:
\
n
pass
\
n
except Exception:
\
n
pass"
,
# TryFinally
"try:
\
n
pass
\
n
finally:
\
n
pass"
,
# Assert
"assert v"
,
# Import
"import sys"
,
# ImportFrom
"from sys import v"
,
# Exec
"exec 'v'"
,
# Global
"global v"
,
# Expr
"1"
,
# Pass,
"pass"
,
# Break
"break"
,
# Continue
"continue"
,
]
# These are compiled through "single"
# because of overlap with "eval", it just tests what
# can't be tested with "eval"
single_tests
=
[
"1+2"
]
# These are compiled through "eval"
# It should test all expressions
eval_tests
=
[
# BoolOp
"a and b"
,
# BinOp
"a + b"
,
# UnaryOp
"not v"
,
# Lambda
"lambda:None"
,
# Dict
"{ 1:2 }"
,
# ListComp
"[a for b in c if d]"
,
# GeneratorExp
"(a for b in c if d)"
,
# Yield - yield expressions can't work outside a function
#
# Compare
"1 < 2 < 3"
,
# Call
"f(1,2,c=3,*d,**e)"
,
# Repr
"`v`"
,
# Num
"10L"
,
# Str
"'string'"
,
# Attribute
"a.b"
,
# Subscript
"a[b:c]"
,
# Name
"v"
,
# List
"[1,2,3]"
,
# Tuple
"1,2,3"
]
# TODO: expr_context, slice, boolop, operator, unaryop, cmpop, comprehension
# excepthandler, arguments, keywords, alias
if
__name__
==
'__main__'
and
sys
.
argv
[
1
:]
==
[
'-g'
]:
for
statements
,
kind
in
((
exec_tests
,
"exec"
),
(
single_tests
,
"single"
),
(
eval_tests
,
"eval"
)):
print
kind
+
"_results = ["
for
s
in
statements
:
print
repr
(
to_tuple
(
compile
(
s
,
"?"
,
kind
,
0x400
)))
+
","
print
"]"
print
"run_tests()"
raise
SystemExit
def
run_tests
():
for
input
,
output
,
kind
in
((
exec_tests
,
exec_results
,
"exec"
),
(
single_tests
,
single_results
,
"single"
),
(
eval_tests
,
eval_results
,
"eval"
)):
for
i
,
o
in
itertools
.
izip
(
input
,
output
):
assert
to_tuple
(
compile
(
i
,
"?"
,
kind
,
0x400
))
==
o
#### EVERYTHING BELOW IS GENERATED #####
exec_results
=
[
(
'Module'
,
[(
'FunctionDef'
,
'f'
,
(
'arguments'
,
[],
None
,
None
,
[]),
[(
'Pass'
,)],
[])]),
(
'Module'
,
[(
'ClassDef'
,
'C'
,
[],
[(
'Pass'
,)])]),
(
'Module'
,
[(
'FunctionDef'
,
'f'
,
(
'arguments'
,
[],
None
,
None
,
[]),
[(
'Return'
,
(
'Num'
,
1
))],
[])]),
(
'Module'
,
[(
'Delete'
,
[(
'Name'
,
'v'
,
(
'Del'
,))])]),
(
'Module'
,
[(
'Assign'
,
[(
'Name'
,
'v'
,
(
'Store'
,))],
(
'Num'
,
1
))]),
(
'Module'
,
[(
'AugAssign'
,
(
'Name'
,
'v'
,
(
'Load'
,)),
(
'Add'
,),
(
'Num'
,
1
))]),
(
'Module'
,
[(
'Print'
,
(
'Name'
,
'f'
,
(
'Load'
,)),
[(
'Num'
,
1
)],
False
)]),
(
'Module'
,
[(
'For'
,
(
'Name'
,
'v'
,
(
'Store'
,)),
(
'Name'
,
'v'
,
(
'Load'
,)),
[(
'Pass'
,)],
[])]),
(
'Module'
,
[(
'While'
,
(
'Name'
,
'v'
,
(
'Load'
,)),
[(
'Pass'
,)],
[])]),
(
'Module'
,
[(
'If'
,
(
'Name'
,
'v'
,
(
'Load'
,)),
[(
'Pass'
,)],
[])]),
(
'Module'
,
[(
'Raise'
,
(
'Name'
,
'Exception'
,
(
'Load'
,)),
(
'Str'
,
'string'
),
None
)]),
(
'Module'
,
[(
'TryExcept'
,
[(
'Pass'
,)],
[(
'excepthandler'
,
(
'Name'
,
'Exception'
,
(
'Load'
,)),
None
,
[(
'Pass'
,)])],
[])]),
(
'Module'
,
[(
'TryFinally'
,
[(
'Pass'
,)],
[(
'Pass'
,)])]),
(
'Module'
,
[(
'Assert'
,
(
'Name'
,
'v'
,
(
'Load'
,)),
None
)]),
(
'Module'
,
[(
'Import'
,
[(
'alias'
,
'sys'
,
None
)])]),
(
'Module'
,
[(
'ImportFrom'
,
'sys'
,
[(
'alias'
,
'v'
,
None
)],
0
)]),
(
'Module'
,
[(
'Exec'
,
(
'Str'
,
'v'
),
None
,
None
)]),
(
'Module'
,
[(
'Global'
,
[
'v'
])]),
(
'Module'
,
[(
'Expr'
,
(
'Num'
,
1
))]),
(
'Module'
,
[(
'Pass'
,)]),
(
'Module'
,
[(
'Break'
,)]),
(
'Module'
,
[(
'Continue'
,)]),
]
single_results
=
[
(
'Interactive'
,
[(
'Expr'
,
(
'BinOp'
,
(
'Num'
,
1
),
(
'Add'
,),
(
'Num'
,
2
)))]),
]
eval_results
=
[
(
'Expression'
,
(
'BoolOp'
,
(
'And'
,),
[(
'Name'
,
'a'
,
(
'Load'
,)),
(
'Name'
,
'b'
,
(
'Load'
,))])),
(
'Expression'
,
(
'BinOp'
,
(
'Name'
,
'a'
,
(
'Load'
,)),
(
'Add'
,),
(
'Name'
,
'b'
,
(
'Load'
,)))),
(
'Expression'
,
(
'UnaryOp'
,
(
'Not'
,),
(
'Name'
,
'v'
,
(
'Load'
,)))),
(
'Expression'
,
(
'Lambda'
,
(
'arguments'
,
[],
None
,
None
,
[]),
(
'Name'
,
'None'
,
(
'Load'
,)))),
(
'Expression'
,
(
'Dict'
,
[(
'Num'
,
1
)],
[(
'Num'
,
2
)])),
(
'Expression'
,
(
'ListComp'
,
(
'Name'
,
'a'
,
(
'Load'
,)),
[(
'comprehension'
,
(
'Name'
,
'b'
,
(
'Store'
,)),
(
'Name'
,
'c'
,
(
'Load'
,)),
[(
'Name'
,
'd'
,
(
'Load'
,))])])),
(
'Expression'
,
(
'GeneratorExp'
,
(
'Name'
,
'a'
,
(
'Load'
,)),
[(
'comprehension'
,
(
'Name'
,
'b'
,
(
'Store'
,)),
(
'Name'
,
'c'
,
(
'Load'
,)),
[(
'Name'
,
'd'
,
(
'Load'
,))])])),
(
'Expression'
,
(
'Compare'
,
(
'Num'
,
1
),
[(
'Lt'
,),
(
'Lt'
,)],
[(
'Num'
,
2
),
(
'Num'
,
3
)])),
(
'Expression'
,
(
'Call'
,
(
'Name'
,
'f'
,
(
'Load'
,)),
[(
'Num'
,
1
),
(
'Num'
,
2
)],
[(
'keyword'
,
'c'
,
(
'Num'
,
3
))],
(
'Name'
,
'd'
,
(
'Load'
,)),
(
'Name'
,
'e'
,
(
'Load'
,)))),
(
'Expression'
,
(
'Repr'
,
(
'Name'
,
'v'
,
(
'Load'
,)))),
(
'Expression'
,
(
'Num'
,
10L
)),
(
'Expression'
,
(
'Str'
,
'string'
)),
(
'Expression'
,
(
'Attribute'
,
(
'Name'
,
'a'
,
(
'Load'
,)),
'b'
,
(
'Load'
,))),
(
'Expression'
,
(
'Subscript'
,
(
'Name'
,
'a'
,
(
'Load'
,)),
(
'Slice'
,
(
'Name'
,
'b'
,
(
'Load'
,)),
(
'Name'
,
'c'
,
(
'Load'
,)),
None
),
(
'Load'
,))),
(
'Expression'
,
(
'Name'
,
'v'
,
(
'Load'
,))),
(
'Expression'
,
(
'List'
,
[(
'Num'
,
1
),
(
'Num'
,
2
),
(
'Num'
,
3
)],
(
'Load'
,))),
(
'Expression'
,
(
'Tuple'
,
[(
'Num'
,
1
),
(
'Num'
,
2
),
(
'Num'
,
3
)],
(
'Load'
,))),
]
run_tests
()
import
sys
,
itertools
def
to_tuple
(
t
):
if
t
is
None
or
isinstance
(
t
,
(
basestring
,
int
,
long
,
complex
)):
return
t
elif
isinstance
(
t
,
list
):
return
[
to_tuple
(
e
)
for
e
in
t
]
result
=
[
t
.
__class__
.
__name__
]
if
t
.
_fields
is
None
:
return
tuple
(
result
)
for
f
in
t
.
_fields
:
result
.
append
(
to_tuple
(
getattr
(
t
,
f
)))
return
tuple
(
result
)
# These tests are compiled through "exec"
# There should be atleast one test per statement
exec_tests
=
[
# FunctionDef
"def f(): pass"
,
# ClassDef
"class C:pass"
,
# Return
"def f():return 1"
,
# Delete
"del v"
,
# Assign
"v = 1"
,
# AugAssign
"v += 1"
,
# Print
"print >>f, 1, "
,
# For
"for v in v:pass"
,
# While
"while v:pass"
,
# If
"if v:pass"
,
# Raise
"raise Exception, 'string'"
,
# TryExcept
"try:
\
n
pass
\
n
except Exception:
\
n
pass"
,
# TryFinally
"try:
\
n
pass
\
n
finally:
\
n
pass"
,
# Assert
"assert v"
,
# Import
"import sys"
,
# ImportFrom
"from sys import v"
,
# Exec
"exec 'v'"
,
# Global
"global v"
,
# Expr
"1"
,
# Pass,
"pass"
,
# Break
"break"
,
# Continue
"continue"
,
]
# These are compiled through "single"
# because of overlap with "eval", it just tests what
# can't be tested with "eval"
single_tests
=
[
"1+2"
]
# These are compiled through "eval"
# It should test all expressions
eval_tests
=
[
# BoolOp
"a and b"
,
# BinOp
"a + b"
,
# UnaryOp
"not v"
,
# Lambda
"lambda:None"
,
# Dict
"{ 1:2 }"
,
# ListComp
"[a for b in c if d]"
,
# GeneratorExp
"(a for b in c if d)"
,
# Yield - yield expressions can't work outside a function
#
# Compare
"1 < 2 < 3"
,
# Call
"f(1,2,c=3,*d,**e)"
,
# Repr
"`v`"
,
# Num
"10L"
,
# Str
"'string'"
,
# Attribute
"a.b"
,
# Subscript
"a[b:c]"
,
# Name
"v"
,
# List
"[1,2,3]"
,
# Tuple
"1,2,3"
]
# TODO: expr_context, slice, boolop, operator, unaryop, cmpop, comprehension
# excepthandler, arguments, keywords, alias
if
__name__
==
'__main__'
and
sys
.
argv
[
1
:]
==
[
'-g'
]:
for
statements
,
kind
in
((
exec_tests
,
"exec"
),
(
single_tests
,
"single"
),
(
eval_tests
,
"eval"
)):
print
kind
+
"_results = ["
for
s
in
statements
:
print
repr
(
to_tuple
(
compile
(
s
,
"?"
,
kind
,
0x400
)))
+
","
print
"]"
print
"run_tests()"
raise
SystemExit
def
run_tests
():
for
input
,
output
,
kind
in
((
exec_tests
,
exec_results
,
"exec"
),
(
single_tests
,
single_results
,
"single"
),
(
eval_tests
,
eval_results
,
"eval"
)):
for
i
,
o
in
itertools
.
izip
(
input
,
output
):
assert
to_tuple
(
compile
(
i
,
"?"
,
kind
,
0x400
))
==
o
#### EVERYTHING BELOW IS GENERATED #####
exec_results
=
[
(
'Module'
,
[(
'FunctionDef'
,
'f'
,
(
'arguments'
,
[],
None
,
None
,
[]),
[(
'Pass'
,)],
[])]),
(
'Module'
,
[(
'ClassDef'
,
'C'
,
[],
[(
'Pass'
,)])]),
(
'Module'
,
[(
'FunctionDef'
,
'f'
,
(
'arguments'
,
[],
None
,
None
,
[]),
[(
'Return'
,
(
'Num'
,
1
))],
[])]),
(
'Module'
,
[(
'Delete'
,
[(
'Name'
,
'v'
,
(
'Del'
,))])]),
(
'Module'
,
[(
'Assign'
,
[(
'Name'
,
'v'
,
(
'Store'
,))],
(
'Num'
,
1
))]),
(
'Module'
,
[(
'AugAssign'
,
(
'Name'
,
'v'
,
(
'Load'
,)),
(
'Add'
,),
(
'Num'
,
1
))]),
(
'Module'
,
[(
'Print'
,
(
'Name'
,
'f'
,
(
'Load'
,)),
[(
'Num'
,
1
)],
False
)]),
(
'Module'
,
[(
'For'
,
(
'Name'
,
'v'
,
(
'Store'
,)),
(
'Name'
,
'v'
,
(
'Load'
,)),
[(
'Pass'
,)],
[])]),
(
'Module'
,
[(
'While'
,
(
'Name'
,
'v'
,
(
'Load'
,)),
[(
'Pass'
,)],
[])]),
(
'Module'
,
[(
'If'
,
(
'Name'
,
'v'
,
(
'Load'
,)),
[(
'Pass'
,)],
[])]),
(
'Module'
,
[(
'Raise'
,
(
'Name'
,
'Exception'
,
(
'Load'
,)),
(
'Str'
,
'string'
),
None
)]),
(
'Module'
,
[(
'TryExcept'
,
[(
'Pass'
,)],
[(
'excepthandler'
,
(
'Name'
,
'Exception'
,
(
'Load'
,)),
None
,
[(
'Pass'
,)])],
[])]),
(
'Module'
,
[(
'TryFinally'
,
[(
'Pass'
,)],
[(
'Pass'
,)])]),
(
'Module'
,
[(
'Assert'
,
(
'Name'
,
'v'
,
(
'Load'
,)),
None
)]),
(
'Module'
,
[(
'Import'
,
[(
'alias'
,
'sys'
,
None
)])]),
(
'Module'
,
[(
'ImportFrom'
,
'sys'
,
[(
'alias'
,
'v'
,
None
)],
0
)]),
(
'Module'
,
[(
'Exec'
,
(
'Str'
,
'v'
),
None
,
None
)]),
(
'Module'
,
[(
'Global'
,
[
'v'
])]),
(
'Module'
,
[(
'Expr'
,
(
'Num'
,
1
))]),
(
'Module'
,
[(
'Pass'
,)]),
(
'Module'
,
[(
'Break'
,)]),
(
'Module'
,
[(
'Continue'
,)]),
]
single_results
=
[
(
'Interactive'
,
[(
'Expr'
,
(
'BinOp'
,
(
'Num'
,
1
),
(
'Add'
,),
(
'Num'
,
2
)))]),
]
eval_results
=
[
(
'Expression'
,
(
'BoolOp'
,
(
'And'
,),
[(
'Name'
,
'a'
,
(
'Load'
,)),
(
'Name'
,
'b'
,
(
'Load'
,))])),
(
'Expression'
,
(
'BinOp'
,
(
'Name'
,
'a'
,
(
'Load'
,)),
(
'Add'
,),
(
'Name'
,
'b'
,
(
'Load'
,)))),
(
'Expression'
,
(
'UnaryOp'
,
(
'Not'
,),
(
'Name'
,
'v'
,
(
'Load'
,)))),
(
'Expression'
,
(
'Lambda'
,
(
'arguments'
,
[],
None
,
None
,
[]),
(
'Name'
,
'None'
,
(
'Load'
,)))),
(
'Expression'
,
(
'Dict'
,
[(
'Num'
,
1
)],
[(
'Num'
,
2
)])),
(
'Expression'
,
(
'ListComp'
,
(
'Name'
,
'a'
,
(
'Load'
,)),
[(
'comprehension'
,
(
'Name'
,
'b'
,
(
'Store'
,)),
(
'Name'
,
'c'
,
(
'Load'
,)),
[(
'Name'
,
'd'
,
(
'Load'
,))])])),
(
'Expression'
,
(
'GeneratorExp'
,
(
'Name'
,
'a'
,
(
'Load'
,)),
[(
'comprehension'
,
(
'Name'
,
'b'
,
(
'Store'
,)),
(
'Name'
,
'c'
,
(
'Load'
,)),
[(
'Name'
,
'd'
,
(
'Load'
,))])])),
(
'Expression'
,
(
'Compare'
,
(
'Num'
,
1
),
[(
'Lt'
,),
(
'Lt'
,)],
[(
'Num'
,
2
),
(
'Num'
,
3
)])),
(
'Expression'
,
(
'Call'
,
(
'Name'
,
'f'
,
(
'Load'
,)),
[(
'Num'
,
1
),
(
'Num'
,
2
)],
[(
'keyword'
,
'c'
,
(
'Num'
,
3
))],
(
'Name'
,
'd'
,
(
'Load'
,)),
(
'Name'
,
'e'
,
(
'Load'
,)))),
(
'Expression'
,
(
'Repr'
,
(
'Name'
,
'v'
,
(
'Load'
,)))),
(
'Expression'
,
(
'Num'
,
10L
)),
(
'Expression'
,
(
'Str'
,
'string'
)),
(
'Expression'
,
(
'Attribute'
,
(
'Name'
,
'a'
,
(
'Load'
,)),
'b'
,
(
'Load'
,))),
(
'Expression'
,
(
'Subscript'
,
(
'Name'
,
'a'
,
(
'Load'
,)),
(
'Slice'
,
(
'Name'
,
'b'
,
(
'Load'
,)),
(
'Name'
,
'c'
,
(
'Load'
,)),
None
),
(
'Load'
,))),
(
'Expression'
,
(
'Name'
,
'v'
,
(
'Load'
,))),
(
'Expression'
,
(
'List'
,
[(
'Num'
,
1
),
(
'Num'
,
2
),
(
'Num'
,
3
)],
(
'Load'
,))),
(
'Expression'
,
(
'Tuple'
,
[(
'Num'
,
1
),
(
'Num'
,
2
),
(
'Num'
,
3
)],
(
'Load'
,))),
]
run_tests
()
Lib/test/test_with.py
View file @
400cbc3a
#!/usr/bin/env python
"""Unit tests for the with statement specified in PEP 343."""
__author__
=
"Mike Bland"
__email__
=
"mbland at acm dot org"
import
unittest
from
test.contextmanager
import
GeneratorContextManager
from
test.nested
import
nested
from
test.test_support
import
run_unittest
class
MockContextManager
(
GeneratorContextManager
):
def
__init__
(
self
,
gen
):
GeneratorContextManager
.
__init__
(
self
,
gen
)
self
.
context_called
=
False
self
.
enter_called
=
False
self
.
exit_called
=
False
self
.
exit_args
=
None
def
__context__
(
self
):
self
.
context_called
=
True
return
GeneratorContextManager
.
__context__
(
self
)
def
__enter__
(
self
):
self
.
enter_called
=
True
return
GeneratorContextManager
.
__enter__
(
self
)
def
__exit__
(
self
,
type
,
value
,
traceback
):
self
.
exit_called
=
True
self
.
exit_args
=
(
type
,
value
,
traceback
)
return
GeneratorContextManager
.
__exit__
(
self
,
type
,
value
,
traceback
)
def
mock_contextmanager
(
func
):
def
helper
(
*
args
,
**
kwds
):
return
MockContextManager
(
func
(
*
args
,
**
kwds
))
return
helper
class
MockResource
(
object
):
def
__init__
(
self
):
self
.
yielded
=
False
self
.
stopped
=
False
@
mock_contextmanager
def
mock_contextmanager_generator
():
mock
=
MockResource
()
try
:
mock
.
yielded
=
True
yield
mock
finally
:
mock
.
stopped
=
True
class
MockNested
(
nested
):
def
__init__
(
self
,
*
contexts
):
nested
.
__init__
(
self
,
*
contexts
)
self
.
context_called
=
False
self
.
enter_called
=
False
self
.
exit_called
=
False
self
.
exit_args
=
None
def
__context__
(
self
):
self
.
context_called
=
True
return
nested
.
__context__
(
self
)
def
__enter__
(
self
):
self
.
enter_called
=
True
return
nested
.
__enter__
(
self
)
def
__exit__
(
self
,
*
exc_info
):
self
.
exit_called
=
True
self
.
exit_args
=
exc_info
return
nested
.
__exit__
(
self
,
*
exc_info
)
class
FailureTestCase
(
unittest
.
TestCase
):
def
testNameError
(
self
):
def
fooNotDeclared
():
with
foo
:
pass
self
.
assertRaises
(
NameError
,
fooNotDeclared
)
def
testContextAttributeError
(
self
):
class
LacksContext
(
object
):
def
__enter__
(
self
):
pass
def
__exit__
(
self
,
type
,
value
,
traceback
):
pass
def
fooLacksContext
():
foo
=
LacksContext
()
with
foo
:
pass
self
.
assertRaises
(
AttributeError
,
fooLacksContext
)
def
testEnterAttributeError
(
self
):
class
LacksEnter
(
object
):
def
__context__
(
self
):
pass
def
__exit__
(
self
,
type
,
value
,
traceback
):
pass
def
fooLacksEnter
():
foo
=
LacksEnter
()
with
foo
:
pass
self
.
assertRaises
(
AttributeError
,
fooLacksEnter
)
def
testExitAttributeError
(
self
):
class
LacksExit
(
object
):
def
__context__
(
self
):
pass
def
__enter__
(
self
):
pass
def
fooLacksExit
():
foo
=
LacksExit
()
with
foo
:
pass
self
.
assertRaises
(
AttributeError
,
fooLacksExit
)
def
assertRaisesSyntaxError
(
self
,
codestr
):
def
shouldRaiseSyntaxError
(
s
):
compile
(
s
,
''
,
'single'
)
self
.
assertRaises
(
SyntaxError
,
shouldRaiseSyntaxError
,
codestr
)
def
testAssignmentToNoneError
(
self
):
self
.
assertRaisesSyntaxError
(
'with mock as None:
\
n
pass'
)
self
.
assertRaisesSyntaxError
(
'with mock as (None):
\
n
'
' pass'
)
def
testAssignmentToEmptyTupleError
(
self
):
self
.
assertRaisesSyntaxError
(
'with mock as ():
\
n
'
' pass'
)
def
testAssignmentToTupleOnlyContainingNoneError
(
self
):
self
.
assertRaisesSyntaxError
(
'with mock as None,:
\
n
pass'
)
self
.
assertRaisesSyntaxError
(
'with mock as (None,):
\
n
'
' pass'
)
def
testAssignmentToTupleContainingNoneError
(
self
):
self
.
assertRaisesSyntaxError
(
'with mock as (foo, None, bar):
\
n
'
' pass'
)
def
testContextThrows
(
self
):
class
ContextThrows
(
object
):
def
__context__
(
self
):
raise
RuntimeError
(
"Context threw"
)
def
shouldThrow
():
ct
=
ContextThrows
()
self
.
foo
=
None
with
ct
as
self
.
foo
:
pass
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertEqual
(
self
.
foo
,
None
)
def
testEnterThrows
(
self
):
class
EnterThrows
(
object
):
def
__context__
(
self
):
return
self
def
__enter__
(
self
):
raise
RuntimeError
(
"Context threw"
)
def
__exit__
(
self
,
*
args
):
pass
def
shouldThrow
():
ct
=
EnterThrows
()
self
.
foo
=
None
with
ct
as
self
.
foo
:
pass
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertEqual
(
self
.
foo
,
None
)
def
testExitThrows
(
self
):
class
ExitThrows
(
object
):
def
__context__
(
self
):
return
self
def
__enter__
(
self
):
return
def
__exit__
(
self
,
*
args
):
raise
RuntimeError
(
42
)
def
shouldThrow
():
with
ExitThrows
():
pass
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
class
ContextmanagerAssertionMixin
(
object
):
TEST_EXCEPTION
=
RuntimeError
(
"test exception"
)
def
assertInWithManagerInvariants
(
self
,
mock_manager
):
self
.
assertTrue
(
mock_manager
.
context_called
)
self
.
assertTrue
(
mock_manager
.
enter_called
)
self
.
assertFalse
(
mock_manager
.
exit_called
)
self
.
assertEqual
(
mock_manager
.
exit_args
,
None
)
def
assertAfterWithManagerInvariants
(
self
,
mock_manager
,
exit_args
):
self
.
assertTrue
(
mock_manager
.
context_called
)
self
.
assertTrue
(
mock_manager
.
enter_called
)
self
.
assertTrue
(
mock_manager
.
exit_called
)
self
.
assertEqual
(
mock_manager
.
exit_args
,
exit_args
)
def
assertAfterWithManagerInvariantsNoError
(
self
,
mock_manager
):
self
.
assertAfterWithManagerInvariants
(
mock_manager
,
(
None
,
None
,
None
))
def
assertInWithGeneratorInvariants
(
self
,
mock_generator
):
self
.
assertTrue
(
mock_generator
.
yielded
)
self
.
assertFalse
(
mock_generator
.
stopped
)
def
assertAfterWithGeneratorInvariantsNoError
(
self
,
mock_generator
):
self
.
assertTrue
(
mock_generator
.
yielded
)
self
.
assertTrue
(
mock_generator
.
stopped
)
def
raiseTestException
(
self
):
raise
self
.
TEST_EXCEPTION
def
assertAfterWithManagerInvariantsWithError
(
self
,
mock_manager
):
self
.
assertTrue
(
mock_manager
.
context_called
)
self
.
assertTrue
(
mock_manager
.
enter_called
)
self
.
assertTrue
(
mock_manager
.
exit_called
)
self
.
assertEqual
(
mock_manager
.
exit_args
[
0
],
RuntimeError
)
self
.
assertEqual
(
mock_manager
.
exit_args
[
1
],
self
.
TEST_EXCEPTION
)
def
assertAfterWithGeneratorInvariantsWithError
(
self
,
mock_generator
):
self
.
assertTrue
(
mock_generator
.
yielded
)
self
.
assertTrue
(
mock_generator
.
stopped
)
class
NonexceptionalTestCase
(
unittest
.
TestCase
,
ContextmanagerAssertionMixin
):
def
testInlineGeneratorSyntax
(
self
):
with
mock_contextmanager_generator
():
pass
def
testUnboundGenerator
(
self
):
mock
=
mock_contextmanager_generator
()
with
mock
:
pass
self
.
assertAfterWithManagerInvariantsNoError
(
mock
)
def
testInlineGeneratorBoundSyntax
(
self
):
with
mock_contextmanager_generator
()
as
foo
:
self
.
assertInWithGeneratorInvariants
(
foo
)
# FIXME: In the future, we'll try to keep the bound names from leaking
self
.
assertAfterWithGeneratorInvariantsNoError
(
foo
)
def
testInlineGeneratorBoundToExistingVariable
(
self
):
foo
=
None
with
mock_contextmanager_generator
()
as
foo
:
self
.
assertInWithGeneratorInvariants
(
foo
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
foo
)
def
testInlineGeneratorBoundToDottedVariable
(
self
):
with
mock_contextmanager_generator
()
as
self
.
foo
:
self
.
assertInWithGeneratorInvariants
(
self
.
foo
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
self
.
foo
)
def
testBoundGenerator
(
self
):
mock
=
mock_contextmanager_generator
()
with
mock
as
foo
:
self
.
assertInWithGeneratorInvariants
(
foo
)
self
.
assertInWithManagerInvariants
(
mock
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
foo
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock
)
def
testNestedSingleStatements
(
self
):
mock_a
=
mock_contextmanager_generator
()
with
mock_a
as
foo
:
mock_b
=
mock_contextmanager_generator
()
with
mock_b
as
bar
:
self
.
assertInWithManagerInvariants
(
mock_a
)
self
.
assertInWithManagerInvariants
(
mock_b
)
self
.
assertInWithGeneratorInvariants
(
foo
)
self
.
assertInWithGeneratorInvariants
(
bar
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_b
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
bar
)
self
.
assertInWithManagerInvariants
(
mock_a
)
self
.
assertInWithGeneratorInvariants
(
foo
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_a
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
foo
)
class
NestedNonexceptionalTestCase
(
unittest
.
TestCase
,
ContextmanagerAssertionMixin
):
def
testSingleArgInlineGeneratorSyntax
(
self
):
with
nested
(
mock_contextmanager_generator
()):
pass
def
testSingleArgUnbound
(
self
):
mock_contextmanager
=
mock_contextmanager_generator
()
mock_nested
=
MockNested
(
mock_contextmanager
)
with
mock_nested
:
self
.
assertInWithManagerInvariants
(
mock_contextmanager
)
self
.
assertInWithManagerInvariants
(
mock_nested
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_contextmanager
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_nested
)
def
testSingleArgBoundToNonTuple
(
self
):
m
=
mock_contextmanager_generator
()
# This will bind all the arguments to nested() into a single list
# assigned to foo.
with
nested
(
m
)
as
foo
:
self
.
assertInWithManagerInvariants
(
m
)
self
.
assertAfterWithManagerInvariantsNoError
(
m
)
def
testSingleArgBoundToSingleElementParenthesizedList
(
self
):
m
=
mock_contextmanager_generator
()
# This will bind all the arguments to nested() into a single list
# assigned to foo.
# FIXME: what should this do: with nested(m) as (foo,):
with
nested
(
m
)
as
(
foo
):
self
.
assertInWithManagerInvariants
(
m
)
self
.
assertAfterWithManagerInvariantsNoError
(
m
)
def
testSingleArgBoundToMultipleElementTupleError
(
self
):
def
shouldThrowValueError
():
with
nested
(
mock_contextmanager_generator
())
as
(
foo
,
bar
):
pass
self
.
assertRaises
(
ValueError
,
shouldThrowValueError
)
def
testSingleArgUnbound
(
self
):
mock_contextmanager
=
mock_contextmanager_generator
()
mock_nested
=
MockNested
(
mock_contextmanager
)
with
mock_nested
:
self
.
assertInWithManagerInvariants
(
mock_contextmanager
)
self
.
assertInWithManagerInvariants
(
mock_nested
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_contextmanager
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_nested
)
def
testMultipleArgUnbound
(
self
):
m
=
mock_contextmanager_generator
()
n
=
mock_contextmanager_generator
()
o
=
mock_contextmanager_generator
()
mock_nested
=
MockNested
(
m
,
n
,
o
)
with
mock_nested
:
self
.
assertInWithManagerInvariants
(
m
)
self
.
assertInWithManagerInvariants
(
n
)
self
.
assertInWithManagerInvariants
(
o
)
self
.
assertInWithManagerInvariants
(
mock_nested
)
self
.
assertAfterWithManagerInvariantsNoError
(
m
)
self
.
assertAfterWithManagerInvariantsNoError
(
n
)
self
.
assertAfterWithManagerInvariantsNoError
(
o
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_nested
)
def
testMultipleArgBound
(
self
):
mock_nested
=
MockNested
(
mock_contextmanager_generator
(),
mock_contextmanager_generator
(),
mock_contextmanager_generator
())
with
mock_nested
as
(
m
,
n
,
o
):
self
.
assertInWithGeneratorInvariants
(
m
)
self
.
assertInWithGeneratorInvariants
(
n
)
self
.
assertInWithGeneratorInvariants
(
o
)
self
.
assertInWithManagerInvariants
(
mock_nested
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
m
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
n
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
o
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_nested
)
class
ExceptionalTestCase
(
unittest
.
TestCase
,
ContextmanagerAssertionMixin
):
def
testSingleResource
(
self
):
cm
=
mock_contextmanager_generator
()
def
shouldThrow
():
with
cm
as
self
.
resource
:
self
.
assertInWithManagerInvariants
(
cm
)
self
.
assertInWithGeneratorInvariants
(
self
.
resource
)
self
.
raiseTestException
()
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertAfterWithManagerInvariantsWithError
(
cm
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
resource
)
def
testNestedSingleStatements
(
self
):
mock_a
=
mock_contextmanager_generator
()
mock_b
=
mock_contextmanager_generator
()
def
shouldThrow
():
with
mock_a
as
self
.
foo
:
with
mock_b
as
self
.
bar
:
self
.
assertInWithManagerInvariants
(
mock_a
)
self
.
assertInWithManagerInvariants
(
mock_b
)
self
.
assertInWithGeneratorInvariants
(
self
.
foo
)
self
.
assertInWithGeneratorInvariants
(
self
.
bar
)
self
.
raiseTestException
()
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertAfterWithManagerInvariantsWithError
(
mock_a
)
self
.
assertAfterWithManagerInvariantsWithError
(
mock_b
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
foo
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
bar
)
def
testMultipleResourcesInSingleStatement
(
self
):
cm_a
=
mock_contextmanager_generator
()
cm_b
=
mock_contextmanager_generator
()
mock_nested
=
MockNested
(
cm_a
,
cm_b
)
def
shouldThrow
():
with
mock_nested
as
(
self
.
resource_a
,
self
.
resource_b
):
self
.
assertInWithManagerInvariants
(
cm_a
)
self
.
assertInWithManagerInvariants
(
cm_b
)
self
.
assertInWithManagerInvariants
(
mock_nested
)
self
.
assertInWithGeneratorInvariants
(
self
.
resource_a
)
self
.
assertInWithGeneratorInvariants
(
self
.
resource_b
)
self
.
raiseTestException
()
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertAfterWithManagerInvariantsWithError
(
cm_a
)
self
.
assertAfterWithManagerInvariantsWithError
(
cm_b
)
self
.
assertAfterWithManagerInvariantsWithError
(
mock_nested
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
resource_a
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
resource_b
)
def
testNestedExceptionBeforeInnerStatement
(
self
):
mock_a
=
mock_contextmanager_generator
()
mock_b
=
mock_contextmanager_generator
()
self
.
bar
=
None
def
shouldThrow
():
with
mock_a
as
self
.
foo
:
self
.
assertInWithManagerInvariants
(
mock_a
)
self
.
assertInWithGeneratorInvariants
(
self
.
foo
)
self
.
raiseTestException
()
with
mock_b
as
self
.
bar
:
pass
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertAfterWithManagerInvariantsWithError
(
mock_a
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
foo
)
# The inner statement stuff should never have been touched
self
.
assertEqual
(
self
.
bar
,
None
)
self
.
assertFalse
(
mock_b
.
context_called
)
self
.
assertFalse
(
mock_b
.
enter_called
)
self
.
assertFalse
(
mock_b
.
exit_called
)
self
.
assertEqual
(
mock_b
.
exit_args
,
None
)
def
testNestedExceptionAfterInnerStatement
(
self
):
mock_a
=
mock_contextmanager_generator
()
mock_b
=
mock_contextmanager_generator
()
def
shouldThrow
():
with
mock_a
as
self
.
foo
:
with
mock_b
as
self
.
bar
:
self
.
assertInWithManagerInvariants
(
mock_a
)
self
.
assertInWithManagerInvariants
(
mock_b
)
self
.
assertInWithGeneratorInvariants
(
self
.
foo
)
self
.
assertInWithGeneratorInvariants
(
self
.
bar
)
self
.
raiseTestException
()
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertAfterWithManagerInvariantsWithError
(
mock_a
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_b
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
foo
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
self
.
bar
)
class
NonLocalFlowControlTestCase
(
unittest
.
TestCase
):
def
testWithBreak
(
self
):
counter
=
0
while
True
:
counter
+=
1
with
mock_contextmanager_generator
():
counter
+=
10
break
counter
+=
100
# Not reached
self
.
assertEqual
(
counter
,
11
)
def
testWithContinue
(
self
):
counter
=
0
while
True
:
counter
+=
1
if
counter
>
2
:
break
with
mock_contextmanager_generator
():
counter
+=
10
continue
counter
+=
100
# Not reached
self
.
assertEqual
(
counter
,
12
)
def
testWithReturn
(
self
):
def
foo
():
counter
=
0
while
True
:
counter
+=
1
with
mock_contextmanager_generator
():
counter
+=
10
return
counter
counter
+=
100
# Not reached
self
.
assertEqual
(
foo
(),
11
)
def
testWithYield
(
self
):
def
gen
():
with
mock_contextmanager_generator
():
yield
12
yield
13
x
=
list
(
gen
())
self
.
assertEqual
(
x
,
[
12
,
13
])
def
testWithRaise
(
self
):
counter
=
0
try
:
counter
+=
1
with
mock_contextmanager_generator
():
counter
+=
10
raise
RuntimeError
counter
+=
100
# Not reached
except
RuntimeError
:
self
.
assertEqual
(
counter
,
11
)
else
:
self
.
fail
(
"Didn't raise RuntimeError"
)
class
AssignmentTargetTestCase
(
unittest
.
TestCase
):
def
testSingleComplexTarget
(
self
):
targets
=
{
1
:
[
0
,
1
,
2
]}
with
mock_contextmanager_generator
()
as
targets
[
1
][
0
]:
self
.
assertEqual
(
targets
.
keys
(),
[
1
])
self
.
assertEqual
(
targets
[
1
][
0
].
__class__
,
MockResource
)
with
mock_contextmanager_generator
()
as
targets
.
values
()[
0
][
1
]:
self
.
assertEqual
(
targets
.
keys
(),
[
1
])
self
.
assertEqual
(
targets
[
1
][
1
].
__class__
,
MockResource
)
with
mock_contextmanager_generator
()
as
targets
[
2
]:
keys
=
targets
.
keys
()
keys
.
sort
()
self
.
assertEqual
(
keys
,
[
1
,
2
])
class
C
:
pass
blah
=
C
()
with
mock_contextmanager_generator
()
as
blah
.
foo
:
self
.
assertEqual
(
hasattr
(
blah
,
"foo"
),
True
)
def
testMultipleComplexTargets
(
self
):
class
C
:
def
__context__
(
self
):
return
self
def
__enter__
(
self
):
return
1
,
2
,
3
def
__exit__
(
self
,
*
a
):
pass
targets
=
{
1
:
[
0
,
1
,
2
]}
with
C
()
as
(
targets
[
1
][
0
],
targets
[
1
][
1
],
targets
[
1
][
2
]):
self
.
assertEqual
(
targets
,
{
1
:
[
1
,
2
,
3
]})
with
C
()
as
(
targets
.
values
()[
0
][
2
],
targets
.
values
()[
0
][
1
],
targets
.
values
()[
0
][
0
]):
self
.
assertEqual
(
targets
,
{
1
:
[
3
,
2
,
1
]})
with
C
()
as
(
targets
[
1
],
targets
[
2
],
targets
[
3
]):
self
.
assertEqual
(
targets
,
{
1
:
1
,
2
:
2
,
3
:
3
})
class
B
:
pass
blah
=
B
()
with
C
()
as
(
blah
.
one
,
blah
.
two
,
blah
.
three
):
self
.
assertEqual
(
blah
.
one
,
1
)
self
.
assertEqual
(
blah
.
two
,
2
)
self
.
assertEqual
(
blah
.
three
,
3
)
def
test_main
():
run_unittest
(
FailureTestCase
,
NonexceptionalTestCase
,
NestedNonexceptionalTestCase
,
ExceptionalTestCase
,
NonLocalFlowControlTestCase
,
AssignmentTargetTestCase
)
if
__name__
==
'__main__'
:
test_main
()
#!/usr/bin/env python
"""Unit tests for the with statement specified in PEP 343."""
__author__
=
"Mike Bland"
__email__
=
"mbland at acm dot org"
import
unittest
from
test.contextmanager
import
GeneratorContextManager
from
test.nested
import
nested
from
test.test_support
import
run_unittest
class
MockContextManager
(
GeneratorContextManager
):
def
__init__
(
self
,
gen
):
GeneratorContextManager
.
__init__
(
self
,
gen
)
self
.
context_called
=
False
self
.
enter_called
=
False
self
.
exit_called
=
False
self
.
exit_args
=
None
def
__context__
(
self
):
self
.
context_called
=
True
return
GeneratorContextManager
.
__context__
(
self
)
def
__enter__
(
self
):
self
.
enter_called
=
True
return
GeneratorContextManager
.
__enter__
(
self
)
def
__exit__
(
self
,
type
,
value
,
traceback
):
self
.
exit_called
=
True
self
.
exit_args
=
(
type
,
value
,
traceback
)
return
GeneratorContextManager
.
__exit__
(
self
,
type
,
value
,
traceback
)
def
mock_contextmanager
(
func
):
def
helper
(
*
args
,
**
kwds
):
return
MockContextManager
(
func
(
*
args
,
**
kwds
))
return
helper
class
MockResource
(
object
):
def
__init__
(
self
):
self
.
yielded
=
False
self
.
stopped
=
False
@
mock_contextmanager
def
mock_contextmanager_generator
():
mock
=
MockResource
()
try
:
mock
.
yielded
=
True
yield
mock
finally
:
mock
.
stopped
=
True
class
MockNested
(
nested
):
def
__init__
(
self
,
*
contexts
):
nested
.
__init__
(
self
,
*
contexts
)
self
.
context_called
=
False
self
.
enter_called
=
False
self
.
exit_called
=
False
self
.
exit_args
=
None
def
__context__
(
self
):
self
.
context_called
=
True
return
nested
.
__context__
(
self
)
def
__enter__
(
self
):
self
.
enter_called
=
True
return
nested
.
__enter__
(
self
)
def
__exit__
(
self
,
*
exc_info
):
self
.
exit_called
=
True
self
.
exit_args
=
exc_info
return
nested
.
__exit__
(
self
,
*
exc_info
)
class
FailureTestCase
(
unittest
.
TestCase
):
def
testNameError
(
self
):
def
fooNotDeclared
():
with
foo
:
pass
self
.
assertRaises
(
NameError
,
fooNotDeclared
)
def
testContextAttributeError
(
self
):
class
LacksContext
(
object
):
def
__enter__
(
self
):
pass
def
__exit__
(
self
,
type
,
value
,
traceback
):
pass
def
fooLacksContext
():
foo
=
LacksContext
()
with
foo
:
pass
self
.
assertRaises
(
AttributeError
,
fooLacksContext
)
def
testEnterAttributeError
(
self
):
class
LacksEnter
(
object
):
def
__context__
(
self
):
pass
def
__exit__
(
self
,
type
,
value
,
traceback
):
pass
def
fooLacksEnter
():
foo
=
LacksEnter
()
with
foo
:
pass
self
.
assertRaises
(
AttributeError
,
fooLacksEnter
)
def
testExitAttributeError
(
self
):
class
LacksExit
(
object
):
def
__context__
(
self
):
pass
def
__enter__
(
self
):
pass
def
fooLacksExit
():
foo
=
LacksExit
()
with
foo
:
pass
self
.
assertRaises
(
AttributeError
,
fooLacksExit
)
def
assertRaisesSyntaxError
(
self
,
codestr
):
def
shouldRaiseSyntaxError
(
s
):
compile
(
s
,
''
,
'single'
)
self
.
assertRaises
(
SyntaxError
,
shouldRaiseSyntaxError
,
codestr
)
def
testAssignmentToNoneError
(
self
):
self
.
assertRaisesSyntaxError
(
'with mock as None:
\
n
pass'
)
self
.
assertRaisesSyntaxError
(
'with mock as (None):
\
n
'
' pass'
)
def
testAssignmentToEmptyTupleError
(
self
):
self
.
assertRaisesSyntaxError
(
'with mock as ():
\
n
'
' pass'
)
def
testAssignmentToTupleOnlyContainingNoneError
(
self
):
self
.
assertRaisesSyntaxError
(
'with mock as None,:
\
n
pass'
)
self
.
assertRaisesSyntaxError
(
'with mock as (None,):
\
n
'
' pass'
)
def
testAssignmentToTupleContainingNoneError
(
self
):
self
.
assertRaisesSyntaxError
(
'with mock as (foo, None, bar):
\
n
'
' pass'
)
def
testContextThrows
(
self
):
class
ContextThrows
(
object
):
def
__context__
(
self
):
raise
RuntimeError
(
"Context threw"
)
def
shouldThrow
():
ct
=
ContextThrows
()
self
.
foo
=
None
with
ct
as
self
.
foo
:
pass
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertEqual
(
self
.
foo
,
None
)
def
testEnterThrows
(
self
):
class
EnterThrows
(
object
):
def
__context__
(
self
):
return
self
def
__enter__
(
self
):
raise
RuntimeError
(
"Context threw"
)
def
__exit__
(
self
,
*
args
):
pass
def
shouldThrow
():
ct
=
EnterThrows
()
self
.
foo
=
None
with
ct
as
self
.
foo
:
pass
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertEqual
(
self
.
foo
,
None
)
def
testExitThrows
(
self
):
class
ExitThrows
(
object
):
def
__context__
(
self
):
return
self
def
__enter__
(
self
):
return
def
__exit__
(
self
,
*
args
):
raise
RuntimeError
(
42
)
def
shouldThrow
():
with
ExitThrows
():
pass
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
class
ContextmanagerAssertionMixin
(
object
):
TEST_EXCEPTION
=
RuntimeError
(
"test exception"
)
def
assertInWithManagerInvariants
(
self
,
mock_manager
):
self
.
assertTrue
(
mock_manager
.
context_called
)
self
.
assertTrue
(
mock_manager
.
enter_called
)
self
.
assertFalse
(
mock_manager
.
exit_called
)
self
.
assertEqual
(
mock_manager
.
exit_args
,
None
)
def
assertAfterWithManagerInvariants
(
self
,
mock_manager
,
exit_args
):
self
.
assertTrue
(
mock_manager
.
context_called
)
self
.
assertTrue
(
mock_manager
.
enter_called
)
self
.
assertTrue
(
mock_manager
.
exit_called
)
self
.
assertEqual
(
mock_manager
.
exit_args
,
exit_args
)
def
assertAfterWithManagerInvariantsNoError
(
self
,
mock_manager
):
self
.
assertAfterWithManagerInvariants
(
mock_manager
,
(
None
,
None
,
None
))
def
assertInWithGeneratorInvariants
(
self
,
mock_generator
):
self
.
assertTrue
(
mock_generator
.
yielded
)
self
.
assertFalse
(
mock_generator
.
stopped
)
def
assertAfterWithGeneratorInvariantsNoError
(
self
,
mock_generator
):
self
.
assertTrue
(
mock_generator
.
yielded
)
self
.
assertTrue
(
mock_generator
.
stopped
)
def
raiseTestException
(
self
):
raise
self
.
TEST_EXCEPTION
def
assertAfterWithManagerInvariantsWithError
(
self
,
mock_manager
):
self
.
assertTrue
(
mock_manager
.
context_called
)
self
.
assertTrue
(
mock_manager
.
enter_called
)
self
.
assertTrue
(
mock_manager
.
exit_called
)
self
.
assertEqual
(
mock_manager
.
exit_args
[
0
],
RuntimeError
)
self
.
assertEqual
(
mock_manager
.
exit_args
[
1
],
self
.
TEST_EXCEPTION
)
def
assertAfterWithGeneratorInvariantsWithError
(
self
,
mock_generator
):
self
.
assertTrue
(
mock_generator
.
yielded
)
self
.
assertTrue
(
mock_generator
.
stopped
)
class
NonexceptionalTestCase
(
unittest
.
TestCase
,
ContextmanagerAssertionMixin
):
def
testInlineGeneratorSyntax
(
self
):
with
mock_contextmanager_generator
():
pass
def
testUnboundGenerator
(
self
):
mock
=
mock_contextmanager_generator
()
with
mock
:
pass
self
.
assertAfterWithManagerInvariantsNoError
(
mock
)
def
testInlineGeneratorBoundSyntax
(
self
):
with
mock_contextmanager_generator
()
as
foo
:
self
.
assertInWithGeneratorInvariants
(
foo
)
# FIXME: In the future, we'll try to keep the bound names from leaking
self
.
assertAfterWithGeneratorInvariantsNoError
(
foo
)
def
testInlineGeneratorBoundToExistingVariable
(
self
):
foo
=
None
with
mock_contextmanager_generator
()
as
foo
:
self
.
assertInWithGeneratorInvariants
(
foo
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
foo
)
def
testInlineGeneratorBoundToDottedVariable
(
self
):
with
mock_contextmanager_generator
()
as
self
.
foo
:
self
.
assertInWithGeneratorInvariants
(
self
.
foo
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
self
.
foo
)
def
testBoundGenerator
(
self
):
mock
=
mock_contextmanager_generator
()
with
mock
as
foo
:
self
.
assertInWithGeneratorInvariants
(
foo
)
self
.
assertInWithManagerInvariants
(
mock
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
foo
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock
)
def
testNestedSingleStatements
(
self
):
mock_a
=
mock_contextmanager_generator
()
with
mock_a
as
foo
:
mock_b
=
mock_contextmanager_generator
()
with
mock_b
as
bar
:
self
.
assertInWithManagerInvariants
(
mock_a
)
self
.
assertInWithManagerInvariants
(
mock_b
)
self
.
assertInWithGeneratorInvariants
(
foo
)
self
.
assertInWithGeneratorInvariants
(
bar
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_b
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
bar
)
self
.
assertInWithManagerInvariants
(
mock_a
)
self
.
assertInWithGeneratorInvariants
(
foo
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_a
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
foo
)
class
NestedNonexceptionalTestCase
(
unittest
.
TestCase
,
ContextmanagerAssertionMixin
):
def
testSingleArgInlineGeneratorSyntax
(
self
):
with
nested
(
mock_contextmanager_generator
()):
pass
def
testSingleArgUnbound
(
self
):
mock_contextmanager
=
mock_contextmanager_generator
()
mock_nested
=
MockNested
(
mock_contextmanager
)
with
mock_nested
:
self
.
assertInWithManagerInvariants
(
mock_contextmanager
)
self
.
assertInWithManagerInvariants
(
mock_nested
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_contextmanager
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_nested
)
def
testSingleArgBoundToNonTuple
(
self
):
m
=
mock_contextmanager_generator
()
# This will bind all the arguments to nested() into a single list
# assigned to foo.
with
nested
(
m
)
as
foo
:
self
.
assertInWithManagerInvariants
(
m
)
self
.
assertAfterWithManagerInvariantsNoError
(
m
)
def
testSingleArgBoundToSingleElementParenthesizedList
(
self
):
m
=
mock_contextmanager_generator
()
# This will bind all the arguments to nested() into a single list
# assigned to foo.
# FIXME: what should this do: with nested(m) as (foo,):
with
nested
(
m
)
as
(
foo
):
self
.
assertInWithManagerInvariants
(
m
)
self
.
assertAfterWithManagerInvariantsNoError
(
m
)
def
testSingleArgBoundToMultipleElementTupleError
(
self
):
def
shouldThrowValueError
():
with
nested
(
mock_contextmanager_generator
())
as
(
foo
,
bar
):
pass
self
.
assertRaises
(
ValueError
,
shouldThrowValueError
)
def
testSingleArgUnbound
(
self
):
mock_contextmanager
=
mock_contextmanager_generator
()
mock_nested
=
MockNested
(
mock_contextmanager
)
with
mock_nested
:
self
.
assertInWithManagerInvariants
(
mock_contextmanager
)
self
.
assertInWithManagerInvariants
(
mock_nested
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_contextmanager
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_nested
)
def
testMultipleArgUnbound
(
self
):
m
=
mock_contextmanager_generator
()
n
=
mock_contextmanager_generator
()
o
=
mock_contextmanager_generator
()
mock_nested
=
MockNested
(
m
,
n
,
o
)
with
mock_nested
:
self
.
assertInWithManagerInvariants
(
m
)
self
.
assertInWithManagerInvariants
(
n
)
self
.
assertInWithManagerInvariants
(
o
)
self
.
assertInWithManagerInvariants
(
mock_nested
)
self
.
assertAfterWithManagerInvariantsNoError
(
m
)
self
.
assertAfterWithManagerInvariantsNoError
(
n
)
self
.
assertAfterWithManagerInvariantsNoError
(
o
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_nested
)
def
testMultipleArgBound
(
self
):
mock_nested
=
MockNested
(
mock_contextmanager_generator
(),
mock_contextmanager_generator
(),
mock_contextmanager_generator
())
with
mock_nested
as
(
m
,
n
,
o
):
self
.
assertInWithGeneratorInvariants
(
m
)
self
.
assertInWithGeneratorInvariants
(
n
)
self
.
assertInWithGeneratorInvariants
(
o
)
self
.
assertInWithManagerInvariants
(
mock_nested
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
m
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
n
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
o
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_nested
)
class
ExceptionalTestCase
(
unittest
.
TestCase
,
ContextmanagerAssertionMixin
):
def
testSingleResource
(
self
):
cm
=
mock_contextmanager_generator
()
def
shouldThrow
():
with
cm
as
self
.
resource
:
self
.
assertInWithManagerInvariants
(
cm
)
self
.
assertInWithGeneratorInvariants
(
self
.
resource
)
self
.
raiseTestException
()
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertAfterWithManagerInvariantsWithError
(
cm
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
resource
)
def
testNestedSingleStatements
(
self
):
mock_a
=
mock_contextmanager_generator
()
mock_b
=
mock_contextmanager_generator
()
def
shouldThrow
():
with
mock_a
as
self
.
foo
:
with
mock_b
as
self
.
bar
:
self
.
assertInWithManagerInvariants
(
mock_a
)
self
.
assertInWithManagerInvariants
(
mock_b
)
self
.
assertInWithGeneratorInvariants
(
self
.
foo
)
self
.
assertInWithGeneratorInvariants
(
self
.
bar
)
self
.
raiseTestException
()
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertAfterWithManagerInvariantsWithError
(
mock_a
)
self
.
assertAfterWithManagerInvariantsWithError
(
mock_b
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
foo
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
bar
)
def
testMultipleResourcesInSingleStatement
(
self
):
cm_a
=
mock_contextmanager_generator
()
cm_b
=
mock_contextmanager_generator
()
mock_nested
=
MockNested
(
cm_a
,
cm_b
)
def
shouldThrow
():
with
mock_nested
as
(
self
.
resource_a
,
self
.
resource_b
):
self
.
assertInWithManagerInvariants
(
cm_a
)
self
.
assertInWithManagerInvariants
(
cm_b
)
self
.
assertInWithManagerInvariants
(
mock_nested
)
self
.
assertInWithGeneratorInvariants
(
self
.
resource_a
)
self
.
assertInWithGeneratorInvariants
(
self
.
resource_b
)
self
.
raiseTestException
()
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertAfterWithManagerInvariantsWithError
(
cm_a
)
self
.
assertAfterWithManagerInvariantsWithError
(
cm_b
)
self
.
assertAfterWithManagerInvariantsWithError
(
mock_nested
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
resource_a
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
resource_b
)
def
testNestedExceptionBeforeInnerStatement
(
self
):
mock_a
=
mock_contextmanager_generator
()
mock_b
=
mock_contextmanager_generator
()
self
.
bar
=
None
def
shouldThrow
():
with
mock_a
as
self
.
foo
:
self
.
assertInWithManagerInvariants
(
mock_a
)
self
.
assertInWithGeneratorInvariants
(
self
.
foo
)
self
.
raiseTestException
()
with
mock_b
as
self
.
bar
:
pass
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertAfterWithManagerInvariantsWithError
(
mock_a
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
foo
)
# The inner statement stuff should never have been touched
self
.
assertEqual
(
self
.
bar
,
None
)
self
.
assertFalse
(
mock_b
.
context_called
)
self
.
assertFalse
(
mock_b
.
enter_called
)
self
.
assertFalse
(
mock_b
.
exit_called
)
self
.
assertEqual
(
mock_b
.
exit_args
,
None
)
def
testNestedExceptionAfterInnerStatement
(
self
):
mock_a
=
mock_contextmanager_generator
()
mock_b
=
mock_contextmanager_generator
()
def
shouldThrow
():
with
mock_a
as
self
.
foo
:
with
mock_b
as
self
.
bar
:
self
.
assertInWithManagerInvariants
(
mock_a
)
self
.
assertInWithManagerInvariants
(
mock_b
)
self
.
assertInWithGeneratorInvariants
(
self
.
foo
)
self
.
assertInWithGeneratorInvariants
(
self
.
bar
)
self
.
raiseTestException
()
self
.
assertRaises
(
RuntimeError
,
shouldThrow
)
self
.
assertAfterWithManagerInvariantsWithError
(
mock_a
)
self
.
assertAfterWithManagerInvariantsNoError
(
mock_b
)
self
.
assertAfterWithGeneratorInvariantsWithError
(
self
.
foo
)
self
.
assertAfterWithGeneratorInvariantsNoError
(
self
.
bar
)
class
NonLocalFlowControlTestCase
(
unittest
.
TestCase
):
def
testWithBreak
(
self
):
counter
=
0
while
True
:
counter
+=
1
with
mock_contextmanager_generator
():
counter
+=
10
break
counter
+=
100
# Not reached
self
.
assertEqual
(
counter
,
11
)
def
testWithContinue
(
self
):
counter
=
0
while
True
:
counter
+=
1
if
counter
>
2
:
break
with
mock_contextmanager_generator
():
counter
+=
10
continue
counter
+=
100
# Not reached
self
.
assertEqual
(
counter
,
12
)
def
testWithReturn
(
self
):
def
foo
():
counter
=
0
while
True
:
counter
+=
1
with
mock_contextmanager_generator
():
counter
+=
10
return
counter
counter
+=
100
# Not reached
self
.
assertEqual
(
foo
(),
11
)
def
testWithYield
(
self
):
def
gen
():
with
mock_contextmanager_generator
():
yield
12
yield
13
x
=
list
(
gen
())
self
.
assertEqual
(
x
,
[
12
,
13
])
def
testWithRaise
(
self
):
counter
=
0
try
:
counter
+=
1
with
mock_contextmanager_generator
():
counter
+=
10
raise
RuntimeError
counter
+=
100
# Not reached
except
RuntimeError
:
self
.
assertEqual
(
counter
,
11
)
else
:
self
.
fail
(
"Didn't raise RuntimeError"
)
class
AssignmentTargetTestCase
(
unittest
.
TestCase
):
def
testSingleComplexTarget
(
self
):
targets
=
{
1
:
[
0
,
1
,
2
]}
with
mock_contextmanager_generator
()
as
targets
[
1
][
0
]:
self
.
assertEqual
(
targets
.
keys
(),
[
1
])
self
.
assertEqual
(
targets
[
1
][
0
].
__class__
,
MockResource
)
with
mock_contextmanager_generator
()
as
targets
.
values
()[
0
][
1
]:
self
.
assertEqual
(
targets
.
keys
(),
[
1
])
self
.
assertEqual
(
targets
[
1
][
1
].
__class__
,
MockResource
)
with
mock_contextmanager_generator
()
as
targets
[
2
]:
keys
=
targets
.
keys
()
keys
.
sort
()
self
.
assertEqual
(
keys
,
[
1
,
2
])
class
C
:
pass
blah
=
C
()
with
mock_contextmanager_generator
()
as
blah
.
foo
:
self
.
assertEqual
(
hasattr
(
blah
,
"foo"
),
True
)
def
testMultipleComplexTargets
(
self
):
class
C
:
def
__context__
(
self
):
return
self
def
__enter__
(
self
):
return
1
,
2
,
3
def
__exit__
(
self
,
*
a
):
pass
targets
=
{
1
:
[
0
,
1
,
2
]}
with
C
()
as
(
targets
[
1
][
0
],
targets
[
1
][
1
],
targets
[
1
][
2
]):
self
.
assertEqual
(
targets
,
{
1
:
[
1
,
2
,
3
]})
with
C
()
as
(
targets
.
values
()[
0
][
2
],
targets
.
values
()[
0
][
1
],
targets
.
values
()[
0
][
0
]):
self
.
assertEqual
(
targets
,
{
1
:
[
3
,
2
,
1
]})
with
C
()
as
(
targets
[
1
],
targets
[
2
],
targets
[
3
]):
self
.
assertEqual
(
targets
,
{
1
:
1
,
2
:
2
,
3
:
3
})
class
B
:
pass
blah
=
B
()
with
C
()
as
(
blah
.
one
,
blah
.
two
,
blah
.
three
):
self
.
assertEqual
(
blah
.
one
,
1
)
self
.
assertEqual
(
blah
.
two
,
2
)
self
.
assertEqual
(
blah
.
three
,
3
)
def
test_main
():
run_unittest
(
FailureTestCase
,
NonexceptionalTestCase
,
NestedNonexceptionalTestCase
,
ExceptionalTestCase
,
NonLocalFlowControlTestCase
,
AssignmentTargetTestCase
)
if
__name__
==
'__main__'
:
test_main
()
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