setup.py 8.61 KB
Newer Older
André's avatar
André committed
1 2 3 4 5 6 7 8 9 10 11
#!/usr/bin/env python3

import os
import sys

if sys.version_info[0] < 3:
    sys.exit('Tried to install with Python 2, gajim only supports Python 3.')

import codecs

from setuptools import setup, find_packages
André's avatar
André committed
12
from setuptools import Command
13
from setuptools.command.build_py import build_py as _build
André's avatar
André committed
14 15 16 17 18 19 20
from distutils import log
from distutils.util import convert_path, newer

import gajim

pos = [x for x in os.listdir('po') if x[-3:] == ".po"]
ALL_LINGUAS = sorted([os.path.split(x)[-1][:-3] for x in pos])
21
cwd = os.path.dirname(os.path.realpath(__file__))
André's avatar
André committed
22

André's avatar
André committed
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

def update_trans():
    '''
    Update translation files
    '''
    template = os.path.join('po', 'gajim.pot')
    files = [os.path.join(root, f) for root, d, files in os.walk('gajim') for f in files if os.path.isfile(
        os.path.join(root, f)) and (f.endswith('.py') or f.endswith('.ui'))]
    files.append(os.path.join("data", "gajim-remote.desktop.in"))
    files.append(os.path.join("data", "org.gajim.Gajim.desktop.in"))
    files.append(os.path.join("data", "org.gajim.Gajim.appdata.xml.in"))
    cmd = 'xgettext --from-code=utf-8 -o %s %s' % (
        template, " ".join(files))
    if os.system(cmd) != 0:
        msg = "ERROR: %s could not be created!\n" % template
        raise SystemExit(msg)

    for lang in ALL_LINGUAS:
        po_file = os.path.join('po', lang + '.po')
        cmd = 'msgmerge -U %s %s' % (po_file, template)
        if os.system(cmd) != 0:
            msg = 'ERROR: Updating language translation file failed.'
            ask = msg + '\n Continue updating y/n [n] '
            reply = input(ask)
            if reply in ['n', 'N']:
                raise SystemExit(msg)
        log.info('Updating %s', po_file)


André's avatar
André committed
52 53 54 55 56 57 58
def build_trans(build_cmd):
    '''
    Translate the language files into gajim.mo
    '''
    data_files = build_cmd.distribution.data_files
    for lang in ALL_LINGUAS:
        po_file = os.path.join('po', lang + '.po')
André's avatar
André committed
59
        mo_file = os.path.join(cwd, 'build', 'mo', lang, 'LC_MESSAGES', 'gajim.mo')
André's avatar
André committed
60
        mo_dir = os.path.dirname(mo_file)
61
        if not (os.path.isdir(mo_dir) or os.path.islink(mo_dir)):
André's avatar
André committed
62 63 64 65 66 67 68 69 70 71 72 73 74
            os.makedirs(mo_dir)

        if newer(po_file, mo_file):
            cmd = 'msgfmt %s -o %s' % (po_file, mo_file)
            if os.system(cmd) != 0:
                os.remove(mo_file)
                msg = 'ERROR: Building language translation files failed.'
                ask = msg + '\n Continue building y/n [n] '
                reply = input(ask)
                if reply in ['n', 'N']:
                    raise SystemExit(msg)
            log.info('Compiling %s >> %s', po_file, mo_file)

André's avatar
André committed
75
        # linux specific piece:
André's avatar
André committed
76
        target = 'share/locale/' + lang + '/LC_MESSAGES'
77
        data_files.append((target, [mo_file]))
André's avatar
André committed
78

André's avatar
André committed
79

André's avatar
André committed
80 81
def build_man(build_cmd):
    '''
82
    Compress Gajim manual files
André's avatar
André committed
83 84 85 86
    '''
    data_files = build_cmd.distribution.data_files
    for man in ['gajim.1', 'gajim-history-manager.1', 'gajim-remote.1']:
        filename = os.path.join('data', man)
