Upgrade scripts to Python 3

Python 2 was [removed from macOS in 12.3][0]. This change:

- Automatically converts many files with [2to3][1]
- Manually updates all [shebangs][2] to use `python3` instead of
  versionless `python` or `python2.7`
- Manually applies a few fixes, many of which were noted by 2to3
- Manually undoes a few fixes that were automatically done by 2to3

[0]: https://www.macrumors.com/2022/01/28/apple-removing-python-2-in-macos-12-3/
[1]: https://docs.python.org/3/library/2to3.html
[2]: https://en.wikipedia.org/wiki/Shebang_(Unix)
This commit is contained in:
Evan Hahn 2022-03-21 12:23:45 -05:00
parent cd97d177d4
commit 1101db6a29
22 changed files with 230 additions and 239 deletions

View File

@ -117,11 +117,11 @@ jobs:
run: git fetch origin --depth 1 ${{ github.base_ref }}
- name: Install Dependencies
run: brew install clang-format
run: brew install clang-format python3
- name: Lint files changed in the PR
run: |
python Scripts/precommit.py --ref origin/${{ github.base_ref }}
python3 Scripts/precommit.py --ref origin/${{ github.base_ref }}
# https://help.github.com/en/actions/reference/development-tools-for-github-actions#logging-commands
git diff --name-only | sed -E 's|(.*)|::error file=\1::Incorrectly formatted (Scripts/precommit.py)|'

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
@ -6,7 +6,6 @@ import sys
import subprocess
import datetime
import argparse
import commands
import re
git_repo_path = os.path.abspath(subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).strip())
@ -80,12 +79,12 @@ def process_if_appropriate(file_path):
continue
if not has_match:
has_match = True
print 'file_path', file_path, 'file_ext', file_ext
print('file_path', file_path, 'file_ext', file_ext)
for match in matches:
# print 'match', match, type(match)
print '\t', 'match:', match.group(0)
print('\t', 'match:', match.group(0))
if has_match:
print
print()
if __name__ == "__main__":

View File

@ -1557,7 +1557,7 @@ class LineParser:
self.lines.reverse()
self.next_line_comments = []
def next(self):
def __next__(self):
# lineParser = LineParser(text.split('\n'))
self.next_line_comments = []
@ -1598,7 +1598,7 @@ def parse_enum(args, proto_file_path, parser, parent_context, enum_name):
allow_alias = False
while True:
try:
line = parser.next()
line = next(parser)
except StopIteration:
raise Exception('Incomplete enum: %s' % proto_file_path)
@ -1650,7 +1650,7 @@ def parse_oneof(args, proto_file_path, parser, parent_context, oneof_name):
while True:
try:
line = parser.next()
line = next(parser)
except StopIteration:
raise Exception('Incomplete oneof: %s' % proto_file_path)
@ -1701,7 +1701,7 @@ def parse_message(args, proto_file_path, parser, parent_context, message_name):
sort_index = 0
while True:
try:
line = parser.next()
line = next(parser)
except StopIteration:
raise Exception('Incomplete message: %s' % proto_file_path)
@ -1864,7 +1864,7 @@ def process_proto_file(args, proto_file_path, dst_file_path):
while True:
try:
line = parser.next()
line = next(parser)
except StopIteration:
break

View File

@ -1,8 +1,7 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import sys
import os
import re
import commands
import subprocess
import argparse
import inspect
@ -13,19 +12,19 @@ def fail(message):
file_name = __file__
current_line_no = inspect.stack()[1][2]
current_function_name = inspect.stack()[1][3]
print 'Failure in:', file_name, current_line_no, current_function_name
print message
print('Failure in:', file_name, current_line_no, current_function_name)
print(message)
sys.exit(1)
def execute_command(command):
try:
print ' '.join(command)
print(' '.join(command))
output = subprocess.check_output(command)
if output:
print output
print(output)
except subprocess.CalledProcessError as e:
print e.output
print(e.output)
sys.exit(1)
@ -229,14 +228,14 @@ def get_versions(plist_file_path):
fail('Could not parse .plist')
release_version_str = release_version_match.group(1)
print 'CFBundleShortVersionString:', release_version_str
print('CFBundleShortVersionString:', release_version_str)
release_version = parse_version_4(release_version_str).asVersion3()
print 'old_release_version:', release_version.formatted()
print('old_release_version:', release_version.formatted())
build_version_1_str = build_version_1_match.group(1)
print 'CFBundleVersion:', build_version_1_str
print('CFBundleVersion:', build_version_1_str)
build_version_1 = parse_version_1(build_version_1_str)
print 'old_build_version_1:', build_version_1.formatted()
print('old_build_version_1:', build_version_1.formatted())
return release_version, build_version_1
@ -261,7 +260,7 @@ def get_tag_variant(args):
elif current_flag in ["production"]:
feature_flag_tag = ""
else:
print "Unrecognized feature flag: " + current_flag
print("Unrecognized feature flag: " + current_flag)
feature_flag_tag = None
@ -278,8 +277,8 @@ def get_tag_variant(args):
argument_tag_string = argument_tag if len(argument_tag) > 0 else "production"
feature_flag_tag_string = feature_flag_tag if len(feature_flag_tag) > 0 else "production"
print "Feature flag mismatch! Arguments specify a " + argument_tag_string + " tag but the current feature flag indicates a " + feature_flag_tag_string + " tag may be more appropriate."
prefer_feature_flag = raw_input("Proceed with a " + feature_flag_tag_string + " instead? (Y/n) ")
print("Feature flag mismatch! Arguments specify a " + argument_tag_string + " tag but the current feature flag indicates a " + feature_flag_tag_string + " tag may be more appropriate.")
prefer_feature_flag = input("Proceed with a " + feature_flag_tag_string + " instead? (Y/n) ")
if len(prefer_feature_flag) == 0 or prefer_feature_flag[0] in "Yy":
return feature_flag_tag
@ -315,11 +314,11 @@ if __name__ == '__main__':
output = subprocess.check_output(['git', 'status', '--porcelain'])
if len(output.strip()) > 0:
print output
print(output)
fail('Git repository has untracked files.')
output = subprocess.check_output(['git', 'diff', '--shortstat'])
if len(output.strip()) > 0:
print output
print(output)
fail('Git repository has untracked files.')
# Ensure .plist is in xml format, not binary.
@ -329,7 +328,7 @@ if __name__ == '__main__':
nse_plist_path,
]
for plist_path in plist_paths:
print 'plist_path:', plist_path
print('plist_path:', plist_path)
output = subprocess.check_output(['plutil', '-convert', 'xml1', plist_path])
# print 'output', output
@ -371,9 +370,9 @@ if __name__ == '__main__':
# new_release_version_3: 5.19.0
# new_build_version_1: 43
# new_build_version_4: 5.19.0.43
print 'new_release_version_3:', new_release_version_3
print 'new_build_version_1:', new_build_version_1
print 'new_build_version_4:', new_build_version_4
print('new_release_version_3:', new_release_version_3)
print('new_build_version_1:', new_build_version_1)
print('new_build_version_4:', new_build_version_4)
for plist_path in plist_paths:
set_versions(plist_path, new_release_version_3, new_build_version_1, new_build_version_4)

