/[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 1313 - (hide annotations)
Mon Jun 30 08:54:52 2003 UTC (21 years, 8 months ago) by jonathan
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 41405 byte(s)
Fixes for installing on windows, and also to include projections

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     # The C-extension names are prefixed woth "Lib." so they get put into
234     # the Lib/ subdirectory. Lib/ is not really a package but distutils
235     # doesn't care
236    
237     # subdirectory containing the extensions
238     ext_dir = "extensions"
239    
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 jonathan 1291 # ("Resources/Locale", "Resources/Locale/*/LC_MESSAGES/*.mo")
301 jonathan 1296 for d, pattern in [("Resources/Bitmaps", "Resources/Bitmaps/*.xpm"),
302 jonathan 1313 ("Resources/Projections", "Resources/Projections/*.proj"),
303 jonathan 1296 ("Resources/XML", "Resources/XML/*.dtd")]:
304 bh 671 data_files.append((d, glob.glob(pattern)))
305 bh 6
306     #
307     # Command definitions
308     #
309     # So far distutils are only meant to distribute python extensions, not
310     # complete applications, so we have to redefine a few commands
311 bh 67 #
312 bh 6
313    
314 bh 67 # Much of the data_dist command is directly copied from the distutils'
315     # sdist command
316     class data_dist(Command):
317 bh 6
318 bh 67 description = "create a data distribution (tarball, zip file, etc.)"
319    
320     user_options = [
321     ('formats=', None,
322     "formats for source distribution (comma-separated list)"),
323     ('keep-temp', 'k',
324     "keep the distribution tree around after creating " +
325     "archive file(s)"),
326     ('dist-dir=', 'd',
327     "directory to put the source distribution archive(s) in "
328     "[default: dist]"),
329     ]
330    
331     boolean_options = ['keep-temp']
332    
333     def initialize_options (self):
334     self.formats = None
335     self.keep_temp = 0
336     self.dist_dir = None
337    
338     def finalize_options (self):
339     self.ensure_string_list('formats')
340     if self.formats is None:
341     self.formats = ["zip"]
342     bad_format = archive_util.check_archive_formats(self.formats)
343     if bad_format:
344     raise DistutilsOptionError, \
345     "unknown archive format '%s'" % bad_format
346    
347     if self.dist_dir is None:
348     self.dist_dir = "dist"
349    
350    
351     def run(self):
352     # 'filelist' contains the list of files that will make up the
353     # manifest
354     self.filelist = FileList()
355    
356     # Do whatever it takes to get the list of files to process.
357     # File list is accumulated in 'self.filelist'.
358     self.get_file_list()
359    
360     # Otherwise, go ahead and create the source distribution tarball,
361     # or zipfile, or whatever.
362     self.make_distribution()
363    
364     def get_file_list(self):
365     """Figure out the list of files to include in the data
366     distribution, and put it in 'self.filelist'.
367     """
368     self.filelist.findall("Data")
369     self.filelist.include_pattern("*", anchor = 0)
370     self.filelist.exclude_pattern(r'/(RCS|CVS)/.*', is_regex=1)
371     self.filelist.sort()
372     self.filelist.remove_duplicates()
373    
374     def make_release_tree(self, base_dir, files):
375     """Create the directory tree that will become the source
376     distribution archive. All directories implied by the filenames in
377     'files' are created under 'base_dir', and then we hard link or copy
378     (if hard linking is unavailable) those files into place.
379     Essentially, this duplicates the developer's source tree, but in a
380     directory named after the distribution, containing only the files
381     to be distributed.
382     """
383     # Create all the directories under 'base_dir' necessary to
384     # put 'files' there; the 'mkpath()' is just so we don't die
385     # if the manifest happens to be empty.
386     self.mkpath(base_dir)
387     dir_util.create_tree(base_dir, files,
388     verbose=self.verbose, dry_run=self.dry_run)
389    
390     # And walk over the list of files, either making a hard link (if
391     # os.link exists) to each one that doesn't already exist in its
392     # corresponding location under 'base_dir', or copying each file
393     # that's out-of-date in 'base_dir'. (Usually, all files will be
394     # out-of-date, because by default we blow away 'base_dir' when
395     # we're done making the distribution archives.)
396    
397     if hasattr(os, 'link'): # can make hard links on this system
398     link = 'hard'
399     msg = "making hard links in %s..." % base_dir
400     else: # nope, have to copy
401     link = None
402     msg = "copying files to %s..." % base_dir
403    
404     if not files:
405     self.warn("no files to distribute -- empty manifest?")
406     else:
407     self.announce(msg)
408     for file in files:
409     if not os.path.isfile(file):
410     self.warn("'%s' not a regular file -- skipping" % file)
411     else:
412     dest = os.path.join(base_dir, file)
413     self.copy_file(file, dest, link=link)
414    
415    
416     def make_distribution (self):
417     """Create the source distribution(s). First, we create the release
418     tree with 'make_release_tree()'; then, we create all required
419     archive files (according to 'self.formats') from the release tree.
420     Finally, we clean up by blowing away the release tree (unless
421     'self.keep_temp' is true). The list of archive files created is
422     stored so it can be retrieved later by 'get_archive_files()'.
423     """
424     # Don't warn about missing meta-data here -- should be (and is!)
425     # done elsewhere.
426     base_dir = "Thuban-data-" + self.distribution.get_version()
427     base_name = os.path.join(self.dist_dir, base_dir)
428    
429     self.make_release_tree(base_dir, self.filelist.files)
430     archive_files = [] # remember names of files we create
431     for fmt in self.formats:
432     file = self.make_archive(base_name, fmt, base_dir=base_dir)
433     archive_files.append(file)
434    
435     self.archive_files = archive_files
436    
437     if not self.keep_temp:
438     dir_util.remove_tree(base_dir, self.verbose, self.dry_run)
439    
440    
441    
442 bh 6 class InstallLocal(Command):
443    
444     """
445     A new install command to just link (or copy, on non-POSIX systems)
446     the extension modules to the top directory so that Thuban can be run
447     directly from the source dir.
448     """
449    
450     description =\
451 bh 71 "Create some symlinks so you can run thuban from the source directory"
452 bh 6
453     user_options = [
454     ('skip-build', None, "skip the build steps"),
455 bh 253 ('create-init-module', None,
456     "Create the thubaninit.py module to ease use of Thuban as a library"),
457     ('dont-create-init-module', None,
458     "Do not create the thubaninit.py module"),
459 bh 6 ]
460    
461 bh 253 boolean_options = ["create-init-module"]
462     negative_opt = {'dont-create-init-module' : 'create-init-module'}
463    
464    
465 bh 6 def initialize_options (self):
466     self.extensions = None
467     self.build_dir = None
468     self.skip_build = None
469 bh 253 self.create_init_module = None
470 bh 6
471     def finalize_options (self):
472     self.set_undefined_options("install",
473     ("build_lib", "build_dir"),
474     ('skip_build', 'skip_build'))
475     self.extensions = self.distribution.ext_modules
476 bh 253 if self.create_init_module is None:
477     # by default we create the init module
478     self.create_init_module = 1
479 bh 6
480     def run(self):
481     # Make sure we have built everything we need first
482     self.build()
483    
484     # now do the work. Simply link or copy the Lib dir
485     libdir = os.path.join(self.build_dir, "Lib")
486     if os.name == "posix":
487 bh 71 # on posix, just link the Lib dir
488 bh 6 self.link_dir(libdir, "Lib")
489     else:
490     self.copy_tree(libdir, "Lib")
491    
492 bh 253 # create the init module if desired
493     if self.create_init_module:
494     # create the init module
495     initfilename = "thubaninit.py"
496     contents = thubaninit_contents("")
497     self.execute(write_file, (initfilename, contents),
498     "Create %s" % initfilename)
499    
500 bh 6 def link_dir(self, src, dest):
501     """Create a symbolic link dest pointing to src"""
502     if self.verbose:
503 bh 15 self.announce("symlinking %s -> %s" % (src, dest))
504 bh 6 if self.dry_run:
505     return
506    
507     if not (os.path.exists(dest) and os.path.samefile(src, dest)):
508     os.symlink(src, dest)
509    
510     def build (self):
511     if not self.skip_build:
512     if self.distribution.has_pure_modules():
513     self.run_command('build_py')
514     if self.distribution.has_ext_modules():
515     self.run_command('build_ext')
516    
517    
518    
519     class thuban_build_py(build_py):
520    
521     """
522 bh 8 A new build_py that can deal with both packages and modules in one
523     distribution.
524 bh 6 """
525    
526 bh 452 # FIXME: When Thuban can rely on Python 2.3 as the oldest supported
527     # Python release we don't need to override the run and
528     # find_all_modules methods anymore. distutils will allow both python
529     # modules and packages starting with 2.3.
530    
531 bh 6 def run(self):
532 bh 8 """The same the as the original in build_py revision 1.33 except
533 bh 6 that this allows both packages and modules to be in one
534     distribution
535     """
536     if not self.py_modules and not self.packages:
537     return
538    
539     # Now we're down to two cases: 'py_modules' only and 'packages' only.
540     if self.py_modules:
541     self.build_modules()
542     if self.packages:
543     self.build_packages()
544    
545     self.byte_compile(self.get_outputs(include_bytecode=0))
546    
547     def find_modules (self):
548     """Thuban specific version of build_py.find_modules. Unlike the
549     original version, we assume that the modules in self.py_modules
550     can contain directories and are all to be placed into the same
551     subdirectory, Lib, in the build directory. This is achieved by
552     returning the modules as a list (package, module, filename)
553     where package is 'Lib', module is the basename of the module name
554     and filename is the filename relative to the package root.
555     """
556     modules = []
557     for module in self.py_modules:
558     module_base = os.path.basename(module)
559     module_file = module + ".py"
560     if not self.check_module(module, module_file):
561     continue
562    
563     modules.append(("Lib", module_base, module_file))
564     return modules
565    
566 bh 15 def find_all_modules (self):
567     # same as find_all_modules of the original build_py command
568     # (rev. 1.33) but handle installations with both modules and
569     # packages. Needed here so tha the get_outputs works correctly
570     modules = []
571     if self.py_modules:
572     modules.extend(self.find_modules())
573     if self.packages:
574     for package in self.packages:
575     package_dir = self.get_package_dir(package)
576     m = self.find_package_modules(package, package_dir)
577     modules.extend(m)
578 bh 6
579 bh 15 return modules
580    
581    
582 bh 253 thubaninit_contents_start = """
583 bh 204 # This module was automatically generated by Thuban's install script
584     '''Import this module once per program (best place is probably the file
585     that ends up as your __main__ module) to be able to import Thuban
586     afterwards.
587 bh 15
588 bh 204 Usage:
589    
590     import thubaninit
591     import Thuban
592     '''
593     import sys, os
594 bh 253 """
595    
596     thubaninit_contents_thubaninitdir = """
597 bh 204 sys.path.insert(0, %(thubandir)s)
598 bh 253 """
599     thubaninit_contents_otherdirs = """
600 bh 204 # Put the Lib dir into the path. The Lib dir contains some extra Python
601     # modules
602     import Thuban
603     thubandir = os.path.join(Thuban.__path__[0], '..')
604     dir = os.path.join(thubandir, "Lib")
605     if os.path.isdir(dir):
606     sys.path.insert(0, dir)
607     """
608    
609 bh 253 def thubaninit_contents(thubandir):
610     """Return the contents of the the thubaninit file as a list of lines.
611 bh 204
612 bh 253 The parameter thubandir is the parent directory where the Thuban/
613     package or the empty string if the thubaninit file itself will be
614     located in that direcory as well.
615     """
616     contents = thubaninit_contents_start
617     if thubandir:
618     thubandir = repr(thubandir)
619     contents += thubaninit_contents_thubaninitdir % locals()
620     contents += thubaninit_contents_otherdirs
621     return contents.split("\n")
622    
623    
624 bh 6 class ThubanInstall(install):
625    
626 bh 8 """
627     Thuban specific install command.
628    
629     Extend the standard install command to symlink the installed script
630     to $prefix/bin/
631     """
632 bh 15
633     user_options = install.user_options[:]
634     user_options.extend([("do-symlink", None,
635     "Create a symlink to the script in <prefix>/bin."
636     "(default on posix systems and only relevant there)"),
637    
638     ("extra-files", None,
639 bh 204 "List of filenames or (src, dest) pairs describing"
640 bh 15 " extra files to install "
641 jonathan 1229 "(can only be set from within setup.py"),
642 bh 204
643 bh 212 ("create-init-module=", None,
644     "If true, create a module in the site-packages"
645     " directory that tweaks sys.path to let you easily"
646     " import thuban modules from outside of thuban."),
647     ("init-module-dir=", None,
648 bh 204 "Directory in which to create the init module."
649     " Defaults to Python's site-packages directory."),
650 bh 15 ])
651    
652     boolean_options = install.boolean_options[:]
653     boolean_options.append("do-symlink")
654 bh 204 boolean_options.append("create-init-module")
655 bh 15
656     def initialize_options(self):
657     self.do_symlink = None
658     self.extra_files = []
659 bh 212
660     # initialize the create_init_module flag from the global
661     # determined at runtime
662     self.create_init_module = create_init_module
663 bh 204 self.init_module_dir = None
664 bh 15 install.initialize_options(self)
665    
666     def finalize_options(self):
667     if self.do_symlink is None:
668     if os.name == "posix":
669     self.do_symlink = 1
670     else:
671     self.do_symlink = 0
672     install.finalize_options(self)
673 bh 204 self.expand_with_pure_python_dirs(["init_module_dir"])
674 bh 15
675 bh 204 def expand_with_pure_python_dirs(self, attrs):
676     """Expand the attributes with default values of base and platbase"""
677     # it seems that the values for "prefix" and "exec_prefix" in
678     # self.config_vars are the corresponding values used by the
679     # python interpreter, so we just assign these to "base" and
680     # "platbase".
681     config_vars = self.config_vars.copy()
682     config_vars["base"] = self.config_vars["prefix"]
683     config_vars["platbase"] = self.config_vars["exec_prefix"]
684     for attr in attrs:
685     val = getattr(self, attr)
686     if val is not None:
687     if os.name == 'posix':
688     val = os.path.expanduser(val)
689     val = subst_vars(val, config_vars)
690     setattr(self, attr, val)
691    
692     def select_scheme(self, scheme):
693     """Extend the inherited method to set init_module_dir"""
694     install.select_scheme(self, scheme)
695     # only set init_module_dir if it wasn't set by the user
696     if self.init_module_dir is None:
697     self.init_module_dir = INSTALL_SCHEMES[scheme]['purelib']
698    
699     def convert_paths(self, *args):
700     """Extend the inherited method so that we can remember some filename
701     """
702     # remember the installation directory before its root gets
703     # changed
704     self.install_lib_orig = self.install_lib
705     apply(install.convert_paths, (self,) + args)
706    
707 bh 6 def run(self):
708     install.run(self)
709 bh 15 for item in self.extra_files:
710     if type(item) == TupleType:
711     src, dest = item
712     else:
713     src = dest = item
714 bh 266 self.copy_file(convert_path(src),
715 bh 15 os.path.join(self.root, convert_path(dest)))
716    
717     if os.name == "posix" and self.do_symlink:
718 bh 19 install_scripts = self.install_scripts
719     if self.root:
720     install_scripts = install_scripts[len(self.root):]
721     scriptfile = os.path.join(install_scripts, "thuban.py")
722 bh 6 bindir = os.path.join(self.prefix, "bin")
723 bh 18 if self.root:
724     bindir = change_root(self.root, bindir)
725 bh 6 binfile = os.path.join(bindir, "thuban")
726     self.mkpath(bindir)
727 bh 19 self.link_file(scriptfile, binfile)
728 bh 6
729 bh 204 if self.create_init_module:
730     # create the init module
731     initfilename = self.thuban_init_filename()
732     if self.root:
733     initfilename = change_root(self.root, initfilename)
734 bh 266 contents = thubaninit_contents(self.install_lib_orig)
735 bh 204 self.mkpath(os.path.dirname(initfilename))
736 bh 253 self.execute(write_file, (initfilename, contents),
737 bh 204 "Create %s" % initfilename)
738    
739 bh 19 def link_file(self, src, dest):
740     """Create a symbolic link dest pointing to src.
741    
742     Unlike the symlink variant of the command object's copy_file
743     method, this method even performs the link if src doesn't exist.
744     This is useful when installing with an alternat root directory"""
745     if self.verbose:
746     self.announce("symlinking %s -> %s" % (src, dest))
747     if self.dry_run:
748     return
749    
750     if not os.path.exists(dest):
751     os.symlink(src, dest)
752    
753 bh 204 def thuban_init_filename(self):
754     """Return the filename for the init-module"""
755     # Since we override the normal install dirs to point to our own
756     # prefix we have to reach into installed
757     return self.init_module_dir + "/thubaninit.py"
758 bh 19
759 bh 15 def get_outputs (self):
760     outputs = install.get_outputs(self)
761     for item in self.extra_files:
762     if type(item) == TupleType:
763     src, dest = item
764     else:
765     src = dest = item
766     outputs.append(os.path.join(self.root, convert_path(dest)))
767 bh 19 if os.name == "posix" and self.do_symlink:
768     bindir = os.path.join(self.prefix, "bin")
769     if self.root:
770     bindir = change_root(self.root, bindir)
771     binfile = os.path.join(bindir, "thuban")
772     outputs.append(binfile)
773 bh 204 if self.create_init_module:
774     initfilename = self.thuban_init_filename()
775     if self.root:
776     initfilename = change_root(self.root, initfilename)
777     outputs.append(initfilename)
778 bh 15 return outputs
779 bh 6
780 bh 19
781 bh 203 # scripts to override some of the commands put into the spec-file by the
782     # bdist_rpm command.
783    
784 bh 19 bdist_rpm_prep_script = '''
785     %setup
786     cp extensions/pyshapelib/{README,README.pyshapelib}
787     cp extensions/pyshapelib/{COPYING,COPYING.pyshapelib}
788     cp extensions/pyprojection/{LICENSE,LICENSE.pyprojection}
789     '''
790    
791 jonathan 555 bdist_rpm_build_script = '''
792     env PATH="$PATH:%(prefix)s/lib/wxPython/bin:/usr/lib/wxPython/bin" CFLAGS="$RPM_OPT_FLAGS" %(python)s setup.py build
793     '''
794    
795 bh 203 bdist_rpm_install_script = '''
796     %(python)s setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES \
797     --prefix=%(prefix)s
798     '''
799 bh 19
800 bh 266
801 bh 19 class thuban_bdist_rpm(bdist_rpm):
802    
803     """Thuban specific RPM distribution command"""
804    
805 bh 203 user_options = bdist_rpm.user_options[:]
806     user_options.extend([("prefix=", None, "Install prefix for the RPM"),
807     ])
808    
809 bh 90 def initialize_options(self):
810 bh 203 # per default, RPMs are installed in /usr
811     self.prefix = "/usr/"
812 bh 19
813 bh 203 # create the scripts we want to override. We actually fill them
814     # with contents later because some values we put into those
815     # scripts such as the python interpreter to use are only known
816     # then.
817     open("bdist_rpm_prep", "w").close()
818 jonathan 555 open("bdist_rpm_build", "w").close()
819 bh 203 open("bdist_rpm_install", "w").close()
820 bh 90 bdist_rpm.initialize_options(self)
821 bh 19
822 bh 203 def _make_spec_file(self):
823     # create the scripts for the spec-file. Now we know the python
824     # interpreter to use.
825     open("bdist_rpm_prep", "w").write(bdist_rpm_prep_script)
826 jonathan 555
827     build = bdist_rpm_build_script % {"python": self.python,
828     "prefix": self.prefix}
829     open("bdist_rpm_build", "w").write(build)
830    
831 bh 203 install = bdist_rpm_install_script % {"python": self.python,
832     "prefix": self.prefix}
833     open("bdist_rpm_install", "w").write(install)
834 bh 19
835 bh 203 #
836     return bdist_rpm._make_spec_file(self)
837    
838    
839 bh 15 class bdist_inno(Command):
840    
841     """Command to create a windows installer with Inno Setup"""
842    
843     description = "Create a windows installer with Inno Setup"
844    
845     user_options = [
846     ('skip-build', None, "skip the build steps"),
847     ('bdist-dir=', None,
848     "temporary directory for creating the distribution"),
849     ('run-inno', None,
850     "Run inno-setup to create the installer. On by default on nt"),
851     ('iss-name', None,
852     "The name of the iss file to generate. "
853     "Shouldn't contain directories"),
854    
855     # Parameters for the Inno Setup script
856     ('copyright', None, "Copyright notice for the Inno Setup file"),
857     ('default-dir-name', None,
858     "Default installation directory. Defaults to '{pf}\\<name>'"),
859     ('default-group-name', None,
860     "Default program group name. Defaults to <name>'"),
861     ("license-file", None, "File containing the license."),
862     ("output-basename", None,
863     "Base filename for the Inno Setup output "
864     "(defaults to <name>-<version>-<issrevision>)."),
865     ("iss-revision", None,
866     "revision of the generated installer of the package version"),
867    
868     ("icons-entries", None,
869     "List if InnoIconItems "
870     "(this can only be set from inside the setup.py script)"),
871     ]
872    
873     boolean_options = ["do-symlink"]
874    
875     def initialize_options(self):
876     self.skip_build = 0
877     self.bdist_dir = None
878     self.run_inno = None
879     self.iss_name = None
880     self.copyright = ""
881     self.default_dir_name = None
882     self.default_group_name = None
883     self.license_file = None
884     self.output_basename = None
885     self.iss_revision = None
886     self.icons_entries = []
887    
888     def finalize_options(self):
889     self.set_undefined_options("install",
890     ('skip_build', 'skip_build'))
891     if self.bdist_dir is None:
892     bdist_base = self.get_finalized_command('bdist').bdist_base
893     self.bdist_dir = os.path.join(bdist_base, 'inno')
894    
895     if self.run_inno is None:
896     self.run_inno = os.name == "nt"
897    
898     name = self.distribution.get_name()
899     if self.iss_name is None:
900     self.iss_name = name + '.iss'
901    
902     if self.default_dir_name is None:
903     self.default_dir_name = "{pf}\\" + name
904     if self.default_group_name is None:
905     self.default_group_name = name
906    
907     if self.iss_revision is None:
908     self.iss_revision = 0
909     if self.output_basename is None:
910     self.output_basename = "%s-%s-%d" \
911     % (name, self.distribution.get_version(),
912     self.iss_revision)
913    
914     def run(self, install_options = None):
915     """Execute the command. install_options if given, should be a
916     directory of additional options to set in the install step"""
917     # Obviously have to build before we can install
918 jonathan 533
919 bh 15 if not self.skip_build:
920     self.run_command('build')
921    
922     # Install in a temporary directory
923     install = self.reinitialize_command('install')
924     install.root = self.bdist_dir
925     if install_options is not None:
926     for key, value in install_options.items():
927     setattr(install, key, value)
928     if os.name != 'nt':
929     # Must force install to use the 'nt' scheme;
930     install.select_scheme('nt')
931    
932     self.announce("installing to %s" % self.bdist_dir)
933     install.ensure_finalized()
934     install.run()
935    
936     # Create the iss file
937     iss_file = os.path.join(self.bdist_dir, self.iss_name)
938     self.execute(write_file, (iss_file, self.generate_iss()),
939     "Create Inno Setup script file %s" % iss_file)
940    
941 bh 266 # and invoke
942 bh 15 if self.run_inno:
943     self.spawn(["iscc", iss_file])
944    
945     def generate_iss(self):
946     """Return the contents of the iss file as list of strings, one
947     string per line"""
948    
949     # first, turn the icons entries into a more usable form
950     icons = {}
951     for item in self.icons_entries:
952     icons[item.filename] = item
953    
954     iss = []
955    
956     name = self.distribution.get_name()
957     iss.extend(["[Setup]",
958     "AppName=" + name,
959     "AppVerName=" + name + " "+self.distribution.get_version(),
960     "DefaultDirName=" + self.default_dir_name,
961     "DefaultGroupName=" + self.default_group_name,
962     ])
963     if self.copyright:
964     iss.append("AppCopyright=" + self.copyright)
965     if self.license_file:
966     iss.append("LicenseFile=" + self.license_file)
967    
968     iss.append("OutputBasefilename=" + self.output_basename)
969    
970     iss.append("")
971     iss.append("[Files]")
972    
973     install = self.get_finalized_command("install")
974     install_scripts = self.get_finalized_command("install_scripts")
975     script_files = install_scripts.get_outputs()
976     prefixlen = len(self.bdist_dir) + len(os.sep)
977     for filename in install.get_outputs():
978     filename = filename[prefixlen:]
979     icon = icons.get(filename)
980     dirname = os.path.dirname(filename)
981     if os.name != "nt":
982     # change the separators to \ on non-windos systems
983     filename = string.join(string.split(filename, os.sep), "\\")
984     dirname = string.join(string.split(dirname, os.sep), "\\")
985     line = 'Source: "%s"' % filename
986     if icon is not None:
987     # install it as defined in the icon object
988     backslash = string.rfind(icon.install_name, "\\")
989     if backslash >= 0:
990     dirname = icon.install_name[:backslash]
991     basename = icon.install_name[backslash + 1:]
992     else:
993     dirname = ""
994     basename = icon.install_name
995     line = '%s; DestDir: "%s"; DestName: "%s"' % (line, dirname,
996     basename)
997     else:
998     line = line + '; DestDir: "{app}\\%s"' % (dirname)
999     iss.append(line)
1000    
1001     iss.append("")
1002     iss.append("[Icons]")
1003     for icon in self.icons_entries:
1004     line = 'Name: "{group}\\%s"; Filename: "%s";' \
1005     % (icon.title, icon.install_name)
1006     iss.append(line)
1007 bh 266
1008 bh 15 return iss
1009    
1010    
1011     class InnoIconItem:
1012    
1013 bh 54 """Describe one item for the start menu for the Inno Setup installer"""
1014 bh 15
1015     def __init__(self, filename, title, install_name = None):
1016     self.filename = filename
1017     self.title = title
1018     if install_name is not None:
1019     self.install_name = install_name
1020     else:
1021     self.install_name = filename
1022    
1023 bh 266
1024 bh 15 class thuban_bdist_inno(bdist_inno):
1025    
1026     """Thuban specific Inno Setup stuff"""
1027    
1028     def run(self):
1029     install_options = {
1030     "prefix": ".",
1031 jonathan 533 "install_lib": "$base",
1032     "install_data": "$base",
1033 bh 15 "install_scripts": "$base",
1034     "warn_dir": 0,
1035     "extra_files": ["COPYING", "Lib/proj.dll"],
1036     }
1037 bh 54 # don't make a symlink because we're simulating windows, so
1038     # that we can generate the iss-file even on Linux
1039     install_options["do_symlink"] = 0
1040 jonathan 533
1041 bh 15 bdist_inno.run(self, install_options)
1042 bh 266
1043 jonathan 543 class thuban_build_docs(Command):
1044 bh 266
1045 jonathan 543 """Command to generate documentation from source code."""
1046    
1047     description = "Generate documentation."
1048    
1049     user_options = []
1050    
1051     def initialize_options(self): pass
1052    
1053     def finalize_options(self): pass
1054    
1055     def run(self, install_options = None):
1056     self.spawn(["happydoc", "-d./Doc", "./Thuban"])
1057    
1058 jonathan 1229 class thuban_build_ext(build_ext):
1059    
1060     """Extend the build_ext command to optionally include the
1061     GDAL extension.
1062     """
1063    
1064     user_options = build_ext.user_options[:]
1065     user_options.extend([("with-gdal", None, "Include GDAL support."),
1066     ("without-gdal", None, "Don't include GDAL support.")])
1067    
1068     boolean_options = ["with-gdal"]
1069     negative_opt = {'without-gdal' : 'with-gdal'}
1070    
1071     def initialize_options(self):
1072     self.with_gdal = True
1073     build_ext.initialize_options(self)
1074    
1075     def finalize_options(self):
1076     build_ext.finalize_options(self)
1077     if self.with_gdal and include_gdal:
1078     self.extensions.append(Extension("Lib.gdalwarp",
1079     [ext_dir + "/thuban/gdalwarp.cpp",
1080     ext_dir + "/thuban/cpl_mfile.cpp",
1081     ext_dir + "/thuban/bmpdataset.cpp"],
1082 jonathan 1238 include_dirs = gdal_cs_params[CS_INCDIRS] +
1083     [ext_dir + "/thuban/"],
1084 jonathan 1229 define_macros = gdal_cs_params[CS_DEFS],
1085     library_dirs = gdal_cs_params[CS_LIBDIRS],
1086 jonathan 1238 libraries = gdal_cs_params[CS_LIBS]))
1087 jonathan 1229
1088     def run(self, install_options = None):
1089     build_ext.run(self)
1090    
1091 bh 15 #
1092     # Run the script
1093     #
1094    
1095 bh 6 long_description = """\
1096     Thuban is a viewer for geographic data written in Python
1097     """
1098    
1099 bh 15 setup(name = "Thuban",
1100 jonathan 1291 version = "0.8.0",
1101 bh 6 description = "Geographic data viewer",
1102     long_description = long_description,
1103     licence = "GPL",
1104     author = "Intevation GmbH",
1105     author_email = "[email protected]",
1106 bh 209 url = "http://thuban.intevation.de/",
1107 bh 6
1108     scripts = ["thuban.py"],
1109     packages = ["Thuban", "Thuban.Lib", "Thuban.Model", "Thuban.UI"],
1110     ext_modules = extensions,
1111     py_modules = py_modules,
1112     data_files = data_files,
1113    
1114     # defaults for the install command
1115     options = {"install":
1116     # prefix defaults to python's prefix normally
1117     {"prefix": prefix,
1118     # make sure both libs and scripts are installed in the
1119     # same directory.
1120 bh 200 "install_lib": "$base/lib/thuban",
1121     "install_scripts": "$base/lib/thuban",
1122     "install_data": "$base/lib/thuban",
1123 bh 6
1124     # Don't print warning messages about the lib dir not
1125     # being on Python's path. The libraries are Thuban
1126     # specific and are installed just for Thuban. They'll
1127     # be automatically on Python's path when Thuban is run
1128     "warn_dir": 0,
1129 bh 15 },
1130     "bdist_inno":
1131     {"icons_entries": [InnoIconItem(".\\thuban.py",
1132     "Start Thuban",
1133     "{app}\\thuban.pyw")],
1134     "license_file": "COPYING",
1135     }
1136     },
1137 bh 6 cmdclass = {"build_py": thuban_build_py,
1138     "install_local": InstallLocal,
1139 bh 15 "install": ThubanInstall,
1140 bh 19 "bdist_rpm": thuban_bdist_rpm,
1141 bh 67 "bdist_inno": thuban_bdist_inno,
1142 jonathan 543 "data_dist": data_dist,
1143 jonathan 1229 "build_docs": thuban_build_docs,
1144     "build_ext": thuban_build_ext
1145 bh 15 })
1146 bh 6
1147 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