/[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 1717 - (hide annotations)
Thu Sep 18 12:41:34 2003 UTC (21 years, 5 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 41579 byte(s)
(data_files): Only add the mo files if the Locales
directory actually exists, so that setup.py works with a fresh CVS
checkout

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