Simplify PRESUBMIT.py and check_package_boundaries.py

Bug: webrtc:6954
Change-Id: Ia93eb8cc8a13bdcba5217fd8d52b72defa108b2f
Reviewed-on: https://webrtc-review.googlesource.com/6021
Commit-Queue: Oleh Prypin <oprypin@webrtc.org>
Reviewed-by: Henrik Kjellander <kjellander@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20158}
This commit is contained in:
Oleh Prypin
2017-10-04 20:17:54 +02:00
committed by Commit Bot
parent 1af3d82b10
commit 2f33a5671e
7 changed files with 96 additions and 127 deletions

View File

@ -9,15 +9,12 @@
# be found in the AUTHORS file in the root of the source tree.
import argparse
import logging
import collections
import os
import re
import sys
DISPLAY_LEVEL = 1
IGNORE_LEVEL = 0
# TARGET_RE matches a GN target, and extracts the target name and the contents.
TARGET_RE = re.compile(r'\d+\$(?P<indent>\s*)\w+\("(?P<target_name>\w+)"\) {'
r'(?P<target_contents>.*?)'
@ -28,27 +25,16 @@ TARGET_RE = re.compile(r'\d+\$(?P<indent>\s*)\w+\("(?P<target_name>\w+)"\) {'
SOURCES_RE = re.compile(r'sources \+?= \[(?P<sources>.*?)\]',
re.MULTILINE | re.DOTALL)
LOG_FORMAT = '%(message)s'
ERROR_MESSAGE = ("{}:{} in target '{}':\n"
" Source file '{}'\n"
" crosses boundary of package '{}'.\n")
ERROR_MESSAGE = ("{build_file_path}:{line_number} in target '{target_name}':\n"
" Source file '{source_file}'\n"
" crosses boundary of package '{subpackage}'.")
class Logger(object):
def __init__(self, messages_left=None):
self.log_level = DISPLAY_LEVEL
self.messages_left = messages_left
def Log(self, build_file_path, line_number, target_name, source_file,
subpackage):
if self.messages_left is not None:
if not self.messages_left:
self.log_level = IGNORE_LEVEL
else:
self.messages_left -= 1
message = ERROR_MESSAGE.format(build_file_path, line_number, target_name,
source_file, subpackage)
logging.log(self.log_level, message)
class PackageBoundaryViolation(
collections.namedtuple('PackageBoundaryViolation',
'build_file_path line_number target_name source_file subpackage')):
def __str__(self):
return ERROR_MESSAGE.format(**self._asdict())
def _BuildSubpackagesPattern(packages, query):
@ -70,12 +56,11 @@ def _ReadFileAndPrependLines(file_path):
for line_number, line in enumerate(f, 1))
def _CheckBuildFile(build_file_path, packages, logger):
"""Iterates oven all the targets of the given BUILD.gn file, and verifies that
def _CheckBuildFile(build_file_path, packages):
"""Iterates over all the targets of the given BUILD.gn file, and verifies that
the source files referenced by it don't belong to any of it's subpackages.
Returns True if a package boundary violation was found.
Returns an iterator over PackageBoundaryViolations for this package.
"""
found_violations = False
package = os.path.dirname(build_file_path)
subpackages_re = _BuildSubpackagesPattern(packages, package)
@ -90,14 +75,11 @@ def _CheckBuildFile(build_file_path, packages, logger):
source_file = subpackages_match.group('source_file')
line_number = subpackages_match.group('line_number')
if subpackage:
found_violations = True
logger.Log(build_file_path, line_number, target_name, source_file,
subpackage)
return found_violations
yield PackageBoundaryViolation(build_file_path, line_number,
target_name, source_file, subpackage)
def CheckPackageBoundaries(root_dir, logger, build_files=None):
def CheckPackageBoundaries(root_dir, build_files=None):
packages = [root for root, _, files in os.walk(root_dir)
if 'BUILD.gn' in files]
@ -107,11 +89,13 @@ def CheckPackageBoundaries(root_dir, logger, build_files=None):
else:
build_files = [os.path.join(package, 'BUILD.gn') for package in packages]
return any([_CheckBuildFile(build_file_path, packages, logger)
for build_file_path in build_files])
messages = []
for build_file_path in build_files:
messages.extend(_CheckBuildFile(build_file_path, packages))
return messages
def main():
def main(argv):
parser = argparse.ArgumentParser(
description='Script that checks package boundary violations in GN '
'build files.')
@ -127,14 +111,18 @@ def main():
help='If set, the maximum number of violations to be '
'displayed.')
args = parser.parse_args()
args = parser.parse_args(argv)
logging.basicConfig(format=LOG_FORMAT)
logging.getLogger().setLevel(DISPLAY_LEVEL)
logger = Logger(args.max_messages)
messages = CheckPackageBoundaries(args.root_dir, args.build_files)
messages = messages[:args.max_messages]
return CheckPackageBoundaries(args.root_dir, logger, args.build_files)
for i, message in enumerate(messages):
if i > 0:
print
print message
return bool(messages)
if __name__ == '__main__':
sys.exit(main())
sys.exit(main(sys.argv[1:]))

View File

@ -25,54 +25,46 @@ def ReadPylFile(file_path):
return ast.literal_eval(f.read())
class Logger(object):
def __init__(self, test_dir):
self.messages = []
self.test_dir = test_dir
def Log(self, build_file_path, line_number, target_name, source_file,
subpackage):
build_file_path = os.path.relpath(build_file_path, self.test_dir)
build_file_path = build_file_path.replace(os.path.sep, '/')
self.messages.append([build_file_path, line_number, target_name,
source_file, subpackage])
class UnitTest(unittest.TestCase):
def RunTest(self, test_dir, check_all_build_files=False):
logger = Logger(test_dir)
def _RunTest(self, test_dir, check_all_build_files=False):
build_files = [os.path.join(test_dir, 'BUILD.gn')]
if check_all_build_files:
build_files = None
CheckPackageBoundaries(test_dir, logger, build_files)
messages = []
for violation in CheckPackageBoundaries(test_dir, build_files):
build_file_path = os.path.relpath(violation.build_file_path, test_dir)
build_file_path = build_file_path.replace(os.path.sep, '/')
messages.append(violation._replace(build_file_path=build_file_path))
expected_messages = ReadPylFile(os.path.join(test_dir, 'expected.pyl'))
self.assertListEqual(sorted(expected_messages), sorted(logger.messages))
self.assertListEqual(sorted(expected_messages), sorted(messages))
def testNoErrors(self):
self.RunTest(os.path.join(TESTDATA_DIR, 'no_errors'))
self._RunTest(os.path.join(TESTDATA_DIR, 'no_errors'))
def testMultipleErrorsSingleTarget(self):
self.RunTest(os.path.join(TESTDATA_DIR, 'multiple_errors_single_target'))
self._RunTest(os.path.join(TESTDATA_DIR, 'multiple_errors_single_target'))
def testMultipleErrorsMultipleTargets(self):
self.RunTest(os.path.join(TESTDATA_DIR, 'multiple_errors_multiple_targets'))
self._RunTest(os.path.join(TESTDATA_DIR,
'multiple_errors_multiple_targets'))
def testCommonPrefix(self):
self.RunTest(os.path.join(TESTDATA_DIR, 'common_prefix'))
self._RunTest(os.path.join(TESTDATA_DIR, 'common_prefix'))
def testAllBuildFiles(self):
self.RunTest(os.path.join(TESTDATA_DIR, 'all_build_files'), True)
self._RunTest(os.path.join(TESTDATA_DIR, 'all_build_files'), True)
def testSanitizeFilename(self):
# The `dangerous_filename` test case contains a directory with '++' in its
# name. If it's not properly escaped, a regex error would be raised.
self.RunTest(os.path.join(TESTDATA_DIR, 'dangerous_filename'), True)
self._RunTest(os.path.join(TESTDATA_DIR, 'dangerous_filename'), True)
def testRelativeFilename(self):
test_dir = os.path.join(TESTDATA_DIR, 'all_build_files')
logger = Logger(test_dir)
with self.assertRaises(AssertionError):
CheckPackageBoundaries(test_dir, logger, ["BUILD.gn"])
CheckPackageBoundaries(test_dir, ["BUILD.gn"])
if __name__ == '__main__':

View File

@ -1,20 +1,20 @@
[['subpackage2/BUILD.gn',
[('subpackage2/BUILD.gn',
'12',
'error_2',
'subsubpackage2/dummy_subsubpackage2.cc',
'subsubpackage2'],
['subpackage2/BUILD.gn',
'subsubpackage2'),
('subpackage2/BUILD.gn',
'13',
'error_2',
'subsubpackage2/dummy_subsubpackage2.h',
'subsubpackage2'],
['subpackage1/BUILD.gn',
'subsubpackage2'),
('subpackage1/BUILD.gn',
'12',
'error_1',
'subsubpackage1/dummy_subsubpackage1.cc',
'subsubpackage1'],
['subpackage1/BUILD.gn',
'subsubpackage1'),
('subpackage1/BUILD.gn',
'13',
'error_1',
'subsubpackage1/dummy_subsubpackage1.h',
'subsubpackage1']]
'subsubpackage1')]

View File

@ -1,5 +1,5 @@
[["BUILD.gn",
[("BUILD.gn",
"13",
"dummy_target",
"libc++/dummy_subpackage_file.h",
"libc++"]]
"libc++")]

View File

@ -1,20 +1,20 @@
[['BUILD.gn',
[('BUILD.gn',
'18',
'error_1',
'subpackage1/dummy_subpackage1.cc',
'subpackage1'],
['BUILD.gn',
'subpackage1'),
('BUILD.gn',
'19',
'error_1',
'subpackage1/dummy_subpackage1.h',
'subpackage1'],
['BUILD.gn',
'subpackage1'),
('BUILD.gn',
'25',
'error_2',
'subpackage1/dummy_subpackage2.cc',
'subpackage1'],
['BUILD.gn',
'subpackage1'),
('BUILD.gn',
'26',
'error_2',
'subpackage1/dummy_subpackage2.h',
'subpackage1']]
'subpackage1')]

View File

@ -1,10 +1,10 @@
[["BUILD.gn",
[("BUILD.gn",
"11",
"dummy_target",
"subpackage/dummy_subpackage_file.cc",
"subpackage"],
["BUILD.gn",
"subpackage"),
("BUILD.gn",
"12",
"dummy_target",
"subpackage/dummy_subpackage_file.h",
"subpackage"]]
"subpackage")]