diff --git a/PRESUBMIT.py b/PRESUBMIT.py
new file mode 100644
index 00000000000..f73d32455e6
--- /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 b25d960fae9..598127dcae0 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 0565464c315..93603e3d992 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)
},
- format: (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)
- util.run('vpython', [path.join(config.braveCoreDir, 'build', 'commands', 'scripts', 'format.py'), options.full ? '--full' : ''], 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)
+ 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 5e056fcc456..19b47ab62fd
--- 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 006e4955766..00000000000
--- 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 9de25cf96ad..8034958a53a 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 7156e22c353..f2e6bc5a2ac 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 2a6c8f18206..b1ff288b20c 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 4fc5d3fe6b8..07708ecc6b5 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 00000000000..1d3cdffe954
--- /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 6784bd0633c..90fe0c1ec5f 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 00000000000..19bf25e3ad1
--- /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 00000000000..7d002dfe6e3
--- /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 00000000000..97b4e0960a7
--- /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 00000000000..caa8778ccd3
--- /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 00000000000..7a8e2da4cb6
--- /dev/null
+++ b/win_build_output/CPPLINT.cfg
@@ -0,0 +1 @@
+exclude_files=midl