/[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 54 - (hide annotations)
Tue Sep 11 11:45:09 2001 UTC (23 years, 5 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 24735 byte(s)
	* setup.py (InnoIconItem): fix typo

	(thuban_bdist_inno.run):
	(bdist_inno.run): Move the decision not to create symlinks on
	non-nt platforms to thuban_bdist_inno and do it unconditinally
	since we never want to create the symlinks here

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