Added INSTALLATION.
[faces-project.git] / setup.py
blobc811a480db33b57cec9918e473c0226c0d3ecf09
1 ############################################################################
2 # Copyright (C) 2005 by Reithinger GmbH
3 # mreithinger@web.de
5 # This file is part of faces.
6 #
7 # faces is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # faces is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the
19 # Free Software Foundation, Inc.,
20 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 ############################################################################
23 import sys
24 import os
25 import os.path
27 try:
28 from setuptools import setup
29 except ImportError:
30 from distutils.core import setup
32 from distutils.command.install_data import install_data
33 from distutils.dir_util import remove_tree, mkpath
34 from distutils.errors import DistutilsFileError, DistutilsInternalError
35 from distutils import log
39 def copy_tree(src, dst, filter_=None):
40 from distutils.file_util import copy_file
42 if not os.path.isdir(src):
43 raise DistutilsFileError, \
44 "cannot copy tree '%s': not a directory" % src
45 try:
46 names = os.listdir(src)
47 except os.error, (errno, errstr):
48 if dry_run:
49 names = []
50 else:
51 raise DistutilsFileError, \
52 "error listing files in '%s': %s" % (src, errstr)
54 mkpath(dst)
55 outputs = []
57 for n in names:
58 src_name = os.path.join(src, n)
59 dst_name = os.path.join(dst, n)
61 if filter_ and not filter_(src_name): continue
63 if os.path.isdir(src_name):
64 outputs.extend(copy_tree(src_name, dst_name, filter_))
65 else:
66 copy_file(src_name, dst_name)
67 outputs.append(dst_name)
69 return outputs
72 def copy_filter(src):
73 dir, name = os.path.split(src)
74 return name != "setup" and not name.startswith(".svn")
77 class smart_install_data(install_data):
78 def run(self):
79 #need to change self.install_dir to the actual library dir
80 install_cmd = self.get_finalized_command('install')
81 self.install_dir = getattr(install_cmd, 'install_lib')
82 return install_data.run(self)
85 used_install_data = smart_install_data
88 making_dist = False
89 make_py2exe = False
90 help = False
93 for a in sys.argv:
94 if a[1:].startswith("dist") or a.startswith("egg"): making_dist = True
95 if a == "py2exe":
96 make_py2exe = True
97 making_dist = True
98 used_install_data = install_data
100 if a.startswith("--help") or a.startswith("register"):
101 making_dist = False
102 help = True
103 break
106 options = {"py2exe": { # create a compressed zip archive
107 "compressed": 1,
108 "packages": ["encodings", "pytz.zoneinfo", "faces.lib", "faces.charting", "faces.gui", "faces.tools", "faces.gui.editor"],
109 "includes": ["faces.tools.clocking",
110 "matplotlib.numerix.random_array",
111 "pylab",
112 "site" ],
113 "excludes": [ "curses" ]
116 faces_dest_dir = "faces" #os.path.join("src", "faces")
117 metapie_dest_dir = "metapie" #os.path.join("src", "metapie")
120 if making_dist:
121 try: remove_tree(faces_dest_dir)
122 except: pass
124 try: remove_tree(metapie_dest_dir)
125 except: pass
127 import metapie
128 import faces
129 import matplotlib
131 faces_dir = os.path.dirname(faces.__file__)
132 metapie_dir = os.path.dirname(metapie.__file__)
134 copy_tree(faces_dir, faces_dest_dir, copy_filter)
135 copy_tree(metapie_dir, metapie_dest_dir, copy_filter)
136 else:
137 import metapie
138 import faces
139 import matplotlib
142 try:
143 import py2exe
145 manifest_template = '''
146 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
147 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
148 <assemblyIdentity
149 version="5.0.0.0"
150 processorArchitecture="x86"
151 name="%(prog)s"
152 type="win32"
154 <description>%(prog)s Program</description>
155 <dependency>
156 <dependentAssembly>
157 <assemblyIdentity
158 type="win32"
159 name="Microsoft.Windows.Common-Controls"
160 version="6.0.0.0"
161 processorArchitecture="X86"
162 publicKeyToken="6595b64144ccf1df"
163 language="*"
165 </dependentAssembly>
166 </dependency>
167 </assembly>
169 RT_MANIFEST = 24
171 pp_opt=dict(script="faces/gui/plangui.py",
172 other_resources=[(RT_MANIFEST, 1,
173 manifest_template\
174 % dict(prog="plangui"))],
175 icon_resources=[(1, "faces/gui/resources/images/gantt.ico")],)
177 class InnoScript:
178 def __init__(self, name, lib_dir, dist_dir, windows_exe_files=[],
179 lib_files=[], version="0.1"):
180 self.lib_dir = lib_dir
181 self.dist_dir = dist_dir
182 if not self.dist_dir[-1] in "\\/":
183 self.dist_dir += "\\"
184 self.name = name
185 self.version = version
186 self.windows_exe_files = [self.chop(p) for p in windows_exe_files]
187 self.lib_files = [self.chop(p) for p in lib_files]
190 def chop(self, pathname):
191 print "chop", pathname
192 assert pathname.startswith(self.dist_dir)
193 return pathname[len(self.dist_dir):]
196 def create(self, pathname="dist\\faces.iss"):
197 self.pathname = pathname
198 ofi = self.file = open(pathname, "w")
199 print >> ofi, "; WARNING: This script has been created by py2exe." + \
200 " Changes to this script"
201 print >> ofi, "; will be overwritten the next time py2exe is run!"
202 print >> ofi, r"[Languages]"
203 print >> ofi, r'Name: English; MessagesFile: "compiler:Default.isl"'
204 print >> ofi, r'Name: Deutsch; MessagesFile: "compiler:Languages\German.isl"'
205 print >> ofi
207 print >> ofi, r"[Setup]"
208 print >> ofi, r"AppName=%s" % self.name
209 print >> ofi, r"AppVerName=%s %s" % (self.name, self.version)
210 print >> ofi, r"DefaultDirName={pf}\%s" % self.name
211 print >> ofi, r"DefaultGroupName=%s" % self.name
212 print >> ofi, "Compression=bzip"
213 print >> ofi
215 print >> ofi, r"[Files]"
216 for path in self.windows_exe_files + self.lib_files:
217 print >> ofi, r'Source: "%s"; DestDir: "{app}\%s"; Flags: ignoreversion'\
218 % (path, os.path.dirname(path))
219 print >> ofi
221 print >> ofi, r"[Icons]"
222 for path in self.windows_exe_files:
223 print >> ofi, r'Name: "{group}\%s"; Filename: "{app}\%s"' % \
224 (self.name, path)
225 print >> ofi, 'Name: "{group}\Uninstall %s"; Filename: "{uninstallexe}"' % self.name
227 def compile(self):
228 try:
229 import ctypes
230 except ImportError:
231 try:
232 import win32api
233 except ImportError:
234 import os
235 os.startfile(self.pathname)
236 else:
237 print "Ok, using win32api."
238 win32api.ShellExecute(0, "compile",
239 self.pathname,
240 None,
241 None,
243 else:
244 print "Cool, you have ctypes installed."
245 res = ctypes.windll.shell32.ShellExecuteA(0, "compile",
246 self.pathname,
247 None,
248 None,
250 if res < 32:
251 raise RuntimeError, "ShellExecute failed, error %d" % res
255 class build_installer(py2exe.build_exe.py2exe):
256 # This class first builds the exe file(s), then creates a Windows installer.
257 # You need InnoSetup for it.
258 def run(self):
259 # First, let py2exe do it's work.
260 py2exe.build_exe.py2exe.run(self)
262 lib_dir = self.lib_dir
263 dist_dir = self.dist_dir
265 # create the Installer, using the files py2exe has created.
266 script = InnoScript("faces",
267 lib_dir,
268 dist_dir,
269 self.windows_exe_files,
270 self.lib_files,
271 version=faces.__version__)
272 print "*** creating the inno setup script***"
273 script.create()
274 print "*** compiling the inno setup script***"
275 script.compile()
278 def find_dlls(self, extensions):
279 exedir = os.path.dirname(sys.executable)
280 dlls = py2exe.build_exe.py2exe.find_dlls(self, extensions)
281 #dlls.add(os.path.join(exedir, "msvcp71.dll"))
282 #dlls.add(os.path.join(exedir, "msvcr71.dll"))
283 #dlls.add(os.path.join(exedir, "gdiplus.dll"))
284 #print "extensions", extensions
285 #print "dlls", dlls
286 #raise RuntimeError()
287 return dlls
289 except:
290 class build_installer: pass
291 pp_opt={}
294 if not help:
295 def get_data_files(unix_src, os_src):
296 names = os.listdir(os_src)
297 dir_list = []
298 file_list = []
299 for n in names:
300 name = os.path.join(os_src, n)
301 if os.path.isdir(name):
302 dir_list.extend(get_data_files(unix_src + "/" + n, name))
303 else:
304 file_list.append(name)
306 if file_list:
307 dir_list.insert(0, (unix_src, file_list))
308 return dir_list
310 if make_py2exe:
311 import glob
312 mat_data_path = matplotlib.get_data_path()
314 data_files = get_data_files("resources/faces/templates",
315 os.path.join(faces_dest_dir, "templates"))
316 data_files += get_data_files("resources/faces/gui",
317 os.path.join(faces_dest_dir,
318 "gui", "resources"))
319 data_files += get_data_files("resources/metapie",
320 os.path.join(metapie_dest_dir, "resources"))
321 data_files += get_data_files("howtos",
322 os.path.join(faces_dest_dir, "howtos"))
324 #data_files += get_data_files("resources/faces/locale",
325 # os.path.join("faces", "locale"))
326 #data_files += get_data_files("resources/metapie/locale",
327 # os.path.join("metapie", "locale"))
329 isdir = os.path.isdir
330 split = os.path.split
332 def matplot_recursive_add(path, prefix=""):
333 paths = glob.glob(os.path.join(path, "*"))
334 dirs = [ p for p in paths if isdir(p) ]
335 files = [ p for p in paths if not isdir(p) ]
336 dir, name = split(path)
337 if prefix:
338 prefix += "/%s" % name
339 else:
340 prefix = "matplotlibdata"
342 if files:
343 data_files.append((prefix, files))
345 for d in dirs:
346 matplot_recursive_add(d, prefix)
348 matplot_recursive_add(mat_data_path)
349 data_files.append((".", (os.path.join("..", "extbin", "poster.exe"),)))
351 else:
352 data_files = get_data_files("faces/templates",
353 os.path.join(faces_dest_dir, "templates"))
355 data_files += get_data_files("faces/gui/resources",
356 os.path.join(faces_dest_dir,
357 "gui", "resources"))
358 data_files += get_data_files("faces/howtos",
359 os.path.join(faces_dest_dir, "howtos"))
360 data_files += get_data_files("metapie/resources",
361 os.path.join(metapie_dest_dir, "resources"))
362 #data_files += get_data_files("faces/locale",
363 # os.path.join(faces_dest_dir, "locale"))
364 #data_files += get_data_files("metapie/locale",
365 # os.path.join(metapie_dest_dir, "locale"))
369 else:
370 data_files = []
373 long_desc="""faces is a powerful and flexible
374 project management tool. It not only offers
375 many extraordinary features like, multiple
376 resource balancing algorithms, multi scenario planing.
377 but can also be easily extended and customized.
378 Faces consists of a python class framework and a graphical
379 front-end."""
383 setup(name="faces-pm", version = faces.__version__,
384 url="http://faces.homeip.net/",
385 author="Michael Reithinger",
386 author_email="mreithinger@web.de",
387 description="Extendible project management software",
388 long_description=long_desc,
389 download_url="http://faces.homeip.net/download.html",
390 cmdclass = {"py2exe": build_installer ,
391 'install_data': used_install_data },
392 options=options,
393 windows=[pp_opt],
394 packages=["faces", "faces.gui", "faces.charting",
395 "faces.lib", "faces.tools", "metapie",
396 "faces.gui.editor",
397 "metapie.gui", "metapie.gui.wxcontrols"],
398 data_files=data_files,
399 classifiers=["Development Status :: 4 - Beta",
400 "Environment :: Console",
401 "Environment :: Win32 (MS Windows)",
402 "Environment :: X11 Applications",
403 "Intended Audience :: Other Audience",
404 "Intended Audience :: Developers",
405 "License :: OSI Approved :: GNU General Public License (GPL)",
406 "Operating System :: OS Independent",
407 "Topic :: Office/Business",
408 "Topic :: Office/Business :: Scheduling",
409 "Topic :: Software Development" ],
410 scripts=['bin/faces'],
411 # install_requires=[ 'matplotlib>=0.87.2' ]
412 # 'wxPython>=2.6.0',
413 # 'Cheetah>=2.0' ],
416 if making_dist:
417 remove_tree(faces_dest_dir)
418 remove_tree(metapie_dest_dir)