From ffaafe67e63d21e723d998b011f117003d6f6624 Mon Sep 17 00:00:00 2001 From: Taneli Hukkinen <3275109+hukkin@users.noreply.github.com> Date: Tue, 14 Jan 2025 12:12:54 +0200 Subject: [PATCH] Fix generated script when entry point func name is used by the script template --- distlib/scripts.py | 11 ++++++++++- tests/test_scripts.py | 12 ++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/distlib/scripts.py b/distlib/scripts.py index b1fc705..60309b1 100644 --- a/distlib/scripts.py +++ b/distlib/scripts.py @@ -47,6 +47,7 @@ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) sys.exit(%(func)s()) ''' +SCRIPT_TEMPLATE_RESERVED_NAMES = ('re', 'sys', '__name__') # Pre-fetch the contents of all executable wrapper stubs. # This is to address https://github.com/pypa/pip/issues/12666. @@ -94,6 +95,7 @@ class ScriptMaker(object): specifications. """ script_template = SCRIPT_TEMPLATE + script_template_reserved_names = SCRIPT_TEMPLATE_RESERVED_NAMES executable = None # for shebangs @@ -247,8 +249,15 @@ def _get_shebang(self, encoding, post_interp=b'', options=None): return shebang def _get_script_text(self, entry): + import_name = entry.suffix.split('.')[0] + if import_name in self.script_template_reserved_names: + import_as = import_name + ' as _' + import_name + func = '_' + entry.suffix + else: + import_as = None + func = entry.suffix return self.script_template % dict( - module=entry.prefix, import_name=entry.suffix.split('.')[0], func=entry.suffix) + module=entry.prefix, import_name=import_as if import_as else import_name, func=func) manifest = _DEFAULT_MANIFEST diff --git a/tests/test_scripts.py b/tests/test_scripts.py index a93a08a..3b39320 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -449,6 +449,18 @@ def get_script_filenames(self, name): expected = set([e.replace('.py', '.exe') for e in expected]) self.assertEqual(expected, set(files)) + def test_reserved_names(self): + self.maker.clobber = True + for reserved_name in ('sys', 're', '__name__'): + spec = 'foo = foo:' + reserved_name + files = self.maker.make(spec) + self.assertEqual(len(files), 2) + for fn in files: + with open(fn, 'r') as f: + text = f.read() + self.assertIn('from foo import ' + reserved_name + ' as _' + reserved_name, text) + self.assertIn('sys.exit(_' + reserved_name + '())', text) + if __name__ == '__main__': # pragma: no cover unittest.main()