]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-99437: runpy: decode path-like objects before setting globals (#114838)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 12 Aug 2024 08:22:13 +0000 (10:22 +0200)
committerGitHub <noreply@github.com>
Mon, 12 Aug 2024 08:22:13 +0000 (11:22 +0300)
Co-authored-by: Kamil Turek <kamil.turek@hotmail.com>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Lib/runpy.py
Lib/test/test_runpy.py
Misc/NEWS.d/next/Library/2023-08-04-18-43-21.gh-issue-99437.Et8hu8.rst [new file with mode: 0644]

index 42f896c9cd509406726390e82fc42e4958b9bf5c..ef54d3282eee06d937aa1d9d1043cfb93bf01c31 100644 (file)
@@ -247,17 +247,17 @@ def _get_main_module_details(error=ImportError):
         sys.modules[main_name] = saved_main
 
 
-def _get_code_from_file(run_name, fname):
+def _get_code_from_file(fname):
     # Check for a compiled file first
     from pkgutil import read_code
-    decoded_path = os.path.abspath(os.fsdecode(fname))
-    with io.open_code(decoded_path) as f:
+    code_path = os.path.abspath(fname)
+    with io.open_code(code_path) as f:
         code = read_code(f)
     if code is None:
         # That didn't work, so try it as normal source code
-        with io.open_code(decoded_path) as f:
+        with io.open_code(code_path) as f:
             code = compile(f.read(), fname, 'exec')
-    return code, fname
+    return code
 
 def run_path(path_name, init_globals=None, run_name=None):
     """Execute code located at the specified filesystem location.
@@ -279,12 +279,13 @@ def run_path(path_name, init_globals=None, run_name=None):
     pkg_name = run_name.rpartition(".")[0]
     from pkgutil import get_importer
     importer = get_importer(path_name)
+    path_name = os.fsdecode(path_name)
     if isinstance(importer, type(None)):
         # Not a valid sys.path entry, so run the code directly
         # execfile() doesn't help as we want to allow compiled files
-        code, fname = _get_code_from_file(run_name, path_name)
+        code = _get_code_from_file(path_name)
         return _run_module_code(code, init_globals, run_name,
-                                pkg_name=pkg_name, script_name=fname)
+                                pkg_name=pkg_name, script_name=path_name)
     else:
         # Finder is defined for path, so add it to
         # the start of sys.path
index 9c8494105838fc447f4ea94769d902c74a44b54b..3f68962a589d6d7052bf80f9d9c5adc1a548e956 100644 (file)
@@ -660,8 +660,10 @@ class RunPathTestCase(unittest.TestCase, CodeExecutionMixin):
         with temp_dir() as script_dir:
             mod_name = 'script'
             script_name = FakePath(self._make_test_script(script_dir, mod_name))
-            self._check_script(script_name, "<run_path>", script_name,
-                               script_name, expect_spec=False)
+            self._check_script(script_name, "<run_path>",
+                               os.fsdecode(script_name),
+                               os.fsdecode(script_name),
+                               expect_spec=False)
 
     def test_basic_script_no_suffix(self):
         with temp_dir() as script_dir:
diff --git a/Misc/NEWS.d/next/Library/2023-08-04-18-43-21.gh-issue-99437.Et8hu8.rst b/Misc/NEWS.d/next/Library/2023-08-04-18-43-21.gh-issue-99437.Et8hu8.rst
new file mode 100644 (file)
index 0000000..da4e20f
--- /dev/null
@@ -0,0 +1,2 @@
+:func:`runpy.run_path` now decodes path-like objects, making sure __file__
+and sys.argv[0] of the module being run are always strings.