/[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 18 - (show annotations)
Mon Sep 3 16:25:09 2001 UTC (23 years, 6 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 23111 byte(s)
* Thuban/UI/mainwindow.py (MainWindow.AddLayer): Fit the map to
the window when the first layer is added to the map.

* setup.py (ThubanInstall.run): Honor the build root (self.root)
when linking thuban.py to <prefix>/bin

1 # Copyright (c) 2001 by Intevation GmbH
2 # Authors:
3 # Bernhard Herzog <[email protected]>
4 #
5 # This program is free software under the GPL (>=v2)
6 # Read the file COPYING coming with Thuban for details.
7
8 """Distutils setup script for Thuban."""
9
10 __version__ = "$Revision$"
11
12 # Configuration:
13 #
14 # depending on your platform you may have to configure some variables by
15 # hand below.
16 #
17
18 import os
19 from types import TupleType
20 from distutils.core import setup, Extension, Command
21 from distutils.command.install import install
22 from distutils.command.build_py import build_py
23 from distutils.file_util import write_file
24 from distutils.util import convert_path, change_root
25
26 import distutils
27
28 from string import split
29 import string
30
31 if os.name == "posix":
32 ###################################################################
33 # Posix configuration. Adapt this if you're running some kind of
34 # Unix like system.
35
36 # Directories where Proj4 is installed
37 proj4_prefix = "/usr/local/"
38 proj4_incdir = os.path.join(proj4_prefix, "include")
39 proj4_libdir = os.path.join(proj4_prefix, "lib")
40 proj4_lib = "proj"
41
42
43 # You shpuldn't have to modify anything below here
44 ###################################################################
45
46 # The installation prefix (similar to autoconf's --prefix). This is
47 # only the default value, you can override it on the command line
48 # with the install command's --prefix option
49 prefix = "/usr/local/"
50
51 # On POSIX-systems we run wxgtk-config to determine the C++-compiler
52 # flags
53 wx_config_script = "wxgtk-config"
54 # These lists will be filled automatically below
55 wx_defs = []
56 wx_incdirs = []
57 wx_libdirs = []
58 wx_libs = []
59
60 elif os.name == "nt":
61 #################################################################
62 # Windows configuration.
63 #
64
65 # Directories where Proj4 is installed
66 proj4_prefix = r"D:\cygwin\home\user\proj-4.4.3\src"
67 proj4_incdir = proj4_prefix
68 proj4_libdir = proj4_prefix
69 proj4_lib = "proj_i"
70
71 # Define include and lib directories for wxWindows and
72 wx_prefix = r"D:\wx230"
73 wx_inc = os.path.join(wx_prefix, "include")
74 wx_lib = os.path.join(wx_prefix, "lib")
75
76 #
77 # Unless you use a wxPython version other than 2.3.1, you probably
78 # shouldn't have to modify anything below here
79 ##################################################################
80
81 # Installation prefix. Just install relative to current directory by
82 # default. This is only the default value, you can override it on
83 # the command line with the install command's --prefix option
84 prefix = r"install"
85
86 # There doesn't seem to be an easy way to get at the wx compiler
87 # flags, so we define them here. These flags work for us with
88 # wxPython 2.3.1. They may have to be modified for other versions.
89
90 # there's no config script.
91 wx_config_script = ""
92
93 # the values of wx_defs and wx_libs. copied from the wxPython
94 # setup.py
95 wx_defs = [ ('WIN32', None), # Some of these are no longer
96 ('__WIN32__', None), # necessary. Anybody know which?
97 ('_WINDOWS', None),
98 ('__WINDOWS__', None),
99 ('WINVER', '0x0400'),
100 ('__WIN95__', None),
101 ('STRICT', None),
102
103 ('__WXMSW__', None),
104 ('WXUSINGDLL', '1'),
105
106 ('SWIG_GLOBAL', None),
107 ('HAVE_CONFIG_H', None),
108 ('WXP_USE_THREAD', '1'),
109 ]
110
111 wx_incdirs = [wx_inc]
112 wx_libdirs = [wx_lib]
113 wx_libs = ["wx23_1h"]
114 wx_libs = wx_libs + ['kernel32', 'user32', 'gdi32', 'comdlg32',
115 'winspool', 'winmm', 'shell32', 'oldnames',
116 'comctl32', 'ctl3d32', 'odbc32', 'ole32', 'oleaut32',
117 'uuid', 'rpcrt4', 'advapi32', 'wsock32']
118 else:
119 raise RuntimeError("Unsupported platform " + os.name)
120
121
122 ######################################################################
123 #
124 # There's nothing beyond this point that has to be modified for a
125 # normal installation
126 #
127 ######################################################################
128
129
130 #
131 # Functions to determine wxWindows config on POSIX systems
132 #
133
134 def run_script(cmdline):
135 """Run command and return its stdout or none in case of errors"""
136 pipe = os.popen(cmdline)
137 result = pipe.read()
138 if pipe.close() is not None:
139 print '"' + cmdline + '"', 'failed'
140 return None
141 return result
142
143
144 def run_wx_script(command):
145 # first, determine the C++ preprocessor flags
146 flags = run_script(command + ' --cxxflags ')
147 if flags is None:
148 return 0
149 for flag in split(flags):
150 start = flag[:2]
151 value = flag[2:]
152 if start == "-I":
153 wx_incdirs.append(value)
154 elif start == "-D":
155 wx_defs.append((value, None))
156
157 # determine the library flags
158 flags = run_script(command + ' --libs')
159 if flags is None:
160 return 0
161 for flag in split(flags):
162 start = flag[:2]
163 value = flag[2:]
164 if start == "-L":
165 wx_libdirs.append(value)
166 elif start == "-l":
167 wx_libs.append(value)
168
169 if wx_config_script:
170 # if there's a wx config script, run it to determine the configuration
171 run_wx_script(wx_config_script)
172
173
174
175 #
176 # Define some extension and python modules
177 #
178 # The C-extension names are prefixed woth "Lib." so they get put into
179 # the Lib/ subdirectory. Lib/ is not really a package but distutils
180 # doesn't care
181
182 # subdirectory containing the extensions
183 ext_dir = "extensions"
184
185 # subdirectory with some shapelib files
186 shp_dir = ext_dir + "/shapelib"
187
188 # lists to fill with the module descriptions
189 extensions = []
190 py_modules = []
191
192
193 #
194 # Thuban specific modules
195 #
196
197 extensions.append(Extension("Lib.wxproj",
198 [ext_dir + "/thuban/wxproj.cpp",
199 shp_dir + "/shpopen.c"],
200 include_dirs = [shp_dir, proj4_incdir] +wx_incdirs,
201 define_macros = wx_defs,
202 library_dirs = [proj4_libdir] + wx_libdirs,
203 libraries = [proj4_lib] + wx_libs))
204
205 #
206 # shapelib wrappers are also distributed with thuban
207 #
208
209 extensions.append(Extension("Lib.shapelibc",
210 [ext_dir + "/pyshapelib/shapelib_wrap.c",
211 shp_dir + "/shpopen.c"],
212 include_dirs = [shp_dir]))
213 extensions.append(Extension("Lib.dbflibc",
214 [ext_dir + "/pyshapelib/dbflib_wrap.c",
215 shp_dir + "/dbfopen.c"],
216 include_dirs = [shp_dir]))
217 for name in ("shapelib", "dbflib"):
218 py_modules.append(ext_dir + "/pyshapelib/" + name)
219
220 #
221 # PROJ4 bindings are also distributed with thuban
222 #
223 extensions.append(Extension("Lib.Projectionc",
224 [ext_dir + "/pyprojection/Projection_wrap.c"],
225 include_dirs = [proj4_incdir],
226 library_dirs = [proj4_libdir],
227 libraries = [proj4_lib]))
228 py_modules.append(ext_dir + "/pyprojection/Projection")
229
230
231 #
232 # Data files
233 #
234
235 data_files = []
236
237 # bitmaps
238 dir = "Resources/Bitmaps"
239 bitmaps = []
240 for file in os.listdir(os.path.join("Resources", "Bitmaps")):
241 if string.lower(file[-4:]) == ".xpm":
242 bitmaps.append(dir + '/' + file)
243 data_files.append((dir, bitmaps))
244
245 #
246 # Command definitions
247 #
248 # So far distutils are only meant to distribute python extensions, not
249 # complete applications, so we have to redefine a few commands
250
251
252
253 class InstallLocal(Command):
254
255 """
256 A new install command to just link (or copy, on non-POSIX systems)
257 the extension modules to the top directory so that Thuban can be run
258 directly from the source dir.
259 """
260
261 description =\
262 "Create some symlink so you can run thubanfrom the source directory"
263
264 user_options = [
265 ('skip-build', None, "skip the build steps"),
266 ]
267
268 def initialize_options (self):
269 self.extensions = None
270 self.build_dir = None
271 self.skip_build = None
272
273 def finalize_options (self):
274 self.set_undefined_options("install",
275 ("build_lib", "build_dir"),
276 ('skip_build', 'skip_build'))
277 self.extensions = self.distribution.ext_modules
278
279 def run(self):
280 # Make sure we have built everything we need first
281 self.build()
282
283 # now do the work. Simply link or copy the Lib dir
284 libdir = os.path.join(self.build_dir, "Lib")
285 if os.name == "posix":
286 # on posix, just lilnk the Lib dir
287 self.link_dir(libdir, "Lib")
288 else:
289 self.copy_tree(libdir, "Lib")
290
291 def link_dir(self, src, dest):
292 """Create a symbolic link dest pointing to src"""
293 if self.verbose:
294 self.announce("symlinking %s -> %s" % (src, dest))
295 if self.dry_run:
296 return
297
298 if not (os.path.exists(dest) and os.path.samefile(src, dest)):
299 os.symlink(src, dest)
300
301 def build (self):
302 if not self.skip_build:
303 if self.distribution.has_pure_modules():
304 self.run_command('build_py')
305 if self.distribution.has_ext_modules():
306 self.run_command('build_ext')
307
308
309
310 class thuban_build_py(build_py):
311
312 """
313 A new build_py that can deal with both packages and modules in one
314 distribution.
315 """
316
317 def run(self):
318 """The same the as the original in build_py revision 1.33 except
319 that this allows both packages and modules to be in one
320 distribution
321 """
322 if not self.py_modules and not self.packages:
323 return
324
325 # Now we're down to two cases: 'py_modules' only and 'packages' only.
326 if self.py_modules:
327 self.build_modules()
328 if self.packages:
329 self.build_packages()
330
331 self.byte_compile(self.get_outputs(include_bytecode=0))
332
333 def find_modules (self):
334 """Thuban specific version of build_py.find_modules. Unlike the
335 original version, we assume that the modules in self.py_modules
336 can contain directories and are all to be placed into the same
337 subdirectory, Lib, in the build directory. This is achieved by
338 returning the modules as a list (package, module, filename)
339 where package is 'Lib', module is the basename of the module name
340 and filename is the filename relative to the package root.
341 """
342 modules = []
343 for module in self.py_modules:
344 module_base = os.path.basename(module)
345 module_file = module + ".py"
346 if not self.check_module(module, module_file):
347 continue
348
349 modules.append(("Lib", module_base, module_file))
350 return modules
351
352 def find_all_modules (self):
353 # same as find_all_modules of the original build_py command
354 # (rev. 1.33) but handle installations with both modules and
355 # packages. Needed here so tha the get_outputs works correctly
356 modules = []
357 if self.py_modules:
358 modules.extend(self.find_modules())
359 if self.packages:
360 for package in self.packages:
361 package_dir = self.get_package_dir(package)
362 m = self.find_package_modules(package, package_dir)
363 modules.extend(m)
364
365 return modules
366
367
368
369 class ThubanInstall(install):
370
371 """
372 Thuban specific install command.
373
374 Extend the standard install command to symlink the installed script
375 to $prefix/bin/
376 """
377
378 user_options = install.user_options[:]
379 user_options.extend([("do-symlink", None,
380 "Create a symlink to the script in <prefix>/bin."
381 "(default on posix systems and only relevant there)"),
382
383 ("extra-files", None,
384 "List of filenames or (src, dest) pairs describing "
385 " extra files to install "
386 "(can only be set from witin setup.py"),
387 ])
388
389 boolean_options = install.boolean_options[:]
390 boolean_options.append("do-symlink")
391
392 def initialize_options(self):
393 self.do_symlink = None
394 self.extra_files = []
395 install.initialize_options(self)
396
397 def finalize_options(self):
398 if self.do_symlink is None:
399 if os.name == "posix":
400 self.do_symlink = 1
401 else:
402 self.do_symlink = 0
403 install.finalize_options(self)
404
405 def run(self):
406 install.run(self)
407 for item in self.extra_files:
408 if type(item) == TupleType:
409 src, dest = item
410 else:
411 src = dest = item
412 self.copy_file(convert_path(src),
413 os.path.join(self.root, convert_path(dest)))
414
415 if os.name == "posix" and self.do_symlink:
416 scriptfile = os.path.join(self.install_scripts, "thuban.py")
417 bindir = os.path.join(self.prefix, "bin")
418 if self.root:
419 bindir = change_root(self.root, bindir)
420 binfile = os.path.join(bindir, "thuban")
421 self.mkpath(bindir)
422 self.copy_file(scriptfile, binfile, link="sym")
423
424 def get_outputs (self):
425 outputs = install.get_outputs(self)
426 for item in self.extra_files:
427 if type(item) == TupleType:
428 src, dest = item
429 else:
430 src = dest = item
431 outputs.append(os.path.join(self.root, convert_path(dest)))
432 return outputs
433
434 class bdist_inno(Command):
435
436 """Command to create a windows installer with Inno Setup"""
437
438 description = "Create a windows installer with Inno Setup"
439
440 user_options = [
441 ('skip-build', None, "skip the build steps"),
442 ('bdist-dir=', None,
443 "temporary directory for creating the distribution"),
444 ('run-inno', None,
445 "Run inno-setup to create the installer. On by default on nt"),
446 ('iss-name', None,
447 "The name of the iss file to generate. "
448 "Shouldn't contain directories"),
449
450 # Parameters for the Inno Setup script
451 ('copyright', None, "Copyright notice for the Inno Setup file"),
452 ('default-dir-name', None,
453 "Default installation directory. Defaults to '{pf}\\<name>'"),
454 ('default-group-name', None,
455 "Default program group name. Defaults to <name>'"),
456 ("license-file", None, "File containing the license."),
457 ("output-basename", None,
458 "Base filename for the Inno Setup output "
459 "(defaults to <name>-<version>-<issrevision>)."),
460 ("iss-revision", None,
461 "revision of the generated installer of the package version"),
462
463 ("icons-entries", None,
464 "List if InnoIconItems "
465 "(this can only be set from inside the setup.py script)"),
466 ]
467
468 boolean_options = ["do-symlink"]
469
470 def initialize_options(self):
471 self.skip_build = 0
472 self.bdist_dir = None
473 self.run_inno = None
474 self.iss_name = None
475 self.copyright = ""
476 self.default_dir_name = None
477 self.default_group_name = None
478 self.license_file = None
479 self.output_basename = None
480 self.iss_revision = None
481 self.icons_entries = []
482
483 def finalize_options(self):
484 self.set_undefined_options("install",
485 ('skip_build', 'skip_build'))
486 if self.bdist_dir is None:
487 bdist_base = self.get_finalized_command('bdist').bdist_base
488 self.bdist_dir = os.path.join(bdist_base, 'inno')
489
490 if self.run_inno is None:
491 self.run_inno = os.name == "nt"
492
493 name = self.distribution.get_name()
494 if self.iss_name is None:
495 self.iss_name = name + '.iss'
496
497 if self.default_dir_name is None:
498 self.default_dir_name = "{pf}\\" + name
499 if self.default_group_name is None:
500 self.default_group_name = name
501
502 if self.iss_revision is None:
503 self.iss_revision = 0
504 if self.output_basename is None:
505 self.output_basename = "%s-%s-%d" \
506 % (name, self.distribution.get_version(),
507 self.iss_revision)
508
509 def run(self, install_options = None):
510 """Execute the command. install_options if given, should be a
511 directory of additional options to set in the install step"""
512 # Obviously have to build before we can install
513 if not self.skip_build:
514 self.run_command('build')
515
516 # Install in a temporary directory
517 install = self.reinitialize_command('install')
518 install.root = self.bdist_dir
519 if install_options is not None:
520 for key, value in install_options.items():
521 setattr(install, key, value)
522 if os.name != 'nt':
523 # Must force install to use the 'nt' scheme;
524 install.select_scheme('nt')
525 # don't make a symlink because we're simulating windows, so
526 # that we can generate the iss-file even on Linux
527 install.do_symlink = 0
528
529 self.announce("installing to %s" % self.bdist_dir)
530 install.ensure_finalized()
531 install.run()
532
533 # Create the iss file
534 iss_file = os.path.join(self.bdist_dir, self.iss_name)
535 self.execute(write_file, (iss_file, self.generate_iss()),
536 "Create Inno Setup script file %s" % iss_file)
537
538 # and invoke
539 if self.run_inno:
540 self.spawn(["iscc", iss_file])
541
542 def generate_iss(self):
543 """Return the contents of the iss file as list of strings, one
544 string per line"""
545
546 # first, turn the icons entries into a more usable form
547 icons = {}
548 for item in self.icons_entries:
549 icons[item.filename] = item
550
551 iss = []
552
553 name = self.distribution.get_name()
554 iss.extend(["[Setup]",
555 "AppName=" + name,
556 "AppVerName=" + name + " "+self.distribution.get_version(),
557 "DefaultDirName=" + self.default_dir_name,
558 "DefaultGroupName=" + self.default_group_name,
559 ])
560 if self.copyright:
561 iss.append("AppCopyright=" + self.copyright)
562 if self.license_file:
563 iss.append("LicenseFile=" + self.license_file)
564
565 iss.append("OutputBasefilename=" + self.output_basename)
566
567 iss.append("")
568 iss.append("[Files]")
569
570 install = self.get_finalized_command("install")
571 install_scripts = self.get_finalized_command("install_scripts")
572 script_files = install_scripts.get_outputs()
573 prefixlen = len(self.bdist_dir) + len(os.sep)
574 for filename in install.get_outputs():
575 filename = filename[prefixlen:]
576 icon = icons.get(filename)
577 dirname = os.path.dirname(filename)
578 if os.name != "nt":
579 # change the separators to \ on non-windos systems
580 filename = string.join(string.split(filename, os.sep), "\\")
581 dirname = string.join(string.split(dirname, os.sep), "\\")
582 line = 'Source: "%s"' % filename
583 if icon is not None:
584 # install it as defined in the icon object
585 backslash = string.rfind(icon.install_name, "\\")
586 if backslash >= 0:
587 dirname = icon.install_name[:backslash]
588 basename = icon.install_name[backslash + 1:]
589 else:
590 dirname = ""
591 basename = icon.install_name
592 line = '%s; DestDir: "%s"; DestName: "%s"' % (line, dirname,
593 basename)
594 else:
595 line = line + '; DestDir: "{app}\\%s"' % (dirname)
596 iss.append(line)
597
598 iss.append("")
599 iss.append("[Icons]")
600 for icon in self.icons_entries:
601 line = 'Name: "{group}\\%s"; Filename: "%s";' \
602 % (icon.title, icon.install_name)
603 iss.append(line)
604
605 return iss
606
607
608 class InnoIconItem:
609
610 """Describe one item for he start menu for the Inno Setup installer"""
611
612 def __init__(self, filename, title, install_name = None):
613 self.filename = filename
614 self.title = title
615 if install_name is not None:
616 self.install_name = install_name
617 else:
618 self.install_name = filename
619
620
621 class thuban_bdist_inno(bdist_inno):
622
623 """Thuban specific Inno Setup stuff"""
624
625 def run(self):
626 install_options = {
627 "prefix": ".",
628 "install_scripts": "$base",
629 "warn_dir": 0,
630 "extra_files": ["COPYING", "Lib/proj.dll"],
631 }
632 bdist_inno.run(self, install_options)
633
634
635 #
636 # Run the script
637 #
638
639
640 long_description = """\
641 Thuban is a viewer for geographic data written in Python
642 """
643
644 setup(name = "Thuban",
645 version = "0.0.3",
646 description = "Geographic data viewer",
647 long_description = long_description,
648 licence = "GPL",
649 author = "Intevation GmbH",
650 author_email = "[email protected]",
651 url = "ftp:intevation.de/",
652
653 scripts = ["thuban.py"],
654 packages = ["Thuban", "Thuban.Lib", "Thuban.Model", "Thuban.UI"],
655 ext_modules = extensions,
656 py_modules = py_modules,
657 data_files = data_files,
658
659 # defaults for the install command
660 options = {"install":
661 # prefix defaults to python's prefix normally
662 {"prefix": prefix,
663 # make sure both libs and scripts are installed in the
664 # same directory.
665 "install_lib": "$base/thuban",
666 "install_scripts": "$base/thuban",
667 "install_data": "$base/thuban",
668
669 # Don't print warning messages about the lib dir not
670 # being on Python's path. The libraries are Thuban
671 # specific and are installed just for Thuban. They'll
672 # be automatically on Python's path when Thuban is run
673 "warn_dir": 0,
674 },
675 "bdist_inno":
676 {"icons_entries": [InnoIconItem(".\\thuban.py",
677 "Start Thuban",
678 "{app}\\thuban.pyw")],
679 "license_file": "COPYING",
680 }
681 },
682 cmdclass = {"build_py": thuban_build_py,
683 "install_local": InstallLocal,
684 "install": ThubanInstall,
685 "bdist_inno": thuban_bdist_inno
686 })
687
688

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26