Add more type definitions (#882)

* More typing to base.ts

* Add more types

* More types
This commit is contained in:
Fábio Rosado
2022-10-27 23:48:28 +01:00
committed by GitHub
parent 4850f39b5a
commit 1c53d91c6b
13 changed files with 115 additions and 29 deletions

View File

@@ -22,6 +22,7 @@
"@rollup/plugin-legacy": "2.2.0",
"@rollup/plugin-node-resolve": "14.1.0",
"@rollup/plugin-typescript": "8.5.0",
"@types/codemirror": "^5.60.5",
"@types/jest": "29.1.2",
"@types/node": "18.8.3",
"@typescript-eslint/eslint-plugin": "5.39.0",
@@ -1510,6 +1511,15 @@
"@babel/types": "^7.3.0"
}
},
"node_modules/@types/codemirror": {
"version": "5.60.5",
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.5.tgz",
"integrity": "sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==",
"dev": true,
"dependencies": {
"@types/tern": "*"
}
},
"node_modules/@types/estree": {
"version": "0.0.39",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
@@ -1628,6 +1638,15 @@
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
"dev": true
},
"node_modules/@types/tern": {
"version": "0.23.4",
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz",
"integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==",
"dev": true,
"dependencies": {
"@types/estree": "*"
}
},
"node_modules/@types/tough-cookie": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz",
@@ -7364,6 +7383,15 @@
"@babel/types": "^7.3.0"
}
},
"@types/codemirror": {
"version": "5.60.5",
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.5.tgz",
"integrity": "sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==",
"dev": true,
"requires": {
"@types/tern": "*"
}
},
"@types/estree": {
"version": "0.0.39",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
@@ -7482,6 +7510,15 @@
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
"dev": true
},
"@types/tern": {
"version": "0.23.4",
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz",
"integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==",
"dev": true,
"requires": {
"@types/estree": "*"
}
},
"@types/tough-cookie": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz",

View File

@@ -20,6 +20,7 @@
"@rollup/plugin-legacy": "2.2.0",
"@rollup/plugin-node-resolve": "14.1.0",
"@rollup/plugin-typescript": "8.5.0",
"@types/codemirror": "^5.60.5",
"@types/jest": "29.1.2",
"@types/node": "18.8.3",
"@typescript-eslint/eslint-plugin": "5.39.0",

View File

@@ -1,7 +1,7 @@
import { basicSetup, EditorView } from 'codemirror';
import { python } from '@codemirror/lang-python';
import { indentUnit } from '@codemirror/language'
import { Compartment, StateCommand } from '@codemirror/state';
import { Compartment } from '@codemirror/state';
import { keymap } from '@codemirror/view';
import { defaultKeymap } from '@codemirror/commands';
import { oneDarkTheme } from '@codemirror/theme-one-dark';

View File

