/[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 2024 - (hide annotations)
Fri Dec 5 16:45:19 2003 UTC (21 years, 3 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 42066 byte(s)
* MANIFEST.in: Add the devtools directory

* setup.py (setup call): Use license instead of licence. This
silences a deprecation warning on Python 2.3

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