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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26