comparing with /home/esnow/projects/.cpython searching for changes changeset: 77148:492f1efa2a86 tag: tip user: Eric Snow date: Sat May 26 12:41:03 2012 -0600 summary: [issue 13475] add -p/-P command-line options diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -24,7 +24,7 @@ When invoking Python, you may specify any of these options:: - python [-bBdEhiOqsSuvVWx?] [-c command | -m module-name | script | - ] [args] + python [-bBdEhiOpPqsSuvVWx?] [-c command | -m module-name | script | - ] [args] The most common use case is, of course, a simple invocation of a script:: @@ -220,6 +220,26 @@ Discard docstrings in addition to the :option:`-O` optimizations. +.. cmdoption:: -p dir + + Explicitly initialize ``sys.path[0]`` to ``dir``. If used multiple times, + all but the last one are ignored. The :option:`-P` option will negate the + usage of any preceding ``-p``. + + See the entry on :data:`~sys.path` for more information on the normal + implicit behavior the interpreter regarding ``sys.path[0]``. + + .. versionadded:: 3.3 + + +.. cmdoption:: -P + + Disable initialization of ``sys.path[0]``. The :option:`-p` option will + negate the usage of any preceding ``-P``. + + .. versionadded:: 3.3 + + .. cmdoption:: -q Don't display the copyright and version messages even in interactive mode. diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -61,6 +61,39 @@ opts = eval(out.splitlines()[0]) self.assertEqual(opts, {'a': True, 'b': 'c,d=e'}) + def test_path(self): + path = tempfile.gettempdir() + + rc, out, err = assert_python_ok('-c', 'import sys; print(sys.path)') + path0 = eval(out.splitlines()[0])[0] + self.assertEqual(path0, '') + + rc, out, err = assert_python_ok('-p', path, + '-c', 'import sys; print(sys.path)') + path0 = eval(out.splitlines()[0])[0] + self.assertEqual(path0, path) + + rc, out, err = assert_python_ok('-P', + '-c', 'import sys; print(sys.path)') + path0 = eval(out.splitlines()[0])[0] + self.assertNotEqual(path0, '') + + rc, out, err = assert_python_ok('-p', path, '-P', + '-c', 'import sys; print(sys.path)') + path0 = eval(out.splitlines()[0])[0] + self.assertNotEqual(path0, path) + self.assertNotEqual(path0, '') + + rc, out, err = assert_python_ok('-P', '-p', path, + '-c', 'import sys; print(sys.path)') + path0 = eval(out.splitlines()[0])[0] + self.assertEqual(path0, path) + + rc, out, err = assert_python_ok('-p', '/tmp', '-p', path, + '-c', 'import sys; print(sys.path)') + path0 = eval(out.splitlines()[0])[0] + self.assertEqual(path0, path) + def test_run_module(self): # Test expected operation of the '-m' switch # Switch needs an argument diff --git a/Modules/main.c b/Modules/main.c --- a/Modules/main.c +++ b/Modules/main.c @@ -47,7 +47,7 @@ static int orig_argc; /* command line options */ -#define BASE_OPTS L"bBc:dEhiJm:OqRsStuvVW:xX:?" +#define BASE_OPTS L"bBc:dEhiJm:Op:PqRsStuvVW:xX:?" #define PROGRAM_OPTS BASE_OPTS @@ -72,11 +72,13 @@ -m mod : run library module as a script (terminates option list)\n\ -O : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\ -OO : remove doc-strings in addition to the -O optimizations\n\ +-p dir : initialize sys.path[0] to dir\n\ +-P : disable sys.path[0] initialization\n\ -q : don't print version and copyright messages on interactive startup\n\ +"; +static char *usage_3 = "\ -s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\ -S : don't imply 'import site' on initialization\n\ -"; -static char *usage_3 = "\ -u : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x\n\ see man page for details on internal buffering relating to '-u'\n\ -v : verbose (trace import statements); also PYTHONVERBOSE=x\n\ @@ -84,10 +86,10 @@ -V : print the Python version number and exit (also --version)\n\ -W arg : warning control; arg is action:message:category:module:lineno\n\ also PYTHONWARNINGS=arg\n\ +"; +static char *usage_4 = "\ -x : skip first line of source, allowing use of non-Unix forms of #!cmd\n\ -X opt : set implementation-specific option\n\ -"; -static char *usage_4 = "\ file : program read from script file\n\ - : program read from stdin (default; interactive mode if a tty)\n\ arg ...: arguments passed to program in sys.argv[1:]\n\n\ @@ -319,6 +321,7 @@ wchar_t *command = NULL; wchar_t *filename = NULL; wchar_t *module = NULL; + wchar_t *path0 = NULL; FILE *fp = stdin; char *p; #ifdef MS_WINDOWS @@ -456,6 +459,14 @@ Py_QuietFlag++; break; + case 'p': + path0 = _PyOS_optarg; + break; + + case 'P': + path0 = -1; + break; + case 'R': /* Ignored */ break; @@ -644,7 +655,15 @@ argv[_PyOS_optind] = L"-m"; } - PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind); + PySys_SetArgvEx(argc-_PyOS_optind, argv+_PyOS_optind, (path0 == NULL)); + + if (path0 != NULL && path0 != -1) { + PyObject *newpath0 = PyUnicode_FromWideChar(path0, wcslen(path0)); + + PyList_Insert(PySys_GetObject("path"), 0, newpath0); + Py_DECREF(newpath0); + } + if ((Py_InspectFlag || (command == NULL && filename == NULL && module == NULL)) && isatty(fileno(stdin))) {