Skip to content

Commit 4bbbd42

Browse files
CPython Developersyouknowone
authored andcommitted
Update runpy from CPython 3.10.6
1 parent 8cb2600 commit 4bbbd42

2 files changed

Lines changed: 41 additions & 15 deletions

File tree

Lib/runpy.py

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
import sys
1414
import importlib.machinery # importlib first so we can test #15386 via -m
1515
import importlib.util
16+
import io
1617
import types
17-
from pkgutil import read_code, get_importer
18+
import os
1819

1920
__all__ = [
2021
"run_module", "run_path",
@@ -131,6 +132,9 @@ def _get_module_details(mod_name, error=ImportError):
131132
# importlib, where the latter raises other errors for cases where
132133
# pkgutil previously raised ImportError
133134
msg = "Error while finding module specification for {!r} ({}: {})"
135+
if mod_name.endswith(".py"):
136+
msg += (f". Try using '{mod_name[:-3]}' instead of "
137+
f"'{mod_name}' as the module name.")
134138
raise error(msg.format(mod_name, type(ex).__name__, ex)) from ex
135139
if spec is None:
136140
raise error("No module named %s" % mod_name)
@@ -194,9 +198,24 @@ def _run_module_as_main(mod_name, alter_argv=True):
194198

195199
def run_module(mod_name, init_globals=None,
196200
run_name=None, alter_sys=False):
197-
"""Execute a module's code without importing it
201+
"""Execute a module's code without importing it.
198202
199-
Returns the resulting top level namespace dictionary
203+
mod_name -- an absolute module name or package name.
204+
205+
Optional arguments:
206+
init_globals -- dictionary used to pre-populate the module’s
207+
globals dictionary before the code is executed.
208+
209+
run_name -- if not None, this will be used for setting __name__;
210+
otherwise, __name__ will be set to mod_name + '__main__' if the
211+
named module is a package and to just mod_name otherwise.
212+
213+
alter_sys -- if True, sys.argv[0] is updated with the value of
214+
__file__ and sys.modules[__name__] is updated with a temporary
215+
module object for the module being executed. Both are
216+
restored to their original values before the function returns.
217+
218+
Returns the resulting module globals dictionary.
200219
"""
201220
mod_name, mod_spec, code = _get_module_details(mod_name)
202221
if run_name is None:
@@ -228,27 +247,35 @@ def _get_main_module_details(error=ImportError):
228247

229248
def _get_code_from_file(run_name, fname):
230249
# Check for a compiled file first
231-
with open(fname, "rb") as f:
250+
from pkgutil import read_code
251+
decoded_path = os.path.abspath(os.fsdecode(fname))
252+
with io.open_code(decoded_path) as f:
232253
code = read_code(f)
233254
if code is None:
234255
# That didn't work, so try it as normal source code
235-
with open(fname, "rb") as f:
256+
with io.open_code(decoded_path) as f:
236257
code = compile(f.read(), fname, 'exec')
237258
return code, fname
238259

239260
def run_path(path_name, init_globals=None, run_name=None):
240-
"""Execute code located at the specified filesystem location
261+
"""Execute code located at the specified filesystem location.
262+
263+
path_name -- filesystem location of a Python script, zipfile,
264+
or directory containing a top level __main__.py script.
265+
266+
Optional arguments:
267+
init_globals -- dictionary used to pre-populate the module’s
268+
globals dictionary before the code is executed.
241269
242-
Returns the resulting top level namespace dictionary
270+
run_name -- if not None, this will be used to set __name__;
271+
otherwise, '<run_path>' will be used for __name__.
243272
244-
The file path may refer directly to a Python script (i.e.
245-
one that could be directly executed with execfile) or else
246-
it may refer to a zipfile or directory containing a top
247-
level __main__.py script.
273+
Returns the resulting module globals dictionary.
248274
"""
249275
if run_name is None:
250276
run_name = "<run_path>"
251277
pkg_name = run_name.rpartition(".")[0]
278+
from pkgutil import get_importer
252279
importer = get_importer(path_name)
253280
# Trying to avoid importing imp so as to not consume the deprecation warning.
254281
is_NullImporter = False

Lib/test/test_runpy.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
import textwrap
1313
import unittest
1414
import warnings
15-
from test.support import verbose, no_tracing
15+
from test.support import no_tracing, verbose
16+
from test.support.import_helper import forget, make_legacy_pyc, unload
1617
from test.support.os_helper import create_empty_file, temp_dir
1718
from test.support.script_helper import make_script, make_zip_script
18-
from test.support.import_helper import unload, forget, make_legacy_pyc
1919

2020

2121
import runpy
@@ -745,8 +745,7 @@ def test_main_recursion_error(self):
745745
"runpy.run_path(%r)\n") % dummy_dir
746746
script_name = self._make_test_script(script_dir, mod_name, source)
747747
zip_name, fname = make_zip_script(script_dir, 'test_zip', script_name)
748-
msg = "recursion depth exceeded"
749-
self.assertRaisesRegex(RecursionError, msg, run_path, zip_name)
748+
self.assertRaises(RecursionError, run_path, zip_name)
750749

751750
# TODO: RUSTPYTHON, detect encoding comments in files
752751
@unittest.expectedFailure

0 commit comments

Comments
 (0)