/[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 1698 - (hide annotations)
Mon Sep 1 16:26:26 2003 UTC (21 years, 6 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 41531 byte(s)
(data_files): Add the .mo files
(setup call): Up to version 0.9.0

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