/[thuban]/branches/WIP-pyshapelib-bramz/setup.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/setup.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 209 - (hide annotations)
Tue Jul 9 16:17:32 2002 UTC (22 years, 8 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 35272 byte(s)
	* setup.py: In the setup call, use the thuban homepage as the
	value of the url parameter.

1 bh 86 # Copyright (c) 2001, 2002 by Intevation GmbH
2 bh 6 # Authors:
3     # Bernhard Herzog <[email protected]>
4     #
5     # This program is free software under the GPL (>=v2)
6     # Read the file COPYING coming with Thuban for details.
7    
8     """Distutils setup script for Thuban."""
9    
10     __version__ = "$Revision$"
11    
12     # Configuration:
13     #
14     # depending on your platform you may have to configure some variables by
15     # hand below.
16     #
17    
18     import os
19 bh 15 from types import TupleType
20 bh 6 from distutils.core import setup, Extension, Command
21 bh 204 from distutils.command.install import install, INSTALL_SCHEMES, subst_vars
22 bh 6 from distutils.command.build_py import build_py
23 bh 19 from distutils.command.bdist_rpm import bdist_rpm
24 bh 15 from distutils.file_util import write_file
25 bh 67 from distutils.filelist import FileList
26 bh 18 from distutils.util import convert_path, change_root
27 bh 6
28 bh 67 from distutils import archive_util, dir_util
29 bh 6 import distutils
30    
31     from string import split
32     import string
33    
34     if os.name == "posix":
35     ###################################################################
36     # Posix configuration. Adapt this if you're running some kind of
37     # Unix like system.
38    
39     # Directories where Proj4 is installed
40     proj4_prefix = "/usr/local/"
41     proj4_incdir = os.path.join(proj4_prefix, "include")
42     proj4_libdir = os.path.join(proj4_prefix, "lib")
43     proj4_lib = "proj"
44    
45    
46     # You shpuldn't have to modify anything below here
47     ###################################################################
48    
49     # The installation prefix (similar to autoconf's --prefix). This is
50     # only the default value, you can override it on the command line
51 bh 203 # with the install command's --prefix option.
52     #
53     # Note that there's a separate prefix option for the bdist_rpm
54     # command completely independend of this one.
55 bh 6 prefix = "/usr/local/"
56    
57     # On POSIX-systems we run wxgtk-config to determine the C++-compiler
58     # flags
59 bh 19 wx_config_script = "wx-config"
60 bh 6 # These lists will be filled automatically below
61     wx_defs = []
62     wx_incdirs = []
63     wx_libdirs = []
64     wx_libs = []
65    
66     elif os.name == "nt":
67     #################################################################
68     # Windows configuration.
69     #
70    
71     # Directories where Proj4 is installed
72     proj4_prefix = r"D:\cygwin\home\user\proj-4.4.3\src"
73     proj4_incdir = proj4_prefix
74     proj4_libdir = proj4_prefix
75     proj4_lib = "proj_i"
76    
77 bh 15 # Define include and lib directories for wxWindows and
78     wx_prefix = r"D:\wx230"
79     wx_inc = os.path.join(wx_prefix, "include")
80     wx_lib = os.path.join(wx_prefix, "lib")
81    
82 bh 6 #
83     # Unless you use a wxPython version other than 2.3.1, you probably
84     # shouldn't have to modify anything below here
85     ##################################################################
86    
87     # Installation prefix. Just install relative to current directory by
88     # default. This is only the default value, you can override it on
89     # the command line with the install command's --prefix option
90     prefix = r"install"
91    
92     # There doesn't seem to be an easy way to get at the wx compiler
93     # flags, so we define them here. These flags work for us with
94     # wxPython 2.3.1. They may have to be modified for other versions.
95    
96     # there's no config script.
97     wx_config_script = ""
98    
99     # the values of wx_defs and wx_libs. copied from the wxPython
100     # setup.py
101     wx_defs = [ ('WIN32', None), # Some of these are no longer
102     ('__WIN32__', None), # necessary. Anybody know which?
103     ('_WINDOWS', None),
104     ('__WINDOWS__', None),
105     ('WINVER', '0x0400'),
106     ('__WIN95__', None),
107     ('STRICT', None),
108    
109     ('__WXMSW__', None),
110     ('WXUSINGDLL', '1'),
111    
112     ('SWIG_GLOBAL', None),
113     ('HAVE_CONFIG_H', None),
114     ('WXP_USE_THREAD', '1'),
115     ]
116    
117     wx_incdirs = [wx_inc]
118     wx_libdirs = [wx_lib]
119     wx_libs = ["wx23_1h"]
120     wx_libs = wx_libs + ['kernel32', 'user32', 'gdi32', 'comdlg32',
121     'winspool', 'winmm', 'shell32', 'oldnames',
122     'comctl32', 'ctl3d32', 'odbc32', 'ole32', 'oleaut32',
123     'uuid', 'rpcrt4', 'advapi32', 'wsock32']
124     else:
125     raise RuntimeError("Unsupported platform " + os.name)
126    
127    
128     ######################################################################
129     #
130     # There's nothing beyond this point that has to be modified for a
131     # normal installation
132     #
133     ######################################################################
134    
135    
136     #
137     # Functions to determine wxWindows config on POSIX systems
138     #
139    
140     def run_script(cmdline):
141     """Run command and return its stdout or none in case of errors"""
142     pipe = os.popen(cmdline)
143     result = pipe.read()
144     if pipe.close() is not None:
145     print '"' + cmdline + '"', 'failed'
146     return None
147     return result
148    
149    
150     def run_wx_script(command):
151 bh 19 # first, determine the C++ preprocessor flags Use --cflags here
152     # because it seems that older version don't have --cxxflags and
153     # newer ones return the same result for both
154     flags = run_script(command + ' --cflags ')
155 bh 6 if flags is None:
156     return 0
157     for flag in split(flags):
158     start = flag[:2]
159     value = flag[2:]
160     if start == "-I":
161     wx_incdirs.append(value)
162     elif start == "-D":
163     wx_defs.append((value, None))
164    
165     # determine the library flags
166     flags = run_script(command + ' --libs')
167     if flags is None:
168     return 0
169     for flag in split(flags):
170     start = flag[:2]
171     value = flag[2:]
172     if start == "-L":
173     wx_libdirs.append(value)
174     elif start == "-l":
175     wx_libs.append(value)
176    
177     if wx_config_script:
178     # if there's a wx config script, run it to determine the configuration
179     run_wx_script(wx_config_script)
180    
181    
182    
183     #
184     # Define some extension and python modules
185     #
186     # The C-extension names are prefixed woth "Lib." so they get put into
187     # the Lib/ subdirectory. Lib/ is not really a package but distutils
188     # doesn't care
189    
190     # subdirectory containing the extensions
191     ext_dir = "extensions"
192    
193     # subdirectory with some shapelib files
194     shp_dir = ext_dir + "/shapelib"
195    
196     # lists to fill with the module descriptions
197     extensions = []
198     py_modules = []
199    
200    
201     #
202     # Thuban specific modules
203     #
204    
205     extensions.append(Extension("Lib.wxproj",
206 bh 97 [ext_dir + "/thuban/wxproj.cpp"],
207     include_dirs = ([shp_dir, proj4_incdir,
208     ext_dir + "/pyshapelib/"]
209     + wx_incdirs),
210 bh 6 define_macros = wx_defs,
211     library_dirs = [proj4_libdir] + wx_libdirs,
212     libraries = [proj4_lib] + wx_libs))
213    
214     #
215     # shapelib wrappers are also distributed with thuban
216     #
217    
218     extensions.append(Extension("Lib.shapelibc",
219     [ext_dir + "/pyshapelib/shapelib_wrap.c",
220 bh 142 shp_dir + "/shpopen.c",
221     shp_dir + "/shptree.c"],
222 bh 6 include_dirs = [shp_dir]))
223 bh 142 extensions.append(Extension("Lib.shptree",
224     [ext_dir + "/pyshapelib/shptreemodule.c"],
225     include_dirs = [shp_dir]))
226 bh 6 extensions.append(Extension("Lib.dbflibc",
227     [ext_dir + "/pyshapelib/dbflib_wrap.c",
228     shp_dir + "/dbfopen.c"],
229     include_dirs = [shp_dir]))
230 bh 164 for name in ("shapelib", "dbflib"):
231 bh 6 py_modules.append(ext_dir + "/pyshapelib/" + name)
232    
233     #
234     # PROJ4 bindings are also distributed with thuban
235     #
236     extensions.append(Extension("Lib.Projectionc",
237     [ext_dir + "/pyprojection/Projection_wrap.c"],
238     include_dirs = [proj4_incdir],
239     library_dirs = [proj4_libdir],
240     libraries = [proj4_lib]))
241     py_modules.append(ext_dir + "/pyprojection/Projection")
242    
243    
244     #
245     # Data files
246     #
247    
248     data_files = []
249    
250     # bitmaps
251 bh 15 dir = "Resources/Bitmaps"
252 bh 6 bitmaps = []
253     for file in os.listdir(os.path.join("Resources", "Bitmaps")):
254     if string.lower(file[-4:]) == ".xpm":
255 bh 15 bitmaps.append(dir + '/' + file)
256 bh 6 data_files.append((dir, bitmaps))
257    
258     #
259     # Command definitions
260     #
261     # So far distutils are only meant to distribute python extensions, not
262     # complete applications, so we have to redefine a few commands
263 bh 67 #
264 bh 6
265    
266 bh 67 # Much of the data_dist command is directly copied from the distutils'
267     # sdist command
268     class data_dist(Command):
269 bh 6
270 bh 67 description = "create a data distribution (tarball, zip file, etc.)"
271    
272     user_options = [
273     ('formats=', None,
274     "formats for source distribution (comma-separated list)"),
275     ('keep-temp', 'k',
276     "keep the distribution tree around after creating " +
277     "archive file(s)"),
278     ('dist-dir=', 'd',
279     "directory to put the source distribution archive(s) in "
280     "[default: dist]"),
281     ]
282    
283     boolean_options = ['keep-temp']
284    
285     def initialize_options (self):
286     self.formats = None
287     self.keep_temp = 0
288     self.dist_dir = None
289    
290     def finalize_options (self):
291     self.ensure_string_list('formats')
292     if self.formats is None:
293     self.formats = ["zip"]
294     bad_format = archive_util.check_archive_formats(self.formats)
295     if bad_format:
296     raise DistutilsOptionError, \
297     "unknown archive format '%s'" % bad_format
298    
299     if self.dist_dir is None:
300     self.dist_dir = "dist"
301    
302    
303     def run(self):
304     # 'filelist' contains the list of files that will make up the
305     # manifest
306     self.filelist = FileList()
307    
308     # Do whatever it takes to get the list of files to process.
309     # File list is accumulated in 'self.filelist'.
310     self.get_file_list()
311    
312     # Otherwise, go ahead and create the source distribution tarball,
313     # or zipfile, or whatever.
314     self.make_distribution()
315    
316     def get_file_list(self):
317     """Figure out the list of files to include in the data
318     distribution, and put it in 'self.filelist'.
319     """
320     self.filelist.findall("Data")
321     self.filelist.include_pattern("*", anchor = 0)
322     self.filelist.exclude_pattern(r'/(RCS|CVS)/.*', is_regex=1)
323     self.filelist.sort()
324     self.filelist.remove_duplicates()
325    
326     def make_release_tree(self, base_dir, files):
327     """Create the directory tree that will become the source
328     distribution archive. All directories implied by the filenames in
329     'files' are created under 'base_dir', and then we hard link or copy
330     (if hard linking is unavailable) those files into place.
331     Essentially, this duplicates the developer's source tree, but in a
332     directory named after the distribution, containing only the files
333     to be distributed.
334     """
335     # Create all the directories under 'base_dir' necessary to
336     # put 'files' there; the 'mkpath()' is just so we don't die
337     # if the manifest happens to be empty.
338     self.mkpath(base_dir)
339     dir_util.create_tree(base_dir, files,
340     verbose=self.verbose, dry_run=self.dry_run)
341    
342     # And walk over the list of files, either making a hard link (if
343     # os.link exists) to each one that doesn't already exist in its
344     # corresponding location under 'base_dir', or copying each file
345     # that's out-of-date in 'base_dir'. (Usually, all files will be
346     # out-of-date, because by default we blow away 'base_dir' when
347     # we're done making the distribution archives.)
348    
349     if hasattr(os, 'link'): # can make hard links on this system
350     link = 'hard'
351     msg = "making hard links in %s..." % base_dir
352     else: # nope, have to copy
353     link = None
354     msg = "copying files to %s..." % base_dir
355    
356     if not files:
357     self.warn("no files to distribute -- empty manifest?")
358     else:
359     self.announce(msg)
360     for file in files:
361     if not os.path.isfile(file):
362     self.warn("'%s' not a regular file -- skipping" % file)
363     else:
364     dest = os.path.join(base_dir, file)
365     self.copy_file(file, dest, link=link)
366    
367    
368     def make_distribution (self):
369     """Create the source distribution(s). First, we create the release
370     tree with 'make_release_tree()'; then, we create all required
371     archive files (according to 'self.formats') from the release tree.
372     Finally, we clean up by blowing away the release tree (unless
373     'self.keep_temp' is true). The list of archive files created is
374     stored so it can be retrieved later by 'get_archive_files()'.
375     """
376     # Don't warn about missing meta-data here -- should be (and is!)
377     # done elsewhere.
378     base_dir = "Thuban-data-" + self.distribution.get_version()
379     base_name = os.path.join(self.dist_dir, base_dir)
380    
381     self.make_release_tree(base_dir, self.filelist.files)
382     archive_files = [] # remember names of files we create
383     for fmt in self.formats:
384     file = self.make_archive(base_name, fmt, base_dir=base_dir)
385     archive_files.append(file)
386    
387     self.archive_files = archive_files
388    
389     if not self.keep_temp:
390     dir_util.remove_tree(base_dir, self.verbose, self.dry_run)
391    
392    
393    
394 bh 6 class InstallLocal(Command):
395    
396     """
397     A new install command to just link (or copy, on non-POSIX systems)
398     the extension modules to the top directory so that Thuban can be run
399     directly from the source dir.
400     """
401    
402     description =\
403 bh 71 "Create some symlinks so you can run thuban from the source directory"
404 bh 6
405     user_options = [
406     ('skip-build', None, "skip the build steps"),
407     ]
408    
409     def initialize_options (self):
410     self.extensions = None
411     self.build_dir = None
412     self.skip_build = None
413    
414     def finalize_options (self):
415     self.set_undefined_options("install",
416     ("build_lib", "build_dir"),
417     ('skip_build', 'skip_build'))
418     self.extensions = self.distribution.ext_modules
419    
420     def run(self):
421     # Make sure we have built everything we need first
422     self.build()
423    
424     # now do the work. Simply link or copy the Lib dir
425     libdir = os.path.join(self.build_dir, "Lib")
426     if os.name == "posix":
427 bh 71 # on posix, just link the Lib dir
428 bh 6 self.link_dir(libdir, "Lib")
429     else:
430     self.copy_tree(libdir, "Lib")
431    
432     def link_dir(self, src, dest):
433     """Create a symbolic link dest pointing to src"""
434     if self.verbose:
435 bh 15 self.announce("symlinking %s -> %s" % (src, dest))
436 bh 6 if self.dry_run:
437     return
438    
439     if not (os.path.exists(dest) and os.path.samefile(src, dest)):
440     os.symlink(src, dest)
441    
442     def build (self):
443     if not self.skip_build:
444     if self.distribution.has_pure_modules():
445     self.run_command('build_py')
446     if self.distribution.has_ext_modules():
447     self.run_command('build_ext')
448    
449    
450    
451     class thuban_build_py(build_py):
452    
453     """
454 bh 8 A new build_py that can deal with both packages and modules in one
455     distribution.
456 bh 6 """
457    
458     def run(self):
459 bh 8 """The same the as the original in build_py revision 1.33 except
460 bh 6 that this allows both packages and modules to be in one
461     distribution
462     """
463     if not self.py_modules and not self.packages:
464     return
465    
466     # Now we're down to two cases: 'py_modules' only and 'packages' only.
467     if self.py_modules:
468     self.build_modules()
469     if self.packages:
470     self.build_packages()
471    
472     self.byte_compile(self.get_outputs(include_bytecode=0))
473    
474     def find_modules (self):
475     """Thuban specific version of build_py.find_modules. Unlike the
476     original version, we assume that the modules in self.py_modules
477     can contain directories and are all to be placed into the same
478     subdirectory, Lib, in the build directory. This is achieved by
479     returning the modules as a list (package, module, filename)
480     where package is 'Lib', module is the basename of the module name
481     and filename is the filename relative to the package root.
482     """
483     modules = []
484     for module in self.py_modules:
485     module_base = os.path.basename(module)
486     module_file = module + ".py"
487     if not self.check_module(module, module_file):
488     continue
489    
490     modules.append(("Lib", module_base, module_file))
491     return modules
492    
493 bh 15 def find_all_modules (self):
494     # same as find_all_modules of the original build_py command
495     # (rev. 1.33) but handle installations with both modules and
496     # packages. Needed here so tha the get_outputs works correctly
497     modules = []
498     if self.py_modules:
499     modules.extend(self.find_modules())
500     if self.packages:
501     for package in self.packages:
502     package_dir = self.get_package_dir(package)
503     m = self.find_package_modules(package, package_dir)
504     modules.extend(m)
505 bh 6
506 bh 15 return modules
507    
508    
509 bh 204 thubaninit_contents = """
510     # This module was automatically generated by Thuban's install script
511     '''Import this module once per program (best place is probably the file
512     that ends up as your __main__ module) to be able to import Thuban
513     afterwards.
514 bh 15
515 bh 204 Usage:
516    
517     import thubaninit
518     import Thuban
519     '''
520     import sys, os
521     sys.path.insert(0, %(thubandir)s)
522    
523     # Put the Lib dir into the path. The Lib dir contains some extra Python
524     # modules
525     import Thuban
526     thubandir = os.path.join(Thuban.__path__[0], '..')
527     dir = os.path.join(thubandir, "Lib")
528     if os.path.isdir(dir):
529     sys.path.insert(0, dir)
530     """
531    
532    
533 bh 6 class ThubanInstall(install):
534    
535 bh 8 """
536     Thuban specific install command.
537    
538     Extend the standard install command to symlink the installed script
539     to $prefix/bin/
540     """
541 bh 15
542     user_options = install.user_options[:]
543     user_options.extend([("do-symlink", None,
544     "Create a symlink to the script in <prefix>/bin."
545     "(default on posix systems and only relevant there)"),
546    
547     ("extra-files", None,
548 bh 204 "List of filenames or (src, dest) pairs describing"
549 bh 15 " extra files to install "
550     "(can only be set from witin setup.py"),
551 bh 204
552     ("create-init-module", None,
553     "Create a module in the site-packages directory that"
554     " tweaks sys.path to let you easily import thuban"
555     " modules from outside of thuban."),
556     ("init-module-dir", None,
557     "Directory in which to create the init module."
558     " Defaults to Python's site-packages directory."),
559    
560 bh 15 ])
561    
562     boolean_options = install.boolean_options[:]
563     boolean_options.append("do-symlink")
564 bh 204 boolean_options.append("create-init-module")
565 bh 15
566     def initialize_options(self):
567     self.do_symlink = None
568     self.extra_files = []
569 bh 204 self.create_init_module = 1
570     self.init_module_dir = None
571 bh 15 install.initialize_options(self)
572    
573     def finalize_options(self):
574     if self.do_symlink is None:
575     if os.name == "posix":
576     self.do_symlink = 1
577     else:
578     self.do_symlink = 0
579     install.finalize_options(self)
580 bh 204 self.expand_with_pure_python_dirs(["init_module_dir"])
581 bh 15
582 bh 204 def expand_with_pure_python_dirs(self, attrs):
583     """Expand the attributes with default values of base and platbase"""
584     # it seems that the values for "prefix" and "exec_prefix" in
585     # self.config_vars are the corresponding values used by the
586     # python interpreter, so we just assign these to "base" and
587     # "platbase".
588     config_vars = self.config_vars.copy()
589     config_vars["base"] = self.config_vars["prefix"]
590     config_vars["platbase"] = self.config_vars["exec_prefix"]
591     for attr in attrs:
592     val = getattr(self, attr)
593     if val is not None:
594     if os.name == 'posix':
595     val = os.path.expanduser(val)
596     val = subst_vars(val, config_vars)
597     setattr(self, attr, val)
598    
599     def select_scheme(self, scheme):
600     """Extend the inherited method to set init_module_dir"""
601     install.select_scheme(self, scheme)
602     # only set init_module_dir if it wasn't set by the user
603     if self.init_module_dir is None:
604     self.init_module_dir = INSTALL_SCHEMES[scheme]['purelib']
605    
606     def convert_paths(self, *args):
607     """Extend the inherited method so that we can remember some filename
608     """
609     # remember the installation directory before its root gets
610     # changed
611     self.install_lib_orig = self.install_lib
612     apply(install.convert_paths, (self,) + args)
613    
614 bh 6 def run(self):
615     install.run(self)
616 bh 15 for item in self.extra_files:
617     if type(item) == TupleType:
618     src, dest = item
619     else:
620     src = dest = item
621     self.copy_file(convert_path(src),
622     os.path.join(self.root, convert_path(dest)))
623    
624     if os.name == "posix" and self.do_symlink:
625 bh 19 install_scripts = self.install_scripts
626     if self.root:
627     install_scripts = install_scripts[len(self.root):]
628     scriptfile = os.path.join(install_scripts, "thuban.py")
629 bh 6 bindir = os.path.join(self.prefix, "bin")
630 bh 18 if self.root:
631     bindir = change_root(self.root, bindir)
632 bh 6 binfile = os.path.join(bindir, "thuban")
633     self.mkpath(bindir)
634 bh 19 self.link_file(scriptfile, binfile)
635 bh 6
636 bh 204 if self.create_init_module:
637     # create the init module
638     initfilename = self.thuban_init_filename()
639     if self.root:
640     initfilename = change_root(self.root, initfilename)
641     contents = thubaninit_contents % {
642     "thubandir": repr(self.install_lib_orig)
643     }
644     self.mkpath(os.path.dirname(initfilename))
645     self.execute(write_file, (initfilename, split(contents, "\n")),
646     "Create %s" % initfilename)
647    
648 bh 19 def link_file(self, src, dest):
649     """Create a symbolic link dest pointing to src.
650    
651     Unlike the symlink variant of the command object's copy_file
652     method, this method even performs the link if src doesn't exist.
653     This is useful when installing with an alternat root directory"""
654     if self.verbose:
655     self.announce("symlinking %s -> %s" % (src, dest))
656     if self.dry_run:
657     return
658    
659     if not os.path.exists(dest):
660     os.symlink(src, dest)
661    
662 bh 204 def thuban_init_filename(self):
663     """Return the filename for the init-module"""
664     # Since we override the normal install dirs to point to our own
665     # prefix we have to reach into installed
666     return self.init_module_dir + "/thubaninit.py"
667 bh 19
668 bh 15 def get_outputs (self):
669     outputs = install.get_outputs(self)
670     for item in self.extra_files:
671     if type(item) == TupleType:
672     src, dest = item
673     else:
674     src = dest = item
675     outputs.append(os.path.join(self.root, convert_path(dest)))
676 bh 19 if os.name == "posix" and self.do_symlink:
677     bindir = os.path.join(self.prefix, "bin")
678     if self.root:
679     bindir = change_root(self.root, bindir)
680     binfile = os.path.join(bindir, "thuban")
681     outputs.append(binfile)
682 bh 204 if self.create_init_module:
683     initfilename = self.thuban_init_filename()
684     if self.root:
685     initfilename = change_root(self.root, initfilename)
686     outputs.append(initfilename)
687 bh 15 return outputs
688 bh 6
689 bh 19
690 bh 203 # scripts to override some of the commands put into the spec-file by the
691     # bdist_rpm command.
692    
693 bh 19 bdist_rpm_prep_script = '''
694     %setup
695     cp extensions/pyshapelib/{README,README.pyshapelib}
696     cp extensions/pyshapelib/{COPYING,COPYING.pyshapelib}
697     cp extensions/pyprojection/{LICENSE,LICENSE.pyprojection}
698     '''
699    
700 bh 203 bdist_rpm_install_script = '''
701     %(python)s setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES \
702     --prefix=%(prefix)s
703     '''
704 bh 19
705    
706     class thuban_bdist_rpm(bdist_rpm):
707    
708     """Thuban specific RPM distribution command"""
709    
710 bh 203 user_options = bdist_rpm.user_options[:]
711     user_options.extend([("prefix=", None, "Install prefix for the RPM"),
712     ])
713    
714 bh 90 def initialize_options(self):
715 bh 203 # per default, RPMs are installed in /usr
716     self.prefix = "/usr/"
717 bh 19
718 bh 203 # create the scripts we want to override. We actually fill them
719     # with contents later because some values we put into those
720     # scripts such as the python interpreter to use are only known
721     # then.
722     open("bdist_rpm_prep", "w").close()
723     open("bdist_rpm_install", "w").close()
724 bh 90 bdist_rpm.initialize_options(self)
725 bh 19
726 bh 203 def _make_spec_file(self):
727     # create the scripts for the spec-file. Now we know the python
728     # interpreter to use.
729     open("bdist_rpm_prep", "w").write(bdist_rpm_prep_script)
730     install = bdist_rpm_install_script % {"python": self.python,
731     "prefix": self.prefix}
732     open("bdist_rpm_install", "w").write(install)
733 bh 19
734 bh 203 #
735     return bdist_rpm._make_spec_file(self)
736    
737    
738 bh 15 class bdist_inno(Command):
739    
740     """Command to create a windows installer with Inno Setup"""
741    
742     description = "Create a windows installer with Inno Setup"
743    
744     user_options = [
745     ('skip-build', None, "skip the build steps"),
746     ('bdist-dir=', None,
747     "temporary directory for creating the distribution"),
748     ('run-inno', None,
749     "Run inno-setup to create the installer. On by default on nt"),
750     ('iss-name', None,
751     "The name of the iss file to generate. "
752     "Shouldn't contain directories"),
753    
754     # Parameters for the Inno Setup script
755     ('copyright', None, "Copyright notice for the Inno Setup file"),
756     ('default-dir-name', None,
757     "Default installation directory. Defaults to '{pf}\\<name>'"),
758     ('default-group-name', None,
759     "Default program group name. Defaults to <name>'"),
760     ("license-file", None, "File containing the license."),
761     ("output-basename", None,
762     "Base filename for the Inno Setup output "
763     "(defaults to <name>-<version>-<issrevision>)."),
764     ("iss-revision", None,
765     "revision of the generated installer of the package version"),
766    
767     ("icons-entries", None,
768     "List if InnoIconItems "
769     "(this can only be set from inside the setup.py script)"),
770     ]
771    
772     boolean_options = ["do-symlink"]
773    
774     def initialize_options(self):
775     self.skip_build = 0
776     self.bdist_dir = None
777     self.run_inno = None
778     self.iss_name = None
779     self.copyright = ""
780     self.default_dir_name = None
781     self.default_group_name = None
782     self.license_file = None
783     self.output_basename = None
784     self.iss_revision = None
785     self.icons_entries = []
786    
787     def finalize_options(self):
788     self.set_undefined_options("install",
789     ('skip_build', 'skip_build'))
790     if self.bdist_dir is None:
791     bdist_base = self.get_finalized_command('bdist').bdist_base
792     self.bdist_dir = os.path.join(bdist_base, 'inno')
793    
794     if self.run_inno is None:
795     self.run_inno = os.name == "nt"
796    
797     name = self.distribution.get_name()
798     if self.iss_name is None:
799     self.iss_name = name + '.iss'
800    
801     if self.default_dir_name is None:
802     self.default_dir_name = "{pf}\\" + name
803     if self.default_group_name is None:
804     self.default_group_name = name
805    
806     if self.iss_revision is None:
807     self.iss_revision = 0
808     if self.output_basename is None:
809     self.output_basename = "%s-%s-%d" \
810     % (name, self.distribution.get_version(),
811     self.iss_revision)
812    
813     def run(self, install_options = None):
814     """Execute the command. install_options if given, should be a
815     directory of additional options to set in the install step"""
816     # Obviously have to build before we can install
817     if not self.skip_build:
818     self.run_command('build')
819    
820     # Install in a temporary directory
821     install = self.reinitialize_command('install')
822     install.root = self.bdist_dir
823     if install_options is not None:
824     for key, value in install_options.items():
825     setattr(install, key, value)
826     if os.name != 'nt':
827     # Must force install to use the 'nt' scheme;
828     install.select_scheme('nt')
829    
830     self.announce("installing to %s" % self.bdist_dir)
831     install.ensure_finalized()
832     install.run()
833    
834     # Create the iss file
835     iss_file = os.path.join(self.bdist_dir, self.iss_name)
836     self.execute(write_file, (iss_file, self.generate_iss()),
837     "Create Inno Setup script file %s" % iss_file)
838    
839     # and invoke
840     if self.run_inno:
841     self.spawn(["iscc", iss_file])
842    
843     def generate_iss(self):
844     """Return the contents of the iss file as list of strings, one
845     string per line"""
846    
847     # first, turn the icons entries into a more usable form
848     icons = {}
849     for item in self.icons_entries:
850     icons[item.filename] = item
851    
852     iss = []
853    
854     name = self.distribution.get_name()
855     iss.extend(["[Setup]",
856     "AppName=" + name,
857     "AppVerName=" + name + " "+self.distribution.get_version(),
858     "DefaultDirName=" + self.default_dir_name,
859     "DefaultGroupName=" + self.default_group_name,
860     ])
861     if self.copyright:
862     iss.append("AppCopyright=" + self.copyright)
863     if self.license_file:
864     iss.append("LicenseFile=" + self.license_file)
865    
866     iss.append("OutputBasefilename=" + self.output_basename)
867    
868     iss.append("")
869     iss.append("[Files]")
870    
871     install = self.get_finalized_command("install")
872     install_scripts = self.get_finalized_command("install_scripts")
873     script_files = install_scripts.get_outputs()
874     prefixlen = len(self.bdist_dir) + len(os.sep)
875     for filename in install.get_outputs():
876     filename = filename[prefixlen:]
877     icon = icons.get(filename)
878     dirname = os.path.dirname(filename)
879     if os.name != "nt":
880     # change the separators to \ on non-windos systems
881     filename = string.join(string.split(filename, os.sep), "\\")
882     dirname = string.join(string.split(dirname, os.sep), "\\")
883     line = 'Source: "%s"' % filename
884     if icon is not None:
885     # install it as defined in the icon object
886     backslash = string.rfind(icon.install_name, "\\")
887     if backslash >= 0:
888     dirname = icon.install_name[:backslash]
889     basename = icon.install_name[backslash + 1:]
890     else:
891     dirname = ""
892     basename = icon.install_name
893     line = '%s; DestDir: "%s"; DestName: "%s"' % (line, dirname,
894     basename)
895     else:
896     line = line + '; DestDir: "{app}\\%s"' % (dirname)
897     iss.append(line)
898    
899     iss.append("")
900     iss.append("[Icons]")
901     for icon in self.icons_entries:
902     line = 'Name: "{group}\\%s"; Filename: "%s";' \
903     % (icon.title, icon.install_name)
904     iss.append(line)
905    
906     return iss
907    
908    
909     class InnoIconItem:
910    
911 bh 54 """Describe one item for the start menu for the Inno Setup installer"""
912 bh 15
913     def __init__(self, filename, title, install_name = None):
914     self.filename = filename
915     self.title = title
916     if install_name is not None:
917     self.install_name = install_name
918     else:
919     self.install_name = filename
920    
921 bh 54
922 bh 15 class thuban_bdist_inno(bdist_inno):
923    
924     """Thuban specific Inno Setup stuff"""
925    
926     def run(self):
927     install_options = {
928     "prefix": ".",
929     "install_scripts": "$base",
930     "warn_dir": 0,
931     "extra_files": ["COPYING", "Lib/proj.dll"],
932     }
933 bh 54 # don't make a symlink because we're simulating windows, so
934     # that we can generate the iss-file even on Linux
935     install_options["do_symlink"] = 0
936 bh 15 bdist_inno.run(self, install_options)
937    
938    
939     #
940     # Run the script
941     #
942    
943    
944 bh 6 long_description = """\
945     Thuban is a viewer for geographic data written in Python
946     """
947    
948 bh 15 setup(name = "Thuban",
949 bh 160 version = "0.1.2",
950 bh 6 description = "Geographic data viewer",
951     long_description = long_description,
952     licence = "GPL",
953     author = "Intevation GmbH",
954     author_email = "[email protected]",
955 bh 209 url = "http://thuban.intevation.de/",
956 bh 6
957     scripts = ["thuban.py"],
958     packages = ["Thuban", "Thuban.Lib", "Thuban.Model", "Thuban.UI"],
959     ext_modules = extensions,
960     py_modules = py_modules,
961     data_files = data_files,
962    
963     # defaults for the install command
964     options = {"install":
965     # prefix defaults to python's prefix normally
966     {"prefix": prefix,
967     # make sure both libs and scripts are installed in the
968     # same directory.
969 bh 200 "install_lib": "$base/lib/thuban",
970     "install_scripts": "$base/lib/thuban",
971     "install_data": "$base/lib/thuban",
972 bh 6
973     # Don't print warning messages about the lib dir not
974     # being on Python's path. The libraries are Thuban
975     # specific and are installed just for Thuban. They'll
976     # be automatically on Python's path when Thuban is run
977     "warn_dir": 0,
978 bh 15 },
979     "bdist_inno":
980     {"icons_entries": [InnoIconItem(".\\thuban.py",
981     "Start Thuban",
982     "{app}\\thuban.pyw")],
983     "license_file": "COPYING",
984     }
985     },
986 bh 6 cmdclass = {"build_py": thuban_build_py,
987     "install_local": InstallLocal,
988 bh 15 "install": ThubanInstall,
989 bh 19 "bdist_rpm": thuban_bdist_rpm,
990 bh 67 "bdist_inno": thuban_bdist_inno,
991     "data_dist": data_dist
992 bh 15 })
993 bh 6
994 bh 15

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26