tacker/tools/check_i18n.py
Hervé Beraud 2e7813d09d Stop to use the __future__ module.
The __future__ module [1] was used in this context to ensure compatibility
between python 2 and python 3.

We previously dropped the support of python 2.7 [2] and now we only support
python 3 so we don't need to continue to use this module and the imports
listed below.

Imports commonly used and their related PEPs:
- `division` is related to PEP 238 [3]
- `print_function` is related to PEP 3105 [4]
- `unicode_literals` is related to PEP 3112 [5]
- `with_statement` is related to PEP 343 [6]
- `absolute_import` is related to PEP 328 [7]

[1] https://docs.python.org/3/library/__future__.html
[2] https://governance.openstack.org/tc/goals/selected/ussuri/drop-py27.html
[3] https://www.python.org/dev/peps/pep-0238
[4] https://www.python.org/dev/peps/pep-3105
[5] https://www.python.org/dev/peps/pep-3112
[6] https://www.python.org/dev/peps/pep-0343
[7] https://www.python.org/dev/peps/pep-0328

Change-Id: I2436a7fd91a1d081c2c5fac28452a57f048e5a73
2020-06-02 21:00:17 +02:00

153 lines
5.3 KiB
Python

# Copyright 2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import compiler
import os.path
import sys
from oslo_utils import importutils
def is_localized(node):
"""Check message wrapped by _()"""
if isinstance(node.parent, compiler.ast.CallFunc):
if isinstance(node.parent.node, compiler.ast.Name):
if node.parent.node.name == '_':
return True
return False
class ASTWalker(compiler.visitor.ASTVisitor):
def default(self, node, *args):
for child in node.getChildNodes():
child.parent = node
compiler.visitor.ASTVisitor.default(self, node, *args)
class Visitor(object):
def __init__(self, filename, i18n_msg_predicates,
msg_format_checkers, debug):
self.filename = filename
self.debug = debug
self.error = 0
self.i18n_msg_predicates = i18n_msg_predicates
self.msg_format_checkers = msg_format_checkers
with open(filename) as f:
self.lines = f.readlines()
def visitConst(self, node):
if not isinstance(node.value, str):
return
if is_localized(node):
for (checker, msg) in self.msg_format_checkers:
if checker(node):
print('%s:%d %s: %s Error: %s' %
(self.filename, node.lineno,
self.lines[node.lineno - 1][:-1],
checker.__name__, msg),
file=sys.stderr)
self.error = 1
return
if debug:
print('%s:%d %s: %s' %
(self.filename, node.lineno,
self.lines[node.lineno - 1][:-1],
"Pass"))
else:
for (predicate, action, msg) in self.i18n_msg_predicates:
if predicate(node):
if action == 'skip':
if debug:
print('%s:%d %s: %s' %
(self.filename, node.lineno,
self.lines[node.lineno - 1][:-1],
"Pass"))
return
elif action == 'error':
print('%s:%d %s: %s Error: %s' %
(self.filename, node.lineno,
self.lines[node.lineno - 1][:-1],
predicate.__name__, msg),
file=sys.stderr)
self.error = 1
return
elif action == 'warn':
print('%s:%d %s: %s' %
(self.filename, node.lineno,
self.lines[node.lineno - 1][:-1],
"Warn: %s" % msg))
return
print('Predicate with wrong action!', file=sys.stderr)
def is_file_in_black_list(black_list, f):
for f in black_list:
if os.path.abspath(input_file).startswith(
os.path.abspath(f)):
return True
return False
def check_i18n(input_file, i18n_msg_predicates, msg_format_checkers, debug):
input_mod = compiler.parseFile(input_file)
v = compiler.visitor.walk(input_mod,
Visitor(input_file,
i18n_msg_predicates,
msg_format_checkers,
debug),
ASTWalker())
return v.error
if __name__ == '__main__':
input_path = sys.argv[1]
try:
cfg_mod = importutils.import_module(tools.check_i18n)
except Exception:
print("Load cfg module failed", file=sys.stderr)
sys.exit(1)
i18n_msg_predicates = cfg_mod.i18n_msg_predicates
msg_format_checkers = cfg_mod.msg_format_checkers
black_list = cfg_mod.file_black_list
debug = False
if len(sys.argv) > 2:
if sys.argv[2] == '-d':
debug = True
if os.path.isfile(input_path):
sys.exit(check_i18n(input_path,
i18n_msg_predicates,
msg_format_checkers,
debug))
error = 0
for dirpath, dirs, files in os.walk(input_path):
for f in files:
if not f.endswith('.py'):
continue
input_file = os.path.join(dirpath, f)
if is_file_in_black_list(black_list, input_file):
continue
if check_i18n(input_file,
i18n_msg_predicates,
msg_format_checkers,
debug):
error = 1
sys.exit(error)