[Python-checkins] r84140 - in python/branches/py3k: Doc/using/cmdline.rst Lib/test/script_helper.py Lib/test/support.py Lib/test/test_cmd_line.py Lib/test/test_cmd_line_script.py Misc/NEWS Modules/main.c Python/sysmodule.c

nick.coghlan python-checkins at python.org
Tue Aug 17 15:06:11 CEST 2010


Author: nick.coghlan
Date: Tue Aug 17 15:06:11 2010
New Revision: 84140

Log:
Issue #8202: Set sys.argv[0] to -m rather than -c while searching for the module to execute. Also updates all the cmd_line_script tests to validate the setting of sys.path[0] and the current working directory

Modified:
   python/branches/py3k/Doc/using/cmdline.rst
   python/branches/py3k/Lib/test/script_helper.py
   python/branches/py3k/Lib/test/support.py
   python/branches/py3k/Lib/test/test_cmd_line.py
   python/branches/py3k/Lib/test/test_cmd_line_script.py
   python/branches/py3k/Misc/NEWS
   python/branches/py3k/Modules/main.c
   python/branches/py3k/Python/sysmodule.c

Modified: python/branches/py3k/Doc/using/cmdline.rst
==============================================================================
--- python/branches/py3k/Doc/using/cmdline.rst	(original)
+++ python/branches/py3k/Doc/using/cmdline.rst	Tue Aug 17 15:06:11 2010
@@ -95,8 +95,9 @@
       file is not available.
 
    If this option is given, the first element of :data:`sys.argv` will be the
-   full path to the module file. As with the :option:`-c` option, the current
-   directory will be added to the start of :data:`sys.path`.
+   full path to the module file (while the module file is being located, the
+   first element will be set to ``"-m"``). As with the :option:`-c` option,
+   the current directory will be added to the start of :data:`sys.path`.
 
    Many standard library modules contain code that is invoked on their execution
    as a script.  An example is the :mod:`timeit` module::

Modified: python/branches/py3k/Lib/test/script_helper.py
==============================================================================
--- python/branches/py3k/Lib/test/script_helper.py	(original)
+++ python/branches/py3k/Lib/test/script_helper.py	Tue Aug 17 15:06:11 2010
@@ -86,9 +86,9 @@
     #    zip_file.close()
     return zip_name, os.path.join(zip_name, name_in_zip)
 
-def make_pkg(pkg_dir):
+def make_pkg(pkg_dir, init_source=''):
     os.mkdir(pkg_dir)
-    make_script(pkg_dir, '__init__', '')
+    make_script(pkg_dir, '__init__', init_source)
 
 def make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename,
                  source, depth=1, compiled=False):

Modified: python/branches/py3k/Lib/test/support.py
==============================================================================
--- python/branches/py3k/Lib/test/support.py	(original)
+++ python/branches/py3k/Lib/test/support.py	Tue Aug 17 15:06:11 2010
@@ -419,21 +419,32 @@
 SAVEDCWD = os.getcwd()
 
 @contextlib.contextmanager
-def temp_cwd(name='tempcwd', quiet=False):
+def temp_cwd(name='tempcwd', quiet=False, path=None):
     """
-    Context manager that creates a temporary directory and set it as CWD.
+    Context manager that temporarily changes the CWD.
 
-    The new CWD is created in the current directory and it's named *name*.
-    If *quiet* is False (default) and it's not possible to create or change
-    the CWD, an error is raised.  If it's True, only a warning is raised
-    and the original CWD is used.
+    An existing path may be provided as *path*, in which case this
+    function makes no changes to the file system.
+
+    Otherwise, the new CWD is created in the current directory and it's
+    named *name*. If *quiet* is False (default) and it's not possible to
+    create or change the CWD, an error is raised.  If it's True, only a
+    warning is raised and the original CWD is used.
     """
     saved_dir = os.getcwd()
     is_temporary = False
+    if path is None:
+        path = name
+        try:
+            os.mkdir(name)
+            is_temporary = True
+        except OSError:
+            if not quiet:
+                raise
+            warnings.warn('tests may fail, unable to create temp CWD ' + name,
+                          RuntimeWarning, stacklevel=3)
     try:
-        os.mkdir(name)
-        os.chdir(name)
-        is_temporary = True
+        os.chdir(path)
     except OSError:
         if not quiet:
             raise

Modified: python/branches/py3k/Lib/test/test_cmd_line.py
==============================================================================
--- python/branches/py3k/Lib/test/test_cmd_line.py	(original)
+++ python/branches/py3k/Lib/test/test_cmd_line.py	Tue Aug 17 15:06:11 2010
@@ -1,5 +1,5 @@
 # Tests invocation of the interpreter with various command line arguments
