mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
Add more type definitions (#882)
* More typing to base.ts * Add more types * More types
This commit is contained in:
37
pyscriptjs/package-lock.json
generated
37
pyscriptjs/package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { addClasses, htmlDecode, ensureUniqueId } from '../utils';
|
||||
import { addClasses, htmlDecode } from '../utils';
|
||||
|
||||
export class PyTitle extends HTMLElement {
|
||||
widths: string[];
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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!
|
||||
|
||||
|
||||
34
pyscriptjs/tests/unit/utils.test.ts
Normal file
34
pyscriptjs/tests/unit/utils.test.ts
Normal 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")
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user