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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26