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