Commit 420628a0 authored by Matthieu Boileau's avatar Matthieu Boileau
Browse files

Merge branch 'develop' into 'master'

v0.3.0

Closes #22

See merge request !17
parents 57e3f22a 8bb1921a
Pipeline #10130 failed with stages
in 1 minute and 6 seconds
*
!pyproject.toml
......@@ -15,3 +15,4 @@ tests/notebooks
*.egg-info/
dist/
poetry.lock
.venv
image: boileaum/jupyter
variables:
GIT_SUBMODULE_STRATEGY: recursive
stages:
- deps
- test
- deploy
before_script:
- curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
- source $HOME/.poetry/env
deps:
stage: deps
tags:
- shell
script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker info
- echo "Building $CI_REGISTRY_IMAGE"
- DOCKER_BUILDKIT=1 docker build --pull -t $CI_REGISTRY_IMAGE -f Dockerfile .
- docker push $CI_REGISTRY_IMAGE
test:
stage: test
image: $CI_REGISTRY_IMAGE
tags:
- docker
script:
......@@ -21,6 +28,7 @@ test:
deploy:
stage: deploy
image: $CI_REGISTRY_IMAGE
tags:
- docker
script:
......
# Changelog
## [0.3.0] - 2020-11-05
### Changed
- `style_ipython.tplx` -> `style_ipython.tex.j2` in `/theme/default/templates/book.tplx`. Please update this file in your local `theme/` dir if you are using nbconvert >= 6.0
- some code enhancement
### Fixed
- Fix issues with pdf generation using nbconvert >= 6.0
FROM boileaum/jupyter
# From Jupyter Project <jupyter@googlegroups.com>
LABEL maintainer="Matthieu Boileau <matthieu.boileau@math.unistra.fr>"
COPY pyproject.toml .
RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
ENV PATH="$HOME/.poetry/bin:$PATH"
RUN poetry install
\ No newline at end of file
"""
Build a small website to host Jupyter notebooks as course chapters
"""
import logging
import argparse
from .nbcourse import NbCourse, DEFAULT_CONFIG_FILE
from .initialize import initialize
from pathlib import Path
from .mydoit import MyDoitHelp, ClassTaskLoader
def get_help_epilog() -> str:
"""Instanciate a minimal nbcourse to return help string"""
course = NbCourse()
loader = ClassTaskLoader(course)
return MyDoitHelp(task_loader=loader).get_help()
def main():
"""CLI for nbcourse"""
prog = globals()['__package__']
description = globals()['__doc__']
formatter = argparse.RawDescriptionHelpFormatter
epilog = get_help_epilog()
parser = argparse.ArgumentParser(prog=prog,
description=description,
formatter_class=formatter,
epilog=epilog)
init = parser.add_argument_group('initialize')
init.add_argument('--init', action='store_true',
help=initialize.__doc__)
generate = parser.add_argument_group('generate')
generate.add_argument('--config', dest='config_file', type=Path,
default=DEFAULT_CONFIG_FILE,
help='Load YAML file describing site configuration '
'(default: %(default)s)')
# Handle undefined arguments
parsed, extra = parser.parse_known_args()
if parsed.init:
initialize()
else:
course = NbCourse(parsed.config_file)
course.build(extra)
log = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
......@@ -2,7 +2,7 @@
python -m nbcourse module entry point to run via python -m
"""
from . import main
from .main import main
if __name__ == '__main__':
......
import jinja2
import logging
from . import log
import os
from bookbook.latex import combine_and_convert
from pathlib import Path
logging.basicConfig(level=logging.INFO)
log = logging.getLogger(__name__)
class BookContext:
"""
......
"""
Build a small website to host Jupyter notebooks as course chapters
"""
import argparse
from .nbcourse import NbCourse, DEFAULT_CONFIG_FILE
from .initialize import initialize
from pathlib import Path
from .mydoit import MyDoitHelp, ClassTaskLoader
def get_help_epilog() -> str:
"""Instanciate a minimal nbcourse to return help string"""
course = NbCourse()
loader = ClassTaskLoader(course)
return MyDoitHelp(task_loader=loader).get_help()
def main():
"""CLI for nbcourse"""
prog = globals()['__package__']
description = globals()['__doc__']
formatter = argparse.RawDescriptionHelpFormatter
epilog = get_help_epilog()
parser = argparse.ArgumentParser(prog=prog,
description=description,
formatter_class=formatter,
epilog=epilog)
init = parser.add_argument_group('initialize')
init.add_argument('--init', action='store_true',
help=initialize.__doc__)
generate = parser.add_argument_group('generate')
generate.add_argument('--config', dest='config_file', type=Path,
default=DEFAULT_CONFIG_FILE,
help='Load YAML file describing site configuration '
'(default: %(default)s)')
parser.add_argument('--verbosity', '-v', type=str, )
# Handle undefined arguments
parsed, extra = parser.parse_known_args()
if parsed.init:
initialize()
else:
course = NbCourse(parsed.config_file)
course.build(extra)
......@@ -8,6 +8,7 @@ Define a NbCourse object containing:
from pathlib import Path, PosixPath
import yaml
from doit.tools import create_folder, config_changed
from . import log
from .utils import update_material, clean_tree, get_file_list, update_dict, \
zip_files
from .pages import HomePage, MarkdownPage
......@@ -16,11 +17,8 @@ import nbformat
from nbconvert.preprocessors import ExecutePreprocessor
from nbconvert import HTMLExporter, SlidesExporter
from .mydoit import MyDoitMain, ClassTaskLoader
import logging
import sys
log = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
DEFAULT_CONFIG_FILE = "nbcourse.yml"
......@@ -28,39 +26,39 @@ DEFAULT_CONFIG_FILE = "nbcourse.yml"
class NbCourse:
default_conf = {
'theme': {
'dir': 'theme/default',
'material': ('css', 'img')
},
'nb': {
'dir': '.',
'timeout': 60,
'material': ()
},
'pages': {
'dir': 'pages',
'home': 'index.html'
},
'book': {
'titlepage': 'titlepage.tex',
'file': None,
},
'local_reveal': False,
'slug_title': 'course',
'output_dir': 'build',
'title': 'A course',
'subtitle': None,
'favicon': None,
'picture': None,
'authors': [],
'chapter_preview_only': [],
'license': None,
'links': {'manual': {
'title': 'Manual',
'target': 'manual.html',
}
}
}
'theme': {
'dir': 'theme/default',
'material': ('css', 'img')
},
'nb': {
'dir': '.',
'timeout': 60,
'material': ()
},
'pages': {
'dir': 'pages',
'home': 'index.html'
},
'book': {
'titlepage': 'titlepage.tex',
'file': None,
},
'local_reveal': False,
'slug_title': 'course',
'output_dir': 'build',
'title': 'A course',
'subtitle': None,
'favicon': None,
'picture': None,
'authors': [],
'chapter_preview_only': [],
'license': None,
'links': {'manual': {
'title': 'Manual',
'target': 'manual.html',
}
}
}
def __init__(self, user_conf=None):
"""Build from user_conf"""
......@@ -72,12 +70,12 @@ class NbCourse:
self.conf[key]['material_paths'] = [
self.conf[key]['path'] / Path(d)
for d in self.conf[key]['material']
]
]
self.conf['pages']['path'] = Path(self.conf['pages']['dir'])
self.conf['output_path'] = Path(self.conf['output_dir'])
if self.conf['local_reveal']:
self.conf['reveal_path'] = Path(__file__).parent / \
Path('reveal.js')
Path('reveal.js')
self.notebooks = tuple(self.conf['nb']['path'].glob('*-*.ipynb'))
if user_conf and not self.notebooks:
log.error("""
......
from . import log
import nbformat
import re
import logging
import markdown
from pathlib import Path
from pprint import pformat
......@@ -9,9 +9,6 @@ from bs4 import BeautifulSoup
import frontmatter
import sys
log = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
class Page:
"""An abstract class for a static web page"""
......@@ -64,7 +61,7 @@ class HomePage(Page):
nb = nbformat.read(str(path), as_version=4)
if nb.cells[0].cell_type != 'markdown':
log.error(f"The first cell of the notebook {path} should be Markdown type " +
log.error(f"The first cell of the notebook {path} should be Markdown type " +
f"({nb.cells[0].cell_type} instead).")
sys.exit()
lines = nb.cells[0].source.splitlines()
......
% Default to the notebook output style
((* if not cell_style is defined *))
((* set cell_style = 'style_ipython.tplx' *))
((* set cell_style = 'style_ipython.tex.j2' *))
((* endif *))
% Inherit from the specified cell style.
......
[tool.poetry]
name = "nbcourse"
version = "0.2.6"
version = "0.3.0"
description = "Create a minisite to publish a course based on Jupyter notebooks"
authors = ["Matthieu Boileau <matthieu.boileau@math.unistra.fr>"]
license = "MIT"
......@@ -10,8 +10,7 @@ readme = "README.md"
[tool.poetry.dependencies]
python = "^3.7"
nbconvert = "^5.6.1"
bookbook = "^0.2"
nbconvert = ">=6.0"
bs4 = "^0.0.1"
IPython = "^7.15.0"
jinja2 = "^2.11.2"
......@@ -22,6 +21,7 @@ rise = "^5.6.1"
pyyaml = "^5.3.1"
doit = ">=0.32.0"
python-frontmatter = "^0.5.0"
bookbook = { git = "https://github.com/boileaum/bookbook.git", branch = "master" }
[tool.poetry.dev-dependencies]
pytest = "^5.4.3"
......
appnope==0.1.0; sys_platform == "darwin" or platform_system == "Darwin"
attrs==19.3.0
appnope==0.1.0; sys_platform == "darwin" and platform_system == "Darwin"
argon2-cffi==20.1.0
async-generator==1.10; python_version >= "3.5"
attrs==20.3.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
backcall==0.2.0
beautifulsoup4==4.9.1
bleach==3.1.5
bookbook==0.2
beautifulsoup4==4.9.3
bleach==3.2.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
bookbook @ git+https://github.com/boileaum/bookbook.git@master ; python_version >= "3.5"
bs4==0.0.1
cloudpickle==1.4.1
colorama==0.4.3; sys_platform == "win32"
cffi==1.14.3
cloudpickle==1.6.0; python_version >= "3.5"
colorama==0.4.4; python_version >= "2.7" and python_full_version < "3.0.0" and sys_platform == "win32" or python_full_version >= "3.5.0" and sys_platform == "win32"
data==0.4
decorator==4.4.2
defusedxml==0.6.0
doit==0.32.0
entrypoints==0.3
decorator==4.4.2; python_version >= "2.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0"
defusedxml==0.6.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
doit==0.33.1; python_version >= "3.5"
entrypoints==0.3; python_version >= "2.7"
funcsigs==1.0.2
future==0.18.2
importlib-metadata==1.6.1; python_version < "3.8"
ipykernel==5.3.0
ipython==7.15.0
future==0.18.2; python_version >= "2.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0"
importlib-metadata==2.0.0; python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "3.8" or python_full_version >= "3.5.0" and python_version < "3.8"
ipykernel==5.3.4; python_version >= "3.5"
ipython-genutils==0.2.0
jedi==0.17.0
jinja2==2.11.2
ipython==7.19.0; python_version >= "3.7"
jedi==0.17.2; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
jinja2==2.11.2; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0")
jsonschema==3.2.0
jupyter-client==6.1.3
jupyter-client==6.1.7; python_version >= "3.5"
jupyter-contrib-core==0.3.3
jupyter-contrib-nbextensions==0.5.1
jupyter-core==4.6.3
jupyter-core==4.6.3; python_version >= "2.7" and python_version < "3.0" or python_version > "3.0" and python_version < "3.1" or python_version > "3.1" and python_version < "3.2" or python_version > "3.2" and python_version < "3.3" or python_version > "3.3" and python_version < "3.4" or python_version > "3.4"
jupyter-highlight-selected-word==0.2.0
jupyter-latex-envs==1.4.6
jupyter-nbextensions-configurator==0.4.1
jupyterlab-pygments==0.1.2
latex==0.7.0
lxml==4.5.1
lxml==4.6.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
macfsevents==0.8.1; sys_platform == "darwin"
markdown==3.2.2
markupsafe==1.1.1
markdown==3.3.3; python_version >= "3.6"
markupsafe==1.1.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
mistune==0.8.4
nbconvert==5.6.1
nbformat==5.0.7
notebook==6.0.3
packaging==20.4
pandocfilters==1.4.2
parso==0.7.0
nbclient==0.5.1; python_version >= "3.6"
nbconvert==6.0.7; python_version >= "3.6"
nbformat==5.0.8; python_version >= "3.5"
nest-asyncio==1.4.2; python_version >= "3.5"
notebook==6.1.4; python_version >= "3.5"
packaging==20.4; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
pandocfilters==1.4.3; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
parso==0.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
pexpect==4.8.0; sys_platform != "win32"
pickleshare==0.7.5
prometheus-client==0.8.0
prompt-toolkit==3.0.5
ptyprocess==0.6.0; sys_platform != "win32" or os_name != "nt"
pygments==2.6.1
prompt-toolkit==3.0.8; python_full_version >= "3.6.1"
ptyprocess==0.6.0; sys_platform != "win32" and os_name != "nt"
pycparser==2.20; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
pygments==2.7.2; python_version >= "3.5"
pyinotify==0.9.6; sys_platform == "linux"
pyparsing==2.4.7
pyrsistent==0.16.0
python-dateutil==2.8.1
pyparsing==2.4.7; python_version >= "2.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0"
pyrsistent==0.17.3; python_version >= "3.5"
python-dateutil==2.8.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0"
python-frontmatter==0.5.0
pywin32==228; sys_platform == "win32"
pywinpty==0.5.7; os_name == "nt"
pyyaml==5.3.1
pyzmq==19.0.1
rise==5.6.1
pyyaml==5.3.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0")
pyzmq==19.0.2; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0"
rise==5.7.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0" and python_version < "4")
send2trash==1.5.0
shutilwhich==1.1.0
six==1.15.0
soupsieve==1.9.6
six==1.15.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0"
soupsieve==2.0.1; python_version >= "3.5"
tempdir==0.7.1
terminado==0.8.3
terminado==0.9.1; python_version >= "3.6"
testpath==0.4.4
tornado==6.0.4
traitlets==4.3.3
wcwidth==0.2.4
tornado==6.1; python_version >= "3.5"
traitlets==5.0.5; python_version >= "3.7"
wcwidth==0.2.5
webencodings==0.5.1
zipp==3.1.0; python_version < "3.8"
zipp==3.4.0; python_version >= "3.6" and python_version < "3.8"
from nbcourse.initialize import initialize
from nbcourse.nbcourse import NbCourse, MyDoitMain, ClassTaskLoader
from nbcourse.utils import get_functions
from nbcourse import get_help_epilog
from nbcourse.main import get_help_epilog
import pytest
from pathlib import Path
import os
......@@ -32,14 +32,17 @@ def _create_project(tmpdir, sample=Path('sample')):
yaml_file.unlink()
yaml_file.symlink_to(TESTS_PATH / sample / 'nbcourse.yml')
@pytest.fixture
def create_project(tmpdir):
_create_project(tmpdir)
@pytest.fixture
def create_wrong_project(tmpdir):
_create_project(tmpdir, sample=Path('wrong_sample'))
def test_minimal_nbcourse(create_project):
"""Only test nbcourse object instantiation"""
NbCourse()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment