cpython: 7b47c98f24da (original) (raw)
Mercurial > cpython
changeset 103888:7b47c98f24da 3.6
Issue #28137: Renames Windows path file to ._pth Issue #28138: Windows ._pth file should allow import site [#28137]
Steve Dower steve.dower@microsoft.com | |
---|---|
date | Sat, 17 Sep 2016 12:54:06 -0700 |
parents | b0350f351752 |
children | 5fab409f97de 2156aa4050c7 |
files | Doc/using/windows.rst Doc/whatsnew/3.6.rst Misc/NEWS PC/getpathp.c Tools/msi/make_zip.py |
diffstat | 5 files changed, 119 insertions(+), 52 deletions(-)[+] [-] Doc/using/windows.rst 32 Doc/whatsnew/3.6.rst 2 Misc/NEWS 9 PC/getpathp.c 113 Tools/msi/make_zip.py 15 |
line wrap: on
line diff
--- a/Doc/using/windows.rst
+++ b/Doc/using/windows.rst
@@ -720,15 +720,24 @@ installation directory. So, if you had
:file:C:\\Python\\Lib\\
and third-party modules should be stored in
:file:C:\\Python\\Lib\\site-packages\\
.
-To completely override :data:sys.path
, create a text file named 'sys.path'
-containing a list of paths alongside the Python executable. This will ignore all
-registry settings and environment variables, enable isolated mode, disable
-importing :mod:site
, and fill :data:sys.path
with exactly the paths listed
-in the file. Paths may be absolute or relative to the directory containing the
-file.
+To completely override :data:sys.path
, create a ._pth
file with the same
+name as the DLL (python36._pth
) or the executable (python._pth
) and
+specify one line for each path to add to :data:sys.path
. The file based on the
+DLL name overrides the one based on the executable, which allows paths to be
+restricted for any program loading the runtime if desired.
-When the 'sys.path'
file is missing, this is how :data:sys.path
is
-populated on Windows:
+When the file exists, all registry and environment variables are ignored,
+isolated mode is enabled, and :mod:site
is not imported unless one line in the
+file specifies import site
. Blank paths and lines starting with #
are
+ignored. Each path may be absolute or relative to the location of the file.
+Import statements other than to site
are not permitted, and arbitrary code
+cannot be specified.
+
+Note that .pth
files (without leading underscore) will be processed normally
+by the :mod:site
module.
+
+When no ._pth
file is found, this is how :data:sys.path
is populated on
+Windows:
- An empty entry is added at the start, which corresponds to the current
directory.
@@ -782,9 +791,10 @@ The end result of all this is:
For those who want to bundle Python into their application or distribution, the
following advice will prevent conflicts with other installations:
-* Include a
sys.path
file alongside your executable containing the
- directories to include. This will ignore user site-packages and other paths
- listed in the registry or in environment variables.
+* Include a
._pth
file alongside your executable containing the
- directories to include. This will ignore paths listed in the registry and
- environment variables, and also ignore :mod:
site
unlessimport site
is - listed.
- If you are loading :file:
python3.dll
or :file:python36.dll
in your own executable, explicitly call :c:func:Py_SetPath
or (at least)
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -108,7 +108,7 @@ Windows improvements:
which means that when the 260 character path limit may no longer apply.
See :ref:removing the MAX_PATH limitation <max-path>
for details.
-* A sys.path
file can be added to force isolated mode and fully specify
+* A ._pth
file can be added to force isolated mode and fully specify
all search paths to avoid registry and environment lookup. See
:ref:the documentation <finding_modules>
for more information.
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ What's New in Python 3.6.0 beta 2 Core and Builtins ----------------- +- Issue #28192: Don't import readline in isolated mode. +
- Upgrade internal unicode databases to Unicode version 9.0.0.
- Issue #28131: Fix a regression in zipimport's compile_source(). zipimport @@ -64,6 +66,13 @@ Library
- Issue #27759: Fix selectors incorrectly retain invalid file descriptors. Patch by Mark Williams. +Windows +------- + +- Issue #28137: Renames Windows path file to ._pth + +- Issue #28138: Windows ._pth file should allow import site + Build -----
--- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -6,8 +6,9 @@ PATH RULES FOR WINDOWS: This describes how sys.path is formed on Windows. It describes the functionality, not the implementation (ie, the order in which these
- are actually fetched is different). The presence of a sys.path file
- alongside the program overrides these rules - see below.
- are actually fetched is different). The presence of a python._pth or
- pythonXY._pth file alongside the program overrides these rules - see
- below.
- If a sys.path file exists adjacent to python.exe, it must contain a
- list of paths to add to sys.path, one per line (like a .pth file but without
- the ability to execute arbitrary code). Each path is relative to the
- directory containing the file. No other paths are added to the search path,
- and the registry finder is not enabled.
- If a '._pth' file exists adjacent to the executable with the same base name
- (e.g. python._pth adjacent to python.exe) or adjacent to the shared library
- (e.g. python36._pth adjacent to python36.dll), it is used in preference to
- the above process. The shared library file takes precedence over the
- executable. The path file must contain a list of paths to add to sys.path,
- one per line. Each path is relative to the directory containing the file.
- Blank lines and comments beginning with '#' are permitted. +
- In the presence of this ._pth file, no other paths are added to the search
- path, the registry finder is not enabled, site.py is not imported and
- isolated mode is enabled. The site package can be enabled by including a
- line reading "import site"; no other imports are recognized. Any invalid
- entry (other than directories that do not exist) will result in immediate
- termination of the program. +
The end result of all this is:
- When running python.exe, or any other .exe in the main Python directory @@ -61,8 +72,9 @@
- An embedding application can use Py_SetPath() to override all of these automatic path computations.
- either a 'EXENAME._pth' or 'DLLNAME._pth' file, optionally including
- "import site" to enable the site module.
---------------------------------------------------------------- */ @@ -135,6 +147,33 @@ reduce(wchar_t *dir) dir[i] = '\0'; } +static int +change_ext(wchar_t *dest, const wchar_t *src, const wchar_t *ext) +{
- size_t src_len = wcsnlen_s(src, MAXPATHLEN+1);
- size_t i = src_len;
- if (i >= MAXPATHLEN+1)
Py_FatalError("buffer overflow in getpathp.c's reduce()");[](#l4.64)
- if (wcsncpy_s(dest, MAXPATHLEN+1, src, i) ||
wcscat_s(dest, MAXPATHLEN+1, ext)) {[](#l4.78)
dest[0] = '\0';[](#l4.79)
return -1;[](#l4.80)
- }
+} static int exists(wchar_t *filename) @@ -499,12 +538,17 @@ find_env_config_value(FILE * env_file, c } static int -read_sys_path_file(const wchar_t *path, const wchar_t *prefix) +read_pth_file(const wchar_t *path, wchar_t *prefix, int *isolated, int *nosite) { FILE *sp_file = _Py_wfopen(path, L"r"); if (sp_file == NULL) return -1;
+ size_t bufsiz = MAXPATHLEN; size_t prefixlen = wcslen(prefix); @@ -516,16 +560,25 @@ read_sys_path_file(const wchar_t *path, char *p = fgets(line, MAXPATHLEN + 1, sp_file); if (!p) break;
if (*p == '\0' || *p == '#')[](#l4.111)
continue;[](#l4.112)
while (*++p) {[](#l4.113)
if (*p == '\r' || *p == '\n') {[](#l4.114)
*p = '\0';[](#l4.115)
break;[](#l4.116)
}[](#l4.117)
}[](#l4.118)
DWORD n = strlen(line);[](#l4.120)
if (n == 0 || p[n - 1] != '\n')[](#l4.121)
break;[](#l4.122)
if (n > 2 && p[n - 1] == '\r')[](#l4.123)
--n;[](#l4.124)
if (strcmp(line, "import site") == 0) {[](#l4.125)
*nosite = 0;[](#l4.126)
continue;[](#l4.127)
} else if (strncmp(line, "import ", 7) == 0) {[](#l4.128)
Py_FatalError("only 'import site' is supported in ._pth file");[](#l4.129)
}[](#l4.130)
DWORD wn = MultiByteToWideChar(CP_UTF8, 0, line, n - 1, NULL, 0);[](#l4.132)
DWORD wn = MultiByteToWideChar(CP_UTF8, 0, line, -1, NULL, 0);[](#l4.133) wchar_t *wline = (wchar_t*)PyMem_RawMalloc((wn + 1) * sizeof(wchar_t));[](#l4.134)
wn = MultiByteToWideChar(CP_UTF8, 0, line, n - 1, wline, wn);[](#l4.135)
wn = MultiByteToWideChar(CP_UTF8, 0, line, -1, wline, wn + 1);[](#l4.136) wline[wn] = '\0';[](#l4.137)
while (wn + prefixlen + 4 > bufsiz) { @@ -539,8 +592,8 @@ read_sys_path_file(const wchar_t *path, if (buf[0]) wcscat_s(buf, bufsiz, L";"); + wchar_t *b = &buf[wcslen(buf)];
[](#l4.146) wcscat_s(buf, bufsiz, prefix);[](#l4.147) join(b, wline);[](#l4.148)
@@ -586,13 +639,12 @@ calculate_path(void) { wchar_t spbuffer[MAXPATHLEN+1];
wcscpy_s(spbuffer, MAXPATHLEN+1, argv0_path);[](#l4.154)
join(spbuffer, L"sys.path");[](#l4.155)
if (exists(spbuffer) && read_sys_path_file(spbuffer, argv0_path) == 0) {[](#l4.156)
wcscpy_s(prefix, MAXPATHLEN + 1, argv0_path);[](#l4.157)
Py_IsolatedFlag = 1;[](#l4.158)
Py_NoSiteFlag = 1;[](#l4.159)
return;[](#l4.160)
if ((dllpath[0] && !change_ext(spbuffer, dllpath, L"._pth") && exists(spbuffer)) ||[](#l4.161)
(progpath[0] && !change_ext(spbuffer, progpath, L"._pth") && exists(spbuffer))) {[](#l4.162)
if (!read_pth_file(spbuffer, prefix, &Py_IsolatedFlag, &Py_NoSiteFlag)) {[](#l4.164)
return;[](#l4.165)
} @@ -631,16 +683,7 @@ calculate_path(void) } /* Calculate zip archive path from DLL or exe path */}[](#l4.166) }[](#l4.167)
- if (wcscpy_s(zip_path, MAXPATHLEN + 1, dllpath[0] ? dllpath : progpath)) {
/* exceeded buffer length - ignore zip_path */[](#l4.175)
zip_path[0] = '\0';[](#l4.176)
- } else {
wchar_t *dot = wcsrchr(zip_path, '.');[](#l4.178)
if (!dot || wcscpy_s(dot, MAXPATHLEN + 1 - (dot - zip_path), L".zip")) {[](#l4.179)
/* exceeded buffer length - ignore zip_path */[](#l4.180)
zip_path[0] = L'\0';[](#l4.181)
}[](#l4.182)
- }
if (pythonhome == NULL || *pythonhome == '\0') { if (zip_path[0] && exists(zip_path)) {
--- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -91,11 +91,13 @@ def include_in_tools(p): return p.suffix.lower() in {'.py', '.pyw', '.txt'} +BASE_NAME = 'python{0.major}{0.minor}'.format(sys.version_info) + FULL_LAYOUT = [ ('/', 'PCBuild/$arch', 'python.exe', is_not_debug), ('/', 'PCBuild/$arch', 'pythonw.exe', is_not_debug),
- ('/', 'PCBuild/$arch', 'python{0.major}.dll'.format(sys.version_info), is_not_debug),
- ('/', 'PCBuild/$arch', 'python{0.major}{0.minor}.dll'.format(sys.version_info), is_not_debug),
- ('/', 'PCBuild/$arch', 'python{}.dll'.format(sys.version_info.major), is_not_debug),
- ('/', 'PCBuild/$arch', '{}.dll'.format(BASE_NAME), is_not_debug), ('DLLs/', 'PCBuild/$arch', '.pyd', is_not_debug), ('DLLs/', 'PCBuild/$arch', '.dll', is_not_debug_or_python), ('include/', 'include', '.h', None), @@ -109,7 +111,7 @@ EMBED_LAYOUT = [ ('/', 'PCBuild/$arch', 'python.exe', is_not_debug), ('/', 'PCBuild/$arch', '.pyd', is_not_debug), ('/', 'PCBuild/$arch', '.dll', is_not_debug),
] if os.getenv('DOC_FILENAME'): @@ -209,9 +211,12 @@ def main(): print('Copied {} files'.format(copied)) if ns.embed:
with open(str(temp / 'sys.path'), 'w') as f:[](#l5.32)
print('python{0.major}{0.minor}.zip'.format(sys.version_info), file=f)[](#l5.33)
with open(str(temp / (BASE_NAME + '._pth')), 'w') as f:[](#l5.34)
print(BASE_NAME + '.zip', file=f)[](#l5.35) print('.', file=f)[](#l5.36)
print('', file=f)[](#l5.37)
print('# Uncomment to run site.main() automatically', file=f)[](#l5.38)
print('#import site', file=f)[](#l5.39)
if out: total = copy_to_layout(out, rglob(temp, '**/*', None))