# -*- python -*- -*- encoding: Latin-1 -*-
__copyright__ = "Copyright (c) 2003 Terje Røsten <terjeros@phys.ntnu.no>"
# Extention of distutils for straw.
import sys
import os
import os.path
import re
import glob
import types
import commands
from distutils.core import Command
from distutils.command.build import build
from distutils.command.install import install
from distutils.command.install_lib import install_lib
from distutils.command.install_data import install_data
from distutils.dep_util import newer
from distutils.util import subst_vars
from distutils.dist import Distribution
from distutils.core import setup
class straw_build(build):
def has_po_files(self):
return self.distribution.has_po_files()
def has_desktop_file(self):
return self.distribution.has_desktop_file()
sub_commands = []
sub_commands.extend(build.sub_commands)
sub_commands.append(('build_mo', has_po_files))
sub_commands.append(('build_desktop', has_desktop_file))
class build_mo(Command):
description = 'build binary message catalog'
user_options = [('build-base=', 'b', 'directory to build to')]
def initialize_options(self):
self.build_base = None
self.force = None
def finalize_options(self):
self.set_undefined_options('build',
('build_base', 'build_base'),
('force', 'force'))
def run(self):
self.announce('Building binary message catalog')
if self.distribution.has_po_files():
for mo, po in self.distribution.translations:
dest = os.path.normpath(self.build_base + '/' + mo)
self.mkpath(os.path.dirname(dest))
if not self.force and not newer(po, dest):
self.warn("not building %s (up-to-date)" % dest)
else:
import msgfmt
msgfmt.make(po, dest)
class build_desktop(Command):
description = 'builds the straw.desktop file'
user_options = [('build-base=', 'b', 'directory to build to')]
def initialize_options(self):
self.build_base = None
self.intl_merge = None
def finalize_options(self):
if self.intl_merge is None:
self.intl_merge = commands.getoutput('which intltool-merge')
if not os.path.exists(self.intl_merge):
sys.exit('intltool-merge does not exist in your PATH. ' + \
'Make sure it exists in your PATH..')
self.set_undefined_options('build',
('build_base', 'build_base'))
def run(self):
self.announce("Building straw.desktop file....")
if self.distribution.has_desktop_file():
for desktop in self.distribution.desktop_file:
dest = os.path.normpath(os.path.join(self.build_base, 'share/applications'))
self.mkpath(dest, 1)
fname = '.'.join(desktop.split('.')[:2]) # straw.desktop.in -> straw.desktop
cmd = '%s -d -u po %s %s/%s' % (self.intl_merge, desktop,
dest, fname)
err, val = commands.getstatusoutput(cmd)
if err:
sys.exit('Unable to translate straw.desktop. %s' % err)
class straw_install(install):
user_options = []
_user_options = [
('sysconfdir=', None, 'specify SYSCONFDIR [default=PREFIX/etc]'),
('disable-modules-check', None,
'do not check that necessary modules is installed'),
('enable-modules-check', None,
'check that necessary modules is installed [default]'),
('disable-schemas-install', None,
'do not install schema files. Setting the variable '
'GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL will prevent this too.'),
('enable-schemas-install', None,
'install schema files. [default]'),
('with-gconftool=', None,
'specify path to the gconftool executable. Can also be set by'
'the variable GCONFTOOL. [default=gconftool-2]' ),
('with-gconf-source=', None,
'Config database for installing schema files. Can also be set by '
'the variable GCONF_SCHEMA_CONFIG_SOURCE. Setting to `auto\' is '
'short for `$(gconftool-2 --get-default-source)\'. '),
('with-gconf-schema-file-dir=', None,
'Directory for installing schema files. Can also be set by the '
'variable GCONF_SCHEMA_FILE_DIR. [default=SYSCONFDIR/gconf/schemas]'),
('with-desktop-file-dir=', None,
'specify directory for the straw.desktop file [default=PREFIX/share/applications')]
user_options.extend(install.user_options)
user_options.extend(_user_options)
boolean_options = []
boolean_options.extend(install.boolean_options)
boolean_options.extend([
'disable-schemas-install', 'disable-modules-check' ])
negative_opt = {}
try:
negative_opt.update(install.negative_opt)
except AttributeError:
pass
negative_opt.update({'enable-schemas-install' : 'disable-schemas-install',
'enable-modules-check' : 'disable-modules-check'})
def initialize_options(self):
install.initialize_options(self)
#self.prefix = '/usr/local'
# if self.sysconfdir is not a absolute path it will
# be prefixed by self.prefix
self.sysconfdir = 'etc'
self.disable_modules_check = 0
self.disable_schemas_install = os.environ.get(
'GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL', 0)
self.with_gconftool = os.environ.get(
'GCONFTOOL', commands.getoutput('which gconftool-2'))
self.with_gconf_source = os.environ.get(
'GCONF_SCHEMA_CONFIG_SOURCE', 'auto')
self.with_gconf_schema_file_dir = os.environ.get(
'GCONF_SCHEMA_FILE_DIR', None)
self.with_desktop_file_dir = 'share/applications'
def finalize_options(self):
if self.prefix == 'auto':
cmd = 'pkg-config --variable=prefix libgnome2.0'
err, val = commands.getstatusoutput(cmd)
if not err:
self.prefix = val
else:
sys.exit('Cannot find prefix: %s. pkgconfig not installed?'
% val)
self.sysconfdir = os.path.join(self.prefix, self.sysconfdir)
if self.root:
self.sysconfdir = os.path.normpath(self.root + '/' + self.sysconfdir)
self.announce(self.sysconfdir)
if self.root and self.with_gconf_schema_file_dir:
self.with_gconf_schema_file_dir = os.path.normpath(
self.root + '/' + self.with_gconf_schema_file_dir)
if not self.disable_schemas_install:
# Sanity check
if not os.path.exists(self.with_gconftool):
sys.exit('gconftool-2 executable not found in your path ' + \
'- should be installed with GConf')
if self.with_gconf_source == 'auto':
cmd = '%s --get-default-source' % self.with_gconftool
self.with_gconf_source = commands.getoutput(cmd)
if self.with_gconf_source != 'auto' and self.root:
self.with_gconf_source = self.with_gconf_source.replace(
'xml::','xml::%s' % self.root)
elif not self.with_gconf_source:
fmt = 'xml::%s/gconf/gconf.xml.defaults'
self.with_gconf_source = fmt % self.sysconfdir
# Run this after we (possibly) have changed prefix.
install.finalize_options(self)
def has_modules_check(self):
return self.distribution.has_modules_check()
def has_config_files(self):
return self.distribution.has_config_files()
def has_po_files(self):
return self.distribution.has_po_files()
def has_desktop_file(self):
return self.distribution.has_desktop_file()
def has_constants(self):
return self.distribution.has_constants()
sub_commands = []
# Check modules before we start to install files
sub_commands.append(('install_modules_check', has_modules_check))
sub_commands.extend(install.sub_commands)
sub_commands.append(('install_mo', has_po_files))
sub_commands.append(('install_gconf', has_config_files))
sub_commands.append(('install_desktop', has_desktop_file))
sub_commands.append(('install_constants', has_constants))
class install_mo(install_data):
description = 'install generated binary message catalog'
def initialize_options(self):
self.translations = self.distribution.translations
self.has_po_files = self.distribution.has_po_files
self.install_dir = None
self.build_dir = None
self.skip_build = None
self.outfiles = []
def finalize_options(self):
self.set_undefined_options('build_mo', ('build_base', 'build_dir'))
self.set_undefined_options('install',
('install_data', 'install_dir'),
('skip_build', 'skip_build'))
def run(self):
if not self.skip_build:
self.run_command('build_mo')
if self.has_po_files():
for mo, po in self.translations:
src = os.path.normpath(self.build_dir + '/' + mo)
if not os.path.isabs(mo):
dest = os.path.normpath(self.install_dir + '/' + mo)
elif self.root:
dest = self.root + mo
else:
dest = mo
self.mkpath(os.path.dirname(dest))
(out, _) = self.copy_file(src, dest)
self.outfiles.append(out)
def get_outputs (self): return self.outfiles
def get_inputs (self): return [ po for mo, po in self.translations ]
class install_gconf(install_data):
'''
Same as install_data but using <sysconfdir> instead of
<prefix>. If <sysconfdir> is not absolute, <prefix> is prefixed
<sysconfdir>. If the tuple has length 3 and the option in the last
element is known, the value of the option is used as dest
directory. On the other hand if option is None, the value of the
option is set to value of the first element in the tuple.
'''
description = 'install generated gconf files'
user_options = [
('sysconfdir', None,
'specify SYSCONFDIR [default=PREFIX/etc]')]
def initialize_options(self):
self.disable_schemas_install = None
self.sysconfdir = None
self.with_gconftool = None
self.with_gconf_source = None
self.with_gconf_schema_file_dir = None
self.config_files = self.distribution.config_files
install_data.initialize_options(self)
def finalize_options(self):
install_data.finalize_options(self)
self.set_undefined_options(
'install',
('disable_schemas_install', 'disable_schemas_install'),
('with_gconftool', 'with_gconftool'),
('with_gconf_source', 'with_gconf_source'),
('sysconfdir','sysconfdir'),
('with_gconf_schema_file_dir', 'with_gconf_schema_file_dir'))
self.option_to_dir()
def install_schema(self):
schemas_dir, schemas_file = self.config_files[0]
schemas_idir = os.path.normpath(self.sysconfdir+'/'+schemas_dir)
self.mkpath(schemas_idir)
os.environ['GCONF_CONFIG_SOURCE'] = self.with_gconf_source
for filepath in schemas_file:
sfile = filepath.split('/')[-1]
ofile = os.path.normpath(os.path.join(schemas_idir,sfile))
self.copy_file(filepath,ofile)
cmd = '%s --makefile-install-rule %s'\
% (self.with_gconftool, ofile)
err, out = commands.getstatusoutput(cmd)
if out:
self.announce(out)
if err:
self.warn('Error: installation of gconf schema files failed: %s' % out)
def run(self):
if not self.disable_schemas_install:
self.install_schema()
def option_to_dir(self):
data_files = []
for tup in self.config_files:
if len(tup) == 2:
data_files.append(tup)
elif len(tup) == 3:
option = tup[2].replace('-','_')
dest = getattr(self, option, None)
if dest:
data_files.append((dest, tup[1]))
else:
data_files.append((tup[0], tup[1]))
dest = os.path.normpath(self.sysconfdir + '/' + tup[0])
setattr(self, option, dest)
self.config_files = data_files
def get_outputs(self): return []
def get_inputs(self): return []
class install_modules_check(Command):
description = 'check that all necessary Python modules are installed'
user_options = [
('disable-modules-check', None,
'do not check that necessary modules is installed'),
('enable-modules-check', None,
'check that necessary modules is installed [default]')]
boolean_options = []
boolean_options.append('disable-modules-check')
negative_opt = {'enable-modules-check' : 'disable-modules-check'}
def initialize_options(self):
self.disable_modules_check = None
self.modules_check = self.distribution.modules_check
def finalize_options(self):
self.set_undefined_options(
'install',
('disable_modules_check', 'disable_modules_check'))
def run(self):
if self.disable_modules_check:
self.announce('Modules not checked')
elif self.modules_check:
self.modules_check()
self.announce('All nescessary modules installed')
def get_outputs(self): return []
def get_inputs(self): return []
class install_desktop(install_data):
description = 'Installs generated desktop file'
user_options = [
('with-desktop-file-dir=', None,
'specify directory for the straw.desktop file [default=PREFIX/share/applications]')]
def initialize_options(self):
self.outfiles = []
self.build_dir = None
self.install_dir = None
self.skip_build = None
self.with_desktop_file_dir = None
def finalize_options(self):
self.set_undefined_options('build_desktop', ('build_base', 'build_dir'))
self.set_undefined_options('install',('install_data','install_dir'),
('skip_build', 'skip_build'),
('with_desktop_file_dir','with_desktop_file_dir'))
def run(self):
if not self.skip_build: self.run_command('build_desktop')
src = os.path.normpath(os.path.join(
self.build_dir, 'share/applications/straw.desktop'))
dest = os.path.normpath(self.install_dir + '/' + self.with_desktop_file_dir)
self.mkpath(dest)
(out, _) = self.copy_file(src, dest)
self.outfiles.append(out)
def get_outputs (self): return self.outfiles
def get_inputs (self):
return (os.path.join(self.build_dir, 'share/applications/straw.desktop'))
class translate(Command):
description = 'update .pot file and merge po files'
user_options = [('pot', 'p', 'only update the pot file (no merge)')]
user_options.extend([('dist=', 'd','Merge LANGCODE.po with existing PO template.')])
boolean_options = ['pot']
def initialize_options(self):
self.intl_update = None
self.pot = 0
self.dist = None
self.pot_file = None
def finalize_options(self):
if not self.intl_update:
self.intl_update = commands.getoutput('which intltool-update')
if not os.path.exists(self.intl_update):
sys.exit('intltool-update does not exist in your PATH. ' + \
'Make sure it exists in your PATH..')
if not self.pot_file:
self.distribution.pot_file
if self.pot and self.dist:
sys.exit('You can only specify one option at time...\n' + \
"'python setup.py translate --help' for more info")
def run(self):
# intltool-update needs to be run inside po/
if os.path.exists('./po/'):
os.chdir('./po/')
else:
sys.exit('po/ directory not found.. not continuing...')
if self.pot:
cmd = '%s --pot' % self.intl_update
err, val = commands.getstatusoutput(cmd)
if err:
os.chdir('../')
sys.exit('Error generating template file %s' % self.pot_file)
if self.dist:
cmd = '%s %s' % (self.intl_update, self.dist)
err, val = commands.getstatusoutput(cmd)
if err:
os.chdir('../')
sys.exit('Error merging %s.po with %s' % (self.dist,self.pot_file))
os.chdir('../')
class install_constants(install_lib):
description = "Installs and substitutes file paths and other constants in constants.py.in"
def initialize_options(self):
self.build_dir = None
self.install_lib = None
self.prefix = None
self.build_dict = None
install_lib.initialize_options(self)
def finalize_options(self):
install_lib.finalize_options(self)
self.set_undefined_options('install',
('install_lib','install_lib'),
('prefix','prefix'),)
self.build_dict = {'libdir': os.path.normpath(os.path.join(self.install_lib,'straw')),
'datadir': os.path.normpath(os.path.join(self.prefix,'share'))}
def run(self):
self.announce("building constants.py...")
self.fix_constants()
install_lib.run(self)
def fix_constants(self):
if self.distribution.has_constants():
for fname,vars_dict in self.distribution.constants:
vars_dict.update(self.build_dict)
f = open(fname,'r')
cdata = f.read()
f.close()
sfname = '.'.join(fname.split('.')[:2]) # foo.py.in -> foo.py
f = open(os.path.normpath(os.path.join(self.build_dir, 'straw', sfname)),'w')
f.write(subst_vars(cdata, vars_dict))
f.close()
self.announce("... done.")
class StrawDistribution(Distribution):
def __init__(self, attrs = None):
self.modules_check = 0
self.msg_sources = None
self.pot_file = None
self.translations = []
self.config_files = []
self.desktop_file = []
self.constants = []
self.ext_modules = []
Distribution.__init__(self, attrs)
self.cmdclass = {
'install_modules_check' : install_modules_check,
'build' : straw_build,
'build_mo' : build_mo,
'translate' : translate,
'build_desktop': build_desktop,
'install' : straw_install,
'install_mo' : install_mo,
'install_desktop' : install_desktop,
'install_constants': install_constants,
'install_gconf' : install_gconf}
def has_po_files(self): return len(self.translations) > 0
def has_modules_check(self): return isinstance(self.modules_check, types.FunctionType)
def has_config_files(self): return len(self.config_files) > 0
def has_desktop_file(self): return len(self.desktop_file) > 0
def has_constants(self): return len(self.constants) > 0
def setup(**kwds):
from distutils.core import setup
kwds['distclass'] = StrawDistribution
setup(**kwds)
syntax highlighted by Code2HTML, v. 0.9.1