View File

@ -1,31 +1,30 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import sys
import os
import re
import commands
import subprocess
import argparse
import inspect
import urllib2
import urllib.request, urllib.error, urllib.parse
import json
def fail(message):
file_name = __file__
current_line_no = inspect.stack()[1][2]
current_function_name = inspect.stack()[1][3]
print 'Failure in:', file_name, current_line_no, current_function_name
print message
print('Failure in:', file_name, current_line_no, current_function_name)
print(message)
sys.exit(1)
def execute_command(command):
try:
print ' '.join(command)
print(' '.join(command))
output = subprocess.check_output(command)
if output:
print output
print(output)
except subprocess.CalledProcessError as e:
print e.output
print(e.output)
sys.exit(1)
def add_field(curl_command, form_key, form_value):
@ -38,7 +37,7 @@ if __name__ == '__main__':
args = parser.parse_args()
params_response = urllib2.urlopen("https://debuglogs.org/").read()
params_response = urllib.request.urlopen("https://debuglogs.org/").read()
params = json.loads(params_response)
@ -49,7 +48,7 @@ if __name__ == '__main__':
upload_key = upload_key + os.path.splitext(args.file)[1]
download_url = 'https://debuglogs.org/' + upload_key
print 'download_url:', download_url
print('download_url:', download_url)
curl_command = ['curl', '-v', '-i', '-X', 'POST']
@ -64,10 +63,10 @@ if __name__ == '__main__':
curl_command.append("file=@%s" % (args.file,))
curl_command.append(upload_url)
print ' '.join(curl_command)
print(' '.join(curl_command))
print 'Running...'
print('Running...')
execute_command(curl_command)
print 'download_url:', download_url
print('download_url:', download_url)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import fileinput
import os

View File

@ -1,13 +1,11 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import sys
import os
import re
import commands
import subprocess
import io
def fail(message):
print message
print(message)
sys.exit(1)
# For simplicity and compactness, we pre-define the
@ -29,7 +27,7 @@ if __name__ == '__main__':
src_filename = "emoji-data.txt"
src_dir_path = os.path.dirname(__file__)
src_file_path = os.path.join(src_dir_path, src_filename)
print 'src_file_path', src_file_path
print('src_file_path', src_file_path)
if not os.path.exists(src_file_path):
fail("Could not find input file")
@ -43,16 +41,16 @@ if __name__ == '__main__':
line = line[:line.index('#')].strip()
if ';' not in line:
continue
print 'line:', line
print('line:', line)
range_text = line[:line.index(';')]
print '\t:', range_text
print('\t:', range_text)
if '..' in range_text:
range_start_hex_string, range_end_hex_string = range_text.split('..')
else:
range_start_hex_string = range_end_hex_string = range_text.strip()
range_start = int(range_start_hex_string.strip(), 16)
range_end = int(range_end_hex_string.strip(), 16)
print '\t', range_start, range_end
print('\t', range_start, range_end)
raw_ranges.append((range_start, range_end,))
@ -70,19 +68,19 @@ if __name__ == '__main__':
if range_start >= last_range_start and range_start <= last_range_end + 1:
# if last_range_end + 1 == range_start:
new_ranges = new_ranges[:-1]
print 'merging', last_range_start, last_range_end, 'and', range_start, range_end
print('merging', last_range_start, last_range_end, 'and', range_start, range_end)
new_ranges.append((last_range_start, max(range_end, last_range_end),))
continue
new_ranges.append((range_start, range_end,))
print
print()
for range_start, range_end in new_ranges:
# print '0x%X...0x%X, // %d Emotions' % (range_start, range_end, (1 + range_end - range_start), )
print 'EmojiRange(rangeStart:0x%X, rangeEnd:0x%X),' % (range_start, range_end, )
print 'new_ranges:', len(new_ranges)
print
print 'Copy and paste the code above into DisplayableText.swift'
print
print('EmojiRange(rangeStart:0x%X, rangeEnd:0x%X),' % (range_start, range_end, ))
print('new_ranges:', len(new_ranges))
print()
print('Copy and paste the code above into DisplayableText.swift')
print()

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import fileinput
import os

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import feature_flags_common
if __name__ == '__main__':

View File

