/[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 1229 by jonathan, Wed Jun 18 14:46:30 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 66  elif os.name == "nt": Line 88  elif os.name == "nt":
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
92        wx_prefix = r"D:\wx240"
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
# 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 232  py_modules.append(ext_dir + "/pyprojecti Line 297  py_modules.append(ext_dir + "/pyprojecti
297  data_files = []  data_files = []
298    
299  # bitmaps  # bitmaps
300  dir = "Resources/Bitmaps/"  for d, pattern in [("Resources/Bitmaps", "Resources/Bitmaps/*.xpm"),
301  bitmaps = []                     ("Resources/Locale", "Resources/Locale/*/LC_MESSAGES/*.mo")
302  for file in os.listdir(os.path.join("Resources", "Bitmaps")):                     ]:
303      if string.lower(file[-4:]) == ".xpm":      data_files.append((d, glob.glob(pattern)))
         bitmaps.append(dir + file)  
 data_files.append((dir, bitmaps))  
304    
305  #  #
306  #       Command definitions  #       Command definitions
307  #  #
308  # So far distutils are only meant to distribute python extensions, not  # So far distutils are only meant to distribute python extensions, not
309  # complete applications, so we have to redefine a few commands  # complete applications, so we have to redefine a few commands
310    #
311    
312    
313    # Much of the data_dist command is directly copied from the distutils'
314    # sdist command
315    class data_dist(Command):
316    
317        description = "create a data distribution (tarball, zip file, etc.)"
318    
319        user_options = [
320            ('formats=', None,
321             "formats for source distribution (comma-separated list)"),
322            ('keep-temp', 'k',
323             "keep the distribution tree around after creating " +
324             "archive file(s)"),
325            ('dist-dir=', 'd',
326             "directory to put the source distribution archive(s) in "
327             "[default: dist]"),
328            ]
329    
330        boolean_options = ['keep-temp']
331    
332        def initialize_options (self):
333            self.formats = None
334            self.keep_temp = 0
335            self.dist_dir = None
336    
337        def finalize_options (self):
338            self.ensure_string_list('formats')
339            if self.formats is None:
340                self.formats = ["zip"]
341            bad_format = archive_util.check_archive_formats(self.formats)
342            if bad_format:
343                raise DistutilsOptionError, \
344                      "unknown archive format '%s'" % bad_format
345    
346            if self.dist_dir is None:
347                self.dist_dir = "dist"
348    
349    
350        def run(self):
351            # 'filelist' contains the list of files that will make up the
352            # manifest
353            self.filelist = FileList()
354            
355            # Do whatever it takes to get the list of files to process.
356            # File list is accumulated in 'self.filelist'.
357            self.get_file_list()
358    
359            # Otherwise, go ahead and create the source distribution tarball,
360            # or zipfile, or whatever.
361            self.make_distribution()
362    
363        def get_file_list(self):
364            """Figure out the list of files to include in the data
365            distribution, and put it in 'self.filelist'.
366            """
367            self.filelist.findall("Data")
368            self.filelist.include_pattern("*", anchor = 0)
369            self.filelist.exclude_pattern(r'/(RCS|CVS)/.*', is_regex=1)
370            self.filelist.sort()
371            self.filelist.remove_duplicates()
372    
373        def make_release_tree(self, base_dir, files):
374            """Create the directory tree that will become the source
375            distribution archive.  All directories implied by the filenames in
376            'files' are created under 'base_dir', and then we hard link or copy
377            (if hard linking is unavailable) those files into place.
378            Essentially, this duplicates the developer's source tree, but in a
379            directory named after the distribution, containing only the files
380            to be distributed.
381            """
382            # Create all the directories under 'base_dir' necessary to
383            # put 'files' there; the 'mkpath()' is just so we don't die
384            # if the manifest happens to be empty.
385            self.mkpath(base_dir)
386            dir_util.create_tree(base_dir, files,
387                                 verbose=self.verbose, dry_run=self.dry_run)
388    
389            # And walk over the list of files, either making a hard link (if
390            # os.link exists) to each one that doesn't already exist in its
391            # corresponding location under 'base_dir', or copying each file
392            # that's out-of-date in 'base_dir'.  (Usually, all files will be
393            # out-of-date, because by default we blow away 'base_dir' when
394            # we're done making the distribution archives.)
395        
396            if hasattr(os, 'link'):        # can make hard links on this system
397                link = 'hard'
398                msg = "making hard links in %s..." % base_dir
399            else:                           # nope, have to copy
400                link = None
401                msg = "copying files to %s..." % base_dir
402    
403            if not files:
404                self.warn("no files to distribute -- empty manifest?")
405            else:
406                self.announce(msg)
407            for file in files:
408                if not os.path.isfile(file):
409                    self.warn("'%s' not a regular file -- skipping" % file)
410                else:
411                    dest = os.path.join(base_dir, file)
412                    self.copy_file(file, dest, link=link)
413    
414    
415        def make_distribution (self):
416            """Create the source distribution(s).  First, we create the release
417            tree with 'make_release_tree()'; then, we create all required
418            archive files (according to 'self.formats') from the release tree.
419            Finally, we clean up by blowing away the release tree (unless
420            'self.keep_temp' is true).  The list of archive files created is
421            stored so it can be retrieved later by 'get_archive_files()'.
422            """
423            # Don't warn about missing meta-data here -- should be (and is!)
424            # done elsewhere.
425            base_dir = "Thuban-data-" + self.distribution.get_version()
426            base_name = os.path.join(self.dist_dir, base_dir)
427    
428            self.make_release_tree(base_dir, self.filelist.files)
429            archive_files = []              # remember names of files we create
430            for fmt in self.formats:
431                file = self.make_archive(base_name, fmt, base_dir=base_dir)
432                archive_files.append(file)
433    
434            self.archive_files = archive_files
435    
436            if not self.keep_temp:
437                dir_util.remove_tree(base_dir, self.verbose, self.dry_run)
438    
439    
440    
# Line 256  class InstallLocal(Command): Line 447  class InstallLocal(Command):
447      """      """
448    
449      description =\      description =\
450          "Create some symlink so you can run thubanfrom the source directory"          "Create some symlinks so you can run thuban from the source directory"
451    
452      user_options = [      user_options = [
         ('debug', 'g', "compile/link with debugging information"),  
453          ('skip-build', None, "skip the build steps"),          ('skip-build', None, "skip the build steps"),
454            ('create-init-module', None,
455             "Create the thubaninit.py module to ease use of Thuban as a library"),
456            ('dont-create-init-module', None,
457             "Do not create the thubaninit.py module"),
458          ]          ]
459    
460        boolean_options = ["create-init-module"]
461        negative_opt = {'dont-create-init-module' : 'create-init-module'}
462    
463    
464      def initialize_options (self):      def initialize_options (self):
465          self.extensions = None          self.extensions = None
466          self.build_dir = None          self.build_dir = None
467          self.skip_build = None          self.skip_build = None
468          self.debug = None          self.create_init_module = None
469    
470      def finalize_options (self):      def finalize_options (self):
471          self.set_undefined_options("install",          self.set_undefined_options("install",
472                                     ("build_lib", "build_dir"),                                     ("build_lib", "build_dir"),
473                                     ('skip_build', 'skip_build'))                                     ('skip_build', 'skip_build'))
474          self.extensions = self.distribution.ext_modules          self.extensions = self.distribution.ext_modules
475            if self.create_init_module is None:
476                # by default we create the init module
477                self.create_init_module = 1
478    
479      def run(self):      def run(self):
480          # Make sure we have built everything we need first          # Make sure we have built everything we need first
# Line 282  class InstallLocal(Command): Line 483  class InstallLocal(Command):
483          # now do the work. Simply link or copy the Lib dir          # now do the work. Simply link or copy the Lib dir
484          libdir = os.path.join(self.build_dir, "Lib")          libdir = os.path.join(self.build_dir, "Lib")
485          if os.name == "posix":          if os.name == "posix":
486              # on posix, just lilnk the Lib dir              # on posix, just link the Lib dir
487              self.link_dir(libdir, "Lib")              self.link_dir(libdir, "Lib")
488          else:          else:
489              self.copy_tree(libdir, "Lib")              self.copy_tree(libdir, "Lib")
490    
491            # create the init module if desired
492            if self.create_init_module:
493                # create the init module
494                initfilename = "thubaninit.py"
495                contents = thubaninit_contents("")
496                self.execute(write_file, (initfilename, contents),
497                             "Create %s" % initfilename)
498    
499      def link_dir(self, src, dest):      def link_dir(self, src, dest):
500          """Create a symbolic link dest pointing to src"""          """Create a symbolic link dest pointing to src"""
501          if self.verbose:          if self.verbose:
502              print "symlinking %s -> %s" % (src, dest)              self.announce("symlinking %s -> %s" % (src, dest))
503          if self.dry_run:          if self.dry_run:
504              return              return
505    
# Line 313  class thuban_build_py(build_py): Line 522  class thuban_build_py(build_py):
522      distribution.      distribution.
523      """      """
524    
525        # FIXME: When Thuban can rely on Python 2.3 as the oldest supported
526        # Python release we don't need to override the run and
527        # find_all_modules methods anymore. distutils will allow both python
528        # modules and packages starting with 2.3.
529    
530      def run(self):      def run(self):
531          """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
532          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 562  class thuban_build_py(build_py):
562              modules.append(("Lib", module_base, module_file))              modules.append(("Lib", module_base, module_file))
563          return modules          return modules
564    
565        def find_all_modules (self):
566            # same as find_all_modules of the original build_py command
567            # (rev. 1.33) but handle installations with both modules and
568            # packages. Needed here so tha the get_outputs works correctly
569            modules = []
570            if self.py_modules:
571                modules.extend(self.find_modules())
572            if self.packages:
573                for package in self.packages:
574                    package_dir = self.get_package_dir(package)
575                    m = self.find_package_modules(package, package_dir)
576                    modules.extend(m)
577    
578            return modules
579    
580    
581    thubaninit_contents_start = """
582    # This module was automatically generated by Thuban's install script
583    '''Import this module once per program (best place is probably the file
584    that ends up as your __main__ module) to be able to import Thuban
585    afterwards.
586    
587    Usage:
588    
589    import thubaninit
590    import Thuban
591    '''
592    import sys, os
593    """
594    
595    thubaninit_contents_thubaninitdir = """
596    sys.path.insert(0, %(thubandir)s)
597    """
598    thubaninit_contents_otherdirs = """
599    # Put the Lib dir into the path. The Lib dir contains some extra Python
600    # modules
601    import Thuban
602    thubandir = os.path.join(Thuban.__path__[0], '..')
603    dir = os.path.join(thubandir, "Lib")
604    if os.path.isdir(dir):
605        sys.path.insert(0, dir)
606    """
607    
608    def thubaninit_contents(thubandir):
609        """Return the contents of the the thubaninit file as a list of lines.
610    
611        The parameter thubandir is the parent directory where the Thuban/
612        package or the empty string if the thubaninit file itself will be
613        located in that direcory as well.
614        """
615        contents = thubaninit_contents_start
616        if thubandir:
617            thubandir = repr(thubandir)
618            contents += thubaninit_contents_thubaninitdir % locals()
619        contents += thubaninit_contents_otherdirs
620        return contents.split("\n")
621    
622    
623  class ThubanInstall(install):  class ThubanInstall(install):
624    
# Line 357  class ThubanInstall(install): Line 628  class ThubanInstall(install):
628      Extend the standard install command to symlink the installed script      Extend the standard install command to symlink the installed script
629      to $prefix/bin/      to $prefix/bin/
630      """      """
631    
632        user_options = install.user_options[:]
633        user_options.extend([("do-symlink", None,
634                              "Create a symlink to the script in <prefix>/bin."
635                            "(default on posix systems and only relevant there)"),
636    
637                             ("extra-files", None,
638                              "List of filenames or (src, dest) pairs describing"
639                              " extra files to install "
640                              "(can only be set from within setup.py"),
641    
642                             ("create-init-module=", None,
643                              "If true, create a module in the site-packages"
644                              " directory that tweaks sys.path to let you easily"
645                              " import thuban modules from outside of thuban."),
646                             ("init-module-dir=", None,
647                              "Directory in which to create the init module."
648                              " Defaults to Python's site-packages directory."),
649                             ])
650    
651        boolean_options = install.boolean_options[:]
652        boolean_options.append("do-symlink")
653        boolean_options.append("create-init-module")
654    
655        def initialize_options(self):
656            self.do_symlink = None
657            self.extra_files = []
658    
659            # initialize the create_init_module flag from the global
660            # determined at runtime
661            self.create_init_module = create_init_module
662            self.init_module_dir = None
663            install.initialize_options(self)
664    
665        def finalize_options(self):
666            if self.do_symlink is None:
667                if os.name == "posix":
668                    self.do_symlink = 1
669                else:
670                    self.do_symlink = 0
671            install.finalize_options(self)
672            self.expand_with_pure_python_dirs(["init_module_dir"])
673    
674        def expand_with_pure_python_dirs(self, attrs):
675            """Expand the attributes with default values of base and platbase"""
676            # it seems that the values for "prefix" and "exec_prefix" in
677            # self.config_vars are the corresponding values used by the
678            # python interpreter, so we just assign these to "base" and
679            # "platbase".
680            config_vars = self.config_vars.copy()
681            config_vars["base"] = self.config_vars["prefix"]
682            config_vars["platbase"] = self.config_vars["exec_prefix"]
683            for attr in attrs:
684                val = getattr(self, attr)
685                if val is not None:
686                    if os.name == 'posix':
687                        val = os.path.expanduser(val)
688                    val = subst_vars(val, config_vars)
689                    setattr(self, attr, val)
690    
691        def select_scheme(self, scheme):
692            """Extend the inherited method to set init_module_dir"""
693            install.select_scheme(self, scheme)
694            # only set init_module_dir if it wasn't set by the user
695            if self.init_module_dir is None:
696                self.init_module_dir = INSTALL_SCHEMES[scheme]['purelib']
697    
698        def convert_paths(self, *args):
699            """Extend the inherited method so that we can remember some filename
700            """
701            # remember the installation directory before its root gets
702            # changed
703            self.install_lib_orig = self.install_lib
704            apply(install.convert_paths, (self,) + args)
705    
706      def run(self):      def run(self):
707          install.run(self)          install.run(self)
708          if os.name == "posix":          for item in self.extra_files:
709              scriptfile = os.path.join(self.install_scripts, "thuban.py")              if type(item) == TupleType:
710                    src, dest = item
711                else:
712                    src = dest = item
713                self.copy_file(convert_path(src),
714                               os.path.join(self.root, convert_path(dest)))
715    
716            if os.name == "posix" and self.do_symlink:
717                install_scripts = self.install_scripts
718                if self.root:
719                    install_scripts = install_scripts[len(self.root):]
720                scriptfile = os.path.join(install_scripts, "thuban.py")
721              bindir = os.path.join(self.prefix, "bin")              bindir = os.path.join(self.prefix, "bin")
722                if self.root:
723                    bindir = change_root(self.root, bindir)
724              binfile = os.path.join(bindir, "thuban")              binfile = os.path.join(bindir, "thuban")
725              self.mkpath(bindir)              self.mkpath(bindir)
726              self.copy_file(scriptfile, binfile, link="sym")              self.link_file(scriptfile, binfile)
727    
728            if self.create_init_module:
729                # create the init module
730                initfilename = self.thuban_init_filename()
731                if self.root:
732                    initfilename = change_root(self.root, initfilename)
733                contents = thubaninit_contents(self.install_lib_orig)
734                self.mkpath(os.path.dirname(initfilename))
735                self.execute(write_file, (initfilename, contents),
736                             "Create %s" % initfilename)
737    
738        def link_file(self, src, dest):
739            """Create a symbolic link dest pointing to src.
740    
741            Unlike the symlink variant of the command object's copy_file
742            method, this method even performs the link if src doesn't exist.
743            This is useful when installing with an alternat root directory"""
744            if self.verbose:
745                self.announce("symlinking %s -> %s" % (src, dest))
746            if self.dry_run:
747                return
748    
749            if not os.path.exists(dest):
750                os.symlink(src, dest)
751    
752        def thuban_init_filename(self):
753            """Return the filename for the init-module"""
754            # Since we override the normal install dirs to point to our own
755            # prefix we have to reach into installed
756            return self.init_module_dir + "/thubaninit.py"
757    
758        def get_outputs (self):
759            outputs = install.get_outputs(self)
760            for item in self.extra_files:
761                if type(item) == TupleType:
762                    src, dest = item
763                else:
764                    src = dest = item
765                outputs.append(os.path.join(self.root, convert_path(dest)))
766            if os.name == "posix" and self.do_symlink:
767                bindir = os.path.join(self.prefix, "bin")
768                if self.root:
769                    bindir = change_root(self.root, bindir)
770                binfile = os.path.join(bindir, "thuban")
771                outputs.append(binfile)
772            if self.create_init_module:
773                initfilename = self.thuban_init_filename()
774                if self.root:
775                    initfilename = change_root(self.root, initfilename)
776                outputs.append(initfilename)
777            return outputs
778    
779    
780    # scripts to override some of the commands put into the spec-file by the
781    # bdist_rpm command.
782    
783    bdist_rpm_prep_script = '''
784    %setup
785    cp extensions/pyshapelib/{README,README.pyshapelib}
786    cp extensions/pyshapelib/{COPYING,COPYING.pyshapelib}
787    cp extensions/pyprojection/{LICENSE,LICENSE.pyprojection}
788    '''
789    
790    bdist_rpm_build_script = '''
791    env PATH="$PATH:%(prefix)s/lib/wxPython/bin:/usr/lib/wxPython/bin" CFLAGS="$RPM_OPT_FLAGS" %(python)s setup.py build
792    '''
793    
794    bdist_rpm_install_script = '''
795    %(python)s setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES \
796       --prefix=%(prefix)s
797    '''
798    
799    
800    class thuban_bdist_rpm(bdist_rpm):
801    
802        """Thuban specific RPM distribution command"""
803    
804        user_options = bdist_rpm.user_options[:]
805        user_options.extend([("prefix=", None, "Install prefix for the RPM"),
806                             ])
807    
808        def initialize_options(self):
809            # per default, RPMs are installed in /usr
810            self.prefix = "/usr/"
811    
812            # create the scripts we want to override. We actually fill them
813            # with contents later because some values we put into those
814            # scripts such as the python interpreter to use are only known
815            # then.
816            open("bdist_rpm_prep", "w").close()
817            open("bdist_rpm_build", "w").close()
818            open("bdist_rpm_install", "w").close()
819            bdist_rpm.initialize_options(self)
820    
821        def _make_spec_file(self):
822            # create the scripts for the spec-file. Now we know the python
823            # interpreter to use.
824            open("bdist_rpm_prep", "w").write(bdist_rpm_prep_script)
825    
826            build = bdist_rpm_build_script % {"python": self.python,
827                                              "prefix": self.prefix}
828            open("bdist_rpm_build", "w").write(build)
829    
830            install = bdist_rpm_install_script % {"python": self.python,
831                                                  "prefix": self.prefix}
832            open("bdist_rpm_install", "w").write(install)
833    
834            #
835            return bdist_rpm._make_spec_file(self)
836    
837    
838    class bdist_inno(Command):
839    
840        """Command to create a windows installer with Inno Setup"""
841    
842        description = "Create a windows installer with Inno Setup"
843    
844        user_options = [
845            ('skip-build', None, "skip the build steps"),
846            ('bdist-dir=', None,
847             "temporary directory for creating the distribution"),
848            ('run-inno', None,
849             "Run inno-setup to create the installer. On by default on nt"),
850            ('iss-name', None,
851             "The name of the iss file to generate. "
852             "Shouldn't contain directories"),
853    
854            # Parameters for the Inno Setup script
855            ('copyright', None, "Copyright notice for the Inno Setup file"),
856            ('default-dir-name', None,
857             "Default installation directory. Defaults to '{pf}\\<name>'"),
858            ('default-group-name', None,
859             "Default program group name. Defaults to <name>'"),
860            ("license-file", None, "File containing the license."),
861            ("output-basename", None,
862             "Base filename for the Inno Setup output "
863             "(defaults to <name>-<version>-<issrevision>)."),
864            ("iss-revision", None,
865             "revision of the generated installer of the package version"),
866    
867            ("icons-entries", None,
868             "List if InnoIconItems "
869             "(this can only be set from inside the setup.py script)"),
870            ]
871    
872        boolean_options = ["do-symlink"]
873    
874        def initialize_options(self):
875            self.skip_build = 0
876            self.bdist_dir = None
877            self.run_inno = None
878            self.iss_name = None
879            self.copyright = ""
880            self.default_dir_name = None
881            self.default_group_name = None
882            self.license_file = None
883            self.output_basename = None
884            self.iss_revision = None
885            self.icons_entries = []
886    
887        def finalize_options(self):
888            self.set_undefined_options("install",
889                                       ('skip_build', 'skip_build'))
890            if self.bdist_dir is None:
891                bdist_base = self.get_finalized_command('bdist').bdist_base
892                self.bdist_dir = os.path.join(bdist_base, 'inno')
893    
894            if self.run_inno is None:
895                self.run_inno = os.name == "nt"
896    
897            name = self.distribution.get_name()
898            if self.iss_name is None:
899                self.iss_name = name + '.iss'
900    
901            if self.default_dir_name is None:
902                self.default_dir_name = "{pf}\\" + name
903            if self.default_group_name is None:
904                self.default_group_name = name
905    
906            if self.iss_revision is None:
907                self.iss_revision = 0
908            if self.output_basename is None:
909                self.output_basename = "%s-%s-%d" \
910                                       % (name, self.distribution.get_version(),
911                                          self.iss_revision)
912    
913        def run(self, install_options = None):
914            """Execute the command. install_options if given, should be a
915            directory of additional options to set in the install step"""
916            # Obviously have to build before we can install
917    
918            if not self.skip_build:
919                self.run_command('build')
920    
921            # Install in a temporary directory
922            install = self.reinitialize_command('install')
923            install.root = self.bdist_dir
924            if install_options is not None:
925                for key, value in install_options.items():
926                    setattr(install, key, value)
927            if os.name != 'nt':
928                # Must force install to use the 'nt' scheme;
929                install.select_scheme('nt')
930    
931            self.announce("installing to %s" % self.bdist_dir)
932            install.ensure_finalized()
933            install.run()
934    
935            # Create the iss file
936            iss_file = os.path.join(self.bdist_dir, self.iss_name)
937            self.execute(write_file, (iss_file, self.generate_iss()),
938                         "Create Inno Setup script file %s" % iss_file)
939    
940            # and invoke
941            if self.run_inno:
942                self.spawn(["iscc", iss_file])
943    
944        def generate_iss(self):
945            """Return the contents of the iss file as list of strings, one
946            string per line"""
947    
948            # first, turn the icons entries into a more usable form
949            icons = {}
950            for item in self.icons_entries:
951                icons[item.filename] = item
952    
953            iss = []
954    
955            name = self.distribution.get_name()
956            iss.extend(["[Setup]",
957                        "AppName=" + name,
958                        "AppVerName=" + name + " "+self.distribution.get_version(),
959                        "DefaultDirName=" + self.default_dir_name,
960                        "DefaultGroupName=" + self.default_group_name,
961                        ])
962            if self.copyright:
963                iss.append("AppCopyright=" + self.copyright)
964            if self.license_file:
965                iss.append("LicenseFile=" + self.license_file)
966    
967            iss.append("OutputBasefilename=" + self.output_basename)
968    
969            iss.append("")
970            iss.append("[Files]")
971    
972            install = self.get_finalized_command("install")
973            install_scripts = self.get_finalized_command("install_scripts")
974            script_files = install_scripts.get_outputs()
975            prefixlen = len(self.bdist_dir) + len(os.sep)
976            for filename in install.get_outputs():
977                filename = filename[prefixlen:]
978                icon = icons.get(filename)
979                dirname = os.path.dirname(filename)
980                if os.name != "nt":
981                    # change the separators to \ on non-windos systems
982                    filename = string.join(string.split(filename, os.sep), "\\")
983                    dirname =  string.join(string.split(dirname, os.sep), "\\")
984                line = 'Source: "%s"' % filename
985                if icon is not None:
986                    # install it as defined in the icon object
987                    backslash = string.rfind(icon.install_name, "\\")
988                    if backslash >= 0:
989                        dirname = icon.install_name[:backslash]
990                        basename = icon.install_name[backslash + 1:]
991                    else:
992                        dirname = ""
993                        basename = icon.install_name
994                    line = '%s; DestDir: "%s"; DestName: "%s"' % (line, dirname,
995                                                                  basename)
996                else:
997                    line = line + '; DestDir: "{app}\\%s"' % (dirname)
998                iss.append(line)
999    
1000            iss.append("")
1001            iss.append("[Icons]")
1002            for icon in self.icons_entries:
1003                line = 'Name: "{group}\\%s"; Filename: "%s";' \
1004                       % (icon.title, icon.install_name)
1005                iss.append(line)
1006    
1007            return iss
1008    
1009    
1010    class InnoIconItem:
1011    
1012        """Describe one item for the start menu for the Inno Setup installer"""
1013    
1014        def __init__(self, filename, title, install_name = None):
1015            self.filename = filename
1016            self.title = title
1017            if install_name is not None:
1018                self.install_name = install_name
1019            else:
1020                self.install_name = filename
1021    
1022    
1023    class thuban_bdist_inno(bdist_inno):
1024    
1025        """Thuban specific Inno Setup stuff"""
1026    
1027        def run(self):
1028            install_options = {
1029                "prefix": ".",
1030                "install_lib": "$base",
1031                "install_data": "$base",
1032                "install_scripts": "$base",
1033                "warn_dir": 0,
1034                "extra_files": ["COPYING", "Lib/proj.dll"],
1035                }
1036            # don't make a symlink because we're simulating windows, so
1037            # that we can generate the iss-file even on Linux
1038            install_options["do_symlink"] = 0
1039    
1040            bdist_inno.run(self, install_options)
1041    
1042    class thuban_build_docs(Command):
1043    
1044        """Command to generate documentation from source code."""
1045    
1046        description = "Generate documentation."
1047    
1048        user_options = []
1049    
1050        def initialize_options(self): pass
1051    
1052        def finalize_options(self): pass
1053    
1054        def run(self, install_options = None):
1055            self.spawn(["happydoc", "-d./Doc", "./Thuban"])
1056    
1057    class thuban_build_ext(build_ext):
1058    
1059        """Extend the build_ext command to optionally include the
1060        GDAL extension.
1061        """
1062    
1063        user_options = build_ext.user_options[:]
1064        user_options.extend([("with-gdal", None, "Include GDAL support."),
1065                             ("without-gdal", None, "Don't include GDAL support.")])
1066    
1067        boolean_options = ["with-gdal"]
1068        negative_opt = {'without-gdal' : 'with-gdal'}
1069    
1070        def initialize_options(self):
1071            self.with_gdal = True
1072            build_ext.initialize_options(self)
1073    
1074        def finalize_options(self):
1075            build_ext.finalize_options(self)
1076            if self.with_gdal and include_gdal:
1077                self.extensions.append(Extension("Lib.gdalwarp",
1078                                    [ext_dir + "/thuban/gdalwarp.cpp",
1079                                    ext_dir + "/thuban/cpl_mfile.cpp",
1080                                    ext_dir + "/thuban/bmpdataset.cpp"],
1081                                    include_dirs = ([gdal_cs_params[CS_INCDIRS],
1082                                                    ext_dir + "/thuban/"]),
1083                                    define_macros = gdal_cs_params[CS_DEFS],
1084                                    library_dirs = gdal_cs_params[CS_LIBDIRS],
1085                                    libraries = [proj4_lib] +
1086                                                gdal_cs_params[CS_LIBS]))
1087    
1088        def run(self, install_options = None):
1089            build_ext.run(self)
1090    
1091    #
1092    #   Run the script
1093    #
1094    
1095  long_description = """\  long_description = """\
1096  Thuban is a viewer for geographic data written in Python  Thuban is a viewer for geographic data written in Python
1097  """  """
1098    
1099  setup(name = "thuban",  setup(name = "Thuban",
1100        version = "0.0.3",        version = "0.2.0",
1101        description = "Geographic data viewer",        description = "Geographic data viewer",
1102        long_description = long_description,        long_description = long_description,
1103        licence = "GPL",        licence = "GPL",
1104        author = "Intevation GmbH",        author = "Intevation GmbH",
1105        author_email = "[email protected]",        author_email = "[email protected]",
1106        url = "ftp:intevation.de/",        url = "http://thuban.intevation.de/",
1107    
1108        scripts = ["thuban.py"],        scripts = ["thuban.py"],
1109        packages = ["Thuban", "Thuban.Lib", "Thuban.Model", "Thuban.UI"],        packages = ["Thuban", "Thuban.Lib", "Thuban.Model", "Thuban.UI"],
# Line 392  setup(name = "thuban", Line 1117  setup(name = "thuban",
1117                   {"prefix": prefix,                   {"prefix": prefix,
1118                    # make sure both libs and scripts are installed in the                    # make sure both libs and scripts are installed in the
1119                    # same directory.                    # same directory.
1120                    "install_lib": "$base/thuban",                    "install_lib": "$base/lib/thuban",
1121                    "install_scripts": "$base/thuban",                    "install_scripts": "$base/lib/thuban",
1122                    "install_data": "$base/thuban/",                    "install_data": "$base/lib/thuban",
1123    
1124                    # Don't print warning messages about the lib dir not                    # Don't print warning messages about the lib dir not
1125                    # being on Python's path. The libraries are Thuban                    # being on Python's path. The libraries are Thuban
1126                    # specific and are installed just for Thuban. They'll                    # specific and are installed just for Thuban. They'll
1127                    # be automatically on Python's path when Thuban is run                    # be automatically on Python's path when Thuban is run
1128                    "warn_dir": 0,                    "warn_dir": 0,
1129                    }},                    },
1130                     "bdist_inno":
1131                     {"icons_entries": [InnoIconItem(".\\thuban.py",
1132                                                     "Start Thuban",
1133                                                     "{app}\\thuban.pyw")],
1134                      "license_file": "COPYING",
1135                      }
1136                     },
1137        cmdclass = {"build_py": thuban_build_py,        cmdclass = {"build_py": thuban_build_py,
1138                    "install_local": InstallLocal,                    "install_local": InstallLocal,
1139                    "install": ThubanInstall})                    "install": ThubanInstall,
1140                      "bdist_rpm": thuban_bdist_rpm,
1141                      "bdist_inno": thuban_bdist_inno,
1142                      "data_dist": data_dist,
1143                      "build_docs": thuban_build_docs,
1144                      "build_ext": thuban_build_ext
1145                      })
1146    
1147    

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26