diff --git a/make.ps1 b/make.ps1
index fb9866b..c0a0122 100644
--- a/make.ps1
+++ b/make.ps1
@@ -28,7 +28,7 @@ switch ($command) {
Activate-Venv -venv $venv
python -m pip install -r requirements-win.txt
python -m pip install -e .
- # python -m pre_commit install
+ python -m pre_commit install
break
}
"compile" {
diff --git a/src/pretty_jupyter/__init__.py b/src/pretty_jupyter/__init__.py
index 70641a0..8ec9c39 100644
--- a/src/pretty_jupyter/__init__.py
+++ b/src/pretty_jupyter/__init__.py
@@ -1,7 +1,13 @@
from pretty_jupyter.magics import JinjaMagics
# these imports are here for conf.json to work
-from pretty_jupyter.preprocessors import TokenPreprocessor, TokenCleaningPreprocessor, NbMetadataPreprocessor, HtmlNbMetadataPreprocessor
+from pretty_jupyter.preprocessors import (
+ HtmlNbMetadataPreprocessor,
+ NbMetadataPreprocessor,
+ TokenCleaningPreprocessor,
+ TokenPreprocessor,
+)
+
def load_ipython_extension(ipython):
# The `ipython` argument is the currently active `InteractiveShell`
diff --git a/src/pretty_jupyter/__main__.py b/src/pretty_jupyter/__main__.py
index ef6d15f..ae45561 100644
--- a/src/pretty_jupyter/__main__.py
+++ b/src/pretty_jupyter/__main__.py
@@ -1,4 +1,4 @@
from pretty_jupyter.console import cli
if __name__ == "__main__":
- cli()
\ No newline at end of file
+ cli()
diff --git a/src/pretty_jupyter/console.py b/src/pretty_jupyter/console.py
index 4f5461f..8a241cb 100644
--- a/src/pretty_jupyter/console.py
+++ b/src/pretty_jupyter/console.py
@@ -1,17 +1,20 @@
import os
import shutil
import sys
+from pathlib import Path
+
import click
-from traitlets.config import Config
-from nbconvert.exporters import HTMLExporter, PDFExporter, LatexExporter
import pkg_resources
-from pathlib import Path
+from nbconvert.exporters import HTMLExporter, LatexExporter, PDFExporter
+from traitlets.config import Config
@click.command()
@click.argument("out_path", type=click.Path())
def quickstart(out_path):
- in_path = pkg_resources.resource_filename("pretty_jupyter", os.path.join("quickstart", "empty.ipynb"))
+ in_path = pkg_resources.resource_filename(
+ "pretty_jupyter", os.path.join("quickstart", "empty.ipynb")
+ )
with open(in_path, "r") as file_r, open(out_path, "w") as file_w:
in_text = file_r.read()
@@ -31,15 +34,13 @@ def nbconvert_dev(input, to, out, include_input):
if out is None:
out = os.path.join(os.path.dirname(input), f"{Path(input).stem}.{to}")
- template_map = {
- "html": "pj",
- "pdf": "pj-pdf",
- "latex": "pj-pdf"
- }
+ template_map = {"html": "pj", "pdf": "pj-pdf", "latex": "pj-pdf"}
- config = Config()
+ config = Config()
config.TemplateExporter.template_name = template_map[to]
- config.TemplateExporter.extra_template_basedirs = [pkg_resources.resource_filename("pretty_jupyter", "templates")]
+ config.TemplateExporter.extra_template_basedirs = [
+ pkg_resources.resource_filename("pretty_jupyter", "templates")
+ ]
config.TemplateExporter.exclude_input = not include_input
if to == "html":
@@ -54,7 +55,7 @@ def nbconvert_dev(input, to, out, include_input):
with open(input, "r", encoding="utf-8") as file:
res = exporter.from_file(file)
output_data = res[0]
-
+
# open file as bytes if the output data are bytes, otherwise opne it as a string
file = open(out, "wb") if isinstance(output_data, bytes) else open(out, "w", encoding="utf-8")
try:
@@ -71,8 +72,12 @@ def install_dev():
src_templates = ["pj", "pj-pdf", "pj-legacy"]
for src_template in src_templates:
- src_folder = os.path.join(pkg_resources.resource_filename("pretty_jupyter", "templates"), src_template)
- target_folder = os.path.join(sys.prefix, f"share/jupyter/nbconvert/templates/{src_template}")
+ src_folder = os.path.join(
+ pkg_resources.resource_filename("pretty_jupyter", "templates"), src_template
+ )
+ target_folder = os.path.join(
+ sys.prefix, f"share/jupyter/nbconvert/templates/{src_template}"
+ )
# for backward compatibility, otherwise copytree has dirs_exist_ok param
if os.path.exists(target_folder):
@@ -80,7 +85,6 @@ def install_dev():
shutil.copytree(src_folder, target_folder)
-
@click.version_option()
@click.group()
def cli():
diff --git a/src/pretty_jupyter/constants.py b/src/pretty_jupyter/constants.py
index 039379e..ff9ed4a 100644
--- a/src/pretty_jupyter/constants.py
+++ b/src/pretty_jupyter/constants.py
@@ -62,11 +62,11 @@
"spacelab",
"superhero",
"united",
- "yeti"
+ "yeti",
]
"""
List of all available local themes that can be specified in the `theme` html metadata.
"""
DEPRECATED_METADATA_MSG_FORMAT = "Specifying attributes '{attributes}' in this position to notebook metadata is deprecated since {version}. Please consider reading changes in this version.\n"
-METADATA_ERROR_FORMAT = "An error occured when validating cell metadata. Error attributes in the metadata were the following:\n{error}"
\ No newline at end of file
+METADATA_ERROR_FORMAT = "An error occured when validating cell metadata. Error attributes in the metadata were the following:\n{error}"
diff --git a/src/pretty_jupyter/helpers/__init__.py b/src/pretty_jupyter/helpers/__init__.py
index 876c037..ce744bd 100644
--- a/src/pretty_jupyter/helpers/__init__.py
+++ b/src/pretty_jupyter/helpers/__init__.py
@@ -1,6 +1,3 @@
from pretty_jupyter.helpers.matplotlib import matplotlib_fig_to_html, matplotlib_fig_to_markdown
-__all__ = [
- matplotlib_fig_to_markdown.__name__,
- matplotlib_fig_to_html.__name__
-]
\ No newline at end of file
+__all__ = [matplotlib_fig_to_markdown.__name__, matplotlib_fig_to_html.__name__]
diff --git a/src/pretty_jupyter/helpers/matplotlib.py b/src/pretty_jupyter/helpers/matplotlib.py
index 724cdf0..1b066bc 100644
--- a/src/pretty_jupyter/helpers/matplotlib.py
+++ b/src/pretty_jupyter/helpers/matplotlib.py
@@ -1,19 +1,10 @@
-from io import BytesIO
import base64
+from io import BytesIO
-_MARKDOWN_SUPPORTED_FMT_MAP = {
- "png": "png",
- "jpeg": "jpeg",
- "jpg": "jpeg"
-}
+_MARKDOWN_SUPPORTED_FMT_MAP = {"png": "png", "jpeg": "jpeg", "jpg": "jpeg"}
_MARKDOWN_IMG_FORMAT = r"![image](data:image/{format};base64,{encoded})"
-_HTML_SUPPORTED_FMT_MAP = {
- "svg": "svg+xml",
- "png": "png",
- "jpeg": "jpeg",
- "jpg": "jpeg"
-}
+_HTML_SUPPORTED_FMT_MAP = {"svg": "svg+xml", "png": "png", "jpeg": "jpeg", "jpg": "jpeg"}
_HTML_IMG_FORMAT = r""
@@ -30,7 +21,15 @@ def matplotlib_fig_to_markdown(fig, fmt="png", autoclose: bool = True, bbox_inch
Returns:
str: Markdown string embedded representation of the figure.
"""
- return convert_mpl(fig, fmt=fmt, output_fmt_string=_MARKDOWN_IMG_FORMAT, supported_fmt_map=_MARKDOWN_SUPPORTED_FMT_MAP, autoclose=autoclose, bbox_inches=bbox_inches)
+ return convert_mpl(
+ fig,
+ fmt=fmt,
+ output_fmt_string=_MARKDOWN_IMG_FORMAT,
+ supported_fmt_map=_MARKDOWN_SUPPORTED_FMT_MAP,
+ autoclose=autoclose,
+ bbox_inches=bbox_inches,
+ )
+
def matplotlib_fig_to_html(fig, fmt="png", autoclose: bool = True, bbox_inches: str = "tight"):
"""
@@ -47,7 +46,15 @@ def matplotlib_fig_to_html(fig, fmt="png", autoclose: bool = True, bbox_inches:
"""
return convert_mpl(fig, fmt, _HTML_IMG_FORMAT, _HTML_SUPPORTED_FMT_MAP, autoclose, bbox_inches)
-def convert_mpl(fig, fmt, output_fmt_string, supported_fmt_map, autoclose: bool = True, bbox_inches: str = "tight"):
+
+def convert_mpl(
+ fig,
+ fmt,
+ output_fmt_string,
+ supported_fmt_map,
+ autoclose: bool = True,
+ bbox_inches: str = "tight",
+):
"""
Converts matplotlib figure into embedded inline string.
@@ -68,9 +75,12 @@ def convert_mpl(fig, fmt, output_fmt_string, supported_fmt_map, autoclose: bool
tmpfile = BytesIO()
fig.savefig(tmpfile, format=fmt, bbox_inches=bbox_inches)
- markdown = output_fmt_string.format(format=supported_fmt_map[fmt], encoded=base64.b64encode(tmpfile.getvalue()).decode('utf-8'))
+ markdown = output_fmt_string.format(
+ format=supported_fmt_map[fmt], encoded=base64.b64encode(tmpfile.getvalue()).decode("utf-8")
+ )
if autoclose:
import matplotlib.pyplot as plt
+
plt.close()
- return markdown
\ No newline at end of file
+ return markdown
diff --git a/src/pretty_jupyter/magics.py b/src/pretty_jupyter/magics.py
index 40813d7..fc8fd63 100644
--- a/src/pretty_jupyter/magics.py
+++ b/src/pretty_jupyter/magics.py
@@ -1,6 +1,6 @@
-from IPython import display
-from IPython.core.magic import Magics, magics_class, cell_magic
import jinja2
+from IPython import display
+from IPython.core.magic import Magics, cell_magic, magics_class
from pretty_jupyter.tokens import convert_markdown_tokens_to_html
@@ -9,18 +9,20 @@
class JinjaMagics(Magics):
def __init__(self, shell):
super().__init__(shell)
-
+
# create a jinja2 environment to use for rendering
# this can be modified for desired effects (ie: using different variable syntax)
- self.env = jinja2.Environment(loader=jinja2.FileSystemLoader('.'))
+ self.env = jinja2.Environment(loader=jinja2.FileSystemLoader("."))
# possible output types
- self.display_functions = dict(html=display.HTML,
- latex=display.Latex,
- json=display.JSON,
- pretty=display.Pretty,
- display=display.display,
- markdown=display.Markdown)
+ self.display_functions = dict(
+ html=display.HTML,
+ latex=display.Latex,
+ json=display.JSON,
+ pretty=display.Pretty,
+ display=display.display,
+ markdown=display.Markdown,
+ )
@cell_magic
def jinja(self, line, cell):
@@ -32,9 +34,14 @@ def jinja(self, line, cell):
# render the cell with jinja (substitutes variables,...)
tmp = self.env.from_string(cell)
- rend = tmp.render(dict((k,v) for (k,v) in self.shell.user_ns.items()
- if not k.startswith('_') and k not in self.shell.user_ns_hidden))
-
+ rend = tmp.render(
+ dict(
+ (k, v)
+ for (k, v) in self.shell.user_ns.items()
+ if not k.startswith("_") and k not in self.shell.user_ns_hidden
+ )
+ )
+
# convert tokens to html
if display_fn_name == "markdown":
rend = convert_markdown_tokens_to_html(rend)
@@ -48,6 +55,7 @@ def jmd(self, line, cell):
raise ValueError(r"%%jmd does not accept any arguments.")
return self.jinja(line="markdown", cell=cell)
+
def is_jinja_cell(input_str: str) -> bool:
"""
Checks whether the input is input of a jinja cell.
@@ -64,9 +72,6 @@ def is_jinja_cell(input_str: str) -> bool:
return False
first_line = lines[0]
- fns = [
- lambda l: l.startswith("%%jinja"),
- lambda l: l.startswith("%%jmd")
- ]
+ fns = [lambda l: l.startswith("%%jinja"), lambda l: l.startswith("%%jmd")]
- return any(fn(first_line) for fn in fns)
\ No newline at end of file
+ return any(fn(first_line) for fn in fns)
diff --git a/src/pretty_jupyter/preprocessors/__init__.py b/src/pretty_jupyter/preprocessors/__init__.py
index efeb18a..d5a9ded 100644
--- a/src/pretty_jupyter/preprocessors/__init__.py
+++ b/src/pretty_jupyter/preprocessors/__init__.py
@@ -1,9 +1,15 @@
-from pretty_jupyter.preprocessors._token_preprocessor import TokenPreprocessor, TokenCleaningPreprocessor
-from pretty_jupyter.preprocessors._metadata_preprocessor import NbMetadataPreprocessor, HtmlNbMetadataPreprocessor
+from pretty_jupyter.preprocessors._metadata_preprocessor import (
+ HtmlNbMetadataPreprocessor,
+ NbMetadataPreprocessor,
+)
+from pretty_jupyter.preprocessors._token_preprocessor import (
+ TokenCleaningPreprocessor,
+ TokenPreprocessor,
+)
__all__ = [
"TokenPreprocessor",
"TokenCleaningPreprocessor",
"NbMetadatapreprocessor",
- "HtmlNbMetadataPreprocessor"
-]
\ No newline at end of file
+ "HtmlNbMetadataPreprocessor",
+]
diff --git a/src/pretty_jupyter/preprocessors/_metadata_preprocessor.py b/src/pretty_jupyter/preprocessors/_metadata_preprocessor.py
index e0302cf..7a417a8 100644
--- a/src/pretty_jupyter/preprocessors/_metadata_preprocessor.py
+++ b/src/pretty_jupyter/preprocessors/_metadata_preprocessor.py
@@ -1,22 +1,26 @@
import copy
-import os
import warnings
-from pretty_jupyter.constants import DEPRECATED_METADATA_MSG_FORMAT, CONFIG_DIR, AVAILABLE_THEMES, METADATA_ERROR_FORMAT
from datetime import date, datetime
-from nbconvert.preprocessors import Preprocessor
-from traitlets import Dict
-from pretty_jupyter.utils import merge_dict
from pathlib import Path
-from cerberus import Validator
-import yaml
-import nbconvert
-from packaging import version
-import pkg_resources
import jinja2
+import nbconvert
+import pkg_resources
+import yaml
+from cerberus import Validator
+from nbconvert.preprocessors import Preprocessor
+from packaging import version
+from traitlets import Dict
-from pretty_jupyter.tokens import read_code_metadata_token, read_markdown_metadata_token
+from pretty_jupyter.constants import (
+ AVAILABLE_THEMES,
+ CONFIG_DIR,
+ DEPRECATED_METADATA_MSG_FORMAT,
+ METADATA_ERROR_FORMAT,
+)
from pretty_jupyter.magics import is_jinja_cell
+from pretty_jupyter.tokens import read_code_metadata_token, read_markdown_metadata_token
+from pretty_jupyter.utils import merge_dict
_DEPRECATED_ATTRIBUTES = ["title", "theme", "toc", "code_folding"]
_DEPRECATED_ATTRIBUTES_VERSION = "2.0.0"
@@ -46,7 +50,7 @@ def __init__(self, **kw):
super().__init__(**kw)
- self.env = jinja2.Environment(loader=jinja2.FileSystemLoader('.'))
+ self.env = jinja2.Environment(loader=jinja2.FileSystemLoader("."))
with open(self.nb_spec_path) as file:
nb_spec = yaml.safe_load(file.read())
@@ -64,7 +68,12 @@ def preprocess(self, nb, resources):
# deprecation warnings to help users fix their error
deprecated_attrs = [a for a in _DEPRECATED_ATTRIBUTES if a in nb.metadata]
if len(deprecated_attrs) > 0:
- warnings.warn(DEPRECATED_METADATA_MSG_FORMAT.format(attributes=", ".join(deprecated_attrs), version=_DEPRECATED_ATTRIBUTES_VERSION), category=DeprecationWarning)
+ warnings.warn(
+ DEPRECATED_METADATA_MSG_FORMAT.format(
+ attributes=", ".join(deprecated_attrs), version=_DEPRECATED_ATTRIBUTES_VERSION
+ ),
+ category=DeprecationWarning,
+ )
# temporarily store nb metadata to resources to be accessible in cell
resources["__pj_metadata"] = nb.metadata.get("pj_metadata", {})
@@ -87,7 +96,7 @@ def preprocess_cell(self, cell, resources, index):
cell, resources = self._preprocess_markdown_cell(cell, resources, index)
if cell.cell_type == "code":
cell, resources = self._preprocess_code_cell(cell, resources, index)
-
+
return cell, resources
def _synchronize_notebook_metadata(self, cell, resources):
@@ -97,12 +106,17 @@ def _synchronize_notebook_metadata(self, cell, resources):
try:
src_metadata = yaml.safe_load(cell.source)
except Exception as exc:
- raise ValueError("An error happend when trying to parse first cell of the notebook with type raw.", exc)
+ raise ValueError(
+ "An error happend when trying to parse first cell of the notebook with type raw.",
+ exc,
+ )
remove_cell_input(cell)
if len(nb_metadata) > 0 and len(src_metadata) > 0:
- warnings.warn("Notebook-level metadata are defined both in the source and in the notebook's metadata. Please remove one of them.")
+ warnings.warn(
+ "Notebook-level metadata are defined both in the source and in the notebook's metadata. Please remove one of them."
+ )
metadata = src_metadata if len(src_metadata) > 0 else nb_metadata
@@ -121,8 +135,12 @@ def _synchronize_notebook_metadata(self, cell, resources):
# run metadata through jinja templating
metadata_copy = copy.deepcopy(metadata)
- for m_key, m_val in filter(lambda x: x[1] is not None and isinstance(x[1], str), metadata_copy.items()):
- metadata[m_key] = self.env.from_string(m_val).render(datetime=datetime, date=date, pj_metadata=metadata_copy)
+ for m_key, m_val in filter(
+ lambda x: x[1] is not None and isinstance(x[1], str), metadata_copy.items()
+ ):
+ metadata[m_key] = self.env.from_string(m_val).render(
+ datetime=datetime, date=date, pj_metadata=metadata_copy
+ )
resources["pj_metadata"] = metadata
@@ -179,7 +197,7 @@ def _preprocess_code_cell(self, cell, resources, index):
for i, output in reversed(list(enumerate(cell.outputs))):
if not is_output_enabled(cell, resources, output):
cell.outputs.pop(i)
-
+
return cell, resources
@@ -208,8 +226,11 @@ def is_output_enabled(cell, resources, output):
def is_stdout(output):
return output.output_type == "stream" and output.name == "stdout"
+
def is_error(output):
- return output.output_type == "error" or (output.output_type == "stream" and output.name == "stderr")
+ return output.output_type == "error" or (
+ output.output_type == "stream" and output.name == "stderr"
+ )
# PRIORITY
# cell > notebook-level, stdout > output (similarly stderr)
@@ -235,6 +256,7 @@ def is_error(output):
return is_enabled
+
def is_input_enabled(cell, resources):
cell_metadata = cell.metadata["pj_metadata"]
nb_metadata = resources["pj_metadata"]["output"]["general"]
@@ -258,4 +280,4 @@ def get_code_folding_value(cell, resources):
if "input_fold" in cell_metadata:
code_folding = cell_metadata["input_fold"]
value = f"fold-{code_folding}"
- return value
\ No newline at end of file
+ return value
diff --git a/src/pretty_jupyter/preprocessors/_token_preprocessor.py b/src/pretty_jupyter/preprocessors/_token_preprocessor.py
index b87893f..4ef14a7 100644
--- a/src/pretty_jupyter/preprocessors/_token_preprocessor.py
+++ b/src/pretty_jupyter/preprocessors/_token_preprocessor.py
@@ -6,7 +6,9 @@
import re
+
from nbconvert.preprocessors import Preprocessor
+
from pretty_jupyter.constants import HTML_TOKEN_REGEX, TOKEN_SEP
from pretty_jupyter.tokens import convert_markdown_tokens_to_html
@@ -33,6 +35,7 @@ class TokenPreprocessor(Preprocessor):
```
"""
+
def preprocess(self, nb, resources):
resources["token_sep"] = TOKEN_SEP
@@ -50,6 +53,7 @@ class TokenCleaningPreprocessor(Preprocessor):
"""
formats = ["text/markdown", "text/html"]
+
def preprocess_cell(self, cell, resources, index):
if cell.cell_type == "code":
for i, output in enumerate(cell.outputs):
diff --git a/src/pretty_jupyter/testing.py b/src/pretty_jupyter/testing.py
index 04237a7..c242d90 100644
--- a/src/pretty_jupyter/testing.py
+++ b/src/pretty_jupyter/testing.py
@@ -13,4 +13,4 @@ def _get_y_location(driver):
def is_visible(element, driver, epsilon_px=10):
- return abs(element.location["y"] - _get_y_location(driver)) < epsilon_px
\ No newline at end of file
+ return abs(element.location["y"] - _get_y_location(driver)) < epsilon_px
diff --git a/src/pretty_jupyter/tokens.py b/src/pretty_jupyter/tokens.py
index 3cd2793..ff955f2 100644
--- a/src/pretty_jupyter/tokens.py
+++ b/src/pretty_jupyter/tokens.py
@@ -1,6 +1,14 @@
-import yaml
import re
-from pretty_jupyter.constants import CODE_METADATA_TOKEN_REGEX, MARKDOWN_METADATA_TOKEN_REGEX, MARKDOWN_TOKEN_REGEX, HTML_TOKEN_FORMAT, TOKEN_SEP
+
+import yaml
+
+from pretty_jupyter.constants import (
+ CODE_METADATA_TOKEN_REGEX,
+ HTML_TOKEN_FORMAT,
+ MARKDOWN_METADATA_TOKEN_REGEX,
+ MARKDOWN_TOKEN_REGEX,
+ TOKEN_SEP,
+)
def convert_markdown_tokens_to_html(input_str: str) -> str:
@@ -30,7 +38,7 @@ def convert_markdown_tokens_to_html(input_str: str) -> str:
html = HTML_TOKEN_FORMAT.format(tokens=token_str)
# replace the md tokens by html tokens
- markdown = line[result.span()[0]:result.span()[1]]
+ markdown = line[result.span()[0] : result.span()[1]]
line = line.replace(markdown, html)
all_lines.append(line)
@@ -38,6 +46,7 @@ def convert_markdown_tokens_to_html(input_str: str) -> str:
output = "\n".join(all_lines)
return output
+
def read_code_metadata_token(input_line: str) -> dict:
# parse token
result = re.search(CODE_METADATA_TOKEN_REGEX, input_line)
@@ -50,6 +59,7 @@ def read_code_metadata_token(input_line: str) -> dict:
return yaml.safe_load(result.groups()[0])
+
def read_markdown_metadata_token(input_line: str):
result = re.search(MARKDOWN_METADATA_TOKEN_REGEX, input_line)
@@ -59,4 +69,4 @@ def read_markdown_metadata_token(input_line: str):
if len(result.groups()) == 0:
return None
- return yaml.safe_load(result.groups()[0])
\ No newline at end of file
+ return yaml.safe_load(result.groups()[0])
diff --git a/src/pretty_jupyter/utils.py b/src/pretty_jupyter/utils.py
index 4518d55..b2cad00 100644
--- a/src/pretty_jupyter/utils.py
+++ b/src/pretty_jupyter/utils.py
@@ -16,6 +16,7 @@ def merge_dict(main_dict: dict, other_dict: dict):
return other_dict
+
def _update_dict(dict_, override_dict):
for key, val in override_dict.items():
if isinstance(val, dict):
diff --git a/tests/test_magics/test_magics.py b/tests/test_magics/test_magics.py
index 066b996..815d974 100644
--- a/tests/test_magics/test_magics.py
+++ b/tests/test_magics/test_magics.py
@@ -1,22 +1,20 @@
from unittest.mock import MagicMock, PropertyMock
+
from pretty_jupyter.magics import JinjaMagics
+
def test_jinja():
shell_mock = MagicMock(name="shell", spec=["user_ns", "user_ns_hidden"])
- type(shell_mock).user_ns = PropertyMock(
- name="user_ns",
- return_value={"a": 15}
- )
+ type(shell_mock).user_ns = PropertyMock(name="user_ns", return_value={"a": 15})
jinja_magics = JinjaMagics(shell_mock)
with open("tests/test_magics/fixture/input_jmarkdown.md") as file:
input_str = file.read()
actual_str = jinja_magics.jinja(
- line=input_str.splitlines()[0][7:],
- cell="\n".join(input_str.splitlines()[1:])
- ).data
+ line=input_str.splitlines()[0][7:], cell="\n".join(input_str.splitlines()[1:])
+ ).data
with open("tests/test_magics/fixture/expected_jmarkdown.md") as file:
expected_str = file.read()
- assert actual_str == expected_str, "Expected string is different than the actual."
\ No newline at end of file
+ assert actual_str == expected_str, "Expected string is different than the actual."
diff --git a/tests/test_notebooks/conftest.py b/tests/test_notebooks/conftest.py
index 9a403d4..dd5e210 100644
--- a/tests/test_notebooks/conftest.py
+++ b/tests/test_notebooks/conftest.py
@@ -1,12 +1,13 @@
import os
+from pathlib import Path
+
+import pkg_resources
import pytest
+import selenium.webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.core.utils import ChromeType
-import selenium.webdriver
-import pkg_resources
-from pathlib import Path
@pytest.fixture()
@@ -21,7 +22,7 @@ def driver():
"--ignore-certificate-errors",
"--disable-extensions",
"--no-sandbox",
- "--disable-dev-shm-usage"
+ "--disable-dev-shm-usage",
]
for option in options:
chrome_options.add_argument(option)
@@ -32,18 +33,22 @@ def driver():
driver.close()
+
@pytest.fixture
def fixture_dir():
return "tests/test_notebooks/fixture"
+
@pytest.fixture
def templates_path():
return str(Path(pkg_resources.resource_filename("pretty_jupyter", "templates")).as_posix())
+
@pytest.fixture
def input_path():
raise NotImplementedError()
+
@pytest.fixture
def out_path(tmpdir, input_path):
path = str((Path(tmpdir) / f"{Path(input_path).stem}.html").absolute())
@@ -53,6 +58,7 @@ def out_path(tmpdir, input_path):
if os.path.exists(path):
os.remove(path)
+
@pytest.fixture
def page_url(out_path):
- return os.path.normpath(f"file:/{out_path}")
\ No newline at end of file
+ return os.path.normpath(f"file:/{out_path}")
diff --git a/tests/test_notebooks/test_basic.py b/tests/test_notebooks/test_basic.py
index 00a91bf..992d89a 100644
--- a/tests/test_notebooks/test_basic.py
+++ b/tests/test_notebooks/test_basic.py
@@ -1,10 +1,12 @@
-from click.testing import CliRunner
-import pytest
-from pretty_jupyter.console import cli
import os
-from selenium.webdriver.common.by import By
import time
+import pytest
+from click.testing import CliRunner
+from selenium.webdriver.common.by import By
+
+from pretty_jupyter.console import cli
+
@pytest.fixture
def input_path(fixture_dir):
@@ -15,7 +17,7 @@ def input_path(fixture_dir):
def test_basic(input_path, out_path, page_url, driver):
runner = CliRunner()
result = runner.invoke(cli, ["nbconvert-dev", input_path, "--out", out_path, "--to", "html"])
-
+
assert result.exit_code == 0
assert os.path.exists(out_path), "The expected file does not exist."
@@ -38,42 +40,65 @@ def test_basic(input_path, out_path, page_url, driver):
##########
assert main_content.find_elements(By.XPATH, h1_xpath)[1].text == "Chapter 1: Tabs"
- tab_section = main_content.find_elements(By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]")[1]
+ tab_section = main_content.find_elements(
+ By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]"
+ )[1]
# select tabs
- list_tabs = tab_section.find_elements(By.XPATH, "ul[contains(@class, 'nav') and contains(@class, 'nav-pills')]/li")
+ list_tabs = tab_section.find_elements(
+ By.XPATH, "ul[contains(@class, 'nav') and contains(@class, 'nav-pills')]/li"
+ )
assert len(list_tabs) == 3, "There should be 3 tabs."
assert list_tabs[1].text == "Tab 2", "The name of the second tab should be 'Tab 2'."
-
- tab_contents = tab_section.find_elements(By.XPATH, """div[contains(@class, 'tab-content')]
- /div[contains(@class, 'section') and contains(@class, 'level2') and contains(@class, 'tab-pane')]""")
+ tab_contents = tab_section.find_elements(
+ By.XPATH,
+ """div[contains(@class, 'tab-content')]
+ /div[contains(@class, 'section') and contains(@class, 'level2') and contains(@class, 'tab-pane')]""",
+ )
assert len(tab_contents) == 3, "There should be 3 tab contents for the tabs."
- assert "active" in tab_contents[0].get_attribute("class"), "First tab should be active at the beginning."
+ assert "active" in tab_contents[0].get_attribute(
+ "class"
+ ), "First tab should be active at the beginning."
# click on the second tab
list_tabs[1].click()
- assert "active" in tab_contents[1].get_attribute("class"), "Second tab should be active after clicking on it."
+ assert "active" in tab_contents[1].get_attribute(
+ "class"
+ ), "Second tab should be active after clicking on it."
# check that the maths rendered properly
# math needs time to render
time.sleep(2)
- assert len(tab_contents[1].find_elements(By.XPATH, ".//span[contains(@class, 'MJXc-display')]")) > 0, "Math didn't render."
+ assert (
+ len(tab_contents[1].find_elements(By.XPATH, ".//span[contains(@class, 'MJXc-display')]"))
+ > 0
+ ), "Math didn't render."
# check that the maths rendered properly
- math_text = tab_contents[1].find_elements(By.XPATH, ".//script[contains(@type, 'math/tex')]")[1].get_attribute("innerHTML")
+ math_text = (
+ tab_contents[1]
+ .find_elements(By.XPATH, ".//script[contains(@type, 'math/tex')]")[1]
+ .get_attribute("innerHTML")
+ )
assert math_text == r"a \cdot a^2 = \frac{a^5}{a^2} = a^3 = 125"
-
+
################
# CODE FOLDING #
################
- jmd_section = driver.find_elements(By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]")[2]
+ jmd_section = driver.find_elements(
+ By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]"
+ )[2]
- code_div = jmd_section.find_elements(By.XPATH, "div[contains(@class, 'py-code-collapse') and contains(@class, 'collapse')]")[0]
- assert len(code_div.find_elements(By.XPATH, "div[contains(@class, 'pj-input')]//pre/span")) > 0, "Code highlighting does not work."
+ code_div = jmd_section.find_elements(
+ By.XPATH, "div[contains(@class, 'py-code-collapse') and contains(@class, 'collapse')]"
+ )[0]
+ assert (
+ len(code_div.find_elements(By.XPATH, "div[contains(@class, 'pj-input')]//pre/span")) > 0
+ ), "Code highlighting does not work."
#####################
# TABLE OF CONTENTS #
@@ -104,10 +129,16 @@ def get_y_location(driver):
tab_section_title = tab_section.find_element(By.XPATH, "h1")
epsilon_px = 10
- assert abs(jmd_title.location["y"] - get_y_location(driver)) < epsilon_px, "Chapter 2: Jinja Markdown must be visible after clicking on it in TOC."
- assert tab_section_title.location["y"] < get_y_location(driver), "Chapter 1: Tabs cannot be visible after clicking on chapter 2."
+ assert (
+ abs(jmd_title.location["y"] - get_y_location(driver)) < epsilon_px
+ ), "Chapter 2: Jinja Markdown must be visible after clicking on it in TOC."
+ assert tab_section_title.location["y"] < get_y_location(
+ driver
+ ), "Chapter 1: Tabs cannot be visible after clicking on chapter 2."
# go to Chapter 1
toc_first_level[1].find_element(By.XPATH, "li").click()
time.sleep(2)
- assert abs(tab_section_title.location["y"] - get_y_location(driver)) < epsilon_px, "Chapter 1: Tabs must be visible after clicking on chapter 1."
\ No newline at end of file
+ assert (
+ abs(tab_section_title.location["y"] - get_y_location(driver)) < epsilon_px
+ ), "Chapter 1: Tabs must be visible after clicking on chapter 1."
diff --git a/tests/test_notebooks/test_cell_metadata.py b/tests/test_notebooks/test_cell_metadata.py
index 629c74c..4d9819e 100644
--- a/tests/test_notebooks/test_cell_metadata.py
+++ b/tests/test_notebooks/test_cell_metadata.py
@@ -1,10 +1,10 @@
-import time
-import pytest
import os
-from selenium.webdriver.common.by import By
-from pathlib import Path
-import sys
import subprocess
+import sys
+from pathlib import Path
+
+import pytest
+from selenium.webdriver.common.by import By
@pytest.fixture
@@ -16,23 +16,30 @@ def input_path(fixture_dir):
def test_cell_metadata(templates_path, input_path, out_path, page_url, driver):
out_dir = os.path.dirname(out_path)
python_path = sys.executable
- retval = subprocess.run(f"{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs={templates_path} --execute --ExecutePreprocessor.allow_errors=True --output-dir=\"{out_dir}\"", check=True, shell=True)
+ retval = subprocess.run(
+ f'{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs={templates_path} --execute --ExecutePreprocessor.allow_errors=True --output-dir="{out_dir}"',
+ check=True,
+ shell=True,
+ )
assert retval.returncode == 0, "jupyter nbconvert command ended up with a failure"
driver.get(page_url)
main_content = driver.find_element(By.XPATH, "//*[@id = 'main-content']")
- code_folding_inputs = main_content.find_elements(By.XPATH, "//*[contains(@class, 'py-code-collapse')]")
+ code_folding_inputs = main_content.find_elements(
+ By.XPATH, "//*[contains(@class, 'py-code-collapse')]"
+ )
assert len(code_folding_inputs) == 4, "There must be 4 code folding input cells."
- assert "input: true, input_fold: show" in code_folding_inputs[0].get_attribute("innerHTML"), "First jinja markdown cell should have input: true and input_fold: show."
- jmd_button = code_folding_inputs[0].find_element(By.XPATH, "preceding-sibling::div[@class = 'row'][1]//button/span")
+ assert "input: true, input_fold: show" in code_folding_inputs[0].get_attribute(
+ "innerHTML"
+ ), "First jinja markdown cell should have input: true and input_fold: show."
+ jmd_button = code_folding_inputs[0].find_element(
+ By.XPATH, "preceding-sibling::div[@class = 'row'][1]//button/span"
+ )
assert jmd_button.get_attribute("innerHTML") == "Hide", "The first jmd button should be shown."
error_output = main_content.find_elements(By.XPATH, "//pre[contains(@class, 'bg-danger')]")
- assert len(error_output) == 1, "The generated page should have one error output right in the end."
-
-
-
-
-
+ assert (
+ len(error_output) == 1
+ ), "The generated page should have one error output right in the end."
diff --git a/tests/test_notebooks/test_lang.py b/tests/test_notebooks/test_lang.py
index cf16859..3dcd352 100644
--- a/tests/test_notebooks/test_lang.py
+++ b/tests/test_notebooks/test_lang.py
@@ -1,10 +1,11 @@
+import os
+import subprocess
+import sys
import time
+from pathlib import Path
+
import pytest
-import os
from selenium.webdriver.common.by import By
-from pathlib import Path
-import sys
-import subprocess
@pytest.fixture
@@ -16,7 +17,11 @@ def input_path(fixture_dir):
def test_lang(templates_path, input_path, out_path, page_url, driver):
out_dir = os.path.dirname(out_path)
python_path = sys.executable
- retval = subprocess.run(f"{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs={templates_path} --execute --output-dir=\"{out_dir}\"", check=True, shell=True)
+ retval = subprocess.run(
+ f'{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs={templates_path} --execute --output-dir="{out_dir}"',
+ check=True,
+ shell=True,
+ )
assert retval.returncode == 0, "jupyter nbconvert command ended up with a failure"
driver.get(page_url)
@@ -27,21 +32,31 @@ def test_lang(templates_path, input_path, out_path, page_url, driver):
assert header.find_element(By.XPATH, "h1").get_attribute("innerHTML") == "Čeština"
header = main_content.find_element(By.XPATH, "//div[@id = 'Hlavička-s-českými-znaky-O_O-1']")
- assert header.find_element(By.XPATH, "h2").get_attribute("innerHTML") == "Hlavička s českými znaky"
+ assert (
+ header.find_element(By.XPATH, "h2").get_attribute("innerHTML") == "Hlavička s českými znaky"
+ )
header = main_content.find_element(By.XPATH, "//div[@id = 'Hlavička-s-českými-znaky-O_O-2']")
- assert header.find_element(By.XPATH, "h2").get_attribute("innerHTML") == "Hlavička s českými znaky"
+ assert (
+ header.find_element(By.XPATH, "h2").get_attribute("innerHTML") == "Hlavička s českými znaky"
+ )
# note: 23 is encoded hash character
- tab = main_content.find_element(By.XPATH, "//a[@href = '#Český-Tab-s-divnými-znaky--_23-O_O-2']/..")
- tab_sec = main_content.find_element(By.XPATH, "//div[@id = 'Český-Tab-s-divnými-znaky--_23-O_O-2']")
+ tab = main_content.find_element(
+ By.XPATH, "//a[@href = '#Český-Tab-s-divnými-znaky--_23-O_O-2']/.."
+ )
+ tab_sec = main_content.find_element(
+ By.XPATH, "//div[@id = 'Český-Tab-s-divnými-znaky--_23-O_O-2']"
+ )
assert "active" not in main_content.get_attribute("class")
tab.click()
time.sleep(0.5)
assert "active" in tab_sec.get_attribute("class")
header = main_content.find_element(By.XPATH, "//div[@id = 'české-id']")
- assert header.find_element(By.XPATH, "h2").get_attribute("innerHTML") == "Unikátní česká hlavička"
+ assert (
+ header.find_element(By.XPATH, "h2").get_attribute("innerHTML") == "Unikátní česká hlavička"
+ )
# RUSSIAN
header = main_content.find_element(By.XPATH, "//div[@id = 'ру́сский-язы́к']")
@@ -62,5 +77,3 @@ def test_lang(templates_path, input_path, out_path, page_url, driver):
header = main_content.find_element(By.XPATH, "//div[@id = 'Российский-ID']")
assert header.find_element(By.XPATH, "h2").get_attribute("innerHTML") == "Уникальный заголовок"
-
-
diff --git a/tests/test_notebooks/test_tabset.py b/tests/test_notebooks/test_tabset.py
index 4766df1..d8a3672 100644
--- a/tests/test_notebooks/test_tabset.py
+++ b/tests/test_notebooks/test_tabset.py
@@ -1,10 +1,11 @@
+import os
+import subprocess
+import sys
import time
+from pathlib import Path
+
import pytest
-import os
from selenium.webdriver.common.by import By
-from pathlib import Path
-import sys
-import subprocess
from pretty_jupyter.testing import is_visible
@@ -18,7 +19,11 @@ def input_path(fixture_dir):
def test_tabset(templates_path, input_path, out_path, page_url, driver):
out_dir = os.path.dirname(out_path)
python_path = sys.executable
- retval = subprocess.run(f"{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs={templates_path} --execute --output-dir=\"{out_dir}\"", check=True, shell=True)
+ retval = subprocess.run(
+ f'{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs={templates_path} --execute --output-dir="{out_dir}"',
+ check=True,
+ shell=True,
+ )
assert retval.returncode == 0, "jupyter nbconvert command ended up with a failure"
driver.get(page_url)
@@ -27,11 +32,18 @@ def test_tabset(templates_path, input_path, out_path, page_url, driver):
################
# BASIC TABSET #
################
- first_chapter = main_content.find_elements(By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]")[0]
-
- list_tabs = first_chapter.find_elements(By.XPATH, "ul[contains(@class, 'nav') and contains(@class, 'nav-pills')]/li")
- tab_contents = first_chapter.find_elements(By.XPATH, """div[contains(@class, 'tab-content')]
- /div[contains(@class, 'section') and contains(@class, 'level2') and contains(@class, 'tab-pane')]""")
+ first_chapter = main_content.find_elements(
+ By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]"
+ )[0]
+
+ list_tabs = first_chapter.find_elements(
+ By.XPATH, "ul[contains(@class, 'nav') and contains(@class, 'nav-pills')]/li"
+ )
+ tab_contents = first_chapter.find_elements(
+ By.XPATH,
+ """div[contains(@class, 'tab-content')]
+ /div[contains(@class, 'section') and contains(@class, 'level2') and contains(@class, 'tab-pane')]""",
+ )
assert len(list_tabs) == 2, "There should be 2 tabs."
assert list_tabs[1].text == "Tab 2", "The name of the second tab should be 'Tab 2'."
@@ -43,31 +55,46 @@ def test_tabset(templates_path, input_path, out_path, page_url, driver):
# click on the first tab
list_tabs[0].click()
time.sleep(0.5)
- assert "active" in list_tabs[0].get_attribute("class") and "active" not in list_tabs[1].get_attribute("class"), "Now tab 2 should be active"
+ assert "active" in list_tabs[0].get_attribute("class") and "active" not in list_tabs[
+ 1
+ ].get_attribute("class"), "Now tab 2 should be active"
assert tab_contents[0].is_displayed(), "Tab 1 should be displayed right now."
assert not tab_contents[1].is_displayed(), "Tab 2 shouldn't be displayed right now."
-
#################
# NESTED TABSET #
#################
- second_chapter = main_content.find_elements(By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]")[1]
-
- tab1_list = second_chapter.find_elements(By.XPATH, "ul[contains(@class, 'nav') and contains(@class, 'nav-pills')]/li")
- tab1_contents = second_chapter.find_elements(By.XPATH, """div[contains(@class, 'tab-content')]
- /div[contains(@class, 'section') and contains(@class, 'level2') and contains(@class, 'tab-pane')]""")
+ second_chapter = main_content.find_elements(
+ By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]"
+ )[1]
+
+ tab1_list = second_chapter.find_elements(
+ By.XPATH, "ul[contains(@class, 'nav') and contains(@class, 'nav-pills')]/li"
+ )
+ tab1_contents = second_chapter.find_elements(
+ By.XPATH,
+ """div[contains(@class, 'tab-content')]
+ /div[contains(@class, 'section') and contains(@class, 'level2') and contains(@class, 'tab-pane')]""",
+ )
assert len(tab1_list) == 2, "The first level of nested tabset has two options."
assert tab1_contents[0].is_displayed(), "First tab on the second level is currently shown."
- assert not tab1_contents[1].is_displayed(), "Second tab on the first level is currently not shown."
-
+ assert not tab1_contents[
+ 1
+ ].is_displayed(), "Second tab on the first level is currently not shown."
+
tab1_list[1].click()
time.sleep(0.5)
assert tab1_contents[1].is_displayed(), "Second tab should be shown."
- tab2_list = tab1_contents[1].find_elements(By.XPATH, "ul[contains(@class, 'nav') and contains(@class, 'nav-pills')]/li")
- tab2_contents = tab1_contents[1].find_elements(By.XPATH, """div[contains(@class, 'tab-content')]
- /div[contains(@class, 'section') and contains(@class, 'level3') and contains(@class, 'tab-pane')]""")
+ tab2_list = tab1_contents[1].find_elements(
+ By.XPATH, "ul[contains(@class, 'nav') and contains(@class, 'nav-pills')]/li"
+ )
+ tab2_contents = tab1_contents[1].find_elements(
+ By.XPATH,
+ """div[contains(@class, 'tab-content')]
+ /div[contains(@class, 'section') and contains(@class, 'level3') and contains(@class, 'tab-pane')]""",
+ )
assert len(tab2_contents) == 3 and len(tab2_list) == 3
assert tab2_contents[2].is_displayed(), "Tab 23 should be displayed initially."
@@ -75,23 +102,33 @@ def test_tabset(templates_path, input_path, out_path, page_url, driver):
time.sleep(0.5)
assert tab2_contents[0].is_displayed(), "Tab 21 should be displayed now."
-
################
# CONTINUATION #
################
- third_chapter = main_content.find_elements(By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]")[2]
+ third_chapter = main_content.find_elements(
+ By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]"
+ )[2]
# two tabsets are there with an invisible title
# the third is section after the tabset
- tabsets = third_chapter.find_elements(By.XPATH, "div[contains(@class, 'section') and contains(@class, 'level2')]")
+ tabsets = third_chapter.find_elements(
+ By.XPATH, "div[contains(@class, 'section') and contains(@class, 'level2')]"
+ )
continuation1 = third_chapter.find_element(By.XPATH, "//span[@id='continuation1']")
continuation2 = third_chapter.find_element(By.XPATH, "//span[@id='continuation2']")
- assert len(tabsets) == 3, "There should be 3 sections, where the first two are tabsets and the last is section after it."
+ assert (
+ len(tabsets) == 3
+ ), "There should be 3 sections, where the first two are tabsets and the last is section after it."
tabset1 = tabsets[0]
- list_tabs = tabset1.find_elements(By.XPATH, "ul[contains(@class, 'nav') and contains(@class, 'nav-pills')]/li")
- tab_contents = tabset1.find_elements(By.XPATH, """div[contains(@class, 'tab-content')]
- /div[contains(@class, 'section') and contains(@class, 'level3') and contains(@class, 'tab-pane')]""")
+ list_tabs = tabset1.find_elements(
+ By.XPATH, "ul[contains(@class, 'nav') and contains(@class, 'nav-pills')]/li"
+ )
+ tab_contents = tabset1.find_elements(
+ By.XPATH,
+ """div[contains(@class, 'tab-content')]
+ /div[contains(@class, 'section') and contains(@class, 'level3') and contains(@class, 'tab-pane')]""",
+ )
assert tab_contents[0].is_displayed(), "Tab 1 should be displayed at the beginning."
assert not tab_contents[1].is_displayed(), "Tab 2 should not be displayed at the beginning."
assert continuation1.is_displayed(), "Text between should be visible all the time."
@@ -107,19 +144,20 @@ def test_tabset(templates_path, input_path, out_path, page_url, driver):
NO_TABSET_METADATA = "{ output: { html: { tabset: false }} }"
+
def test_no_tabset(templates_path, input_path, out_path, page_url, driver):
out_dir = os.path.dirname(out_path)
python_path = sys.executable
- retval = subprocess.run(f"{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs={templates_path} --execute --output-dir=\"{out_dir}\" --HtmlNbMetadataPreprocessor.pj_metadata=\"{NO_TABSET_METADATA}\"", check=True, shell=True)
+ retval = subprocess.run(
+ f'{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs={templates_path} --execute --output-dir="{out_dir}" --HtmlNbMetadataPreprocessor.pj_metadata="{NO_TABSET_METADATA}"',
+ check=True,
+ shell=True,
+ )
assert retval.returncode == 0, "jupyter nbconvert command ended up with a failure"
driver.get(page_url)
- all_tabs = driver.find_elements(By.XPATH, "ul[contains(@class, 'nav') and contains(@class, 'nav-pills')]/li")
+ all_tabs = driver.find_elements(
+ By.XPATH, "ul[contains(@class, 'nav') and contains(@class, 'nav-pills')]/li"
+ )
assert len(all_tabs) == 0, "Tabset is turned off but the tabs have been generated."
-
-
-
-
-
-
\ No newline at end of file
diff --git a/tests/test_notebooks/test_toc.py b/tests/test_notebooks/test_toc.py
index 1d327af..f49b38b 100644
--- a/tests/test_notebooks/test_toc.py
+++ b/tests/test_notebooks/test_toc.py
@@ -1,12 +1,13 @@
+import os
+import subprocess
+import sys
import time
+from pathlib import Path
+
import pytest
-import os
from selenium.webdriver.common.by import By
-from pathlib import Path
-import sys
-import subprocess
-from pretty_jupyter.constants import TOKEN_SEP
+from pretty_jupyter.constants import TOKEN_SEP
from pretty_jupyter.testing import is_visible
@@ -19,7 +20,11 @@ def input_path(fixture_dir):
def test_toc(templates_path, input_path, out_path, page_url, driver):
out_dir = os.path.dirname(out_path)
python_path = sys.executable
- retval = subprocess.run(f"{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs={templates_path} --execute --output-dir=\"{out_dir}\"", check=True, shell=True)
+ retval = subprocess.run(
+ f'{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs={templates_path} --execute --output-dir="{out_dir}"',
+ check=True,
+ shell=True,
+ )
assert retval.returncode == 0, "jupyter nbconvert command ended up with a failure"
driver.get(page_url)
@@ -34,54 +39,88 @@ def test_toc(templates_path, input_path, out_path, page_url, driver):
# check that first section is visible
toc_first_level[0].find_element(By.XPATH, "li").click()
time.sleep(2)
- first_chapter = main_content.find_elements(By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]")[0]
+ first_chapter = main_content.find_elements(
+ By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]"
+ )[0]
first_header = first_chapter.find_element(By.XPATH, "h1")
- assert is_visible(element=first_header, driver=driver), "First chapter should be visible at the beginning."
+ assert is_visible(
+ element=first_header, driver=driver
+ ), "First chapter should be visible at the beginning."
# go to second chapter and check that it is visible and the first section is not (should be scrolled away)
toc_first_level[1].find_element(By.XPATH, "li").click()
time.sleep(2)
toc_first_level[1].find_element(By.XPATH, "li").click()
time.sleep(2)
- second_chapter = main_content.find_elements(By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]")[1]
+ second_chapter = main_content.find_elements(
+ By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]"
+ )[1]
second_header = second_chapter.find_element(By.XPATH, "h1")
- assert is_visible(element=second_header, driver=driver), "Second chapter should be visible after scrolling to it."
- assert not is_visible(element=first_header, driver=driver), "First chapter shouldn't be visible because we scrolled to the second one."
+ assert is_visible(
+ element=second_header, driver=driver
+ ), "Second chapter should be visible after scrolling to it."
+ assert not is_visible(
+ element=first_header, driver=driver
+ ), "First chapter shouldn't be visible because we scrolled to the second one."
# YAML config is one-line because windows cmd probably doesn't support multiline
NOT_GENERATED_METADATA = "{ output: { html: { toc: false } } }"
+
def test_toc_not_generated(templates_path, input_path, out_path, page_url, driver):
out_dir = os.path.dirname(out_path)
python_path = sys.executable
- retval = subprocess.run(f"{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs=\"{templates_path}\" --execute --output-dir=\"{out_dir}\" --HtmlNbMetadataPreprocessor.pj_metadata=\"{NOT_GENERATED_METADATA}\"", check=True, shell=True)
+ retval = subprocess.run(
+ f'{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs="{templates_path}" --execute --output-dir="{out_dir}" --HtmlNbMetadataPreprocessor.pj_metadata="{NOT_GENERATED_METADATA}"',
+ check=True,
+ shell=True,
+ )
assert retval.returncode == 0, "jupyter nbconvert command ended up with a failure"
driver.get(page_url)
toc = driver.find_elements(By.XPATH, "//div[@id='TOC']")
assert len(toc) == 0, "TOC shouldnt've been generated"
+
NUMBER_SECTIONS_METADATA = "{ output: { html: { number_sections: true }} }"
+
def test_toc_number_sections(templates_path, input_path, out_path, page_url, driver):
out_dir = os.path.dirname(out_path)
python_path = sys.executable
- retval = subprocess.run(f"{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs=\"{templates_path}\" --execute --output-dir=\"{out_dir}\" --HtmlNbMetadataPreprocessor.pj_metadata=\"{NUMBER_SECTIONS_METADATA}\"", check=True, shell=True)
+ retval = subprocess.run(
+ f'{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs="{templates_path}" --execute --output-dir="{out_dir}" --HtmlNbMetadataPreprocessor.pj_metadata="{NUMBER_SECTIONS_METADATA}"',
+ check=True,
+ shell=True,
+ )
assert retval.returncode == 0, "jupyter nbconvert command ended up with a failure"
driver.get(page_url)
main_content = driver.find_element(By.XPATH, "//*[@id = 'main-content']")
- second_chapter = main_content.find_elements(By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]/h1")[1]
+ second_chapter = main_content.find_elements(
+ By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]/h1"
+ )[1]
assert second_chapter.get_attribute("innerHTML") == "2. Level 1"
- third_chapter = main_content.find_elements(By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]/h1")[2]
- assert third_chapter.get_attribute("innerHTML") == "Level 1", "The third Level 1 has been marked as unnumbered."
+ third_chapter = main_content.find_elements(
+ By.XPATH, "//div[contains(@class, 'section') and contains(@class, 'level1')]/h1"
+ )[2]
+ assert (
+ third_chapter.get_attribute("innerHTML") == "Level 1"
+ ), "The third Level 1 has been marked as unnumbered."
# test that Level 3s are numbered and they follow the proper naming convention
- assert main_content.find_element(By.XPATH, f"//*[@id = 'Level-2-O_O-1']/h2").get_attribute("innerHTML") == "1.1. Level 2"
- assert main_content.find_element(By.XPATH, f"//*[@id = 'Level-2-O_O-2']/h2").get_attribute("innerHTML") == "2.1. Level 2"
-
-
-
+ assert (
+ main_content.find_element(By.XPATH, f"//*[@id = 'Level-2-O_O-1']/h2").get_attribute(
+ "innerHTML"
+ )
+ == "1.1. Level 2"
+ )
+ assert (
+ main_content.find_element(By.XPATH, f"//*[@id = 'Level-2-O_O-2']/h2").get_attribute(
+ "innerHTML"
+ )
+ == "2.1. Level 2"
+ )
diff --git a/tests/test_notebooks/test_tokens.py b/tests/test_notebooks/test_tokens.py
index bcb7292..3982900 100644
--- a/tests/test_notebooks/test_tokens.py
+++ b/tests/test_notebooks/test_tokens.py
@@ -1,11 +1,12 @@
-import pytest
import os
-from selenium.webdriver.common.by import By
-from pathlib import Path
-import sys
import subprocess
+import sys
+from pathlib import Path
+
import nbconvert
+import pytest
from packaging import version
+from selenium.webdriver.common.by import By
@pytest.fixture
@@ -17,7 +18,11 @@ def input_path(fixture_dir):
def test_tokens(templates_path, input_path, out_path, page_url, driver):
out_dir = os.path.dirname(out_path)
python_path = sys.executable
- retval = subprocess.run(f"{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs={templates_path} --execute --output-dir=\"{out_dir}\"", check=True, shell=True)
+ retval = subprocess.run(
+ f'{python_path} -m jupyter nbconvert --to html --template pj {input_path} --TemplateExporter.extra_template_basedirs={templates_path} --execute --output-dir="{out_dir}"',
+ check=True,
+ shell=True,
+ )
assert retval.returncode == 0, "jupyter nbconvert command ended up with a failure"
driver.get(page_url)
@@ -35,7 +40,9 @@ def test_tokens(templates_path, input_path, out_path, page_url, driver):
assert "red" in header.get_attribute("class")
header = main_content.find_element(By.XPATH, "//div[@id = 'header-whitespaces-id']")
- assert header.find_element(By.XPATH, "h2").get_attribute("innerHTML") == "Header with whitespaces"
+ assert (
+ header.find_element(By.XPATH, "h2").get_attribute("innerHTML") == "Header with whitespaces"
+ )
assert "grey" in header.get_attribute("class")
##################
@@ -50,16 +57,14 @@ def test_tokens(templates_path, input_path, out_path, page_url, driver):
# PANDAS TABLE #
################
table = main_content.find_element(By.XPATH, "//table[@id = 'ptable-id']")
- assert "red" in table.get_attribute("class") and "pj-table-ignore" in table.get_attribute("class")
+ assert "red" in table.get_attribute("class") and "pj-table-ignore" in table.get_attribute(
+ "class"
+ )
#################
# HTML ELEMENTS #
#################
paragraph = main_content.find_element(By.XPATH, "//p[@id = 'paragraph-id']")
- assert "white-letter" in paragraph.get_attribute("class") and "red" in paragraph.get_attribute("class")
-
-
-
-
-
-
+ assert "white-letter" in paragraph.get_attribute("class") and "red" in paragraph.get_attribute(
+ "class"
+ )
diff --git a/tests/test_preprocessors/test_metadata_preprocessor/conftest.py b/tests/test_preprocessors/test_metadata_preprocessor/conftest.py
index 6199193..8de5500 100644
--- a/tests/test_preprocessors/test_metadata_preprocessor/conftest.py
+++ b/tests/test_preprocessors/test_metadata_preprocessor/conftest.py
@@ -1,8 +1,10 @@
from pathlib import Path
from unittest.mock import MagicMock, PropertyMock
+
import pytest
import yaml
+
@pytest.fixture
def fixture_dir():
return "tests/test_preprocessors/test_metadata_preprocessor/fixture"
@@ -18,13 +20,12 @@ def raw_cell(fixture_dir):
return cell
+
@pytest.fixture
def jmd_cell(fixture_dir):
cell = MagicMock(name="jmd_cell")
cell.metadata = {}
- cell.metadata["pj_metadata"] = {
- "input_fold": "disable"
- }
+ cell.metadata["pj_metadata"] = {"input_fold": "disable"}
with open(Path(fixture_dir) / "jmd_cell.md") as file:
type(cell).source = PropertyMock(return_value=file.read())
type(cell).cell_type = PropertyMock(return_value="code")
@@ -33,13 +34,12 @@ def jmd_cell(fixture_dir):
output = MagicMock(name="output")
output.metadata = {}
type(output).output_type = PropertyMock(return_value="execute_result")
- type(output).data = {
- "text/markdown": []
- }
+ type(output).data = {"text/markdown": []}
type(cell).outputs = PropertyMock(return_value=[output])
return cell
+
@pytest.fixture
def code_cell(fixture_dir):
cell = MagicMock(name="code_cell")
@@ -85,11 +85,13 @@ def code_cell(fixture_dir):
return cell
+
@pytest.fixture
def nb_defaults_path(fixture_dir):
return Path(fixture_dir) / "default_nb.yaml"
+
@pytest.fixture
def nb_defaults(nb_defaults_path):
with open(nb_defaults_path) as file:
- return yaml.safe_load(nb_defaults)
\ No newline at end of file
+ return yaml.safe_load(nb_defaults)
diff --git a/tests/test_preprocessors/test_metadata_preprocessor/fixture/code_cell.py b/tests/test_preprocessors/test_metadata_preprocessor/fixture/code_cell.py
index 6fa07bf..b3f389e 100644
--- a/tests/test_preprocessors/test_metadata_preprocessor/fixture/code_cell.py
+++ b/tests/test_preprocessors/test_metadata_preprocessor/fixture/code_cell.py
@@ -1,4 +1,4 @@
# -.-|m { input: true, input_fold: hide, output_error: false }
a = 5
b = 3
-c = a + b
\ No newline at end of file
+c = a + b
diff --git a/tests/test_preprocessors/test_metadata_preprocessor/test_metadata_preprocessor.py b/tests/test_preprocessors/test_metadata_preprocessor/test_metadata_preprocessor.py
index 9467a9e..1207c6c 100644
--- a/tests/test_preprocessors/test_metadata_preprocessor/test_metadata_preprocessor.py
+++ b/tests/test_preprocessors/test_metadata_preprocessor/test_metadata_preprocessor.py
@@ -1,17 +1,20 @@
from pathlib import Path
-import yaml
-import pytest
from unittest.mock import MagicMock
-from pretty_jupyter.preprocessors import NbMetadataPreprocessor, HtmlNbMetadataPreprocessor
+
import nbconvert
+import pytest
+import yaml
from packaging import version
+from pretty_jupyter.preprocessors import HtmlNbMetadataPreprocessor, NbMetadataPreprocessor
+
@pytest.fixture
def expected_raw_cell(fixture_dir):
with open(Path(fixture_dir) / "expected_test_raw.yaml") as file:
return yaml.safe_load(file.read())
+
def test_preprocess_raw_cell(raw_cell, nb_defaults_path, expected_raw_cell):
NbMetadataPreprocessor.nb_defaults_path = nb_defaults_path
override_config = "{ output: { general: { input: false } } }"
@@ -41,7 +44,12 @@ def test_preprocess_jmd_cell(jmd_cell, nb_defaults_path):
with pytest.warns(UserWarning):
cell, resources = preprocessor.preprocess_cell(jmd_cell, resources, index=3)
- assert cell.metadata["pj_metadata"] == {'input': False, 'output': False, 'input_fold': 'fold-show', 'output_error': True}
+ assert cell.metadata["pj_metadata"] == {
+ "input": False,
+ "output": False,
+ "input_fold": "fold-show",
+ "output_error": True,
+ }
if version.parse(nbconvert.__version__) >= version.parse("7.0.0"):
assert cell.metadata["transient"] == {"remove_source": True}
else:
@@ -60,7 +68,3 @@ def test_preprocess_code_cell(code_cell, nb_defaults_path):
assert cell.transient is None
assert len(cell.outputs) == 1
assert cell.outputs[0].output_type == "execute_result"
-
-
-
-
diff --git a/tests/test_tokens/conftest.py b/tests/test_tokens/conftest.py
index 6df54c7..0bbcaea 100644
--- a/tests/test_tokens/conftest.py
+++ b/tests/test_tokens/conftest.py
@@ -6,7 +6,8 @@ def input_str():
with open("tests/test_tokens/fixture/input.md", "r") as file:
return file.read()
+
@pytest.fixture
def expected_str():
with open("tests/test_tokens/fixture/expected.md", "r") as file:
- return file.read()
\ No newline at end of file
+ return file.read()
diff --git a/tests/test_tokens/test_tokens.py b/tests/test_tokens/test_tokens.py
index cd9e3fe..231968a 100644
--- a/tests/test_tokens/test_tokens.py
+++ b/tests/test_tokens/test_tokens.py
@@ -1,6 +1,7 @@
from pretty_jupyter.tokens import convert_markdown_tokens_to_html
+
def test_convert_markdown_tokens_to_html(input_str, expected_str):
actual_str = convert_markdown_tokens_to_html(input_str)
- assert actual_str == expected_str, "Expected string is different than the actual."
\ No newline at end of file
+ assert actual_str == expected_str, "Expected string is different than the actual."