Skip to content

Commit f116732

Browse files
author
Ron de las Alas
authored
Merge pull request #1964 from tansly/build-python3
Make build.py compatible with Python 2 and 3
2 parents a1ef3d6 + 1a33ef8 commit f116732

7 files changed

+43
-40
lines changed

build.py

+25-19
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,16 @@
3535
# msg/js/<LANG>.js for every language <LANG> defined in msg/js/<LANG>.json.
3636

3737
import sys
38-
if sys.version_info[0] != 2:
39-
raise Exception("Blockly build only compatible with Python 2.x.\n"
40-
"You are using: " + sys.version)
4138

42-
import errno, glob, httplib, json, os, re, subprocess, threading, urllib
39+
import errno, glob, json, os, re, subprocess, threading, codecs, functools
40+
41+
if sys.version_info[0] == 2:
42+
import httplib
43+
from urllib import urlencode
44+
else:
45+
import http.client as httplib
46+
from urllib.parse import urlencode
47+
from importlib import reload
4348

4449
REMOTE_COMPILER = "remote"
4550

@@ -194,7 +199,7 @@ def format_js(self, code):
194199

195200
key_whitelist = self.closure_env.keys()
196201

197-
keys_pipe_separated = reduce(lambda accum, key: accum + "|" + key, key_whitelist)
202+
keys_pipe_separated = functools.reduce(lambda accum, key: accum + "|" + key, key_whitelist)
198203
begin_brace = re.compile(r"\{(?!%s)" % (keys_pipe_separated,))
199204

200205
end_brace = re.compile(r"\}")
@@ -336,7 +341,7 @@ def do_compile_local(self, params, target_filename):
336341
return dict(
337342
compiledCode=stdout,
338343
statistics=dict(
339-
originalSize=reduce(lambda v, size: v + size, filesizes, 0),
344+
originalSize=functools.reduce(lambda v, size: v + size, filesizes, 0),
340345
compressedSize=len(stdout),
341346
)
342347
)
@@ -373,9 +378,10 @@ def do_compile_remote(self, params, target_filename):
373378

374379
headers = {"Content-type": "application/x-www-form-urlencoded"}
375380
conn = httplib.HTTPSConnection("closure-compiler.appspot.com")
376-
conn.request("POST", "/compile", urllib.urlencode(remoteParams), headers)
381+
conn.request("POST", "/compile", urlencode(remoteParams), headers)
377382
response = conn.getresponse()
378-
json_str = response.read()
383+
# Decode is necessary for Python 3.4 compatibility
384+
json_str = response.read().decode("utf-8")
379385
conn.close()
380386

381387
# Parse the JSON response.
@@ -388,12 +394,12 @@ def file_lookup(name):
388394
n = int(name[6:]) - 1
389395
return filenames[n]
390396

391-
if json_data.has_key("serverErrors"):
397+
if "serverErrors" in json_data:
392398
errors = json_data["serverErrors"]
393399
for error in errors:
394400
print("SERVER ERROR: %s" % target_filename)
395401
print(error["error"])
396-
elif json_data.has_key("errors"):
402+
elif "errors" in json_data:
397403
errors = json_data["errors"]
398404
for error in errors:
399405
print("FATAL ERROR")
@@ -405,7 +411,7 @@ def file_lookup(name):
405411
print((" " * error["charno"]) + "^")
406412
sys.exit(1)
407413
else:
408-
if json_data.has_key("warnings"):
414+
if "warnings" in json_data:
409415
warnings = json_data["warnings"]
410416
for warning in warnings:
411417
print("WARNING")
@@ -422,11 +428,11 @@ def file_lookup(name):
422428
return False
423429

424430
def write_output(self, target_filename, remove, json_data):
425-
if not json_data.has_key("compiledCode"):
431+
if "compiledCode" not in json_data:
426432
print("FATAL ERROR: Compiler did not return compiledCode.")
427433
sys.exit(1)
428434

429-
code = HEADER + "\n" + json_data["compiledCode"]
435+
code = HEADER + "\n" + json_data["compiledCode"].decode("utf-8")
430436
code = code.replace(remove, "")
431437

432438
# Trim down Google's (and only Google's) Apache licences.
@@ -500,7 +506,7 @@ def _rebuild(self, srcs, dests):
500506
# If a destination file was missing, rebuild.
501507
return True
502508
else:
503-
print("Error checking file creation times: " + e)
509+
print("Error checking file creation times: " + str(e))
504510

