Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 306 lines (238 sloc) 10.248 kb
c7d48b5 further merges of the DEVEL_BRANCH code
tavis_rudd authored
1 #!/usr/bin/env python
2 # $Id: SetupTools.py,v 1.2 2001/10/10 06:59:45 tavis_rudd Exp $
3 """Some tools for extending and working with distutils
4
5 CREDITS: This module borrows code and ideas from M.A. Lemburg's excellent setup
6 tools for the mxBase package.
7
8 """
9
10 __author__ = "Tavis Rudd <tavis@calrudd.com>"
11 __version__ = "$Revision: 1.2 $"[11:-2]
12
13
14 ##################################################
15 ## GLOBALS AND CONSTANTS ##
16
17 True = (1==1)
18 False = (1==0)
19
20 ##################################################
21 ## DEPENDENCIES ##
22
23 from distutils.core import setup
24 from distutils.core import Command
25 from distutils.command.install_data import install_data
26 from distutils.command.sdist import sdist
27
28 import os
29 from os import listdir
30 import os.path
31 from os.path import exists, isdir, isfile, join, splitext
32
33 import types
34 import glob
35 import string
36
37 #imports from Cheetah ...
38 from src.FileUtils import findFiles
39
40 ##################################################
41 ## CLASSES ##
42
43 class mod_install_data(install_data):
44
45 """A copy of M.A Lemburg's modified version of the disutils install_data
46 command that allows data files to be included directly in the installed
47 Python package tree.
48
49 Note that it expects that data_files argument to the disutils.setup()
50 commmand to be a list of strings rather than a list of tuples as is the
51 default. Each of these string entries can be a real file name or a glob
52 pattern representing the files to match."""
53
54 def finalize_options(self):
55
56 if self.install_dir is None:
57 installobj = self.distribution.get_command_obj('install')
58 self.install_dir = installobj.install_platlib
59 install_data.finalize_options(self)
60
61 def run (self):
62
63 if not self.dry_run:
64 self.mkpath(self.install_dir)
65 data_files = self.get_inputs()
66
67 for entry in data_files:
68 if type(entry) != types.StringType:
69 raise ValueError, 'The entries in "data_files" must be strings'
70
71 entry = string.join(string.split(entry, '/'), os.sep)
72 # entry is a filename or glob pattern
73 if entry.startswith('recursive:'):
74 entry = entry[len('recursive:'):]
75 dir = entry.split()[0]
76 globPatterns = entry.split()[1:]
77 filenames = findFiles(dir, globPatterns)
78 else:
79 filenames = glob.glob(entry)
80
81 for filename in filenames:
82 ## generate the dstPath from the filename
83 # - deal with 'package_dir' translations
84 topDir, subPath = (filename.split(os.sep)[0],
85 os.sep.join( filename.split(os.sep)[1:] )
86 )
87
88 package_dirDict = self.distribution.package_dir
89 if package_dirDict:
90 packageDir = topDir
91 for key, val in package_dirDict.items():
92 if val == topDir:
93 packageDir = key
94 break
95 else:
96 packageDir = topDir
97 dstPath = os.path.join(self.install_dir, packageDir, subPath)
98
99 ## add the file to the list of outfiles
100 dstdir = os.path.split(dstPath)[0]
101 if not self.dry_run:
102 self.mkpath(dstdir)
103 outfile = self.copy_file(filename, dstPath)[0]
104 else:
105 outfile = dstPath
106 self.outfiles.append(outfile)
107
108
109 class contrib(Command):
110 """a setup command that will process the contributed packages.
111
112 USAGE: setup.py contrib install
113 or
114 setup.py contrib sdist
115 etc.
116 """
117 description = ""
118
119 # List of option tuples: long name, short name (None if no short
120 # name), and help string.
121 user_options = [ ('cmd=', None,
122 "The command to run on each of the contrib packages"),
123 ('contrib_dir=', None,
124 "The directory which contains all of the contrib packages"),
125 ('contrib_packages=', None,
126 "A whitespace separated list of contrib package subdirs"),
127
128 ]
129
130 def initialize_options (self):
131 self.cmd = 'install'
132
133 def finalize_options (self):
134 pass
135
136 def run(self):
137 cwd = os.getcwd()
138 for p in self.contrib_packages.split():
139 d = os.path.join(cwd, self.contrib_dir, p)
140 os.chdir(d)
141 print "Working on", d, "(", os.getcwd(), ")"
142 try:
143 os.system(sys.executable+' setup.py '+ self.cmd)
144 except:
145 print "An error occurred while installing the contributed packages."
146 #os.chdir(cwd)
147 raise
148
149
150 class sdist_docs(sdist):
151
152 """A setup command that will rebuild Users Guide at the same time as
153 creating a source distribution.
154
155 It relies on the main tex-file being called users_guide.tex and the tex file
156 being in a form that Python's mkhowto script accepts."""
157
158 def run(self):
159 try:
160 from main_package.Version import version
161
162 currentDir = os.getcwd()
163 os.chdir(os.path.join(currentDir,'docs','src'))
164 fp = open('users_guide.tex','r')
165 originalTexCode = fp.read()
166 fp.close()
167
168 newTexCode = re.sub(r'(?<=\\release\{)[0-9\.a-zA-Z]*',str(version), originalTexCode)
169
170 fp = open('users_guide.tex','w')
171 fp.write(newTexCode)
172 fp.close()
173
174 os.system('make -f Makefile')
175 os.chdir(currentDir)
176 except:
177 print "The sdist_docs command couldn't rebuild the Users Guide"
178 os.chdir(currentDir)
179
180 sdist.run(self)
181
182
183 class uninstall(Command):
184
185 description = "uninstall the package files and directories"
186
187 user_options = []
188
189 def initialize_options(self):
190 pass
191
192 def finalize_options(self):
193 pass
194
195 def run(self):
196
197 # Execute build
198 self.announce('determining installation files')
199 self.announce('(re)building package')
200 savevalue = self.distribution.dry_run
201 self.distribution.dry_run = 0
202 self.run_command('build')
203
204 # Execute install in dry-run mode
205 self.announce('dry-run package install')
206 self.distribution.dry_run = 1
207 self.run_command('install')
208 self.distribution.dry_run = savevalue
209 build = self.get_finalized_command('build')
210 install = self.get_finalized_command('install')
211
212 # Remove all installed files
213 self.announce("removing files")
214 dirs = {}
215 filenames = install.get_outputs()
216 for filename in filenames:
217 if not os.path.isabs(filename):
218 raise DistutilsError,\
219 'filename %s from .get_output() not absolute' % \
220 filename
221
222 if os.path.isfile(filename):
223 self.announce("removing %s" % filename)
224 if not self.dry_run:
225 try:
226 os.remove(filename)
227 except OSError, details:
228 self.warn("Could not remove file: %s" % details)
229 dir = os.path.split(filename)[0]
230 if not dirs.has_key(dir):
231 dirs[dir] = 1
232 if os.path.splitext(filename)[1] == '.py':
233 # Remove byte-code files as well
234 try:
235 os.remove(filename + 'c')
236 except OSError:
237 pass
238 try:
239 os.remove(filename + 'o')
240 except OSError:
241 pass
242
243 elif os.path.isdir(filename):
244 # This functionality is currently not being used by distutils
245 if not dirs.has_key(dir):
246 dirs[filename] = 1
247
248 elif not os.path.splitext(filename)[1] in ('.pyo', '.pyc'):
249 self.announce("skipping removal of %s (not found)" %
250 filename)
251
252 # Remove the installation directories
253 self.announce("removing directories")
254 dirs = dirs.keys()
255 dirs.sort(); dirs.reverse() # sort descending
256 for dir in dirs:
257 self.announce("removing directory %s" % dir)
258 if not self.dry_run:
259 try:
260 os.rmdir(dir)
261 except OSError, details:
262 self.warn("could not remove directory: %s" % details)
263
264
265 ##################################################
266 ## FUNCTIONS ##
267
268 def run_setup(configurations):
269
270 """ Run distutils setup.
271
272 The parameters passed to setup() are extracted from the list of modules,
273 classes or instances given in configurations.
274
275 Names with leading underscore are removed from the parameters.
276 Parameters which are not strings, lists, tuples, or dicts are removed as
277 well. Configurations which occur later in the configurations list
278 override settings of configurations earlier in the list.
279
280 """
281 # Build parameter dictionary
282 kws = {}
283 for configuration in configurations:
284 kws.update(vars(configuration))
285 for name, value in kws.items():
286 if name[:1] == '_' or \
287 type(value) not in (types.StringType,
288 types.ListType,
289 types.TupleType,
290 types.DictType,
291 ):
292 del kws[name]
293
294 # Add setup extensions
295 cmdclasses = {'install_data': mod_install_data,
296 'uninstall':uninstall,
297 'contrib':contrib,
298 'sdist_docs':sdist_docs,
299 }
300
301 kws['cmdclass'] = cmdclasses
302
303 # Invoke distutils setup
304 apply(setup, (), kws)
305
Something went wrong with that request. Please try again.