Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] adding a CLI to generate books #89

Merged
merged 18 commits into from
Feb 9, 2019

Conversation

choldgraf
Copy link
Member

@choldgraf choldgraf commented Jan 23, 2019

This is a CLI to generate books, riffing off of #87 here's the help section:

Creating new books:

jupyter-book create [--out-folder OUT_FOLDER] [--license LICENSE]
                    [--content-folder CONTENT_FOLDER] [--toc TOC]
                    [--config CONFIG] [--custom-css CUSTOM_CSS]
                    [--custom-js CUSTOM_JS] [--overwrite] [--demo]
                    name

### Create a new Jupyter Book

positional arguments:
  name                  The name of your Jupyter Book (your book template will
                        be placed in a folder of this name)

optional arguments:
  -h, --help            show this help message and exit
  --out-folder OUT_FOLDER
                        The location where your book will be placed
  --license LICENSE     A path to a LICENSE.md file if you have already
                        created one
  --content-folder CONTENT_FOLDER
                        A path to a folder that holds your book content
  --toc TOC             A path to a yaml file that contains a Table of
                        Contents for your Jupyter Book. This will overwrite
                        parts of the book template's default toc.yml
                        configuration
  --config CONFIG       A path to a configuration YAML file that contains
                        configuration for your Jupyter Book. This will
                        overwrite parts of the book template's default
                        _config.yml configuration
  --custom-css CUSTOM_CSS
                        A path to a CSS file that defines some custom CSS
                        rules for your book
  --custom-js CUSTOM_JS
                        A path to a JS file that defines some custom CSS rules
                        for your book
  --overwrite           Whether to overwrite a pre-existing book if it exists
  --demo                Whether to build the book with demo content instead of
                        your own content

Building book markdown:

jupyter-book build [--path-book PATH_BOOK]
                    [--path-template PATH_TEMPLATE]
                    [--path-config PATH_CONFIG] [--path-toc PATH_TOC]
                    [--overwrite] [--execute] [--local-build]

Convert a collection of Jupyter Notebooks into Jekyll markdown suitable for a
course textbook.

optional arguments:
  -h, --help            show this help message and exit
  --path-book PATH_BOOK
                        Path to the root of the textbook repository.
  --path-template PATH_TEMPLATE
                        Path to the template nbconvert uses to build markdown
                        files
  --path-config PATH_CONFIG
                        Path to the Jekyll configuration file
  --path-toc PATH_TOC   Path to the Table of Contents YAML file
  --overwrite           Overwrite md files if they already exist.
  --execute             Execute notebooks before converting to MD.
  --local-build         Specify you are building site locally for later
                        upload

If you don't give a --content-folder or --toc parameter, then it'll ask you to manually input the path to one per @arokem's suggestions.

Upgrade the book

This will create a copy of the book with the latest jupyter-book
template, then copy over the new files into your current book, preserving
the files that you've modified on your own.

jupyter-book upgrade path_book

Upgrade a book to the latest Jupyter Book version.

positional arguments:
  path_book   Path to the root of the book repository you'd like to upgrade.

To do

  • Write tests
  • Finalize CLI API
  • Finalize interactive inputs
  • Figure out the best way to auto-generate a toc.yml file if none is given (e.g. should it just be a flat list of pages, or should we try to infer page nesting etc)

To demo the CLI

I have a demo of the CLI running on Binder here:

https://mybinder.org/v2/gh/choldgraf/jupyter-book/cli?urlpath=terminals/1

that'll open a terminal - you should then be able to type

jupyter-book create <arbitraryname> --demo

and it'll create a jupyter book in <arbitraryname> with the "demo" content (which is the content from the website).

you should then be able to run:

jupyter-book build --path-book <arbitraryname>

and it'll build the markdown for the book.

Comments?

What do folks think about this general approach? Thoughts ideas etc would be appreciated! cc also @yuvipanda !

@choldgraf
Copy link
Member Author

Anybody know what is the best way to ensure that a folder is copied over when you pip install something? I need to install the CLI which is in 'jupyter-book' but also have access to the template in 'book_template'

@arokem
Copy link
Contributor

arokem commented Jan 25, 2019 via email

@choldgraf
Copy link
Member Author

hmm, I'm not sure how this can include a whole folder of data files. Here's my conundrum:

The project structure in this PR looks like this:

./
├── book_template
├── jupyter_book
├── requirements.txt
└── setup.py

If I install with pip, then this goes to .../site-packages/jupyter_book/<contents-of-jupyter_book-folder>.

What I'd actually like to happen is that either:

.../site-packages/book_template/

would also exist, or

.../site-packages/jupyter_book/jupyter_book
.../site-packages/jupyter_book/book_template

would exist.

Any ideas on how that could happen?

@arokem
Copy link
Contributor

arokem commented Jan 26, 2019 via email

@choldgraf
Copy link
Member Author

so that's basically what I'm doing:

https://github.com/jupyter/jupyter-book/pull/89/files#diff-2eeaed663bd0d25b7e608891384b7298R8

then

https://github.com/jupyter/jupyter-book/pull/89/files#diff-2eeaed663bd0d25b7e608891384b7298R32

Shouldn't running pip install . then deposit everything in book_template into the site-packages/jupyter-book folder?

import os.path as op
from glob import glob