André's avatar
André committed
87
        newdir = os.path.join(cwd, 'build', 'man')
88
        if not (os.path.isdir(newdir) or os.path.islink(newdir)):
André's avatar
André committed
89 90 91 92 93 94 95 96 97 98 99
            os.makedirs(newdir)

        import gzip
        man_file_gz = os.path.join(newdir, man + '.gz')
        if os.path.exists(man_file_gz):
            if newer(filename, man_file_gz):
                os.remove(man_file_gz)
            else:
                filename = False

        if filename:
André's avatar
André committed
100
            # Binary io, so open is OK
André's avatar
André committed
101 102 103 104 105 106
            with open(filename, 'rb') as f_in,\
                    gzip.open(man_file_gz, 'wb') as f_out:
                f_out.writelines(f_in)
                log.info('Compiling %s >> %s', filename, man_file_gz)

        target = 'share/man/man1'
André's avatar
André committed
107
        data_files.append((target, [man_file_gz]))
André's avatar
André committed
108

André's avatar
André committed
109

André's avatar
André committed
110 111 112 113 114
def build_intl(build_cmd):
    '''
    Merge translation files into desktop and mime files
    '''
    data_files = build_cmd.distribution.data_files
115
    base = cwd
André's avatar
André committed
116

André's avatar
André committed
117 118 119
    merge_files = (('data/org.gajim.Gajim.desktop', 'share/applications', '--desktop'),
                   ('data/gajim-remote.desktop', 'share/applications', '--desktop'),
                   ('data/org.gajim.Gajim.appdata.xml', 'share/metainfo', '--xml'))
André's avatar
André committed
120 121 122 123 124 125 126 127 128 129

    for filename, target, option in merge_files:
        filenamelocal = convert_path(filename)
        newfile = os.path.join(base, filenamelocal)
        newdir = os.path.dirname(newfile)
        if not(os.path.isdir(newdir) or os.path.islink(newdir)):
            os.makedirs(newdir)
        merge(filenamelocal + '.in', newfile, option)
        data_files.append((target, [base + '/' + filename]))

André's avatar
André committed
130

André's avatar
André committed
131 132 133 134 135 136 137 138 139 140 141 142 143 144
def substitute_variables(filename_in, filename_out, subst_vars):
    '''
    Substitute variables in a file.
    '''
    f_in = codecs.open(filename_in, encoding='utf-8')
    f_out = codecs.open(filename_out, encoding='utf-8', mode='w')
    for line in f_in:
        for variable, substitution in subst_vars:
            line = line.replace(variable, substitution)
        f_out.write(line)
    f_in.close()
    f_out.close()


André's avatar
André committed
145
def merge(in_file, out_file, option, po_dir='po'):
André's avatar
André committed
146
    '''
André's avatar
André committed
147
    Run the msgfmt command.
André's avatar
André committed
148
    '''
149
    if os.path.exists(in_file):
André's avatar
André committed
150
        cmd = (('msgfmt %(opt)s -d %(po_dir)s --template %(in_file)s '
André's avatar
André committed
151 152 153 154 155
                '-o %(out_file)s') %
               {'opt': option,
                'po_dir': po_dir,
                'in_file': in_file,
                'out_file': out_file})
André's avatar
André committed
156 157
        if os.system(cmd) != 0:
            msg = ('ERROR: %s was not merged into the translation files!\n' %
André's avatar
André committed
158
                   out_file)
André's avatar
André committed
159 160 161 162 163 164 165
            raise SystemExit(msg)
        log.info('Compiling %s >> %s', in_file, out_file)


class build(_build):
    def run(self):
        build_trans(self)
166
        if sys.platform != 'win32':
André's avatar
André committed
167 168 169 170 171
            build_man(self)
            build_intl(self)
        _build.run(self)


André's avatar
André committed
172 173 174 175 176 177 178 179 180 181 182 183 184
class test(Command):
    description = "Run all tests"
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        os.system("./test/runtests.py")

