From f66a4fc204598c2abfe388b680694e3ff0d2dbbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Fri, 27 May 2022 06:54:04 +0200 Subject: [PATCH] dev-python/nbconvert: Support mistune-2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Górny --- .../files/nbconvert-6.5.0-mistune-2.patch | 339 ++++++++++++++++++ .../nbconvert/nbconvert-6.5.0-r1.ebuild | 82 +++++ 2 files changed, 421 insertions(+) create mode 100644 dev-python/nbconvert/files/nbconvert-6.5.0-mistune-2.patch create mode 100644 dev-python/nbconvert/nbconvert-6.5.0-r1.ebuild diff --git a/dev-python/nbconvert/files/nbconvert-6.5.0-mistune-2.patch b/dev-python/nbconvert/files/nbconvert-6.5.0-mistune-2.patch new file mode 100644 index 0000000000000..4a3f4731b32d5 --- /dev/null +++ b/dev-python/nbconvert/files/nbconvert-6.5.0-mistune-2.patch @@ -0,0 +1,339 @@ +From 6e5ba41803cc8c3192f001b3ede9b74454220bda Mon Sep 17 00:00:00 2001 +From: Tiago de Paula +Date: Mon, 9 May 2022 09:39:31 -0300 +Subject: [PATCH] Update to Mistune 2.0.2 (#1764) + +Co-authored-by: Steven Silvester +--- + nbconvert/filters/markdown_mistune.py | 212 ++++++++++++++------------ + setup.py | 2 +- + 2 files changed, 119 insertions(+), 95 deletions(-) + +diff --git a/nbconvert/filters/markdown_mistune.py b/nbconvert/filters/markdown_mistune.py +index 382a5388..636e1e8c 100644 +--- a/nbconvert/filters/markdown_mistune.py ++++ b/nbconvert/filters/markdown_mistune.py +@@ -21,7 +21,7 @@ except ImportError: + from cgi import escape as html_escape + + import bs4 +-import mistune ++from mistune import BlockParser, HTMLRenderer, InlineParser, Markdown + from pygments import highlight + from pygments.formatters import HtmlFormatter + from pygments.lexers import get_lexer_by_name +@@ -34,158 +34,183 @@ class InvalidNotebook(Exception): + pass + + +-class MathBlockGrammar(mistune.BlockGrammar): +- """This defines a single regex comprised of the different patterns that +- identify math content spanning multiple lines. These are used by the +- MathBlockLexer. ++class MathBlockParser(BlockParser): ++ """This acts as a pass-through to the MathInlineParser. It is needed in ++ order to avoid other block level rules splitting math sections apart. + """ + +- multi_math_str = "|".join( +- [r"^\$\$.*?\$\$", r"^\\\\\[.*?\\\\\]", r"^\\begin\{([a-z]*\*?)\}(.*?)\\end\{\1\}"] ++ MULTILINE_MATH = re.compile( ++ r"(?=2.0.0`, where the pattern is passed ++ to the undocumented `re.Scanner`. + """ +- +- inline_math = re.compile(r"^\$(.+?)\$|^\\\\\((.+?)\\\\\)", re.DOTALL) +- block_math = re.compile(r"^\$\$(.*?)\$\$|^\\\\\[(.*?)\\\\\]", re.DOTALL) +- latex_environment = re.compile(r"^\\begin\{([a-z]*\*?)\}(.*?)\\end\{\1\}", re.DOTALL) +- text = re.compile(r"^[\s\S]+?(?=[\\%s\n" % mistune.escape(code) ++ return super().block_code(code) + + formatter = HtmlFormatter() + return highlight(code, lexer, formatter) + + def block_html(self, html): +- embed_images = self.options.get("embed_images", False) +- +- if embed_images: ++ if self.embed_images: + html = self._html_embed_images(html) + + return super().block_html(html) + + def inline_html(self, html): +- embed_images = self.options.get("embed_images", False) +- +- if embed_images: ++ if self.embed_images: + html = self._html_embed_images(html) + + return super().inline_html(html) + +- def header(self, text, level, raw=None): +- html = super().header(text, level, raw=raw) +- if self.options.get("exclude_anchor_links"): ++ def heading(self, text, level): ++ html = super().heading(text, level) ++ if self.exclude_anchor_links: + return html +- anchor_link_text = self.options.get("anchor_link_text", "¶") +- return add_anchor(html, anchor_link_text=anchor_link_text) ++ return add_anchor(html, anchor_link_text=self.anchor_link_text) + + def escape_html(self, text): + return html_escape(text) + ++ def multiline_math(self, text): ++ return text ++ + def block_math(self, text): +- return "$$%s$$" % self.escape_html(text) ++ return f"$${self.escape_html(text)}$$" + + def latex_environment(self, name, text): +- name = self.escape_html(name) +- text = self.escape_html(text) +- return rf"\begin{{{name}}}{text}\end{{{name}}}" ++ name, text = self.escape_html(name), self.escape_html(text) ++ return f"\\begin{{{name}}}{text}\\end{{{name}}}" + + def inline_math(self, text): +- return "$%s$" % self.escape_html(text) ++ return f"${self.escape_html(text)}$" + +- def image(self, src, title, text): ++ def image(self, src, text, title): + """Rendering a image with title and text. + + :param src: source link of the image. +- :param title: title text of the image. + :param text: alt text of the image. ++ :param title: title text of the image. + """ +- attachments = self.options.get("attachments", {}) + attachment_prefix = "attachment:" +- embed_images = self.options.get("embed_images", False) + + if src.startswith(attachment_prefix): + name = src[len(attachment_prefix) :] + +- if name not in attachments: ++ if name not in self.attachments: + raise InvalidNotebook(f"missing attachment: {name}") + +- attachment = attachments[name] ++ attachment = self.attachments[name] + # we choose vector over raster, and lossless over lossy + preferred_mime_types = ["image/svg+xml", "image/png", "image/jpeg"] + for preferred_mime_type in preferred_mime_types: +@@ -197,13 +222,13 @@ class IPythonRenderer(mistune.Renderer): + data = attachment[mime_type] + src = "data:" + mime_type + ";base64," + data + +- elif embed_images: ++ elif self.embed_images: + base64_url = self._src_to_base64(src) + + if base64_url is not None: + src = base64_url + +- return super().image(src, title, text) ++ return super().image(src, text, title) + + def _src_to_base64(self, src): + """Turn the source file into a base64 url. +@@ -211,8 +236,7 @@ class IPythonRenderer(mistune.Renderer): + :param src: source link of the file. + :return: the base64 url or None if the file was not found. + """ +- path = self.options.get("path", "") +- src_path = os.path.join(path, src) ++ src_path = os.path.join(self.path, src) + + if not os.path.exists(src_path): + return None +diff --git a/setup.py b/setup.py +index 7220a875..2dfa2534 100644 +--- a/setup.py ++++ b/setup.py +@@ -245,7 +245,7 @@ setup_args["install_requires"] = [ + "jupyter_core>=4.7", + "jupyterlab_pygments", + "MarkupSafe>=2.0", +- "mistune>=0.8.1,<2", ++ "mistune>=2.0.2", + "nbclient>=0.5.0", + "nbformat>=5.1", + "packaging", +-- +2.35.1 + diff --git a/dev-python/nbconvert/nbconvert-6.5.0-r1.ebuild b/dev-python/nbconvert/nbconvert-6.5.0-r1.ebuild new file mode 100644 index 0000000000000..39c667a2c5766 --- /dev/null +++ b/dev-python/nbconvert/nbconvert-6.5.0-r1.ebuild @@ -0,0 +1,82 @@ +# Copyright 1999-2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +DISTUTILS_USE_PEP517=setuptools +PYTHON_COMPAT=( python3_{8..10} ) + +inherit distutils-r1 + +DESCRIPTION="Converting Jupyter Notebooks" +HOMEPAGE=" + https://nbconvert.readthedocs.io/ + https://github.com/jupyter/nbconvert/ + https://pypi.org/project/nbconvert/ +" +SRC_URI=" + mirror://pypi/${PN:0:1}/${PN}/${P}.tar.gz +" + +LICENSE="BSD" +SLOT="0" +KEYWORDS="~amd64 ~arm ~arm64 ~hppa ~ia64 ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86" + +RDEPEND=" + dev-python/beautifulsoup4[${PYTHON_USEDEP}] + dev-python/bleach[${PYTHON_USEDEP}] + dev-python/defusedxml[${PYTHON_USEDEP}] + >=dev-python/entrypoints-0.2.2[${PYTHON_USEDEP}] + dev-python/jinja[${PYTHON_USEDEP}] + dev-python/jupyter_core[${PYTHON_USEDEP}] + dev-python/jupyterlab_pygments[${PYTHON_USEDEP}] + >=dev-python/markupsafe-2.0[${PYTHON_USEDEP}] + >=dev-python/mistune-2.0.2[${PYTHON_USEDEP}] + dev-python/nbclient[${PYTHON_USEDEP}] + dev-python/nbformat[${PYTHON_USEDEP}] + >=dev-python/pandocfilters-1.4.1[${PYTHON_USEDEP}] + dev-python/pygments[${PYTHON_USEDEP}] + >=dev-python/traitlets-5.1.1[${PYTHON_USEDEP}] + dev-python/testpath[${PYTHON_USEDEP}] + www-servers/tornado[${PYTHON_USEDEP}] +" +BDEPEND=" + test? ( + dev-python/pebble[${PYTHON_USEDEP}] + dev-python/ipykernel[${PYTHON_USEDEP}] + dev-python/ipywidgets[${PYTHON_USEDEP}] + >=dev-python/jupyter_client-4.2[${PYTHON_USEDEP}] + ) +" + +distutils_enable_tests pytest + +PATCHES=( + "${FILESDIR}"/${P}-mistune-2.patch +) + +src_test() { + mkdir -p "${HOME}/.local" || die + cp -r share "${HOME}/.local/" || die + distutils-r1_src_test +} + +python_test() { + local EPYTEST_DESELECT=( + # Missing pyppeteer for now + # TODO: Doesn't skip? + nbconvert/exporters/tests/test_webpdf.py + # Needs pyppeteer too + 'nbconvert/tests/test_nbconvertapp.py::TestNbConvertApp::test_webpdf_with_chromium' + ) + + epytest --pyargs nbconvert +} + +pkg_postinst() { + if ! has_version app-text/pandoc ; then + einfo "Pandoc is required for converting to formats other than Python," + einfo "HTML, and Markdown. If you need this functionality, install" + einfo "app-text/pandoc." + fi +}