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()
|