-# All tests are executed with environment variables ignored
+# Most tests are executed with environment variables ignored
 # See test_cmd_line_script.py for testing of script execution
 
 import test.support, unittest
@@ -7,10 +7,6 @@
 import sys
 from test.script_helper import spawn_python, kill_python, python_exit_code
 
-# XXX (ncoghlan): there are assorted gratuitous inconsistencies between the
-# support code in the Py3k version and the 2.x version that unnecessarily
-# complicate test suite merges. See issue 7331
-
 # spawn_python normally enforces use of -E to avoid environmental effects
 # but one test checks PYTHONPATH behaviour explicitly
 # XXX (ncoghlan): Give script_helper.spawn_python an option to switch

Modified: python/branches/py3k/Lib/test/test_cmd_line_script.py
==============================================================================
--- python/branches/py3k/Lib/test/test_cmd_line_script.py	(original)
+++ python/branches/py3k/Lib/test/test_cmd_line_script.py	Tue Aug 17 15:06:11 2010
@@ -5,12 +5,12 @@
 import os.path
 import py_compile
 
-import test.support
+from test import support
 from test.script_helper import (
     make_pkg, make_script, make_zip_pkg, make_zip_script, run_python,
     temp_dir)
 
-verbose = test.support.verbose
+verbose = support.verbose
 
 test_source = """\
 # Script may be run with optimisation enabled, so don't rely on assert
@@ -36,6 +36,10 @@
 import sys
 assertIdentical(globals(), sys.modules[__name__].__dict__)
 print('sys.argv[0]==%r' % sys.argv[0])
+print('sys.path[0]==%r' % sys.path[0])
+# Check the working directory
+import os
+print('cwd==%r' % os.getcwd())
 """
 
 def _make_test_script(script_dir, script_basename, source=test_source):
@@ -65,32 +69,44 @@
     return make_script(script_dir, script_basename, source)
 
 class CmdLineTest(unittest.TestCase):
-    def _check_script(self, script_name, expected_file,
-                            expected_argv0, expected_package,
-                            *cmd_line_switches):
-        run_args = cmd_line_switches + (script_name,)
-        exit_code, data = run_python(*run_args)
-        if verbose:
+    def _check_output(self, script_name, exit_code, data,
+                             expected_file, expected_argv0,
+                             expected_path0, expected_package):
+        if verbose > 1:
             print("Output from test script %r:" % script_name)
             print(data)
         self.assertEqual(exit_code, 0)
         printed_file = '__file__==%r' % expected_file
-        printed_argv0 = 'sys.argv[0]==%r' % expected_argv0
         printed_package = '__package__==%r' % expected_package
-        if verbose:
+        printed_argv0 = 'sys.argv[0]==%r' % expected_argv0
+        printed_path0 = 'sys.path[0]==%r' % expected_path0
+        printed_cwd = 'cwd==%r' % os.getcwd()
+        if verbose > 1:
             print('Expected output:')
             print(printed_file)
             print(printed_package)
             print(printed_argv0)
+            print(printed_cwd)
         self.assertIn(printed_file.encode('utf-8'), data)
         self.assertIn(printed_package.encode('utf-8'), data)
         self.assertIn(printed_argv0.encode('utf-8'), data)
+        self.assertIn(printed_path0.encode('utf-8'), data)
+        self.assertIn(printed_cwd.encode('utf-8'), data)
+
+    def _check_script(self, script_name, expected_file,
+                            expected_argv0, expected_path0,
+                            expected_package,
+                            *cmd_line_switches):
+        run_args = cmd_line_switches + (script_name,)
+        exit_code, data = run_python(*run_args)
+        self._check_output(script_name, exit_code, data, expected_file,
+                           expected_argv0, expected_path0, expected_package)
 
     def _check_import_error(self, script_name, expected_msg,
                             *cmd_line_switches):
         run_args = cmd_line_switches + (script_name,)
         exit_code, data = run_python(*run_args)
-        if verbose:
+        if verbose > 1:
             print('Output from test script %r:' % script_name)
             print(data)
             print('Expected output: %r' % expected_msg)
@@ -99,28 +115,32 @@
     def test_basic_script(self):
         with temp_dir() as script_dir:
             script_name = _make_test_script(script_dir, 'script')
-            self._check_script(script_name, script_name, script_name, None)
+            self._check_script(script_name, script_name, script_name,
+                               script_dir, None)
 
     def test_script_compiled(self):
         with temp_dir() as script_dir:
             script_name = _make_test_script(script_dir, 'script')
