Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

📦 Add myst-execute package #866

Merged
merged 29 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
61dd857
📦 Add myst-execute package
fwkoch Jan 23, 2024
103af7c
📦 myst-execute 1.0.0 -> 0.0.0
fwkoch Jan 23, 2024
f812a76
wip: initial commit
agoose77 Jan 23, 2024
b24109c
test: check errors
agoose77 Jan 23, 2024
5015d3e
chore: run prettier
agoose77 Jan 23, 2024
7da16df
fix: run lint
agoose77 Jan 23, 2024
fff8a3a
ci: setup Python and Jupyter Server
agoose77 Jan 23, 2024
fdbb2ff
chore: add which
agoose77 Jan 23, 2024
284625f
feat: add jupyter-server and ipykernel
agoose77 Jan 23, 2024
e0179f6
chore: add dependency path
agoose77 Jan 23, 2024
5ce6709
docs: update README
agoose77 Jan 23, 2024
d17aba3
chore: run prettier
agoose77 Jan 23, 2024
37ee3dc
fix: polyfill fetch for node16
agoose77 Jan 24, 2024
1e5833e
test: extend timeout
agoose77 Jan 24, 2024
c9b82a7
refactor: split out caching
agoose77 Jan 24, 2024
8e0be5c
fix: export server settings type
agoose77 Jan 24, 2024
a4cb263
fix: export expression type
agoose77 Jan 24, 2024
399107c
fix: allow sessionManager to fail to resolve
agoose77 Jan 24, 2024
0d313fd
feat: let missing kernel throw error
agoose77 Jan 24, 2024
299553e
refactor: move type definitions
agoose77 Feb 1, 2024
a9a041d
fix: don't run transform if we have no code blocks
agoose77 Jan 24, 2024
3aac6a6
refactor: earlier error
agoose77 Jan 24, 2024
50eb3c9
chore: run linter
agoose77 Jan 24, 2024
74bb509
chore: add changeset
agoose77 Jan 24, 2024
db5625a
feat: make findExistingJupyterServer async
agoose77 Jan 29, 2024
fa12b41
fix: drop changes to Python package metadata
agoose77 Feb 1, 2024
a2e3049
Update packages/myst-execute/src/manager.ts
agoose77 Feb 1, 2024
1b4cbba
Update packages/myst-execute/src/execute.ts
agoose77 Feb 1, 2024
b0bdd1f
chore: drop console logging
agoose77 Feb 1, 2024
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
5 changes: 5 additions & 0 deletions .changeset/khaki-tomatoes-remain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'myst-execute': patch
---

Add myst-execute package
6 changes: 6 additions & 0 deletions .changeset/thick-cups-hear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'myst-common': minor
'myst-cli': minor
---

Move IExpressionResult types to myst-common
2 changes: 2 additions & 0 deletions .github/requirements/requirements-execute.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
jupyter-server
ipykernel
7 changes: 7 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,12 @@ jobs:
with:
node-version: ${{ matrix.node }}
cache: 'npm'
# Setup Python for ipykernel & jupyter-server
- uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
cache-dependency-path: '.github/requirements/requirements-execute.txt'
- run: python -m pip install -r .github/requirements/requirements-execute.txt
- run: npm install
- run: npm run test
27 changes: 4 additions & 23 deletions packages/myst-cli/src/transforms/inlineExpressions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { GenericNode, GenericParent } from 'myst-common';
import type { GenericNode, GenericParent, IExpressionResult } from 'myst-common';
import { fileWarn, NotebookCell, RuleId } from 'myst-common';
import { selectAll } from 'unist-util-select';
import type { InlineExpression } from 'myst-spec-ext';
Expand All @@ -10,25 +10,6 @@ import { BASE64_HEADER_SPLIT } from './images.js';

export const metadataSection = 'user_expressions';

export interface IBaseExpressionResult {
status: string;
}

export interface IExpressionOutput extends IBaseExpressionResult {
status: 'ok';
data: Record<string, string>;
metadata: Record<string, string>;
}

export interface IExpressionError extends IBaseExpressionResult {
status: 'error';
traceback: string[];
ename: string;
evalue: string;
}

export type IExpressionResult = IExpressionError | IExpressionOutput;

