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

[wip] add async #1

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
complete rest of basic tests
  • Loading branch information
bollwyvl committed Nov 7, 2020
commit 5d50cd4473a986581a6a2dc597ea341d5ef473d3
22 changes: 4 additions & 18 deletions nbformat/asynchronous.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,10 @@ def _reads(s, as_version, kwargs_):
return reads(s, as_version, **kwargs_)


def _read(fp, as_version, kwargs_):
return read(fp, as_version, **kwargs_)


def _writes(nb, version, kwargs_):
return writes(nb, version, **kwargs_)


def _write(nb, fp, version, kwargs_):
return writes(nb, fp, version, **kwargs_)

def _validate(nbdict, ref, version, version_minor, relax_add_props, nbjson):
return validate(nbdict, ref, version, version_minor, relax_add_props, nbjson)

Expand All @@ -48,25 +41,18 @@ async def areads(s, as_version, **kwargs):


async def aread(fp, as_version, **kwargs):
with aiofiles.open(fp) as afp:
async with aiofiles.open(fp) as afp:
return await areads(await afp.read(), as_version, **kwargs)

return await _loop().run_in_executor(None, _read, fp, as_version, kwargs)


async def awrites(nb, version=NO_CONVERT, **kwargs):
return await _loop().run_in_executor(None, _writes, nb, version, kwargs)


async def awrite(nb, fp, version=NO_CONVERT, **kwargs):
if isinstance(fp, str):
with aiofiles.open(fp, "w+") as afp:
return await awrites(nb, await afp.read(), version, **kwargs)
elif isinstance(fp, Path):
with aiofiles.open(str(fp), "w+") as afp:
return await awrites(nb, await afp.read(), version, **kwargs)

return await _loop().run_in_executor(None, _write, nb, fp, version, kwargs)
nb_str = await awrites(nb, version, **kwargs)
async with aiofiles.open(fp, "w+", encoding="utf-8") as afp:
await afp.write(nb_str)


async def avalidate(nbdict=None, ref=None, version=None, version_minor=None,
Expand Down
8 changes: 3 additions & 5 deletions nbformat/tests/strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@
from nbformat.v4 import new_code_cell, new_markdown_cell, new_notebook

HERE = Path(__file__).parent
ALL_NOTEBOOK_TEXT = [p.read_text(encoding="utf-8") for p in HERE.glob("*.ipynb")]
ALL_NOTEBOOKS = [
reads(
p.read_text(encoding="utf-8"),
int(re.findall(r"""nbformat":\s+(\d+)""", p.read_text())[0])
)
for p in HERE.glob("*.ipynb")
reads(nb_text, int(re.findall(r"""nbformat":\s+(\d+)""", nb_text)[0]))
for nb_text in ALL_NOTEBOOK_TEXT
]

def _is_valid(nb):
Expand Down
67 changes: 58 additions & 9 deletions nbformat/tests/test_async.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,74 @@
import os
import pytest
import contextlib
from hypothesis import given

from nbformat import reads
from nbformat.asynchronous import areads, avalidate, ValidationError
from nbformat.asynchronous import aread, areads, awrite, awrites, avalidate, ValidationError
from nbformat.json_compat import VALIDATORS
import tempfile

from . import strategies as nbs


@contextlib.contextmanager
def json_validator(validator_name):
os.environ["NBFORMAT_VALIDATOR"] = validator_name
try:
yield
finally:
os.environ.pop("NBFORMAT_VALIDATOR")



# some issues with setting the environment mean they can just be parametrized
async def _valid(nb_txt, caplog):
nb, txt = nb_txt
read_nb = await areads(txt, nb.nbformat)
assert "Notebook JSON" not in caplog.text

await avalidate(read_nb)

with tempfile.TemporaryDirectory() as td:
nb_path = os.path.join(td, "notebook.ipynb")
await awrite(read_nb, nb_path)
await aread(nb_path, nb["nbformat"])

@given(nb_txt=nbs.a_valid_notebook_with_string())
@nbs.base_settings
@pytest.mark.asyncio
async def test_async_valid_default(nb_txt, caplog):
with json_validator("jsonschema"):
await _valid(nb_txt, caplog)


@given(nb_txt=nbs.a_valid_notebook_with_string())
@nbs.base_settings
async def test_areads_valid(nb_txt, caplog):
@pytest.mark.asyncio
async def test_async_valid_fast(nb_txt, caplog):
with json_validator("fastjsonschema"):
await _valid(nb_txt, caplog)


async def _invalid(nb_txt, caplog):
nb, txt = nb_txt
await areads(txt, nb.nbformat)
assert "Notebook JSON" not in caplog.text
read_nb = await areads(txt, nb.nbformat)
assert "Notebook JSON" in caplog.text

with pytest.raises(ValidationError):
await avalidate(read_nb)


@given(nb_txt=nbs.an_invalid_notebook_with_string())
@nbs.base_settings
@pytest.mark.asyncio
async def test_async_invalid_default(nb_txt, caplog):
with json_validator("jsonschema"):
await _invalid(nb_txt, caplog)


@given(nb_txt=nbs.an_invalid_notebook_with_string())
@nbs.base_settings
async def test_areads_invalid(nb_txt, caplog):
nb, txt = nb_txt
await areads(txt, nb.nbformat)
assert "Notebook JSON" in caplog.text
@pytest.mark.asyncio
async def test_async_invalid_false(nb_txt, caplog):
with json_validator("fastjsonschema"):
await _invalid(nb_txt, caplog)