Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2@file
3@brief Patch the distribution to make it portable
4"""
5from __future__ import print_function
7import os
8import re
11class ShebangException(Exception):
12 """
13 exception raised when the shebang is not correct
14 """
15 pass
18def win_patch_paths(folder, path_to_python="", fLOG=print):
19 """
20 Paths are absolute when they are installed in all scripts *.exe*,
21 we replaced them either by an empty string (``path_to_python == ""``)
22 or the current folder.
24 @param folder folder where to find the executable
25 @param path_to_python new python path (replace by)
26 @param fLOG logging function
27 @return list of tuple ('exe or py', 'modified file')
29 See `Create a portable Python with Pip on Windows <http://www.clemens-sielaff.com/create-a-portable-python-with-pip-on-windows/>`_
30 The first three parameters can be environment variables.
31 They will be replaced by their values.
32 """
33 if folder in os.environ:
34 folder = os.environ[folder]
35 if path_to_python not in (None, "") and path_to_python in os.environ:
36 path_to_python = os.environ[path_to_python]
37 if path_to_python is None:
38 exe = os.path.join(folder, "python.exe")
39 if os.path.exists(exe):
40 path_to_python = os.path.absapth(folder)
41 else:
42 exe = os.path.join(folder, "..", "python.exe")
43 path_to_python = os.path.normpath(
44 os.path.abspath(os.path.join(folder, "..")))
46 files = os.listdir(folder)
48 if len(path_to_python) > 0 and not path_to_python.endswith("\\"):
49 path_to_python += "\\"
51 pattern = "([#][!]((([A-Za-z][:])?[/\\\\]?[-a-zA-Z0-9_.]+[/\\\\])*?)(pythonw?[.]exe))"
52 reg_exe = re.compile(pattern, re.IGNORECASE)
53 breg_exe = re.compile(bytes(pattern, encoding="ascii"), re.IGNORECASE)
54 g_path_to_python = path_to_python.replace("\\", "\\\\")
55 bg_path_to_python = bytes(g_path_to_python, encoding="ascii")
56 b1 = bytes("#!", encoding="ascii")
57 b2 = bytes("\\5", encoding="ascii")
59 operations = []
60 for file in files:
61 full = os.path.join(folder, file)
62 if os.path.isfile(full):
63 ext = os.path.splitext(full)[-1]
65 if ext in {".py", ""}:
66 with open(full, "r") as f:
67 content = f.read()
68 new_content = reg_exe.sub(
69 "#!" + g_path_to_python + "\\5", content)
70 if new_content != content:
71 fLOG("[pymy] update ", full)
72 operations.append(("update", full))
73 with open(full, "w") as f:
74 f.write(new_content)
76 elif ext == ".exe":
77 with open(full, "rb") as f:
78 content = f.read()
79 new_content = breg_exe.sub(
80 b1 + bg_path_to_python + b2, content)
81 if new_content != content:
82 fLOG("[win_patch_paths] update ", full)
83 operations.append(("update", full))
84 try:
85 with open(full, "wb") as f:
86 f.write(new_content)
87 except PermissionError as e:
88 with open(full + ".replace", "wb") as f:
89 f.write(new_content)
90 mes = ("unable to overwrite '{0}', it will have to be manually done, " +
91 "another file was created with .replace as an extension").format(
92 full)
93 raise Exception(mes) from e
94 else:
95 pass
97 return operations