From 420f0817918bc07356835aad1d41ee4f41aee868 Mon Sep 17 00:00:00 2001 From: Isaac Flath Date: Sat, 19 Oct 2024 20:41:04 -0400 Subject: [PATCH] Revert "Remove 1/2 of cells test" This reverts commit 69739a6052011c0c6c64a41d50ce8cb14238867d. --- nbs/tutorials/tutorial.ipynb | 1127 ++++++++++++++++++++++++++++++++++ 1 file changed, 1127 insertions(+) diff --git a/nbs/tutorials/tutorial.ipynb b/nbs/tutorials/tutorial.ipynb index 292bff42..24a77cd1 100644 --- a/nbs/tutorials/tutorial.ipynb +++ b/nbs/tutorials/tutorial.ipynb @@ -410,6 +410,1133 @@ "If you don't see a \"gh-pages\" branch, wait a few minutes and reload the page. It should automatically be set up for you." ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now it's time to see all of the goodies nbdev gives you!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Check out your workflows" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Open GitHub Actions by clicking the \"Actions\" tab near the top of your repo page. You should see two workflow runs:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](images/github-actions-initial.png){fig-align=\"center\" .border .rounded .shadow-sm}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you opened this page shortly after pushing your initial commit, the runs may not have a green check (✅) because they're still \"In progress\" or \"Queued\". That's no problem, they shouldn't take much more than a minute to complete." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you see a red cross (❌), that means something failed. Click on the cross, then click \"Details\", and you'll be able to see what failed. If you can't figure out what's wrong, search [the forum](https://forums.fast.ai/c/nbdev/48) in case someone else resolved the same issue, otherwise create a new post describing your issue in as much detail as you can, and we'll try our best to help you. Remember that including a link to an actual repo and/or GitHub Action is the best way for us to quickly identify what's wrong." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What do these workflows do?\n", + "\n", + "- **CI** -- The CI (continuous integration) workflow streamlines your developer workflow, particularly with multiple collaborators. Every time you push to GitHub, it ensures that:\n", + " - Your notebooks and libraries are in sync\n", + " - Your notebooks are cleaned of unwanted metadata (which pollute pull requests and git histories and lead to merge conflicts)\n", + " - Your notebook tests all pass\n", + "- **Deploy to GitHub Pages** -- Builds your docs with Quarto and deploys it to GitHub Pages." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We provide these basic workflows out-of-the-box, however, you can edit their corresponding YAML files in the `.github/workflows/` folder to your liking." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Check out your docs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you [enable GitHub Pages](#enable-github-pages) you should see a new workflow run: \"pages build and deployment\". As the name suggests, this workflow deploys your website contents to GitHub Pages." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](images/github-actions-pages.png){fig-align=\"center\" .border .rounded .shadow-sm}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Wait for the workflow run to complete, then open your website. By default it should be available at: `https://{user}.github.io/{repo}`. For example, you can view `fastai`'s `nbdev-hello-world` docs at ." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](images/nbdev-hello-world-site-initial.png){fig-align=\"center\" .border .rounded .shadow-sm}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Recap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You now have a base nbdev repo with continuous integration and hosted documentation! Here's a recap of the steps you took:\n", + "\n", + "- Created a GitHub repo (with GitHub Pages enabled)\n", + "- Initialised your repo with `nbdev_new`\n", + "- Pushed to GitHub." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Make your first edit" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this section, you'll make your first edit to the repo you created in [_First steps_](#first-steps)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Install hooks for git-friendly notebooks" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Step one when working with Jupyter notebooks in a new repo is to install nbdev's hooks (you can think of \"hooks\" as plugins or extensions to an application).\n", + "\n", + "Install them by entering this command in your terminal:\n", + "\n", + "```sh\n", + "nbdev_install_hooks\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "::: {.callout-note}\n", + "\n", + "The [clean hook](#nbdev_clean-on-saving-notebooks-in-jupyter) currently only supports Jupyter Notebook and JupyterLab. If you're using VSCode, you can try the [experimental nbdev VSCode extension](https://github.com/fastai/nbdev-vscode). Otherwise, you might also want to try [nbdev's pre-commit hooks](/tutorials/pre_commit.ipynb).\n", + "\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "See [_Git-friendly Jupyter_](git_friendly_jupyter.html) for more about how nbdev hooks work and how to customise them. Here's a short summary:\n", + "\n", + "- Fix broken notebooks due to git merge conflicts so that they can be opened and resolved directly in Jupyter.\n", + "- Each time you save a Jupyter notebook, automatically clean unwanted metadata to remove unnecessary changes in pull requests and reduce the chance of git merge conflicts.\n", + "- Automatically trust notebooks in the repo so that you can view widgets from collaborators' commits. For this reason, **you should not install hooks into a repo you don't trust**." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "::: {.callout-tip}\n", + "\n", + "nbdev's git hooks work on _any_ git repo, even if it doesn't use the broader nbdev system.\n", + "\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Build your library" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You should now create your package from your notebook by running:\n", + "\n", + "```sh\n", + "nbdev_export\n", + "```\n", + "\n", + "This will create Python modules for your notebooks. These modules will make up the contents of your Python package." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Install your package" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You might have noticed that `nbdev_new` created a Python package in your repo. In our case, it was automatically named `nbdev_hello_world` by using our repo name `nbdev-hello-world` and replacing `-` with `_` to make it a valid Python package." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next step is to install your package by entering this into your terminal:\n", + "\n", + "```sh\n", + "pip install -e '.[dev]'\n", + "```\n", + "\n", + "This is the recommended way to make a Python package importable from anywhere in your current environment:\n", + "\n", + "- `-e` -- short for \"editable\", lets you immediately use changes made to your package without having to reinstall, which is convenient for development.\n", + "- `.` -- refers to the current directory.\n", + "- `[dev]` -- includes \"development\" requirements: other packages that your notebooks use solely for documentation or testing." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Preview your docs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "nbdev is an interactive programming environment that values fast feedback loops. The `nbdev_preview` command helps achieve this by using Quarto to render your docs on your computer and keep them updated as your edit your notebooks." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Start the preview by entering this into your terminal:\n", + "\n", + "```sh\n", + "nbdev_preview\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It may say `Preparing to preview` for a few seconds while it gets started, and will eventually display something like:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```\n", + "Watching files for changes\n", + "Browse at http://localhost:3000/\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Click the link to open the preview in a new browser tab. It should look exactly like your online docs." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "::: {.callout-tip}\n", + "\n", + "We often find it useful to keep a preview window open on the side while we're editing our notebooks in Jupyter.\n", + "\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Edit 00_core.ipynb" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, open the `nbs/00_core.ipynb` file (generated by running `nbdev_new` earlier) in Jupyter. You don't *have* to start your notebook names with a number, but we find it helpful to show the order that your project should be read in -- even though it could have been created in a different order." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Add your own frontmatter" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You'll see something that looks a bit like this:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "::: {.py-2 .px-3 .mb-4 fig-align=\"center\" .border .rounded .shadow-sm}\n", + "\n", + "**core**\n", + "\n", + "> Fill in a module description here\n", + "\n", + "```python\n", + "#| default_exp core\n", + "```\n", + "\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's explain what these special cells means:\n", + "\n", + "- The first is a markdown cell with nbdev's markdown _frontmatter_ syntax that defines notebook metadata used by Quarto, our documentation engine (see the [frontmatter](/api/09_frontmatter.ipynb) reference page for more). It contains:\n", + " - H1 header (\"core\") -- defining the page title\n", + " - Quote (\"Fill in a module description here\") -- defining the page description\n", + "- The second is a code cell with a _directive_ `default_exp` which decides which module this notebook will export to (see the [Directives](/explanations/directives.ipynb) explanation for more). Currently, it exports to the `core` module." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, rename the notebook, replace the title and description, and change the default export module for your own project." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Once you're done, save the notebook. The live preview started in the previous section should update with your latest changes." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Rerun all cells in your notebook to ensure that they work, and to export the updated modules." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "::: {.callout-tip}\n", + "\n", + "We find the \"restart kernel and run all cells\" Jupyter command (the ⏩ button) so invaluable that we bind it to a keyboard shortcut. A common criticism of notebooks is that out-of-order execution leads to irreproducible notebooks. In our experience, making \"restart and rerun\" a habit solves this problem.\n", + "\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Running the notebook exports Python modules because of the last cell which contains:\n", + "\n", + "```python\n", + "#| hide\n", + "import nbdev; nbdev.nbdev_export()\n", + "```\n", + "\n", + "What does this mean?\n", + "\n", + "- `#| hide` is a directive (like `#| default_exp`) which excludes a cell from both your exported module and docs\n", + "- `nbdev_export` is the command used to export your notebooks to Python modules.\n", + "\n", + "We recommend including a cell like this at the bottom of all of the notebooks you want to export." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "::: {.callout-warning}\n", + "\n", + "Remember to delete any unused modules that aren't exported by a notebook or otherwise needed by your package. This is likely to happen if you change the default export of a notebook -- nbdev doesn't remove the old module. This is intended, since nbdev is designed to work with hybrid packages that use .py modules (with no corresponding notebook) as well as those exported from notebooks.\n", + "\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Add your own function" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a new code cell below the `#| default_exp` cell with a function. For example:\n", + "\n", + "```python\n", + "#| export\n", + "def say_hello(to):\n", + " \"Say hello to somebody\"\n", + " return f'Hello {to}!'\n", + "```\n", + "\n", + "Notice how it includes `#| export` at the top -- this is a directive (like `#| default_exp`) that tells nbdev to include the cell in your exported module and in your documentation.\n", + "\n", + "The documentation should look like this:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "::: {.py-2 .px-3 .mb-4 .border .rounded .shadow-sm}\n", + "\n", + "---\n", + "\n", + "### say_hello\n", + "\n", + "> say_hello (to)\n", + "\n", + "Say hello to somebody\n", + "\n", + ":::\n", + "\n", + "\n" + ] + } + ], + "source": [ + "#| echo: false\n", + "#| output: asis\n", + "def say_hello(to):\n", + " \"Say hello to somebody\"\n", + " return f'Hello {to}!'\n", + "\n", + "print(div(show_doc(say_hello)._repr_markdown_(),\n", + " classes='py-2 px-3 mb-4 border rounded shadow-sm'.split()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Add your own examples, tests, and docs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One of the superpowers of notebook-driven development is that you can very easily add examples, tests, and documentation right below your code." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Include regular code cells, and they'll appear (with output) in your docs, for example:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Hello Isaac!'" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "say_hello(\"Isaac\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is a test too! When you run `nbdev_test` it will execute this cell (and all other test cells) and fail if they raise any exceptions." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For tests, it's preferred to use more explicit `assert`s:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "assert say_hello(\"Hamel\") == \"Hello Hamel!\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "...or functions from [`fastcore.test`](https://fastcore.fast.ai/test.html), which behave like `assert` but also display the actual and expected values if they differ:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from fastcore.test import *" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test_eq(say_hello(\"Hamel\"), \"Hello Hamel!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another superpower of notebook-driven development is that your examples can include plots, images, and even JavaScript widgets. For example, here's an SVG circle:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display,SVG" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(SVG(''))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Prepare your changes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before commiting your changes to GitHub we recommend running `nbdev_prepare` in the terminal, which bundles the following commands:\n", + "\n", + "- `nbdev_export`: Builds the `.py` modules from Jupyter notebooks\n", + "- `nbdev_test`: Tests your notebooks\n", + "- `nbdev_clean`: Cleans your notebooks to get rid of extreanous output for git\n", + "- `nbdev_readme`: Updates your repo's `README.md` file from your index notebook." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Edit index.ipynb" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now you're ready to personalize your documentation home page and `README.md` file; these are both generated automatically from index.ipynb. Open Jupyter, then click on `nbs/index.ipynb` to open it." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We recommend including a longer description about what your package does, how to install it, and how to use it (with a few examples which import and use your package). Remember, examples can be code cells with real outputs rather than plain markdown text -- they'll double as tests too!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Push to Github" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can now commit and push your changes to GitHub. As we mentioned before, always remember to run `nbdev_prepare` before you commit to ensure your modules are exported and your tests pass. You can use `git status` to check which files have been generated or changed. Then:\n", + "\n", + "```sh\n", + "git add .\n", + "git commit -m 'Add `say_hello`; update index' # Update this text with your own message\n", + "git push\n", + "```\n", + "\n", + "This will kick-off your GitHub Actions. Wait a minute or two for those to complete, then check your updated repo and documentation." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Recap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Congratulations, you've used all of the basics needed to build delightful projects with nbdev! Here's a recap of the steps you took:\n", + "\n", + "- Installed hooks for git-friendly notebooks with `nbdev_install_hooks`\n", + "- Installed your package with `pip install -e '.[dev]'`\n", + "- Previewed your docs with `nbdev_preview`\n", + "- Added your own frontmatter, function, tests, and docs to `nbs/00_core.ipynb`\n", + "- Prepared your changes with `nbdev_prepare`\n", + "- Updated `nbs/index.ipynb` with your own information\n", + "- Pushed to GitHub.\n", + "\n", + "Read on to learn about more advanced nbdev functionality. Also see our [explanations](/explanations) for deep-dives on specific topics, as well as our other [tutorials](/tutorials)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Advanced functionality" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Add a class" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a class in `00_core.ipynb` as follows:\n", + "\n", + "```python\n", + "#| export\n", + "class HelloSayer:\n", + " \"Say hello to `to` using `say_hello`\"\n", + " def __init__(self, to): self.to = to\n", + " \n", + " def say(self):\n", + " \"Do the saying\"\n", + " return say_hello(self.to)\n", + "```\n", + "\n", + "This will automatically appear in the docs like this:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "---\n", + "\n", + "[source](https://github.com/fastai/nbdevblob/master/nbdev/tutorial.py#L12){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", + "\n", + "### HelloSayer\n", + "\n", + "> HelloSayer (to)\n", + "\n", + "Say hello to `to` using `say_hello`" + ], + "text/plain": [ + "---\n", + "\n", + "[source](https://github.com/fastai/nbdevblob/master/nbdev/tutorial.py#L12){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", + "\n", + "### HelloSayer\n", + "\n", + "> HelloSayer (to)\n", + "\n", + "Say hello to `to` using `say_hello`" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "class HelloSayer:\n", + " \"Say hello to `to` using `say_hello`\"\n", + " def __init__(self, to): self.to = to\n", + "\n", + " def say(self):\n", + " \"Do the saying\"\n", + " return say_hello(self.to)\n", + "\n", + "show_doc(HelloSayer)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Document with show_doc" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "However, methods aren't automatically documented. To add method docs, use `show_doc`:\n", + "\n", + "```python\n", + "show_doc(HelloSayer.say)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "---\n", + "\n", + "[source](https://github.com/fastai/nbdevblob/master/nbdev/tutorial.py#LNone){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", + "\n", + "### HelloSayer.say\n", + "\n", + "> HelloSayer.say ()\n", + "\n", + "Do the saying" + ], + "text/plain": [ + "---\n", + "\n", + "[source](https://github.com/fastai/nbdevblob/master/nbdev/tutorial.py#LNone){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", + "\n", + "### HelloSayer.say\n", + "\n", + "> HelloSayer.say ()\n", + "\n", + "Do the saying" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "show_doc(HelloSayer.say)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And add some examples and/or tests:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Hello Alexis!'" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "o = HelloSayer(\"Alexis\")\n", + "o.say()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Add links with backticks" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice above there is a link from our new class documentation to our function. That's because we used backticks in the docstring:\n", + "```python\n", + " \"Say hello to `to` using `say_hello`\"\n", + "```\n", + "These are automatically converted to hyperlinks wherever possible. For instance, here are hyperlinks to `HelloSayer` and `say_hello` created using backticks." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set up autoreload" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since you'll be often updating your modules from one notebook, and using them in another, it's helpful if your notebook automatically reads in the new modules as soon as the Python file changes. To make this happen, just add these lines to the top of your notebook:\n", + "\n", + "```\n", + "%load_ext autoreload\n", + "%autoreload 2\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set up prerequisites" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If your module requires other modules as dependencies, you can add those prerequisites to your `settings.ini` in the `requirements` section. The requirements should be separated by a space and if the module requires at least or at most a specific version of the requirement this may be specified here, too.\n", + "\n", + "For example if your module requires the `fastcore` module of at least version 1.0.5, the `torchvision` module of at most version 0.7 and any version of `matplotlib`, then the prerequisites would look like this:\n", + "```python\n", + "requirements = fastcore>=1.0.5 torchvision<0.7 matplotlib\n", + "```\n", + "\n", + "In addition to `requirements` you can specify dependencies with other keywords that have different scopes. Below is a list of all possible dependency keywords:\n", + "\n", + "- `requirements`: Passed to both pip and conda setup\n", + "- `pip_requirements`: Passed to pip setup only\n", + "- `conda_requirements`: Passed to conda setup only\n", + "- `dev_requirements`: Passed to pip setup as a development requirement\n", + "\n", + "For more information about the format of dependencies, see the pypi and conda docs on creating specifications in [setup.py](https://packaging.python.org/tutorials/packaging-projects/#creating-setup-py) and [meta.yaml](https://docs.conda.io/projects/conda-build/en/latest/resources/define-metadata.html), respectively." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set up console scripts" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Behind the scenes, nbdev uses that standard package `setuptools` for handling installation of modules. One very useful feature of `setuptools` is that it can automatically create [cross-platform console scripts](https://python-packaging.readthedocs.io/en/latest/command-line-scripts.html#the-console-scripts-entry-point). nbdev surfaces this functionality; to use it, use the same format as `setuptools`, with whitespace between each script definition (if you have more than one).\n", + "\n", + "```\n", + "console_scripts = nbdev_export=nbdev.cli:nbdev_export\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Upload to pypi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you want people to be able to install your project by just typing `pip install your-project` then you need to upload it to [pypi](https://pypi.org/). The good news is, we've already created a fully pypi compliant installer for your project! So all you need to do is register at pypi (click \"Register\" on pypi) if you haven't previously done so, generate an API token (go to [Account settings](https://pypi.org/manage/account/) and click \"Add API token\") and then create a file called `~/.pypirc` with your token details. It should have these contents:\n", + "\n", + "```\n", + "[pypi]\n", + "username = __token__\n", + "password = your_pypi_token\n", + "```\n", + "\n", + "Another thing you will need is `twine`, so you should run once\n", + "\n", + "``` \n", + "pip install twine\n", + "```\n", + "\n", + "To upload your project to pypi, just type `nbdev_pypi` in your project root directory. Once it's complete, a link to your project on pypi is displayed." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Upload to conda\n", + "\n", + "Similar to `pip install` support, we have provided an anaconda compliant installer to upload your project to [anaconda](https://anaconda.org). Once uploaded, your package can be installed by typing `conda install -c your_anaconda_username your-project`.\n", + "\n", + "You need to register at anaconda (fill out the form to `Sign Up`) which will create a username and password. You will then need to install the following packages\n", + "\n", + "```\n", + "pip install anaconda-client conda-build conda-verify\n", + "```\n", + "\n", + "Before running the anaconda uploader, you need to login to conda using the CLI command (you will be prompted to enter your username and password)\n", + "\n", + "```\n", + "anaconda login\n", + "```\n", + "\n", + "To upload to anaconda, just type `nbdev_conda` in your project root directory." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Upload to pypi and conda\n", + "\n", + "The command `nbdev_release_both` from the root of your nbdev repo will upload your project to both conda and pypi." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Install collapsible headings and toc2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are two jupyter notebook extensions that I highly recommend when working with projects like this. They are:\n", + "\n", + "- [Collapsible headings](https://jupyter-contrib-nbextensions.readthedocs.io/en/latest/nbextensions/collapsible_headings/readme.html): This lets you fold and unfold each section in your notebook, based on its markdown headings. You can also hit left to go to the start of a section, and right to go to the end\n", + "- [TOC2](https://jupyter-contrib-nbextensions.readthedocs.io/en/latest/nbextensions/toc2/README.html): This adds a table of contents to your notebooks, which you can navigate either with the `Navigate` menu item it adds to your notebooks, or the TOC sidebar it adds. These can be modified and/or hidden using its settings." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Math equation support" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "nbdev supports equations (using [Quarto](https://quarto.org/)). You can include math in your notebook's documentation using the following methods." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using `$$`, e.g.:\n", + "\n", + "```\n", + "\\sum_{i=1}^{k+1}i\n", + "```\n", + "\n", + "Which is rendered as:\n", + "\n", + "> \\sum_{i=1}^{k+1}i" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using `$`, e.g.:\n", + "\n", + "```\n", + "This version is displayed inline: \\sum_{i=1}^{k+1}i . You can include text before and after.\n", + "```\n", + "\n", + "Which is rendered as:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> This version is displayed inline: \\sum_{i=1}^{k+1}i . You can include text before and after." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For more information, see [the Quarto Docs](https://quarto.org/docs/visual-editor/technical.html)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Look at nbdev \"source\" for more ideas" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Don't forget that nbdev itself is written in nbdev! It's a good place to look to see how fast.ai uses it in practice, and get a few tips. You'll find the nbdev notebooks here in the [nbs folder](https://github.com/fastai/nbdev/tree/master/nbs) on Github." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Quarto Features" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "nbdev supports most Quarto features. We encourage you to read the [Quarto documentation](https://quarto.org/) to discover all the features available to you. For example, this is how you can [incorporate mermaid charts](https://quarto.org/docs/authoring/diagrams.html):\n", + "\n", + "```{mermaid}\n", + "flowchart LR\n", + " A[Hard edge] --> B(Round edge)\n", + " B --> C{Decision}\n", + " C --> D[Result one]\n", + " C --> E[Result two]\n", + "```\n", + "\n", + "Here is another example of using [Graphviz](https://quarto.org/docs/authoring/diagrams.html#graphviz):\n", + "\n", + "```{dot}\n", + "graph G {\n", + " layout=neato\n", + " run -- intr;\n", + " intr -- runbl;\n", + " runbl -- run;\n", + " run -- kernel;\n", + " kernel -- zombie;\n", + " kernel -- sleep;\n", + " kernel -- runmem;\n", + " sleep -- swap;\n", + " swap -- runswap;\n", + " runswap -- new;\n", + " runswap -- runmem;\n", + " new -- runmem;\n", + " sleep -- runmem;\n", + "}\n", + "```\n", + "\n", + "It is worth taking a look at the documentation for [figures](https://quarto.org/docs/authoring/figures.html), [callouts](https://quarto.org/docs/authoring/callouts.html), [markdown](https://quarto.org/docs/authoring/markdown-basics.html), [widgets](https://quarto.org/docs/interactive/widgets/jupyter.html), [layouts](https://quarto.org/docs/interactive/layout.html), [conditional content](https://quarto.org/docs/authoring/conditional.html) and [quarto extensions](https://quarto.org/docs/extensions/) to name a few useful things we have encountered." + ] + }, { "cell_type": "code", "execution_count": null,