export interface IUserExpressionMetadata {
expression: string;
result: IExpressionResult;
Expand Down Expand Up @@ -69,11 +50,11 @@ function renderExpression(node: InlineExpression, file: VFile): StaticPhrasingCo
},
];
} else if (mimeType === 'text/latex') {
content = [{ type: 'inlineMath', value: processLatex(value) }];
content = [{ type: 'inlineMath', value: processLatex(value as string) }];
} else if (mimeType === 'text/html') {
content = [{ type: 'html', value }];
content = [{ type: 'html', value: value as string }];
} else if (mimeType === 'text/plain') {
content = [{ type: 'text', value }];
content = [{ type: 'text', value: value as string }];
}
});
if (content) return content;
Expand Down
6 changes: 4 additions & 2 deletions packages/myst-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
"vfile-message": "^3.0.0"
},
"devDependencies": {
"myst-spec-ext": "^1.1.22",
"unist-builder": "3.0.0"
"myst-spec-ext": "^1.1.21",
"unist-builder": "3.0.0",
"@jupyterlab/nbformat": "^3.5.2",
"@lumino/coreutils": "^2.0.0"
}
}
1 change: 1 addition & 0 deletions packages/myst-common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export {
ParseTypesEnum,
TargetKind,
} from './types.js';
export type { IExpressionResult, IExpressionError, IExpressionOutput } from './types.js';
agoose77 marked this conversation as resolved.
Show resolved Hide resolved

export type { MessageInfo } from './utils.js';
export type {
Expand Down
28 changes: 27 additions & 1 deletion packages/myst-common/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { Plugin } from 'unified';
import type { Node, Directive, Role } from 'myst-spec';
import type { Directive, Node, Role } from 'myst-spec';
import type { VFile } from 'vfile';
import type * as nbformat from '@jupyterlab/nbformat';
import type { PartialJSONObject } from '@lumino/coreutils';

export type GenericNode<T extends Record<string, any> = Record<string, any>> = {
type: string;
Expand Down Expand Up @@ -151,3 +153,27 @@ export enum AdmonitionKind {
tip = 'tip',
warning = 'warning',
}

export interface IExpressionOutput {
status: 'ok';
data: nbformat.IMimeBundle;
metadata: PartialJSONObject;
}

export interface IExpressionError {
status: 'error';
/**
* Exception name
*/
ename: string;
/**
* Exception value
*/
evalue: string;
/**
* Traceback
*/
traceback: string[];
}

export type IExpressionResult = IExpressionError | IExpressionOutput;
4 changes: 4 additions & 0 deletions packages/myst-execute/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: ['curvenote'],
};
1 change: 1 addition & 0 deletions packages/myst-execute/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
./tests/execute
5 changes: 5 additions & 0 deletions packages/myst-execute/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# MyST Execute

Kernel execution of code and inline expressions using Jupyter.

This package provides a transform that takes a MyST tree, computes the executable content, and stores the results in the AST. It provides basic support for caching of outputs to avoid needless computation.
46 changes: 46 additions & 0 deletions packages/myst-execute/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "myst-execute",
"version": "0.0.0",
"sideEffects": false,
"license": "MIT",
"description": "Execute MyST content with Jupyter",
"author": "Franklin Koch <[email protected]>",
"homepage": "https://github.com/executablebooks/mystmd/tree/main/packages/myst-execution",
"type": "module",
"exports": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/executablebooks/mystmd.git"
},
"scripts": {
"clean": "rimraf dist",
"lint": "eslint \"src/**/!(*.spec).ts\" -c ./.eslintrc.cjs",
"lint:format": "npx prettier --check \"src/**/*.ts\"",
"test": "vitest run",
"test:watch": "vitest watch",
"build:esm": "tsc",
"build": "npm-run-all -l clean -p build:esm"
},
"bugs": {
"url": "https://github.com/executablebooks/mystmd/issues"
},
"dependencies": {
"myst-common": "^1.1.21",
"vfile": "^5.3.7",
"@jupyterlab/services": "^7.0.0",
"unist-util-select": "^4.0.3",
"which": "^4.0.0"
},
"devDependencies": {
"js-yaml": "^4.1.0",
"node-fetch": "^3.3.0",
"@jupyterlab/nbformat": "^3.5.2"
}
}
46 changes: 46 additions & 0 deletions packages/myst-execute/src/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import path from 'node:path';

export interface ICache<T> {
test(key: string): boolean;

get(key: string): T | undefined;

set(key: string, value: T): void;
}

/**
* An implementation of a basic cache
*/
export class LocalDiskCache<T> implements ICache<T> {
agoose77 marked this conversation as resolved.
Show resolved Hide resolved
constructor(cachePath: string) {
this._cachePath = cachePath;

if (!existsSync(cachePath)) {
mkdirSync(cachePath, { recursive: true });
}
}

private readonly _cachePath: string;

private _makeKeyPath(key: string): string {
return path.join(this._cachePath, `${key}.json`);
}

test(key: string): boolean {
return existsSync(this._makeKeyPath(key));
}

get(key: string): T | undefined {
const keyPath = this._makeKeyPath(key);
if (!existsSync(keyPath)) {
return undefined;
}
return JSON.parse(readFileSync(keyPath, { encoding: 'utf8' }));
}

set(key: string, item: T) {
const keyPath = this._makeKeyPath(key);
return writeFileSync(keyPath, JSON.stringify(item), { encoding: 'utf8' });
}
}
Loading
Loading