Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
07900ef
Refactor python part for flexibility
winniederidder Mar 30, 2022
ba46118
Rename BackendEvent and refactor workers
winniederidder Mar 30, 2022
b7082a4
Implement pubsub system for events
winniederidder Mar 30, 2022
d5f34ea
Rename and refactor running code
winniederidder Mar 30, 2022
59094a2
Cleanup to initializing input handlers
winniederidder Mar 30, 2022
4ee6906
Reduce constructor params
winniederidder Mar 30, 2022
2fa34d8
Fix typo
winniederidder Mar 30, 2022
83752a9
Refactor to use coderunner
winniederidder Mar 30, 2022
46f6476
Add last parts of refactor
winniederidder Mar 30, 2022
beda633
Move channel to BackendManager
winniederidder Mar 30, 2022
eae89ce
New packages
winniederidder Mar 31, 2022
ceff1e3
Send input in the right way
winniederidder Mar 31, 2022
de96039
Fix configure input
winniederidder Mar 31, 2022
a5e824e
Use SyncClient
winniederidder Mar 31, 2022
6c08493
Use syncExpose
winniederidder Mar 31, 2022
29ea11f
Use pyodideExpose
winniederidder Mar 31, 2022
9b7e688
Add generic methods to easily expose methods for SyncClient
winniederidder Mar 31, 2022
c0d380c
Docs for new methods
winniederidder Mar 31, 2022
5b22cf0
Delay autocompletion until loaded
winniederidder Mar 31, 2022
f523551
Add support for sleep
winniederidder Mar 31, 2022
b6996ae
First version of proper interrupts
winniederidder Mar 31, 2022
34949ac
Spacing
winniederidder Mar 31, 2022
9a20e20
Add url-loader dependency for python tar
winniederidder Mar 31, 2022
bb34996
Use tar archive for python code
winniederidder Mar 31, 2022
d2364ba
Add and update scripts to build and use python tar package
winniederidder Mar 31, 2022
4536d9e
Allow proper building and bundling
winniederidder Apr 1, 2022
7e62bc1
Upgrade webpack
winniederidder Apr 1, 2022
7ef3813
Gitignore and correct location
winniederidder Apr 1, 2022
57bc895
Rename file and split python files
winniederidder Apr 1, 2022
a438d20
Remove autoreload as it's not practical
winniederidder Apr 2, 2022
2889384
Improve scripts
winniederidder Apr 2, 2022
fb6519d
Fix the await location
winniederidder Apr 2, 2022
119391f
Fix GHA
winniederidder Apr 2, 2022
2de8679
Fix GHA again
winniederidder Apr 2, 2022
a056016
Change how files are copied
winniederidder Apr 2, 2022
49f723e
Less useless conversion calls
winniederidder Apr 2, 2022
df17663
Less parsing
winniederidder Apr 2, 2022
3163cea
Fix button
winniederidder Apr 2, 2022
a27ecac
More flexible parsing
winniederidder Apr 2, 2022
f983262
better content type handling
winniederidder Apr 2, 2022
8b90954
Better use of Python package
winniederidder Apr 2, 2022
bd46ffd
Cleanup autocomplete and proper installs
winniederidder Apr 2, 2022
548776d
Remove some unwanted files from the tar ~3MB
winniederidder Apr 2, 2022
5de93fb
Change how things are bundled
winniederidder Apr 3, 2022
8680810
Add service worker to dev build again
winniederidder Apr 3, 2022
1d35989
Raw loader makes more sense until proper url handling is possible
winniederidder Apr 3, 2022
6c8952b
Refactor and allow adding new backends at runtime
winniederidder Apr 4, 2022
83c390b
Refactor with new version of python_runner
winniederidder Apr 4, 2022
5e11c67
Log and fix
winniederidder Apr 4, 2022
90f5aef
Remove direct export as it can't be imported like that anyway
winniederidder Apr 4, 2022
6fc3b27
Enable run button faster, better restart
winniederidder Apr 4, 2022
e93ffef
Better event and interrupt handling
winniederidder Apr 4, 2022
6979f0c
Use new package versions
winniederidder Apr 5, 2022
436652b
Remove timing since it's now a Promise that is awaited later
winniederidder Apr 5, 2022
2139b24
Use python script to generate compressed tar
winniederidder Apr 5, 2022
7d5583d
Also catch hidden keyboardinterrupts
winniederidder Apr 5, 2022
e9d6f16
Fix separate builds again
winniederidder Apr 5, 2022
d6e84e1
Update build script to make tar accessible
winniederidder Apr 5, 2022
f172a4e
Add tar to github
winniederidder Apr 5, 2022
9bd3032
Fix to_py and exposing
winniederidder Apr 7, 2022
6b82b40
Fix build
winniederidder Apr 12, 2022
b272fc8
Better resizing
winniederidder Apr 12, 2022
cc563df
Merge branch 'main' into upgrade-workers
winniederidder Apr 14, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .github/workflows/deploy-pages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v2.3.1
- name: Install and Build 🔧
# Ensure public files are available when hosted as a web application
# Last step ensures public files are available when hosting the web application
run: |
rm -rf dist/
cp -r public/ dist
yarn install
yarn build
yarn build:app
cp -r public/* dist
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.1.5
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Install and Build 🔧
run: |
yarn install
yarn build
yarn build:library
- name: Publish @dodona/papyros to NPM
uses: JS-DevTools/npm-publish@v1
with:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ yarn-error.log*

# script outputs
translationIssues.txt

src/workers/python/python_package/
19 changes: 12 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dodona/papyros",
"version": "0.1.90",
"version": "0.1.925-tar",
"private": false,
"homepage": ".",
"devDependencies": {
Expand Down Expand Up @@ -33,9 +33,10 @@
"ts-jest": "^27.0.7",
"ts-loader": "^9.2.6",
"typescript": "^4.1.2",
"webpack": "^5.64.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.6.0",
"url-loader": "^4.1.1",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4",
"worker-loader": "^3.0.8"
},
"dependencies": {
Expand All @@ -53,13 +54,17 @@
"@codemirror/search": "^0.19.3",
"@codemirror/state": "^0.19.6",
"comlink": "^4.3.1",
"comsync": "^0.0.7",
"escape-html": "^1.0.3",
"i18n-js": "^3.8.0",
"sync-message": "^0.0.8"
"pyodide-worker-runner": "^0.0.8",
"sync-message": "^0.0.9"
},
"scripts": {
"start": "webpack serve --mode development",
"build": "webpack build --mode production",
"start": "yarn setup && webpack serve --mode development",
"setup": "bash scripts/setup.sh",
"build:app": "bash scripts/build_package.sh development",
"build:library": "bash scripts/build_package.sh production",
"test": "echo No tests defined yet",
"lint": "eslint --ext '.js' --ext '.ts' src",
"validate:translations": "node scripts/ValidateTranslations.js"
Expand Down
4 changes: 4 additions & 0 deletions scripts/build_package.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
rm -rf dist
bash ./scripts/setup.sh
webpack build --mode=$1
5 changes: 5 additions & 0 deletions scripts/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash
cd src/workers/python
python3.9 build_package.py


5 changes: 4 additions & 1 deletion src/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
import { Papyros } from "./Papyros";
import { InputMode } from "./InputManager";
import { getElement } from "./util/Util";
import { papyrosLog, LogType } from "./util/Logging";
import { BackendManager } from "./BackendManager";


async function startPapyros(): Promise<void> {
Expand All @@ -28,11 +30,12 @@ async function startPapyros(): Promise<void> {
}
});
// Try to configure synchronous input mechanism
if (!await papyros.configureInput(location.href, DEFAULT_SERVICE_WORKER, false)) {
if (!await papyros.configureInput(location.href, DEFAULT_SERVICE_WORKER)) {
getElement(MAIN_APP_ID).innerHTML =
"Your browser is unsupported.\n" +
"Please use a modern version of Chrome, Safari, Firefox, ...";
} else { // Start actual application
papyrosLog(LogType.Debug, "Using channel: ", BackendManager.channel);
papyros.launch();
}
}
Expand Down
77 changes: 30 additions & 47 deletions src/Backend.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PapyrosEvent } from "./PapyrosEvent";
import { Channel, readMessage, uuidv4 } from "sync-message";
import { parseData } from "./util/Util";
import { CompletionContext, CompletionResult } from "@codemirror/autocomplete";
import { BackendEvent, BackendEventType } from "./BackendEvent";
import { papyrosLog, LogType } from "./util/Logging";
import { syncExpose, SyncExtras } from "comsync";

/**
* Interface to represent the CodeMirror CompletionContext in a worker
Expand Down Expand Up @@ -37,80 +37,61 @@ export interface WorkerAutocompleteContext {
} | null;
}

export abstract class Backend {
protected onEvent: (e: PapyrosEvent) => any;
protected runId: number;

export abstract class Backend<Extras extends SyncExtras=SyncExtras> {
protected extras: Extras;
protected onEvent: (e: BackendEvent) => any;
/**
* Constructor is limited as it is meant to be used as a WebWorker
* These are then exposed via Comlink. Proper initialization occurs
* in the launch method when the worker is started
* Constructor is limited as it is meant to be used as a WebWorker
* Proper initialization occurs in the launch method when the worker is started
* Synchronously exposing methods should be done here
*/
constructor() {
this.extras = {} as Extras;
// eslint-disable-next-line @typescript-eslint/no-empty-function
this.onEvent = () => { };
this.runId = 0;
this.runCode = this.syncExpose()(this.runCode.bind(this));
}

