Add support for upstream presubmit logic on npm run lint.
This commit is contained in:
@@ -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')
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
},
|
||||
|
||||
|
||||
|
||||
Executable → Regular
+12
@@ -249,15 +249,27 @@ program
|
||||
.option('--base <base branch>', 'set the destination branch for the PR')
|
||||
.action(util.lint)
|
||||
|
||||
program
|
||||
.command('presubmit')
|
||||
.option('--base <base branch>', 'set the destination branch for the PR')
|
||||
.option('--all', 'run presubmit on all files')
|
||||
.action(util.presubmit)
|
||||
|
||||
program
|
||||
.command('pylint')
|
||||
.option('--base <base_branch>', '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 <base branch>', '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
|
||||
|
||||
@@ -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 <martine@danga.com>
|
||||
|
||||
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:]))
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+5
-1
@@ -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/.*
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
|
||||
namespace brave {
|
||||
|
||||
// static
|
||||
PrivateCdnHelper* PrivateCdnHelper::GetInstance() {
|
||||
return base::Singleton<PrivateCdnHelper>::get();
|
||||
}
|
||||
|
||||
bool PrivateCdnHelper::RemovePadding(base::StringPiece* padded_string) const {
|
||||
if (!padded_string) {
|
||||
return false;
|
||||
|
||||
@@ -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 <string>
|
||||
|
||||
#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<PrivateCdnHelper>::get();
|
||||
}
|
||||
static PrivateCdnHelper* GetInstance();
|
||||
|
||||
bool RemovePadding(base::StringPiece* padded_string) const;
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
This file allows src/PRESUBMIT.py to be executed on brave/* files.
|
||||
See presubmit_support.py for details.
|
||||
@@ -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",
|
||||
|
||||
@@ -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())
|
||||
@@ -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)
|
||||
@@ -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')
|
||||
@@ -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)
|
||||
@@ -0,0 +1 @@
|
||||
exclude_files=midl
|
||||
Reference in New Issue
Block a user