summaryrefslogtreecommitdiffstats
path: root/Tools/i18n
diff options
context:
space:
mode:
authorjack1142 <6032823+jack1142@users.noreply.github.com>2020-11-09 22:50:45 (GMT)
committerGitHub <noreply@github.com>2020-11-09 22:50:45 (GMT)
commitbfc6b63102d37ccb58a71711e2342143cd9f4d86 (patch)
tree7363462e163ebfa86f099802493389b42f217871 /Tools/i18n
parent1f73c320e2921605c4963e202f6bdac1ef18f2ce (diff)
downloadcpython-bfc6b63102d37ccb58a71711e2342143cd9f4d86.zip
cpython-bfc6b63102d37ccb58a71711e2342143cd9f4d86.tar.gz
cpython-bfc6b63102d37ccb58a71711e2342143cd9f4d86.tar.bz2
bpo-36310: Allow pygettext.py to detect calls to gettext in f-strings. (GH-19875)
Adds support to Tools/i18n/pygettext.py for gettext calls in f-strings. This process is done by parsing the f-strings, processing each value, and flagging the ones which contain a gettext call. Co-authored-by: Batuhan Taskaya <batuhanosmantaskaya@gmail.com>
Diffstat (limited to 'Tools/i18n')
-rwxr-xr-xTools/i18n/pygettext.py53
1 files changed, 53 insertions, 0 deletions
diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py
index b1d281d..9dd65c2 100755
--- a/Tools/i18n/pygettext.py
+++ b/Tools/i18n/pygettext.py
@@ -162,6 +162,7 @@ import sys
import glob
import time
import getopt
+import ast
import token
import tokenize
@@ -343,6 +344,58 @@ class TokenEater:
return
if ttype == tokenize.NAME and tstring in opts.keywords:
self.__state = self.__keywordseen
+ return
+ if ttype == tokenize.STRING:
+ maybe_fstring = ast.parse(tstring, mode='eval').body
+ if not isinstance(maybe_fstring, ast.JoinedStr):
+ return
+ for value in filter(lambda node: isinstance(node, ast.FormattedValue),
+ maybe_fstring.values):
+ for call in filter(lambda node: isinstance(node, ast.Call),
+ ast.walk(value)):
+ func = call.func
+ if isinstance(func, ast.Name):
+ func_name = func.id
+ elif isinstance(func, ast.Attribute):
+ func_name = func.attr
+ else:
+ continue
+
+ if func_name not in opts.keywords:
+ continue
+ if len(call.args) != 1:
+ print(_(
+ '*** %(file)s:%(lineno)s: Seen unexpected amount of'
+ ' positional arguments in gettext call: %(source_segment)s'
+ ) % {
+ 'source_segment': ast.get_source_segment(tstring, call) or tstring,
+ 'file': self.__curfile,
+ 'lineno': lineno
+ }, file=sys.stderr)
+ continue
+ if call.keywords:
+ print(_(
+ '*** %(file)s:%(lineno)s: Seen unexpected keyword arguments'
+ ' in gettext call: %(source_segment)s'
+ ) % {
+ 'source_segment': ast.get_source_segment(tstring, call) or tstring,
+ 'file': self.__curfile,
+ 'lineno': lineno
+ }, file=sys.stderr)
+ continue
+ arg = call.args[0]
+ if not isinstance(arg, ast.Constant):
+ print(_(
+ '*** %(file)s:%(lineno)s: Seen unexpected argument type'
+ ' in gettext call: %(source_segment)s'
+ ) % {
+ 'source_segment': ast.get_source_segment(tstring, call) or tstring,
+ 'file': self.__curfile,
+ 'lineno': lineno
+ }, file=sys.stderr)
+ continue
+ if isinstance(arg.value, str):
+ self.__addentry(arg.value, lineno)
def __suiteseen(self, ttype, tstring, lineno):
# skip over any enclosure pairs until we see the colon