-            compiled_name = py_compile.compile(script_name, doraise=True)
+            py_compile.compile(script_name, doraise=True)
             os.remove(script_name)
-            self._check_script(compiled_name, compiled_name,
-                               compiled_name, None)
+            pyc_file = support.make_legacy_pyc(script_name)
+            self._check_script(pyc_file, pyc_file,
+                               pyc_file, script_dir, None)
 
     def test_directory(self):
         with temp_dir() as script_dir:
             script_name = _make_test_script(script_dir, '__main__')
-            self._check_script(script_dir, script_name, script_dir, '')
+            self._check_script(script_dir, script_name, script_dir,
+                               script_dir, '')
 
     def test_directory_compiled(self):
         with temp_dir() as script_dir:
             script_name = _make_test_script(script_dir, '__main__')
-            compiled_name = py_compile.compile(script_name, doraise=True)
+            py_compile.compile(script_name, doraise=True)
             os.remove(script_name)
-            pyc_file = test.support.make_legacy_pyc(script_name)
-            self._check_script(script_dir, pyc_file, script_dir, '')
+            pyc_file = support.make_legacy_pyc(script_name)
+            self._check_script(script_dir, pyc_file, script_dir,
+                               script_dir, '')
 
     def test_directory_error(self):
         with temp_dir() as script_dir:
@@ -131,14 +151,14 @@
         with temp_dir() as script_dir:
             script_name = _make_test_script(script_dir, '__main__')
             zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name)
-            self._check_script(zip_name, run_name, zip_name, '')
+            self._check_script(zip_name, run_name, zip_name, zip_name, '')
 
     def test_zipfile_compiled(self):
         with temp_dir() as script_dir:
             script_name = _make_test_script(script_dir, '__main__')
             compiled_name = py_compile.compile(script_name, doraise=True)
             zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name)
-            self._check_script(zip_name, run_name, zip_name, '')
+            self._check_script(zip_name, run_name, zip_name, zip_name, '')
 
     def test_zipfile_error(self):
         with temp_dir() as script_dir:
@@ -153,19 +173,19 @@
             make_pkg(pkg_dir)
             script_name = _make_test_script(pkg_dir, 'script')
             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script')
-            self._check_script(launch_name, script_name, script_name, 'test_pkg')
+            self._check_script(launch_name, script_name, script_name, script_dir, 'test_pkg')
 
     def test_module_in_package_in_zipfile(self):
         with temp_dir() as script_dir:
             zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script')
             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script', zip_name)
-            self._check_script(launch_name, run_name, run_name, 'test_pkg')
+            self._check_script(launch_name, run_name, run_name, zip_name, 'test_pkg')
 
     def test_module_in_subpackage_in_zipfile(self):
         with temp_dir() as script_dir:
             zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script', depth=2)
             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.test_pkg.script', zip_name)
-            self._check_script(launch_name, run_name, run_name, 'test_pkg.test_pkg')
+            self._check_script(launch_name, run_name, run_name, zip_name, 'test_pkg.test_pkg')
 
     def test_package(self):
         with temp_dir() as script_dir:
@@ -174,7 +194,7 @@
             script_name = _make_test_script(pkg_dir, '__main__')
             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg')
             self._check_script(launch_name, script_name,
-                               script_name, 'test_pkg')
+                               script_name, script_dir, 'test_pkg')
 
     def test_package_compiled(self):
         with temp_dir() as script_dir:
@@ -183,10 +203,10 @@
             script_name = _make_test_script(pkg_dir, '__main__')
             compiled_name = py_compile.compile(script_name, doraise=True)
             os.remove(script_name)
-            pyc_file = test.support.make_legacy_pyc(script_name)
+            pyc_file = support.make_legacy_pyc(script_name)
             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg')
             self._check_script(launch_name, pyc_file,
-                               pyc_file, 'test_pkg')
+                               pyc_file, script_dir, 'test_pkg')
 
     def test_package_error(self):
         with temp_dir() as script_dir:
@@ -209,10 +229,53 @@
             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg')
             self._check_import_error(launch_name, msg)
 
