/[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 555 - (show annotations)
Tue Mar 25 16:21:23 2003 UTC (21 years, 11 months ago) by jonathan
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 38451 byte(s)
Added custom script bdist_rpm_build_script so that when the rpm is built
the path to wx-config is correct.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26