/[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 2478 - (hide annotations)
Fri Dec 17 18:48:49 2004 UTC (20 years, 2 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 42176 byte(s)
* Thuban/UI/about.py (unicodeToLocale): Use getdefaultlocale
instead of getlocale because getlocale doesn't return a usable
encoding name on a german windows 2000

* setup.py: windows build: Removed the absolute path names and
made all prfixes relative to the directory containing setup.py.
Makes it a little easier to adapt to a different system.

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