3
# Copyright 2013 Canonical Ltd.
5
# This program is free software: you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License version 3, as published
7
# by the Free Software Foundation.
9
# This program is distributed in the hope that it will be useful, but
10
# WITHOUT ANY WARRANTY; without even the implied warranties of
11
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12
# PURPOSE. See the GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License along
15
# with this program. If not, see <http://www.gnu.org/licenses/>.
17
# In addition, as a special exception, the copyright holders give
18
# permission to link the code of portions of this program with the
19
# OpenSSL library under certain conditions as described in each
20
# individual source file, and distribute linked combinations
22
# You must obey the GNU General Public License in all respects
23
# for all of the code used other than OpenSSL. If you modify
24
# file(s) with this exception, you may extend this exception to your
25
# version of the file(s), but you are not obligated to do so. If you
26
# do not wish to do so, delete this exception statement from your
27
# version. If you delete this exception statement from all source
28
# files in the program, then also delete it here.
29
"""Setup.py: build, distribute, clean."""
35
import DistUtilsExtra.auto
36
from DistUtilsExtra.command import build_extra, build_i18n
38
print >> sys.stderr, 'To build this program you need '\
39
'https://launchpad.net/python-distutils-extra'
41
assert DistUtilsExtra.auto.__version__ >= '2.18', \
42
'needs DistUtilsExtra.auto >= 2.18'
45
PROJECT_NAME = 'ubuntuone-client'
48
POT_FILE = 'po/%s.pot' % PROJECT_NAME
49
SERVICE_FILES = ['data/com.ubuntuone.Credentials.service',
50
'data/com.ubuntuone.SyncDaemon.service']
51
CONFIG_FILES = ['data/logging.conf']
52
CLIENTDEFS = 'ubuntuone/clientdefs.py'
54
BUILD_FILES = [CLIENTDEFS] + CONFIG_FILES
55
CLEANFILES = [POT_FILE, 'MANIFEST'] + BUILD_FILES + SERVICE_FILES
57
if int(VERSION.split('.')[1]) % 2 != 0:
59
LOG_FILE_SIZE = '10485760'
62
LOG_FILE_SIZE = '1048576'
65
def replace_variables(files_to_replace, prefix=None, *args, **kwargs):
66
"""Replace the @VERSION@ in the constants file with the actual version."""
67
for fname in files_to_replace:
68
with open(fname + '.in') as in_file:
69
content = in_file.read()
70
with open(fname, 'w') as out_file:
71
content = content.replace('@VERSION@', VERSION)
72
content = content.replace('@PROJECT_NAME@', PROJECT_NAME)
73
content = content.replace('@GETTEXT_PACKAGE@', PROJECT_NAME)
74
content = content.replace('@LOG_LEVEL@', LOG_LEVEL)
75
content = content.replace('@LOG_FILE_SIZE@', LOG_FILE_SIZE)
76
if prefix is not None:
77
content = content.replace(
78
'@localedir@', os.path.join(prefix,
80
content = content.replace(
81
'@libexecdir@', os.path.join(prefix,
83
out_file.write(content)
86
class Install(DistUtilsExtra.auto.install_auto):
87
"""Class to install proper files."""
92
Read from *.service.in and generate .service files by replacing
93
@prefix@ by self.prefix.
97
# Remove the contrib and tests packages from the packages list
98
# as they are not meant to be installed to the system.
99
pkgs = [x for x in self.distribution.packages if not (
100
x.startswith('contrib') or x.startswith('tests'))]
101
self.distribution.packages = pkgs
103
# Remove the input and dev files from the data files list,
104
# as they are not meant to be installed.
105
data_files = [x for x in self.distribution.data_files if not (
106
x[1][0].endswith('.in') or x[1][0].endswith('-dev.conf'))]
107
self.distribution.data_files = data_files
109
# Get just the prefix value, without the root
110
prefix = self.install_data.replace(
111
self.root if self.root is not None else '', '')
112
replace_variables(SERVICE_FILES, prefix)
113
DistUtilsExtra.auto.install_auto.run(self)
114
# Replace the CLIENTDEFS paths here, so that we can do it directly in
115
# the installed copy, rather than the lcoal copy. This allows us to
116
# have a semi-generated version for use in tests, and a full version
117
# for use in installed systems.
118
with open(CLIENTDEFS) as in_file:
119
content = in_file.read()
120
with open(os.path.join(self.install_purelib,
122
CLIENTDEFS), 'w') as out_file:
123
content = content.replace(
124
'@localedir@', os.path.join(prefix, 'share', 'locale'))
125
content = content.replace(
126
'@libexecdir@', os.path.join(prefix, 'lib', PROJECT_NAME))
127
out_file.write(content)
130
class Build(build_extra.build_extra):
131
"""Build PyQt (.ui) files and resources."""
133
description = "build PyQt GUIs (.ui) and resources (.qrc)"
136
"""Execute the command."""
137
replace_variables(BUILD_FILES)
138
build_extra.build_extra.run(self)
141
class Clean(DistUtilsExtra.auto.clean_build_tree):
142
"""Class to clean up after the build."""
145
"""Clean up the built files."""
146
for built_file in CLEANFILES:
147
if os.path.exists(built_file):
148
os.unlink(built_file)
150
DistUtilsExtra.auto.clean_build_tree.run(self)
153
class BuildLocale(build_i18n.build_i18n):
154
"""Work around a bug in DistUtilsExtra."""
158
build_i18n.build_i18n.run(self)
160
for df in self.distribution.data_files:
161
if df[0].startswith('etc/xdg/'):
162
if sys.platform not in ('darwin', 'win32'):
163
new_df = (df[0].replace('etc/xdg/', '/etc/xdg/'), df[1])
164
self.distribution.data_files[i] = new_df
166
self.distribution.data_files.pop(i)
170
def set_py2exe_paths():
171
"""Set the path so that py2exe finds the required modules."""
172
# Pylint does not understand same spaced imports
173
# pylint: disable=F0401
175
# pylint: enable=F0401
177
# pylint: disable=F0401
178
import py2exe.mf as modulefinder
179
# pylint: enable=F0401
183
# py2exe 0.6.4 introduced a replacement modulefinder.
184
# This means we have to add package paths there,
185
# not to the built-in one. If this new modulefinder gets
186
# integrated into Python, then we might be able to revert
187
# this some day. If this doesn't work, try import modulefinder
188
for package_path in win32com.__path__[1:]:
189
modulefinder.AddPackagePath("win32com", package_path)
190
for extra_mod in ["win32com.server", "win32com.client"]:
191
__import__(extra_mod)
192
module = sys.modules[extra_mod]
193
for module_path in module.__path__[1:]:
194
modulefinder.AddPackagePath(extra_mod, module_path)
197
# pylint: disable=C0103
203
'build_i18n': BuildLocale,
208
'bin/ubuntuone-launch',
212
'bin/ubuntuone-login',
213
'bin/ubuntuone-proxy-tunnel',
214
'bin/ubuntuone-syncdaemon',
220
if sys.platform == 'win32':
228
'dll_excludes': ["mswsock.dll", "powrprof.dll"],
231
# add the console script so that py2exe compiles it
232
'console': bin_scripts + libexec_scripts,
237
('lib/%s' % PROJECT_NAME, libexec_scripts),
238
('share/dbus-1/services', SERVICE_FILES),
239
('/etc/xdg/ubuntuone', CONFIG_FILES + ['data/syncdaemon.conf']),
240
('/etc/apport/crashdb.conf.d', ['data/ubuntuone-client-crashdb.conf']),
241
('share/apport/package-hooks', ['data/source_ubuntuone-client.py']),
242
('share/man/man1', ['docs/man/u1sdtool.1']),
244
scripts.extend(bin_scripts)
247
DistUtilsExtra.auto.setup(
251
author='Ubuntu One Developers',
252
author_email='ubuntuone-users@lists.launchpad.net',
253
description='Ubuntu One file synchronization client',
254
url='https://launchpad.net/%s' % PROJECT_NAME,
255
extra_path=PROJECT_NAME,
257
data_files=data_files,