13
13
'find_potfiles_in',
16
from contextlib import contextmanager
22
def find_potfiles_in(backend, package_dir):
23
"""Search `package_dir` and its subdirectories for POTFILES.in.
25
:param backend: The `Backend` where work is done.
26
:param package_dir: The directory to search.
27
:returns: A list of names of directories that contain a file
28
POTFILES.in, relative to `package_dir`.
20
from subprocess import call
23
def find_potfiles_in():
24
"""Search the current directory and its subdirectories for POTFILES.in.
26
:returns: A list of names of directories that contain a file POTFILES.in.
31
package_dir, include_directories=False, name="POTFILES.in")
32
return [os.path.dirname(path) for path in paths]
35
def check_potfiles_in(backend, path):
29
for dirpath, dirnames, dirfiles in os.walk("."):
30
if "POTFILES.in" in dirfiles:
31
result_dirs.append(dirpath)
35
def check_potfiles_in(path):
36
36
"""Check if the files listed in the POTFILES.in file exist.
38
38
Running 'intltool-update -m' will perform this check and also take a
45
45
all listed files exist. The presence of the 'notexist' file tells us
48
:param backend: The `Backend` where work is done.
49
48
:param path: The directory where POTFILES.in resides.
50
49
:returns: False if the directory does not exist, if an error occurred
51
50
when executing intltool-update or if files are missing from
52
51
POTFILES.in. True if all went fine and all files in POTFILES.in
55
# Abort nicely if the directory does not exist.
56
if not backend.isdir(path):
54
current_path = os.getcwd()
59
# Abort nicely if the directory does not exist.
60
if e.errno == errno.ENOENT:
64
# Remove stale files from a previous run of intltool-update -m.
65
for unlink_name in ['missing', 'notexist']:
67
os.unlink(unlink_name)
69
# It's ok if the files are missing.
70
if e.errno != errno.ENOENT:
72
devnull = open("/dev/null", "w")
74
["/usr/bin/intltool-update", "-m"],
75
stdout=devnull, stderr=devnull)
78
os.chdir(current_path)
81
# An error occurred when executing intltool-update.
58
# Remove stale files from a previous run of intltool-update -m.
61
[os.path.join(path, name) for name in ("missing", "notexist")])
62
with open("/dev/null", "w") as devnull:
65
["/usr/bin/intltool-update", "-m"],
66
stdout=devnull, stderr=devnull, cwd=path)
67
except subprocess.CalledProcessError:
70
return not backend.path_exists(os.path.join(path, "notexist"))
73
def find_intltool_dirs(backend, package_dir):
84
notexist = os.path.join(path, "notexist")
85
return not os.access(notexist, os.R_OK)
88
def find_intltool_dirs():
74
89
"""Search for directories with intltool structure.
76
`package_dir` and its subdirectories are searched. An 'intltool
91
The current directory and its subdiretories are searched. An 'intltool
77
92
structure' is a directory that contains a POFILES.in file and where all
78
93
files listed in that POTFILES.in do actually exist. The latter
79
94
condition makes sure that the file is not stale.
81
:param backend: The `Backend` where work is done.
82
:param package_dir: The directory to search.
83
:returns: A list of directory names, relative to `package_dir`.
96
:returns: A list of directory names.
86
podir for podir in find_potfiles_in(backend, package_dir)
87
if check_potfiles_in(backend, os.path.join(package_dir, podir)))
98
return sorted(filter(check_potfiles_in, find_potfiles_in()))
90
101
def _get_AC_PACKAGE_NAME(config_file):
154
163
config_files = []
155
164
for filename, varname, keep_trying in locations:
156
165
path = os.path.join(dirname, filename)
157
if not backend.path_exists(path):
166
if not os.access(path, os.R_OK):
158
167
# Skip non-existent files.
160
with tempfile.NamedTemporaryFile() as local_file:
161
backend.copy_out(path, local_file.name)
162
config_files.append(ConfigFile(local_file.file))
169
config_files.append(ConfigFile(path))
163
170
new_value = config_files[-1].getVariable(varname)
164
171
if new_value is not None:
165
172
value = new_value
190
205
"has an additional effect: the name of current working directory is no
191
206
more limited to 'po' or 'po-*'." We don't want that limit either.
193
:param backend: The `Backend` where work is done.
194
208
:param podir: The PO directory in which to build template.
195
209
:param domain: The translation domain to use as the name of the template.
196
210
If it is None or empty, 'messages.pot' will be used.
197
:return: The effective domain if generation succeeded, otherwise None.
211
:return: True if generation succeeded.
199
213
if domain is None or domain.strip() == "":
200
214
domain = "messages"
201
with open("/dev/null", "w") as devnull:
216
with open("/dev/null", "w") as devnull:
204
218
["/usr/bin/intltool-update", "-p", "-g", domain],
205
stdout=devnull, stderr=devnull, cwd=podir)
207
except subprocess.CalledProcessError:
211
def generate_pots(backend, package_dir):
219
stdout=devnull, stderr=devnull)
220
return returncode == 0
223
def generate_pots(package_dir='.'):
212
224
"""Top-level function to generate all PO templates in a package."""
214
for podir in find_intltool_dirs(backend, package_dir):
215
full_podir = os.path.join(package_dir, podir)
216
domain = get_translation_domain(backend, full_podir)
217
effective_domain = generate_pot(backend, full_podir, domain)
218
if effective_domain is not None:
219
potpaths.append(os.path.join(podir, effective_domain + ".pot"))
226
with chdir(package_dir):
227
for podir in find_intltool_dirs():
228
domain = get_translation_domain(podir)
229
if generate_pot(podir, domain):
230
potpaths.append(os.path.join(podir, domain + ".pot"))
234
class ConfigFile(object):
224
235
"""Represent a config file and return variables defined in it."""
226
237
def __init__(self, file_or_name):
227
if isinstance(file_or_name, str):
228
with open(file_or_name) as conf_file:
229
self.content = conf_file.read()
231
self.content = file_or_name.read()
238
with open(file_or_name) as conf_file:
239
self.content = conf_file.read()
233
241
def _stripQuotes(self, identifier):
234
242
"""Strip surrounding quotes from `identifier`, if present.