/[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 1698 - (show annotations)
Mon Sep 1 16:26:26 2003 UTC (21 years, 6 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 41531 byte(s)
(data_files): Add the .mo files
(setup call): Up to version 0.9.0

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26