{ "cells": [ { "cell_type": "raw", "id": "0", "metadata": { "editable": true, "raw_mimetype": "text/restructuredtext", "slideshow": { "slide_type": "" }, "tags": [], "vscode": { "languageId": "raw" } }, "source": [ ".. important::\n", " Jupyter widgets cannot be run within the documentation. To interact with the widget, you must run a mybinder instance. To run a mybinder instance of this notebook, please use this link https://mybinder.org/v2/gh/osscar-org/scicode-widgets/HEAD?labpath=docs%2Fsrc%2Fnbgrader.ipynb. Note that also the LaTeX rendering is resolved when running the notebook." ] }, { "cell_type": "markdown", "id": "1", "metadata": {}, "source": [ "# Integrating with nbgrader" ] }, { "cell_type": "markdown", "id": "2", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-20d1e686f2f5e6eb", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Problem1 from the quickstart of nbgrader using scwidgets" ] }, { "cell_type": "markdown", "id": "3", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-d44feca970fbc35c", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "When you initialize the quickstart project from `nbgrader`, a `problem1.ipynb` file is generated. In this notebook, we show how `scwidgets` can be used with `nbgrader`. We transformed the `problem1.ipynb` to a version that uses `scwidgets`." ] }, { "cell_type": "markdown", "id": "4", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-cbffb5535580d50a", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "---" ] }, { "cell_type": "code", "execution_count": null, "id": "5", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-e7b0d7238de01566", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "from scwidgets import CodeExercise, TextExercise, ExerciseRegistry, CheckRegistry, CodeInput, assert_type, assert_equal" ] }, { "cell_type": "code", "execution_count": null, "id": "6", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-bfcc1fc18abb908d", "locked": true, "points": 0, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "### BEGIN HIDDEN TESTS\n", "if 'NAME' not in globals():\n", " NAME = \"reference solution\"\n", "### END HIDDEN TESTS\n", "exercise_registry = ExerciseRegistry(filename_prefix=\"problem1\")\n", "exercise_registry" ] }, { "cell_type": "code", "execution_count": null, "id": "7", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-1f434402bd4a0796", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "check_registry = CheckRegistry()\n", "check_registry" ] }, { "cell_type": "code", "execution_count": null, "id": "8", "metadata": { "nbgrader": { "grade": false, "grade_id": "squares", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "def squares(n):\n", " \"\"\"Compute the squares of numbers from 1 to n, such that the \n", " ith element of the returned list equals i^2.\n", " \n", " \"\"\"\n", " ### BEGIN SOLUTION\n", " if n < 1:\n", " raise ValueError(\"n must be greater than or equal to 1\")\n", " return [i ** 2 for i in range(1, n + 1)]\n", " ### END SOLUTION\n", "\n", "description = \"\"\"\n", "Write a function that returns a list of numbers,\n", "such that $x_i=i^2$, for $1\\leq i \\leq n$.\n", "Make sure it handles the case where $n<1$ by raising a `ValueError`.\n", "\"\"\"\n", "\n", "code_ex_squares = CodeExercise(\n", " code=squares,\n", " parameters={\"n\": (1, 10, 1)},\n", " update=lambda code_ex: print(code_ex.code(code_ex.parameters['n'])),\n", " check_registry=check_registry,\n", " exercise_registry=exercise_registry,\n", " key=\"Part A (2 points)\",\n", " description=description\n", ")\n", "\n", "# Check that squares returns the correct output for several inputs\n", "check_registry.add_check(\n", " code_ex_squares,\n", " asserts=[assert_type, assert_equal],\n", " inputs_parameters=[{\"n\": i} for i in [1, 2, 10, 11]],\n", " outputs_references=[([1],), ([1, 4],), ([1, 4, 9, 16, 25, 36, 49, 64, 81, 100],), ([1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121],)],\n", ")\n", "\n", "# Check that squares raises an error for invalid inputs\n", "def assert_raise_error() -> str:\n", " try:\n", " code_ex_squares.code.unwrapped_function(0)\n", " except ValueError:\n", " return \"\"\n", " else:\n", " return \"Did not raise error for zero\"\n", " \n", " try:\n", " code_ex_squares.code.unwrapped_function(-4)\n", " except ValueError:\n", " return \"\"\n", " else:\n", " return \"Did not error for negative number\"\n", "\n", "check_registry.add_check(\n", " code_ex_squares,\n", " asserts=[\n", " assert_raise_error,\n", " ]\n", ")\n", "\n", "code_ex_squares" ] }, { "cell_type": "code", "execution_count": null, "id": "9", "metadata": { "nbgrader": { "grade": true, "grade_id": "correct_squares", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "### BEGIN HIDDEN TESTS\n", "exercise_registry.load_answer_from_student_name(NAME, code_ex_squares)\n", "checks = check_registry.check_widget(code_ex_squares)\n", "assert checks[0].successful, checks[0].message()\n", "### END HIDDEN TESTS" ] }, { "cell_type": "code", "execution_count": null, "id": "10", "metadata": { "nbgrader": { "grade": true, "grade_id": "squares_invalid_input", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "### BEGIN HIDDEN TESTS\n", "assert checks[1].successful, checks[1].message()\n", "### END HIDDEN TESTS" ] }, { "cell_type": "code", "execution_count": null, "id": "11", "metadata": { "nbgrader": { "grade": false, "grade_id": "sum_of_squares", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "from scwidgets import assert_type, assert_equal\n", "\n", "def sum_of_squares(n):\n", " \"\"\"Compute the sum of the squares of numbers from 1 to n.\"\"\"\n", " ### BEGIN SOLUTION\n", " return sum(squares(n))\n", " ### END SOLUTION\n", "\n", "description = \"\"\"\n", "Using your `squares` function, write a function\n", "that computes the sum of the squares of the numbers\n", "from 1 to $n$. Your function should call the `squares`\n", "function -- it should NOT reimplement its functionality.\n", "\"\"\"\n", "\n", "code_ex_sum_of_squares = CodeExercise(\n", " code=CodeInput(sum_of_squares, builtins={\"squares\": code_ex_squares.code.function}),\n", " parameters={\"n\": (1, 10, 1)},\n", " update=lambda code_ex: print(code_ex.code(code_ex.parameters['n'])),\n", " check_registry=check_registry,\n", " exercise_registry=exercise_registry,\n", " key=\"Part B (1 point)\",\n", " description=description\n", ")\n", "\n", "# Check that sum_of_squares returns the correct answer for various inputs\n", "check_registry.add_check(\n", " code_ex_sum_of_squares,\n", " asserts=[assert_type, assert_equal],\n", " inputs_parameters=[{\"n\": i} for i in [1, 2, 10, 11]],\n", " outputs_references=[(1,), (5,), (385,), (506,)],\n", ")\n", "\n", "# Check that sum_of_squares relies on squares\n", "def assert_uses_squares() -> str:\n", " \"\"\"Check that sum_of_squares relies on squares.\"\"\"\n", " code_ex_sum_of_squares.code.builtins = {}\n", " try:\n", " code_ex_sum_of_squares.code.unwrapped_function(1) # not using builtins\n", " except NameError:\n", " result = \"\"\n", " else:\n", " result = \"sum_of_squares does not use squares\"\n", " code_ex_sum_of_squares.code.builtins = {\"squares\": code_ex_squares.code.function}\n", " return result\n", " \n", "check_registry.add_check(\n", " code_ex_sum_of_squares,\n", " asserts=[\n", " assert_uses_squares,\n", " ]\n", ")\n", "\n", "code_ex_sum_of_squares" ] }, { "cell_type": "code", "execution_count": null, "id": "12", "metadata": { "nbgrader": { "grade": true, "grade_id": "correct_sum_of_squares", "locked": true, "points": 0.5, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "### BEGIN HIDDEN TESTS\n", "exercise_registry.load_answer_from_student_name(NAME, code_ex_sum_of_squares)\n", "checks = check_registry.check_widget(code_ex_sum_of_squares)\n", "assert checks[0].successful, checks[0].message()\n", "### END HIDDEN TESTS" ] }, { "cell_type": "code", "execution_count": null, "id": "13", "metadata": { "nbgrader": { "grade": true, "grade_id": "sum_of_squares_uses_squares", "locked": true, "points": 0.5, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "### BEGIN HIDDEN TESTS\n", "assert checks[1].successful, checks[1].message()\n", "### END HIDDEN TESTS" ] }, { "cell_type": "code", "execution_count": null, "id": "14", "metadata": { "nbgrader": { "grade": false, "grade_id": "sum_of_squares_equation", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "value = \"\"\"\n", "### BEGIN SOLUTION\n", "$\\sum_{i=1}^n i^2$\n", "### END SOLUTION\n", "\"\"\"\n", "\n", "description = \"\"\"\n", "Using LaTeX math notation, write out the equation\n", "that is implemented by your `sum_of_squares` function.\"\"\"\n", "\n", "text_ex = TextExercise(\n", " value=value,\n", " exercise_registry=exercise_registry,\n", " key=\"Part C (1 point)\",\n", " description=description\n", ")\n", "text_ex" ] }, { "cell_type": "code", "execution_count": null, "id": "15", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-f21df018970765c7", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "### BEGIN HIDDEN TESTS\n", "exercise_registry.load_answer_from_student_name(NAME, text_ex)\n", "### END HIDDEN TESTS" ] }, { "cell_type": "code", "execution_count": null, "id": "16", "metadata": { "nbgrader": { "grade": false, "grade_id": "sum_of_squares_application", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "def pyramidal_number(n):\n", " \"\"\"Returns the n^th pyramidal number\"\"\"\n", " summation = sum_of_squares(n)\n", " ### BEGIN SOLUTION\n", " ### END SOLUTION\n", "\n", "description = \"\"\"\n", "Find a use case for your `sum_of_squares` function and implement that use case in the cell below.\n", "\"\"\"\n", "\n", "code_ex_pyramidal_number = CodeExercise(\n", " code=CodeInput(pyramidal_number, builtins={\"sum_of_squares\": code_ex_sum_of_squares.code.function}),\n", " parameters={\"n\": (1, 10, 1)},\n", " update=lambda code_ex: print(code_ex.code(code_ex.parameters['n'])),\n", " exercise_registry=exercise_registry,\n", " key=\"Part D (2 points)\",\n", " description=description\n", ")\n", "\n", "code_ex_pyramidal_number" ] }, { "cell_type": "code", "execution_count": null, "id": "17", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-bf4d174b9af19a27", "locked": true, "points": 4, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "### BEGIN HIDDEN TESTS\n", "exercise_registry.load_answer_from_student_name(NAME, code_ex_pyramidal_number)\n", "### END HIDDEN TESTS" ] }, { "cell_type": "code", "execution_count": null, "id": "18", "metadata": { "nbgrader": { "grade": false, "grade_id": "arithmetic_geometric_sum_equation", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "description = \"\"\"\n", "State the formulae for an arithmetic and geometric\n", "sum and verify them numerically for an example of\n", "your choice.\"\"\"\n", "\n", "text_ex = TextExercise(\n", " value=\"\"\"\n", "### BEGIN SOLUTION\n", "### END SOLUTION\n", "\"\"\",\n", " exercise_registry=exercise_registry,\n", " key=\"Part E (4 points)\",\n", " description=description\n", ")\n", "\n", "text_ex" ] }, { "cell_type": "code", "execution_count": null, "id": "19", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-ef75037ccb87de3a", "locked": true, "points": 2, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "### BEGIN HIDDEN TESTS\n", "exercise_registry.load_answer_from_student_name(NAME, text_ex)\n", "### END HIDDEN TESTS" ] }, { "cell_type": "code", "execution_count": null, "id": "20", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-3b0ef02c9f5f10f0", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "try:\n", " exercise_registry.load_file_from_student_name(NAME)\n", "except FileNotFoundError:\n", " exercise_registry.create_new_file_from_student_name(NAME)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.10" } }, "nbformat": 4, "nbformat_minor": 5 }