@@ -1,4 +1,4 @@
import { addClasses, htmlDecode, ensureUniqueId } from '../utils';
import { addClasses, htmlDecode } from '../utils';
export class PyTitle extends HTMLElement {
widths: string[];

View File

@@ -1,4 +1,5 @@
import type { Runtime } from '../runtime';
import type {PyProxy} from "pyodide"
import { getLogger } from '../logger';
const logger = getLogger('py-register-widget');
@@ -12,7 +13,7 @@ function createWidget(runtime: Runtime, name: string, code: string, klass: strin
name: string = name;
klass: string = klass;
code: string = code;
proxy: any;
proxy: PyProxy;
proxyClass: any;
constructor() {
@@ -38,7 +39,9 @@ function createWidget(runtime: Runtime, name: string, code: string, klass: strin
runtime.globals.set(this.id, this.proxy);
}
}
/* eslint-disable @typescript-eslint/no-unused-vars */
const xPyWidget = customElements.define(name, CustomWidget);
/* eslint-enable @typescript-eslint/no-unused-vars */
}
export function make_PyWidget(runtime: Runtime) {

View File

@@ -24,10 +24,10 @@
*/
interface Logger {
debug(message: string, ...args: any[]): void;
info(message: string, ...args: any[]): void;
warn(message: string, ...args: any[]): void;
error(message: string, ...args: any[]): void;
debug(message: string, ...args: unknown[]): void;
info(message: string, ...args: unknown[]): void;
warn(message: string, ...args: unknown[]): void;
error(message: string, ...args: unknown[]): void;
}
const _cache = new Map<string, Logger>();
@@ -46,7 +46,7 @@ function _makeLogger(prefix: string): Logger {
function make(level: string) {
const out_fn = console[level].bind(console);
function fn(fmt: string, ...args: any[]) {
function fn(fmt: string, ...args: unknown[]) {
out_fn(prefix + fmt, ...args);
}
return fn

View File

@@ -10,6 +10,11 @@ import { getLogger } from './logger';
import { handleFetchError, showError, globalExport } from './utils'
import { createCustomElements } from './components/elements';
type ImportType = { [key: string]: unknown }
type ImportMapType = {
imports: ImportType | null
}
const logger = getLogger('pyscript/main');
@@ -69,7 +74,7 @@ class PyScriptApp {
// and show a big error. PRs welcome :)
logger.info('searching for <py-config>');
const elements = document.getElementsByTagName('py-config');
let el = null;
let el: Element | null = null;
if (elements.length > 0)
el = elements[0];
if (elements.length >= 2) {
@@ -188,7 +193,7 @@ class PyScriptApp {
// lifecycle (7)
executeScripts(runtime: Runtime) {
this.register_importmap(runtime);
void this.register_importmap(runtime);
this.PyScript = make_PyScript(runtime);
customElements.define('py-script', this.PyScript);
}
@@ -207,9 +212,9 @@ class PyScriptApp {
// inside py-script. It's also unclear whether we want to wait or not
// (or maybe only wait only if we do an actual 'import'?)
for (const node of document.querySelectorAll("script[type='importmap']")) {
const importmap = (() => {
const importmap: ImportMapType = (() => {
try {
return JSON.parse(node.textContent);
return JSON.parse(node.textContent) as ImportMapType;
} catch {
return null;
}
@@ -224,7 +229,7 @@ class PyScriptApp {
try {
// XXX: pyodide doesn't like Module(), failing with
// "can't read 'name' of undefined" at import time
exports = { ...(await import(url)) };
exports = { ...(await import(url)) } as object;
} catch {
logger.warn(`failed to fetch '${url}' for '${name}'`);
continue;

View File

@@ -56,8 +56,8 @@ export const defaultConfig: AppConfig = {
export function loadConfigFromElement(el: Element): AppConfig {
let srcConfig;
let inlineConfig;
let srcConfig: AppConfig;
let inlineConfig: AppConfig;
if (el === null) {
srcConfig = {};
inlineConfig = {};
@@ -127,7 +127,7 @@ function mergeConfig(inlineConfig: AppConfig, externalConfig: AppConfig): AppCon
for (const keyType in allKeys)
{
const keys = allKeys[keyType];
const keys: string[] = allKeys[keyType];
keys.forEach(function(item: string){
if (keyType === "boolean")
{
@@ -199,14 +199,14 @@ function validateConfig(configText: string, configType = "toml") {
for (const keyType in allKeys)
{
const keys = allKeys[keyType];
const keys: string[] = allKeys[keyType];
keys.forEach(function(item: string){
if (validateParamInConfig(item, keyType, config))
{
if (item === "runtimes")
{
finalConfig[item] = [];
const runtimes = config[item];
const runtimes = config[item] as object[];
runtimes.forEach(function(eachRuntime: object){
const runtimeConfig: object = {};
for (const eachRuntimeParam in eachRuntime)

View File

@@ -1,5 +1,5 @@
import { getLogger } from './logger';
import { ensureUniqueId, addClasses } from './utils';
import { ensureUniqueId } from './utils';
import type { Runtime } from './runtime';
const logger = getLogger('pyexec');

View File

@@ -1,6 +1,6 @@
import { Runtime } from './runtime';
import { getLogger } from './logger';
import type { loadPyodide as loadPyodideDeclaration, PyodideInterface } from 'pyodide';
import type { loadPyodide as loadPyodideDeclaration, PyodideInterface, PyProxy } from 'pyodide';
// eslint-disable-next-line
// @ts-ignore
import pyscript from './python/pyscript.py';
@@ -10,12 +10,17 @@ declare const loadPyodide: typeof loadPyodideDeclaration;
const logger = getLogger('pyscript/pyodide');
interface Micropip {
install: (packageName: string | string[]) => Promise<void>;
destroy: () => void;
}
export class PyodideRuntime extends Runtime {
src: string;
name?: string;
lang?: string;
interpreter: PyodideInterface;
globals: any;
globals: PyProxy;
constructor(
config: AppConfig,
@@ -83,7 +88,7 @@ export class PyodideRuntime extends Runtime {
async installPackage(package_name: string | string[]): Promise<void> {
if (package_name.length > 0) {
logger.info(`micropip install ${package_name.toString()}`);
const micropip = this.globals.get('micropip');
const micropip = this.globals.get('micropip') as Micropip;
await micropip.install(package_name);
micropip.destroy();
}

View File

@@ -1,5 +1,5 @@
import type { AppConfig } from './pyconfig';
import type { PyodideInterface } from 'pyodide';
import type { PyodideInterface, PyProxy } from 'pyodide';
import { getLogger } from './logger';
const logger = getLogger('pyscript/runtime');
@@ -35,7 +35,7 @@ export abstract class Runtime extends Object {
/**
* global symbols table for the underlying interpreter.
* */
abstract globals: any;
abstract globals: PyProxy;
constructor(config: AppConfig) {
super();
@@ -54,7 +54,7 @@ export abstract class Runtime extends Object {
* (asynchronously) which can call its own API behind the scenes.
* Python exceptions are turned into JS exceptions.
* */
abstract run(code: string): Promise<any>;
abstract run(code: string): Promise<unknown>;
/**
* Same as run, but Python exceptions are not propagated: instead, they
@@ -63,9 +63,10 @@ export abstract class Runtime extends Object {
* This is a bad API and should be killed/refactored/changed eventually,
* but for now we have code which relies on it.
* */
async runButDontRaise(code: string): Promise<any> {
async runButDontRaise(code: string): Promise<unknown> {
return this.run(code).catch(err => {
logger.error(err);
const error = err as Error
logger.error("Error:", error);
});
}

View File

@@ -37,7 +37,7 @@ export function ltrim(code: string): string {
let _uniqueIdCounter = 0;
export function ensureUniqueId(el: HTMLElement) {
if (el.id === "")
el.id = "py-internal-" + _uniqueIdCounter++;
el.id = `py-internal-${_uniqueIdCounter++}`;
}
/*
@@ -94,7 +94,7 @@ export function inJest(): boolean {
return typeof process === 'object' && process.env.JEST_WORKER_ID !== undefined;
}
export function globalExport(name: string, obj: any) {
export function globalExport(name: string, obj: object) {
// attach the given object to the global object, so that it is globally
// visible everywhere. Should be used very sparingly!

View File

@@ -0,0 +1,34 @@
import { jest } from "@jest/globals"
import { ensureUniqueId } from "../../src/utils"
describe("Utils", () => {
let element: HTMLElement;
beforeEach(() => {
element = document.createElement("div");
})
it("ensureUniqueId sets unique id on element", async () => {
expect(element.id).toBe("")
ensureUniqueId(element)
expect(element.id).toBe("py-internal-0")
})
it("ensureUniqueId sets unique id with increasing counter", async () => {
const secondElement = document.createElement("div")
expect(element.id).toBe("")
expect(secondElement.id).toBe("")
ensureUniqueId(element)
ensureUniqueId(secondElement)
// The counter will have been incremented on
// the previous test, make sure it keeps increasing
expect(element.id).toBe("py-internal-1")
expect(secondElement.id).toBe("py-internal-2")
})
})