/[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 209 - (show annotations)
Tue Jul 9 16:17:32 2002 UTC (22 years, 8 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 35272 byte(s)
	* setup.py: In the setup call, use the thuban homepage as the
	value of the url parameter.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26