From ffd10a5576c3dd50ffdab0bb2ec80226aed5d5c8 Mon Sep 17 00:00:00 2001 From: Aleksey Khoroshilov Date: Fri, 27 May 2022 00:02:38 +0700 Subject: [PATCH] Add support for upstream presubmit logic on npm run lint. --- PRESUBMIT.py | 17 ++ build/commands/lib/pylint.js | 30 +++- build/commands/lib/util.js | 35 +++- build/commands/scripts/commands.js | 12 ++ build/commands/scripts/format.py | 45 ----- .../chrome/browser/prefs/browser_prefs.cc | 5 + codereview.settings | 6 +- .../brave_private_cdn/private_cdn_helper.cc | 5 + .../brave_private_cdn/private_cdn_helper.h | 6 +- inherit-review-settings-ok | 2 + package.json | 1 + patches/PRESUBMIT.py.patch | 9 + script/chromium_presubmit_overrides.py | 168 ++++++++++++++++++ script/lib/chromium_presubmit_utils.py | 92 ++++++++++ script/lib/import_inline.py | 17 ++ win_build_output/CPPLINT.cfg | 1 + 16 files changed, 389 insertions(+), 62 deletions(-) create mode 100644 PRESUBMIT.py mode change 100755 => 100644 build/commands/scripts/commands.js delete mode 100644 build/commands/scripts/format.py create mode 100644 inherit-review-settings-ok create mode 100644 patches/PRESUBMIT.py.patch create mode 100644 script/chromium_presubmit_overrides.py create mode 100644 script/lib/chromium_presubmit_utils.py create mode 100644 script/lib/import_inline.py create mode 100644 win_build_output/CPPLINT.cfg diff --git a/PRESUBMIT.py b/PRESUBMIT.py new file mode 100644 index 000000000000..f73d32455e61 --- /dev/null +++ b/PRESUBMIT.py @@ -0,0 +1,17 @@ +# Copyright (c) 2022 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. */ + +USE_PYTHON3 = True +PRESUBMIT_VERSION = '2.0.0' + + +def CheckChangeLintsClean(input_api, output_api): + return input_api.canned_checks.CheckChangeLintsClean(input_api, output_api) + + +def CheckPylint(input_api, output_api): + return input_api.canned_checks.RunPylint(input_api, + output_api, + version='2.7') diff --git a/build/commands/lib/pylint.js b/build/commands/lib/pylint.js index b25d960fae96..598127dcae0d 100644 --- a/build/commands/lib/pylint.js +++ b/build/commands/lib/pylint.js @@ -5,6 +5,7 @@ const path = require('path') const fs = require('fs') +const os = require('os') const config = require('../lib/config') const util = require('../lib/util') const {EOL} = require('os'); @@ -65,14 +66,14 @@ const getAllFiles = (check_folders) => { return files.split('\n') } -const getChangedFiles = (base_branch, check_folders) => { - if (!base_branch) { +const getChangedFiles = (options, check_folders) => { + if (options.all) { return getAllFiles(check_folders) } - const merge_base = runGit(['merge-base', 'origin/' + base_branch, 'HEAD']) + const merge_base = runGit(['merge-base', options.base, 'HEAD']) if (!merge_base) { - console.error('Could not determine merge-base for branch ' + base_branch) + console.error('Could not determine merge-base for branch ' + options.base) process.exit(1) } const changed_files = runGit(['diff', '--name-only', '--diff-filter', 'drt', @@ -114,26 +115,31 @@ const runPylintLoop = (options, args, paths, report_file) => { result &= doPylint(loop_args) currentLen = 0 loop_args = [...args] - } + } loop_args.push(pyPath) currentLen += pyPath.length } if (currentLen > 0) { - result &= doPylint(loop_args) + result &= doPylint(loop_args) } return result } const pylint = (options = {}) => { + if (!options.base) { + options.base = 'origin/master' + } else if (!options.base.startsWith('origin/')) { + options.base = 'origin/' + options.base + } const check_folders = ['build', 'components', 'installer', 'script', 'tools'] const report_file = 'pylint-report.txt' const description = getDescription(options.base, check_folders) // Get changed or all python files - const paths = getChangedFiles(options.base, check_folders) + const paths = getChangedFiles(options, check_folders) if (!paths.length) { console.log('No ' + description) if (options.report) { @@ -142,8 +148,14 @@ const pylint = (options = {}) => { return } - // Prepare pylint args - let args = ['-j0', '-rn'] + var j_value = 0 + if (process.platform === 'win32') { + // Windows can't handle unrestricted -j0 value, limit it to sane value. + j_value = Math.min(32, os.cpus().length) + } + + // Prepare pylint args. + let args = [ '-j' + j_value.toString(), '-rn'] if (options.report) { args.push('-fparseable') // Clean previous report as we will be appending to it diff --git a/build/commands/lib/util.js b/build/commands/lib/util.js index 0565464c3155..93603e3d9926 100755 --- a/build/commands/lib/util.js +++ b/build/commands/lib/util.js @@ -587,7 +587,7 @@ const util = { util.run('goma_ctl', ['showflags'], options) util.run('goma_ctl', ['stat'], options) } - + // Setting `AUTONINJA_BUILD_ID` allows tracing Goma remote execution which helps with // debugging issues (e.g., slowness or remote-failures). options.env.AUTONINJA_BUILD_ID = buildId @@ -627,11 +627,42 @@ const util = { '--base_branch=' + options.base], cmd_options) }, + presubmit: (options = {}) => { + if (!options.base) { + options.base = 'origin/master' + } + // Temporary cleanup call, should be removed when everyone will remove + // 'gerrit.host' from their brave checkout. + util.runGit( + config.braveCoreDir, ['config', '--unset-all', 'gerrit.host'], true) + let cmd_options = config.defaultOptions + cmd_options.cwd = config.braveCoreDir + cmd_options = mergeWithDefault(cmd_options) + cmd = 'git' + args = ['cl', 'presubmit', options.base, '--force'] + if (options.all) + args.append('--all') + util.run(cmd, args, cmd_options) + }, + format: (options = {}) => { + if (!options.base) { + options.base = 'origin/master' + } let cmd_options = config.defaultOptions cmd_options.cwd = config.braveCoreDir cmd_options = mergeWithDefault(cmd_options) - util.run('vpython', [path.join(config.braveCoreDir, 'build', 'commands', 'scripts', 'format.py'), options.full ? '--full' : ''], cmd_options) + cmd = 'git' + args = ['cl', 'format', '--upstream=' + options.base] + if (options.full) + args.append('--full') + if (options.js) + args.append('--js') + if (options.rust) + args.append('--rust-fmt') + if (options.swift) + args.append('--swift-format') + util.run(cmd, args, cmd_options) }, diff --git a/build/commands/scripts/commands.js b/build/commands/scripts/commands.js old mode 100755 new mode 100644 index 5e056fcc456b..19b47ab62fd8 --- a/build/commands/scripts/commands.js +++ b/build/commands/scripts/commands.js @@ -249,15 +249,27 @@ program .option('--base ', 'set the destination branch for the PR') .action(util.lint) +program + .command('presubmit') + .option('--base ', 'set the destination branch for the PR') + .option('--all', 'run presubmit on all files') + .action(util.presubmit) + program .command('pylint') .option('--base ', 'only analyse files changed relative to base_branch') + .option('--all', 'run pylint on all files') .option('--report', 'produce a parseable report file') .action(pylint) program .command('format') + .option('--base ', 'set the destination branch for the PR') .option('--full', 'format all lines in changed files instead of only the changed lines') + .option('--js', 'format javascript code with clang-format') + .option('--rust', 'enables formatting of Rust file types using rustfmt') + .option('--swift', + 'enables formatting of Swift file types using swift-format') .action(util.format) program diff --git a/build/commands/scripts/format.py b/build/commands/scripts/format.py deleted file mode 100644 index 006e4955766a..000000000000 --- a/build/commands/scripts/format.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env vpython -# Copyright (c) 2020 The Brave Authors. All rights reserved. -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this file, -# You can obtain one at http://mozilla.org/MPL/2.0/. - -#!/usr/bin/env vpython -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# Copyright (C) 2008 Evan Martin - -import os -import sys - -import git_cl - - -def main(args): - """Runs clang-format and gn format on the current changelist.""" - parser = git_cl.OptionParser() - parser.parse_args([]) - - # Change the current working directory before calling so that it - # shows the correct base. - settings = git_cl.settings - previous_cwd = os.getcwd() - os.chdir(settings.GetRoot()) - try: - cmd = ['cl', 'format'] + args - print('git ' + ' '.join(cmd)) - git_cl.RunGit(cmd) - except: - e = sys.exc_info()[1] - print('Could not run format: %s' % e.message) - return 1 - finally: - os.chdir(previous_cwd) - print('Formatting done.') - return 0 - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/chromium_src/chrome/browser/prefs/browser_prefs.cc b/chromium_src/chrome/browser/prefs/browser_prefs.cc index 9de25cf96ad6..8034958a53a1 100644 --- a/chromium_src/chrome/browser/prefs/browser_prefs.cc +++ b/chromium_src/chrome/browser/prefs/browser_prefs.cc @@ -56,6 +56,7 @@ // This method should be periodically pruned of year+ old migrations. void MigrateObsoleteProfilePrefs(Profile* profile) { + // BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS #if !BUILDFLAG(USE_GCM_FROM_PLATFORM) // Added 02/2020. // Must be called before ChromiumImpl because it's migrating a Chromium pref @@ -98,10 +99,12 @@ void MigrateObsoleteProfilePrefs(Profile* profile) { #if BUILDFLAG(ENABLE_BRAVE_TRANSLATE_GO) translate::MigrateBraveProfilePrefs(profile->GetPrefs()); #endif + // END_MIGRATE_OBSOLETE_PROFILE_PREFS } // This method should be periodically pruned of year+ old migrations. void MigrateObsoleteLocalStatePrefs(PrefService* local_state) { + // BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS MigrateObsoleteLocalStatePrefs_ChromiumImpl(local_state); #if BUILDFLAG(ENABLE_WIDEVINE) @@ -115,4 +118,6 @@ void MigrateObsoleteLocalStatePrefs(PrefService* local_state) { #endif decentralized_dns::MigrateObsoleteLocalStatePrefs(local_state); + + // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS } diff --git a/codereview.settings b/codereview.settings index 7156e22c353d..f2e6bc5a2ac4 100644 --- a/codereview.settings +++ b/codereview.settings @@ -1,3 +1,7 @@ # This file is used by git-cl to get repository specific information. -GERRIT_HOST: True + +# Don't add GERRIT_HOST, it will make PRESUBMIT checks do unnecessary stuff. +# CODE_REVIEW_SERVER is a mock value to not generate errors during PRESUBMIT. +CODE_REVIEW_SERVER: github.com + LINT_IGNORE_REGEX: win_build_output/midl/google_update/.* diff --git a/components/brave_private_cdn/private_cdn_helper.cc b/components/brave_private_cdn/private_cdn_helper.cc index 2a6c8f182068..b1ff288b20c9 100644 --- a/components/brave_private_cdn/private_cdn_helper.cc +++ b/components/brave_private_cdn/private_cdn_helper.cc @@ -9,6 +9,11 @@ namespace brave { +// static +PrivateCdnHelper* PrivateCdnHelper::GetInstance() { + return base::Singleton::get(); +} + bool PrivateCdnHelper::RemovePadding(base::StringPiece* padded_string) const { if (!padded_string) { return false; diff --git a/components/brave_private_cdn/private_cdn_helper.h b/components/brave_private_cdn/private_cdn_helper.h index 4fc5d3fe6b8f..07708ecc6b53 100644 --- a/components/brave_private_cdn/private_cdn_helper.h +++ b/components/brave_private_cdn/private_cdn_helper.h @@ -6,8 +6,6 @@ #ifndef BRAVE_COMPONENTS_BRAVE_PRIVATE_CDN_PRIVATE_CDN_HELPER_H_ #define BRAVE_COMPONENTS_BRAVE_PRIVATE_CDN_PRIVATE_CDN_HELPER_H_ -#include - #include "base/memory/singleton.h" #include "base/strings/string_piece.h" @@ -18,9 +16,7 @@ class PrivateCdnHelper final { PrivateCdnHelper(const PrivateCdnHelper&) = delete; PrivateCdnHelper& operator=(const PrivateCdnHelper&) = delete; - static PrivateCdnHelper* GetInstance() { - return base::Singleton::get(); - } + static PrivateCdnHelper* GetInstance(); bool RemovePadding(base::StringPiece* padded_string) const; diff --git a/inherit-review-settings-ok b/inherit-review-settings-ok new file mode 100644 index 000000000000..1d3cdffe954c --- /dev/null +++ b/inherit-review-settings-ok @@ -0,0 +1,2 @@ +This file allows src/PRESUBMIT.py to be executed on brave/* files. +See presubmit_support.py for details. diff --git a/package.json b/package.json index 6784bd0633c7..90fe0c1ec5ff 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "pull_l10n": "node ./build/commands/scripts/commands.js pull_l10n", "chromium_rebase_l10n": "node ./build/commands/scripts/commands.js chromium_rebase_l10n", "lint": "node ./build/commands/scripts/commands.js lint", + "presubmit": "node ./build/commands/scripts/commands.js presubmit", "format": "node ./build/commands/scripts/commands.js format", "test": "node ./build/commands/scripts/commands.js test", "test:scripts": "jest build/commands/lib build/commands/scripts", diff --git a/patches/PRESUBMIT.py.patch b/patches/PRESUBMIT.py.patch new file mode 100644 index 000000000000..19bf25e3ad1b --- /dev/null +++ b/patches/PRESUBMIT.py.patch @@ -0,0 +1,9 @@ +diff --git a/PRESUBMIT.py b/PRESUBMIT.py +index 81b1b62c3ef84dedaba01ef067bafc66d9ebfbb4..7e4fb471f68b60b23b03603902f33fb0e90ca204 100644 +--- a/PRESUBMIT.py ++++ b/PRESUBMIT.py +@@ -5845,3 +5845,4 @@ def CheckPythonShebang(input_api, output_api): + "Please use '#!/usr/bin/env python/2/3' as the shebang of %s" % + file)) + return result ++if not globals().get('__name__'): from lib.import_inline import inline_module; inline_module('chromium_presubmit_overrides', globals(), locals()) diff --git a/script/chromium_presubmit_overrides.py b/script/chromium_presubmit_overrides.py new file mode 100644 index 000000000000..7d002dfe6e34 --- /dev/null +++ b/script/chromium_presubmit_overrides.py @@ -0,0 +1,168 @@ +# Copyright (c) 2022 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. */ + +# This file is executed (not imported) in the context of src/PRESUBMIT.py, it +# uses existing functions from a global scope to change them. This allows us to +# alter root Chromium presubmit checks without introducing too much conflict. + +# pylint: disable=protected-access + +import copy + +import lib.chromium_presubmit_utils as chromium_presubmit_utils + +_BRAVE_DEFAULT_FILES_TO_SKIP = (r'win_build_output[\\/].*', ) + + +# Modify depot_tools-bundled checks (Chromium calls them canned checks). +def _modify_canned_checks(input_api): + input_api.DEFAULT_FILES_TO_SKIP += _BRAVE_DEFAULT_FILES_TO_SKIP + + # pylint: disable=unused-variable + + # Disable upstream-specific license check. + @chromium_presubmit_utils.override_check(input_api.canned_checks) + def CheckLicense(*_, **__): + return [] + + # We don't use OWNERS files. + @chromium_presubmit_utils.override_check(input_api.canned_checks) + def CheckOwnersFormat(*_, **__): + return [] + + # We don't use OWNERS files. + @chromium_presubmit_utils.override_check(input_api.canned_checks) + def CheckOwners(*_, **__): + return [] + + # We don't upload change to Chromium git. + @chromium_presubmit_utils.override_check(input_api.canned_checks) + def CheckChangeWasUploaded(*_, **__): + return [] + + # We don't upload change to Chromium git. + @chromium_presubmit_utils.override_check(input_api.canned_checks) + def CheckChangeHasBugField(*_, **__): + return [] + + # We don't upload change to Chromium git. + @chromium_presubmit_utils.override_check(input_api.canned_checks) + def CheckTreeIsOpen(*_, **__): + return [] + + # Enforce format check, fix output text to show our command instead. + @chromium_presubmit_utils.override_check(input_api.canned_checks) + def CheckPatchFormatted(original_check, input_api, output_api, *args, + **kwargs): + if 'result_factory' in kwargs: + del kwargs['result_factory'] + result = original_check(input_api, + output_api, + *args, + result_factory=output_api.PresubmitError, + **kwargs) + for item in result: + item._message = item._message.replace('git cl format', + 'npm run format --') + item._message = item._message.replace('gn format', + 'npm run format --') + return result + + # Override Pylint checker to do per-file lint. + @chromium_presubmit_utils.override_check(input_api.canned_checks) + def GetPylint(original_check, input_api, *args, **kwargs): + # Change upstream logic to lint each Python file individually instead of + # getting *all* files from the root directory. Upstream does it to catch + # breakages in unmodified files. + def _FetchAllFiles(_, input_api, files_to_check, files_to_skip): + src_filter = lambda f: input_api.FilterSourceFile( + f, files_to_check=files_to_check, files_to_skip=files_to_skip) + return [ + f.LocalPath() + for f in input_api.AffectedSourceFiles(src_filter) + ] + + # Make Pylint work on high core Windows machines. crbug.com/1190269 + cpu_count = input_api.cpu_count + if input_api.is_windows: + cpu_count = min(cpu_count, 32) + + with chromium_presubmit_utils.override_scope_function( + input_api.canned_checks, _FetchAllFiles): + with chromium_presubmit_utils.override_scope_variable( + input_api, 'cpu_count', cpu_count): + # is_committing = True forces pylint to be errors. + with chromium_presubmit_utils.override_scope_variable( + input_api, 'is_committing', True): + return original_check(input_api, *args, **kwargs) + + +# Override the first ever check defined in PRESUBMIT.py to make changes to +# input_api/output_api before any real check is run. +@chromium_presubmit_utils.override_check( + globals(), chromium_presubmit_utils.get_first_check_name(globals())) +def OverriddenFirstCheck(original_check, input_api, output_api, *args, + **kwargs): + _modify_canned_checks(input_api) + return original_check(input_api, output_api, *args, **kwargs) + + +# We don't use OWNERS files. +@chromium_presubmit_utils.override_check(globals()) +def CheckSecurityOwners(*_, **__): + return [] + + +# This validates added strings with screenshot tests which we don't use. +@chromium_presubmit_utils.override_check(globals()) +def CheckStrings(*_, **__): + return [] + + +# Don't check upstream pydeps. +@chromium_presubmit_utils.override_check(globals()) +def CheckPydepsNeedsUpdating(*_, **__): + return [] + + +# Override to add brave/ prefix for the header guard checks. +@chromium_presubmit_utils.override_check(globals()) +def CheckForIncludeGuards(original_check, input_api, output_api, *args, + **kwargs): + def AffectedSourceFiles(self, original_method, source_file): + def PrependBrave(affected_file): + affected_file = copy.copy(affected_file) + affected_file._path = f'brave/{affected_file._path}' + return affected_file + + return [ + PrependBrave(f) for f in filter(self.FilterSourceFile, + original_method(source_file)) + ] + + with chromium_presubmit_utils.override_scope_function( + input_api, AffectedSourceFiles): + return original_check(input_api, output_api, *args, **kwargs) + + +# Ignore some files to check for JSON parse errors. +@chromium_presubmit_utils.override_check(globals()) +def CheckParseErrors(original_check, input_api, output_api, *args, **kwargs): + # pylint: disable=undefined-variable + _KNOWN_TEST_DATA_AND_INVALID_JSON_FILE_PATTERNS.append(r'tsconfig\.json$') + return original_check(input_api, output_api, *args, **kwargs) + + +# Modify check to include all files to check, otherwise it checks only +# ^chrome, ^components, etc. (ignoring ^brave). +@chromium_presubmit_utils.override_check(globals()) +def CheckMPArchApiUsage(original_check, input_api, output_api, *args, + **kwargs): + def AffectedFiles(self, original_method, *_, **__): + return original_method(False, self.FilterSourceFile) + + with chromium_presubmit_utils.override_scope_function( + input_api, AffectedFiles): + return original_check(input_api, output_api, *args, **kwargs) diff --git a/script/lib/chromium_presubmit_utils.py b/script/lib/chromium_presubmit_utils.py new file mode 100644 index 000000000000..97b4e0960a7b --- /dev/null +++ b/script/lib/chromium_presubmit_utils.py @@ -0,0 +1,92 @@ +# Copyright (c) 2022 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import contextlib +import inspect +import types + + +def override_check(scope, name=None): + """Replaces existing PRESUBMIT check. Can be used with globals() scope or a + class scope (such as input_api.canned_checks).""" + def decorator(new_func): + is_dict_scope = isinstance(scope, dict) + check_name = name or new_func.__name__ + if is_dict_scope: + original_check = scope.get(check_name, None) + else: + original_check = getattr(scope, check_name, None) + + if not callable(original_check): + print(f'WARNING: {check_name} check to override not found.\n' + 'Please update chromium_presubmit_overrides.py!') + + def noop_check(*_, **__): + return [] + + return noop_check + + def wrapped_f(*args, **kwargs): + return new_func(original_check, *args, **kwargs) + + if is_dict_scope: + scope[check_name] = wrapped_f + else: + setattr(scope, check_name, wrapped_f) + + return wrapped_f + + return decorator + + +@contextlib.contextmanager +def override_scope_function(scope, new_function, name=None): + """Scoped function override helper. Can override a scope method or a class + function.""" + function_name = name or new_function.__name__ + original_function = getattr(scope, function_name, None) + try: + if not callable(original_function): + raise NameError(f'Failed to override scope function: ' + f'{function_name} not found or not callable') + + def wrapped_method(self, *args, **kwargs): + return new_function(self, original_function, *args, **kwargs) + + def wrapped_function(*args, **kwargs): + return new_function(original_function, *args, **kwargs) + + if inspect.ismethod(original_function): + setattr(scope, function_name, + types.MethodType(wrapped_method, scope)) + else: + setattr(scope, function_name, wrapped_function) + + yield + finally: + if original_function: + setattr(scope, function_name, original_function) + + +@contextlib.contextmanager +def override_scope_variable(scope, name, value): + """Scoped variable override helper.""" + if not hasattr(scope, name): + raise NameError(f'Failed to override scope variable: {name} not found') + original_value = getattr(scope, name) + try: + setattr(scope, name, value) + yield + finally: + setattr(scope, name, original_value) + + +def get_first_check_name(scope): + """Returns first Check* method from the scope.""" + assert isinstance(scope, dict) + for key, value in scope.items(): + if key.startswith('Check') and callable(value): + return key + raise LookupError('Check* method not found in scope') diff --git a/script/lib/import_inline.py b/script/lib/import_inline.py new file mode 100644 index 000000000000..caa8778ccd3e --- /dev/null +++ b/script/lib/import_inline.py @@ -0,0 +1,17 @@ +# Copyright (c) 2022 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import importlib + + +def inline_module(module_name, _globals, _locals): + """Finds module and inlines it by executing using passed scopes.""" + module_spec = importlib.util.find_spec(module_name) + if not module_spec: + raise ModuleNotFoundError( + f"Can't find module to inline: {module_name}") + # pylint: disable=exec-used + exec(module_spec.loader.get_data(module_spec.loader.path), _globals, + _locals) diff --git a/win_build_output/CPPLINT.cfg b/win_build_output/CPPLINT.cfg new file mode 100644 index 000000000000..7a8e2da4cb65 --- /dev/null +++ b/win_build_output/CPPLINT.cfg @@ -0,0 +1 @@ +exclude_files=midl