505511
def run(self):
506512
# The files msg/json/{en,qqq,synonyms}.json depend on msg/messages.js.
@@ -573,7 +579,7 @@ def exclude_horizontal(item):
573579
test_args = [closure_compiler, os.path.join("build", "test_input.js")]
574580
test_proc = subprocess.Popen(test_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
575581
(stdout, _) = test_proc.communicate()
576-
assert stdout == read(os.path.join("build", "test_expect.js"))
582+
assert stdout.decode("utf-8") == read(os.path.join("build", "test_expect.js"))
577583

578584
print("Using local compiler: %s ...\n" % CLOSURE_COMPILER_NPM)
579585
except (ImportError, AssertionError):
@@ -602,11 +608,11 @@ def exclude_horizontal(item):
602608
developers.google.com/blockly/guides/modify/web/closure""")
603609
sys.exit(1)
604610

605-
search_paths = calcdeps.ExpandDirectories(
606-
["core", os.path.join(closure_root, closure_library)])
611+
search_paths = list(calcdeps.ExpandDirectories(
612+
["core", os.path.join(closure_root, closure_library)]))
607613

608-
search_paths_horizontal = filter(exclude_vertical, search_paths)
609-
search_paths_vertical = filter(exclude_horizontal, search_paths)
614+
search_paths_horizontal = list(filter(exclude_vertical, search_paths))
615+
search_paths_vertical = list(filter(exclude_horizontal, search_paths))
610616

611617
closure_env = {
612618
"closure_dir": closure_dir,

i18n/common.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def read_json_file(filename):
5959
if '@metadata' in defs:
6060
del defs['@metadata']
6161
return defs
62-
except ValueError, e:
62+
except ValueError as e:
6363
print('Error reading ' + filename)
6464
raise InputError(filename, str(e))
6565

@@ -85,7 +85,7 @@ def _create_qqq_file(output_dir):
8585
"""
8686
qqq_file_name = os.path.join(os.curdir, output_dir, 'qqq.json')
8787
qqq_file = codecs.open(qqq_file_name, 'w', 'utf-8')
88-
print 'Created file: ' + qqq_file_name
88+
print('Created file: ' + qqq_file_name)
8989
qqq_file.write('{\n')
9090
return qqq_file
9191

@@ -126,7 +126,7 @@ def _create_lang_file(author, lang, output_dir):
126126
"""
127127
lang_file_name = os.path.join(os.curdir, output_dir, lang + '.json')
128128
lang_file = codecs.open(lang_file_name, 'w', 'utf-8')
129-
print 'Created file: ' + lang_file_name
129+
print('Created file: ' + lang_file_name)
130130
# string.format doesn't like printing braces, so break up our writes.
131131
lang_file.write('{\n\t"@metadata": {')
132132
lang_file.write("""
@@ -166,7 +166,7 @@ def _create_key_file(output_dir):
166166
key_file_name = os.path.join(os.curdir, output_dir, 'keys.json')
167167
key_file = open(key_file_name, 'w')
168168
key_file.write('{\n')
169-
print 'Created file: ' + key_file_name
169+
print('Created file: ' + key_file_name)
170170
return key_file
171171

172172

i18n/create_messages.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,8 @@
2929

3030

3131
def string_is_ascii(s):
32-
try:
33-
s.decode('ascii')
34-
return True
35-
except UnicodeEncodeError:
36-
return False
32+
# This approach is better for compatibility
33+
return all(ord(c) < 128 for c in s)
3734

3835
def load_constants(filename):
3936
"""Read in constants file, which must be output in every language."""
@@ -81,14 +78,14 @@ def main():
8178
print('ERROR: definition of {0} in {1} contained a newline character.'.
8279
format(key, args.source_lang_file))
8380
sys.exit(1)
84-
sorted_keys = source_defs.keys()
85-
sorted_keys.sort()
81+
sorted_keys = sorted(source_defs.keys())
8682

8783
# Read in synonyms file, which must be output in every language.
8884
synonym_defs = read_json_file(os.path.join(
8985
os.curdir, args.source_synonym_file))
86+
# synonym_defs is also being sorted to ensure the same order is kept
9087
synonym_text = '\n'.join(['Blockly.Msg.{0} = Blockly.Msg.{1};'.format(
91-
key, synonym_defs[key]) for key in synonym_defs])
88+
key, synonym_defs[key]) for key in sorted(synonym_defs)])
9289

9390
# Read in constants file, which must be output in every language.
9491
constants_text = load_constants(os.path.join(os.curdir, args.source_constants_file))

i18n/dedup_json.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ def main():
5151
try:
5252
with codecs.open(filename, 'r', 'utf-8') as infile:
5353
j = json.load(infile)
54-
except ValueError, e:
54+
except ValueError as e:
5555
print('Error reading ' + filename)
56-
raise InputError(file, str(e))
56+
raise InputError(filename, str(e))
5757

5858
# Built up output strings as an array to make output of delimiters easier.
5959
output = []

i18n/json_to_js.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def _process_file(path_to_json, target_lang, key_dict):
100100
if key != '@metadata':
101101
try:
102102
identifier = key_dict[key]
103-
except KeyError, e:
103+
except KeyError as e:
104104
print('Key "%s" is in %s but not in %s' %
105105
(key, keyfile, args.key_file))
106106
raise e

i18n/tests.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def contains_all_chars(orig, result):
3737
u'block of actions.']
3838
for sentence in sentences:
3939
output = common.insert_breaks(sentence, 30, 50)
40-
self.assert_(contains_all_chars(sentence, output),
40+
self.assertTrue(contains_all_chars(sentence, output),
4141
u'Mismatch between:\n{0}\n{1}'.format(
4242
re.sub(spaces, '', sentence),
4343
re.sub(spaces, '', output)))

i18n/xliff_to_json.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def get_value(tag_name):
6565
try:
6666
result['source'] = get_value('source')
6767
result['target'] = get_value('target')
68-
except InputError, e:
68+
except InputError as e:
6969
raise InputError(key, e.msg)
7070

7171
# Get notes, using the from value as key and the data as value.
@@ -112,8 +112,8 @@ def _process_file(filename):
112112
except IOError:
113113
# Don't get caught by below handler
114114
raise
115-
except Exception, e:
116-
print
115+
except Exception as e:
116+
print()
117117
raise InputError(filename, str(e))
118118

119119
# Make sure needed fields are present and non-empty.
@@ -146,8 +146,8 @@ def _process_file(filename):
146146
results.append(unit)
147147

148148
return results
149-
except IOError, e:
150-
print 'Error with file {0}: {1}'.format(filename, e.strerror)
149+
except IOError as e:
150+
print('Error with file {0}: {1}'.format(filename, e.strerror))
151151
sys.exit(1)
152152

153153

0 commit comments

Comments
 (0)