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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26