Skip to content

Commit

Permalink
fix filename in jlite
Browse files Browse the repository at this point in the history
  • Loading branch information
sglyon committed Jun 22, 2023
1 parent 0059076 commit c362a5b
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 49 deletions.
38 changes: 38 additions & 0 deletions dodo.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import os


def task_bump_version_patch():
Expand Down Expand Up @@ -28,13 +29,49 @@ def task_build():
}


def update_jlite_json_quickbuild():
jlite_config_path = "../web/public/jlite/jupyter-lite.json"
# first read in existing jupyter-lite.jsonfile
with open(jlite_config_path, "r") as f:
jlite = json.load(f)

# then find name of file starting with `remoteEntry.` within
# the ./jupyteach_jupyterlite_contents/labextension/static directory
remoteEntry = [
f
for f in os.listdir("./jupyteach_jupyterlite_contents/labextension/static")
if f.startswith("remoteEntry.")
][0]

# find the object within jlite['federated_extensions'] that has name == '@jupyteach/jupyterlite-contents'
ext = None
for e in jlite["jupyter-config-data"]["federated_extensions"]:
if e["name"] == "@jupyteach/jupyterlite-contents":
ext = e
break

if ext is None:
raise ValueError(
"Could not find @jupyteach/jupyterlite-contents in jupyter-lite.json"
)

# update the 'load' property of `ext` to match `static/{remoteEntry}`
ext["load"] = f"static/{remoteEntry}"

# now write out updated jupyter-lite-json file to jlite_config_path. Use indent=2
# to make it human readable
with open(jlite_config_path, "w") as f:
json.dump(jlite, f, indent=2)


def task_devbuild():
return {
"actions": [
"rm -rf _output",
"yarn run build:prod",
"jupyter lite build --force",
"rsync -av --delete ./_output/ ../web/public/jlite/",
update_jlite_json_quickbuild,
],
}

Expand All @@ -44,5 +81,6 @@ def task_quickbuild():
"actions": [
"yarn run build:prod",
"rsync -av --delete ./jupyteach_jupyterlite_contents/labextension/static/ ../web/public/jlite/extensions/@jupyteach/jupyterlite-contents/static/",
update_jlite_json_quickbuild,
],
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jupyteach/jupyterlite-contents",
"version": "0.1.9",
"version": "0.1.11",
"description": "A JupyterLite server extension.",
"keywords": [
"jupyter",
Expand Down Expand Up @@ -108,4 +108,4 @@
]
}
}
}
}
97 changes: 50 additions & 47 deletions src/contents.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Contents } from '@jupyterlite/contents';
import { Contents as ServerContents } from '@jupyterlab/services';
import { PathExt } from '@jupyterlab/coreutils';
import { ApolloClient, gql } from '@apollo/client/core';

