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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26