comparison setup.py @ 0:1fd2201f5c36

Initial commit of parpg-core.
author M. George Hansen <technopolitica@gmail.com>
date Sat, 14 May 2011 01:12:35 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1fd2201f5c36
1 #!/usr/bin/env python2
2 """
3 Cross-system setup script responsible for creating source and binary
4 packages for Linux, Windows, and Mac
5 """
6 import sys
7 import os
8 import string
9 from distutils.core import setup, Command, Distribution as _Distribution
10 from distutils.command import (install as distutils_install,
11 build as distutils_build)
12 from distutils.util import subst_vars, convert_path
13
14 distutils_install.SCHEME_KEYS += ('config',)
15
16 # Update existing installation schemes with the new config key.
17 distutils_install.INSTALL_SCHEMES['unix_prefix'].update(
18 {
19 'data' : '$base/share/$dist_name',
20 'config': '$base/etc/$dist_name'
21 }
22 )
23 distutils_install.INSTALL_SCHEMES['unix_local'].update(
24 {
25 'data' : '$base/local/share/$dist_name',
26 'config': '$base/local/etc/$dist_name'
27 }
28 )
29 distutils_install.INSTALL_SCHEMES['deb_system'].update(
30 {
31 'data' : '$base/share/$dist_name',
32 'config': '$base/etc/$dist_name'
33 }
34 )
35 distutils_install.INSTALL_SCHEMES['unix_home'].update(
36 {
37 'data' : '$base/share/$dist_name',
38 'config': '$base/etc/$dist_name'
39 }
40 )
41 distutils_install.INSTALL_SCHEMES['unix_user'].update(
42 {
43 'data' : '$userbase/share/$dist_name',
44 'config': '$userbase/etc/$dist_name'
45 }
46 )
47 distutils_install.WINDOWS_SCHEME.update(
48 {
49 'config': '$base'
50 }
51 )
52 distutils_install.INSTALL_SCHEMES['nt_user'].update(
53 {
54 'config': '$userbase',
55 }
56 )
57 distutils_install.INSTALL_SCHEMES['mac'].update(
58 {
59 'config': '$base',
60 }
61 )
62 distutils_install.INSTALL_SCHEMES['mac_user'].update(
63 {
64 'config': '$userbase',
65 }
66 )
67 distutils_install.INSTALL_SCHEMES['os2'].update(
68 {
69 'config': '$base',
70 }
71 )
72 distutils_install.INSTALL_SCHEMES['os2_home'].update(
73 {
74 'config': '$userbase',
75 }
76 )
77
78
79 class build_templates(Command):
80 description = '"build" template files (copy to build directory, ' \
81 'substituting build variables)'
82 user_options = [
83 ('build-dir=', 'd', 'directory to "build" (copy) to'),
84 ('force', 'f', 'forcibly build everything (ignore file timestamps)'),
85 ]
86 boolean_options = ['force']
87
88 def initialize_options(self):
89 self.build_base = None
90 self.build_dir = None
91 self.force = None
92 self.config_vars = None
93 self.templates = None
94
95 def finalize_options(self):
96 self.set_undefined_options(
97 'build',
98 ('build_base', 'build_base'),
99 ('force', 'force'),
100 )
101 self.build_dir = os.path.join(self.build_base, 'templates')
102 self.set_undefined_options('install', ('config_vars', 'config_vars'))
103 self.templates = self.distribution.templates
104
105 def run(self):
106 if self.has_templates():
107 self.build_templates()
108
109 def build_templates(self):
110 build_dir = self.build_dir
111 for template_path, outfile_rel_path in self.templates.items():
112 outfile_path = os.path.join(build_dir, outfile_rel_path)
113 self.copy_file(template_path, outfile_path, preserve_mode=False)
114 self.substitute_template(outfile_path)
115
116 def substitute_template(self, file_path):
117 with file(file_path, 'r') as template_file:
118 template_content = template_file.read()
119 template = string.Template(template_content)
120 config_vars = self.config_vars
121 file_content = template.substitute(config_vars)
122 with file(file_path, 'w') as config_file:
123 config_file.write(file_content)
124
125 def has_templates(self):
126 return self.distribution.has_templates()
127
128
129 class install_config(Command):
130 description = 'install configuration files'
131 user_options = [
132 ('install-dir=', 'd', 'directory to install configuration files to'),
133 ('force', 'f', 'force installation (overwrite existing files)'),
134 ('skip-build', None, 'skip the build steps'),
135 ]
136 boolean_options = ['force', 'skip-build']
137
138 def initialize_options(self):
139 self.install_dir = None
140 self.force = 0
141 self.skip_build = None
142 self.config_files = None
143 self.config_templates = None
144 self.config_vars = None
145
146 def finalize_options(self):
147 self.set_undefined_options(
148 'install',
149 ('install_config', 'install_dir'),
150 ('force', 'force'),
151 ('skip_build', 'skip_build'),
152 ('config_vars', 'config_vars'),
153 )
154 self.config_files = self.distribution.config_files
155 self.config_templates = self.distribution.config_templates
156
157 def run(self):
158 install_dir = self.install_dir
159 outfiles = []
160 for file_path in self.config_files:
161 output_file_path = os.path.join(install_dir, file_path)
162 output_dir_path = os.path.dirname(output_file_path)
163 self.mkpath(output_dir_path)
164 outfile = self.copy_file(file_path, output_dir_path,
165 preserve_mode=0)
166 outfiles.append(outfile)
167 self.outfiles = outfiles
168
169 def get_inputs(self):
170 return self.distribution.config_files or []
171
172 def get_outputs(self):
173 return self.outfiles or []
174
175
176 class install(distutils_install.install):
177 user_options = distutils_install.install.user_options + [
178 ('install-config=', None,
179 'installation directory for system-wide configuration files')
180 ]
181
182 def has_config(self):
183 return self.distribution.has_config()
184
185 def has_templates(self):
186 return self.distribution.has_templates()
187
188 def initialize_options(self):
189 self.install_config = None
190 distutils_install.install.initialize_options(self)
191
192 def finalize_options(self):
193 distutils_install.install.finalize_options(self)
194 # FIXME M. George Hansen 2011-05-11: Probably shouldn't be using a
195 # private method here...
196 self._expand_attrs(['install_config'])
197 self.convert_paths('config')
198 self.config_vars['config'] = self.install_config
199 if self.root is not None:
200 self.change_roots('config')
201 install_scheme = self.install_scheme
202 for key, value in install_scheme.items():
203 if os.name in ['posix', 'nt']:
204 value = os.path.expanduser(value)
205 value = subst_vars(value, self.config_vars)
206 value = convert_path(value)
207 self.config_vars[key] = value
208
209 def select_scheme(self, name):
210 # Store the selected scheme for later processing.
211 distutils_install.install.select_scheme(self, name)
212 self.install_scheme = distutils_install.INSTALL_SCHEMES[name]
213
214 def get_program_files_path(self):
215 assert sys.platform == 'win32'
216 try:
217 program_files_path = os.environ['ProgramFiles']
218 except KeyError:
219 # ProgramFiles environmental variable isn't set, so we'll have to
220 # find it ourselves. Bit of a hack, but better than nothing.
221 program_files_path = ''
222 try:
223 import win32api
224 except ImportError:
225 program_files_path = ''
226 else:
227 drive_names = \
228 [drive_name for drive_name in
229 win32api.GetLogicalDriveStrings().split('\000') if
230 drive_name]
231 for drive_name in drive_names:
232 search_path = os.path.join(drive_name, 'Program Files')
233 if os.path.isdir(search_path):
234 program_files_path = search_path
235 if not program_files_path:
236 error_message = 'unable to determine path to Program Files'
237 raise error_message
238
239 return program_files_path
240
241 sub_commands = distutils_install.install.sub_commands + [
242 ('install_config', has_config),
243 ]
244
245
246 class build(distutils_build.build):
247 def has_templates(self):
248 return self.distribution.has_templates()
249
250 sub_commands = [('build_templates', has_templates)] + \
251 distutils_build.build.sub_commands
252
253
254 class Distribution(_Distribution):
255 def __init__(self, attrs=None):
256 self.templates = {}
257 self.config_files = []
258 _Distribution.__init__(self, attrs)
259
260 def has_config(self):
261 return self.config_files and len(self.config_files) > 0
262
263 def has_templates(self):
264 return self.templates and len(self.templates) > 0
265
266
267 setup(
268 name='parpg',
269 scripts=['parpg'],
270 templates={'system.cfg': 'system.cfg.in', 'parpg': 'parpg.in'},
271 config_files=['system.cfg'],
272 packages=['parpg'],
273 modules=['src/main.py'],
274 package_dir={'parpg': 'src/parpg'},
275 version='0.2.0',
276 url='http://www.parpg.net',
277 description='',
278 long_description='',
279 cmdclass={'install': install, 'install_config': install_config,
280 'build': build, 'build_templates': build_templates},
281 distclass=Distribution,
282 classifiers=[
283 'Programming Language :: Python',
284 'License :: OSI Approved :: GNU General Public License (GPL)',
285 'Intended Audience :: End Users/Desktop',
286 'Intended Audience :: Developers',
287 'Development Status :: 2 - Pre-Alpha',
288 'Operating System :: OS Independent',
289 'Natural Language :: English',
290 'Topic :: Games/Entertainment :: Role-Playing',
291 ],
292 )