|
1 #!/usr/bin/env python |
|
2 # -*- coding: utf-8 -*- |
|
3 |
|
4 # Copyright (c) 2002-2009 Detlev Offenbach <detlev@die-offenbachs.de> |
|
5 # |
|
6 # This is the install script for eric4. |
|
7 |
|
8 """ |
|
9 Installation script for the eric4 IDE and all eric4 related tools. |
|
10 """ |
|
11 |
|
12 import sys |
|
13 import os |
|
14 import re |
|
15 import compileall |
|
16 import py_compile |
|
17 import glob |
|
18 import shutil |
|
19 import fnmatch |
|
20 import distutils.sysconfig |
|
21 |
|
22 # Define the globals. |
|
23 progName = None |
|
24 modDir = None |
|
25 pyModDir = None |
|
26 platBinDir = None |
|
27 distDir = None |
|
28 apisDir = None |
|
29 doCleanup = True |
|
30 doCompile = True |
|
31 cfg = {} |
|
32 progLanguages = ["Python", "Ruby"] |
|
33 |
|
34 def usage(rcode = 2): |
|
35 """ |
|
36 Display a usage message and exit. |
|
37 |
|
38 @param rcode the return code passed back to the calling process. |
|
39 """ |
|
40 global progName, platBinDir, modDir, distDir, apisDir |
|
41 |
|
42 print |
|
43 print "Usage:" |
|
44 print " %s [-chxz] [-a dir] [-b dir] [-d dir] [-f file] [-i dir]" % (progName) |
|
45 print "where:" |
|
46 print " -h display this help message" |
|
47 print " -a dir where the API files will be installed" |
|
48 if apisDir: |
|
49 print " (default: %s)" % (apisDir) |
|
50 else: |
|
51 print " (no default value)" |
|
52 print " -b dir where the binaries will be installed" |
|
53 print " (default: %s)" % (platBinDir) |
|
54 print " -d dir where eric4 python files will be installed" |
|
55 print " (default: %s)" % (modDir) |
|
56 print " -f file configuration file naming the various installation paths" |
|
57 if not sys.platform.startswith("win"): |
|
58 print " -i dir temporary install prefix" |
|
59 print " (default: %s)" % (distDir) |
|
60 print " -x don't perform dependency checks (use on your own risk)" |
|
61 print " -c don't cleanup old installation first" |
|
62 print " -z don't compile the installed python files" |
|
63 print |
|
64 print "The file given to the -f option must be valid Python code defining a" |
|
65 print "dictionary called 'cfg' with the keys 'ericDir', 'ericPixDir', 'ericIconDir'," |
|
66 print "'ericDTDDir', 'ericCSSDir', 'ericStylesDir', 'ericDocDir', 'ericExamplesDir'," |
|
67 print "'ericTranslationsDir', 'ericTemplatesDir', 'ericCodeTemplatesDir'," |
|
68 print "'ericOthersDir','bindir', 'mdir' and 'apidir." |
|
69 print "These define the directories for the installation of the various parts of"\ |
|
70 " eric4." |
|
71 |
|
72 sys.exit(rcode) |
|
73 |
|
74 |
|
75 def initGlobals(): |
|
76 """ |
|
77 Sets the values of globals that need more than a simple assignment. |
|
78 """ |
|
79 global platBinDir, modDir, pyModDir, apisDir |
|
80 |
|
81 if sys.platform.startswith("win"): |
|
82 platBinDir = sys.exec_prefix |
|
83 if platBinDir.endswith("\\"): |
|
84 platBinDir = platBinDir[:-1] |
|
85 else: |
|
86 platBinDir = "/usr/local/bin" |
|
87 |
|
88 modDir = distutils.sysconfig.get_python_lib(True) |
|
89 pyModDir = modDir |
|
90 |
|
91 try: |
|
92 from PyQt4 import pyqtconfig |
|
93 qtDataDir = pyqtconfig._pkg_config["qt_data_dir"] |
|
94 except (AttributeError, ImportError): |
|
95 qtDataDir = None |
|
96 if qtDataDir: |
|
97 apisDir = os.path.join(qtDataDir, "qsci", "api") |
|
98 else: |
|
99 apisDir = None |
|
100 |
|
101 |
|
102 def copyToFile(name, text): |
|
103 """ |
|
104 Copy a string to a file. |
|
105 |
|
106 @param name the name of the file. |
|
107 @param text the contents to copy to the file. |
|
108 """ |
|
109 f = open(name,"w") |
|
110 f.write(text) |
|
111 f.close() |
|
112 |
|
113 |
|
114 def wrapperName(dname, wfile): |
|
115 """ |
|
116 Create the platform specific name for the wrapper script. |
|
117 |
|
118 @param dname name of the directory to place the wrapper into |
|
119 @param wfile basename (without extension) of the wrapper script |
|
120 @return the name of the wrapper script |
|
121 """ |
|
122 if sys.platform.startswith("win"): |
|
123 wname = dname + "\\" + wfile + ".bat" |
|
124 else: |
|
125 wname = dname + "/" + wfile |
|
126 |
|
127 return wname |
|
128 |
|
129 |
|
130 def createPyWrapper(pydir, wfile): |
|
131 """ |
|
132 Create an executable wrapper for a Python script. |
|
133 |
|
134 @param pydir the name of the directory where the Python script will eventually |
|
135 be installed |
|
136 @param wfile the basename of the wrapper |
|
137 @return the platform specific name of the wrapper |
|
138 """ |
|
139 # all kinds of Windows systems |
|
140 if sys.platform.startswith("win"): |
|
141 wname = wfile + ".bat" |
|
142 wrapper = \ |
|
143 '''@"%s\\pythonw" "%s\\%s.py" %%1 %%2 %%3 %%4 %%5 %%6 %%7 %%8 %%9 |
|
144 ''' % (platBinDir, pydir, wfile) |
|
145 |
|
146 # Mac OS X |
|
147 elif sys.platform == "darwin": |
|
148 wname = wfile |
|
149 wrapper = \ |
|
150 '''#!/bin/sh |
|
151 |
|
152 exec "%s/bin/pythonw" "%s/%s.py" "$@" |
|
153 ''' % (sys.exec_prefix, pydir, wfile) |
|
154 |
|
155 # *nix systems |
|
156 else: |
|
157 wname = wfile |
|
158 wrapper = \ |
|
159 '''#!/bin/sh |
|
160 |
|
161 exec "%s" "%s/%s.py" "$@" |
|
162 ''' % (sys.executable, pydir, wfile) |
|
163 |
|
164 copyToFile(wname, wrapper) |
|
165 os.chmod(wname, 0755) |
|
166 |
|
167 return wname |
|
168 |
|
169 |
|
170 def copyTree(src, dst, filters, excludeDirs=[]): |
|
171 """ |
|
172 Copy Python, translation, documentation, wizards configuration, |
|
173 designer template files and DTDs of a directory tree. |
|
174 |
|
175 @param src name of the source directory |
|
176 @param dst name of the destination directory |
|
177 @param filters list of filter pattern determining the files to be copied |
|
178 @param excludeDirs list of (sub)directories to exclude from copying |
|
179 """ |
|
180 try: |
|
181 names = os.listdir(src) |
|
182 except OSError: |
|
183 return # ignore missing directories (most probably the i18n directory) |
|
184 |
|
185 for name in names: |
|
186 srcname = os.path.join(src, name) |
|
187 dstname = os.path.join(dst, name) |
|
188 for filter in filters: |
|
189 if fnmatch.fnmatch(srcname, filter): |
|
190 if not os.path.isdir(dst): |
|
191 os.makedirs(dst) |
|
192 shutil.copy2(srcname, dstname) |
|
193 break |
|
194 else: |
|
195 if os.path.isdir(srcname) and not srcname in excludeDirs: |
|
196 copyTree(srcname, dstname, filters) |
|
197 |
|
198 |
|
199 def createGlobalPluginsDir(): |
|
200 """ |
|
201 Create the global plugins directory, if it doesn't exist. |
|
202 """ |
|
203 global cfg, distDir |
|
204 |
|
205 pdir = os.path.join(cfg['mdir'], "eric4plugins") |
|
206 fname = os.path.join(pdir, "__init__.py") |
|
207 if not os.path.exists(fname): |
|
208 if not os.path.exists(pdir): |
|
209 os.mkdir(pdir, 0755) |
|
210 f = open(fname, "wb") |
|
211 f.write(\ |
|
212 '''# -*- coding: utf-8 -*- |
|
213 |
|
214 """ |
|
215 Package containing the global plugins. |
|
216 """ |
|
217 ''' |
|
218 ) |
|
219 f.close() |
|
220 |
|
221 |
|
222 def cleanUp(): |
|
223 """ |
|
224 Uninstall the old eric files. |
|
225 """ |
|
226 try: |
|
227 from eric4config import getConfig |
|
228 except ImportError: |
|
229 # eric4 wasn't installed previously |
|
230 return |
|
231 |
|
232 global pyModDir, progLanguages |
|
233 |
|
234 # Remove the wrapper scripts |
|
235 rem_wnames = [ |
|
236 "eric4-api", "eric4-compare", |
|
237 "eric4-configure", "eric4-diff", |
|
238 "eric4-doc", "eric4-helpviewer", |
|
239 "eric4-qregexp", "eric4-re", |
|
240 "eric4-trpreviewer", "eric4-uipreviewer", |
|
241 "eric4-unittest", "eric4", |
|
242 "eric4-tray", "eric4-editor", |
|
243 "eric4-plugininstall", "eric4-pluginuninstall", |
|
244 "eric4-pluginrepository", "eric4-sqlbrowser", |
|
245 "eric4-webbrowser", |
|
246 ] |
|
247 for rem_wname in rem_wnames: |
|
248 rwname = wrapperName(getConfig('bindir'), rem_wname) |
|
249 if os.path.exists(rwname): |
|
250 os.remove(rwname) |
|
251 |
|
252 # Cleanup our config file |
|
253 for name in ['eric4config.py', 'eric4config.pyc']: |
|
254 e4cfile = os.path.join(pyModDir, name) |
|
255 if os.path.exists(e4cfile): |
|
256 os.remove(e4cfile) |
|
257 |
|
258 # Cleanup the install directories |
|
259 for name in ['ericExamplesDir', 'ericDocDir', 'ericDTDDir', 'ericCSSDir', |
|
260 'ericIconDir', 'ericPixDir', 'ericDir', 'ericTemplatesDir', |
|
261 'ericCodeTemplatesDir', 'ericOthersDir', 'ericStylesDir']: |
|
262 if os.path.exists(getConfig(name)): |
|
263 shutil.rmtree(getConfig(name), True) |
|
264 |
|
265 # Cleanup translations |
|
266 for name in glob.glob(os.path.join(getConfig('ericTranslationsDir'), 'eric4_*.qm')): |
|
267 if os.path.exists(name): |
|
268 os.remove(name) |
|
269 |
|
270 # Cleanup API files |
|
271 try: |
|
272 apidir = getConfig('apidir') |
|
273 for progLanguage in progLanguages: |
|
274 for name in getConfig('apis'): |
|
275 apiname = os.path.join(apidir, progLanguage, name) |
|
276 if os.path.exists(apiname): |
|
277 os.remove(apiname) |
|
278 except AttributeError: |
|
279 pass |
|
280 |
|
281 |
|
282 def installEric(): |
|
283 """ |
|
284 Actually perform the installation steps. |
|
285 """ |
|
286 global distDir, doCleanup, cfg, progLanguages |
|
287 |
|
288 # Create the platform specific wrappers. |
|
289 wnames = [] |
|
290 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-api")) |
|
291 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-compare")) |
|
292 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-configure")) |
|
293 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-diff")) |
|
294 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-doc")) |
|
295 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-webbrowser")) |
|
296 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-qregexp")) |
|
297 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-re")) |
|
298 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-trpreviewer")) |
|
299 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-uipreviewer")) |
|
300 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-unittest")) |
|
301 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-tray")) |
|
302 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-editor")) |
|
303 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-plugininstall")) |
|
304 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-pluginuninstall")) |
|
305 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-pluginrepository")) |
|
306 wnames.append(createPyWrapper(cfg['ericDir'], "eric4-sqlbrowser")) |
|
307 wnames.append(createPyWrapper(cfg['ericDir'], "eric4")) |
|
308 |
|
309 # set install prefix, if not None |
|
310 if distDir: |
|
311 for key in cfg.keys(): |
|
312 cfg[key] = os.path.normpath(distDir + os.sep + cfg[key]) |
|
313 |
|
314 try: |
|
315 # Install the files |
|
316 # make the install directories |
|
317 for key in cfg.keys(): |
|
318 if not os.path.isdir(cfg[key]): |
|
319 os.makedirs(cfg[key]) |
|
320 |
|
321 # copy the eric4 config file |
|
322 if distDir: |
|
323 shutil.copy('eric4config.py', cfg['mdir']) |
|
324 if os.path.exists('eric4config.pyc'): |
|
325 shutil.copy('eric4config.pyc', cfg['mdir']) |
|
326 else: |
|
327 shutil.copy('eric4config.py', modDir) |
|
328 if os.path.exists('eric4config.pyc'): |
|
329 shutil.copy('eric4config.pyc', modDir) |
|
330 |
|
331 # copy the eric4.pth file |
|
332 if distDir: |
|
333 shutil.copy('eric%seric4.pth' % os.sep, cfg['mdir']) |
|
334 else: |
|
335 shutil.copy('eric%seric4.pth' % os.sep, modDir) |
|
336 |
|
337 # copy the various parts of eric4 |
|
338 copyTree('eric', cfg['ericDir'], ['*.py', '*.pyc', '*.pyo', '*.pyw'], |
|
339 ['eric%sExamples' % os.sep]) |
|
340 copyTree('eric', cfg['ericDir'], ['*.rb'], |
|
341 ['eric%sExamples' % os.sep]) |
|
342 copyTree('eric%sPlugins' % os.sep, '%s%sPlugins' % (cfg['ericDir'], os.sep), |
|
343 ['*.png']) |
|
344 copyTree('eric%sDocumentation' % os.sep, cfg['ericDocDir'], ['*.html', '*.qch']) |
|
345 copyTree('eric%sDTDs' % os.sep, cfg['ericDTDDir'], ['*.dtd']) |
|
346 copyTree('eric%sCSSs' % os.sep, cfg['ericCSSDir'], ['*.css']) |
|
347 copyTree('eric%sStyles' % os.sep, cfg['ericStylesDir'], ['*.qss']) |
|
348 copyTree('eric%si18n' % os.sep, cfg['ericTranslationsDir'], ['*.qm']) |
|
349 copyTree('eric%sicons' % os.sep, cfg['ericIconDir'], ['*.png', 'LICENSE*.*']) |
|
350 copyTree('eric%spixmaps' % os.sep, cfg['ericPixDir'], ['*.png', '*.xpm', '*.ico']) |
|
351 copyTree('eric%sDesignerTemplates' % os.sep, cfg['ericTemplatesDir'], ['*.tmpl']) |
|
352 copyTree('eric%sCodeTemplates' % os.sep, cfg['ericCodeTemplatesDir'], ['*.tmpl']) |
|
353 copyTree('eric%sExamples' % os.sep, cfg['ericExamplesDir'], |
|
354 ['*.py', '*.pyc', '*.pyo']) |
|
355 |
|
356 # copy the wrappers |
|
357 for wname in wnames: |
|
358 shutil.copy(wname, cfg['bindir']) |
|
359 |
|
360 # copy the license file |
|
361 shutil.copy('eric%sLICENSE.GPL3' % os.sep, cfg['ericDir']) |
|
362 |
|
363 # create the global plugins directory |
|
364 createGlobalPluginsDir() |
|
365 |
|
366 except IOError, msg: |
|
367 sys.stderr.write('IOError: %s\nTry install as root.\n' % msg) |
|
368 sys.exit(7) |
|
369 |
|
370 # copy some text files to the doc area |
|
371 for name in ["LICENSE.GPL3", "THANKS", "changelog"]: |
|
372 try: |
|
373 shutil.copy('eric%s%s' % (os.sep, name), cfg['ericDocDir']) |
|
374 except EnvironmentError: |
|
375 print "Could not install 'eric%s%s'." % (os.sep, name) |
|
376 for name in glob.glob(os.path.join('eric', 'README*.*')): |
|
377 try: |
|
378 shutil.copy(name, cfg['ericDocDir']) |
|
379 except EnvironmentError: |
|
380 print "Could not install 'eric%s%s'." % (os.sep, name) |
|
381 |
|
382 # copy some more stuff |
|
383 for name in ['default.e4k']: |
|
384 try: |
|
385 shutil.copy('eric%s%s' % (os.sep, name), cfg['ericOthersDir']) |
|
386 except EnvironmentError: |
|
387 print "Could not install 'eric%s%s'." % (os.sep, name) |
|
388 |
|
389 # install the API file |
|
390 for progLanguage in progLanguages: |
|
391 apidir = os.path.join(cfg['apidir'], progLanguage.lower()) |
|
392 if not os.path.exists(apidir): |
|
393 os.makedirs(apidir) |
|
394 for apiName in glob.glob(os.path.join("eric", "APIs", progLanguage, "*.api")): |
|
395 try: |
|
396 shutil.copy(apiName, apidir) |
|
397 except EnvironmentError: |
|
398 print "Could not install '%s'." % apiName |
|
399 |
|
400 |
|
401 def createInstallConfig(): |
|
402 """ |
|
403 Create the installation config dictionary. |
|
404 """ |
|
405 global modDir, platBinDir, cfg, apisDir |
|
406 |
|
407 ericdir = os.path.join(modDir, "eric4") |
|
408 cfg = { |
|
409 'ericDir' : ericdir, |
|
410 'ericPixDir' : os.path.join(ericdir, "pixmaps"), |
|
411 'ericIconDir' : os.path.join(ericdir, "icons"), |
|
412 'ericDTDDir' : os.path.join(ericdir, "DTDs"), |
|
413 'ericCSSDir' : os.path.join(ericdir, "CSSs"), |
|
414 'ericStylesDir' : os.path.join(ericdir, "Styles"), |
|
415 'ericDocDir' : os.path.join(ericdir, "Documentation"), |
|
416 'ericExamplesDir' : os.path.join(ericdir, "Examples"), |
|
417 'ericTranslationsDir' : os.path.join(ericdir, "i18n"), |
|
418 'ericTemplatesDir' : os.path.join(ericdir, "DesignerTemplates"), |
|
419 'ericCodeTemplatesDir' : os.path.join(ericdir, 'CodeTemplates'), |
|
420 'ericOthersDir' : ericdir, |
|
421 'bindir' : platBinDir, |
|
422 'mdir' : modDir, |
|
423 } |
|
424 if apisDir: |
|
425 cfg['apidir'] = apisDir |
|
426 else: |
|
427 cfg['apidir'] = os.path.join(ericdir, "api") |
|
428 configLength = 15 |
|
429 |
|
430 def createConfig(): |
|
431 """ |
|
432 Create a config file with the respective config entries. |
|
433 """ |
|
434 global cfg |
|
435 |
|
436 apis = [] |
|
437 for progLanguage in progLanguages: |
|
438 for apiName in glob.glob(os.path.join("eric", "APIs", progLanguage, "*.api")): |
|
439 apis.append(os.path.basename(apiName)) |
|
440 |
|
441 fn = 'eric4config.py' |
|
442 config = \ |
|
443 """# -*- coding: utf-8 -*- |
|
444 # |
|
445 # This module contains the configuration of the individual eric4 installation |
|
446 # |
|
447 |
|
448 _pkg_config = { |
|
449 'ericDir' : r'%s', |
|
450 'ericPixDir' : r'%s', |
|
451 'ericIconDir' : r'%s', |
|
452 'ericDTDDir' : r'%s', |
|
453 'ericCSSDir' : r'%s', |
|
454 'ericStylesDir' : r'%s', |
|
455 'ericDocDir' : r'%s', |
|
456 'ericExamplesDir' : r'%s', |
|
457 'ericTranslationsDir' : r'%s', |
|
458 'ericTemplatesDir' : r'%s', |
|
459 'ericCodeTemplatesDir' : r'%s', |
|
460 'ericOthersDir' : r'%s', |
|
461 'bindir' : r'%s', |
|
462 'mdir' : r'%s', |
|
463 'apidir' : r'%s', |
|
464 'apis' : %s, |
|
465 } |
|
466 |
|
467 def getConfig(name): |
|
468 ''' |
|
469 Module function to get a configuration value. |
|
470 |
|
471 @param name the name of the configuration value (string). |
|
472 ''' |
|
473 try: |
|
474 return _pkg_config[name] |
|
475 except KeyError: |
|
476 pass |
|
477 |
|
478 raise AttributeError, '"%%s" is not a valid configuration value' %% name |
|
479 """ % (cfg['ericDir'], cfg['ericPixDir'], cfg['ericIconDir'], |
|
480 cfg['ericDTDDir'], cfg['ericCSSDir'], |
|
481 cfg['ericStylesDir'], cfg['ericDocDir'], |
|
482 cfg['ericExamplesDir'], cfg['ericTranslationsDir'], |
|
483 cfg['ericTemplatesDir'], |
|
484 cfg['ericCodeTemplatesDir'], cfg['ericOthersDir'], |
|
485 cfg['bindir'], cfg['mdir'], |
|
486 cfg['apidir'], apis) |
|
487 copyToFile(fn, config) |
|
488 |
|
489 def doDependancyChecks(): |
|
490 """ |
|
491 Perform some dependency checks. |
|
492 """ |
|
493 print 'Checking dependencies' |
|
494 |
|
495 # perform dependency checks |
|
496 if sys.version_info < (2, 6, 0): |
|
497 print 'Sorry, you must have Python 2.6.0 or higher.' |
|
498 sys.exit(5) |
|
499 if sys.version_info > (2, 9, 9): |
|
500 print 'Sorry, eric4 requires Python 2 for running.' |
|
501 sys.exit(5) |
|
502 print "Python Version: %d.%d.%d" % sys.version_info[:3] |
|
503 |
|
504 try: |
|
505 from PyQt4.QtCore import qVersion, PYQT_VERSION |
|
506 except ImportError, msg: |
|
507 print 'Sorry, please install PyQt4.' |
|
508 print 'Error: %s' % msg |
|
509 sys.exit(1) |
|
510 print "Found PyQt" |
|
511 |
|
512 try: |
|
513 from PyQt4 import Qsci |
|
514 except ImportError, msg: |
|
515 print "Sorry, please install QScintilla2 and" |
|
516 print "it's PyQt4 wrapper." |
|
517 print 'Error: %s' % msg |
|
518 sys.exit(1) |
|
519 print "Found QScintilla2" |
|
520 |
|
521 # check version of Qt |
|
522 qtMajor = int(qVersion().split('.')[0]) |
|
523 qtMinor = int(qVersion().split('.')[1]) |
|
524 if qtMajor < 4 or (qtMajor == 4 and qtMinor < 5): |
|
525 print 'Sorry, you must have Qt version 4.5.0 or higher.' |
|
526 sys.exit(2) |
|
527 print "Qt Version: %s" % qVersion() |
|
528 |
|
529 #check version of PyQt |
|
530 from PyQt4.QtCore import PYQT_VERSION_STR |
|
531 pyqtVersion = PYQT_VERSION_STR |
|
532 # always assume, that snapshots are new enough |
|
533 if pyqtVersion.find("snapshot-") == -1: |
|
534 while pyqtVersion.count('.') < 2: |
|
535 pyqtVersion += '.0' |
|
536 (maj, min, pat) = pyqtVersion.split('.') |
|
537 maj = int(maj) |
|
538 min = int(min) |
|
539 pat = int(pat) |
|
540 if maj < 4 or (maj == 4 and min < 7): |
|
541 print 'Sorry, you must have PyQt 4.7.0 or higher or' \ |
|
542 ' a recent snapshot release.' |
|
543 sys.exit(3) |
|
544 print "PyQt Version: ", pyqtVersion |
|
545 |
|
546 #check version of QScintilla |
|
547 from PyQt4.Qsci import QSCINTILLA_VERSION_STR |
|
548 scintillaVersion = QSCINTILLA_VERSION_STR |
|
549 # always assume, that snapshots are new enough |
|
550 if scintillaVersion.find("snapshot-") == -1: |
|
551 while scintillaVersion.count('.') < 2: |
|
552 scintillaVersion += '.0' |
|
553 (maj, min, pat) = scintillaVersion.split('.') |
|
554 maj = int(maj) |
|
555 min = int(min) |
|
556 pat = int(pat) |
|
557 if maj < 2 or (maj == 2 and min < 4): |
|
558 print 'Sorry, you must have QScintilla 2.4.0 or higher or' \ |
|
559 ' a recent snapshot release.' |
|
560 sys.exit(4) |
|
561 print "QScintilla Version: ", QSCINTILLA_VERSION_STR |
|
562 print "All dependencies ok." |
|
563 print |
|
564 |
|
565 def compileUiFiles(): |
|
566 """ |
|
567 Compile the .ui files to Python sources. |
|
568 """ |
|
569 try: |
|
570 from PyQt4.uic import compileUiDir |
|
571 except ImportError: |
|
572 from PyQt4.uic import compileUi |
|
573 |
|
574 def compileUiDir(dir, recurse = False, map = None, **compileUi_args): |
|
575 """ |
|
576 Creates Python modules from Qt Designer .ui files in a directory or |
|
577 directory tree. |
|
578 |
|
579 Note: This function is a modified version of the one found in PyQt4. |
|
580 |
|
581 @param dir Name of the directory to scan for files whose name ends with |
|
582 '.ui'. By default the generated Python module is created in the same |
|
583 directory ending with '.py'. |
|
584 @param recurse flag indicating that any sub-directories should be scanned. |
|
585 @param map an optional callable that is passed the name of the directory |
|
586 containing the '.ui' file and the name of the Python module that will be |
|
587 created. The callable should return a tuple of the name of the directory |
|
588 in which the Python module will be created and the (possibly modified) |
|
589 name of the module. |
|
590 @param compileUi_args any additional keyword arguments that are passed to |
|
591 the compileUi() function that is called to create each Python module. |
|
592 """ |
|
593 def compile_ui(ui_dir, ui_file): |
|
594 """ |
|
595 Local function to compile a single .ui file. |
|
596 |
|
597 @param ui_dir directory containing the .ui file (string) |
|
598 @param ui_file file name of the .ui file (string) |
|
599 """ |
|
600 # Ignore if it doesn't seem to be a .ui file. |
|
601 if ui_file.endswith('.ui'): |
|
602 py_dir = ui_dir |
|
603 py_file = ui_file[:-3] + '.py' |
|
604 |
|
605 # Allow the caller to change the name of the .py file or generate |
|
606 # it in a different directory. |
|
607 if map is not None: |
|
608 py_dir, py_file = map(py_dir, py_file) |
|
609 |
|
610 # Make sure the destination directory exists. |
|
611 try: |
|
612 os.makedirs(py_dir) |
|
613 except: |
|
614 pass |
|
615 |
|
616 ui_path = os.path.join(ui_dir, ui_file) |
|
617 py_path = os.path.join(py_dir, py_file) |
|
618 |
|
619 ui_file = open(ui_path, 'r') |
|
620 py_file = open(py_path, 'w') |
|
621 |
|
622 try: |
|
623 compileUi(ui_file, py_file, **compileUi_args) |
|
624 finally: |
|
625 ui_file.close() |
|
626 py_file.close() |
|
627 |
|
628 if recurse: |
|
629 for root, _, files in os.walk(dir): |
|
630 for ui in files: |
|
631 compile_ui(root, ui) |
|
632 else: |
|
633 for ui in os.listdir(dir): |
|
634 if os.path.isfile(os.path.join(dir, ui)): |
|
635 compile_ui(dir, ui) |
|
636 |
|
637 def pyName(py_dir, py_file): |
|
638 """ |
|
639 Local function to create the Python source file name for the compiled .ui file. |
|
640 |
|
641 @param py_dir suggested name of the directory (string) |
|
642 @param py_file suggested name for the compile source file (string) |
|
643 @return tuple of directory name (string) and source file name (string) |
|
644 """ |
|
645 return py_dir, "Ui_%s" % py_file |
|
646 |
|
647 compileUiDir("eric", True, pyName) |
|
648 |
|
649 def main(argv): |
|
650 """ |
|
651 The main function of the script. |
|
652 |
|
653 @param argv the list of command line arguments. |
|
654 """ |
|
655 import getopt |
|
656 |
|
657 # Parse the command line. |
|
658 global progName, modDir, doCleanup, doCompile, distDir, cfg, apisDir |
|
659 progName = os.path.basename(argv[0]) |
|
660 |
|
661 initGlobals() |
|
662 |
|
663 try: |
|
664 if sys.platform.startswith("win"): |
|
665 optlist, args = getopt.getopt(argv[1:],"chxza:b:d:f:") |
|
666 else: |
|
667 optlist, args = getopt.getopt(argv[1:],"chxza:b:d:f:i:") |
|
668 except getopt.GetoptError: |
|
669 usage() |
|
670 |
|
671 global platBinDir |
|
672 |
|
673 depChecks = True |
|
674 |
|
675 for opt, arg in optlist: |
|
676 if opt == "-h": |
|
677 usage(0) |
|
678 elif opt == "-a": |
|
679 apisDir = arg |
|
680 elif opt == "-b": |
|
681 platBinDir = arg |
|
682 elif opt == "-d": |
|
683 modDir = arg |
|
684 elif opt == "-i": |
|
685 distDir = os.path.normpath(arg) |
|
686 elif opt == "-x": |
|
687 depChecks = False |
|
688 elif opt == "-c": |
|
689 doCleanup = False |
|
690 elif opt == "-z": |
|
691 doCompile = False |
|
692 elif opt == "-f": |
|
693 try: |
|
694 execfile(arg, globals()) |
|
695 if len(cfg) != configLength: |
|
696 print "The configuration dictionary in '%s' is incorrect. Aborting"\ |
|
697 % arg |
|
698 sys.exit(6) |
|
699 except: |
|
700 cfg = {} |
|
701 |
|
702 if len(cfg) == 0: |
|
703 createInstallConfig() |
|
704 |
|
705 if depChecks: |
|
706 doDependancyChecks() |
|
707 |
|
708 # get rid of development config file, if it exists |
|
709 try: |
|
710 os.remove(os.path.join("eric", "eric4config.py")) |
|
711 except EnvironmentError: |
|
712 pass |
|
713 |
|
714 # cleanup old installation |
|
715 try: |
|
716 if doCleanup: |
|
717 if distDir: |
|
718 shutil.rmtree(distDir, True) |
|
719 else: |
|
720 cleanUp() |
|
721 except IOError, msg: |
|
722 sys.stderr.write('IOError: %s\nTry install as root.\n' % msg) |
|
723 |
|
724 # Create a config file and delete the default one |
|
725 createConfig() |
|
726 |
|
727 # Compile .ui files |
|
728 print "Compiling user interface files..." |
|
729 compileUiFiles() |
|
730 |
|
731 if doCompile: |
|
732 print "\nCompiling source files..." |
|
733 if distDir: |
|
734 compileall.compile_dir("eric", |
|
735 ddir = os.path.join(distDir, modDir, cfg['ericDir']), |
|
736 rx = re.compile("Python3"), |
|
737 quiet = True) |
|
738 py_compile.compile("eric4config.py", |
|
739 dfile = os.path.join(distDir, modDir, "eric4config.py")) |
|
740 else: |
|
741 compileall.compile_dir("eric", |
|
742 ddir = os.path.join(modDir, cfg['ericDir']), |
|
743 rx = re.compile("Python3"), |
|
744 quiet = True) |
|
745 py_compile.compile("eric4config.py", |
|
746 dfile = os.path.join(modDir, "eric4config.py")) |
|
747 print "\nInstalling eric4 ..." |
|
748 installEric() |
|
749 print "\nInstallation complete." |
|
750 print |
|
751 |
|
752 # check PyXML version and output a message for broken PyXML (< 0.8.6) |
|
753 try: |
|
754 import _xmlplus |
|
755 v = _xmlplus.version_info |
|
756 if v < (0, 8, 6): |
|
757 from eric4.patch_pyxml import isPatched, patchPyXML |
|
758 if not isPatched(): |
|
759 print "NOTE:" |
|
760 print " Found PyXML %d.%d.%d, which needs a patch to work correctly" % \ |
|
761 (v[0], v[1], v[2]) |
|
762 print " with foreign characters. Please see 'README-PyXML.txt' for" |
|
763 print " details." |
|
764 res = raw_input(" Shall pyXML be patched now (y/n)? ") |
|
765 if res in ["Y", "y"]: |
|
766 patchPyXML() |
|
767 except ImportError: |
|
768 pass |
|
769 |
|
770 #check version of PyQt |
|
771 from PyQt4.QtCore import PYQT_VERSION_STR |
|
772 pyqtVersion = PYQT_VERSION_STR |
|
773 # always assume, that snapshots are new enough |
|
774 if pyqtVersion.find("snapshot-") == -1: |
|
775 while pyqtVersion.count('.') < 2: |
|
776 pyqtVersion += '.0' |
|
777 (maj, min, pat) = pyqtVersion.split('.') |
|
778 maj = int(maj) |
|
779 min = int(min) |
|
780 pat = int(pat) |
|
781 if min < 5: |
|
782 print |
|
783 print "You have to patch PyQt QNetworkAccessManager." |
|
784 print "See the patches directory for details." |
|
785 |
|
786 print |
|
787 if sys.platform.startswith("win"): |
|
788 raw_input("Press enter to continue...") |
|
789 |
|
790 |
|
791 if __name__ == "__main__": |
|
792 try: |
|
793 main(sys.argv) |
|
794 except SystemExit: |
|
795 raise |
|
796 except: |
|
797 print \ |
|
798 """An internal error occured. Please report all the output of the program, |
|
799 including the following traceback, to eric5-bugs@eric-ide.python-projects.org. |
|
800 """ |
|
801 raise |