@ -1,8 +1,7 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import sys
import os
import re
import commands
import subprocess
import inspect
@ -10,19 +9,19 @@ def fail(message):
file_name = __file__
current_line_no = inspect.stack()[1][2]
current_function_name = inspect.stack()[1][3]
print 'Failure in:', file_name, current_line_no, current_function_name
print message
print('Failure in:', file_name, current_line_no, current_function_name)
print(message)
sys.exit(1)
def execute_command(command):
try:
print ' '.join(command)
print(' '.join(command))
output = subprocess.check_output(command)
if output:
print output
print(output)
except subprocess.CalledProcessError as e:
print e.output
print(e.output)
sys.exit(1)
def get_feature_flag():
@ -39,11 +38,11 @@ def get_feature_flag():
def set_feature_flags(new_flags_level):
output = subprocess.check_output(['git', 'status', '--porcelain'])
if len(output.strip()) > 0:
print output
print(output)
fail('Git repository has untracked files.')
output = subprocess.check_output(['git', 'diff', '--shortstat'])
if len(output.strip()) > 0:
print output
print(output)
fail('Git repository has untracked files.')
flags_path = 'SignalServiceKit/src/Util/FeatureFlags.swift'
@ -72,4 +71,4 @@ def set_feature_flags(new_flags_level):
cmds = ['git', 'commit', '-m', '"Feature flags for .%s."' % ( new_flags_level, )]
execute_command(cmds)
else:
print "Feature flags already set to %s, nothing to do" % new_flags_level
print("Feature flags already set to %s, nothing to do" % new_flags_level)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import feature_flags_common
if __name__ == '__main__':

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import feature_flags_common
if __name__ == '__main__':

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import feature_flags_common
if __name__ == '__main__':

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
@ -6,10 +6,12 @@ import sys
import subprocess
import datetime
import argparse
import commands
import subprocess
git_repo_path = os.path.abspath(subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).strip())
git_repo_path = os.path.abspath(
subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], text=True).strip()
)
@ -56,7 +58,7 @@ def parse_include(line):
elif not remainder:
return None
else:
print ('Unexpected import or include: '+ line)
print('Unexpected import or include: ' + line)
sys.exit(1)
comment = None
@ -64,7 +66,7 @@ def parse_include(line):
isQuote = True
endIndex = remainder.find('"', 1)
if endIndex < 0:
print ('Unexpected import or include: '+ line)
print('Unexpected import or include: ' + line)
sys.exit(1)
body = remainder[1:endIndex]
comment = remainder[endIndex+1:]
@ -72,12 +74,12 @@ def parse_include(line):
isQuote = False
endIndex = remainder.find('>', 1)
if endIndex < 0:
print ('Unexpected import or include: '+ line)
print('Unexpected import or include: ' + line)
sys.exit(1)
body = remainder[1:endIndex]
comment = remainder[endIndex+1:]
else:
print ('Unexpected import or include: '+ remainder)
print('Unexpected import or include: ' + remainder)
sys.exit(1)
return include(isInclude, isQuote, body, comment)
@ -256,7 +258,7 @@ def sort_matching_blocks(sort_name, filepath, filename, file_extension, text, ma
break
if text != processed:
print sort_name, filepath
print(sort_name, filepath)
return processed
@ -327,7 +329,7 @@ def process(filepath):
filename = os.path.basename(filepath)
if filename.startswith('.'):
raise "shouldn't call process with dotfile"
raise Exception("shouldn't call process with dotfile")
file_ext = os.path.splitext(filename)[1]
if file_ext in ('.swift'):
env_copy = os.environ.copy()
@ -335,14 +337,14 @@ def process(filepath):
env_copy["SCRIPT_INPUT_FILE_0"] = '%s' % ( short_filepath, )
try:
lint_output = subprocess.check_output(['swiftlint', '--fix', '--use-script-input-files'], env=env_copy)
except subprocess.CalledProcessError, e:
except subprocess.CalledProcessError as e:
lint_output = e.output
print lint_output
print(lint_output)
try:
lint_output = subprocess.check_output(['swiftlint', 'lint', '--use-script-input-files'], env=env_copy)
except subprocess.CalledProcessError, e:
except subprocess.CalledProcessError as e:
lint_output = e.output
print lint_output
print(lint_output)
with open(filepath, 'rt') as f:
text = f.read()
@ -377,7 +379,7 @@ def process(filepath):
if original_text == text:
return
print 'Updating:', short_filepath
print('Updating:', short_filepath)
with open(filepath, 'wt') as f:
f.write(text)
@ -439,7 +441,7 @@ def check_diff_for_keywords():
command_line = 'git diff --staged | grep --color=always -C 3 -E "%s"' % matching_expression
try:
output = subprocess.check_output(command_line, shell=True)
except subprocess.CalledProcessError, e:
except subprocess.CalledProcessError as e:
# > man grep
# EXIT STATUS
# The grep utility exits with one of the following values:
@ -480,7 +482,7 @@ if __name__ == "__main__":
elif args.ref:
filepaths = []
output = commands.getoutput('git diff --name-only --diff-filter=ACMR %s HEAD' % args.ref)
output = subprocess.getoutput('git diff --name-only --diff-filter=ACMR %s HEAD' % args.ref)
filepaths.extend([line.strip() for line in output.split('\n')])
# Only process each path once.
@ -496,11 +498,11 @@ if __name__ == "__main__":
filepaths = []
# Staging
output = commands.getoutput('git diff --cached --name-only --diff-filter=ACMR')
output = subprocess.getoutput('git diff --cached --name-only --diff-filter=ACMR')
filepaths.extend([line.strip() for line in output.split('\n')])
# Working
output = commands.getoutput('git diff --name-only --diff-filter=ACMR')
output = subprocess.getoutput('git diff --name-only --diff-filter=ACMR')
filepaths.extend([line.strip() for line in output.split('\n')])
# Only process each path once.
@ -510,8 +512,8 @@ if __name__ == "__main__":
filepath = os.path.abspath(os.path.join(git_repo_path, filepath))
process_if_appropriate(filepath)
print 'git clang-format...'
print('git clang-format...')
# we don't want to format .proto files, so we specify every other supported extension
print commands.getoutput('git clang-format --extensions "c,h,m,mm,cc,cp,cpp,c++,cxx,hh,hxx,cu,java,js,ts,cs" --commit %s' % clang_format_commit)
print(subprocess.getoutput('git clang-format --extensions "c,h,m,mm,cc,cp,cpp,c++,cxx,hh,hxx,cu,java,js,ts,cs" --commit %s' % clang_format_commit))
check_diff_for_keywords()

View File

@ -1,4 +1,4 @@
#!/usr/bin/python2.7
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# When we make a hotfix, we need to reverse integrate our hotfix back into

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
@ -12,7 +12,7 @@ def fail(*args):
git_repo_path = os.path.abspath(subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).strip())
print 'git_repo_path:', git_repo_path
print('git_repo_path:', git_repo_path)
def sds_to_relative_path(path):
path = os.path.abspath(path)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
@ -6,7 +6,6 @@ import sys
import subprocess
import datetime
import argparse
import commands
import re
import json
import sds_common
@ -92,7 +91,7 @@ class ParsedClass:
# TODO: We should handle all properties?
if property.should_ignore_property():
print 'Ignoring property:', property.name
print('Ignoring property:', property.name)
continue
self.property_map[property.name] = property
@ -127,13 +126,13 @@ class ParsedClass:
if duplicate_property is not None:
# print '\t', 'duplicate', property.name
if property.swift_type_safe() != duplicate_property.swift_type_safe():
print 'property:', property.class_name, property.name, property.swift_type_safe(), property.is_optional
print 'duplicate_property:', duplicate_property.class_name, duplicate_property.name, duplicate_property.swift_type_safe(), duplicate_property.is_optional
print('property:', property.class_name, property.name, property.swift_type_safe(), property.is_optional)
print('duplicate_property:', duplicate_property.class_name, duplicate_property.name, duplicate_property.swift_type_safe(), duplicate_property.is_optional)
fail("Duplicate property doesn't match:", property.name)
elif property.is_optional != duplicate_property.is_optional:
if property.name in root_property_names:
print 'property:', property.class_name, property.name, property.swift_type_safe(), property.is_optional
print 'duplicate_property:', duplicate_property.class_name, duplicate_property.name, duplicate_property.swift_type_safe(), duplicate_property.is_optional
print('property:', property.class_name, property.name, property.swift_type_safe(), property.is_optional)
print('duplicate_property:', duplicate_property.class_name, duplicate_property.name, duplicate_property.swift_type_safe(), duplicate_property.is_optional)
fail("Duplicate property doesn't match:", property.name)
# If one subclass property is optional and the other isn't, we should
@ -205,23 +204,23 @@ class ParsedClass:
def should_generate_extensions(self):
if self.name in (OLD_BASE_MODEL_CLASS_NAME, NEW_BASE_MODEL_CLASS_NAME, ):
print 'Ignoring class (1):', self.name
print('Ignoring class (1):', self.name)
return False
if should_ignore_class(self):
print 'Ignoring class (2):', self.name
print('Ignoring class (2):', self.name)
return False
if not self.is_sds_model():
# Only write serialization extensions for SDS models.
print 'Ignoring class (3):', self.name
print('Ignoring class (3):', self.name)
return False
# The migration should not be persisted in the data store.
if self.name in ('OWSDatabaseMigration', 'YDBDatabaseMigration', 'OWSResaveCollectionDBMigration', ):
print 'Ignoring class (4):', self.name
print('Ignoring class (4):', self.name)
return False
if self.super_class_name in ('OWSDatabaseMigration', 'YDBDatabaseMigration', 'OWSResaveCollectionDBMigration', ):
print 'Ignoring class (5):', self.name
print('Ignoring class (5):', self.name)
return False
return True
@ -880,26 +879,26 @@ def properties_and_inherited_properties(clazz):
def generate_swift_extensions_for_model(clazz):
print '\t', 'processing', clazz.__dict__
print('\t', 'processing', clazz.__dict__)
if not clazz.should_generate_extensions():
return
has_sds_superclass = clazz.has_sds_superclass()
print '\t', '\t', 'clazz.name', clazz.name, type(clazz.name)
print '\t', '\t', 'clazz.super_class_name', clazz.super_class_name
print '\t', '\t', 'filepath', clazz.filepath
print '\t', '\t', 'table_superclass', clazz.table_superclass().name
print '\t', '\t', 'has_sds_superclass', has_sds_superclass
print('\t', '\t', 'clazz.name', clazz.name, type(clazz.name))
print('\t', '\t', 'clazz.super_class_name', clazz.super_class_name)
print('\t', '\t', 'filepath', clazz.filepath)
print('\t', '\t', 'table_superclass', clazz.table_superclass().name)
print('\t', '\t', 'has_sds_superclass', has_sds_superclass)
swift_filename = os.path.basename(clazz.filepath)
swift_filename = swift_filename[:swift_filename.find('.')] + '+SDS.swift'
swift_filepath = os.path.join(os.path.dirname(clazz.filepath), swift_filename)
print '\t', '\t', 'swift_filepath', swift_filepath
print('\t', '\t', 'swift_filepath', swift_filepath)
record_type = get_record_type(clazz)
print '\t', '\t', 'record_type', record_type
print('\t', '\t', 'record_type', record_type)
# TODO: We'll need to import SignalServiceKit for non-SSK models.
@ -2012,7 +2011,7 @@ public extension %(model_name)s {
# print 'swift_body', swift_body
print 'Writing:', swift_filepath
print('Writing:', swift_filepath)
swift_body = sds_common.clean_up_generated_swift(swift_body)
@ -2023,7 +2022,7 @@ public extension %(model_name)s {
def process_class_map(class_map):
print 'processing', class_map
print('processing', class_map)
for clazz in class_map.values():
generate_swift_extensions_for_model(clazz)
@ -2035,7 +2034,7 @@ record_type_map = {}
# It's critical that our "record type" values are consistent, even if we add/remove/rename model classes.
# Therefore we persist the mapping of known classes in a JSON file that is under source control.
def update_record_type_map(record_type_swift_path, record_type_json_path):
print 'update_record_type_map'
print('update_record_type_map')
record_type_map_filepath = record_type_json_path
@ -2147,7 +2146,7 @@ enum_type_map = {}
def objc_type_for_enum(enum_name):
if enum_name not in enum_type_map:
print 'enum_type_map', enum_type_map
print('enum_type_map', enum_type_map)
fail('Enum has unknown type:', enum_name)
enum_type = enum_type_map[enum_name]
return enum_type
@ -2200,14 +2199,14 @@ def try_to_parse_file(file_path):
_, file_extension = os.path.splitext(filename)
if filename.endswith(sds_common.SDS_JSON_FILE_EXTENSION):
# print 'filename:', filename
print '\t', 'found', file_path
print('\t', 'found', file_path)
return parse_sds_json(file_path)
else:
return {}
def find_sds_intermediary_files_in_path(path):
print 'find_sds_intermediary_files_in_path', path
print('find_sds_intermediary_files_in_path', path)
class_map = {}
if os.path.isfile(path):
class_map.update(try_to_parse_file(path))
@ -2250,7 +2249,7 @@ def is_swift_class_name(swift_type):
configuration_json = {}
def parse_config_json(config_json_path):
print 'config_json_path', config_json_path
print('config_json_path', config_json_path)
with open(config_json_path, 'rt') as f:
json_str = f.read()
@ -2266,12 +2265,12 @@ def parse_config_json(config_json_path):
def swift_type_for_nsnumber(property):
nsnumber_types = configuration_json.get('nsnumber_types')
if nsnumber_types is None:
print 'Suggestion: update: %s' % ( str(global_args.config_json_path), )
print('Suggestion: update: %s' % ( str(global_args.config_json_path), ))
fail('Configuration JSON is missing mapping for properties of type NSNumber.')
key = property.class_name + '.' + property.name
swift_type = nsnumber_types.get(key)
if swift_type is None:
print 'Suggestion: update: %s' % ( str(global_args.config_json_path), )
print('Suggestion: update: %s' % ( str(global_args.config_json_path), ))
fail('Configuration JSON is missing mapping for properties of type NSNumber:', key)
return swift_type
@ -2358,7 +2357,7 @@ def was_property_renamed_for_property(property):
property_order_json = {}
def parse_property_order_json(property_order_json_path):
print 'property_order_json_path', property_order_json_path
print('property_order_json_path', property_order_json_path)
with open(property_order_json_path, 'rt') as f:
json_str = f.read()
@ -2410,12 +2409,12 @@ if __name__ == "__main__":
property_order_json_path = os.path.abspath(args.property_order_json_path)
# We control the code generation process using a JSON config file.
print
print 'Parsing Config'
print()
print('Parsing Config')
parse_config_json(config_json_path)
print
print 'Parsing Config'
print()
print('Parsing Config')
parse_property_order_json(property_order_json_path)
# The code generation needs to understand the class hierarchy so that
@ -2425,19 +2424,19 @@ if __name__ == "__main__":
# the model class hierarchies.
# * Generate deserialization methods that handle all subclasses.
# * etc.
print
print 'Parsing Global Class Map'
print()
print('Parsing Global Class Map')
global_class_map.update(find_sds_intermediary_files_in_path(search_path))
print 'global_class_map', global_class_map
print('global_class_map', global_class_map)
update_subclass_map()
print
print 'Parsing Record Type Map'
print()
print('Parsing Record Type Map')
update_record_type_map(record_type_swift_path, record_type_json_path)
print
print 'Processing'
print()
print('Processing')
process_class_map(find_sds_intermediary_files_in_path(src_path))
# Persist updated property order

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
@ -6,7 +6,6 @@ import sys
import subprocess
import datetime
import argparse
import commands
import re
import json
import sds_common
@ -115,8 +114,8 @@ class ParsedClass:
if protocol_name.startswith('NS') or protocol_name.startswith('AV') or protocol_name.startswith('UI') or protocol_name.startswith('MF') or protocol_name.startswith('UN') or protocol_name.startswith('CN'):
# Ignore built in protocols.
continue
print 'clazz:', self.name
print 'file_path:', file_path
print('clazz:', self.name)
print('file_path:', file_path)
fail('Missing protocol:', protocol_name)
result.append(protocol)
@ -169,12 +168,12 @@ def split_objc_ast_prefix(line):
def process_objc_ast(namespace, file_path, raw_ast):
m_filename = os.path.basename(file_path)
print 'm_filename:', m_filename
print('m_filename:', m_filename)
file_base, file_extension = os.path.splitext(m_filename)
if file_extension != '.m':
fail('Bad file extension:', file_extension)
h_filename = file_base + '.h'
print 'h_filename:', h_filename
print('h_filename:', h_filename)
# TODO: Remove
lines = raw_ast.split('\n')
@ -227,12 +226,12 @@ process_objc_enum_declaration_regex = re.compile(r"^.+? ([^ ]+) '([^']+)':'([^']
enum_type_map = {}
def process_objc_enum_declaration(namespace, file_path, lines, prefix, remainder):
print '\t', 'enum_declaration', remainder
print('\t', 'enum_declaration', remainder)
match = process_objc_enum_declaration_regex.search(remainder)
if match is None:
print 'file_path:', file_path
print 'Could not match line:', remainder
print('file_path:', file_path)
print('Could not match line:', remainder)
return
type1 = get_match_group(match, 1)
type2 = get_match_group(match, 2)
@ -241,23 +240,23 @@ def process_objc_enum_declaration(namespace, file_path, lines, prefix, remainder
# print 'enum?', type1, type2, type3
if type1.startswith('line:'):
print 'Ignoring invalid enum(1):', type1, type2, type3
print('Ignoring invalid enum(1):', type1, type2, type3)
return
if type1 in enum_type_map:
return
enum_type_map[type1] = type2
print 'enum_type_map', enum_type_map
print('enum_type_map', enum_type_map)
# |-TypedefDecl 0x7f8d8fb44748 <line:12:1, line:22:3> col:3 referenced RPRecentCallType 'enum RPRecentCallType':'RPRecentCallType'
process_objc_type_declaration_regex = re.compile(r"^.+?'([^']+)'(:'([^']+)')?$")
def process_objc_type_declaration(namespace, file_path, lines, prefix, remainder):
print '\t', 'type_declaration', remainder
print('\t', 'type_declaration', remainder)
match = process_objc_type_declaration_regex.search(remainder)
if match is None:
print 'file_path:', file_path
print('file_path:', file_path)
fail('Could not match line:', remainder)
type1 = get_match_group(match, 1)
type2 = get_match_group(match, 2)
@ -272,10 +271,10 @@ def process_objc_type_declaration(namespace, file_path, lines, prefix, remainder
# print 'type_declaration:', type1, type2, type3
if type3.startswith('line:'):
print 'Ignoring invalid enum(2):', type1, type2, type3
print('Ignoring invalid enum(2):', type1, type2, type3)
return
if type3 not in enum_type_map:
print 'Enum has unknown type:', type3
print('Enum has unknown type:', type3)
enum_type = 'NSUInteger'
else:
enum_type = enum_type_map[type3]
@ -298,7 +297,7 @@ def process_objc_interface(namespace, file_path, lines, decl_prefix, decl_remain
super_class_name = None
if lines.hasNext():
line = lines.next()
line = next(lines)
prefix, remainder = split_objc_ast_prefix(line)
if len(prefix) > len(decl_prefix):
splits = remainder.split(' ')
@ -325,7 +324,7 @@ def process_objc_category(namespace, file_path, lines, decl_prefix, decl_remaind
# | `-ObjCMethodDecl 0x1092f8580 <col:53> col:53 implicit - fakeProperty2 'NSString * _Nullable':'NSString *'
if not lines.hasNext():
fail('Category missing interface.')
line = lines.next()
line = next(lines)
prefix, remainder = split_objc_ast_prefix(line)
if len(prefix) <= len(decl_prefix):
fail('Category missing interface.')
@ -346,7 +345,7 @@ def process_objc_implementation(namespace, file_path, lines, decl_prefix, decl_r
clazz.is_implemented = True
def process_objc_protocol_decl(namespace, file_path, lines, decl_prefix, decl_remainder):
print '\t', 'protocol decl', decl_remainder
print('\t', 'protocol decl', decl_remainder)
clazz = process_objc_class(namespace, file_path, lines, decl_prefix, decl_remainder)
if clazz is not None:
clazz.is_implemented = True
@ -371,7 +370,7 @@ def process_objc_class(namespace, file_path, lines, decl_prefix, decl_remainder,
fail("super_class_name does not match:", clazz.super_class_name, super_class_name)
while lines.hasNext():
line = lines.next()
line = next(lines)
prefix, remainder = split_objc_ast_prefix(line)
if len(prefix) <= len(decl_prefix):
# Declaration is over.
@ -459,7 +458,7 @@ def process_objc_property_impl(clazz, prefix, file_path, line, remainder):
match = process_objc_property_impl_regex.search(remainder)
if match is None:
print 'file_path:', file_path
print('file_path:', file_path)
fail('Could not match line:', line)
property_name = match.group(1).strip()
property = clazz.get_property(property_name)
@ -471,15 +470,15 @@ def process_objc_property_impl(clazz, prefix, file_path, line, remainder):
# to handle them.
return
print 'file_path:', file_path
print 'line:', line
print '\t', 'clazz', clazz.name, clazz.counter
print '\t', 'property_name', property_name
print('file_path:', file_path)
print('line:', line)
print('\t', 'clazz', clazz.name, clazz.counter)
print('\t', 'property_name', property_name)
for name in clazz.property_names():
print '\t\t', name
print('\t\t', name)
fail("Can't find property:", property_name)
else:
print 'property synthesized', line
print('property synthesized', line)
property.is_synthesized = True
@ -505,8 +504,8 @@ def process_objc_property(clazz, prefix, file_path, line, remainder):
match = process_objc_property_regex.search(remainder)
if match is None:
print 'file_path:', file_path
print 'remainder:', remainder
print('file_path:', file_path)
print('remainder:', remainder)
fail('Could not match line:', line)
property_name = match.group(1).strip()
property_type_1 = get_match_group(match, 2)
@ -531,7 +530,7 @@ def process_objc_property(clazz, prefix, file_path, line, remainder):
property_type = property_type_1
# property_type = property_type_1
print '\t', property_name, 'property_type', property_type, 'property_type1', property_type_1, 'property_type2', property_type_2, 'property_type', property_type
print('\t', property_name, 'property_type', property_type, 'property_type1', property_type_1, 'property_type2', property_type_2, 'property_type', property_type)
property = clazz.get_property(property_name)
if property is None:
@ -547,8 +546,8 @@ def process_objc_property(clazz, prefix, file_path, line, remainder):
# CocoaLumberjack has nullability consistency issues.
# Ignore them.
return
print 'file_path:', file_path
print 'clazz:', clazz.name
print('file_path:', file_path)
print('clazz:', clazz.name)
fail("Property is_optional don't match", property_name)
if property.objc_type != property_type:
# There's a common pattern of using a mutable private property
@ -557,11 +556,11 @@ def process_objc_property(clazz, prefix, file_path, line, remainder):
if property_type.startswith('NSMutable') and property.objc_type == 'NS' + property_type[len('NSMutable'):]:
property.objc_type = property_type
else:
print 'file_path:', file_path
print 'remainder:', remainder
print 'property.objc_type:', property.objc_type
print 'property_type:', property_type
print 'property_name:', property_name
print('file_path:', file_path)
print('remainder:', remainder)
print('property.objc_type:', property.objc_type)
print('property_type:', property_type)
print('property_name:', property_name)
fail("Property types don't match", property.objc_type, property_type)
@ -583,7 +582,7 @@ def emit_output(file_path, namespace):
for property in clazz.all_properties():
if not property.is_synthesized:
print '\t', 'Ignoring property:', property.name
print('\t', 'Ignoring property:', property.name)
continue
property_dict = {
@ -633,7 +632,7 @@ def find_header_include_paths(include_path):
if has_header:
result.append('-I' + dir_path)
else:
print 'Ignoring:', dir_path
print('Ignoring:', dir_path)
# Add root if necessary.
add_dir_if_has_header(include_path)
@ -708,15 +707,15 @@ def gather_module_headers(pods_dir_path):
def get_pch_include(file_path):
print 'file_path', file_path
print('file_path', file_path)
ssk_path = os.path.join(git_repo_path, 'SignalServiceKit') + os.sep
sm_path = os.path.join(git_repo_path, 'SignalMessaging') + os.sep
s_path = os.path.join(git_repo_path, 'Signal') + os.sep
sae_path = os.path.join(git_repo_path, 'SignalShareExtension') + os.sep
print 'ssk_path', ssk_path
print 'sm_path', sm_path
print 's_path', s_path
print 'sae_path', sae_path
print('ssk_path', ssk_path)
print('sm_path', sm_path)
print('s_path', s_path)
print('sae_path', sae_path)
if file_path.startswith(ssk_path):
return os.path.join(git_repo_path, "Pods/Target Support Files/SignalServiceKit/SignalServiceKit-prefix.pch")
elif file_path.startswith(sm_path):
@ -778,16 +777,16 @@ def process_objc(file_path, swift_bridging_path, intermediates):
# 'test4.txt'
]
for part in command:
print '\t', part
print('\t', part)
# command = ' '.join(command).strip()
# print 'command', command
# output = commands.getoutput(command)
# command = ' '.join(command).strip()
print 'command', command
print('command', command)
exit_code, output, error_output = ows_getoutput(command)
print 'exit_code:', exit_code
print 'error_output:', error_output
print('exit_code:', exit_code)
print('error_output:', error_output)
# print 'output:', len(output)
# exit(1)
@ -797,10 +796,10 @@ def process_objc(file_path, swift_bridging_path, intermediates):
if intermediates:
intermediate_file_path = file_path + '.ast'
print 'Writing intermediate:', intermediate_file_path
print('Writing intermediate:', intermediate_file_path)
with open(intermediate_file_path, 'wt') as f:
f.write(raw_ast)
print 'raw_ast:', len(raw_ast)
print('raw_ast:', len(raw_ast))
namespace = Namespace()
@ -808,10 +807,10 @@ def process_objc(file_path, swift_bridging_path, intermediates):
output = emit_output(file_path, namespace)
print 'output', output
print('output', output)
parsed_file_path = file_path + sds_common.SDS_JSON_FILE_EXTENSION
print 'parsed_file_path', parsed_file_path
print('parsed_file_path', parsed_file_path)
with open(parsed_file_path, 'wt') as f:
f.write(output)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
@ -6,7 +6,6 @@ import sys
import subprocess
import datetime
import argparse
import commands
import re
import json
import sds_common
@ -97,7 +96,7 @@ def process_file(file_path, namespace, intermediates):
if exit_code != 0:
fail('Missing sourcekitten. Install with homebrew?')
print 'Extracting Swift Bridging Info For:', file_path
print('Extracting Swift Bridging Info For:', file_path)
command = [
'sourcekitten',
'structure',
@ -114,9 +113,9 @@ def process_file(file_path, namespace, intermediates):
# print 'command', command
exit_code, output, error_output = ows_getoutput(command)
if exit_code != 0:
print 'exit_code:', exit_code
print('exit_code:', exit_code)
if len(error_output.strip()) > 0:
print 'error_output:', error_output
print('error_output:', error_output)
# print 'output:', len(output)
# exit(1)
@ -127,7 +126,7 @@ def process_file(file_path, namespace, intermediates):
if intermediates:
intermediate_file_path = file_path + '.ast'
print 'Writing intermediate:', intermediate_file_path
print('Writing intermediate:', intermediate_file_path)
with open(intermediate_file_path, 'wt') as f:
f.write(output)
@ -181,7 +180,7 @@ def generate_swift_bridging_header(namespace, swift_bridging_path):
if not os.path.exists(parent_dir_path):
os.makedirs(parent_dir_path)
print 'Writing:', swift_bridging_path
print('Writing:', swift_bridging_path)
with open(swift_bridging_path, 'wt') as f:
f.write(output)
@ -193,7 +192,7 @@ def process_dir(src_dir_path, dir_name, dst_dir_path):
dir_path = os.path.abspath(os.path.join(src_dir_path, dir_name))
print 'Searching:', dir_path
print('Searching:', dir_path)
for rootdir, dirnames, filenames in os.walk(dir_path):
for filename in filenames:

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
@ -6,7 +6,6 @@ import sys
import subprocess
import datetime
import argparse
import commands
import re
import json
import sds_common
@ -28,7 +27,7 @@ def ows_getoutput(cmd):
def process_file(file_path):
print 'Scanning:', file_path
print('Scanning:', file_path)
with open(file_path, 'rt') as f:
src_text = f.read()
@ -46,7 +45,7 @@ def process_file(file_path):
# Ignore this framework.
continue
print '\t', 'Fixing:', import_name
print('\t', 'Fixing:', import_name)
new_import = '#import <%s/%s.h>' % ( import_name, import_name, )
text = text[:match.start(1)] + new_import + text[match.end(1):]

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
"""
This script can be used to grep the source to tree to see which localized strings are in use.
@ -41,5 +41,5 @@ if __name__ == '__main__':
for item in open(strings_file).readlines():
grep_for = item.strip().split(' = ')[0].replace('"','')
if rgrep_match(src_dir_name, grep_for):
print item.strip()
print(item.strip())

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
@ -6,7 +6,6 @@ import sys
import subprocess
import datetime
import argparse
import commands
import re
@ -110,7 +109,7 @@ def process(filepath, c_macros, swift_macros):
position = best_match.end(1)
if not has_printed_filename:
has_printed_filename = True
print short_filepath
print(short_filepath)
raw_event_name = best_match.group(1).strip()
if is_swift:
@ -124,10 +123,10 @@ def process(filepath, c_macros, swift_macros):
if match:
event_name = match.group(1).strip()
else:
print '\t', 'Ignoring event: _%s_' % raw_event_name
print('\t', 'Ignoring event: _%s_' % raw_event_name)
continue
event_names.append(event_name)
print '\t', 'event_name', event_name
print('\t', 'event_name', event_name)
if is_swift:
before = '"%s"' % event_name
@ -150,7 +149,7 @@ def process(filepath, c_macros, swift_macros):
# if original_text == text:
# return
print 'Updating:', short_filepath
print('Updating:', short_filepath)
with open(filepath, 'wt') as f:
f.write(text)
@ -229,17 +228,17 @@ def update_event_names(header_file_path, source_file_path):
code_generation_start = text.find(code_generation_marker)
code_generation_end = text.rfind(code_generation_marker)
if code_generation_start < 0:
print 'Could not find marker in file:', file
print('Could not find marker in file:', file)
sys.exit(1)
if code_generation_end < 0 or code_generation_end == code_generation_start:
print 'Could not find marker in file:', file
print('Could not find marker in file:', file)
sys.exit(1)
event_name_map = {}
print
print 'Parsing old generated code'
print
print()
print('Parsing old generated code')
print()
old_generated = text[code_generation_start + len(code_generation_marker):code_generation_end]
# print 'old_generated', old_generated
@ -259,31 +258,31 @@ def update_event_names(header_file_path, source_file_path):
matcher = re.compile(pattern)
match = matcher.search(split)
if not match:
print 'Could not parse:', split
print 'In file:', filepath
print('Could not parse:', split)
print('In file:', filepath)
sys.exit(1)
method_name = match.group(1).strip()
print 'method_name:', method_name
print('method_name:', method_name)
pattern = r'return @"(.+)";'
matcher = re.compile(pattern)
match = matcher.search(split)
if not match:
print 'Could not parse:', split
print 'In file:', filepath
print('Could not parse:', split)
print('In file:', filepath)
sys.exit(1)
event_name = match.group(1).strip()
print 'event_name:', event_name
print('event_name:', event_name)
event_name_map[event_name] = method_name
print
print()
all_event_names = sorted(set(event_name_map.keys() + event_names))
print 'all_event_names', all_event_names
all_event_names = sorted(set(list(event_name_map.keys()) + event_names))
print('all_event_names', all_event_names)
generated = code_generation_marker
for event_name in all_event_names:
@ -299,9 +298,9 @@ def update_event_names(header_file_path, source_file_path):
}''' % (objc_name, event_name)
generated = generated + '\n\n' + text_for_event
generated = generated + '\n\n' + code_generation_marker
print 'generated', generated
print('generated', generated)
new_text = text[:code_generation_start] + generated + text[code_generation_end + len(code_generation_marker):]
print 'text', new_text
print('text', new_text)
with open(filepath, 'wt') as f:
f.write(new_text)
@ -314,10 +313,10 @@ def update_event_names(header_file_path, source_file_path):
code_generation_start = text.find(code_generation_marker)
code_generation_end = text.rfind(code_generation_marker)
if code_generation_start < 0:
print 'Could not find marker in file:', file
print('Could not find marker in file:', file)
sys.exit(1)
if code_generation_end < 0 or code_generation_end == code_generation_start:
print 'Could not find marker in file:', file
print('Could not find marker in file:', file)
sys.exit(1)
generated = code_generation_marker
@ -328,9 +327,9 @@ def update_event_names(header_file_path, source_file_path):
text_for_event = '+ (NSString *)%s;' % (objc_name,)
generated = generated + '\n\n' + text_for_event
generated = generated + '\n\n' + code_generation_marker
print 'generated', generated
print('generated', generated)
new_text = text[:code_generation_start] + generated + text[code_generation_end + len(code_generation_marker):]
print 'text', new_text
print('text', new_text)
with open(filepath, 'wt') as f:
f.write(new_text)
@ -341,26 +340,26 @@ if __name__ == "__main__":
macros_header_file_path = os.path.join(git_repo_path, 'SignalServiceKit', 'src', 'Util', 'OWSAnalytics.h')
if not os.path.exists(macros_header_file_path):
print 'Macros header does not exist:', macros_header_file_path
print('Macros header does not exist:', macros_header_file_path)
sys.exit(1)
c_macros = extract_macros(macros_header_file_path)
print 'c_macros:', c_macros
print('c_macros:', c_macros)
macros_header_file_path = os.path.join(git_repo_path, 'Signal', 'src', 'util', 'OWSAnalytics.swift')
if not os.path.exists(macros_header_file_path):
print 'Macros header does not exist:', macros_header_file_path
print('Macros header does not exist:', macros_header_file_path)
sys.exit(1)
swift_macros = extract_macros(macros_header_file_path)
print 'swift_macros:', swift_macros
print('swift_macros:', swift_macros)
event_names_header_file_path = os.path.join(git_repo_path, 'SignalServiceKit', 'src', 'Util', 'OWSAnalyticsEvents.h')
if not os.path.exists(event_names_header_file_path):
print 'event_names_header_file_path does not exist:', event_names_header_file_path
print('event_names_header_file_path does not exist:', event_names_header_file_path)
sys.exit(1)
event_names_source_file_path = os.path.join(git_repo_path, 'SignalServiceKit', 'src', 'Util', 'OWSAnalyticsEvents.m')
if not os.path.exists(event_names_source_file_path):
print 'event_names_source_file_path does not exist:', event_names_source_file_path
print('event_names_source_file_path does not exist:', event_names_source_file_path)
sys.exit(1)
for rootdir, dirnames, filenames in os.walk(git_repo_path):
@ -368,6 +367,6 @@ if __name__ == "__main__":
file_path = os.path.abspath(os.path.join(rootdir, filename))
process_if_appropriate(file_path, c_macros, swift_macros)
print
print 'event_names', sorted(set(event_names))
print()
print('event_names', sorted(set(event_names)))
update_event_names(event_names_header_file_path, event_names_source_file_path)