André's avatar
André committed
185

André's avatar
André committed
186 187 188 189 190 191
class test_nogui(test):
    description = "Run tests without GUI"

    def run(self):
        os.system("./test/runtests.py -n")

André's avatar
André committed
192

André's avatar
André committed
193 194 195 196 197 198 199 200 201 202 203 204 205
class update_po(Command):
    description = "Update po files"
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        update_trans()

André's avatar
André committed
206

207
package_data_activities = ['data/activities/*/*/*.png']
André's avatar
André committed
208 209 210 211
package_data_emoticons = ['data/emoticons/*/emoticons_theme.py',
                          'data/emoticons/*/*.png',
                          'data/emoticons/*/LICENSE']
package_data_gui = ['data/gui/*.ui']
André's avatar
André committed
212 213 214 215 216
package_data_icons = ['data/icons/hicolor/*/*/*.png',
                      'data/icons/hicolor/*/*/*.svg']
package_data_iconsets = ['data/iconsets/*/*/*.gif',
                         'data/iconsets/*/*/*.png',
                         'data/iconsets/transports/*/*/*.png']
217
package_data_moods = ['data/moods/*/*.png']
André's avatar
André committed
218
package_data_other = ['data/other/*']
219
package_data_sounds = ['data/sounds/*.wav']
André's avatar
André committed
220
package_data_style = ['data/style/gajim.css']
221
package_plugins_data = ['data/plugins/*/*']
222 223
package_data = (package_data_activities
                + package_data_emoticons
André's avatar
André committed
224 225 226
                + package_data_gui
                + package_data_icons
                + package_data_iconsets
227
                + package_data_moods
André's avatar
André committed
228
                + package_data_other
229 230 231
                + package_data_sounds
                + package_data_style
                + package_plugins_data)
André's avatar
André committed
232 233 234 235


# only install subdirectories of data
data_files_app_icon = [
André's avatar
André committed
236 237 238 239 240 241 242
    ("share/icons/hicolor/64x64/apps",
     ["gajim/data/icons/hicolor/64x64/apps/org.gajim.Gajim.png"]),
    ("share/icons/hicolor/128x128/apps",
     ["gajim/data/icons/hicolor/128x128/apps/org.gajim.Gajim.png"]),
    ("share/icons/hicolor/scalable/apps",
     ["gajim/data/icons/hicolor/scalable/apps/org.gajim.Gajim.svg"])
]
André's avatar
André committed
243 244 245 246

data_files = data_files_app_icon

setup(
André's avatar
André committed
247 248 249 250 251 252 253 254
    name="gajim",
    description='A GTK+ Jabber client',
    version=gajim.__version__,
    author="Philipp Hörist, Yann Leboulanger",
    author_email="gajim-devel@gajim.org",
    url='https://gajim.org',
    license='GPL v3',
    classifiers=[
255 256
        'Programming Language :: Python :: 3',
    ],
André's avatar
André committed
257
    cmdclass={
258
        'build_py': build,
André's avatar
André committed
259 260
        'test': test,
        'test_nogui': test_nogui,
André's avatar
André committed
261
        'update_po': update_po,
André's avatar
André committed
262
    },
André's avatar
André committed
263
    scripts=[
André's avatar
André committed
264 265
        'scripts/gajim',
        'scripts/gajim-history-manager',
André's avatar
André committed
266 267 268 269 270
        'scripts/gajim-remote'],
    packages=find_packages(exclude=["gajim.dev", "test*"]),
    package_data={'gajim': package_data},
    data_files=data_files,
    install_requires=[
Philipp Hörist's avatar
Philipp Hörist committed
271
        'dbus-python;sys_platform=="linux"',
André's avatar
André committed
272
        'nbxmpp',
André's avatar
André committed
273
        'pyOpenSSL>=0.12',
Philipp Hörist's avatar
Philipp Hörist committed
274
        'pyasn1',
André's avatar
André committed
275
    ],
André's avatar
André committed
276
)