/[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

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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26