Remove all but 2 eslint-disable pragmas (#1335)

Turns off:
 - no-explicit-any (we need to handle any return values from runPython)
 - no-unsafe-assignment (noisy and pointless)

And resolves all but two remaining ones. The last two lints regard access to private Pyodide variables and so:
 - they are not easy to work around without an upstream Pyodide patch
 - they should trigger linter and require explicit override
This commit is contained in:
Hood Chatham
2023-03-30 10:51:36 -07:00
committed by GitHub
parent 854e9d1378
commit 146afb6532
13 changed files with 42 additions and 61 deletions

View File

@@ -21,9 +21,11 @@ module.exports = {
// ts-ignore is already an explicit override, no need to have a second lint
'@typescript-eslint/ban-ts-comment': 'off',
// any related lints
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unsafe-assignment': 'error',
// any-related lints
// These two come up a lot, so they probably aren't worth it
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
// encourage people to cast "any" to a more specific type before using it
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-argument': 'error',
@@ -35,5 +37,6 @@ module.exports = {
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/restrict-plus-operands': 'error',
'@typescript-eslint/no-empty-function': 'error',
'@typescript-eslint/restrict-template-expressions': ['error', { allowBoolean: true }],
},
};

View File

@@ -7,10 +7,8 @@ function createCustomElements(interpreter: InterpreterClient, app: PyScriptApp)
const PyWidget = make_PyWidget(interpreter);
const PyRepl = make_PyRepl(interpreter, app);
/* eslint-disable @typescript-eslint/no-unused-vars */
const xPyRepl = customElements.define('py-repl', PyRepl);
const xPyWidget = customElements.define('py-register-widget', PyWidget);
/* eslint-enable @typescript-eslint/no-unused-vars */
customElements.define('py-repl', PyRepl);
customElements.define('py-register-widget', PyWidget);
}
export { createCustomElements };

View File