+    def test_issue8202(self):
+        # Make sure package __init__ modules see "-m" in sys.argv0 while
+        # searching for the module to execute
+        with temp_dir() as script_dir:
+            with support.temp_cwd(path=script_dir):
+                pkg_dir = os.path.join(script_dir, 'test_pkg')
+                make_pkg(pkg_dir, "import sys; print('init_argv0==%r' % sys.argv[0])")
+                script_name = _make_test_script(pkg_dir, 'script')
+                exit_code, data = run_python('-m', 'test_pkg.script')
+                if verbose > 1:
+                    print(data)
+                self.assertEqual(exit_code, 0)
+                expected = "init_argv0==%r" % '-m'
+                self.assertIn(expected.encode('utf-8'), data)
+                self._check_output(script_name, exit_code, data,
+                                   script_name, script_name, '', 'test_pkg')
+
+    def test_issue8202_dash_c_file_ignored(self):
+        # Make sure a "-c" file in the current directory
+        # does not alter the value of sys.path[0]
+        with temp_dir() as script_dir:
+            with support.temp_cwd(path=script_dir):
+                with open("-c", "w") as f:
+                    f.write("data")
+                    exit_code, data = run_python('-c',
+                        'import sys; print("sys.path[0]==%r" % sys.path[0])')
+                    if verbose > 1:
+                        print(data)
+                    self.assertEqual(exit_code, 0)
+                    expected = "sys.path[0]==%r" % ''
+                    self.assertIn(expected.encode('utf-8'), data)
+
+    def test_issue8202_dash_m_file_ignored(self):
+        # Make sure a "-m" file in the current directory
+        # does not alter the value of sys.path[0]
+        with temp_dir() as script_dir:
+            script_name = _make_test_script(script_dir, 'other')
+            with support.temp_cwd(path=script_dir):
+                with open("-m", "w") as f:
+                    f.write("data")
+                    exit_code, data = run_python('-m', 'other')
+                    self._check_output(script_name, exit_code, data,
+                                      script_name, script_name, '', '')
 
 def test_main():
-    test.support.run_unittest(CmdLineTest)
-    test.support.reap_children()
+    support.run_unittest(CmdLineTest)
+    support.reap_children()
 
 if __name__ == '__main__':
     test_main()

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Tue Aug 17 15:06:11 2010
@@ -12,6 +12,9 @@
 Core and Builtins
 -----------------
 
+- Issue #8202: sys.argv[0] is now set to '-m' instead of '-c' when searching
+  for the module file to be executed with the -m command  line option.
+
 - Issue #9599: Create PySys_FormatStdout() and PySys_FormatStderr() functions
   to write a message formatted by PyUnicode_FromFormatV() to sys.stdout and
   sys.stderr.

Modified: python/branches/py3k/Modules/main.c
==============================================================================
--- python/branches/py3k/Modules/main.c	(original)
+++ python/branches/py3k/Modules/main.c	Tue Aug 17 15:06:11 2010
@@ -604,10 +604,9 @@
     }
 
     if (module != NULL) {
-        /* Backup _PyOS_optind and force sys.argv[0] = '-c'
-           so that PySys_SetArgv correctly sets sys.path[0] to ''*/
+        /* Backup _PyOS_optind and force sys.argv[0] = '-m'*/
         _PyOS_optind--;
-        argv[_PyOS_optind] = L"-c";
+        argv[_PyOS_optind] = L"-m";
     }
 
     PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);

Modified: python/branches/py3k/Python/sysmodule.c
==============================================================================
--- python/branches/py3k/Python/sysmodule.c	(original)
+++ python/branches/py3k/Python/sysmodule.c	Tue Aug 17 15:06:11 2010
@@ -1723,6 +1723,10 @@
 }
 #endif
 
+#define _HAVE_SCRIPT_ARGUMENT(argc, argv) \
+  (argc > 0 && argv0 != NULL && \
+   wcscmp(argv0, L"-c") != 0 && wcscmp(argv0, L"-m") != 0)
+  
 void
 PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
 {
@@ -1747,7 +1751,7 @@
         wchar_t link[MAXPATHLEN+1];
         wchar_t argv0copy[2*MAXPATHLEN+1];
         int nr = 0;
-        if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0)
+        if (_HAVE_SCRIPT_ARGUMENT(argc, argv))
             nr = _Py_wreadlink(argv0, link, MAXPATHLEN);
         if (nr > 0) {
             /* It's a symlink */
@@ -1772,7 +1776,7 @@
         }
 #endif /* HAVE_READLINK */
 #if SEP == '\\' /* Special case for MS filename syntax */
-        if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) {
+        if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) {
             wchar_t *q;
 #if defined(MS_WINDOWS) && !defined(MS_WINCE)
             /* This code here replaces the first element in argv with the full
@@ -1798,7 +1802,7 @@
             }
         }
 #else /* All other filename syntaxes */
-        if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) {
+        if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) {
 #if defined(HAVE_REALPATH)
             if (_wrealpath(argv0, fullpath)) {
                 argv0 = fullpath;


More information about the Python-checkins mailing list