/[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 452 - (hide annotations)
Tue Mar 4 11:31:04 2003 UTC (22 years ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 37546 byte(s)
(thuban_build_py.build): Add a comment about distutils in
Python 2.3 containing some of the functionality we implement in
setup.py ourselves.

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