const GET_NOTEBOOK_FRAGMENT = gql`
Expand All @@ -12,17 +11,6 @@ const GET_NOTEBOOK_FRAGMENT = gql`
}
`;

interface IContentResponseType {
content: any;
name: string;
last_modified: string;
created: string;
size: number;
mimetype: string;
type: ServerContents.ContentType;
filepath: string;
}

interface IContentBlock {
authorId: number;
createdAt: string;
Expand All @@ -36,26 +24,30 @@ interface IContentBlock {
updatedAt: string;
}

const extractNotebookIdAndKey = (
path: string
): { id: number | undefined; key: string | undefined } => {
const basename = PathExt.basename(path);
const match = basename.match(/(\d+)\.ipynb/);
if (match) {
const id = +match[1];
return { id, key: `ContentBlock:${id}` };
}
return { id: undefined, key: undefined };
};

export type IModel = ServerContents.IModel;
/**
* A class to handle requests to /api/contents
*/
export class JupyteachContents extends Contents {
requestId = 0;
responses: { [key: number]: IContentResponseType } = {};
apolloClient: ApolloClient<Record<string, unknown>> | undefined = undefined;
contentBlockIDToFileName: { [key: number]: string } = {};
fileNameToContentBlockID: { [key: string]: number } = {};

getIdAndKey = (

Check failure on line 36 in src/contents.ts

View workflow job for this annotation

GitHub Actions / build

Insert `{`
{fileName, contentBlockId}: {fileName?: string, contentBlockId?: number},

Check failure on line 37 in src/contents.ts

View workflow job for this annotation

GitHub Actions / build

Replace `{fileName,·contentBlockId}:·{fileName?:·string,·contentBlockId?:·number},` with `fileName,⏎····contentBlockId⏎··}:·{⏎····fileName?:·string;⏎····contentBlockId?:·number;`
): { id: number | undefined; key: string | undefined } => {

Check failure on line 38 in src/contents.ts

View workflow job for this annotation

GitHub Actions / build

Insert `}`
if (contentBlockId) {
return {id: contentBlockId, key: `ContentBlock:${contentBlockId}`};

Check failure on line 40 in src/contents.ts

View workflow job for this annotation

GitHub Actions / build

Replace `id:·contentBlockId,·key:·`ContentBlock:${contentBlockId}`` with `·id:·contentBlockId,·key:·`ContentBlock:${contentBlockId}`·`
}
if (fileName) {
// Try to access blockID in `fileNameToContentBlockID`
const blockID = this.fileNameToContentBlockID[fileName];
if (blockID) {
return {id: blockID, key: `ContentBlock:${blockID}`};

Check failure on line 46 in src/contents.ts

View workflow job for this annotation

GitHub Actions / build

Replace `id:·blockID,·key:·`ContentBlock:${blockID}`` with `·id:·blockID,·key:·`ContentBlock:${blockID}`·`
}
}
return {id: undefined, key: undefined};

Check failure on line 49 in src/contents.ts

View workflow job for this annotation

GitHub Actions / build

Replace `id:·undefined,·key:·undefined` with `·id:·undefined,·key:·undefined·`
};

/**
* Save a file.
Expand All @@ -71,18 +63,21 @@ export class JupyteachContents extends Contents {
): Promise<IModel | null> {
// call the superclass method
console.debug('[contents.ts] save', { path, options });
const out = super.save(path, options);
const { id, key } = extractNotebookIdAndKey(path);
const { id, key } = this.getIdAndKey({fileName: options.name});

Check failure on line 66 in src/contents.ts

View workflow job for this annotation

GitHub Actions / build

Replace `fileName:·options.name` with `·fileName:·options.name·`

if (this.apolloClient && id) {
this.apolloClient.cache.modify({
id: key,
fields: {
nbContent: (_) => options.content
nbContent: _ => options.content
}
})
console.debug('[contents.ts] save -- just called modify to update nbContent')
});
console.debug(
'[contents.ts] save -- just called modify to update nbContent'
);
}

const out = super.save(path, options);
return out;
}

Expand All @@ -106,7 +101,7 @@ export class JupyteachContents extends Contents {
options?: ServerContents.IFetchOptions | undefined
): Promise<ServerContents.IModel | null> {
// Try this...
const { id, key } = extractNotebookIdAndKey(path);
console.debug('[contents.ts] get', { path, options });
const url = new URL(window.location.href);
const forceRefreshRaw = url.searchParams.get('forceRefresh');
const haveRefreshArg = forceRefreshRaw !== null;
Expand All @@ -119,6 +114,11 @@ export class JupyteachContents extends Contents {
return out;
}
}

const blockIdRaw = url.searchParams.get('contentBlockId');
const contentBlockId = blockIdRaw ? +blockIdRaw : undefined;
const { id, key } = this.getIdAndKey({contentBlockId});

Check failure on line 120 in src/contents.ts

View workflow job for this annotation

GitHub Actions / build

Replace `contentBlockId` with `·contentBlockId·`

if (this.apolloClient && id) {
// check to see if this is in the cache already -- should be !"])
const nb = this.apolloClient.readFragment({
Expand All @@ -128,30 +128,33 @@ export class JupyteachContents extends Contents {
IContentBlock,
'properties' | 'createdAt' | 'id' | 'nbContent'
> | null;
console.debug('[contents.ts] get inside if', {
path,
options,
nb,
client: this.apolloClient
});
if (nb) {
return {
content: nb.nbContent,
const out = {
name: nb.properties.fileName,
path: nb.properties.fileName,
type: 'notebook' as const,
writable: true,
created: nb.createdAt,
format: 'json',
last_modified: nb.properties.lastModified,
mimetype: 'application/x-ipynb+json',
name: nb.properties.fileName,
path: nb.properties.fileName,
size: JSON.stringify(nb.nbContent).length,
type: 'notebook',
writable: true
content: nb.nbContent,
format: 'json' as const,
size: JSON.stringify(nb.nbContent).length
};
if (contentBlockId) {
this.contentBlockIDToFileName[contentBlockId] = nb.properties.fileName;

Check failure on line 145 in src/contents.ts

View workflow job for this annotation

GitHub Actions / build

Insert `⏎···········`
this.fileNameToContentBlockID[nb.properties.fileName] = contentBlockId;

Check failure on line 146 in src/contents.ts

View workflow job for this annotation

GitHub Actions / build

Insert `⏎···········`
}
console.debug('[contents.ts] get returning from Apollo cache', { out });
return out;
}
}

const out = await super.get(path, options);
console.debug('[contents.ts] get fallback response', { out });

// otherwise, just fallback
return super.get(path, options);
return out;
}

async createCheckpoint(
Expand Down

0 comments on commit c362a5b

Please sign in to comment.