Mercurial > parpg-core
view setup.py @ 5:33684971cdb1
Replaced the shell script launcher with a cross-platform C executable.
* Replaced the Unix-only shell script launcher with a cross-platform compiled executable written in C.
* Added several new configuration variables to the SConsctruct script which allows the user to specify where their Python site-packages and executable are located;
* Cleaned up the SConstruct script and made it easier to grok.
author | M. George Hansen <technopolitica@gmail.com> |
---|---|
date | Tue, 17 May 2011 14:18:25 -0700 |
parents | 1fd2201f5c36 |
children |
line wrap: on
line source
#!/usr/bin/env python2 """ Cross-system setup script responsible for creating source and binary packages for Linux, Windows, and Mac """ import sys import os import string from distutils.core import setup, Command, Distribution as _Distribution from distutils.command import (install as distutils_install, build as distutils_build) from distutils.util import subst_vars, convert_path distutils_install.SCHEME_KEYS += ('config',) # Update existing installation schemes with the new config key. distutils_install.INSTALL_SCHEMES['unix_prefix'].update( { 'data' : '$base/share/$dist_name', 'config': '$base/etc/$dist_name' } ) distutils_install.INSTALL_SCHEMES['unix_local'].update( { 'data' : '$base/local/share/$dist_name', 'config': '$base/local/etc/$dist_name' } ) distutils_install.INSTALL_SCHEMES['deb_system'].update( { 'data' : '$base/share/$dist_name', 'config': '$base/etc/$dist_name' } ) distutils_install.INSTALL_SCHEMES['unix_home'].update( { 'data' : '$base/share/$dist_name', 'config': '$base/etc/$dist_name' } ) distutils_install.INSTALL_SCHEMES['unix_user'].update( { 'data' : '$userbase/share/$dist_name', 'config': '$userbase/etc/$dist_name' } ) distutils_install.WINDOWS_SCHEME.update( { 'config': '$base' } ) distutils_install.INSTALL_SCHEMES['nt_user'].update( { 'config': '$userbase', } ) distutils_install.INSTALL_SCHEMES['mac'].update( { 'config': '$base', } ) distutils_install.INSTALL_SCHEMES['mac_user'].update( { 'config': '$userbase', } ) distutils_install.INSTALL_SCHEMES['os2'].update( { 'config': '$base', } ) distutils_install.INSTALL_SCHEMES['os2_home'].update( { 'config': '$userbase', } ) class build_templates(Command): description = '"build" template files (copy to build directory, ' \ 'substituting build variables)' user_options = [ ('build-dir=', 'd', 'directory to "build" (copy) to'), ('force', 'f', 'forcibly build everything (ignore file timestamps)'), ] boolean_options = ['force'] def initialize_options(self): self.build_base = None self.build_dir = None self.force = None self.config_vars = None self.templates = None def finalize_options(self): self.set_undefined_options( 'build', ('build_base', 'build_base'), ('force', 'force'), ) self.build_dir = os.path.join(self.build_base, 'templates') self.set_undefined_options('install', ('config_vars', 'config_vars')) self.templates = self.distribution.templates def run(self): if self.has_templates(): self.build_templates() def build_templates(self): build_dir = self.build_dir for template_path, outfile_rel_path in self.templates.items(): outfile_path = os.path.join(build_dir, outfile_rel_path) self.copy_file(template_path, outfile_path, preserve_mode=False) self.substitute_template(outfile_path) def substitute_template(self, file_path): with file(file_path, 'r') as template_file: template_content = template_file.read() template = string.Template(template_content) config_vars = self.config_vars file_content = template.substitute(config_vars) with file(file_path, 'w') as config_file: config_file.write(file_content) def has_templates(self): return self.distribution.has_templates() class install_config(Command): description = 'install configuration files' user_options = [ ('install-dir=', 'd', 'directory to install configuration files to'), ('force', 'f', 'force installation (overwrite existing files)'), ('skip-build', None, 'skip the build steps'), ] boolean_options = ['force', 'skip-build'] def initialize_options(self): self.install_dir = None self.force = 0 self.skip_build = None self.config_files = None self.config_templates = None self.config_vars = None def finalize_options(self): self.set_undefined_options( 'install', ('install_config', 'install_dir'), ('force', 'force'), ('skip_build', 'skip_build'), ('config_vars', 'config_vars'), ) self.config_files = self.distribution.config_files self.config_templates = self.distribution.config_templates def run(self): install_dir = self.install_dir outfiles = [] for file_path in self.config_files: output_file_path = os.path.join(install_dir, file_path) output_dir_path = os.path.dirname(output_file_path) self.mkpath(output_dir_path) outfile = self.copy_file(file_path, output_dir_path, preserve_mode=0) outfiles.append(outfile) self.outfiles = outfiles def get_inputs(self): return self.distribution.config_files or [] def get_outputs(self): return self.outfiles or [] class install(distutils_install.install): user_options = distutils_install.install.user_options + [ ('install-config=', None, 'installation directory for system-wide configuration files') ] def has_config(self): return self.distribution.has_config() def has_templates(self): return self.distribution.has_templates() def initialize_options(self): self.install_config = None distutils_install.install.initialize_options(self) def finalize_options(self): distutils_install.install.finalize_options(self) # FIXME M. George Hansen 2011-05-11: Probably shouldn't be using a # private method here... self._expand_attrs(['install_config']) self.convert_paths('config') self.config_vars['config'] = self.install_config if self.root is not None: self.change_roots('config') install_scheme = self.install_scheme for key, value in install_scheme.items(): if os.name in ['posix', 'nt']: value = os.path.expanduser(value) value = subst_vars(value, self.config_vars) value = convert_path(value) self.config_vars[key] = value def select_scheme(self, name): # Store the selected scheme for later processing. distutils_install.install.select_scheme(self, name) self.install_scheme = distutils_install.INSTALL_SCHEMES[name] def get_program_files_path(self): assert sys.platform == 'win32' try: program_files_path = os.environ['ProgramFiles'] except KeyError: # ProgramFiles environmental variable isn't set, so we'll have to # find it ourselves. Bit of a hack, but better than nothing. program_files_path = '' try: import win32api except ImportError: program_files_path = '' else: drive_names = \ [drive_name for drive_name in win32api.GetLogicalDriveStrings().split('\000') if drive_name] for drive_name in drive_names: search_path = os.path.join(drive_name, 'Program Files') if os.path.isdir(search_path): program_files_path = search_path if not program_files_path: error_message = 'unable to determine path to Program Files' raise error_message return program_files_path sub_commands = distutils_install.install.sub_commands + [ ('install_config', has_config), ] class build(distutils_build.build): def has_templates(self): return self.distribution.has_templates() sub_commands = [('build_templates', has_templates)] + \ distutils_build.build.sub_commands class Distribution(_Distribution): def __init__(self, attrs=None): self.templates = {} self.config_files = [] _Distribution.__init__(self, attrs) def has_config(self): return self.config_files and len(self.config_files) > 0 def has_templates(self): return self.templates and len(self.templates) > 0 setup( name='parpg', scripts=['parpg'], templates={'system.cfg': 'system.cfg.in', 'parpg': 'parpg.in'}, config_files=['system.cfg'], packages=['parpg'], modules=['src/main.py'], package_dir={'parpg': 'src/parpg'}, version='0.2.0', url='http://www.parpg.net', description='', long_description='', cmdclass={'install': install, 'install_config': install_config, 'build': build, 'build_templates': build_templates}, distclass=Distribution, classifiers=[ 'Programming Language :: Python', 'License :: OSI Approved :: GNU General Public License (GPL)', 'Intended Audience :: End Users/Desktop', 'Intended Audience :: Developers', 'Development Status :: 2 - Pre-Alpha', 'Operating System :: OS Independent', 'Natural Language :: English', 'Topic :: Games/Entertainment :: Role-Playing', ], )