Skip to content

Commit

Permalink
Add more type definitions (#882)
Browse files Browse the repository at this point in the history
* More typing to base.ts

* Add more types

* More types
  • Loading branch information
FabioRosado committed Oct 27, 2022
1 parent 4850f39 commit 1c53d91
Show file tree
Hide file tree
Showing 13 changed files with 115 additions and 29 deletions.
37 changes: 37 additions & 0 deletions pyscriptjs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyscriptjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion pyscriptjs/src/components/pyrepl.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
2 changes: 1 addition & 1 deletion pyscriptjs/src/components/pytitle.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { addClasses, htmlDecode, ensureUniqueId } from '../utils';
import { addClasses, htmlDecode } from '../utils';

export class PyTitle extends HTMLElement {
widths: string[];
Expand Down
5 changes: 4 additions & 1 deletion pyscriptjs/src/components/pywidget.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Runtime } from '../runtime';
import type {PyProxy} from "pyodide"
import { getLogger } from '../logger';

const logger = getLogger('py-register-widget');
Expand All @@ -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() {
Expand All @@ -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) {
Expand Down
10 changes: 5 additions & 5 deletions pyscriptjs/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>();
Expand All @@ -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
Expand Down
15 changes: 10 additions & 5 deletions pyscriptjs/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
Expand All @@ -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;
}
Expand All @@ -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;
Expand Down
10 changes: 5 additions & 5 deletions pyscriptjs/src/pyconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {};
Expand Down Expand Up @@ -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")
{
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion pyscriptjs/src/pyexec.ts
Original file line number Diff line number Diff line change
@@ -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');
Expand Down
11 changes: 8 additions & 3 deletions pyscriptjs/src/pyodide.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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,
Expand Down Expand Up @@ -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();
}
Expand Down
11 changes: 6 additions & 5 deletions pyscriptjs/src/runtime.ts
Original file line number Diff line number Diff line change
@@ -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');
Expand Down Expand Up @@ -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();
Expand All @@ -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
Expand All @@ -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);
});
}

Expand Down
4 changes: 2 additions & 2 deletions pyscriptjs/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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++}`;
}

/*
Expand Down Expand Up @@ -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!

Expand Down
34 changes: 34 additions & 0 deletions pyscriptjs/tests/unit/utils.test.ts
Original file line number Diff line number Diff line change
@@ -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")
})
})

0 comments on commit 1c53d91

Please sign in to comment.