Skip to content

Commit

Permalink
Write functionality to handle non notebook files (#50)
Browse files Browse the repository at this point in the history
* Write functionality to handle non notebook files.

* Commit release how to.

* Write tests.

* Add docs.

* Run black.

* Change type of incorrect format read.

* Correct typing in check function.

* Sort imports.

* Commit documentation file.
  • Loading branch information
drvinceknight committed Jan 4, 2021
1 parent b7a9ffc commit 8680670
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 10 deletions.
10 changes: 10 additions & 0 deletions docs/howto/handle_a_submission_in_the_wrong_format.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
handle a submission in the wrong format
=======================================

If a file is checked that is not an `ipynb` file then the checker will write the
following to the feedback file::

"Your notebook file was not in the correct format and could not be read"

Note than when batch checking, this will not stop the checker from checking the
other files.
1 change: 1 addition & 0 deletions docs/howto/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ How to:
release_a_source_assignment.rst
solve_an_assignment.rst
check_a_submission.rst
handle_a_submission_in_the_wrong_format.rst
contribute.rst
release.rst
22 changes: 22 additions & 0 deletions docs/howto/release.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
release
-------

The release process:

1. Adjust the version number in :code:`version.py`.
2. Tag a new release::

git tag <release number>

3. Push the new tag to github::

git push --tags

4. Create a new release on github.
5. Create a distribution::

python setup.py sdist bdist_wheel

6. Use :code:`twine` to upload to pypi::

python -m twine upload dist/*
24 changes: 17 additions & 7 deletions src/nbchkr/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,24 @@ def check(
with typer.progressbar(sorted(glob.iglob(submitted))) as bar:
for path in bar:
nb_node = nbchkr.utils.read(path)
tags_match = nbchkr.utils.check_tags_match(
source_nb_node=source_nb_node, nb_node=nb_node
)
if nb_node != {}:
tags_match = nbchkr.utils.check_tags_match(
source_nb_node=source_nb_node, nb_node=nb_node
)

nb_node = nbchkr.utils.add_checks(
nb_node=nb_node, source_nb_node=source_nb_node
)
score, maximum_score, feedback_md = nbchkr.utils.check(nb_node=nb_node)
nb_node = nbchkr.utils.add_checks(
nb_node=nb_node, source_nb_node=source_nb_node
)
score, maximum_score, feedback_md = nbchkr.utils.check(
nb_node=nb_node
)
else:
score, maximum_score, feedback_md = (
None,
None,
"Your notebook file was not in the correct format and could not be read",
)
tags_match = False

with open(f"{path}{feedback_suffix}", "w") as f:
f.write(feedback_md)
Expand Down
9 changes: 6 additions & 3 deletions src/nbchkr/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import json
import pathlib
import re
from typing import Tuple, Union
from typing import Optional, Tuple, Union

import nbformat # type: ignore
import unidecode # type: ignore
Expand All @@ -29,7 +29,10 @@ def read(nb_path: Union[pathlib.Path, str], as_version: int = 4) -> dict:
Returns the python `dict` representation.
"""
with open(nb_path, "r") as f:
nb = nbformat.read(f, as_version=as_version)
try:
nb = nbformat.read(f, as_version=as_version)
except nbformat.reader.NotJSONError:
return {}
return nb


Expand Down Expand Up @@ -169,7 +172,7 @@ def check(
timeout: int = 600,
score_regex_pattern=None,
answer_tag_pattern=None,
) -> Tuple[int, int, str]:
) -> Tuple[Optional[int], Optional[int], str]:
"""
Given a `nb_node`, it executes the notebook and keep track of the score.
Expand Down
9 changes: 9 additions & 0 deletions tests/test_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ def test_read_nb_gives_dictionary():
assert type(nb) is nbformat.NotebookNode


def test_read_nb_gives_none_when_not_reading_notebook():
"""
Tries to read in this test file.
"""
nb_path = __file__
nb = nbchkr.utils.read(nb_path=nb_path)
assert nb == {}


def test_add_checks_creates_notebook_with_assertions():
nb_node = nbchkr.utils.read(nb_path=NB_PATH / "submission.ipynb")
source_nb_node = nbchkr.utils.read(nb_path=NB_PATH / "test.ipynb")
Expand Down
57 changes: 57 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,60 @@ def test_check_on_documentation_examples():

expected_number_of_feedback_files = 3
assert number_of_feedback_files == expected_number_of_feedback_files


def test_check_on_a_non_notebook_file():
"""
Tries to read in this test file.
"""
# TODO add better tear down.

submission_nb = __file__
expected_output = ["", "", "False"]
expected_feedback = (
"Your notebook file was not in the correct format and could not be read"
)

output = subprocess.run(
[
"nbchkr",
"check",
"--source",
f"{NB_PATH}/test.ipynb",
"--submitted",
f"{submission_nb}",
"--feedback-suffix",
"_feedback.md",
"--output",
"output.csv",
],
capture_output=True,
)
expected_stdout = str.encode(
f"{submission_nb} checked against {NB_PATH}/test.ipynb. Feedback written to {submission_nb}_feedback.md and output written to output.csv.\n"
)
expected_stdout += str.encode(
f"WARNING: {submission_nb} has tags that do not match the source.\n"
)
assert output.stdout == expected_stdout

with open("output.csv", "r") as f:
csv_reader = csv.reader(f)
output = list(csv_reader)

expected_output = [
["Submission filepath", "Score", "Maximum score", "Tags match"],
[f"{submission_nb}"] + expected_output,
]
assert output == expected_output

with open(f"{submission_nb}_feedback.md", "r") as f:
feedback = f.read()
assert feedback == expected_feedback

# TODO Add a better pytest cleanup.
try:
pathlib.Path(f"{submission_nb}_feedback.md").unlink()
except FileNotFoundError: # TODO Ensure py3.8 is used so that can pass
# `missing_ok=True` to `path.unlink`.
pass

0 comments on commit 8680670

Please sign in to comment.