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
85134706
Commit
85134706
authored
Dec 03, 2015
by
Martin Panter
Browse files
Options
Browse Files
Download
Plain Diff
Issue #14285: Merge runpy exception fix from 3.5
parents
7c088a9b
657257ed
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
110 additions
and
32 deletions
+110
-32
Lib/runpy.py
Lib/runpy.py
+21
-23
Lib/test/test_cmd_line_script.py
Lib/test/test_cmd_line_script.py
+62
-9
Lib/test/test_runpy.py
Lib/test/test_runpy.py
+22
-0
Misc/NEWS
Misc/NEWS
+5
-0
No files found.
Lib/runpy.py
View file @
85134706
...
@@ -99,7 +99,7 @@ def _run_module_code(code, init_globals=None,
...
@@ -99,7 +99,7 @@ def _run_module_code(code, init_globals=None,
return
mod_globals
.
copy
()
return
mod_globals
.
copy
()
# Helper to get the loader, code and filename for a module
# Helper to get the loader, code and filename for a module
def
_get_module_details
(
mod_name
):
def
_get_module_details
(
mod_name
,
error
=
ImportError
):
try
:
try
:
spec
=
importlib
.
util
.
find_spec
(
mod_name
)
spec
=
importlib
.
util
.
find_spec
(
mod_name
)
except
(
ImportError
,
AttributeError
,
TypeError
,
ValueError
)
as
ex
:
except
(
ImportError
,
AttributeError
,
TypeError
,
ValueError
)
as
ex
:
...
@@ -107,27 +107,34 @@ def _get_module_details(mod_name):
...
@@ -107,27 +107,34 @@ def _get_module_details(mod_name):
# importlib, where the latter raises other errors for cases where
# importlib, where the latter raises other errors for cases where
# pkgutil previously raised ImportError
# pkgutil previously raised ImportError
msg
=
"Error while finding spec for {!r} ({}: {})"
msg
=
"Error while finding spec for {!r} ({}: {})"
raise
ImportE
rror
(
msg
.
format
(
mod_name
,
type
(
ex
),
ex
))
from
ex
raise
e
rror
(
msg
.
format
(
mod_name
,
type
(
ex
),
ex
))
from
ex
if
spec
is
None
:
if
spec
is
None
:
raise
ImportE
rror
(
"No module named %s"
%
mod_name
)
raise
e
rror
(
"No module named %s"
%
mod_name
)
if
spec
.
submodule_search_locations
is
not
None
:
if
spec
.
submodule_search_locations
is
not
None
:
if
mod_name
==
"__main__"
or
mod_name
.
endswith
(
".__main__"
):
if
mod_name
==
"__main__"
or
mod_name
.
endswith
(
".__main__"
):
raise
ImportError
(
"Cannot use package as __main__ module"
)
raise
error
(
"Cannot use package as __main__ module"
)
__import__
(
mod_name
)
# Do not catch exceptions initializing package
try
:
try
:
pkg_main_name
=
mod_name
+
".__main__"
pkg_main_name
=
mod_name
+
".__main__"
return
_get_module_details
(
pkg_main_name
)
return
_get_module_details
(
pkg_main_name
)
except
ImportError
as
e
:
except
ImportError
as
e
:
raise
ImportE
rror
((
"%s; %r is a package and cannot "
+
raise
e
rror
((
"%s; %r is a package and cannot "
+
"be directly executed"
)
%
(
e
,
mod_name
))
"be directly executed"
)
%
(
e
,
mod_name
))
loader
=
spec
.
loader
loader
=
spec
.
loader
if
loader
is
None
:
if
loader
is
None
:
raise
ImportE
rror
(
"%r is a namespace package and cannot be executed"
raise
e
rror
(
"%r is a namespace package and cannot be executed"
%
mod_name
)
%
mod_name
)
code
=
loader
.
get_code
(
mod_name
)
try
:
code
=
loader
.
get_code
(
mod_name
)
except
ImportError
as
e
:
raise
error
(
format
(
e
))
from
e
if
code
is
None
:
if
code
is
None
:
raise
ImportE
rror
(
"No code object available for %s"
%
mod_name
)
raise
e
rror
(
"No code object available for %s"
%
mod_name
)
return
mod_name
,
spec
,
code
return
mod_name
,
spec
,
code
class
_Error
(
Exception
):
"""Error that _run_module_as_main() should report without a traceback"""
# XXX ncoghlan: Should this be documented and made public?
# XXX ncoghlan: Should this be documented and made public?
# (Current thoughts: don't repeat the mistake that lead to its
# (Current thoughts: don't repeat the mistake that lead to its
# creation when run_module() no longer met the needs of
# creation when run_module() no longer met the needs of
...
@@ -148,20 +155,11 @@ def _run_module_as_main(mod_name, alter_argv=True):
...
@@ -148,20 +155,11 @@ def _run_module_as_main(mod_name, alter_argv=True):
"""
"""
try
:
try
:
if
alter_argv
or
mod_name
!=
"__main__"
:
# i.e. -m switch
if
alter_argv
or
mod_name
!=
"__main__"
:
# i.e. -m switch
mod_name
,
mod_spec
,
code
=
_get_module_details
(
mod_name
)
mod_name
,
mod_spec
,
code
=
_get_module_details
(
mod_name
,
_Error
)
else
:
# i.e. directory or zipfile execution
else
:
# i.e. directory or zipfile execution
mod_name
,
mod_spec
,
code
=
_get_main_module_details
()
mod_name
,
mod_spec
,
code
=
_get_main_module_details
(
_Error
)
except
ImportError
as
exc
:
except
_Error
as
exc
:
# Try to provide a good error message
msg
=
"%s: %s"
%
(
sys
.
executable
,
exc
)
# for directories, zip files and the -m switch
if
alter_argv
:
# For -m switch, just display the exception
info
=
str
(
exc
)
else
:
# For directories/zipfiles, let the user
# know what the code was looking for
info
=
"can't find '__main__' module in %r"
%
sys
.
argv
[
0
]
msg
=
"%s: %s"
%
(
sys
.
executable
,
info
)
sys
.
exit
(
msg
)
sys
.
exit
(
msg
)
main_globals
=
sys
.
modules
[
"__main__"
].
__dict__
main_globals
=
sys
.
modules
[
"__main__"
].
__dict__
if
alter_argv
:
if
alter_argv
:
...
@@ -184,7 +182,7 @@ def run_module(mod_name, init_globals=None,
...
@@ -184,7 +182,7 @@ def run_module(mod_name, init_globals=None,
# Leave the sys module alone
# Leave the sys module alone
return
_run_code
(
code
,
{},
init_globals
,
run_name
,
mod_spec
)
return
_run_code
(
code
,
{},
init_globals
,
run_name
,
mod_spec
)
def
_get_main_module_details
():
def
_get_main_module_details
(
error
=
ImportError
):
# Helper that gives a nicer error message when attempting to
# Helper that gives a nicer error message when attempting to
# execute a zipfile or directory by invoking __main__.py
# execute a zipfile or directory by invoking __main__.py
# Also moves the standard __main__ out of the way so that the
# Also moves the standard __main__ out of the way so that the
...
@@ -196,7 +194,7 @@ def _get_main_module_details():
...
@@ -196,7 +194,7 @@ def _get_main_module_details():
return
_get_module_details
(
main_name
)
return
_get_module_details
(
main_name
)
except
ImportError
as
exc
:
except
ImportError
as
exc
:
if
main_name
in
str
(
exc
):
if
main_name
in
str
(
exc
):
raise
ImportE
rror
(
"can't find %r module in %r"
%
raise
e
rror
(
"can't find %r module in %r"
%
(
main_name
,
sys
.
path
[
0
]))
from
exc
(
main_name
,
sys
.
path
[
0
]))
from
exc
raise
raise
finally
:
finally
:
...
...
Lib/test/test_cmd_line_script.py
View file @
85134706
...
@@ -397,20 +397,73 @@ class CmdLineTest(unittest.TestCase):
...
@@ -397,20 +397,73 @@ class CmdLineTest(unittest.TestCase):
script_name
,
script_name
,
''
,
''
,
script_name
,
script_name
,
''
,
''
,
importlib
.
machinery
.
SourceFileLoader
)
importlib
.
machinery
.
SourceFileLoader
)
@
contextlib
.
contextmanager
def
setup_test_pkg
(
self
,
*
args
):
with
support
.
temp_dir
()
as
script_dir
,
\
support
.
change_cwd
(
path
=
script_dir
):
pkg_dir
=
os
.
path
.
join
(
script_dir
,
'test_pkg'
)
make_pkg
(
pkg_dir
,
*
args
)
yield
pkg_dir
def
check_dash_m_failure
(
self
,
*
args
):
rc
,
out
,
err
=
assert_python_failure
(
'-m'
,
*
args
,
__isolated
=
False
)
if
verbose
>
1
:
print
(
repr
(
out
))
self
.
assertEqual
(
rc
,
1
)
return
err
def
test_dash_m_error_code_is_one
(
self
):
def
test_dash_m_error_code_is_one
(
self
):
# If a module is invoked with the -m command line flag
# If a module is invoked with the -m command line flag
# and results in an error that the return code to the
# and results in an error that the return code to the
# shell is '1'
# shell is '1'
with
support
.
temp_dir
()
as
script_dir
:
with
self
.
setup_test_pkg
()
as
pkg_dir
:
with
support
.
change_cwd
(
path
=
script_dir
):
script_name
=
_make_test_script
(
pkg_dir
,
'other'
,
pkg_dir
=
os
.
path
.
join
(
script_dir
,
'test_pkg'
)
"if __name__ == '__main__': raise ValueError"
)
make_pkg
(
pkg_dir
)
err
=
self
.
check_dash_m_failure
(
'test_pkg.other'
,
*
example_args
)
script_name
=
_make_test_script
(
pkg_dir
,
'other'
,
self
.
assertIn
(
b'ValueError'
,
err
)
"if __name__ == '__main__': raise ValueError"
)
rc
,
out
,
err
=
assert_python_failure
(
'-m'
,
'test_pkg.other'
,
*
example_args
)
def
test_dash_m_errors
(
self
):
if
verbose
>
1
:
# Exercise error reporting for various invalid package executions
print
(
repr
(
out
))
tests
=
(
(
'builtins'
,
br'No code object available'
),
(
'builtins.x'
,
br'Error while finding spec.*AttributeError'
),
(
'builtins.x.y'
,
br'Error while finding spec.*'
br'ImportError.*No module named.*not a package'
),
(
'os.path'
,
br'loader.*cannot handle'
),
(
'importlib'
,
br'No module named.*'
br'is a package and cannot be directly executed'
),
(
'importlib.nonexistant'
,
br'No module named'
),
)
for
name
,
regex
in
tests
:
with
self
.
subTest
(
name
):
rc
,
_
,
err
=
assert_python_failure
(
'-m'
,
name
)
self
.
assertEqual
(
rc
,
1
)
self
.
assertEqual
(
rc
,
1
)
self
.
assertRegex
(
err
,
regex
)
self
.
assertNotIn
(
b'Traceback'
,
err
)
def
test_dash_m_init_traceback
(
self
):
# These were wrapped in an ImportError and tracebacks were
# suppressed; see Issue 14285
exceptions
=
(
ImportError
,
AttributeError
,
TypeError
,
ValueError
)
for
exception
in
exceptions
:
exception
=
exception
.
__name__
init
=
"raise {0}('Exception in __init__.py')"
.
format
(
exception
)
with
self
.
subTest
(
exception
),
\
self
.
setup_test_pkg
(
init
)
as
pkg_dir
:
err
=
self
.
check_dash_m_failure
(
'test_pkg'
)
self
.
assertIn
(
exception
.
encode
(
'ascii'
),
err
)
self
.
assertIn
(
b'Exception in __init__.py'
,
err
)
self
.
assertIn
(
b'Traceback'
,
err
)
def
test_dash_m_main_traceback
(
self
):
# Ensure that an ImportError's traceback is reported
with
self
.
setup_test_pkg
()
as
pkg_dir
:
main
=
"raise ImportError('Exception in __main__ module')"
_make_test_script
(
pkg_dir
,
'__main__'
,
main
)
err
=
self
.
check_dash_m_failure
(
'test_pkg'
)
self
.
assertIn
(
b'ImportError'
,
err
)
self
.
assertIn
(
b'Exception in __main__ module'
,
err
)
self
.
assertIn
(
b'Traceback'
,
err
)
def
test_pep_409_verbiage
(
self
):
def
test_pep_409_verbiage
(
self
):
# Make sure PEP 409 syntax properly suppresses
# Make sure PEP 409 syntax properly suppresses
...
...
Lib/test/test_runpy.py
View file @
85134706
...
@@ -439,6 +439,28 @@ from ..uncle.cousin import nephew
...
@@ -439,6 +439,28 @@ from ..uncle.cousin import nephew
if
verbose
>
1
:
print
(
"Testing package depth:"
,
depth
)
if
verbose
>
1
:
print
(
"Testing package depth:"
,
depth
)
self
.
_check_package
(
depth
)
self
.
_check_package
(
depth
)
def
test_run_package_init_exceptions
(
self
):
# These were previously wrapped in an ImportError; see Issue 14285
result
=
self
.
_make_pkg
(
""
,
1
,
"__main__"
)
pkg_dir
,
_
,
mod_name
,
_
=
result
mod_name
=
mod_name
.
replace
(
".__main__"
,
""
)
self
.
addCleanup
(
self
.
_del_pkg
,
pkg_dir
,
1
,
mod_name
)
init
=
os
.
path
.
join
(
pkg_dir
,
"__runpy_pkg__"
,
"__init__.py"
)
exceptions
=
(
ImportError
,
AttributeError
,
TypeError
,
ValueError
)
for
exception
in
exceptions
:
name
=
exception
.
__name__
with
self
.
subTest
(
name
):
source
=
"raise {0}('{0} in __init__.py.')"
.
format
(
name
)
with
open
(
init
,
"wt"
,
encoding
=
"ascii"
)
as
mod_file
:
mod_file
.
write
(
source
)
try
:
run_module
(
mod_name
)
except
exception
as
err
:
self
.
assertNotIn
(
"finding spec"
,
format
(
err
))
else
:
self
.
fail
(
"Nothing raised; expected {}"
.
format
(
name
))
def
test_run_package_in_namespace_package
(
self
):
def
test_run_package_in_namespace_package
(
self
):
for
depth
in
range
(
1
,
4
):
for
depth
in
range
(
1
,
4
):
if
verbose
>
1
:
print
(
"Testing package depth:"
,
depth
)
if
verbose
>
1
:
print
(
"Testing package depth:"
,
depth
)
...
...
Misc/NEWS
View file @
85134706
...
@@ -109,6 +109,11 @@ Core and Builtins
...
@@ -109,6 +109,11 @@ Core and Builtins
Library
Library
-------
-------
- Issue #14285: When executing a package with the "python -m package" option,
and package initialization fails, a proper traceback is now reported. The
"runpy" module now lets exceptions from package initialization pass back to
the caller, rather than raising ImportError.
- Issue #25177: Fixed problem with the mean of very small and very large
- Issue #25177: Fixed problem with the mean of very small and very large
numbers. As a side effect, statistics.mean and statistics.variance should
numbers. As a side effect, statistics.mean and statistics.variance should
be significantly faster.
be significantly faster.
...
...
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