1
# -*- coding: utf-8 -*-
2
# Copyright (c) 2010, 2011, Sebastian Wiesner <lunaryorn@googlemail.com>
5
# Redistribution and use in source and binary forms, with or without
6
# modification, are permitted provided that the following conditions are met:
8
# 1. Redistributions of source code must retain the above copyright notice,
9
# this list of conditions and the following disclaimer.
10
# 2. Redistributions in binary form must reproduce the above copyright
11
# notice, this list of conditions and the following disclaimer in the
12
# documentation and/or other materials provided with the distribution.
14
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
# POSSIBILITY OF SUCH DAMAGE.
31
KDE4-specific distutils extension code.
33
.. moduleauthor:: Sebastian Wiesner <lunaryorn@googlemail.com>
36
from __future__ import (print_function, division, unicode_literals,
42
from collections import namedtuple
43
from itertools import chain
45
from distutils import log
46
from distutils.util import change_root
47
from distutils.errors import DistutilsSetupError
48
from setuptools import Distribution as _Distribution
50
from synaptiks.setup import BaseCommand, get_output, change_prefix
53
class Distribution(_Distribution):
55
A setuptools distribution with some extra kde-specific attributes.
58
def __init__(self, attrs=None):
59
# register kde_* attributes for distutils
62
self.kde_handbook = None
63
_Distribution.__init__(self, attrs=attrs)
66
class KDEBaseCmd(BaseCommand):
67
user_options = [(b'kde4-config-exe=', None,
68
'Full path to kde4-config executable')]
70
def initialize_options(self):
71
self.kde4_config_exe = None
74
def finalize_options(self):
75
if self.kde4_config_exe is None:
76
self.kde4_config_exe = self._find_executable(
77
'kde4-config', 'Please install kdelibs')
78
self.kde4_prefix = get_output([self.kde4_config_exe, '--prefix'])
79
if not self.kde4_prefix:
80
raise SystemExit('Could not determine KDE4 installation prefix')
82
self.kde4_prefix = os.path.normpath(self.kde4_prefix)
84
def _get_install_directory(self, resource_type, with_root=True):
85
if resource_type == 'appdata':
86
tail_path = self.distribution.metadata.name
87
resource_type = 'data'
91
# manually handle KDE and XDG autostart resources, because kde4-config
92
# doesn't provide the install path for this resource type
93
if resource_type == 'autostart':
94
install_directory = os.path.join(
95
self.kde4_prefix, 'share', 'autostart')
96
elif resource_type == 'xdgconf-autostart':
98
real_prefix = getattr(sys, 'real_prefix', None)
99
if real_prefix is not None and sys.prefix != real_prefix:
100
# we are installing into a virtualenv for testing purposes, so
103
# the system-wide autostart directory is given by the XDG autostart
105
install_directory = os.path.join(root, 'etc/xdg/autostart')
107
install_directory = get_output(
108
[self.kde4_config_exe, '--install', resource_type])
109
if not install_directory:
110
raise SystemExit('Could not determine install directory '
111
'for %s' % resource_type)
113
# substitute the KDE prefix with the prefix from distutils
114
install_cmd = self.get_finalized_command('install')
115
actual_install_dir = change_prefix(
116
install_directory, self.kde4_prefix, install_cmd.prefix)
118
actual_install_dir = os.path.join(actual_install_dir, tail_path)
119
if with_root and install_cmd.root:
120
# respect a changed root
121
actual_install_dir = change_root(
122
install_cmd.root, actual_install_dir)
123
return os.path.normpath(actual_install_dir)
125
def get_outputs(self):
128
def copy_files(self, files, install_dir):
129
self.mkpath(install_dir)
130
for filename in files:
131
destname, _ = self.copy_file(filename, install_dir)
132
self._outputs.append(destname)
135
class InstallFiles(KDEBaseCmd):
136
description = 'Install KDE 4 files'
138
def finalize_options(self):
139
KDEBaseCmd.finalize_options(self)
140
self.kde_files = self.distribution.kde_files
143
if not self.kde_files:
145
for resource_type, files in self.kde_files.iteritems():
146
install_dir = self._get_install_directory(resource_type)
147
self.copy_files(files, install_dir)
150
class ThemeIcon(namedtuple('_ThemeIcon', 'theme size category filename')):
153
return os.path.join(self.theme, self.size, self.category)
155
StandAloneIcon = namedtuple('StandaloneIcon', 'filename')
158
class InstallIcons(KDEBaseCmd):
159
description = 'Install KDE icons'
161
def finalize_options(self):
162
KDEBaseCmd.finalize_options(self)
163
self.kde_icons = self.distribution.kde_icons
166
if not self.kde_icons:
168
theme_install_dir = self._get_install_directory('icon')
169
standalone_install_dir = os.path.join(
170
self._get_install_directory('appdata'), 'pics')
171
for icon in self.kde_icons:
172
if isinstance(icon, ThemeIcon):
173
dest_dir = os.path.join(theme_install_dir, icon.path)
174
elif isinstance(icon, StandAloneIcon):
175
dest_dir = standalone_install_dir
177
raise DistutilsSetupError('unknown icon type: %r' % icon)
178
self.copy_files([icon.filename], dest_dir)
181
class InstallMessages(KDEBaseCmd):
182
description = 'Install KDE message catalogs'
184
def finalize_options(self):
185
KDEBaseCmd.finalize_options(self)
186
compile_catalog = self.get_finalized_command('compile_catalog')
187
self.build_dir = compile_catalog.build_dir
188
domain = self.distribution.metadata.name
189
self.catalog_name = domain + '.mo'
191
def install_catalog(self, catalog):
192
locale = os.path.splitext(catalog)[0]
193
target_tail = os.path.join(locale, 'LC_MESSAGES')
194
target_directory = os.path.join(
195
self._get_install_directory('locale'), target_tail)
196
self.mkpath(target_directory)
197
target_file = os.path.join(target_directory, self.catalog_name)
198
source_file = os.path.join(self.build_dir, catalog)
199
destname, _ = self.copy_file(source_file, target_file)
200
self._outputs.append(destname)
203
self.run_command('compile_catalog')
204
compiled_catalogs = os.listdir(self.build_dir)
205
for catalog in compiled_catalogs:
206
self.install_catalog(catalog)
209
class BuildHandbook(BaseCommand):
211
(b'meinproc4-exe=', None, 'Full path to meinproc4 executable'),
212
(b'build-dir=', None, 'Build directory')]
214
def initialize_options(self):
215
self.meinproc4_exe = None
216
self.build_dir = None
218
def finalize_options(self):
219
if self.meinproc4_exe is None:
220
self.meinproc4_exe = self._find_executable(
221
'meinproc4', 'Please install kdelibs')
222
if self.build_dir is None:
223
build = self.get_finalized_command('build')
224
self.build_dir = os.path.join(build.build_base, 'handbook')
225
self.handbook = self.distribution.kde_handbook
226
self.handbook_directory = os.path.dirname(self.handbook)
229
self.mkpath(self.build_dir)
230
docbook_files = glob(os.path.join(
231
self.handbook_directory, '*.docbook'))
232
image_files = glob(os.path.join(self.handbook_directory, '*.png'))
233
for filename in chain(docbook_files, image_files):
234
self.copy_file(filename, self.build_dir)
235
# build the index cache
236
cache_file = os.path.join(self.build_dir, 'index.cache.bz2')
237
self.spawn([self.meinproc4_exe, '--check', '--cache', cache_file,
241
class InstallHandbook(KDEBaseCmd):
242
description = 'Install a KDE handbook'
244
user_options = KDEBaseCmd.user_options + [
245
(b'build-dir=', None, 'Build directory')]
247
def initialize_options(self):
248
KDEBaseCmd.initialize_options(self)
249
self.build_dir = None
251
def finalize_options(self):
252
KDEBaseCmd.finalize_options(self)
253
if self.build_dir is None:
254
build = self.get_finalized_command('build_kde_handbook')
255
self.build_dir = build.build_dir
256
self.name = self.distribution.metadata.name
258
def symlink(self, source, dest):
259
if self.verbose >= 1:
260
log.info('symbolically linking %s -> %s', source, dest)
263
if os.path.isdir(dest):
264
dest = os.path.join(dest, os.path.basename(source))
265
# for now, simply ignore existing symlinks, not really the way to go,
267
if not os.path.islink(dest):
268
os.symlink(source, dest)
269
# do *not* add symlink dest to outputs here due to a bug in pip 0.8.2
270
# (and possibly other versions): "pip install" removes the whole
271
# directory pointed to and leaves the symlink, instead of leaving the
272
# directory untouched and removing the symlink.
273
# self._outputs.append(dest)
277
files = [os.path.join(self.build_dir, fn)
278
for fn in os.listdir(self.build_dir)]
279
handbook_install_directory = os.path.join(
280
self._get_install_directory('html'), 'en', self.name)
281
self.copy_files(files, handbook_install_directory)
282
html_directory = self._get_install_directory('html', with_root=False)
283
self.symlink(os.path.join(html_directory, 'en', 'common'),
284
os.path.join(handbook_install_directory))
287
from setuptools.command.install import install as install_cls
288
install_cls.sub_commands.extend([
289
('install_kde_files', lambda s: True),
290
('install_kde_icons', lambda s: True),
291
('install_kde_messages', lambda s: True),
292
('install_kde_handbook', lambda s: True),
295
from distutils.command.build import build as build_cls
296
build_cls.sub_commands.append(('build_kde_handbook', lambda s: True))
299
CMDCLASS = {'install_kde_files': InstallFiles,
300
'install_kde_icons': InstallIcons,
301
'install_kde_messages': InstallMessages,
302
'build_kde_handbook': BuildHandbook,
303
'install_kde_handbook': InstallHandbook,