/[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 928 - (hide annotations)
Tue May 20 15:22:10 2003 UTC (21 years, 9 months ago) by jonathan
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 38769 byte(s)
Add gdalwarp library extension.

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