Mercurial > parpg-core
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 ) |