|
1 #!/usr/bin/env python3 |
|
2 # -*- coding: utf-8 -*- |
|
3 |
|
4 # Copyright (c) 2019 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
5 # |
|
6 |
|
7 """ |
|
8 Module implementing the post install logic for 'pip install'. |
|
9 """ |
|
10 |
|
11 import sys |
|
12 import os |
|
13 import shutil |
|
14 import sysconfig |
|
15 import contextlib |
|
16 |
|
17 ###################################################################### |
|
18 ## Post installation hooks for Windows below |
|
19 ###################################################################### |
|
20 |
|
21 |
|
22 def createWindowsLinks(): |
|
23 """ |
|
24 Create Desktop and Start Menu links. |
|
25 """ |
|
26 regPath = ( |
|
27 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer" + |
|
28 "\\User Shell Folders" |
|
29 ) |
|
30 |
|
31 # 1. create desktop shortcuts |
|
32 regName = "Desktop" |
|
33 desktopFolder = os.path.normpath( |
|
34 os.path.expandvars(getWinregEntry(regName, regPath))) |
|
35 for linkName, targetPath, iconPath in windowsDesktopEntries(): |
|
36 linkPath = os.path.join(desktopFolder, linkName) |
|
37 createWindowsShortcut(linkPath, targetPath, iconPath) |
|
38 |
|
39 # 2. create start menu entry and shortcuts |
|
40 regName = "Programs" |
|
41 programsEntry = getWinregEntry(regName, regPath) |
|
42 if programsEntry: |
|
43 programsFolder = os.path.normpath(os.path.expandvars(programsEntry)) |
|
44 eric7EntryPath = os.path.join(programsFolder, windowsProgramsEntry()) |
|
45 if not os.path.exists(eric7EntryPath): |
|
46 try: |
|
47 os.makedirs(eric7EntryPath) |
|
48 except OSError: |
|
49 # maybe restrictions prohibited link creation |
|
50 return |
|
51 |
|
52 for linkName, targetPath, iconPath in windowsDesktopEntries(): |
|
53 linkPath = os.path.join(eric7EntryPath, linkName) |
|
54 createWindowsShortcut(linkPath, targetPath, iconPath) |
|
55 |
|
56 |
|
57 def getWinregEntry(name, path): |
|
58 """ |
|
59 Function to get an entry from the Windows Registry. |
|
60 |
|
61 @param name variable name |
|
62 @type str |
|
63 @param path registry path of the variable |
|
64 @type str |
|
65 @return value of requested registry variable |
|
66 @rtype any |
|
67 """ |
|
68 try: |
|
69 import winreg |
|
70 except ImportError: |
|
71 return None |
|
72 |
|
73 try: |
|
74 registryKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0, |
|
75 winreg.KEY_READ) |
|
76 value, _ = winreg.QueryValueEx(registryKey, name) |
|
77 winreg.CloseKey(registryKey) |
|
78 return value |
|
79 except WindowsError: |
|
80 return None |
|
81 |
|
82 |
|
83 def windowsDesktopEntries(): |
|
84 """ |
|
85 Function to generate data for the Windows Desktop links. |
|
86 |
|
87 @return list of tuples containing the desktop link name, |
|
88 the link target and the icon target |
|
89 @rtype list of tuples of (str, str, str) |
|
90 """ |
|
91 import eric7 |
|
92 |
|
93 majorVersion, minorVersion = sys.version_info[:2] |
|
94 scriptsDir = sysconfig.get_path("scripts") |
|
95 iconsDir = os.path.join(os.path.dirname(eric7.__file__), "pixmaps") |
|
96 entriesTemplates = [ |
|
97 ("eric7 (Python {0}.{1}).lnk", |
|
98 os.path.join(scriptsDir, "eric7.exe"), |
|
99 os.path.join(iconsDir, "eric7.ico") |
|
100 ), |
|
101 ("eric7 Browser (Python {0}.{1}).lnk", |
|
102 os.path.join(scriptsDir, "eric7_browser.exe"), |
|
103 os.path.join(iconsDir, "ericWeb48.ico") |
|
104 ), |
|
105 ] |
|
106 |
|
107 return [ |
|
108 (e[0].format(majorVersion, minorVersion), e[1], e[2]) |
|
109 for e in entriesTemplates |
|
110 ] |
|
111 |
|
112 |
|
113 def createWindowsShortcut(linkPath, targetPath, iconPath): |
|
114 """ |
|
115 Create Windows shortcut. |
|
116 |
|
117 @param linkPath path of the shortcut file |
|
118 @type str |
|
119 @param targetPath path the shortcut shall point to |
|
120 @type str |
|
121 @param iconPath path of the icon file |
|
122 @type str |
|
123 """ |
|
124 from win32com.client import Dispatch |
|
125 from pywintypes import com_error |
|
126 |
|
127 with contextlib.suppress(com_error): |
|
128 shell = Dispatch('WScript.Shell') |
|
129 shortcut = shell.CreateShortCut(linkPath) |
|
130 shortcut.Targetpath = targetPath |
|
131 shortcut.WorkingDirectory = os.path.dirname(targetPath) |
|
132 shortcut.IconLocation = iconPath |
|
133 shortcut.save() |
|
134 |
|
135 |
|
136 def windowsProgramsEntry(): |
|
137 """ |
|
138 Function to generate the name of the Start Menu top entry. |
|
139 |
|
140 @return name of the Start Menu top entry |
|
141 @rtype str |
|
142 """ |
|
143 majorVersion, minorVersion = sys.version_info[:2] |
|
144 return "eric7 (Python {0}.{1})".format(majorVersion, minorVersion) |
|
145 |
|
146 ###################################################################### |
|
147 ## Post installation hooks for Linux below |
|
148 ###################################################################### |
|
149 |
|
150 |
|
151 def copyLinuxMetaData(): |
|
152 """ |
|
153 Function to copy the meta data files. |
|
154 """ |
|
155 import eric7 |
|
156 |
|
157 scriptsDir = sysconfig.get_path("scripts") |
|
158 dstDir = os.path.join(os.path.expanduser("~"), ".local", "share") |
|
159 iconsDir = os.path.join(os.path.dirname(eric7.__file__), "pixmaps") |
|
160 svgIconsDir = os.path.join(os.path.dirname(eric7.__file__), |
|
161 "icons", "breeze-dark") |
|
162 linuxDir = os.path.join(os.path.dirname(eric7.__file__), "data", "linux") |
|
163 |
|
164 for metaDir in ["appdata", "metainfo"]: |
|
165 copyMetaFile(os.path.join(linuxDir, "eric7.appdata.xml"), |
|
166 os.path.join(dstDir, metaDir), |
|
167 "eric7.appdata.xml") |
|
168 |
|
169 for svgIcon in ("eric.svg", "ericWeb48.svg"): |
|
170 copyMetaFile(os.path.join(svgIconsDir, svgIcon), |
|
171 os.path.join(dstDir, "icons"), |
|
172 svgIcon) |
|
173 for icon in ("eric48_icon.png", "ericWeb48_icon.png"): |
|
174 copyMetaFile(os.path.join(iconsDir, icon), |
|
175 os.path.join(dstDir, "icons"), |
|
176 icon) |
|
177 copyMetaFile(os.path.join(iconsDir, "eric48_icon.png"), |
|
178 os.path.join(dstDir, "icons", "hicolor", "48x48", "apps"), |
|
179 "eric.png") |
|
180 copyMetaFile(os.path.join(iconsDir, "ericWeb48_icon.png"), |
|
181 os.path.join(dstDir, "icons", "hicolor", "48x48", "apps"), |
|
182 "ericWeb.png") |
|
183 |
|
184 for desktop in ["eric7.desktop", "eric7_browser.desktop"]: |
|
185 copyDesktopFile( |
|
186 os.path.join(linuxDir, desktop), |
|
187 os.path.join(dstDir, "applications", desktop), |
|
188 scriptsDir |
|
189 ) |
|
190 |
|
191 |
|
192 def copyMetaFile(srcname, dstpath, dstname): |
|
193 """ |
|
194 Function to copy a file to its destination. |
|
195 |
|
196 @param srcname name of the source file |
|
197 @type str |
|
198 @param dstpath name of the destination path |
|
199 @type str |
|
200 @param dstname name of the destination file (without path) |
|
201 @type str |
|
202 """ |
|
203 if not os.path.isdir(dstpath): |
|
204 os.makedirs(dstpath) |
|
205 dstname = os.path.join(dstpath, dstname) |
|
206 shutil.copy2(srcname, dstname) |
|
207 os.chmod(dstname, 0o644) |
|
208 |
|
209 |
|
210 def copyDesktopFile(src, dst, scriptsdir): |
|
211 """ |
|
212 Modify a desktop file and write it to its destination. |
|
213 |
|
214 @param src source file name (string) |
|
215 @param dst destination file name (string) |
|
216 @param scriptsdir directory containing the scripts (string) |
|
217 """ |
|
218 with open(src, "r", encoding="utf-8") as f: |
|
219 text = f.read() |
|
220 |
|
221 text = text.replace("@BINDIR@", scriptsdir) |
|
222 |
|
223 with open(dst, "w", encoding="utf-8") as f: |
|
224 f.write(text) |
|
225 os.chmod(dst, 0o644) |
|
226 |
|
227 ###################################################################### |
|
228 ## Main script below |
|
229 ###################################################################### |
|
230 |
|
231 |
|
232 def main(): |
|
233 """ |
|
234 Main script orchestrating the platform dependent post installation tasks. |
|
235 """ |
|
236 if sys.platform.startswith(("win", "cygwin")): |
|
237 createWindowsLinks() |
|
238 elif sys.platform.startswith("linux"): |
|
239 copyLinuxMetaData() |
|
240 |
|
241 sys.exit(0) |
|
242 |
|
243 |
|
244 if __name__ == "__main__": |
|
245 main() |