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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.8  
changed lines
  Added in v.1717

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26