/[thuban]/branches/WIP-pyshapelib-bramz/setup.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/setup.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 671 - (hide annotations)
Tue Apr 15 18:09:47 2003 UTC (21 years, 10 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 38461 byte(s)
* Thuban/__init__.py (_): Implement the translation function for
real using the python gettext module.

* Thuban/UI/classifier.py (ClassTable.GetRowLabelValue): Don't
translate empty strings.

* Thuban/UI/application.py (ThubanApplication.read_startup_files):
Add a missing space to a warning message

* po/README: New. Notes about the management of the translation
files.

* po/Makefile: New. Makefile to help manage the translation files.

* po/es.po: New. Spanish translation by Daniel Calvelo Aros

* MANIFEST.in: Include the *.mo files in Resources/Locale and the
translations and support files in po/

* setup.py (data_files): Add the *.mo files to the data_files too

* README: Add note about the translations when building from CVS

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26