/[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 266 - (show annotations)
Wed Aug 21 09:15:26 2002 UTC (22 years, 6 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 37292 byte(s)
(ThubanInstall.run): Don't repr install_lib_orig
because thubaninit_contents will do it for us.

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 ('create-init-module', None,
421 "Create the thubaninit.py module to ease use of Thuban as a library"),
422 ('dont-create-init-module', None,
423 "Do not create the thubaninit.py module"),
424 ]
425
426 boolean_options = ["create-init-module"]
427 negative_opt = {'dont-create-init-module' : 'create-init-module'}
428
429
430 def initialize_options (self):
431 self.extensions = None
432 self.build_dir = None
433 self.skip_build = None
434 self.create_init_module = None
435
436 def finalize_options (self):
437 self.set_undefined_options("install",
438 ("build_lib", "build_dir"),
439 ('skip_build', 'skip_build'))
440 self.extensions = self.distribution.ext_modules
441 if self.create_init_module is None:
442 # by default we create the init module
443 self.create_init_module = 1
444
445 def run(self):
446 # Make sure we have built everything we need first
447 self.build()
448
449 # now do the work. Simply link or copy the Lib dir
450 libdir = os.path.join(self.build_dir, "Lib")
451 if os.name == "posix":
452 # on posix, just link the Lib dir
453 self.link_dir(libdir, "Lib")
454 else:
455 self.copy_tree(libdir, "Lib")
456
457 # create the init module if desired
458 if self.create_init_module:
459 # create the init module
460 initfilename = "thubaninit.py"
461 contents = thubaninit_contents("")
462 self.execute(write_file, (initfilename, contents),
463 "Create %s" % initfilename)
464
465 def link_dir(self, src, dest):
466 """Create a symbolic link dest pointing to src"""
467 if self.verbose:
468 self.announce("symlinking %s -> %s" % (src, dest))
469 if self.dry_run:
470 return
471
472 if not (os.path.exists(dest) and os.path.samefile(src, dest)):
473 os.symlink(src, dest)
474
475 def build (self):
476 if not self.skip_build:
477 if self.distribution.has_pure_modules():
478 self.run_command('build_py')
479 if self.distribution.has_ext_modules():
480 self.run_command('build_ext')
481
482
483
484 class thuban_build_py(build_py):
485
486 """
487 A new build_py that can deal with both packages and modules in one
488 distribution.
489 """
490
491 def run(self):
492 """The same the as the original in build_py revision 1.33 except
493 that this allows both packages and modules to be in one
494 distribution
495 """
496 if not self.py_modules and not self.packages:
497 return
498
499 # Now we're down to two cases: 'py_modules' only and 'packages' only.
500 if self.py_modules:
501 self.build_modules()
502 if self.packages:
503 self.build_packages()
504
505 self.byte_compile(self.get_outputs(include_bytecode=0))
506
507 def find_modules (self):
508 """Thuban specific version of build_py.find_modules. Unlike the
509 original version, we assume that the modules in self.py_modules
510 can contain directories and are all to be placed into the same
511 subdirectory, Lib, in the build directory. This is achieved by
512 returning the modules as a list (package, module, filename)
513 where package is 'Lib', module is the basename of the module name
514 and filename is the filename relative to the package root.
515 """
516 modules = []
517 for module in self.py_modules:
518 module_base = os.path.basename(module)
519 module_file = module + ".py"
520 if not self.check_module(module, module_file):
521 continue
522
523 modules.append(("Lib", module_base, module_file))
524 return modules
525
526 def find_all_modules (self):
527 # same as find_all_modules of the original build_py command
528 # (rev. 1.33) but handle installations with both modules and
529 # packages. Needed here so tha the get_outputs works correctly
530 modules = []
531 if self.py_modules:
532 modules.extend(self.find_modules())
533 if self.packages:
534 for package in self.packages:
535 package_dir = self.get_package_dir(package)
536 m = self.find_package_modules(package, package_dir)
537 modules.extend(m)
538
539 return modules
540
541
542 thubaninit_contents_start = """
543 # This module was automatically generated by Thuban's install script
544 '''Import this module once per program (best place is probably the file
545 that ends up as your __main__ module) to be able to import Thuban
546 afterwards.
547
548 Usage:
549
550 import thubaninit
551 import Thuban
552 '''
553 import sys, os
554 """
555
556 thubaninit_contents_thubaninitdir = """
557 sys.path.insert(0, %(thubandir)s)
558 """
559 thubaninit_contents_otherdirs = """
560 # Put the Lib dir into the path. The Lib dir contains some extra Python
561 # modules
562 import Thuban
563 thubandir = os.path.join(Thuban.__path__[0], '..')
564 dir = os.path.join(thubandir, "Lib")
565 if os.path.isdir(dir):
566 sys.path.insert(0, dir)
567 """
568
569 def thubaninit_contents(thubandir):
570 """Return the contents of the the thubaninit file as a list of lines.
571
572 The parameter thubandir is the parent directory where the Thuban/
573 package or the empty string if the thubaninit file itself will be
574 located in that direcory as well.
575 """
576 contents = thubaninit_contents_start
577 if thubandir:
578 thubandir = repr(thubandir)
579 contents += thubaninit_contents_thubaninitdir % locals()
580 contents += thubaninit_contents_otherdirs
581 return contents.split("\n")
582
583
584 class ThubanInstall(install):
585
586 """
587 Thuban specific install command.
588
589 Extend the standard install command to symlink the installed script
590 to $prefix/bin/
591 """
592
593 user_options = install.user_options[:]
594 user_options.extend([("do-symlink", None,
595 "Create a symlink to the script in <prefix>/bin."
596 "(default on posix systems and only relevant there)"),
597
598 ("extra-files", None,
599 "List of filenames or (src, dest) pairs describing"
600 " extra files to install "
601 "(can only be set from witin setup.py"),
602
603 ("create-init-module=", None,
604 "If true, create a module in the site-packages"
605 " directory that tweaks sys.path to let you easily"
606 " import thuban modules from outside of thuban."),
607 ("init-module-dir=", None,
608 "Directory in which to create the init module."
609 " Defaults to Python's site-packages directory."),
610 ])
611
612 boolean_options = install.boolean_options[:]
613 boolean_options.append("do-symlink")
614 boolean_options.append("create-init-module")
615
616 def initialize_options(self):
617 self.do_symlink = None
618 self.extra_files = []
619
620 # initialize the create_init_module flag from the global
621 # determined at runtime
622 self.create_init_module = create_init_module
623 self.init_module_dir = None
624 install.initialize_options(self)
625
626 def finalize_options(self):
627 if self.do_symlink is None:
628 if os.name == "posix":
629 self.do_symlink = 1
630 else:
631 self.do_symlink = 0
632 install.finalize_options(self)
633 self.expand_with_pure_python_dirs(["init_module_dir"])
634
635 def expand_with_pure_python_dirs(self, attrs):
636 """Expand the attributes with default values of base and platbase"""
637 # it seems that the values for "prefix" and "exec_prefix" in
638 # self.config_vars are the corresponding values used by the
639 # python interpreter, so we just assign these to "base" and
640 # "platbase".
641 config_vars = self.config_vars.copy()
642 config_vars["base"] = self.config_vars["prefix"]
643 config_vars["platbase"] = self.config_vars["exec_prefix"]
644 for attr in attrs:
645 val = getattr(self, attr)
646 if val is not None:
647 if os.name == 'posix':
648 val = os.path.expanduser(val)
649 val = subst_vars(val, config_vars)
650 setattr(self, attr, val)
651
652 def select_scheme(self, scheme):
653 """Extend the inherited method to set init_module_dir"""
654 install.select_scheme(self, scheme)
655 # only set init_module_dir if it wasn't set by the user
656 if self.init_module_dir is None:
657 self.init_module_dir = INSTALL_SCHEMES[scheme]['purelib']
658
659 def convert_paths(self, *args):
660 """Extend the inherited method so that we can remember some filename
661 """
662 # remember the installation directory before its root gets
663 # changed
664 self.install_lib_orig = self.install_lib
665 apply(install.convert_paths, (self,) + args)
666
667 def run(self):
668 install.run(self)
669 for item in self.extra_files:
670 if type(item) == TupleType:
671 src, dest = item
672 else:
673 src = dest = item
674 self.copy_file(convert_path(src),
675 os.path.join(self.root, convert_path(dest)))
676
677 if os.name == "posix" and self.do_symlink:
678 install_scripts = self.install_scripts
679 if self.root:
680 install_scripts = install_scripts[len(self.root):]
681 scriptfile = os.path.join(install_scripts, "thuban.py")
682 bindir = os.path.join(self.prefix, "bin")
683 if self.root:
684 bindir = change_root(self.root, bindir)
685 binfile = os.path.join(bindir, "thuban")
686 self.mkpath(bindir)
687 self.link_file(scriptfile, binfile)
688
689 if self.create_init_module:
690 # create the init module
691 initfilename = self.thuban_init_filename()
692 if self.root:
693 initfilename = change_root(self.root, initfilename)
694 contents = thubaninit_contents(self.install_lib_orig)
695 self.mkpath(os.path.dirname(initfilename))
696 self.execute(write_file, (initfilename, contents),
697 "Create %s" % initfilename)
698
699 def link_file(self, src, dest):
700 """Create a symbolic link dest pointing to src.
701
702 Unlike the symlink variant of the command object's copy_file
703 method, this method even performs the link if src doesn't exist.
704 This is useful when installing with an alternat root directory"""
705 if self.verbose:
706 self.announce("symlinking %s -> %s" % (src, dest))
707 if self.dry_run:
708 return
709
710 if not os.path.exists(dest):
711 os.symlink(src, dest)
712
713 def thuban_init_filename(self):
714 """Return the filename for the init-module"""
715 # Since we override the normal install dirs to point to our own
716 # prefix we have to reach into installed
717 return self.init_module_dir + "/thubaninit.py"
718
719 def get_outputs (self):
720 outputs = install.get_outputs(self)
721 for item in self.extra_files:
722 if type(item) == TupleType:
723 src, dest = item
724 else:
725 src = dest = item
726 outputs.append(os.path.join(self.root, convert_path(dest)))
727 if os.name == "posix" and self.do_symlink:
728 bindir = os.path.join(self.prefix, "bin")
729 if self.root:
730 bindir = change_root(self.root, bindir)
731 binfile = os.path.join(bindir, "thuban")
732 outputs.append(binfile)
733 if self.create_init_module:
734 initfilename = self.thuban_init_filename()
735 if self.root:
736 initfilename = change_root(self.root, initfilename)
737 outputs.append(initfilename)
738 return outputs
739
740
741 # scripts to override some of the commands put into the spec-file by the
742 # bdist_rpm command.
743
744 bdist_rpm_prep_script = '''
745 %setup
746 cp extensions/pyshapelib/{README,README.pyshapelib}
747 cp extensions/pyshapelib/{COPYING,COPYING.pyshapelib}
748 cp extensions/pyprojection/{LICENSE,LICENSE.pyprojection}
749 '''
750
751 bdist_rpm_install_script = '''
752 %(python)s setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES \
753 --prefix=%(prefix)s
754 '''
755
756
757 class thuban_bdist_rpm(bdist_rpm):
758
759 """Thuban specific RPM distribution command"""
760
761 user_options = bdist_rpm.user_options[:]
762 user_options.extend([("prefix=", None, "Install prefix for the RPM"),
763 ])
764
765 def initialize_options(self):
766 # per default, RPMs are installed in /usr
767 self.prefix = "/usr/"
768
769 # create the scripts we want to override. We actually fill them
770 # with contents later because some values we put into those
771 # scripts such as the python interpreter to use are only known
772 # then.
773 open("bdist_rpm_prep", "w").close()
774 open("bdist_rpm_install", "w").close()
775 bdist_rpm.initialize_options(self)
776
777 def _make_spec_file(self):
778 # create the scripts for the spec-file. Now we know the python
779 # interpreter to use.
780 open("bdist_rpm_prep", "w").write(bdist_rpm_prep_script)
781 install = bdist_rpm_install_script % {"python": self.python,
782 "prefix": self.prefix}
783 open("bdist_rpm_install", "w").write(install)
784
785 #
786 return bdist_rpm._make_spec_file(self)
787
788
789 class bdist_inno(Command):
790
791 """Command to create a windows installer with Inno Setup"""
792
793 description = "Create a windows installer with Inno Setup"
794
795 user_options = [
796 ('skip-build', None, "skip the build steps"),
797 ('bdist-dir=', None,
798 "temporary directory for creating the distribution"),
799 ('run-inno', None,
800 "Run inno-setup to create the installer. On by default on nt"),
801 ('iss-name', None,
802 "The name of the iss file to generate. "
803 "Shouldn't contain directories"),
804
805 # Parameters for the Inno Setup script
806 ('copyright', None, "Copyright notice for the Inno Setup file"),
807 ('default-dir-name', None,
808 "Default installation directory. Defaults to '{pf}\\<name>'"),
809 ('default-group-name', None,
810 "Default program group name. Defaults to <name>'"),
811 ("license-file", None, "File containing the license."),
812 ("output-basename", None,
813 "Base filename for the Inno Setup output "
814 "(defaults to <name>-<version>-<issrevision>)."),
815 ("iss-revision", None,
816 "revision of the generated installer of the package version"),
817
818 ("icons-entries", None,
819 "List if InnoIconItems "
820 "(this can only be set from inside the setup.py script)"),
821 ]
822
823 boolean_options = ["do-symlink"]
824
825 def initialize_options(self):
826 self.skip_build = 0
827 self.bdist_dir = None
828 self.run_inno = None
829 self.iss_name = None
830 self.copyright = ""
831 self.default_dir_name = None
832 self.default_group_name = None
833 self.license_file = None
834 self.output_basename = None
835 self.iss_revision = None
836 self.icons_entries = []
837
838 def finalize_options(self):
839 self.set_undefined_options("install",
840 ('skip_build', 'skip_build'))
841 if self.bdist_dir is None:
842 bdist_base = self.get_finalized_command('bdist').bdist_base
843 self.bdist_dir = os.path.join(bdist_base, 'inno')
844
845 if self.run_inno is None:
846 self.run_inno = os.name == "nt"
847
848 name = self.distribution.get_name()
849 if self.iss_name is None:
850 self.iss_name = name + '.iss'
851
852 if self.default_dir_name is None:
853 self.default_dir_name = "{pf}\\" + name
854 if self.default_group_name is None:
855 self.default_group_name = name
856
857 if self.iss_revision is None:
858 self.iss_revision = 0
859 if self.output_basename is None:
860 self.output_basename = "%s-%s-%d" \
861 % (name, self.distribution.get_version(),
862 self.iss_revision)
863
864 def run(self, install_options = None):
865 """Execute the command. install_options if given, should be a
866 directory of additional options to set in the install step"""
867 # Obviously have to build before we can install
868 if not self.skip_build:
869 self.run_command('build')
870
871 # Install in a temporary directory
872 install = self.reinitialize_command('install')
873 install.root = self.bdist_dir
874 if install_options is not None:
875 for key, value in install_options.items():
876 setattr(install, key, value)
877 if os.name != 'nt':
878 # Must force install to use the 'nt' scheme;
879 install.select_scheme('nt')
880
881 self.announce("installing to %s" % self.bdist_dir)
882 install.ensure_finalized()
883 install.run()
884
885 # Create the iss file
886 iss_file = os.path.join(self.bdist_dir, self.iss_name)
887 self.execute(write_file, (iss_file, self.generate_iss()),
888 "Create Inno Setup script file %s" % iss_file)
889
890 # and invoke
891 if self.run_inno:
892 self.spawn(["iscc", iss_file])
893
894 def generate_iss(self):
895 """Return the contents of the iss file as list of strings, one
896 string per line"""
897
898 # first, turn the icons entries into a more usable form
899 icons = {}
900 for item in self.icons_entries:
901 icons[item.filename] = item
902
903 iss = []
904
905 name = self.distribution.get_name()
906 iss.extend(["[Setup]",
907 "AppName=" + name,
908 "AppVerName=" + name + " "+self.distribution.get_version(),
909 "DefaultDirName=" + self.default_dir_name,
910 "DefaultGroupName=" + self.default_group_name,
911 ])
912 if self.copyright:
913 iss.append("AppCopyright=" + self.copyright)
914 if self.license_file:
915 iss.append("LicenseFile=" + self.license_file)
916
917 iss.append("OutputBasefilename=" + self.output_basename)
918
919 iss.append("")
920 iss.append("[Files]")
921
922 install = self.get_finalized_command("install")
923 install_scripts = self.get_finalized_command("install_scripts")
924 script_files = install_scripts.get_outputs()
925 prefixlen = len(self.bdist_dir) + len(os.sep)
926 for filename in install.get_outputs():
927 filename = filename[prefixlen:]
928 icon = icons.get(filename)
929 dirname = os.path.dirname(filename)
930 if os.name != "nt":
931 # change the separators to \ on non-windos systems
932 filename = string.join(string.split(filename, os.sep), "\\")
933 dirname = string.join(string.split(dirname, os.sep), "\\")
934 line = 'Source: "%s"' % filename
935 if icon is not None:
936 # install it as defined in the icon object
937 backslash = string.rfind(icon.install_name, "\\")
938 if backslash >= 0:
939 dirname = icon.install_name[:backslash]
940 basename = icon.install_name[backslash + 1:]
941 else:
942 dirname = ""
943 basename = icon.install_name
944 line = '%s; DestDir: "%s"; DestName: "%s"' % (line, dirname,
945 basename)
946 else:
947 line = line + '; DestDir: "{app}\\%s"' % (dirname)
948 iss.append(line)
949
950 iss.append("")
951 iss.append("[Icons]")
952 for icon in self.icons_entries:
953 line = 'Name: "{group}\\%s"; Filename: "%s";' \
954 % (icon.title, icon.install_name)
955 iss.append(line)
956
957 return iss
958
959
960 class InnoIconItem:
961
962 """Describe one item for the start menu for the Inno Setup installer"""
963
964 def __init__(self, filename, title, install_name = None):
965 self.filename = filename
966 self.title = title
967 if install_name is not None:
968 self.install_name = install_name
969 else:
970 self.install_name = filename
971
972
973 class thuban_bdist_inno(bdist_inno):
974
975 """Thuban specific Inno Setup stuff"""
976
977 def run(self):
978 install_options = {
979 "prefix": ".",
980 "install_scripts": "$base",
981 "warn_dir": 0,
982 "extra_files": ["COPYING", "Lib/proj.dll"],
983 }
984 # don't make a symlink because we're simulating windows, so
985 # that we can generate the iss-file even on Linux
986 install_options["do_symlink"] = 0
987 bdist_inno.run(self, install_options)
988
989
990 #
991 # Run the script
992 #
993
994
995 long_description = """\
996 Thuban is a viewer for geographic data written in Python
997 """
998
999 setup(name = "Thuban",
1000 version = "0.1.3cvs",
1001 description = "Geographic data viewer",
1002 long_description = long_description,
1003 licence = "GPL",
1004 author = "Intevation GmbH",
1005 author_email = "[email protected]",
1006 url = "http://thuban.intevation.de/",
1007
1008 scripts = ["thuban.py"],
1009 packages = ["Thuban", "Thuban.Lib", "Thuban.Model", "Thuban.UI"],
1010 ext_modules = extensions,
1011 py_modules = py_modules,
1012 data_files = data_files,
1013
1014 # defaults for the install command
1015 options = {"install":
1016 # prefix defaults to python's prefix normally
1017 {"prefix": prefix,
1018 # make sure both libs and scripts are installed in the
1019 # same directory.
1020 "install_lib": "$base/lib/thuban",
1021 "install_scripts": "$base/lib/thuban",
1022 "install_data": "$base/lib/thuban",
1023
1024 # Don't print warning messages about the lib dir not
1025 # being on Python's path. The libraries are Thuban
1026 # specific and are installed just for Thuban. They'll
1027 # be automatically on Python's path when Thuban is run
1028 "warn_dir": 0,
1029 },
1030 "bdist_inno":
1031 {"icons_entries": [InnoIconItem(".\\thuban.py",
1032 "Start Thuban",
1033 "{app}\\thuban.pyw")],
1034 "license_file": "COPYING",
1035 }
1036 },
1037 cmdclass = {"build_py": thuban_build_py,
1038 "install_local": InstallLocal,
1039 "install": ThubanInstall,
1040 "bdist_rpm": thuban_bdist_rpm,
1041 "bdist_inno": thuban_bdist_inno,
1042 "data_dist": data_dist
1043 })
1044
1045

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26