/[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 1994 - (show annotations)
Fri Nov 28 16:44:03 2003 UTC (21 years, 3 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 41584 byte(s)
(setup call): Update version to 1.0rc1. Use the
thuban@intevation.de email address as author email instead of my
personal one.

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 if os.path.isdir("Resources/Locale"):
305 for d in os.listdir("Resources/Locale"):
306 data_files.append(("Resources/Locale/" + d +"/LC_MESSAGES",
307 ["Resources/Locale/"+ d +"/LC_MESSAGES/thuban.mo"]))
308
309 #
310 # Command definitions
311 #
312 # So far distutils are only meant to distribute python extensions, not
313 # complete applications, so we have to redefine a few commands
314 #
315
316
317 # Much of the data_dist command is directly copied from the distutils'
318 # sdist command
319 class data_dist(Command):
320
321 description = "create a data distribution (tarball, zip file, etc.)"
322
323 user_options = [
324 ('formats=', None,
325 "formats for source distribution (comma-separated list)"),
326 ('keep-temp', 'k',
327 "keep the distribution tree around after creating " +
328 "archive file(s)"),
329 ('dist-dir=', 'd',
330 "directory to put the source distribution archive(s) in "
331 "[default: dist]"),
332 ]
333
334 boolean_options = ['keep-temp']
335
336 def initialize_options (self):
337 self.formats = None
338 self.keep_temp = 0
339 self.dist_dir = None
340
341 def finalize_options (self):
342 self.ensure_string_list('formats')
343 if self.formats is None:
344 self.formats = ["zip"]
345 bad_format = archive_util.check_archive_formats(self.formats)
346 if bad_format:
347 raise DistutilsOptionError, \
348 "unknown archive format '%s'" % bad_format
349
350 if self.dist_dir is None:
351 self.dist_dir = "dist"
352
353
354 def run(self):
355 # 'filelist' contains the list of files that will make up the
356 # manifest
357 self.filelist = FileList()
358
359 # Do whatever it takes to get the list of files to process.
360 # File list is accumulated in 'self.filelist'.
361 self.get_file_list()
362
363 # Otherwise, go ahead and create the source distribution tarball,
364 # or zipfile, or whatever.
365 self.make_distribution()
366
367 def get_file_list(self):
368 """Figure out the list of files to include in the data
369 distribution, and put it in 'self.filelist'.
370 """
371 self.filelist.findall("Data")
372 self.filelist.include_pattern("*", anchor = 0)
373 self.filelist.exclude_pattern(r'/(RCS|CVS)/.*', is_regex=1)
374 self.filelist.sort()
375 self.filelist.remove_duplicates()
376
377 def make_release_tree(self, base_dir, files):
378 """Create the directory tree that will become the source
379 distribution archive. All directories implied by the filenames in
380 'files' are created under 'base_dir', and then we hard link or copy
381 (if hard linking is unavailable) those files into place.
382 Essentially, this duplicates the developer's source tree, but in a
383 directory named after the distribution, containing only the files
384 to be distributed.
385 """
386 # Create all the directories under 'base_dir' necessary to
387 # put 'files' there; the 'mkpath()' is just so we don't die
388 # if the manifest happens to be empty.
389 self.mkpath(base_dir)
390 dir_util.create_tree(base_dir, files,
391 verbose=self.verbose, dry_run=self.dry_run)
392
393 # And walk over the list of files, either making a hard link (if
394 # os.link exists) to each one that doesn't already exist in its
395 # corresponding location under 'base_dir', or copying each file
396 # that's out-of-date in 'base_dir'. (Usually, all files will be
397 # out-of-date, because by default we blow away 'base_dir' when
398 # we're done making the distribution archives.)
399
400 if hasattr(os, 'link'): # can make hard links on this system
401 link = 'hard'
402 msg = "making hard links in %s..." % base_dir
403 else: # nope, have to copy
404 link = None
405 msg = "copying files to %s..." % base_dir
406
407 if not files:
408 self.warn("no files to distribute -- empty manifest?")
409 else:
410 self.announce(msg)
411 for file in files:
412 if not os.path.isfile(file):
413 self.warn("'%s' not a regular file -- skipping" % file)
414 else:
415 dest = os.path.join(base_dir, file)
416 self.copy_file(file, dest, link=link)
417
418
419 def make_distribution (self):
420 """Create the source distribution(s). First, we create the release
421 tree with 'make_release_tree()'; then, we create all required
422 archive files (according to 'self.formats') from the release tree.
423 Finally, we clean up by blowing away the release tree (unless
424 'self.keep_temp' is true). The list of archive files created is
425 stored so it can be retrieved later by 'get_archive_files()'.
426 """
427 # Don't warn about missing meta-data here -- should be (and is!)
428 # done elsewhere.
429 base_dir = "Thuban-data-" + self.distribution.get_version()
430 base_name = os.path.join(self.dist_dir, base_dir)
431
432 self.make_release_tree(base_dir, self.filelist.files)
433 archive_files = [] # remember names of files we create
434 for fmt in self.formats:
435 file = self.make_archive(base_name, fmt, base_dir=base_dir)
436 archive_files.append(file)
437
438 self.archive_files = archive_files
439
440 if not self.keep_temp:
441 dir_util.remove_tree(base_dir, self.verbose, self.dry_run)
442
443
444
445 class InstallLocal(Command):
446
447 """
448 A new install command to just link (or copy, on non-POSIX systems)
449 the extension modules to the top directory so that Thuban can be run
450 directly from the source dir.
451 """
452
453 description =\
454 "Create some symlinks so you can run thuban from the source directory"
455
456 user_options = [
457 ('skip-build', None, "skip the build steps"),
458 ('create-init-module', None,
459 "Create the thubaninit.py module to ease use of Thuban as a library"),
460 ('dont-create-init-module', None,
461 "Do not create the thubaninit.py module"),
462 ]
463
464 boolean_options = ["create-init-module"]
465 negative_opt = {'dont-create-init-module' : 'create-init-module'}
466
467
468 def initialize_options (self):
469 self.extensions = None
470 self.build_dir = None
471 self.skip_build = None
472 self.create_init_module = None
473
474 def finalize_options (self):
475 self.set_undefined_options("install",
476 ("build_lib", "build_dir"),
477 ('skip_build', 'skip_build'))
478 self.extensions = self.distribution.ext_modules
479 if self.create_init_module is None:
480 # by default we create the init module
481 self.create_init_module = 1
482
483 def run(self):
484 # Make sure we have built everything we need first
485 self.build()
486
487 # now do the work. Simply link or copy the Lib dir
488 libdir = os.path.join(self.build_dir, "Lib")
489 if os.name == "posix":
490 # on posix, just link the Lib dir
491 self.link_dir(libdir, "Lib")
492 else:
493 self.copy_tree(libdir, "Lib")
494
495 # create the init module if desired
496 if self.create_init_module:
497 # create the init module
498 initfilename = "thubaninit.py"
499 contents = thubaninit_contents("")
500 self.execute(write_file, (initfilename, contents),
501 "Create %s" % initfilename)
502
503 def link_dir(self, src, dest):
504 """Create a symbolic link dest pointing to src"""
505 if self.verbose:
506 self.announce("symlinking %s -> %s" % (src, dest))
507 if self.dry_run:
508 return
509
510 if not (os.path.exists(dest) and os.path.samefile(src, dest)):
511 os.symlink(src, dest)
512
513 def build (self):
514 if not self.skip_build:
515 if self.distribution.has_pure_modules():
516 self.run_command('build_py')
517 if self.distribution.has_ext_modules():
518 self.run_command('build_ext')
519
520
521
522 class thuban_build_py(build_py):
523
524 """
525 A new build_py that can deal with both packages and modules in one
526 distribution.
527 """
528
529 # FIXME: When Thuban can rely on Python 2.3 as the oldest supported
530 # Python release we don't need to override the run and
531 # find_all_modules methods anymore. distutils will allow both python
532 # modules and packages starting with 2.3.
533
534 def run(self):
535 """The same the as the original in build_py revision 1.33 except
536 that this allows both packages and modules to be in one
537 distribution
538 """
539 if not self.py_modules and not self.packages:
540 return
541
542 # Now we're down to two cases: 'py_modules' only and 'packages' only.
543 if self.py_modules:
544 self.build_modules()
545 if self.packages:
546 self.build_packages()
547
548 self.byte_compile(self.get_outputs(include_bytecode=0))
549
550 def find_modules (self):
551 """Thuban specific version of build_py.find_modules. Unlike the
552 original version, we assume that the modules in self.py_modules
553 can contain directories and are all to be placed into the same
554 subdirectory, Lib, in the build directory. This is achieved by
555 returning the modules as a list (package, module, filename)
556 where package is 'Lib', module is the basename of the module name
557 and filename is the filename relative to the package root.
558 """
559 modules = []
560 for module in self.py_modules:
561 module_base = os.path.basename(module)
562 module_file = module + ".py"
563 if not self.check_module(module, module_file):
564 continue
565
566 modules.append(("Lib", module_base, module_file))
567 return modules
568
569 def find_all_modules (self):
570 # same as find_all_modules of the original build_py command
571 # (rev. 1.33) but handle installations with both modules and
572 # packages. Needed here so tha the get_outputs works correctly
573 modules = []
574 if self.py_modules:
575 modules.extend(self.find_modules())
576 if self.packages:
577 for package in self.packages:
578 package_dir = self.get_package_dir(package)
579 m = self.find_package_modules(package, package_dir)
580 modules.extend(m)
581
582 return modules
583
584
585 thubaninit_contents_start = """
586 # This module was automatically generated by Thuban's install script
587 '''Import this module once per program (best place is probably the file
588 that ends up as your __main__ module) to be able to import Thuban
589 afterwards.
590
591 Usage:
592
593 import thubaninit
594 import Thuban
595 '''
596 import sys, os
597 """
598
599 thubaninit_contents_thubaninitdir = """
600 sys.path.insert(0, %(thubandir)s)
601 """
602 thubaninit_contents_otherdirs = """
603 # Put the Lib dir into the path. The Lib dir contains some extra Python
604 # modules
605 import Thuban
606 thubandir = os.path.join(Thuban.__path__[0], '..')
607 dir = os.path.join(thubandir, "Lib")
608 if os.path.isdir(dir):
609 sys.path.insert(0, dir)
610 """
611
612 def thubaninit_contents(thubandir):
613 """Return the contents of the the thubaninit file as a list of lines.
614
615 The parameter thubandir is the parent directory where the Thuban/
616 package or the empty string if the thubaninit file itself will be
617 located in that direcory as well.
618 """
619 contents = thubaninit_contents_start
620 if thubandir:
621 thubandir = repr(thubandir)
622 contents += thubaninit_contents_thubaninitdir % locals()
623 contents += thubaninit_contents_otherdirs
624 return contents.split("\n")
625
626
627 class ThubanInstall(install):
628
629 """
630 Thuban specific install command.
631
632 Extend the standard install command to symlink the installed script
633 to $prefix/bin/
634 """
635
636 user_options = install.user_options[:]
637 user_options.extend([("do-symlink", None,
638 "Create a symlink to the script in <prefix>/bin."
639 "(default on posix systems and only relevant there)"),
640
641 ("extra-files", None,
642 "List of filenames or (src, dest) pairs describing"
643 " extra files to install "
644 "(can only be set from within setup.py"),
645
646 ("create-init-module=", None,
647 "If true, create a module in the site-packages"
648 " directory that tweaks sys.path to let you easily"
649 " import thuban modules from outside of thuban."),
650 ("init-module-dir=", None,
651 "Directory in which to create the init module."
652 " Defaults to Python's site-packages directory."),
653 ])
654
655 boolean_options = install.boolean_options[:]
656 boolean_options.append("do-symlink")
657 boolean_options.append("create-init-module")
658
659 def initialize_options(self):
660 self.do_symlink = None
661 self.extra_files = []
662
663 # initialize the create_init_module flag from the global
664 # determined at runtime
665 self.create_init_module = create_init_module
666 self.init_module_dir = None
667 install.initialize_options(self)
668
669 def finalize_options(self):
670 if self.do_symlink is None:
671 if os.name == "posix":
672 self.do_symlink = 1
673 else:
674 self.do_symlink = 0
675 install.finalize_options(self)
676 self.expand_with_pure_python_dirs(["init_module_dir"])
677
678 def expand_with_pure_python_dirs(self, attrs):
679 """Expand the attributes with default values of base and platbase"""
680 # it seems that the values for "prefix" and "exec_prefix" in
681 # self.config_vars are the corresponding values used by the
682 # python interpreter, so we just assign these to "base" and
683 # "platbase".
684 config_vars = self.config_vars.copy()
685 config_vars["base"] = self.config_vars["prefix"]
686 config_vars["platbase"] = self.config_vars["exec_prefix"]
687 for attr in attrs:
688 val = getattr(self, attr)
689 if val is not None:
690 if os.name == 'posix':
691 val = os.path.expanduser(val)
692 val = subst_vars(val, config_vars)
693 setattr(self, attr, val)
694
695 def select_scheme(self, scheme):
696 """Extend the inherited method to set init_module_dir"""
697 install.select_scheme(self, scheme)
698 # only set init_module_dir if it wasn't set by the user
699 if self.init_module_dir is None:
700 self.init_module_dir = INSTALL_SCHEMES[scheme]['purelib']
701
702 def convert_paths(self, *args):
703 """Extend the inherited method so that we can remember some filename
704 """
705 # remember the installation directory before its root gets
706 # changed
707 self.install_lib_orig = self.install_lib
708 apply(install.convert_paths, (self,) + args)
709
710 def run(self):
711 install.run(self)
712 for item in self.extra_files:
713 if type(item) == TupleType:
714 src, dest = item
715 else:
716 src = dest = item
717 self.copy_file(convert_path(src),
718 os.path.join(self.root, convert_path(dest)))
719
720 if os.name == "posix" and self.do_symlink:
721 install_scripts = self.install_scripts
722 if self.root:
723 install_scripts = install_scripts[len(self.root):]
724 scriptfile = os.path.join(install_scripts, "thuban.py")
725 bindir = os.path.join(self.prefix, "bin")
726 if self.root:
727 bindir = change_root(self.root, bindir)
728 binfile = os.path.join(bindir, "thuban")
729 self.mkpath(bindir)
730 self.link_file(scriptfile, binfile)
731
732 if self.create_init_module:
733 # create the init module
734 initfilename = self.thuban_init_filename()
735 if self.root:
736 initfilename = change_root(self.root, initfilename)
737 contents = thubaninit_contents(self.install_lib_orig)
738 self.mkpath(os.path.dirname(initfilename))
739 self.execute(write_file, (initfilename, contents),
740 "Create %s" % initfilename)
741
742 def link_file(self, src, dest):
743 """Create a symbolic link dest pointing to src.
744
745 Unlike the symlink variant of the command object's copy_file
746 method, this method even performs the link if src doesn't exist.
747 This is useful when installing with an alternat root directory"""
748 if self.verbose:
749 self.announce("symlinking %s -> %s" % (src, dest))
750 if self.dry_run:
751 return
752
753 if not os.path.exists(dest):
754 os.symlink(src, dest)
755
756 def thuban_init_filename(self):
757 """Return the filename for the init-module"""
758 # Since we override the normal install dirs to point to our own
759 # prefix we have to reach into installed
760 return self.init_module_dir + "/thubaninit.py"
761
762 def get_outputs (self):
763 outputs = install.get_outputs(self)
764 for item in self.extra_files:
765 if type(item) == TupleType:
766 src, dest = item
767 else:
768 src = dest = item
769 outputs.append(os.path.join(self.root, convert_path(dest)))
770 if os.name == "posix" and self.do_symlink:
771 bindir = os.path.join(self.prefix, "bin")
772 if self.root:
773 bindir = change_root(self.root, bindir)
774 binfile = os.path.join(bindir, "thuban")
775 outputs.append(binfile)
776 if self.create_init_module:
777 initfilename = self.thuban_init_filename()
778 if self.root:
779 initfilename = change_root(self.root, initfilename)
780 outputs.append(initfilename)
781 return outputs
782
783
784 # scripts to override some of the commands put into the spec-file by the
785 # bdist_rpm command.
786
787 bdist_rpm_prep_script = '''
788 %setup
789 cp libraries/pyshapelib/{README,README.pyshapelib}
790 cp libraries/pyshapelib/{COPYING,COPYING.pyshapelib}
791 cp libraries/pyprojection/{LICENSE,LICENSE.pyprojection}
792 '''
793
794 bdist_rpm_build_script = '''
795 env PATH="$PATH:%(prefix)s/lib/wxPython/bin:/usr/lib/wxPython/bin" CFLAGS="$RPM_OPT_FLAGS" %(python)s setup.py build
796 '''
797
798 bdist_rpm_install_script = '''
799 %(python)s setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES \
800 --prefix=%(prefix)s
801 '''
802
803
804 class thuban_bdist_rpm(bdist_rpm):
805
806 """Thuban specific RPM distribution command"""
807
808 user_options = bdist_rpm.user_options[:]
809 user_options.extend([("prefix=", None, "Install prefix for the RPM"),
810 ])
811
812 def initialize_options(self):
813 # per default, RPMs are installed in /usr
814 self.prefix = "/usr/"
815
816 # create the scripts we want to override. We actually fill them
817 # with contents later because some values we put into those
818 # scripts such as the python interpreter to use are only known
819 # then.
820 open("bdist_rpm_prep", "w").close()
821 open("bdist_rpm_build", "w").close()
822 open("bdist_rpm_install", "w").close()
823 bdist_rpm.initialize_options(self)
824
825 def _make_spec_file(self):
826 # create the scripts for the spec-file. Now we know the python
827 # interpreter to use.
828 open("bdist_rpm_prep", "w").write(bdist_rpm_prep_script)
829
830 build = bdist_rpm_build_script % {"python": self.python,
831 "prefix": self.prefix}
832 open("bdist_rpm_build", "w").write(build)
833
834 install = bdist_rpm_install_script % {"python": self.python,
835 "prefix": self.prefix}
836 open("bdist_rpm_install", "w").write(install)
837
838 #
839 return bdist_rpm._make_spec_file(self)
840
841
842 class bdist_inno(Command):
843
844 """Command to create a windows installer with Inno Setup"""
845
846 description = "Create a windows installer with Inno Setup"
847
848 user_options = [
849 ('skip-build', None, "skip the build steps"),
850 ('bdist-dir=', None,
851 "temporary directory for creating the distribution"),
852 ('run-inno', None,
853 "Run inno-setup to create the installer. On by default on nt"),
854 ('iss-name', None,
855 "The name of the iss file to generate. "
856 "Shouldn't contain directories"),
857
858 # Parameters for the Inno Setup script
859 ('copyright', None, "Copyright notice for the Inno Setup file"),
860 ('default-dir-name', None,
861 "Default installation directory. Defaults to '{pf}\\<name>'"),
862 ('default-group-name', None,
863 "Default program group name. Defaults to <name>'"),
864 ("license-file", None, "File containing the license."),
865 ("output-basename", None,
866 "Base filename for the Inno Setup output "
867 "(defaults to <name>-<version>-<issrevision>)."),
868 ("iss-revision", None,
869 "revision of the generated installer of the package version"),
870
871 ("icons-entries", None,
872 "List if InnoIconItems "
873 "(this can only be set from inside the setup.py script)"),
874 ]
875
876 boolean_options = ["do-symlink"]
877
878 def initialize_options(self):
879 self.skip_build = 0
880 self.bdist_dir = None
881 self.run_inno = None
882 self.iss_name = None
883 self.copyright = ""
884 self.default_dir_name = None
885 self.default_group_name = None
886 self.license_file = None
887 self.output_basename = None
888 self.iss_revision = None
889 self.icons_entries = []
890
891 def finalize_options(self):
892 self.set_undefined_options("install",
893 ('skip_build', 'skip_build'))
894 if self.bdist_dir is None:
895 bdist_base = self.get_finalized_command('bdist').bdist_base
896 self.bdist_dir = os.path.join(bdist_base, 'inno')
897
898 if self.run_inno is None:
899 self.run_inno = os.name == "nt"
900
901 name = self.distribution.get_name()
902 if self.iss_name is None:
903 self.iss_name = name + '.iss'
904
905 if self.default_dir_name is None:
906 self.default_dir_name = "{pf}\\" + name
907 if self.default_group_name is None:
908 self.default_group_name = name
909
910 if self.iss_revision is None:
911 self.iss_revision = 0
912 if self.output_basename is None:
913 self.output_basename = "%s-%s-%d" \
914 % (name, self.distribution.get_version(),
915 self.iss_revision)
916
917 def run(self, install_options = None):
918 """Execute the command. install_options if given, should be a
919 directory of additional options to set in the install step"""
920 # Obviously have to build before we can install
921
922 if not self.skip_build:
923 self.run_command('build')
924
925 # Install in a temporary directory
926 install = self.reinitialize_command('install')
927 install.root = self.bdist_dir
928 if install_options is not None:
929 for key, value in install_options.items():
930 setattr(install, key, value)
931 if os.name != 'nt':
932 # Must force install to use the 'nt' scheme;
933 install.select_scheme('nt')
934
935 self.announce("installing to %s" % self.bdist_dir)
936 install.ensure_finalized()
937 install.run()
938
939 # Create the iss file
940 iss_file = os.path.join(self.bdist_dir, self.iss_name)
941 self.execute(write_file, (iss_file, self.generate_iss()),
942 "Create Inno Setup script file %s" % iss_file)
943
944 # and invoke
945 if self.run_inno:
946 self.spawn(["iscc", iss_file])
947
948 def generate_iss(self):
949 """Return the contents of the iss file as list of strings, one
950 string per line"""
951
952 # first, turn the icons entries into a more usable form
953 icons = {}
954 for item in self.icons_entries:
955 icons[item.filename] = item
956
957 iss = []
958
959 name = self.distribution.get_name()
960 iss.extend(["[Setup]",
961 "AppName=" + name,
962 "AppVerName=" + name + " "+self.distribution.get_version(),
963 "DefaultDirName=" + self.default_dir_name,
964 "DefaultGroupName=" + self.default_group_name,
965 ])
966 if self.copyright:
967 iss.append("AppCopyright=" + self.copyright)
968 if self.license_file:
969 iss.append("LicenseFile=" + self.license_file)
970
971 iss.append("OutputBasefilename=" + self.output_basename)
972
973 iss.append("")
974 iss.append("[Files]")
975
976 install = self.get_finalized_command("install")
977 install_scripts = self.get_finalized_command("install_scripts")
978 script_files = install_scripts.get_outputs()
979 prefixlen = len(self.bdist_dir) + len(os.sep)
980 for filename in install.get_outputs():
981 filename = filename[prefixlen:]
982 icon = icons.get(filename)
983 dirname = os.path.dirname(filename)
984 if os.name != "nt":
985 # change the separators to \ on non-windos systems
986 filename = string.join(string.split(filename, os.sep), "\\")
987 dirname = string.join(string.split(dirname, os.sep), "\\")
988 line = 'Source: "%s"' % filename
989 if icon is not None:
990 # install it as defined in the icon object
991 backslash = string.rfind(icon.install_name, "\\")
992 if backslash >= 0:
993 dirname = icon.install_name[:backslash]
994 basename = icon.install_name[backslash + 1:]
995 else:
996 dirname = ""
997 basename = icon.install_name
998 line = '%s; DestDir: "%s"; DestName: "%s"' % (line, dirname,
999 basename)
1000 else:
1001 line = line + '; DestDir: "{app}\\%s"' % (dirname)
1002 iss.append(line)
1003
1004 iss.append("")
1005 iss.append("[Icons]")
1006 for icon in self.icons_entries:
1007 line = 'Name: "{group}\\%s"; Filename: "%s";' \
1008 % (icon.title, icon.install_name)
1009 iss.append(line)
1010
1011 return iss
1012
1013
1014 class InnoIconItem:
1015
1016 """Describe one item for the start menu for the Inno Setup installer"""
1017
1018 def __init__(self, filename, title, install_name = None):
1019 self.filename = filename
1020 self.title = title
1021 if install_name is not None:
1022 self.install_name = install_name
1023 else:
1024 self.install_name = filename
1025
1026
1027 class thuban_bdist_inno(bdist_inno):
1028
1029 """Thuban specific Inno Setup stuff"""
1030
1031 def run(self):
1032 install_options = {
1033 "prefix": ".",
1034 "install_lib": "$base",
1035 "install_data": "$base",
1036 "install_scripts": "$base",
1037 "warn_dir": 0,
1038 "extra_files": ["COPYING", "Lib/proj.dll"],
1039 }
1040 # don't make a symlink because we're simulating windows, so
1041 # that we can generate the iss-file even on Linux
1042 install_options["do_symlink"] = 0
1043
1044 bdist_inno.run(self, install_options)
1045
1046 class thuban_build_docs(Command):
1047
1048 """Command to generate documentation from source code."""
1049
1050 description = "Generate documentation."
1051
1052 user_options = []
1053
1054 def initialize_options(self): pass
1055
1056 def finalize_options(self): pass
1057
1058 def run(self, install_options = None):
1059 self.spawn(["happydoc", "-d./Doc", "./Thuban"])
1060
1061 class thuban_build_ext(build_ext):
1062
1063 """Extend the build_ext command to optionally include the
1064 GDAL extension.
1065 """
1066
1067 user_options = build_ext.user_options[:]
1068 user_options.extend([("with-gdal", None, "Include GDAL support."),
1069 ("without-gdal", None, "Don't include GDAL support.")])
1070
1071 boolean_options = ["with-gdal"]
1072 negative_opt = {'without-gdal' : 'with-gdal'}
1073
1074 def initialize_options(self):
1075 self.with_gdal = True
1076 build_ext.initialize_options(self)
1077
1078 def finalize_options(self):
1079 build_ext.finalize_options(self)
1080 if self.with_gdal and include_gdal:
1081 self.extensions.append(Extension("Lib.gdalwarp",
1082 [ext_dir + "/thuban/gdalwarp.cpp",
1083 ext_dir + "/thuban/cpl_mfile.cpp",
1084 ext_dir + "/thuban/bmpdataset.cpp"],
1085 include_dirs = gdal_cs_params[CS_INCDIRS] +
1086 [ext_dir + "/thuban/"],
1087 define_macros = gdal_cs_params[CS_DEFS],
1088 library_dirs = gdal_cs_params[CS_LIBDIRS],
1089 libraries = gdal_cs_params[CS_LIBS]))
1090
1091 def run(self, install_options = None):
1092 build_ext.run(self)
1093
1094 #
1095 # Run the script
1096 #
1097
1098 long_description = """\
1099 Thuban is a viewer for geographic data written in Python
1100 """
1101
1102 setup(name = "Thuban",
1103 version = "1.0rc1",
1104 description = "Geographic data viewer",
1105 long_description = long_description,
1106 licence = "GPL",
1107 author = "Intevation GmbH",
1108 author_email = "[email protected]",
1109 url = "http://thuban.intevation.de/",
1110
1111 scripts = ["thuban.py"],
1112 packages = ["Thuban", "Thuban.Lib", "Thuban.Model", "Thuban.UI"],
1113 ext_modules = extensions,
1114 py_modules = py_modules,
1115 data_files = data_files,
1116
1117 # defaults for the install command
1118 options = {"install":
1119 # prefix defaults to python's prefix normally
1120 {"prefix": prefix,
1121 # make sure both libs and scripts are installed in the
1122 # same directory.
1123 "install_lib": "$base/lib/thuban",
1124 "install_scripts": "$base/lib/thuban",
1125 "install_data": "$base/lib/thuban",
1126
1127 # Don't print warning messages about the lib dir not
1128 # being on Python's path. The libraries are Thuban
1129 # specific and are installed just for Thuban. They'll
1130 # be automatically on Python's path when Thuban is run
1131 "warn_dir": 0,
1132 },
1133 "bdist_inno":
1134 {"icons_entries": [InnoIconItem(".\\thuban.py",
1135 "Start Thuban",
1136 "{app}\\thuban.pyw")],
1137 "license_file": "COPYING",
1138 }
1139 },
1140 cmdclass = {"build_py": thuban_build_py,
1141 "install_local": InstallLocal,
1142 "install": ThubanInstall,
1143 "bdist_rpm": thuban_bdist_rpm,
1144 "bdist_inno": thuban_bdist_inno,
1145 "data_dist": data_dist,
1146 "build_docs": thuban_build_docs,
1147 "build_ext": thuban_build_ext
1148 })
1149
1150

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26