/**
* @return {any} The function to expose methods for Comsync to allow interrupting
*/
protected syncExpose(): any {
return syncExpose;
}

/**
* Initialize the backend by doing all setup-related work
* @param {function(PapyrosEvent):void} onEvent Callback for when events occur
* @param {Channel} channel for communication with the main thread
* @param {function(BackendEvent):void} onEvent Callback for when events occur
* @return {Promise<void>} Promise of launching
*/
launch(
onEvent: (e: PapyrosEvent) => void,
channel: Channel
onEvent: (e: BackendEvent) => void
): Promise<void> {
// Input messages are handled in a special way
// In order to link input requests to their responses
// An ID is required to make the connection
// The message must be read in the worker to not stall the main thread
const onInput = (e: PapyrosEvent): string => {
const inputData = parseData(e.data, e.contentType);
const messageId = uuidv4();
inputData.messageId = messageId;
e.data = JSON.stringify(inputData);
e.contentType = "text/json";
this.onEvent = (e: BackendEvent) => {
onEvent(e);
return readMessage(channel, messageId);
};
this.onEvent = (e: PapyrosEvent) => {
e.runId = this.runId;
if (e.type === "input") {
return onInput(e);
} else {
return onEvent(e);
if (e.type === BackendEventType.Sleep) {
return this.extras.syncSleep(e.data);
} else if (e.type === BackendEventType.Input) {
return this.extras.readMessage();
}
};
return Promise.resolve();
}

/**
* Internal helper method that actually executes the code
* Results or Errors must be passed by using the onEvent-callback
* @param code The code to run
*/
protected abstract _runCodeInternal(code: string): Promise<any>;

/**
* Executes the given code
* @param {Extras} extras Helper properties to run code
* @param {string} code The code to run
* @param {string} runId The uuid for this execution
* @return {Promise<void>} Promise of execution
*/
async runCode(code: string, runId: number): Promise<any> {
this.runId = runId;
return await this._runCodeInternal(code);
}
abstract runCode(extras: Extras, code: string): Promise<void>;

/**
* Converts the context to a cloneable object containing useful properties
* to generate autocompletion suggestions with
* Class instances are not passable to workers, so we extract the useful information
* @param {CompletionContext} context Current context to autocomplete for
* @param {RegExp} expr Expression to match the previous token with
* default a word with an optional dot to represent property access
* @return {WorkerAutocompleteContext} Completion context that can be passed as a message
*/
static convertCompletionContext(context: CompletionContext, expr = /\w*(\.)?/):
Expand All @@ -120,14 +101,16 @@ export abstract class Backend {
return [line.number, (range.head - line.from)];
})[0];
const beforeMatch = context.matchBefore(expr);
return {
const ret = {
explicit: context.explicit,
before: beforeMatch,
pos: context.pos,
column: column,
line: lineNr,
text: context.state.doc.toString()
};
papyrosLog(LogType.Debug, "Worker completion context:", ret);
return ret;
}

/**
Expand Down
38 changes: 38 additions & 0 deletions src/BackendEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Enum representing all possible types for supported events
*/
export enum BackendEventType {
Start = "start",
End = "end",
Input = "input",
Output = "output",
Sleep = "sleep",
Error = "error",
Interrupt = "interrupt"
}
/**
* All possible types for ease of iteration
*/
export const BACKEND_EVENT_TYPES = [
BackendEventType.Start, BackendEventType.End,
BackendEventType.Input, BackendEventType.Output,
BackendEventType.Sleep, BackendEventType.Error,
BackendEventType.Interrupt
];
/**
* Interface for events used for communication between threads
*/
export interface BackendEvent {
/**
* The type of action generating this event
*/
type: BackendEventType;
/**
* The actual data stored in this event
*/
data: any;
/**
* The format used for the data to help with parsing
*/
contentType?: string;
}
Loading