/[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 515 - (show annotations)
Tue Mar 11 16:45:20 2003 UTC (21 years, 11 months ago) by jonathan
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 37604 byte(s)
Update some definitions to use wxWindows2.4 files.

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_install_script = '''
760 %(python)s setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES \
761 --prefix=%(prefix)s
762 '''
763
764
765 class thuban_bdist_rpm(bdist_rpm):
766
767 """Thuban specific RPM distribution command"""
768
769 user_options = bdist_rpm.user_options[:]
770 user_options.extend([("prefix=", None, "Install prefix for the RPM"),
771 ])
772
773 def initialize_options(self):
774 # per default, RPMs are installed in /usr
775 self.prefix = "/usr/"
776
777 # create the scripts we want to override. We actually fill them
778 # with contents later because some values we put into those
779 # scripts such as the python interpreter to use are only known
780 # then.
781 open("bdist_rpm_prep", "w").close()
782 open("bdist_rpm_install", "w").close()
783 bdist_rpm.initialize_options(self)
784
785 def _make_spec_file(self):
786 # create the scripts for the spec-file. Now we know the python
787 # interpreter to use.
788 open("bdist_rpm_prep", "w").write(bdist_rpm_prep_script)
789 install = bdist_rpm_install_script % {"python": self.python,
790 "prefix": self.prefix}
791 open("bdist_rpm_install", "w").write(install)
792
793 #
794 return bdist_rpm._make_spec_file(self)
795
796
797 class bdist_inno(Command):
798
799 """Command to create a windows installer with Inno Setup"""
800
801 description = "Create a windows installer with Inno Setup"
802
803 user_options = [
804 ('skip-build', None, "skip the build steps"),
805 ('bdist-dir=', None,
806 "temporary directory for creating the distribution"),
807 ('run-inno', None,
808 "Run inno-setup to create the installer. On by default on nt"),
809 ('iss-name', None,
810 "The name of the iss file to generate. "
811 "Shouldn't contain directories"),
812
813 # Parameters for the Inno Setup script
814 ('copyright', None, "Copyright notice for the Inno Setup file"),
815 ('default-dir-name', None,
816 "Default installation directory. Defaults to '{pf}\\<name>'"),
817 ('default-group-name', None,
818 "Default program group name. Defaults to <name>'"),
819 ("license-file", None, "File containing the license."),
820 ("output-basename", None,
821 "Base filename for the Inno Setup output "
822 "(defaults to <name>-<version>-<issrevision>)."),
823 ("iss-revision", None,
824 "revision of the generated installer of the package version"),
825
826 ("icons-entries", None,
827 "List if InnoIconItems "
828 "(this can only be set from inside the setup.py script)"),
829 ]
830
831 boolean_options = ["do-symlink"]
832
833 def initialize_options(self):
834 self.skip_build = 0
835 self.bdist_dir = None
836 self.run_inno = None
837 self.iss_name = None
838 self.copyright = ""
839 self.default_dir_name = None
840 self.default_group_name = None
841 self.license_file = None
842 self.output_basename = None
843 self.iss_revision = None
844 self.icons_entries = []
845
846 def finalize_options(self):
847 self.set_undefined_options("install",
848 ('skip_build', 'skip_build'))
849 if self.bdist_dir is None:
850 bdist_base = self.get_finalized_command('bdist').bdist_base
851 self.bdist_dir = os.path.join(bdist_base, 'inno')
852
853 if self.run_inno is None:
854 self.run_inno = os.name == "nt"
855
856 name = self.distribution.get_name()
857 if self.iss_name is None:
858 self.iss_name = name + '.iss'
859
860 if self.default_dir_name is None:
861 self.default_dir_name = "{pf}\\" + name
862 if self.default_group_name is None:
863 self.default_group_name = name
864
865 if self.iss_revision is None:
866 self.iss_revision = 0
867 if self.output_basename is None:
868 self.output_basename = "%s-%s-%d" \
869 % (name, self.distribution.get_version(),
870 self.iss_revision)
871
872 def run(self, install_options = None):
873 """Execute the command. install_options if given, should be a
874 directory of additional options to set in the install step"""
875 # Obviously have to build before we can install
876 if not self.skip_build:
877 self.run_command('build')
878
879 # Install in a temporary directory
880 install = self.reinitialize_command('install')
881 install.root = self.bdist_dir
882 if install_options is not None:
883 for key, value in install_options.items():
884 setattr(install, key, value)
885 if os.name != 'nt':
886 # Must force install to use the 'nt' scheme;
887 install.select_scheme('nt')
888
889 self.announce("installing to %s" % self.bdist_dir)
890 install.ensure_finalized()
891 install.run()
892
893 # Create the iss file
894 iss_file = os.path.join(self.bdist_dir, self.iss_name)
895 self.execute(write_file, (iss_file, self.generate_iss()),
896 "Create Inno Setup script file %s" % iss_file)
897
898 # and invoke
899 if self.run_inno:
900 self.spawn(["iscc", iss_file])
901
902 def generate_iss(self):
903 """Return the contents of the iss file as list of strings, one
904 string per line"""
905
906 # first, turn the icons entries into a more usable form
907 icons = {}
908 for item in self.icons_entries:
909 icons[item.filename] = item
910
911 iss = []
912
913 name = self.distribution.get_name()
914 iss.extend(["[Setup]",
915 "AppName=" + name,
916 "AppVerName=" + name + " "+self.distribution.get_version(),
917 "DefaultDirName=" + self.default_dir_name,
918 "DefaultGroupName=" + self.default_group_name,
919 ])
920 if self.copyright:
921 iss.append("AppCopyright=" + self.copyright)
922 if self.license_file:
923 iss.append("LicenseFile=" + self.license_file)
924
925 iss.append("OutputBasefilename=" + self.output_basename)
926
927 iss.append("")
928 iss.append("[Files]")
929
930 install = self.get_finalized_command("install")
931 install_scripts = self.get_finalized_command("install_scripts")
932 script_files = install_scripts.get_outputs()
933 prefixlen = len(self.bdist_dir) + len(os.sep)
934 for filename in install.get_outputs():
935 filename = filename[prefixlen:]
936 icon = icons.get(filename)
937 dirname = os.path.dirname(filename)
938 if os.name != "nt":
939 # change the separators to \ on non-windos systems
940 filename = string.join(string.split(filename, os.sep), "\\")
941 dirname = string.join(string.split(dirname, os.sep), "\\")
942 line = 'Source: "%s"' % filename
943 if icon is not None:
944 # install it as defined in the icon object
945 backslash = string.rfind(icon.install_name, "\\")
946 if backslash >= 0:
947 dirname = icon.install_name[:backslash]
948 basename = icon.install_name[backslash + 1:]
949 else:
950 dirname = ""
951 basename = icon.install_name
952 line = '%s; DestDir: "%s"; DestName: "%s"' % (line, dirname,
953 basename)
954 else:
955 line = line + '; DestDir: "{app}\\%s"' % (dirname)
956 iss.append(line)
957
958 iss.append("")
959 iss.append("[Icons]")
960 for icon in self.icons_entries:
961 line = 'Name: "{group}\\%s"; Filename: "%s";' \
962 % (icon.title, icon.install_name)
963 iss.append(line)
964
965 return iss
966
967
968 class InnoIconItem:
969
970 """Describe one item for the start menu for the Inno Setup installer"""
971
972 def __init__(self, filename, title, install_name = None):
973 self.filename = filename
974 self.title = title
975 if install_name is not None:
976 self.install_name = install_name
977 else:
978 self.install_name = filename
979
980
981 class thuban_bdist_inno(bdist_inno):
982
983 """Thuban specific Inno Setup stuff"""
984
985 def run(self):
986 install_options = {
987 "prefix": ".",
988 "install_scripts": "$base",
989 "warn_dir": 0,
990 "extra_files": ["COPYING", "Lib/proj.dll"],
991 }
992 # don't make a symlink because we're simulating windows, so
993 # that we can generate the iss-file even on Linux
994 install_options["do_symlink"] = 0
995 bdist_inno.run(self, install_options)
996
997
998 #
999 # Run the script
1000 #
1001
1002
1003 long_description = """\
1004 Thuban is a viewer for geographic data written in Python
1005 """
1006
1007 setup(name = "Thuban",
1008 version = "0.1.3",
1009 description = "Geographic data viewer",
1010 long_description = long_description,
1011 licence = "GPL",
1012 author = "Intevation GmbH",
1013 author_email = "[email protected]",
1014 url = "http://thuban.intevation.de/",
1015
1016 scripts = ["thuban.py"],
1017 packages = ["Thuban", "Thuban.Lib", "Thuban.Model", "Thuban.UI"],
1018 ext_modules = extensions,
1019 py_modules = py_modules,
1020 data_files = data_files,
1021
1022 # defaults for the install command
1023 options = {"install":
1024 # prefix defaults to python's prefix normally
1025 {"prefix": prefix,
1026 # make sure both libs and scripts are installed in the
1027 # same directory.
1028 "install_lib": "$base/lib/thuban",
1029 "install_scripts": "$base/lib/thuban",
1030 "install_data": "$base/lib/thuban",
1031
1032 # Don't print warning messages about the lib dir not
1033 # being on Python's path. The libraries are Thuban
1034 # specific and are installed just for Thuban. They'll
1035 # be automatically on Python's path when Thuban is run
1036 "warn_dir": 0,
1037 },
1038 "bdist_inno":
1039 {"icons_entries": [InnoIconItem(".\\thuban.py",
1040 "Start Thuban",
1041 "{app}\\thuban.pyw")],
1042 "license_file": "COPYING",
1043 }
1044 },
1045 cmdclass = {"build_py": thuban_build_py,
1046 "install_local": InstallLocal,
1047 "install": ThubanInstall,
1048 "bdist_rpm": thuban_bdist_rpm,
1049 "bdist_inno": thuban_bdist_inno,
1050 "data_dist": data_dist
1051 })
1052
1053

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26