Tests for Jupyter Notebooks

Notebook Invalid

$ echo -e "x: int = 1" > $TMPDIR/notebook.ipynb && \
> $PYREFLY check $TMPDIR/notebook.ipynb
ERROR * Expected a Jupyter Notebook, which must be internally stored as JSON, but this file isn't valid JSON* (glob)
--> */notebook.ipynb:1:1 (glob)
 |
 |
[1]

Notebook Invalid JSON

$ echo -e "{}" > $TMPDIR/notebook.ipynb && \
> $PYREFLY check $TMPDIR/notebook.ipynb
ERROR * This file does not match the schema expected of Jupyter Notebooks: missing field `cells`* (glob)
--> */notebook.ipynb:1:1 (glob)
 |
 |
[1]

Notebook Top Level Await

$ echo -e '{"cells":[{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["import asyncio\\nawait asyncio.sleep(1)"]}],"metadata":{"language_info":{"name":"python"}},"nbformat":4,"nbformat_minor":4}' > $TMPDIR/notebook.ipynb && \
> $PYREFLY check $TMPDIR/notebook.ipynb
[0]

Notebook Top Level Async With

$ echo -e '{"cells":[{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["import asyncio\\nasync with asyncio.timeout(1):\\n    await asyncio.sleep(0.5)"]}],"metadata":{"language_info":{"name":"python"}},"nbformat":4,"nbformat_minor":4}' > $TMPDIR/notebook.ipynb && \
> $PYREFLY check $TMPDIR/notebook.ipynb
[0]

Notebook Top Level Async For

$ echo -e '{"cells":[{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["async def arange(n):\\n    for i in range(n):\\n        yield i\\nasync for x in arange(5):\\n    pass"]}],"metadata":{"language_info":{"name":"python"}},"nbformat":4,"nbformat_minor":4}' > $TMPDIR/notebook.ipynb && \
> $PYREFLY check $TMPDIR/notebook.ipynb
[0]

Shebang Notebook Top Level Await

$ echo -e '#!/usr/bin/env -S notebookrunner --kernel default\nimport asyncio\nawait asyncio.sleep(1)' > $TMPDIR/notebook.py && \
> $PYREFLY check $TMPDIR/notebook.py
[0]

Shebang Notebook Top Level Async With

$ echo -e '#!/usr/bin/env -S notebookrunner --kernel default\nimport asyncio\nasync with asyncio.timeout(1):\n    await asyncio.sleep(0.5)' > $TMPDIR/notebook.py && \
> $PYREFLY check $TMPDIR/notebook.py
[0]

Shebang Notebook Top Level Async For

$ echo -e '#!/usr/bin/env -S notebookrunner --kernel default\nasync def arange(n):\n    for i in range(n):\n        yield i\nasync for x in arange(5):\n    pass' > $TMPDIR/notebook.py && \
> $PYREFLY check $TMPDIR/notebook.py
[0]

Non-Notebook Python Top Level Await Rejected

$ echo -e 'import asyncio\nawait asyncio.sleep(1)' > $TMPDIR/regular.py && \
> $PYREFLY check $TMPDIR/regular.py
ERROR `await` can only be used inside an async function [invalid-syntax]
 --> */regular.py:2:1 (glob)
  |
* (glob)
* (glob)
  |
[1]

Notebook Directive

$ echo -e '{"cells":[{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["%matplotlib inline"]}],"metadata":{"language_info":{"name":"python"}},"nbformat":4,"nbformat_minor":4}' > $TMPDIR/notebook.ipynb && \
> $PYREFLY check $TMPDIR/notebook.ipynb
[0]

Notebook Error

$ touch $TMPDIR/pyrefly.toml && \
> echo -e '{"cells":[{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["x: bool = 5"]}],"metadata":{"language_info":{"name":"python"}},"nbformat":4,"nbformat_minor":4}' > $TMPDIR/notebook.ipynb && \
> $PYREFLY check $TMPDIR/notebook.ipynb
ERROR `Literal[5]` is not assignable to `bool` [bad-assignment]
 --> */notebook.ipynb#1:1:11 (glob)
  |
1 | x: bool = 5
  |    ----   ^
  |    |
  |    declared type
  |
[1]

Notebook Error Second Cell

$ touch $TMPDIR/pyrefly.toml && \
> echo -e '{"cells":[{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["x: bool = True"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["x: bool = 5"]}],"metadata":{"language_info":{"name":"python"}},"nbformat":4,"nbformat_minor":4}' > $TMPDIR/notebook.ipynb && \
> $PYREFLY check $TMPDIR/notebook.ipynb
ERROR `Literal[5]` is not assignable to `bool` [bad-assignment]
 --> */notebook.ipynb#2:1:11 (glob)
  |
1 | x: bool = 5
  |    ----   ^
  |    |
  |    declared type
  |
[1]

Notebook Suppressed Error

$ echo -e '{"cells":[{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# type: ignore\\nx: bool = 5"]}],"metadata":{"language_info":{"name":"python"}},"nbformat":4,"nbformat_minor":4}' > $TMPDIR/notebook.ipynb && \
> $PYREFLY check $TMPDIR/notebook.ipynb
[0]