template_files = glob(op.join('jupyter_book', 'book_template', '**', '*'), recursive=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
template_files = glob(op.join('jupyter_book', 'book_template', '**', '*'), recursive=True)
template_files = glob(op.join('book_template', '**', '*'), recursive=True)

Following the shablona example, I think that this might need to be a path relative to the package.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, if that doesn't work:

Suggested change
template_files = glob(op.join('jupyter_book', 'book_template', '**', '*'), recursive=True)
template_files = [op.join('book_template', '*'), op.join('book_template', '*', '*')]

And so on, for as many levels of recursion as you need.

@choldgraf
Copy link
Member Author

ahh I think I figured it out - there was a gotcha in there. setup.py does indeed want paths relative to the package (in this case jupyter_book) however since I was using glob( to list those paths, I still needed to use the "correct" relative paths first. So I have to glob the files, then remove the top-level folder from each resulting path. Intuitive!

@choldgraf
Copy link
Member Author

choldgraf commented Jan 26, 2019

OK I have a demo of the CLI running on Binder here:

https://mybinder.org/v2/gh/choldgraf/jupyter-book/cli?urlpath=terminals/2

that'll open JupyterLab - you should be able to then open a terminal and type

jupyter-book create <arbitraryname> --demo

and it'll create a jupyter book in <arbitraryname> with the "demo" content (which is the content from the website).

you should then be able to run:

jupyter-book build --path-book <arbitraryname>

and it'll build the markdown for the book.

If anybody wants to give it a shot and give feedback on the API etc, that'd be helpful!

(and thanks @arokem for the help on the package_data!)

@gnestor
Copy link

gnestor commented Jan 29, 2019

I just tried it out and it works great!

I was going to suggest removing the --path-book argument from jupyter-book build and make the path the default argument but it looks like the API has changed and that is now the case 👍

The only issue is that I'm unable to serve the book on binder:

jovyan@jupyter-choldgraf-2djupyter-2dbook-2dmt96jhm3:~/my-book$ make serve
bundle exec guard
make: bundle: Command not found
Makefile:27: recipe for target 'serve' failed
make: *** [serve] Error 127

jovyan@jupyter-choldgraf-2djupyter-2dbook-2dmt96jhm3:~/my-book$ make install
gem install bundler
make: gem: Command not found
Makefile:14: recipe for target 'install' failed
make: *** [install] Error 127

@choldgraf
Copy link
Member Author

choldgraf commented Jan 29, 2019

Woot! thanks for the feedback - the latest push adds a binder/ folder that uses a conda environment with Ruby installed (turns out you can install Ruby with conda-forge on *nix). That should work (though I dunno if the port opening will work within Binder).

Any other thoughts on the CLI itself? Seems like a reasonable choice to create books / update old books / etc?

Edit: hmmm I take that back, it doesn't seem like Binder can build the gems needed because a file isn't there that it expects to be there:

/srv/conda/bin/ruby -r ./siteconf20190129-373-di8g14.rb extconf.rb
creating Makefile

current directory: /home/jovyan/.gem/ruby/2.4.0/gems/commonmarker-0.18.2/ext/commonmarker
make "DESTDIR=" clean

current directory: /home/jovyan/.gem/ruby/2.4.0/gems/commonmarker-0.18.2/ext/commonmarker
make "DESTDIR="
compiling arena.c
make: /home/conda/feedstock_root/build_artifacts/ruby_1537084490905/_build_env/bin/x86_64-conda_cos6-linux-gnu-cc: Commandnot found

@gnestor
Copy link

gnestor commented Jan 29, 2019

I think the interface is great 👍

@kysolvik
Copy link

kysolvik commented Feb 1, 2019

I think your suggestion sounds good. If you wanted to keep the prompts, you could set the default for content as "None" or something similar, with a message that if they don't specify a content dir it creates an empty/simple one. But maybe more trouble than it's worth vs. just removing the prompts.

Originally I was thinking of an optional flag similar to --demo, like "--blank" or "--empty"

@choldgraf
Copy link
Member Author

choldgraf commented Feb 2, 2019

OK the latest push removes the interactive prompts for book content. If someone just types:

jupyter-book create mybook

then it'll simply add a bare-bones book w/ just a few pages of content to get you started (and adds this to the notice at the end).

If you add content with the --content flag, then it'll ask you if you want to create a table of contents file if you haven't specified one.

@kysolvik wanna give that a shot? seem more intuitive? less?

@lheagy
Copy link

lheagy commented Feb 7, 2019

Hi Chris, this is looking good! One question about consistency: in the book setup the flags for the path to the toc, config, etc are just --toc, --config, whereas for the build, these are now pre-pended with path, e.g. --path-toc, --path-config. Is this distinction intentional? or can we update to make them consistent? (I would vote for the less-verbose version --toc, --config unless others have strong opinions)

@choldgraf
Copy link
Member Author

@lheagy I think that's a great point, will take a pass to standardize these flags

@choldgraf
Copy link
Member Author

ok, CLI should now be more consistent. Thanks for all of your advice on this one @arokem @gnestor @kysolvik @yuvipanda and @lheagy - if you have any other thoughts please do share them! Otherwise I'll plan on merging this ~tomorrow after going through the docs once more

@choldgraf choldgraf mentioned this pull request Feb 8, 2019
@choldgraf
Copy link
Member Author

ok! I took another pass at docs and updated the TOC part of the CLI, and magically the tests are still passing, and so I am merging this!! Let's goooooo 🎉

@choldgraf choldgraf merged commit 43874c9 into executablebooks:master Feb 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants