back to index

nbdev tutorial


Chapters

0:0 Introduction
4:0 Creating a repo
11:25 envdev
13:10 notebook
16:40 documentation
17:30 testing
19:35 python module
22:50 index notebook
24:45 create documentation
31:30 class documentation
34:10 say hello
34:50 auto reload
36:55 running tests
38:20 installing Jekyll
40:10 console scripts
43:45 pipi
45:0 pip install
46:30 makefile
47:40 collapsible headings TOC
49:25 Notebooks
51:50 Editing Notebooks
56:5 Conventions

Whisper Transcript | Transcript Only Page

00:00:00.000 | - Yeah.
00:00:01.200 | - Okay, hi everybody.
00:00:02.340 | Welcome to this tutorial for NBDev.
00:00:06.520 | And I am joined by Silva.
00:00:10.720 | Say hello, Silva.
00:00:12.440 | - Hi.
00:00:13.800 | - Who you guys will know from Fast AI and Alexis.
00:00:18.040 | - Hello.
00:00:19.040 | - Who you won't know necessarily
00:00:21.280 | since he's known as a swift guy,
00:00:23.640 | but he's gonna be here to help
00:00:25.680 | with clarifications and questions
00:00:29.120 | and so forth along the way.
00:00:31.260 | You might recognize him actually briefly mentioned
00:00:35.440 | in part two of the most recent course
00:00:38.040 | during the swift bit.
00:00:41.280 | So we're gonna start,
00:00:43.160 | if you go to NBDev.fast.ai
00:00:46.040 | and on the left click on NBDev tutorial,
00:00:49.200 | we're just gonna step through it step by step.
00:00:51.280 | So there won't really be much information here
00:00:53.880 | that isn't already available
00:00:57.600 | in that tutorial.
00:00:59.520 | So if you're more of a reading person than a video person,
00:01:02.040 | feel free to do the reading version.
00:01:03.760 | So I won't go into too much detail about what NBDev is.
00:01:08.840 | There is as linked here,
00:01:10.680 | a post with a lot of information about why it exists
00:01:15.200 | and what it's for.
00:01:16.200 | But in brief, it's a system for exploratory programming,
00:01:20.400 | which is kind of a way of writing software,
00:01:23.480 | which involves or is kind of cognizant of the fact
00:01:27.240 | that I think for most of us,
00:01:29.120 | 90% of the time that we're programming,
00:01:31.120 | we're figuring out how to do things
00:01:33.280 | rather than just typing things in
00:01:35.000 | already knowing how to do things.
00:01:36.280 | So there's a lot of exploration and experimentation.
00:01:39.400 | And so we wanna support that
00:01:40.840 | and even make their process of developing it
00:01:44.720 | something that other people can see
00:01:46.240 | and learn from themselves.
00:01:47.520 | So the platform that is,
00:01:51.000 | this is all built on is as the name suggests,
00:01:53.400 | Jupyter Notebooks.
00:01:55.280 | So this is all gonna assume
00:01:56.560 | that you're at least somewhat familiar
00:01:57.800 | with Jupyter Notebooks already.
00:01:59.880 | Jupyter Notebooks are a very nice environment
00:02:02.560 | for exploring code and data.
00:02:06.500 | The only other thing I'll say is,
00:02:10.980 | Silva and I both feel like we're significantly
00:02:16.080 | as in like three to three times more productive
00:02:20.040 | using this notebook based way of programming
00:02:22.640 | than what we're used to being kind of traditional IDEs
00:02:27.640 | and editors and TDD and such like.
00:02:31.040 | But I will say it does require
00:02:33.320 | a somewhat different mindset,
00:02:34.400 | somewhat different way of doing things
00:02:36.840 | kind of involves really embracing
00:02:41.640 | the experimental side of things
00:02:43.940 | rather than trying to do everything totally top down
00:02:46.960 | in the way that we often learn it at school.
00:02:51.960 | All right, so anyway, let's get started.
00:02:54.640 | And so step one, so this thing we're looking at here,
00:02:57.520 | nbdev tutorial, not surprisingly comes from a notebook.
00:03:02.520 | So actually, if you click on GitHub over here,
00:03:08.520 | you can see nbdev's repository
00:03:14.720 | and in nbs is the notebooks for nbdev.
00:03:18.120 | And here is tutorial.
00:03:19.340 | So everything in nbdev itself comes from notebooks.
00:03:24.340 | So if you ever wanna know how something is written,
00:03:33.140 | an easy way would be just to actually have a look
00:03:37.140 | at those various notebooks.
00:03:40.040 | So for example, if we look in within Jupyter,
00:03:44.300 | here is the nbdev tutorial we're looking at right now.
00:03:48.100 | And you'll see that some things are added automatically
00:03:53.100 | for us, like a table of contents,
00:03:55.580 | we didn't have to write it ourselves.
00:03:57.540 | So step one is to create a repo.
00:04:03.460 | So I'm gonna try and show the easy low fiction way
00:04:10.020 | to do things once you learn more about how nbdev works,
00:04:13.660 | you'll find that there are different choices
00:04:17.420 | you could make always along the way.
00:04:18.980 | I'm gonna assume we're using GitHub
00:04:20.500 | 'cause that's the lowest fiction way.
00:04:22.460 | You can certainly use other repositories as well.
00:04:26.500 | So step one is to click on this link here,
00:04:29.220 | which takes advantage of a handy thing in GitHub
00:04:32.880 | called repository templates.
00:04:35.380 | And it will just make a copy
00:04:36.820 | of a kind of bare bones skeleton repository.
00:04:40.220 | So let's call this hello nbdev.
00:04:45.980 | - And just to add one position
00:04:47.980 | since we had a lot of people asking the link only works
00:04:50.700 | if you are logged in in GitHub.
00:04:53.740 | - Thank you, correct, correct.
00:04:57.020 | A tutorial example for nbdev.
00:05:02.020 | Okay, let's make that a public repository.
00:05:04.900 | Okay, here it is.
00:05:08.820 | And I realized I didn't open that in a new window.
00:05:12.220 | So let's go back here.
00:05:14.060 | Okay, so that is going ahead and creating a new repo.
00:05:18.580 | Here it is.
00:05:19.420 | So here's our nbdev repo that just got created.
00:05:22.000 | Not much to see at this stage.
00:05:27.000 | So step two, while we're there,
00:05:29.700 | is we're gonna set up our documentation site.
00:05:32.100 | The documentation for nbdev uses something called Jekyll,
00:05:37.900 | which is a simple thing that builds your site
00:05:41.980 | to allow it to be hosted on any kind of static host.
00:05:45.260 | GitHub Pages supports Jekyll.
00:05:47.380 | So you can host it there for free.
00:05:49.960 | You don't have to use that.
00:05:52.060 | You can use pretty much any host you can think of.
00:05:56.260 | But GitHub Pages is gonna be the easiest way.
00:05:58.360 | So let's go ahead and use that.
00:05:59.580 | So we have to enable it.
00:06:00.900 | So to enable GitHub Pages, we click Settings.
00:06:03.480 | And we scroll down to GitHub Pages
00:06:08.540 | and we click on Docs folder.
00:06:10.820 | And if we now scroll down again,
00:06:15.420 | you'll see your site is now ready to be published
00:06:17.860 | at this address.
00:06:19.180 | So I'm gonna go ahead and copy that address.
00:06:21.300 | And then as it says here, copy that URL,
00:06:27.260 | go back to your main repo page,
00:06:28.820 | click Edit next to the description
00:06:30.560 | and place the URL there.
00:06:33.500 | So we'll go back to here, click Edit, paste it here.
00:06:39.060 | Paste it here, save.
00:06:41.740 | Okay, so we've done the first bit.
00:06:45.900 | Step two, edit settings.py.
00:06:52.460 | Sorry, that should be settings.ini.
00:06:54.340 | We will fix that.
00:06:55.960 | In fact, let's go ahead and fix it now
00:06:58.700 | so that by the time you watch this, it will be fixed.
00:07:04.460 | Edit settings.ini, there we go.
00:07:09.460 | Okay, edit settings.ini.
00:07:12.660 | So this is basically the file
00:07:17.100 | that everything in your project will be,
00:07:20.620 | all the configuration will be created from that one place.
00:07:24.140 | That makes life really easy
00:07:25.220 | 'cause you don't have to edit anything else
00:07:27.740 | for your documentation, for your packaging, et cetera.
00:07:32.140 | So we're gonna edit all the commented out bits.
00:07:35.140 | So let's go ahead and find settings.ini and edit it.
00:07:40.140 | And all these sections here which are commented
00:07:45.640 | as it says they're required.
00:07:47.360 | So let's uncomment them.
00:07:48.880 | And we'll call this, hello, nvdev, user jphoo.
00:07:56.840 | User jphoo, description, a tutorial project for nvdev.
00:08:01.840 | Keywords, fast.ai, nvdev, tutorials.
00:08:13.080 | So these are just things that are gonna end up
00:08:14.360 | in the GitHub metadata
00:08:16.520 | and maybe in your PIP installers metadata.
00:08:19.220 | - So that's one question I'd sort of ask.
00:08:24.520 | What does all this give you?
00:08:26.640 | When I first interacted with it,
00:08:27.740 | I realized that there was this config file
00:08:29.840 | but I didn't realize how many things it drove.
00:08:31.480 | So it drives automatic document generation
00:08:34.200 | and then also other downstream configurations
00:08:37.080 | that let you easily share your library onto PyPy.
00:08:40.680 | Are those the main two sort of fallouts from it
00:08:43.200 | or is there anything else?
00:08:44.360 | - Also the actual Python project that is created
00:08:48.520 | from your notebooks.
00:08:55.760 | Yeah, those are basically the artifacts we end up creating
00:08:57.800 | an installer, a Python project, and documentation.
00:09:02.300 | - Okay, so those will all be things
00:09:04.440 | that's been in the nuisance to figure out individually
00:09:06.320 | but they'll come out--
00:09:07.160 | - Well, and also when they're in different files,
00:09:09.120 | it's kind of like probably six or seven different files
00:09:11.680 | that end up grabbing stuff for this,
00:09:14.360 | from the make file through to the navigation bar
00:09:16.960 | or through to the Jekyll config file, the setup.py file.
00:09:22.320 | So yeah, that's make life significantly easier.
00:09:26.080 | It also means we can create tools
00:09:27.880 | that know to read and write stuff in this one place.
00:09:31.760 | So it makes it easier to kind of modify the tooling.
00:09:35.000 | Other things you could put here,
00:09:36.700 | this is where the version number is.
00:09:39.300 | As you'll see, that's gonna be managed for us automatically.
00:09:42.280 | If you set your minimum Python here,
00:09:44.920 | then that'll change how your setup.py
00:09:47.880 | pip installation is done.
00:09:49.240 | This is also for your setup.py.
00:09:52.180 | The sidebar is the thing over here in your documentation,
00:09:57.180 | which is automatically created for you.
00:10:00.340 | If you wanna create a multi-layered sidebar,
00:10:02.580 | you can make it custom.
00:10:05.240 | You can choose a license.
00:10:06.780 | PyPy expects you to say one of these seven statuses.
00:10:12.700 | You can change where things live.
00:10:14.740 | This stuff down here, these %s things
00:10:18.960 | is because we're using a Python standard library module
00:10:22.380 | called config parser to read this.
00:10:24.340 | And this is how Python standard library config parser
00:10:27.920 | uses kind of variables.
00:10:29.180 | So in this case, user will be replaced
00:10:31.220 | with the value of user automatically by Python
00:10:34.100 | when it's read.
00:10:34.940 | So that is that file.
00:10:38.140 | So let's go ahead and commit that.
00:10:40.720 | Okay.
00:10:46.940 | So, oh, and we did skip a step which is to clone the repo.
00:10:51.940 | So let's go ahead and clone our repo as well.
00:10:58.940 | Okay, so JPHO/LONBDev.
00:11:11.660 | LONBDev.
00:11:12.500 | Cool, all right.
00:11:20.560 | Okay, so the next thing is Git and Jupyter Notebook
00:11:30.060 | don't always play nice together.
00:11:34.380 | A Jupyter Notebook, if you've never looked inside one,
00:11:39.920 | looks like this.
00:11:40.940 | As you can see, it's basically, it's, well, it is JSON.
00:11:45.740 | And when you move cells around or edit cells,
00:11:49.340 | or even run a cell to create outputs,
00:11:52.760 | it can create a whole lot of a big def basically,
00:11:55.760 | which can cause conflicts really easily.
00:12:01.580 | So one easy way to avoid those conflicts in the first place
00:12:04.860 | is to not save stuff to GitHub
00:12:08.140 | like cell metadata or notebook metadata.
00:12:11.380 | And so NBDev comes with things
00:12:13.640 | that will clean out that stuff for you.
00:12:16.080 | And so there's a whole bunch of command line tools in NBDev.
00:12:20.580 | If you type NBDev and hit tab, you'll see them all.
00:12:23.440 | And one of them is called install Git Hocks.
00:12:27.340 | So if we run that, then that will install things into Git,
00:12:31.360 | which will now automatically clean up that stuff,
00:12:35.480 | which could cause conflicts.
00:12:37.420 | If you do get a conflict anyway later on,
00:12:39.940 | if you're collaborating with somebody else,
00:12:42.500 | you can run NBDev fix merge with a file name,
00:12:47.000 | and it will try to merge them with an understanding
00:12:50.620 | of how Jupyter Notebooks work.
00:12:52.340 | And if it can't, it'll create a new readable notebook
00:12:57.340 | where the different cells are,
00:13:02.020 | the conflict cells are actually represented directly
00:13:04.260 | in the notebook.
00:13:06.640 | Okay, so we're now ready to edit our notebook.
00:13:11.640 | So you can run Jupyter Notebook if it's not already running.
00:13:17.860 | Personally, I tend to just have Jupyter Notebook
00:13:22.380 | always running in my notebooks directory.
00:13:25.580 | And so I can jump to any repo.
00:13:27.620 | So in this case, I can go to hello NBDev.
00:13:30.660 | And you'll see there's something here called 00 core.
00:13:33.540 | So core, you can call it anything you like.
00:13:38.540 | The core bit is gonna be what the HTML page will be called.
00:13:42.920 | The number is totally optional,
00:13:44.580 | but so that and I have found it pretty handy
00:13:47.380 | to have incrementing numbers as you add more notebooks,
00:13:51.560 | 'cause it kind of gives the reader a sense of it all.
00:13:55.500 | How was this built?
00:13:56.740 | What order should I read to understand
00:13:58.660 | if I wanna understand all the details
00:14:00.260 | of how something is put together?
00:14:01.900 | - Are any special Jupyter extensions required
00:14:06.900 | to be installed on the Jupyter server
00:14:09.060 | that's used for notebooks?
00:14:10.140 | - No, nothing's required.
00:14:11.460 | - Okay.
00:14:12.300 | - Okay, so when we open it up,
00:14:17.820 | as it says, you see something like this.
00:14:19.940 | So let's look at what this all means.
00:14:24.060 | You'll see there's some comments which are special.
00:14:31.540 | So the first special comment is default export comment.
00:14:36.480 | And this is the name of the Python module
00:14:40.060 | that is going to be created.
00:14:42.280 | So in our case,
00:14:46.920 | our Python module is gonna be called Hello NBDev.
00:14:57.260 | So this will create a sub module called Hello NBDev.core.
00:15:02.260 | So that's what the special comment means.
00:15:06.080 | So when we run the various NBDev commands,
00:15:09.100 | they look for various special comments,
00:15:10.860 | and this is an important one.
00:15:12.260 | This is another special comment,
00:15:14.820 | and it means when you create the documentation,
00:15:17.140 | don't include this in it.
00:15:18.700 | Otherwise, pretty much everything in the notebook
00:15:20.820 | is included in the documentation,
00:15:23.060 | unless you specifically say hide.
00:15:27.180 | - Just one thought since we're here
00:15:29.740 | for the default export name.
00:15:31.140 | Pretty sure that if you want all the links
00:15:34.420 | to work properly in the documentation,
00:15:36.020 | the default export name should be kind of
00:15:37.860 | the same as the notebook.
00:15:39.220 | So if you want to export in core,
00:15:40.700 | your notebook should be named something underscore core,
00:15:44.660 | like 00 underscore core.
00:15:46.340 | And if it's like core.utils,
00:15:48.420 | it should be named 001.core.utils, and so on and so forth.
00:15:53.220 | - Yeah, well, I've never tried not doing it that way.
00:15:55.100 | - So that's probably gonna make a lot of--
00:15:56.740 | - Miniver, but some users have.
00:15:58.780 | Yeah, some users haven't reported
00:16:00.460 | that the links didn't work, so.
00:16:01.660 | - Fair enough, yes.
00:16:02.900 | Okay, so, all right, so that's default X.
00:16:08.820 | The next one to know about is hash export.
00:16:13.500 | So we're gonna add a function to this notebook.
00:16:15.420 | So let's just go ahead and copy and paste this one.
00:16:17.820 | And it's just a perfectly normal Python function
00:16:23.600 | with one exception, which is it says hash export at the top.
00:16:26.760 | So hash export means please include this cell
00:16:32.220 | in the exported, in this case,
00:16:33.860 | hello nbdev.core package.
00:16:37.000 | So now that we've done that,
00:16:41.180 | oh, and the other thing it does is it's gonna include,
00:16:45.020 | include it in the documentation.
00:16:46.980 | So if you have a look at the tutorial, for instance,
00:16:51.340 | you can see that I've got this function here.
00:16:55.600 | And you can see in the tutorial,
00:16:57.660 | the function has automatically created this documentation
00:17:02.420 | with the docstring, a link to the source,
00:17:06.120 | and parameters and so forth.
00:17:08.100 | So that's what export does, it does those two things,
00:17:12.420 | puts it in the Python module,
00:17:14.180 | and if it's a function or a class or a variable assignment,
00:17:17.980 | it'll put it in the documentation.
00:17:20.720 | Sorry, if it's a function or a class,
00:17:23.440 | it'll put it in the documentation in that special form.
00:17:26.140 | Okay, so the whole point of one of the key points of this
00:17:33.960 | is to experiment and to show people that experimentation.
00:17:38.960 | So let's go ahead and actually run that.
00:17:46.520 | And so, and we can add some more information.
00:17:50.240 | There's just in markdown or whatever.
00:17:52.040 | Okay, hello, so far.
00:18:07.520 | - Hi.
00:18:09.240 | - And yeah, as it mentions here, you can,
00:18:14.040 | and it's a good idea to put in plots and images
00:18:16.920 | and stuff like that, so here's an example of SVG.
00:18:19.520 | And what we do a lot, and we find it works pretty well,
00:18:23.840 | is to also include tests.
00:18:27.120 | So, all right, so we've already got an error in our test,
00:18:34.440 | that's good, oh, and that's why,
00:18:38.560 | because it's printing rather than returning.
00:18:40.920 | So you can see what happens when you get a test failure,
00:18:45.920 | it just appears here, and that will also appear later on
00:18:50.920 | when you see the test runner,
00:18:54.360 | it can also appear in the terminal or continuous integration,
00:18:59.360 | which we'll also learn about.
00:19:01.200 | And this will by default appear in the documentation.
00:19:06.200 | So I probably don't really want this import line to appear,
00:19:10.880 | so let's move that into the hidden cell.
00:19:12.840 | But it's not a bad idea to actually include
00:19:15.680 | at least a few basic tests in the documentation,
00:19:18.000 | 'cause it can show people exactly
00:19:20.520 | what behavior they should expect.
00:19:22.360 | So that's a bit of a, I don't know,
00:19:25.680 | taste issue as to how many tests you hide
00:19:28.280 | and how many you show.
00:19:31.080 | So far, and I tend to err on the side
00:19:34.240 | of showing rather than hiding.
00:19:35.980 | All right, so now we can create our Python module.
00:19:40.640 | So nbdev build-lib, we'll build it.
00:19:44.480 | And you can run most nbdev commands from anywhere
00:19:50.720 | inside your repo, you don't have to be
00:19:52.480 | at the root of the repo.
00:19:53.680 | And as you can see, it's converted
00:19:57.160 | the two Python files we have.
00:19:59.280 | And so we now have a hello nbdev folder,
00:20:03.040 | and it contains these files,
00:20:09.040 | and there's the one we just created.
00:20:13.600 | And as you see, it's got a little bit more
00:20:15.560 | than what we asked for.
00:20:17.440 | In particular, it's defined under all.
00:20:19.880 | It's considered a best practice in Python
00:20:21.760 | to just export using under all the things
00:20:24.400 | that you actually want to export.
00:20:26.000 | And so it actually gets a little bit easier
00:20:28.440 | with nbdev to follow that best practice.
00:20:31.440 | - So just to spell it out here,
00:20:35.600 | the package or the project becomes a Python package,
00:20:40.240 | and then every notebook becomes a Python module.
00:20:43.720 | Is that correct?
00:20:44.720 | - Exactly, and you can create sub-modules as well,
00:20:46.880 | just by putting, instead of export this one,
00:20:51.880 | instead of default exp-core, it'd be default exp-blah.
00:21:04.200 | It would be default exp-blah.blah to create a sub-module.
00:21:08.960 | - An export means that it goes into the module and the docs.
00:21:18.400 | Hide means it goes into neither,
00:21:21.160 | and if there's no annotation,
00:21:23.240 | then that means it goes into the docs, but not the module.
00:21:25.880 | - Exactly.
00:21:26.720 | - You also have exports with an S for export and show,
00:21:32.440 | and this will go into the module,
00:21:34.040 | and the source code will sustain the documentation
00:21:37.160 | if you want the source code to be in your documentation
00:21:40.280 | website.
00:21:41.120 | - Yeah, which is actually what I probably should have done
00:21:43.200 | back here for the tutorial.
00:21:45.800 | I wrote the source code in the markdown
00:21:49.040 | and also put it here so that you would see the source code
00:21:52.440 | as well, but I probably should have just used exports,
00:21:54.880 | would be another way to kind of do the same thing.
00:21:57.320 | But I don't use exports very often.
00:22:01.080 | Normally you don't really want to show the source code
00:22:03.800 | of a function in the documentation,
00:22:05.640 | but sometimes it happens.
00:22:07.600 | - Is there any support for the,
00:22:10.760 | how is, how is non-markdown cell content treated at all?
00:22:15.160 | Or maybe it's not.
00:22:16.160 | But does it make it into the docs successfully?
00:22:17.960 | - Non-markdown meaning,
00:22:19.720 | I mean, there's only really two types
00:22:21.160 | who would use markdown or code.
00:22:24.240 | Code appears directly, outputs appear,
00:22:27.400 | and markdown appears as HTML.
00:22:30.360 | - I guess I meant like if you had markdown
00:22:31.680 | that was effectively including an image of some kind.
00:22:34.840 | - Yep, all that kind of markdown will work fine.
00:22:38.160 | Yep, yep, so images and all that stuff
00:22:42.920 | is all supported, plots, et cetera.
00:22:45.760 | Okay, so now we can create or edit index notebook
00:22:53.280 | and that's gonna be what your documentation homepage
00:22:57.520 | and readme is automatically generated from.
00:23:00.200 | So here's index.
00:23:04.760 | And so the first thing to do is to note
00:23:09.240 | that it's importing your lib.core.
00:23:12.280 | So we should import, change that to hello nvdev.core
00:23:17.280 | and let's see if that cell runs.
00:23:21.040 | It did, so we have successfully imported something.
00:23:24.800 | You'll see that in both here and here,
00:23:29.800 | there's a kind of slightly special markdown
00:23:32.560 | which is an h1 followed by a quote.
00:23:35.120 | This is used to create the HTML documentation title
00:23:40.120 | and initial heading in your documentation.
00:23:44.160 | So you should keep it in this format.
00:23:48.320 | So welcome to, hello.
00:23:54.800 | Wow, nvdev, what's up?
00:23:58.800 | - Just to learn nvdev but you can put world if you want.
00:24:05.560 | - Fair enough, not the world, just to nvdev.
00:24:07.720 | An amazing tutorial.
00:24:12.280 | Okay, we hope you enjoy this project.
00:24:21.640 | Okay, so the main thing to do here
00:24:24.760 | is to make sure that it works.
00:24:27.280 | So say hello, Alexis.
00:24:32.280 | Great, let's see this at work.
00:24:39.760 | Okay, so that's done.
00:24:45.400 | So now we can create our documentation.
00:24:51.320 | So we now go nvdev build ducks.
00:24:56.320 | And so you'll now see there is in ducks
00:25:06.840 | a index.html and a core.html.
00:25:17.840 | All right, so let's try to commit this.
00:25:21.520 | So we do git status.
00:25:24.760 | We'll see there's a whole bunch of extra stuff here.
00:25:28.480 | So let's add it.
00:25:29.600 | And so you can see the things that it's modified for us
00:25:39.960 | if you want to dig into the details,
00:25:41.320 | things like the sidebar, the navigation bar,
00:25:45.120 | the config for YAML.
00:25:48.120 | One thing you might want to do actually
00:25:50.000 | is the init.py that's created for you is by default empty.
00:25:55.000 | So you might, for example, want to go,
00:25:58.000 | oh, from.core import star.
00:26:03.000 | So if you did that, then that would allow us
00:26:07.560 | to modify our index example
00:26:14.040 | to just import directly from hello nvdev.
00:26:17.000 | Let's test that still works.
00:26:19.680 | It does, cool.
00:26:21.840 | So let's commit that.
00:26:26.240 | And it commit, push.
00:26:35.840 | There we go.
00:26:41.440 | Okay, so GitHub is gonna go ahead and process that commit.
00:26:46.440 | And so if we go back to the main GitHub page,
00:26:54.440 | we'll see we now have more than one commit.
00:27:00.800 | So if I click on here,
00:27:04.680 | you can see that initially there's an X.
00:27:10.640 | And that X, if I click on it,
00:27:12.520 | tells me it failed to build my project.
00:27:16.080 | And so specifically, you can see that it...
00:27:20.640 | Let's see.
00:27:24.320 | It failed to find the description flag
00:27:33.320 | in my settings.any.
00:27:34.560 | So when you first clone the repo by definition,
00:27:40.560 | it's not in a state that's ready.
00:27:42.720 | So this is kind of the way that nvdev
00:27:45.720 | with the help of GitHub actions automatically checks
00:27:50.400 | that all of your bits and pieces work, as you can see.
00:27:56.360 | So it's gonna make sure it can install it,
00:27:57.960 | that it can read the notebooks,
00:27:59.840 | that they don't have that extra metadata,
00:28:02.680 | that the library matches the notebooks,
00:28:07.240 | and that the tests all run.
00:28:09.600 | So that generally takes a couple of minutes.
00:28:12.400 | Okay, so this one's now finished, and we still have an X.
00:28:17.480 | So let's go and find out what went wrong.
00:28:19.280 | Now a test didn't run.
00:28:23.280 | Ah, so in this case, I tried to use tests from FastCore,
00:28:34.120 | and they failed.
00:28:35.360 | So let's go ahead and fix that.
00:28:37.880 | So to fix that, the best way to do it is to tell nvdev,
00:28:42.880 | or which it really talks to Python's setup tools,
00:28:46.040 | that we need FastCore installed.
00:28:49.040 | So to do that, as you would hopefully expect,
00:28:54.040 | it's in settings.any, and you'll see here,
00:28:57.200 | there's a section called requirements,
00:28:59.120 | and we can just add space separated any requirements we have.
00:29:05.320 | In this case, FastCore.
00:29:07.880 | - And that's the PyPy package name?
00:29:09.800 | - That is correct, yep.
00:29:11.360 | And if you're a more advanced user,
00:29:15.080 | and you want to kind of debug things,
00:29:18.040 | or customize things more carefully,
00:29:21.280 | you'll see that the setup.py is,
00:29:24.200 | it's only 46 lines of code, right?
00:29:26.840 | We try to make everything super simple.
00:29:28.640 | And you can see it's just like, as I said,
00:29:30.120 | it's just using config parser.
00:29:31.840 | And so if you want to see how those requirements
00:29:34.160 | are being read,
00:29:36.480 | you can see it's just grabbing the requirements thing,
00:29:38.800 | and splitting it,
00:29:40.600 | and then setting that to install requires.
00:29:43.840 | So it's a pretty thin wrapper over,
00:29:47.000 | for example, setup tools.
00:29:48.400 | Okay, so,
00:29:52.480 | add FastCore depth, get push.
00:29:59.280 | Okay.
00:30:00.120 | And let's go check our documentation,
00:30:08.240 | because it did say that the page built correctly.
00:30:13.240 | So we should now be able to click on
00:30:15.480 | the web link we created earlier.
00:30:18.420 | And there it is, there's our documentation.
00:30:22.600 | And you'll see this module name here
00:30:27.920 | has automatically been grabbed from over here.
00:30:32.280 | So while we're here, let's go ahead and fix that.
00:30:34.880 | Hello, nbdev, I guess it should be this really.
00:30:40.680 | And you can see the title's been set over here.
00:30:50.440 | And here is the automatically generated documentation,
00:30:56.200 | the docstrings being put here,
00:30:57.640 | and you can see the inputs and outputs,
00:30:59.240 | markdown all in one place.
00:31:01.740 | Great.
00:31:07.760 | Oh, and now we have a tick.
00:31:11.240 | Okay, so that means that it successfully
00:31:13.720 | completed all the steps.
00:31:18.520 | So that's kind of like enough to
00:31:26.000 | get started, the basics are now all in place.
00:31:30.400 | So from here, we can start adding
00:31:32.920 | some more advanced functionality.
00:31:34.920 | So for instance, class.
00:31:38.720 | Okay, so here's a class.
00:31:50.200 | And so when you have a class,
00:31:54.800 | it appears in the documentation like this.
00:31:58.840 | So it's got the docstring for the class,
00:32:01.000 | link to the source for the class,
00:32:02.400 | and the parameters for the constructor.
00:32:04.400 | The methods are not documented automatically.
00:32:09.440 | So to add method documentation,
00:32:12.420 | you have to add a call to the special showdoc,
00:32:20.520 | which is part of nbdev.showdoc.
00:32:24.800 | And so when we do that, as you can see,
00:32:27.480 | it makes it appear here.
00:32:29.560 | And so it might be nice to include a docstring.
00:32:31.960 | You don't have to, but now it'll appear here.
00:32:39.440 | And in the documentation, the showdoc input would appear,
00:32:42.900 | just this markdown output.
00:32:44.800 | So this kind of makes it nice and easy to,
00:32:50.960 | intersperse markdown comments and images and plots
00:32:55.480 | and whatever in amongst your documentation of your class
00:32:58.140 | and add headings and stuff like that.
00:33:00.600 | And I should mention, it's a really good idea
00:33:02.200 | to add headings because it's gonna help
00:33:05.480 | your table of contents.
00:33:06.920 | It makes it easier to get around.
00:33:08.760 | So I might say, for example, functions here.
00:33:18.640 | And then classes will automatically add their own heading.
00:33:23.520 | And so this method will already sit underneath
00:33:26.620 | the Hallowsayer headings.
00:33:29.540 | We don't have to do that.
00:33:30.800 | Yeah, and let's add examples.
00:33:40.080 | Always a good idea.
00:33:45.560 | Or you could add tests.
00:33:46.920 | So we have a bug, which is now that should return.
00:33:51.920 | Great, and we could have used a test of course.
00:34:00.680 | All right.
00:34:03.760 | So here's something neat, which is, see here,
00:34:14.560 | it says say hello to using say hello.
00:34:17.960 | And that say hello, if I click on it,
00:34:20.660 | jumps to the documentation to say hello.
00:34:24.240 | Even although I didn't create the link.
00:34:29.240 | So nbdev will look for anything in backticks,
00:34:33.460 | whether it be in markdown or docstrings or whatever.
00:34:37.040 | And it will attempt to see if it can resolve it
00:34:40.080 | at the Python symbol.
00:34:41.480 | And if it can, it will create a hyperlink
00:34:44.240 | through the definition of that symbol.
00:34:46.080 | So you can see not only do we have it in the docstring here,
00:34:52.120 | but you can also see here that I've got hyperlinks
00:34:57.000 | in markdown.
00:34:57.840 | Again, they were just created using backticks.
00:35:01.480 | So that's something pretty handy.
00:35:05.640 | - And does it look through all things in backticks
00:35:08.640 | or only cells that are exported?
00:35:10.080 | 'Cause I noticed that right now
00:35:11.120 | the class definition is not exported yet.
00:35:14.500 | - Yes, it'll only create links to things
00:35:18.300 | that it can actually resolve.
00:35:20.500 | So if something's not exported,
00:35:21.820 | then it won't be able to resolve it.
00:35:23.580 | So yeah, let's fix that.
00:35:26.780 | Thank you.
00:35:30.340 | Okay, this is not an nbdev thing,
00:35:36.700 | but just a useful tip.
00:35:38.080 | These two lines will set up what's called auto reload,
00:35:41.820 | which is, so for example, in index,
00:35:44.960 | where we're using this module,
00:35:51.360 | if we have these two lines as the first two lines,
00:35:54.660 | then every time we update hello world nb.core,
00:35:59.660 | we don't have to manually restart this kernel.
00:36:05.820 | That code will automatically be available
00:36:07.820 | inside this notebook.
00:36:09.020 | So that's a useful thing to add.
00:36:12.100 | The other useful thing to add
00:36:17.500 | is to put these two lines at the very end
00:36:19.900 | of your exported notebook along with a hash hide.
00:36:27.780 | And this is exactly the same as running nbdev buildlib.
00:36:34.220 | So if I run this cell,
00:36:37.300 | and if we now have a look at our module,
00:36:40.140 | you'll see that class has been added.
00:36:46.140 | Okay, so that's that.
00:36:56.380 | So now that's all done.
00:36:58.340 | Let's make sure we haven't broken anything
00:36:59.980 | by running all of our tests.
00:37:01.700 | And tests can be in any notebook at all.
00:37:05.040 | So to run all of our tests in all notebooks,
00:37:08.120 | we can just run nbdev test nbs.
00:37:11.020 | And that'll actually run the test
00:37:12.460 | in all notebooks in parallel.
00:37:14.100 | So even when you've got a pretty big repo,
00:37:16.780 | like we do for fast.aiv2, it just takes a few seconds.
00:37:20.900 | There we go.
00:37:24.500 | And if there were any errors,
00:37:25.500 | it would pop them up and show you the stack trace
00:37:27.780 | of where the test failed.
00:37:29.520 | - One thing to add about the tests documentation
00:37:34.060 | and building the library is that if you're working
00:37:36.660 | on a notebook and it's not finished yet,
00:37:38.460 | you can put an underscore at the beginning of its name
00:37:41.500 | and it won't be considered by all of those commands.
00:37:44.060 | - Let's try that.
00:37:47.140 | new Python three,
00:37:53.020 | one over zero,
00:37:56.660 | rename underscore,
00:38:03.820 | not finished.
00:38:05.540 | No problem.
00:38:16.220 | Okay.
00:38:17.060 | All right.
00:38:24.480 | Sometimes your documentation will fail to build.
00:38:28.640 | GitHub pages will give you a red cross next to the bit
00:38:32.140 | where it's trying to build the pages.
00:38:33.660 | But it tends not to give you any information about why.
00:38:37.020 | So to find out why,
00:38:38.380 | it's a good idea to set up Jekyll locally,
00:38:41.760 | if there's a problem.
00:38:42.660 | Also, it's sometimes nice just to look at your docs locally
00:38:45.980 | rather than pushing and seeing how they look
00:38:48.420 | only after GitHub builds them.
00:38:51.300 | So you need to install Jekyll to do that.
00:38:55.340 | If you're on Ubuntu,
00:38:56.380 | the easiest way is the official on Jekyll installation.
00:39:00.080 | Run these exact lines of code
00:39:02.860 | and that will install Jekyll.
00:39:05.080 | And then after you've done that,
00:39:11.460 | the next step is to CD into the docs directory
00:39:16.140 | and type bundle install.
00:39:17.880 | Okay.
00:39:23.840 | Then CD back to your repo root and type make docs serve.
00:39:29.660 | Okay.
00:39:30.500 | Okay, that.
00:39:43.820 | So that's listening on port 4000.
00:39:47.300 | I'm actually not running this locally, it's remote.
00:39:49.780 | And I'm doing SSH forwarding.
00:39:51.460 | So I need to do something slightly different,
00:39:54.620 | but there we go.
00:39:55.740 | So here you can see it is running locally.
00:39:59.780 | Okay.
00:40:00.620 | Cool.
00:40:03.220 | When you're done, control C will kill it.
00:40:05.540 | Okay, prerequisites we've already done.
00:40:10.580 | The next thing to mention is console scripts.
00:40:16.260 | So maybe you want to create a console script.
00:40:21.260 | There's actually a very nice system in setup tools
00:40:28.460 | for creating console scripts that will actually work
00:40:30.540 | on Windows or Mac or Linux automatically and the trick.
00:40:35.540 | And that's a surface through again, settings.any.
00:40:40.820 | And the trick is to create a line
00:40:44.040 | like this console scripts equals.
00:40:47.120 | And so one easy way to see how this works
00:40:50.300 | is to look at nbdev.
00:40:56.700 | And you'll see there's a 06 CLI here.
00:40:59.420 | And we use our fast script library for creating these.
00:41:07.780 | But you can just have a normal,
00:41:10.820 | if name equals main or whatever.
00:41:12.740 | In fact, you don't actually need that for console scripts.
00:41:14.500 | You can just create a function that looks at sys.argv.
00:41:17.800 | And so once you've got a function,
00:41:21.840 | all you need to do is to add
00:41:24.420 | to your settings.any console scripts equals.
00:41:27.500 | This is going to be the name of the script that you want.
00:41:30.460 | This is the name of your library.
00:41:33.540 | This is the name of your module where you defined it.
00:41:36.680 | And this is the name of the function.
00:41:38.340 | - So this is showing us the configuration
00:41:41.620 | which actually creates the nbdev build live
00:41:44.660 | with console script itself.
00:41:46.820 | - Exactly, exactly.
00:41:48.940 | Now, just putting it in the settings.any doesn't do anything.
00:41:52.340 | You have to install it to make it work.
00:41:55.100 | And so that you can test it,
00:41:56.980 | the easiest way is to type pip install minus e dot
00:42:01.980 | from the root of your repo.
00:42:03.940 | And that does something called an editable install.
00:42:07.740 | And that will install the console scripts in such a way
00:42:12.380 | and the module in such a way
00:42:14.100 | that it's actually linking back to the live code.
00:42:16.420 | So you can change things without having to reinstall.
00:42:19.380 | And so that's a nice, easy way to test your module
00:42:23.260 | in other projects and to test your console scripts
00:42:26.420 | without having to reinstall it each time.
00:42:30.100 | - Sorry, I know you said this,
00:42:32.460 | but just looking at that configuration,
00:42:33.700 | why does nbdev build live appear twice
00:42:37.140 | before the second equal sign and after?
00:42:39.500 | - This is the name of the console script
00:42:41.620 | that you're creating.
00:42:42.700 | - Okay.
00:42:43.540 | - This is the name of the function that is being called.
00:42:47.340 | - Okay.
00:42:48.180 | - So they could be different.
00:42:50.400 | - Okay, so nbdev.cli is naming a module.
00:42:53.260 | And then nbdev build lib is the function within that module.
00:42:56.940 | - Yeah, in fact, maybe rather than looking at the notebook,
00:42:59.900 | let's look at the generated module.
00:43:02.900 | So if you look at nbdev, cli, here is nbdev build lib.
00:43:10.260 | So it is a function inside nbdev.cli.
00:43:18.700 | - Okay, so you could use this,
00:43:22.060 | if those two names weren't identical,
00:43:23.780 | to define a script that had a slightly different name
00:43:26.020 | from the function that you use.
00:43:27.780 | - Yep, and for more information about this,
00:43:31.660 | click on this little cross-platform console scripts link
00:43:34.900 | in the tutorial where it'll explain,
00:43:36.860 | 'cause it's all just passing it through to setup tools,
00:43:39.620 | which is the standard library thing in Python.
00:43:41.580 | So you can see all the details there.
00:43:46.060 | - Thanks for the question.
00:43:47.820 | All right, so since this is such a great module,
00:43:50.640 | and probably everybody on the internet will want to use it,
00:43:53.220 | we should make it easier for everybody to use
00:43:55.100 | by uploading it to PyPy,
00:43:57.500 | so that people can then go pip install hello nbdev.
00:44:02.420 | So, first of all, click where it says PyPy here,
00:44:08.780 | if you haven't ever done this before.
00:44:10.940 | And then click on register,
00:44:13.380 | and go ahead and create an account.
00:44:15.780 | And then once you have your account,
00:44:18.740 | create this file called .pypyrc in your home directory,
00:44:23.360 | containing those three lines.
00:44:25.580 | I've already done that.
00:44:28.660 | So since I've done that,
00:44:30.040 | I can go ahead and say make release.
00:44:35.680 | And what that will do is it will bump the version,
00:44:40.700 | 'cause you can't have two releases
00:44:41.920 | with the same version number, and then upload it.
00:44:44.700 | And so if you now look at cat settings.any,
00:44:48.260 | you'll see it's now 002,
00:44:50.180 | and you'll see that it has uploaded it to PyPy.
00:44:53.620 | And so now, we can go and have a look.
00:44:57.080 | There we go.
00:45:01.960 | So now you can pip install hello nbdev.
00:45:04.640 | And so you can see everything's gonna happen for you.
00:45:10.620 | Your index has automatically been put into here.
00:45:14.220 | Your homepage has automatically been set
00:45:18.940 | to the GitHub repo, which is not working.
00:45:23.500 | Oh, 'cause I named it wrongly.
00:45:24.980 | Let's fix that.
00:45:29.260 | Vim settings.any.
00:45:31.340 | Yes, so the GitHub repo actually set a different name
00:45:37.220 | to the library name.
00:45:38.060 | That's gonna confuse everybody,
00:45:40.500 | but we can fix it in one place.
00:45:42.380 | All right, so let's go ahead and commit that.
00:45:47.380 | Fix gh link.
00:45:58.700 | And let's do another release.
00:46:12.460 | And so this will bump the version to 003.
00:46:14.900 | And we should now be able to...
00:46:21.060 | There we go.
00:46:24.380 | Here's 003.
00:46:25.220 | Cool.
00:46:31.680 | All right, so.
00:46:32.820 | - So just, sorry, this may be the basic question,
00:46:35.180 | but make release, does that just call the same scripts
00:46:39.180 | that you were showing individually before, like nbdev?
00:46:41.860 | - Okay, exactly.
00:46:42.700 | So here's the makefile.
00:46:43.740 | So the makefile to create a distribution
00:46:48.460 | is python-setup.py.
00:46:49.820 | This is just the standard setup tools.
00:46:52.100 | And release will bump clean,
00:46:56.680 | bump calls nbdev-bump-version.
00:46:58.900 | Plain calls...
00:47:02.820 | Plain calls rm-rf-dist.
00:47:10.340 | And then twine-upload is a thing.
00:47:13.940 | And you'll need to have installed twine.
00:47:15.180 | So pip install twine if you don't already have it.
00:47:17.620 | So yeah, so you can see, for example,
00:47:18.900 | when you go docs-serve, it calls nbdev-build-docs
00:47:22.860 | and then calls the standard Jekyll thing.
00:47:25.860 | So yeah, the makefile is teeny tiny.
00:47:29.220 | And you don't have to use the makefile at all.
00:47:35.180 | If you're not into makefiles,
00:47:36.260 | you can just run any of those things manually.
00:47:38.460 | So Alexis, you asked earlier about
00:47:43.460 | whether any extensions are required.
00:47:49.060 | And the answer was no.
00:47:50.860 | But there are two extensions that we do recommend,
00:47:53.720 | not just for nbdev, but for anything
00:47:56.660 | where you're just trying to create
00:47:58.340 | and use well-structured notebooks.
00:48:01.260 | The first is collapsible headings.
00:48:02.960 | And collapsible headings is the thing
00:48:06.420 | that is allowing me, for example,
00:48:10.340 | if you look at the tutorial,
00:48:11.700 | these little arrows here, I can collapse them.
00:48:15.340 | I never use the arrows.
00:48:16.580 | I always hit right and left.
00:48:17.700 | So right goes to the end of a section.
00:48:19.780 | Left goes to the start.
00:48:21.620 | Left again to close it up.
00:48:23.460 | Left again to go to the start of the super section.
00:48:26.620 | Left again to close that up.
00:48:28.700 | So that's collapsible headings, which is super handy.
00:48:31.780 | And the other one that's super handy is TOC2.
00:48:35.980 | Table of contents.
00:48:39.020 | And you can configure that in various different ways,
00:48:41.700 | but the main thing I find useful
00:48:44.100 | is that I get this nice navigate menu
00:48:49.380 | to jump straight to anything,
00:48:50.800 | which gives me the same functionality
00:48:53.260 | as I have in the documentation
00:48:56.780 | that gives me these table of contents.
00:49:03.340 | Which is probably gonna be easier to see
00:49:05.220 | if I look at the tutorial.
00:49:06.980 | Oops, that should be last AI.
00:49:09.100 | Yeah, nbdev, great.
00:49:14.520 | So the contents is automatically created.
00:49:19.060 | So I don't need it in Jekyll.
00:49:21.540 | Okay.
00:49:25.500 | So yeah, finally, I don't know,
00:49:29.540 | it's often just helpful to see
00:49:31.100 | how things have already been written in another context.
00:49:36.100 | And so going and having a look at the nbdev notebooks,
00:49:40.140 | all that functionality you've seen is just in
00:49:42.580 | one, two, three, four, five, six, seven, eight notebooks.
00:49:46.780 | And like, for example,
00:49:48.280 | have a look at our export, right?
00:49:53.180 | And it kind of gives you a sense
00:49:55.300 | of how we go about programming.
00:49:59.320 | You can see like it starts with like,
00:50:01.880 | what's a notebook?
00:50:02.900 | A notebook is JSON.
00:50:07.100 | So here's something like starts right at step one.
00:50:09.820 | So like, if you're trying to understand all the detail
00:50:11.900 | of how nbdev works, then start here,
00:50:14.820 | because you can see the very first bit,
00:50:16.620 | which is where we actually read the JSON of a notebook.
00:50:19.660 | And then you can see it's created a dict
00:50:21.900 | and here's the keys of the dict.
00:50:24.060 | And here's an example of the metadata and so forth.
00:50:28.020 | So kind of, we kind of try to write,
00:50:31.160 | this is how we explore, right?
00:50:32.820 | Is when we start, when we started this,
00:50:35.060 | we didn't know much about what a notebook is
00:50:37.620 | in terms of how it was formatted.
00:50:39.220 | So as we started building the functions to read it
00:50:41.500 | and explore it, that became part of the documentation
00:50:46.180 | and part of the process.
00:50:47.740 | And so then you can also see that the checks
00:50:49.900 | that we did along the way as we tried to build something
00:50:52.920 | to test whether a cell has some particular
00:50:55.740 | or expression and so forth.
00:50:58.020 | So yeah, and then as you go along,
00:51:01.160 | you might see, you know, other little things
00:51:04.120 | which we haven't described like default class level.
00:51:06.380 | And then you can go and search the documentation
00:51:08.100 | to find out what they are.
00:51:09.500 | And wow, that was good timing.
00:51:13.140 | That was exactly an hour.
00:51:14.980 | Any things you guys wanted to mention?
00:51:17.940 | Anything we missed?
00:51:18.900 | Any questions?
00:51:19.860 | - I had one question.
00:51:22.900 | I know that you work in a notebook
00:51:25.500 | and then using these compile tools essentially,
00:51:28.220 | you can generate a Python module.
00:51:29.900 | It's like what you would have if you'd worked
00:51:31.700 | with a traditional text editor or an ID.
00:51:34.160 | But people already have tool choices
00:51:35.940 | that they're comfortable with.
00:51:37.520 | Let's say you do that and then you want to go in
00:51:39.780 | and make a change directly to the Python code
00:51:42.900 | that's been generated.
00:51:43.740 | How do you get the change back into the notebook?
00:51:45.300 | Is that always a manual process?
00:51:47.640 | - Not at all.
00:51:48.820 | So that's a really good point.
00:51:51.540 | And we encourage people where possible
00:51:56.540 | where appropriate to edit things in the notebook.
00:52:01.600 | And the reason for that is that in the notebook,
00:52:03.580 | you can see that context.
00:52:05.500 | There's a pros about why is it done this way
00:52:07.620 | or what else did we try?
00:52:08.860 | You can see the tests right next to it.
00:52:10.660 | You can explore to make sure the change you made
00:52:13.220 | really is working the way you thought it was.
00:52:15.860 | But sometimes there's extremely good reasons
00:52:20.460 | to modify the actual Python files.
00:52:25.460 | And so in particular,
00:52:32.880 | when you're kind of starting to find your way
00:52:39.100 | around something,
00:52:40.500 | it can be really helpful to use kind of the tags features,
00:52:47.320 | for example.
00:52:48.160 | So if I'm reading through this and I'm like,
00:52:49.580 | oh, what's say hello do?
00:52:51.600 | And so I'd like in VMI hit control right square bracket
00:52:54.180 | to jump straight to the definition of say hello.
00:52:56.460 | And obviously, particularly across files,
00:52:58.020 | this is really useful.
00:52:59.100 | And then maybe you just want to explore
00:53:01.780 | by like adding the print statement somewhere,
00:53:05.660 | or maybe you find like a typo in a doc string.
00:53:09.580 | So there's no particular point to go
00:53:11.300 | all the way back to the notebook.
00:53:13.060 | So let's say we do that.
00:53:19.300 | Anybody at all?
00:53:21.780 | All right, so I've only changed the doc string.
00:53:23.180 | So there's no particular point to go back to the notebook,
00:53:26.860 | but I would like to now have that be modified
00:53:29.380 | in the notebook as well.
00:53:31.260 | So to do that, I just type nb dev update lib instead
00:53:36.260 | of build lib.
00:53:37.420 | And so that will modify the notebook
00:53:40.540 | to match the changed module.
00:53:43.840 | So if we now go back to oocor,
00:53:46.100 | there is the change.
00:53:51.100 | Now, this is not for doing like major refactorings and stuff.
00:53:57.820 | It's kind of, you can only do small changes.
00:54:04.380 | It's relying on these special cell comments
00:54:07.020 | to kind of know where cells are
00:54:08.500 | and to be able to find the right place to change.
00:54:11.100 | But for little changes like that, it'll work fine.
00:54:14.660 | Yes, the main thing is, as long as you don't want
00:54:17.000 | to add a new cell, it's gonna work.
00:54:19.280 | But that's the only limitation.
00:54:20.960 | - Yep.
00:54:23.240 | Anything else?
00:54:26.040 | - And to complete what you just said,
00:54:28.240 | if at any point you want to see the diff
00:54:30.840 | between the notebooks and the library,
00:54:32.480 | there is a command for that, which is nb dev diff
00:54:36.740 | or something, we've stopped complete.
00:54:39.760 | I named them, but I forgot all the names.
00:54:44.360 | So let's say we want to go back to what we had before.
00:54:47.340 | nb dev diff nb's.
00:54:53.320 | - Diff nb's, yeah.
00:54:54.280 | - And so you can see this is the difference
00:54:57.480 | between the notebook and the module.
00:55:01.480 | And this is run automatically when you push.
00:55:08.140 | And so if there's a difference, it'll tell you so.
00:55:12.760 | And so one obvious way to fix that is just to run
00:55:15.600 | nb dev build lib, for instance.
00:55:19.800 | And then there won't be a difference anymore.
00:55:22.360 | Well, that's an impressive.
00:55:25.100 | - Down to the kernel there.
00:55:30.400 | - What just happened?
00:55:31.400 | That's terrifying.
00:55:34.960 | Did my whole machine just blow up
00:55:36.280 | when we were chatting here or something?
00:55:38.120 | That was weird.
00:55:40.800 | I mean, get cwd, no such file or directory.
00:55:43.600 | Wow, oh, I see what happened.
00:55:45.760 | I said nb dev build lib when I was inside the lib.
00:55:48.960 | So the directory I was in had just got replaced
00:55:51.760 | by a new directory and didn't exist anymore.
00:55:54.280 | I don't quite know what that's got to do with the MKL,
00:55:56.240 | but it's all good.
00:55:58.860 | Right.
00:56:02.960 | Okay, anything else?
00:56:04.320 | - I think I just want to pull things together
00:56:08.120 | to make sure I understood one thing.
00:56:09.020 | It sounds like there's a set of conventions
00:56:11.640 | that you need to follow for this to work,
00:56:14.240 | but they're pretty straightforward.
00:56:16.060 | Basic one is that the project becomes a package,
00:56:19.560 | the notebooks become modules.
00:56:21.540 | It's advisable, maybe necessary, I'm not sure about that,
00:56:24.880 | that the notebooks be named
00:56:26.520 | with this number prefixing convention.
00:56:28.960 | - I'm not sure the number prefixing is necessary.
00:56:30.960 | The fact that they match the name
00:56:33.040 | with the modules and documentations is necessary.
00:56:38.040 | The numbers is just a recommendation, I think.
00:56:44.040 | - A lot of the names that need to be aligned
00:56:46.760 | could be, are specified in the settings on any file.
00:56:50.440 | And then there's also a special markdown cell
00:56:52.440 | which needs to be set up in a certain way
00:56:55.340 | that has an h1 header, a quote,
00:56:57.280 | and then possibly text afterwards.
00:56:59.280 | - You could, if you don't have that,
00:57:01.080 | it'll just mean that you'll have some default
00:57:04.320 | or you won't have a proper title and stuff.
00:57:07.280 | - All right, so that just affects how the docs look.
00:57:09.200 | That's not something where it's parsed.
00:57:10.800 | - The default exp is necessary.
00:57:13.360 | Now that I think about it, I don't know why it's necessary
00:57:15.480 | because we should be able to just grab it from the name.
00:57:18.560 | Maybe by the time you're watching this,
00:57:19.780 | that will be fixed.
00:57:21.760 | - It's just because sometimes you have notebooks
00:57:24.320 | that are not exported at all.
00:57:25.760 | So you need a way to--
00:57:27.160 | - Yeah, that makes sense.
00:57:28.480 | - Oh yeah, and then there's a convention
00:57:29.720 | around underscore notebooks not being exported.
00:57:32.280 | And in terms of what someone would need to use this,
00:57:36.320 | you need to have stuff like Python assault, obviously,
00:57:39.960 | but you need Jekyll installed
00:57:42.160 | to do the document generation locally.
00:57:45.240 | This thing called Twine, it's also part of the--
00:57:50.000 | - You can store Twine in order to push to PayPal.
00:57:53.280 | Other than those, everything is automatically installed
00:57:56.320 | when you pip install mbdev.
00:57:59.600 | - Okay.
00:58:00.440 | - Including Jupyter, which,
00:58:05.640 | but if you've installed from Anaconda,
00:58:08.880 | that'll be installed for you anyway.
00:58:11.440 | - And in terms of the key mechanics of interaction,
00:58:13.920 | there's a set of build tools for building the load,
00:58:16.240 | for building the docs.
00:58:17.480 | There's a make file for like bumping versions
00:58:22.320 | and uploading docs.
00:58:23.480 | And then within the notebooks themselves,
00:58:24.980 | there's hide, which means don't put it in the module
00:58:27.160 | or the docs.
00:58:28.000 | There's export, which means put it in the module
00:58:29.560 | and the docs.
00:58:30.840 | There's nothing at all,
00:58:31.680 | which means only put it in the docs.
00:58:33.160 | And then there's export s or exports,
00:58:35.120 | which means put the code as well as the--
00:58:38.520 | - Yeah, the export code.
00:58:40.040 | - As well as the export in the docs in the module.
00:58:44.360 | - Right, exactly.
00:58:45.320 | - Just wanna make sure I had the essentials right.
00:58:49.760 | - No, that's very helpful, thank you.
00:58:52.000 | Okay.
00:58:52.840 | Thanks, Kang.
00:58:54.680 | See you next time we do a thrilling tutorial.
00:58:58.800 | - Awesome.
00:58:59.640 | - All right.
00:59:00.460 | - See you.
00:59:01.460 | - Bye.
00:59:02.300 | [BLANK_AUDIO]