/[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 452 - (show annotations)
Tue Mar 4 11:31:04 2003 UTC (22 years ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 37546 byte(s)
(thuban_build_py.build): Add a comment about distutils in
Python 2.3 containing some of the functionality we implement in
setup.py ourselves.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26