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

FIX: fix path suffix condition in core/read.py #641

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion myst_nb/core/read.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def create_nb_reader(
# we check suffixes ordered by longest first, to ensure we get the "closest" match
iterator = sorted(readers.items(), key=lambda x: len(x[0]), reverse=True)
for suffix, (reader, reader_kwargs, commonmark_only) in iterator:
if Path(path).suffix == suffix:
if str(Path(path)).endswith(suffix):
if isinstance(reader, str):
# attempt to load the reader as an object path
reader = import_object(reader)
Expand Down
34 changes: 25 additions & 9 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ def build_matplotlib_font_cache():
FontManager()


def _split_ext(conf, sphinx_params):
if custom_formats := conf.get("nb_custom_formats"):
split_files = [
file.rstrip(k)
for file in sphinx_params["files"]
for k in custom_formats.keys()
if file.endswith(k)
]
else:
split_files = [os.path.splitext(file)[0] for file in sphinx_params["files"]]

return split_files[0], split_files


@pytest.fixture()
def get_test_path():
def _get_test_path(name):
Expand All @@ -55,7 +69,7 @@ class SphinxFixture:
def __init__(self, app, filenames):
self.app = app
self.env = app.env
self.files = [os.path.splitext(ff) for ff in filenames]
self.files = filenames
self.software_versions = (
f".sphinx{sphinx.version_info[0]}" # software version tracking for fixtures
)
Expand All @@ -79,42 +93,42 @@ def warnings(self):

def invalidate_files(self):
"""Invalidate the files, such that it will be flagged for a re-read."""
for name, _ in self.files:
for name in self.files:
self.env.all_docs.pop(name)

def get_resolved_doctree(self, docname=None):
"""Load and return the built docutils.document, after post-transforms."""
docname = docname or self.files[0][0]
docname = docname or self.files[0]
doctree = self.env.get_and_resolve_doctree(docname, self.app.builder)
doctree["source"] = docname
return doctree

def get_doctree(self, docname=None):
"""Load and return the built docutils.document."""
docname = docname or self.files[0][0]
docname = docname or self.files[0]
doctree = self.env.get_doctree(docname)
doctree["source"] = docname
return doctree

def get_html(self, index=0):
"""Return the built HTML file."""
name = self.files[index][0]
name = self.files[index]
_path = self.app.outdir / (name + ".html")
if not _path.exists():
pytest.fail("html not output")
return bs4.BeautifulSoup(_path.read_text(), "html.parser")

def get_nb(self, index=0):
"""Return the output notebook (after any execution)."""
name = self.files[index][0]
name = self.files[index]
_path = self.app.srcdir / "_build" / "jupyter_execute" / (name + ".ipynb")
if not _path.exists():
pytest.fail("notebook not output")
return _path.read_text(encoding="utf-8")

def get_report_file(self, index=0):
"""Return the report file for a failed execution."""
name = self.files[index][0]
name = self.files[index]
_path = self.app.outdir / "reports" / (name + ".err.log")
if not _path.exists():
pytest.fail("report log not output")
Expand Down Expand Up @@ -153,9 +167,11 @@ def sphinx_run(sphinx_params, make_app, tmp_path):
conf = sphinx_params.get("conf", {})
buildername = sphinx_params.get("buildername", "html")

master_doc, split_files = _split_ext(conf, sphinx_params)

confoverrides = {
"extensions": ["myst_nb"],
"master_doc": os.path.splitext(sphinx_params["files"][0])[0],
"master_doc": master_doc,
"exclude_patterns": ["_build"],
"nb_execution_show_tb": True,
}
Expand Down Expand Up @@ -199,7 +215,7 @@ def sphinx_run(sphinx_params, make_app, tmp_path):
buildername=buildername, srcdir=app_srcdir, confoverrides=confoverrides
)

yield SphinxFixture(app, sphinx_params["files"])
yield SphinxFixture(app, split_files)

# reset working directory
os.chdir(current_dir)
Expand Down
21 changes: 21 additions & 0 deletions tests/notebooks/custom-formats2.extra.exnt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: "Test chunk options in Rmd/Jupyter conversion"
author: "Marc Wouts"
date: "June 16, 2018"
jupyter:
kernelspec:
display_name: Python
language: python
name: python3
---

# Custom Formats

```{python echo=TRUE}
import pandas as pd
x = pd.Series({'A':1, 'B':3, 'C':2})
```

```{python bar_plot, echo=FALSE, fig.height=5, fig.width=8}
x.plot(kind='bar', title='Sample plot')
```
44 changes: 44 additions & 0 deletions tests/test_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,3 +365,47 @@ def test_custom_convert_cache(sphinx_run, file_regression, check_nbs):
assert data
assert data["method"] == "cache"
assert data["succeeded"] is True


@pytest.mark.sphinx_params(
"custom-formats2.extra.exnt",
conf={
"nb_execution_mode": "auto",
"nb_custom_formats": {".extra.exnt": ["jupytext.reads", {"fmt": "Rmd"}]},
},
)
def test_custom_convert_multiple_extensions_auto(
sphinx_run, file_regression, check_nbs
):
"""The outputs should be populated."""
sphinx_run.build()
assert sphinx_run.warnings() == ""
regress_nb_doc(file_regression, sphinx_run, check_nbs)

assert NbMetadataCollector.new_exec_data(sphinx_run.env)
data = NbMetadataCollector.get_exec_data(sphinx_run.env, "custom-formats2")
assert data
assert data["method"] == "auto"
assert data["succeeded"] is True


@pytest.mark.sphinx_params(
"custom-formats2.extra.exnt",
conf={
"nb_execution_mode": "cache",
"nb_custom_formats": {".extra.exnt": ["jupytext.reads", {"fmt": "Rmd"}]},
},
)
def test_custom_convert_multiple_extensions_cache(
sphinx_run, file_regression, check_nbs
):
"""The outputs should be populated."""
sphinx_run.build()
assert sphinx_run.warnings() == ""
regress_nb_doc(file_regression, sphinx_run, check_nbs)

assert NbMetadataCollector.new_exec_data(sphinx_run.env)
data = NbMetadataCollector.get_exec_data(sphinx_run.env, "custom-formats2")
assert data
assert data["method"] == "cache"
assert data["succeeded"] is True
102 changes: 102 additions & 0 deletions tests/test_execute/test_custom_convert_multiple_extensions_auto.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{
"cells": [
{
"cell_type": "raw",
"id": "d0aefb9b",
"metadata": {},
"source": [
"---\n",
"title: \"Test chunk options in Rmd/Jupyter conversion\"\n",
"author: \"Marc Wouts\"\n",
"date: \"June 16, 2018\"\n",
"---"
]
},
{
"cell_type": "markdown",
"id": "c67b3701",
"metadata": {},
"source": [
"# Custom Formats"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "ef881a36",
"metadata": {
"echo": true
},
"outputs": [],
"source": [
"import pandas as pd\n",
"x = pd.Series({'A':1, 'B':3, 'C':2})"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "f7710843",
"metadata": {
"fig.height": 5,
"fig.width": 8,
"name": "bar_plot",
"tags": [
"remove_input"
]
},
"outputs": [
{
"data": {
"text/plain": [
"<Axes: title={'center': 'Sample plot'}>"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"x.plot(kind='bar', title='Sample plot')"
]
}
],
"metadata": {
"jupytext": {
"text_representation": {
"extension": ".Rmd",
"format_name": "rmarkdown"
}
},
"kernelspec": {
"display_name": "Python",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.8"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading