/[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 212 - (show annotations)
Wed Jul 10 14:06:09 2002 UTC (22 years, 8 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 35981 byte(s)
	* setup.py (create_init_module): New configurable variable whose
	default depends on the platform we're running on.
	(ThubanInstall.initialize_options): Initialize
	self.create_init_module from the global create_init_module
	(ThubanInstall.user_options): indictate that the options
	create-init-module and init-module-dir have arguments.

	* setup.py: In the setup call change the version number to include
	cvs.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26