1#!/usr/bin/env python 2 3# Copyright 2017 The Kubernetes Authors. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""Extract strings from command files and externalize into translation files. 18Expects to be run from the root directory of the repository. 19 20Usage: 21 extract.py pkg/kubectl/cmd/apply.go 22 23""" 24import fileinput 25import sys 26import re 27 28class MatchHandler(object): 29 """ Simple holder for a regular expression and a function 30 to run if that regular expression matches a line. 31 The function should expect (re.match, file, linenumber) as parameters 32 """ 33 def __init__(self, regex, replace_fn): 34 self.regex = re.compile(regex) 35 self.replace_fn = replace_fn 36 37def short_replace(match, file, line_number): 38 """Replace a Short: ... cobra command description with an internationalization 39 """ 40 sys.stdout.write('{}i18n.T({}),\n'.format(match.group(1), match.group(2))) 41 42SHORT_MATCH = MatchHandler(r'(\s+Short:\s+)("[^"]+"),', short_replace) 43 44def import_replace(match, file, line_number): 45 """Add an extra import for the i18n library. 46 Doesn't try to be smart and detect if it's already present, assumes a 47 gofmt round wil fix things. 48 """ 49 sys.stdout.write('{}\n"k8s.io/kubectl/pkg/util/i18n"\n'.format(match.group(1))) 50 51IMPORT_MATCH = MatchHandler('(.*"k8s.io/kubectl/pkg/cmd/util")', import_replace) 52 53 54def string_flag_replace(match, file, line_number): 55 """Replace a cmd.Flags().String("...", "", "...") with an internationalization 56 """ 57 sys.stdout.write('{}i18n.T("{})"))\n'.format(match.group(1), match.group(2))) 58 59STRING_FLAG_MATCH = MatchHandler('(\s+cmd\.Flags\(\).String\("[^"]*", "[^"]*", )"([^"]*)"\)', string_flag_replace) 60 61 62def long_string_replace(match, file, line_number): 63 return '{}i18n.T({}){}'.format(match.group(1), match.group(2), match.group(3)) 64 65LONG_DESC_MATCH = MatchHandler('(LongDesc\()(`[^`]+`)([^\n]\n)', long_string_replace) 66 67EXAMPLE_MATCH = MatchHandler('(Examples\()(`[^`]+`)([^\n]\n)', long_string_replace) 68 69def replace(filename, matchers, multiline_matchers): 70 """Given a file and a set of matchers, run those matchers 71 across the file and replace it with the results. 72 """ 73 # Run all the matchers 74 line_number = 0 75 for line in fileinput.input(filename, inplace=True): 76 line_number += 1 77 matched = False 78 for matcher in matchers: 79 match = matcher.regex.match(line) 80 if match: 81 matcher.replace_fn(match, filename, line_number) 82 matched = True 83 break 84 if not matched: 85 sys.stdout.write(line) 86 sys.stdout.flush() 87 with open(filename, 'r') as datafile: 88 content = datafile.read() 89 for matcher in multiline_matchers: 90 match = matcher.regex.search(content) 91 while match: 92 rep = matcher.replace_fn(match, filename, 0) 93 # Escape back references in the replacement string 94 # (And escape for Python) 95 # (And escape for regex) 96 rep = re.sub('\\\\(\\d)', '\\\\\\\\\\1', rep) 97 content = matcher.regex.sub(rep, content, 1) 98 match = matcher.regex.search(content) 99 sys.stdout.write(content) 100 101 # gofmt the file again 102 from subprocess import call 103 call(["goimports", "-w", filename]) 104 105replace(sys.argv[1], [SHORT_MATCH, IMPORT_MATCH, STRING_FLAG_MATCH], [LONG_DESC_MATCH, EXAMPLE_MATCH]) 106