@@ -133,14 +133,13 @@ export function make_PyRepl(interpreter: InterpreterClient, app: PyScriptApp) {
// execute the python code
await app.plugins.beforePyReplExec({ interpreter: interpreter, src: pySrc, outEl: outEl, pyReplTag: this });
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const { result } = await pyExec(interpreter, pySrc, outEl);
await app.plugins.afterPyReplExec({
interpreter: interpreter,
src: pySrc,
outEl: outEl,
pyReplTag: this,
result, // eslint-disable-line @typescript-eslint/no-unsafe-assignment
result,
});
this.autogenerateMaybe();

View File

@@ -36,7 +36,6 @@ export function make_PyScript(interpreter: InterpreterClient, app: PyScriptApp)
this.innerHTML = '';
await app.plugins.beforePyScriptExec({ interpreter: interpreter, src: pySrc, pyScriptTag: this });
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
const result = (await pyExec(interpreter, pySrc, this)).result;
await app.plugins.afterPyScriptExec({
interpreter: interpreter,
@@ -44,7 +43,6 @@ export function make_PyScript(interpreter: InterpreterClient, app: PyScriptApp)
pyScriptTag: this,
result: result,
});
/* eslint-enable @typescript-eslint/no-unsafe-assignment */
} finally {
releaseLock();
app.decrementPendingTags();

View File

@@ -40,8 +40,7 @@ function createWidget(interpreter: InterpreterClient, name: string, code: string
await interpreter.globals.set(this.id, this.proxy);
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const xPyWidget = customElements.define(name, CustomWidget);
customElements.define(name, CustomWidget);
}
export function make_PyWidget(interpreter: InterpreterClient) {

View File

@@ -69,7 +69,6 @@ export function _createAlertBanner(
messageType: MessageType = 'text',
logMessage = true,
) {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
switch (`log-${level}-${logMessage}`) {
case 'log-error-true':
console.error(message);

View File

@@ -59,7 +59,6 @@ export class InterpreterClient extends Object {
* 2. a Synclink Proxy wrapping an object of this if the result is not
* serializable.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async run(code: string, id?: string): Promise<{ result: any }> {
return this._remote.pyscript_py._run_pyscript(code, id);
}

View File

@@ -4,7 +4,7 @@ import { loadConfigFromElement } from './pyconfig';
import type { AppConfig } from './pyconfig';
import { InterpreterClient } from './interpreter_client';
import { version } from './version';
import { PluginManager, define_custom_element, Plugin } from './plugin';
import { PluginManager, define_custom_element, Plugin, PythonPlugin } from './plugin';
import { make_PyScript, initHandlers, mountElements } from './components/pyscript';
import { getLogger } from './logger';
import { showWarning, globalExport, createLock } from './utils';
@@ -16,7 +16,6 @@ import { PyTerminalPlugin } from './plugins/pyterminal';
import { SplashscreenPlugin } from './plugins/splashscreen';
import { ImportmapPlugin } from './plugins/importmap';
import { StdioDirector as StdioDirector } from './plugins/stdiodirector';
import type { PyProxy } from 'pyodide';
import { RemoteInterpreter } from './remote_interpreter';
import { robustFetch } from './fetch';
import * as Synclink from 'synclink';
@@ -131,7 +130,6 @@ export class PyScriptApp {
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async _handleUserErrorMaybe(error: any) {
const e = error as UserError;
if (e && e.$$isUserError) {
@@ -399,7 +397,7 @@ export class PyScriptApp {
// eventually replace with interpreter.pyimport(modulename);
const module = interpreter._unwrapped_remote.pyimport(modulename);
if (typeof (await module.plugin) !== 'undefined') {
const py_plugin = module.plugin as PyProxy & { init(app: PyScriptApp): void };
const py_plugin = module.plugin as PythonPlugin;
py_plugin.init(this);
this.plugins.addPythonPlugin(py_plugin);
} else {

View File

@@ -1,8 +1,4 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access,
@typescript-eslint/no-unsafe-call,
@typescript-eslint/no-explicit-any,
@typescript-eslint/no-unsafe-assignment */
import type { PyScriptApp } from './main';
import type { AppConfig } from './pyconfig';
import type { UserError } from './exceptions';
import { getLogger } from './logger';
@@ -125,9 +121,21 @@ export class Plugin {
}
}
export type PythonPlugin = {
init(app: PyScriptApp): void;
configure?: (config: AppConfig) => Promise<void>;
afterSetup?: (interpreter: InterpreterClient) => Promise<void>;
afterStartup?: (interpreter: InterpreterClient) => Promise<void>;
beforePyScriptExec?: { callKwargs: (options: any) => Promise<void> };
afterPyScriptExec?: { callKwargs: (options: any) => Promise<void> };
beforePyReplExec?: { callKwargs: (options: any) => Promise<void> };
afterPyReplExec?: { callKwargs: (options: any) => Promise<void> };
onUserError?: (error: UserError) => Promise<void>;
};
export class PluginManager {
_plugins: Plugin[];
_pythonPlugins: any[];
_pythonPlugins: PythonPlugin[];
constructor() {
this._plugins = [];
@@ -138,7 +146,7 @@ export class PluginManager {
for (const p of plugins) this._plugins.push(p);
}
addPythonPlugin(plugin: any) {
addPythonPlugin(plugin: PythonPlugin) {
this._pythonPlugins.push(plugin);
}
@@ -179,8 +187,7 @@ export class PluginManager {
async beforePyScriptExec(options: { interpreter: InterpreterClient; src: string; pyScriptTag: PyScriptTag }) {
for (const p of this._plugins) p.beforePyScriptExec?.(options);
for (const p of this._pythonPlugins)
await p.beforePyScriptExec(options.interpreter, options.src, options.pyScriptTag);
for (const p of this._pythonPlugins) await p.beforePyScriptExec.callKwargs(options);
}
async afterPyScriptExec(options: {
@@ -191,8 +198,7 @@ export class PluginManager {
}) {
for (const p of this._plugins) p.afterPyScriptExec?.(options);
for (const p of this._pythonPlugins)
await p.afterPyScriptExec(options.interpreter, options.src, options.pyScriptTag, options.result);
for (const p of this._pythonPlugins) await p.afterPyScriptExec.callKwargs(options);
}
async beforePyReplExec(options: {
@@ -203,21 +209,13 @@ export class PluginManager {
}) {
for (const p of this._plugins) p.beforePyReplExec?.(options);
for (const p of this._pythonPlugins)
await p.beforePyReplExec?.(options.interpreter, options.src, options.outEl, options.pyReplTag);
for (const p of this._pythonPlugins) await p.beforePyReplExec?.callKwargs(options);
}
async afterPyReplExec(options: { interpreter: InterpreterClient; src: string; outEl; pyReplTag; result }) {
for (const p of this._plugins) p.afterPyReplExec?.(options);
for (const p of this._pythonPlugins)
await p.afterPyReplExec?.(
options.interpreter,
options.src,
options.outEl,
options.pyReplTag,
options.result,
);
for (const p of this._pythonPlugins) await p.afterPyReplExec?.callKwargs(options);
}
async onUserError(error: UserError) {
@@ -227,6 +225,9 @@ export class PluginManager {
}
}
type PyElementInstance = { connect(): void };
type PyElementClass = (htmlElement: HTMLElement) => PyElementInstance;
/**
* Defines a new CustomElement (via customElement.defines) with `tag`,
* where the new CustomElement is a proxy that delegates the logic to
@@ -238,12 +239,12 @@ export class PluginManager {
* received by the newly created CustomElement will be
* delegated to that instance.
*/
export function define_custom_element(tag: string, pyPluginClass: any): any {
export function define_custom_element(tag: string, pyElementClass: PyElementClass): any {
logger.info(`creating plugin: ${tag}`);
class ProxyCustomElement extends HTMLElement {
shadow: ShadowRoot;
wrapper: HTMLElement;
pyPluginInstance: any;
pyElementInstance: PyElementInstance;
originalInnerHTML: string;
constructor() {
@@ -254,11 +255,11 @@ export function define_custom_element(tag: string, pyPluginClass: any): any {
this.wrapper = document.createElement('slot');
this.shadow.appendChild(this.wrapper);
this.originalInnerHTML = this.innerHTML;
this.pyPluginInstance = pyPluginClass(this);
this.pyElementInstance = pyElementClass(this);
}
connectedCallback() {
const innerHTML = this.pyPluginInstance.connect();
const innerHTML = this.pyElementInstance.connect();
if (typeof innerHTML === 'string') this.innerHTML = innerHTML;
}
}

View File

@@ -50,7 +50,7 @@ export class StdioDirector extends Plugin {
interpreter: InterpreterClient;
src: string;
pyScriptTag: PyScriptTag;
result: any; // eslint-disable-line @typescript-eslint/no-explicit-any
result: any;
}): void {
if (options.pyScriptTag.stdout_manager != null) {
this._stdioMultiplexer.removeListener(options.pyScriptTag.stdout_manager);
@@ -99,7 +99,7 @@ export class StdioDirector extends Plugin {
src: string;
outEl: HTMLElement;
pyReplTag: InstanceType<ReturnType<typeof make_PyRepl>>;
result: any; // eslint-disable-line @typescript-eslint/no-explicit-any
result: any;
}): Promise<void> {
// display the value of the last-evaluated expression in the REPL
if (options.result !== undefined) {

View File

@@ -6,7 +6,6 @@ import { UserError, ErrorCode } from './exceptions';
const logger = getLogger('py-config');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export interface AppConfig extends Record<string, any> {
name?: string;
description?: string;
@@ -107,7 +106,6 @@ function fillUserData(inputConfig: AppConfig, resultConfig: AppConfig): AppConfi
for (const key in inputConfig) {
// fill in all extra keys ignored by the validator
if (!(key in defaultConfig)) {
// eslint-disable-next-line
resultConfig[key] = inputConfig[key];
}
}
@@ -127,11 +125,9 @@ function mergeConfig(inlineConfig: AppConfig, externalConfig: AppConfig): AppCon
for (const [keyType, keys] of allKeys) {
keys.forEach(function (item: string) {
if (keyType === 'boolean') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
merged[item] =
typeof inlineConfig[item] !== 'undefined' ? inlineConfig[item] : externalConfig[item];
} else {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
merged[item] = inlineConfig[item] || externalConfig[item];
}
});
@@ -200,7 +196,6 @@ function validateConfig(configText: string, configType = 'toml') {
const interpreterConfig: InterpreterConfig = {};
for (const eachInterpreterParam in eachInterpreter) {
if (validateParamInConfig(eachInterpreterParam, 'string', eachInterpreter)) {
// eslint-disable-next-line
interpreterConfig[eachInterpreterParam] = eachInterpreter[eachInterpreterParam];
}
}
@@ -224,7 +219,6 @@ function validateConfig(configText: string, configType = 'toml') {
const interpreterConfig: InterpreterConfig = {};
for (const eachInterpreterParam in eachInterpreter) {
if (validateParamInConfig(eachInterpreterParam, 'string', eachInterpreter)) {
// eslint-disable-next-line
interpreterConfig[eachInterpreterParam] = eachInterpreter[eachInterpreterParam];
}
}
@@ -238,14 +232,12 @@ function validateConfig(configText: string, configType = 'toml') {
for (const eachFetchConfigParam in eachFetch) {
const targetType = eachFetchConfigParam === 'files' ? 'array' : 'string';
if (validateParamInConfig(eachFetchConfigParam, targetType, eachFetch)) {
// eslint-disable-next-line
eachFetchConfig[eachFetchConfigParam] = eachFetch[eachFetchConfigParam];
}
}
finalConfig[item].push(eachFetchConfig);
});
} else {
// eslint-disable-next-line
finalConfig[item] = config[item];
}
}

View File

@@ -10,7 +10,6 @@ export async function pyExec(
interpreter: InterpreterClient,
pysrc: string,
outElem: HTMLElement,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Promise<{ result: any }> {
ensureUniqueId(outElem);
if (await interpreter._remote.pyscript_py.uses_top_level_await(pysrc)) {
@@ -46,7 +45,6 @@ export async function pyExec(
* pyDisplay(interpreter, obj);
* pyDisplay(interpreter, obj, { target: targetID });
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export async function pyDisplay(interpreter: InterpreterClient, obj: any, kwargs: { [k: string]: any } = {}) {
const display = (await interpreter.globals.get('display')) as PyProxyCallable;
try {

View File

@@ -106,11 +106,10 @@ export class RemoteInterpreter extends Object {
fullStdLib: false,
}),
);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
this.FS = this.interface.FS;
// eslint-disable-next-line
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
this.PATH = (this.interface as any)._module.PATH;
// eslint-disable-next-line
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
this.PATH_FS = (this.interface as any)._module.PATH_FS;
// TODO: Remove this once `runtimes` is removed!
@@ -270,10 +269,8 @@ export class RemoteInterpreter extends Object {
return Synclink.proxy(this.interface.pyimport(mod_name));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
setHandler(func_name: string, handler: any): void {
const pyscript_module = this.interface.pyimport('pyscript');
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
pyscript_module[func_name] = handler;
}
}