davanstrien HF Staff julien-c HF Staff commited on
Commit
e3344eb
·
0 Parent(s):

Duplicate from julien-c/nbconvert

Browse files

Co-authored-by: Julien Chaumond <[email protected]>

Files changed (9) hide show
  1. .gitattributes +34 -0
  2. .gitignore +1 -0
  3. .vscode/settings.json +4 -0
  4. Dockerfile +11 -0
  5. README.md +12 -0
  6. app.py +91 -0
  7. requirements.txt +5 -0
  8. static/.prettierrc +3 -0
  9. static/index.html +85 -0
.gitattributes ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tflite filter=lfs diff=lfs merge=lfs -text
29
+ *.tgz filter=lfs diff=lfs merge=lfs -text
30
+ *.wasm filter=lfs diff=lfs merge=lfs -text
31
+ *.xz filter=lfs diff=lfs merge=lfs -text
32
+ *.zip filter=lfs diff=lfs merge=lfs -text
33
+ *.zst filter=lfs diff=lfs merge=lfs -text
34
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ .env/
.vscode/settings.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "editor.formatOnSave": true,
3
+ "python.formatting.provider": "black"
4
+ }
Dockerfile ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10
2
+
3
+ WORKDIR /code
4
+
5
+ COPY ./requirements.txt /code/requirements.txt
6
+
7
+ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
8
+
9
+ COPY . .
10
+
11
+ CMD ["uvicorn", "--host", "0.0.0.0", "--port", "7860", "app:app"]
README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: nbconvert
3
+ emoji: 💪
4
+ colorFrom: purple
5
+ colorTo: purple
6
+ sdk: docker
7
+ pinned: false
8
+ license: mit
9
+ duplicated_from: julien-c/nbconvert
10
+ ---
11
+
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Literal
2
+ import httpx
3
+ import nbformat
4
+ from nbformat import NotebookNode, ValidationError
5
+ from nbconvert import HTMLExporter
6
+ from starlette.applications import Starlette
7
+ from starlette.exceptions import HTTPException
8
+ from starlette.responses import FileResponse, JSONResponse, HTMLResponse
9
+ from starlette.requests import Request
10
+ from starlette.routing import Route
11
+
12
+ client = httpx.AsyncClient()
13
+ html_exporter = HTMLExporter(template_name="lab")
14
+
15
+
16
+ async def homepage(_):
17
+ return FileResponse("static/index.html")
18
+
19
+
20
+ async def healthz(_):
21
+ return JSONResponse({"success": True})
22
+
23
+
24
+ def convert(s: str, theme: Literal["light", "dark"], debug_info: str) -> str:
25
+ # Capture potential validation error:
26
+ try:
27
+ notebook_node: NotebookNode = nbformat.reads(
28
+ s,
29
+ as_version=nbformat.current_nbformat,
30
+ )
31
+ except nbformat.reader.NotJSONError:
32
+ print(400, f"Notebook is not JSON. {debug_info}")
33
+ raise HTTPException(400, f"Notebook is not JSON.")
34
+ except ValidationError as e:
35
+ print(
36
+ 400,
37
+ f"Notebook is invalid according to nbformat: {e}. {debug_info}",
38
+ )
39
+ raise HTTPException(
40
+ 400,
41
+ f"Notebook is invalid according to nbformat: {e}.",
42
+ )
43
+
44
+ print(f"Input: nbformat v{notebook_node.nbformat}.{notebook_node.nbformat_minor}")
45
+ html_exporter.theme = theme
46
+ body, _ = html_exporter.from_notebook_node(notebook_node)
47
+ # TODO(customize or simplify template?)
48
+ # TODO(also check source code for jupyter/nbviewer)
49
+ return body
50
+
51
+
52
+ async def convert_from_url(req: Request):
53
+ url = req.query_params.get("url")
54
+ theme = "dark" if req.query_params.get("theme") == "dark" else "light"
55
+
56
+ if not url:
57
+ raise HTTPException(400, "Param url is missing")
58
+ print("\n===", url)
59
+ r = await client.get(
60
+ url,
61
+ follow_redirects=True,
62
+ # httpx no follow redirect by default
63
+ )
64
+ if r.status_code != 200:
65
+ raise HTTPException(
66
+ 400, f"Got an error {r.status_code} when fetching remote file"
67
+ )
68
+
69
+ return HTMLResponse(content=convert(r.text, theme=theme, debug_info=f"url={url}"))
70
+
71
+
72
+ async def convert_from_upload(req: Request):
73
+ theme = "dark" if req.query_params.get("theme") == "dark" else "light"
74
+
75
+ s = (await req.body()).decode("utf-8")
76
+ return HTMLResponse(
77
+ content=convert(
78
+ s, theme=theme, debug_info=f"upload_from={req.headers.get('user-agent')}"
79
+ )
80
+ )
81
+
82
+
83
+ app = Starlette(
84
+ debug=False,
85
+ routes=[
86
+ Route("/", homepage),
87
+ Route("/healthz", healthz),
88
+ Route("/convert", convert_from_url),
89
+ Route("/upload", convert_from_upload, methods=["POST"]),
90
+ ],
91
+ )
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ httpx==0.23.3
2
+ starlette==0.23.1
3
+ ipython==8.8.0
4
+ nbconvert==7.2.8
5
+ uvicorn==0.20.0
static/.prettierrc ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "useTabs": true
3
+ }
static/index.html ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <script src="https://cdn.tailwindcss.com"></script>
7
+ </head>
8
+ <body>
9
+ <div class="container mx-auto py-4 dark:text-white">
10
+ <h1 class="text-3xl font-bold text-center">nbconvert-server</h1>
11
+ <p class="text-center">
12
+ An internal API used as a backend for notebook rendering on the Hub
13
+ </p>
14
+ <svg class="mx-auto mb-8" width="32" height="32" viewBox="0 0 24 24">
15
+ <path
16
+ fill="#888888"
17
+ fill-rule="evenodd"
18
+ d="M16.48 14h4.02a2.5 2.5 0 1 0 0-5H6.618a1 1 0 0 1-.894-.553l-.448-.894A1 1 0 0 0 4.382 7H2.517a1 1 0 0 0-.92 1.394l2.143 5a1 1 0 0 0 .92.606h3.863a1 1 0 0 1 .928 1.371L8.55 17.63A1 1 0 0 0 9.477 19h2.042a1 1 0 0 0 .781-.375l3.4-4.25a1 1 0 0 1 .78-.375zM9.5 8h4.75L12.3 5.4a1 1 0 0 0-.8-.4H9.618a1 1 0 0 0-.894 1.447L9.5 8z"
19
+ clip-rule="evenodd"
20
+ />
21
+ </svg>
22
+
23
+ <div class="w-96 mx-auto">
24
+ <p>Sample notebooks:</p>
25
+ <ul class="list-disc">
26
+ <li>
27
+ climategan (LFS-stored > 10MB)
28
+ <a
29
+ target="_blank"
30
+ class="underline"
31
+ href="/convert?url=https://huggingface.co/spaces/NimaBoscarino/climategan/resolve/main/notebooks/plot_metrics.ipynb"
32
+ >
33
+ html</a
34
+ >,
35
+ <a
36
+ target="_blank"
37
+ class="underline"
38
+ href="https://huggingface.co/spaces/NimaBoscarino/climategan/blob/main/notebooks/plot_metrics.ipynb"
39
+ >
40
+ on Hub
41
+ </a>
42
+ </li>
43
+ <li>
44
+ Fake_News_Classificaton.ipynb (stored in raw git)
45
+ <a
46
+ target="_blank"
47
+ class="underline"
48
+ href="/convert?url=https://huggingface.co/pceiyos/fake_news_detection_nlp/resolve/main/Fake_News_Classificaton.ipynb"
49
+ >
50
+ html</a
51
+ >,
52
+ <a
53
+ target="_blank"
54
+ class="underline"
55
+ href="https://huggingface.co/pceiyos/fake_news_detection_nlp/blob/main/Fake_News_Classificaton.ipynb"
56
+ >
57
+ on Hub
58
+ </a>
59
+ </li>
60
+ <li>
61
+ Dall-e mini (specific revision)
62
+ <a
63
+ target="_blank"
64
+ class="underline"
65
+ href="/convert?url=https://huggingface.co/spaces/dalle-mini/dalle-mini/resolve/63679e968109278c5f0169100b1755bbda9f4bc6/tools/inference/inference_pipeline.ipynb"
66
+ >
67
+ html</a
68
+ >,
69
+ <a
70
+ target="_blank"
71
+ class="underline"
72
+ href="https://huggingface.co/spaces/dalle-mini/dalle-mini/blob/63679e968109278c5f0169100b1755bbda9f4bc6/tools/inference/inference_pipeline.ipynb"
73
+ >
74
+ on Hub
75
+ </a>
76
+ </li>
77
+ </ul>
78
+ </div>
79
+
80
+ <div class="text-xs text-gray-500 text-center mt-10 mb-4">
81
+ ping @julien-c if anything looks wrong
82
+ </div>
83
+ </div>
84
+ </body>
85
+ </html>