/[thuban]/branches/WIP-pyshapelib-bramz/setup.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/setup.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 928 - (show 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 # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
2 # 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 from types import TupleType
20 import glob
21 from distutils.core import setup, Extension, Command
22 from distutils.command.install import install, INSTALL_SCHEMES, subst_vars
23 from distutils.command.build_py import build_py
24 from distutils.command.bdist_rpm import bdist_rpm
25 from distutils.file_util import write_file
26 from distutils.filelist import FileList
27 from distutils.util import convert_path, change_root
28
29 from distutils import archive_util, dir_util
30 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 # You shouldn't have to modify anything below here
48 ###################################################################
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 # 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 prefix = "/usr/local/"
57
58 # 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 # On POSIX-systems we run wxgtk-config to determine the C++-compiler
64 # flags
65 wx_config_script = "wx-config"
66 # 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 # Define include and lib directories for wxWindows and
84 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
89
90 #
91 # Unless you use a wxPython version other than 2.4.0, you probably
92 # 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 # 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 # 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 wx_incdirs = wx_inc
134 wx_libdirs = wx_lib
135 wx_libs = ["wxmsw24h"]
136
137 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 # 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 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 [ext_dir + "/thuban/wxproj.cpp"],
224 include_dirs = ([shp_dir, proj4_incdir,
225 ext_dir + "/pyshapelib/"]
226 + wx_incdirs),
227 define_macros = wx_defs,
228 library_dirs = [proj4_libdir] + wx_libdirs,
229 libraries = [proj4_lib] + wx_libs))
230
231 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 #
239 # shapelib wrappers are also distributed with thuban
240 #
241
242 extensions.append(Extension("Lib.shapelibc",
243 [ext_dir + "/pyshapelib/shapelib_wrap.c",
244 shp_dir + "/shpopen.c",
245 shp_dir + "/shptree.c"],
246 include_dirs = [shp_dir]))
247 extensions.append(Extension("Lib.shptree",
248 [ext_dir + "/pyshapelib/shptreemodule.c"],
249 include_dirs = [shp_dir]))
250 extensions.append(Extension("Lib.dbflibc",
251 [ext_dir + "/pyshapelib/dbflib_wrap.c",
252 shp_dir + "/dbfopen.c"],
253 include_dirs = [shp_dir]))
254 for name in ("shapelib", "dbflib"):
255 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 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
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 #
286
287
288 # Much of the data_dist command is directly copied from the distutils'
289 # sdist command
290 class data_dist(Command):
291
292 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 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 "Create some symlinks so you can run thuban from the source directory"
426
427 user_options = [
428 ('skip-build', None, "skip the build steps"),
429 ('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 ]
434
435 boolean_options = ["create-init-module"]
436 negative_opt = {'dont-create-init-module' : 'create-init-module'}
437
438
439 def initialize_options (self):
440 self.extensions = None
441 self.build_dir = None
442 self.skip_build = None
443 self.create_init_module = None
444
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 if self.create_init_module is None:
451 # by default we create the init module
452 self.create_init_module = 1
453
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 # on posix, just link the Lib dir
462 self.link_dir(libdir, "Lib")
463 else:
464 self.copy_tree(libdir, "Lib")
465
466 # 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 def link_dir(self, src, dest):
475 """Create a symbolic link dest pointing to src"""
476 if self.verbose:
477 self.announce("symlinking %s -> %s" % (src, dest))
478 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 A new build_py that can deal with both packages and modules in one
497 distribution.
498 """
499
500 # 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 def run(self):
506 """The same the as the original in build_py revision 1.33 except
507 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 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
553 return modules
554
555
556 thubaninit_contents_start = """
557 # 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
562 Usage:
563
564 import thubaninit
565 import Thuban
566 '''
567 import sys, os
568 """
569
570 thubaninit_contents_thubaninitdir = """
571 sys.path.insert(0, %(thubandir)s)
572 """
573 thubaninit_contents_otherdirs = """
574 # 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 def thubaninit_contents(thubandir):
584 """Return the contents of the the thubaninit file as a list of lines.
585
586 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 class ThubanInstall(install):
599
600 """
601 Thuban specific install command.
602
603 Extend the standard install command to symlink the installed script
604 to $prefix/bin/
605 """
606
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 "List of filenames or (src, dest) pairs describing"
614 " extra files to install "
615 "(can only be set from witin setup.py"),
616
617 ("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 "Directory in which to create the init module."
623 " Defaults to Python's site-packages directory."),
624 ])
625
626 boolean_options = install.boolean_options[:]
627 boolean_options.append("do-symlink")
628 boolean_options.append("create-init-module")
629
630 def initialize_options(self):
631 self.do_symlink = None
632 self.extra_files = []
633
634 # initialize the create_init_module flag from the global
635 # determined at runtime
636 self.create_init_module = create_init_module
637 self.init_module_dir = None
638 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 self.expand_with_pure_python_dirs(["init_module_dir"])
648
649 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 def run(self):
682 install.run(self)
683 for item in self.extra_files:
684 if type(item) == TupleType:
685 src, dest = item
686 else:
687 src = dest = item
688 self.copy_file(convert_path(src),
689 os.path.join(self.root, convert_path(dest)))
690
691 if os.name == "posix" and self.do_symlink:
692 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 bindir = os.path.join(self.prefix, "bin")
697 if self.root:
698 bindir = change_root(self.root, bindir)
699 binfile = os.path.join(bindir, "thuban")
700 self.mkpath(bindir)
701 self.link_file(scriptfile, binfile)
702
703 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 contents = thubaninit_contents(self.install_lib_orig)
709 self.mkpath(os.path.dirname(initfilename))
710 self.execute(write_file, (initfilename, contents),
711 "Create %s" % initfilename)
712
713 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 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
733 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 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 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 return outputs
753
754
755 # scripts to override some of the commands put into the spec-file by the
756 # bdist_rpm command.
757
758 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 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 bdist_rpm_install_script = '''
770 %(python)s setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES \
771 --prefix=%(prefix)s
772 '''
773
774
775 class thuban_bdist_rpm(bdist_rpm):
776
777 """Thuban specific RPM distribution command"""
778
779 user_options = bdist_rpm.user_options[:]
780 user_options.extend([("prefix=", None, "Install prefix for the RPM"),
781 ])
782
783 def initialize_options(self):
784 # per default, RPMs are installed in /usr
785 self.prefix = "/usr/"
786
787 # 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 open("bdist_rpm_build", "w").close()
793 open("bdist_rpm_install", "w").close()
794 bdist_rpm.initialize_options(self)
795
796 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
801 build = bdist_rpm_build_script % {"python": self.python,
802 "prefix": self.prefix}
803 open("bdist_rpm_build", "w").write(build)
804
805 install = bdist_rpm_install_script % {"python": self.python,
806 "prefix": self.prefix}
807 open("bdist_rpm_install", "w").write(install)
808
809 #
810 return bdist_rpm._make_spec_file(self)
811
812
813 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
893 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 # and invoke
916 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
982 return iss
983
984
985 class InnoIconItem:
986
987 """Describe one item for the start menu for the Inno Setup installer"""
988
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
998 class thuban_bdist_inno(bdist_inno):
999
1000 """Thuban specific Inno Setup stuff"""
1001
1002 def run(self):
1003 install_options = {
1004 "prefix": ".",
1005 "install_lib": "$base",
1006 "install_data": "$base",
1007 "install_scripts": "$base",
1008 "warn_dir": 0,
1009 "extra_files": ["COPYING", "Lib/proj.dll"],
1010 }
1011 # 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
1015 bdist_inno.run(self, install_options)
1016
1017 class thuban_build_docs(Command):
1018
1019 """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 #
1033 # Run the script
1034 #
1035
1036
1037 long_description = """\
1038 Thuban is a viewer for geographic data written in Python
1039 """
1040
1041 setup(name = "Thuban",
1042 version = "0.2.0",
1043 description = "Geographic data viewer",
1044 long_description = long_description,
1045 licence = "GPL",
1046 author = "Intevation GmbH",
1047 author_email = "[email protected]",
1048 url = "http://thuban.intevation.de/",
1049
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 "install_lib": "$base/lib/thuban",
1063 "install_scripts": "$base/lib/thuban",
1064 "install_data": "$base/lib/thuban",
1065
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 },
1072 "bdist_inno":
1073 {"icons_entries": [InnoIconItem(".\\thuban.py",
1074 "Start Thuban",
1075 "{app}\\thuban.pyw")],
1076 "license_file": "COPYING",
1077 }
1078 },
1079 cmdclass = {"build_py": thuban_build_py,
1080 "install_local": InstallLocal,
1081 "install": ThubanInstall,
1082 "bdist_rpm": thuban_bdist_rpm,
1083 "bdist_inno": thuban_bdist_inno,
1084 "data_dist": data_dist,
1085 "build_docs": thuban_build_docs
1086 })
1087
1088

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26