File: releaseutils.py

package info (click to toggle)
python-fedora 1.1.1-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,436 kB
  • sloc: python: 3,362; xml: 107; makefile: 14
file content (218 lines) | stat: -rwxr-xr-x 6,886 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#!/usr/bin/python -tt

# Copyright Red Hat Inc 2013-2015
# Licensed under the terms of the LGPLv2+

from __future__ import print_function

import glob
import os
import shutil
import sys
import textwrap

from contextlib import contextmanager
from distutils.sysconfig import get_python_lib

from kitchen.pycompat27 import subprocess
import pkg_resources

import fedora.release
from six.moves import configparser, map


#
# Helper functions
#

@contextmanager
def pushd(dirname):
    '''Contextmanager so that we can switch directories that the script is
    running in and have the current working directory restored  afterwards.
    '''
    curdir = os.getcwd()
    os.chdir(dirname)
    try:
        yield curdir
    finally:
        os.chdir(curdir)


class MsgFmt(object):
    def run(self, args):
        cmd = subprocess.Popen(args, shell=False)
        cmd.wait()


def setup_message_compiler():
    # Look for msgfmt
    try:
        # Prefer msgfmt because it will throw errors on misformatted messages
        subprocess.Popen(['msgfmt', '-h'], stdout=subprocess.PIPE)
    except OSError:
        import babel.messages.frontend

        return (
            babel.messages.frontend.CommandLineInterface(),
            'pybabel compile -D %(domain)s -d locale -i %(pofile)s -l %(lang)s'
        )
    else:
        return (
            MsgFmt(),
            'msgfmt -c -o locale/%(lang)s/LC_MESSAGES/%(domain)s.mo %(pofile)s'
        )


def build_catalogs():
    # Get the directory with message catalogs
    # Reuse transifex's config file first as it will know this
    cfg = configparser.SafeConfigParser()
    cfg.read('.tx/config')
    cmd, args = setup_message_compiler()

    try:
        shutil.rmtree('locale')
    except OSError as e:
        # If the error is that locale does not exist, we're okay.  We're
        # deleting it here, afterall
        if e.errno != 2:
            raise

    for section in [s for s in cfg.sections() if s != 'main']:
        try:
            file_filter = cfg.get(section, 'file_filter')
            source_file = cfg.get(section, 'source_file')
        except configparser.NoOptionError:
            continue
        glob_pattern = file_filter.replace('<lang>', '*')
        pot = os.path.basename(source_file)
        if pot.endswith('.pot'):
            pot = pot[:-4]
        arg_values = {'domain': pot}
        for po_file in glob.glob(glob_pattern):
            file_pattern = os.path.basename(po_file)
            lang = file_pattern.replace('.po', '')
            os.makedirs(os.path.join('locale', lang, 'LC_MESSAGES'))
            arg_values['pofile'] = po_file
            arg_values['lang'] = lang
            compile_args = args % arg_values
            compile_args = compile_args.split(' ')
            cmd.run(compile_args)


def _add_destdir(path):
    if ENVVARS['DESTDIR'] is not None:
        if path.startswith('/'):
            path = path[1:]
        path = os.path.join(ENVVARS['DESTDIR'], path)
    return path


def _install_catalogs(localedir):
    with pushd('locale'):
        for catalog in glob.glob('*/LC_MESSAGES/*.mo'):
            # Make the directory for the locale
            dirname = os.path.dirname(catalog)
            dst = os.path.join(localedir, dirname)
            try:
                os.makedirs(dst, 0o755)
            except OSError as e:
                # Only allow file exists to pass
                if e.errno != 17:
                    raise
            shutil.copy2(catalog, dst)


def install_catalogs():
    # First try to install the messages to an FHS location
    if ENVVARS['INSTALLSTRATEGY'] == 'EGG':
        localedir = get_python_lib()

        # Need certain info from the user
        if ENVVARS['PACKAGENAME'] is None:
            print ('Set the PACKAGENAME environment variable and try again')
            sys.exit(2)
        if ENVVARS['MODULENAME'] is None:
            print ('Set the MODULENAME environment variable and try again')
            sys.exit(2)

        # Get teh egg name from pkg_resources
        dist = pkg_resources.Distribution(project_name=ENVVARS['PACKAGENAME'],
                                          version=fedora.release.VERSION)

        # Set the localedir to be inside the egg directory
        localedir = os.path.join(localedir, '{}.egg'.format(dist.egg_name()),
                                 ENVVARS['MODULENAME'], 'locale')
        # Tack on DESTDIR if needed
        localedir = _add_destdir(localedir)
        _install_catalogs(localedir)

    elif ENVVARS['INSTALLSTRATEGY'] == 'SITEPACKAGES':
        # For a generic utility to be used with other modules, this would also
        # need to handle arch-specific locations (get_python_lib(1))

        # Retrieve the site-packages directory
        localedir = get_python_lib()

        # Set the install path to be inside of the module in site-packages
        if ENVVARS['MODULENAME'] is None:
            print ('Set the MODULENAME environment variable and try again')
            sys.exit(2)
        localedir = os.path.join(localedir, ENVVARS['MODULENAME'], 'locale')
        localedir = _add_destdir(localedir)
        _install_catalogs(localedir)

    else:
        # FHS
        localedir = _add_destdir('/usr/share/locale')
        _install_catalogs(localedir)


def usage():
    print ('Subcommands:')
    for command in sorted(SUBCOMMANDS.keys()):
        print('%-15s  %s' % (command, SUBCOMMANDS[command][1]))

    print()
    print('This script can be customized by setting the following ENV VARS:')
    for var in sorted(ENVVARDESC.keys()):
        lines = textwrap.wrap(
            '%-15s  %s' % (var, ENVVARDESC[var]),
            subsequent_indent=' '*8
        )
        for line in lines:
            print(line.rstrip())
    sys.exit(1)

SUBCOMMANDS = {
    'build_catalogs': (
        build_catalogs, 'Compile the message catalogs from po files'
    ),
    'install_catalogs': (
        install_catalogs,
        'Install the message catalogs to the system'
    ),
}

ENVVARDESC = {
    'DESTDIR': 'Alternate root directory hierarchy to install into',
    'PACKAGENAME': 'Pypi packagename (commonly the setup.py name field)',
    'MODULENAME': 'Python module name (commonly used with import NAME)',
    'INSTALLSTRATEGY': 'One of FHS, EGG, SITEPACKAGES.  FHS will work'
    ' for system packages installed using'
    ' --single-version-externally-managed.  EGG install into an egg'
    ' directory.  SITEPACKAGES will install into a $PACKAGENAME'
    ' directory directly in site-packages.  Default FHS'
}

ENVVARS = dict(map(lambda k: (k, os.environ.get(k)), ENVVARDESC.keys()))

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('At least one subcommand is needed\n')
        usage()
    try:
        SUBCOMMANDS[sys.argv[1]][0]()
    except KeyError:
        print ('Unknown subcommand: %s\n' % sys.argv[1])
        usage()