From 9efbcf064127761ca92de7e3405bf34659182504 Mon Sep 17 00:00:00 2001 From: xadupre Date: Wed, 9 Oct 2024 00:21:30 +0200 Subject: [PATCH 01/13] Add tools to fix latex in text --- .gitignore | 1 + _doc/api/tools.rst | 8 +- _unittests/ut_tools/test_latex_functions.py | 27 +++++ sphinx_runpython/tools/latex_functions.py | 112 ++++++++++++++++++++ 4 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 _unittests/ut_tools/test_latex_functions.py create mode 100644 sphinx_runpython/tools/latex_functions.py diff --git a/.gitignore b/.gitignore index 350005b..df9ed38 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ _doc/examples/*.html _doc/examples/plot_*.png _doc/_static/require.js _doc/_static/viz.js +_doc/sg_execution_times.rst _unittests/ut__main/*.png _unittests/ut__main/data/*.rst _unittests/ut__main/data/*.py diff --git a/_doc/api/tools.rst b/_doc/api/tools.rst index ef56e9b..45edb46 100644 --- a/_doc/api/tools.rst +++ b/_doc/api/tools.rst @@ -2,7 +2,6 @@ tools ===== - Checks the readme syntax ======================== @@ -28,3 +27,10 @@ into examples which can be used into a sphinx gallery. :: python -m sphinx_runpython --help + +Tools related to latex +====================== + +.. autofunction:: sphinx_runpython.tools.latex_functions.build_regex + +.. autofunction:: sphinx_runpython.tools.latex_functions.replace_latex_command diff --git a/_unittests/ut_tools/test_latex_functions.py b/_unittests/ut_tools/test_latex_functions.py new file mode 100644 index 0000000..3ecbb5d --- /dev/null +++ b/_unittests/ut_tools/test_latex_functions.py @@ -0,0 +1,27 @@ +import unittest +from sphinx_runpython.ext_test_case import ExtTestCase +from sphinx_runpython.tools.latex_functions import build_regex, replace_latex_command + + +class TestLatexFunction(ExtTestCase): + + def test_build_regex(self): + regs = build_regex() + self.assertEqual(regs["supegal"], "\\geqslant") + + def test_replace_pattern(self): + self.assertEqual(replace_latex_command("\\R"), "\\mathbb{R}") + self.assertEqual(replace_latex_command("A\\R B"), "A\\mathbb{R} B") + self.assertEqual(replace_latex_command("\\pa{5+3i}"), "\\left(5+3i\\right)") + self.assertEqual(replace_latex_command("A\\pa{5+3i}B"), "A\\left(5+3i\\right)B") + self.assertEqual(replace_latex_command("\\cro{5+3i}"), "\\left[5+3i\\right]") + self.assertEqual( + replace_latex_command("\\acc{5+3i}"), "\\left\\{5+3i\\right\\}" + ) + self.assertEqual( + replace_latex_command("\\vecteur{a}{b}"), "\\left(a,\\dots,b\\right)" + ) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/sphinx_runpython/tools/latex_functions.py b/sphinx_runpython/tools/latex_functions.py new file mode 100644 index 0000000..8ba9cd0 --- /dev/null +++ b/sphinx_runpython/tools/latex_functions.py @@ -0,0 +1,112 @@ +import re +from typing import Dict, Optional, Tuple, Union + +PREAMBLE = """ +\\newcommand{\\vecteurno}[2]{#1,\\dots,#2} +\\newcommand{\\R}{\\mathbb{R}} +\\newcommand{\\pa}[1]{\\left(#1\\right)} +\\newcommand{\\cro}[1]{\\left[#1\\right]} +\\newcommand{\\acc}[1]{\\left\\{#1\\right\\}} +\\newcommand{\\vecteur}[2]{\\left(#1,\\dots,#2\\right)} +\\newcommand{\\N}[0]{\\mathbb{N}} +\\newcommand{\\indicatrice}[1]{ {1\\!\\!1}_{\\left\\{#1\\right\\}} } +\\newcommand{\\infegal}[0]{\\leqslant} +\\newcommand{\\supegal}[0]{\\geqslant} +\\newcommand{\\ensemble}[2]{\\left\\{#1,\\dots,#2\\right\\}} +\\newcommand{\\fleche}[1]{\\overrightarrow{#1}} +\\newcommand{\\intervalle}[2]{\\left\\{#1,\\cdots,#2\\right\\}} +\\newcommand{\\independant}[0]{\\perp \\!\\!\\! \\perp} +\\newcommand{\\esp}{\\mathbb{E}} +\\newcommand{\\espf}[2]{\\mathbb{E}_{#1}\\left(#2\\right)} +\\newcommand{\\var}{\\mathbb{V}} +\\newcommand{\\pr}[1]{\\mathbb{P}\\left(#1\\right)} +\\newcommand{\\loi}[0]{{\\cal L}} +\\newcommand{\\norm}[1]{\\left\\Vert#1\\right\\Vert} +\\newcommand{\\norme}[1]{\\left\\Vert#1\\right\\Vert} +\\newcommand{\\scal}[2]{\\left<#1,#2\\right>} +\\newcommand{\\dans}[0]{\\rightarrow} +\\newcommand{\\partialfrac}[2]{\\frac{\\partial #1}{\\partial #2}} +\\newcommand{\\partialdfrac}[2]{\\dfrac{\\partial #1}{\\partial #2}} +\\newcommand{\\trace}[1]{tr\\left(#1\\right)} +\\newcommand{\\sac}[0]{|} +\\newcommand{\\abs}[1]{\\left|#1\\right|} +\\newcommand{\\loinormale}[2]{{\\cal N} \\left(#1,#2\\right)} +\\newcommand{\\loibinomialea}[1]{{\\cal B} \\left(#1\\right)} +\\newcommand{\\loibinomiale}[2]{{\\cal B} \\left(#1,#2\\right)} +\\newcommand{\\loimultinomiale}[1]{{\\cal M} \\left(#1\\right)} +\\newcommand{\\variance}[1]{\\mathbb{V}\\left(#1\\right)} +\\newcommand{\\intf}[1]{\\left\\lfloor #1 \\right\\rfloor} +""" + + +def build_regex(text: Optional[str] = None) -> Dict[str, Union[str, Tuple[str, str]]]: + """ + Parses a preamble in latex and builds regular expressions + based on it. + """ + if text is None: + text = PREAMBLE + lines = [_ for _ in text.split("\n") if "newcommand" in _] + reg = re.compile(r"newcommand\{\\([a-zA-Z]+)\}(\[([0-9])\])?\{(.+)\}") + res = {} + for i, line in enumerate(lines): + match = reg.search(line) + assert match, f"Unable to match pattern reg={reg} in line {i}: {line!r}" + name, n, pat = match.group(1), match.group(3), match.group(4) + if n is None or int(n) == 0: + res[name] = pat + else: + look = f"\\\\{name} *" + "\\{(.+)\\}" * int(n) + for c in "\\": + pat = pat.replace(c, f"\\{c}") + for k in range(0, int(n)): + pat = pat.replace(f"#{k+1}", f"\\{k+1}") + res[name] = (look, pat) + return res + + +def replace_latex_command( + text: str, patterns: Optional[Dict[str, Union[str, Tuple[str, str]]]] = None +) -> str: + """ + Replaces a latex by its raw expression. + + :param text: text + :param regex: one in the known list or None for all + :return: modified text + + The default patterns are defined by: + + .. runpython:: + :showcode: + + from sphinx_runpython.tools.latex_functions import PREAMBLE + + print(PREAMBLE) + + With gives: + + .. runpython:: + :showcode: + + import pprint + from sphinx_runpython.tools.latex_functions import build_regex + + pprint.pprint(build_regex()) + """ + if patterns is None: + patterns = build_regex() + + for k, v in patterns.items(): + if isinstance(v, str): + text = text.replace(f"\\{k}", v) + elif isinstance(v, tuple) and len(v) == 2: + try: + text = re.sub(v[0], v[1], text) + except re.error as e: + raise AssertionError( + f"Unable to replace pattern {v[0]!r} by {v[1]!r} for text={text!r}" + ) from e + else: + raise AssertionError(f"Unable to understand v={v!r} for k={k!r}") + return text From d3febf7fededb82ea66a7093b054be016518874e Mon Sep 17 00:00:00 2001 From: xadupre Date: Wed, 9 Oct 2024 15:32:07 +0200 Subject: [PATCH 02/13] better style --- _doc/conf.py | 1 - .../data/float_and_double_rouding.ipynb | 20 +-- .../ut__main/test_documentation_examples.py | 2 +- _unittests/ut_gdot/test_download_helper.py | 2 +- pyproject.toml | 47 +++++- setup.py | 1 - sphinx_runpython/__init__.py | 1 - .../blocdefs/sphinx_blocref_extension.py | 24 +-- .../blocdefs/sphinx_mathdef_extension.py | 30 ++-- .../collapse/sphinx_collapse_extension.py | 2 +- sphinx_runpython/convert.py | 2 +- .../docassert/sphinx_docassert_extension.py | 2 +- .../epkg/sphinx_epkg_extension.py | 9 +- sphinx_runpython/ext_helper.py | 12 +- sphinx_runpython/ext_io_helper.py | 37 ++--- sphinx_runpython/ext_test_case.py | 9 +- .../gdot/sphinx_gdot_extension.py | 4 +- sphinx_runpython/import_object_helper.py | 17 +-- sphinx_runpython/language.py | 2 +- .../quote/sphinx_quote_extension.py | 13 +- sphinx_runpython/readme.py | 24 ++- sphinx_runpython/runpython/run_cmd.py | 17 ++- .../runpython/sphinx_runpython_extension.py | 140 +++++++++--------- sphinx_runpython/sphinx_rst_builder.py | 44 +++--- sphinx_runpython/tools/img_export.py | 6 +- sphinx_runpython/tools/latex_functions.py | 2 +- 26 files changed, 246 insertions(+), 224 deletions(-) diff --git a/_doc/conf.py b/_doc/conf.py index 44af3b6..f3eed40 100644 --- a/_doc/conf.py +++ b/_doc/conf.py @@ -1,4 +1,3 @@ -# coding: utf-8 import os import sys from sphinx_runpython import __version__ diff --git a/_unittests/ut__main/data/float_and_double_rouding.ipynb b/_unittests/ut__main/data/float_and_double_rouding.ipynb index bc37d49..2769921 100644 --- a/_unittests/ut__main/data/float_and_double_rouding.ipynb +++ b/_unittests/ut__main/data/float_and_double_rouding.ipynb @@ -299,7 +299,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "" ] @@ -329,7 +329,7 @@ "source": [ "import random\n", "\n", - "for i in range(0, 100000):\n", + "for i in range(100000):\n", " i, j = random.randint(0, len(rnd32) - 1), random.randint(0, len(rnd32) - 1)\n", " d32 = numpy.float64(rnd32[i] * rnd32[j])\n", " d64 = numpy.float64(rnd32[i]) * numpy.float64(rnd32[j])\n", @@ -396,7 +396,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "" ] @@ -597,7 +597,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "" ] @@ -627,7 +627,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "" ] @@ -773,7 +773,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "" ] @@ -911,7 +911,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "" ] @@ -1050,7 +1050,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "" ] @@ -1190,7 +1190,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "" ] @@ -1243,4 +1243,4 @@ }, "nbformat": 4, "nbformat_minor": 2 -} \ No newline at end of file +} diff --git a/_unittests/ut__main/test_documentation_examples.py b/_unittests/ut__main/test_documentation_examples.py index e870745..1791f08 100644 --- a/_unittests/ut__main/test_documentation_examples.py +++ b/_unittests/ut__main/test_documentation_examples.py @@ -49,7 +49,7 @@ def run_test(self, fold: str, name: str, verbose=0) -> int: if verbose: print(f"failed: {name!r} due to missing dot.") return 0 - raise AssertionError( + raise AssertionError( # noqa: B904 "Example '{}' (cmd: {} - exec_prefix='{}') " "failed due to\n{}" "".format(name, cmds, sys.exec_prefix, st) diff --git a/_unittests/ut_gdot/test_download_helper.py b/_unittests/ut_gdot/test_download_helper.py index 989089d..b400382 100644 --- a/_unittests/ut_gdot/test_download_helper.py +++ b/_unittests/ut_gdot/test_download_helper.py @@ -17,7 +17,7 @@ def test_download_timeout(self): except InternetException: return - assert False + raise AssertionError(f"No exception raised for url={url!r}") if __name__ == "__main__": diff --git a/pyproject.toml b/pyproject.toml index d280fb0..ba20bd7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,14 +6,49 @@ exclude = [ ".git", "build", "dist", + "onnxscript", ] -# Same as Black. -line-length = 88 +line-length = 93 -[tool.ruff.lint.mccabe] -# Unlike Flake8, default to a complexity level of 10. -max-complexity = 10 +[tool.ruff.lint] +select = [ + "B", # flake8-bugbear + "C4", # flake8-comprehensions + #"D", # pydocstyle + "E", # pycodestyle + "F", # Pyflakes + "G", # flake8-logging-format + #"I", # isort + "ISC", # flake8-implicit-str-concat + "LOG", # flake8-logging + #"N", # pep8-naming + #"NPY", # modern numpy + #"PERF", # Perflint + "PIE", # flake8-pie + "PYI", # flake8-pyi + "RUF", # Ruff-specific rules + "SIM", # flake8-simplify + "SLOT", # flake8-slot + "T10", # flake8-debugger + #"TID", # Disallow relative imports + #"TRY", # flake8-try-except-raise + "UP", # pyupgrade + "W", # pycodestyle + "YTT", # flake8-2020 +] -[tool.ruff.lint.per-file-ignores] +[tool.ruff.lint.extend-per-file-ignores] +"**" = [ + "C401", "C408", "C413", + "PIE790", + "PYI041", + "RUF012", "RUF100", "RUF010", + "SIM108", "SIM102", "SIM114", "SIM103", "SIM910", + "UP015", "UP027", "UP031", "UP034", "UP032" +] +"_doc/examples/plot_*.py" = ["E402", "B018", "PIE808", "SIM105", "SIM117"] +"_doc/notebooks/plot_*.py" = ["E402", "B018", "PIE808", "SIM105", "SIM117"] +"_doc/examples/plot_first_example.py" = ["F811"] +"_unittests/*/data/*.ipynb" = ["UP030"] "sphinx_runpython/runpython/sphinx_runpython_extension.py" = ["F401"] diff --git a/setup.py b/setup.py index 0781717..c2abad8 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os from setuptools import setup diff --git a/sphinx_runpython/__init__.py b/sphinx_runpython/__init__.py index e989e8a..bc412c6 100644 --- a/sphinx_runpython/__init__.py +++ b/sphinx_runpython/__init__.py @@ -1,4 +1,3 @@ -# coding: utf-8 __version__ = "0.3.0" __author__ = "Xavier Dupré" __github__ = "https://github.com/sdpython/sphinx-runpython" diff --git a/sphinx_runpython/blocdefs/sphinx_blocref_extension.py b/sphinx_runpython/blocdefs/sphinx_blocref_extension.py index 2a18261..d18d2a0 100644 --- a/sphinx_runpython/blocdefs/sphinx_blocref_extension.py +++ b/sphinx_runpython/blocdefs/sphinx_blocref_extension.py @@ -143,7 +143,7 @@ def private_run(self, add_container=False): self.options["class"] = [f"admonition-{name_desc}"] # body - (blocref,) = super(BlocRef, self).run() + (blocref,) = super(BlocRef, self).run() # noqa: UP008 if isinstance(blocref, nodes.system_message): return [blocref] @@ -160,7 +160,7 @@ def private_run(self, add_container=False): # mid breftag = self.options.get("tag", "").strip() if len(breftag) == 0: - raise ValueError("tag is empty") # pragma: no cover + raise ValueError("tag is empty") if env is not None: mid = int(env.new_serialno(f"index{name_desc}-{breftag}")) + 1 else: @@ -169,7 +169,7 @@ def private_run(self, add_container=False): # title titleo = self.options.get("title", "").strip() if len(titleo) == 0: - raise ValueError("title is empty") # pragma: no cover + raise ValueError("title is empty") title = self._update_title(titleo, breftag, mid) # main node @@ -205,9 +205,9 @@ def private_run(self, add_container=False): set_source_info(self, targetnode) try: self.state.add_target(targetid, "", targetnode, lineno) - except Exception as e: # pragma: no cover + except Exception as e: raise RuntimeError( - "Issue in \n File '{0}', line " + "Issue in \n File '{0}', line " # noqa: UP030 "{1}\ntitle={2}\ntag={3}\ntargetid={4}".format( docname, lineno, title, breftag, targetid ) @@ -258,8 +258,8 @@ def process_blocrefs_generic(app, doctree, bloc_name, class_node): try: targetnode = node.parent[node.parent.index(node) - 1] if not isinstance(targetnode, nodes.target): - raise IndexError # pragma: no cover - except IndexError: # pragma: no cover + raise IndexError + except IndexError: targetnode = None newnode = node.deepcopy() breftag = newnode["breftag"] @@ -507,14 +507,14 @@ def process_blocref_nodes_generic( fromdocname, blocref_info["docname"] ) if blocref_info["target"] is None: - raise NoUri # pragma: no cover + raise NoUri try: newnode["refuri"] += "#" + blocref_info["target"]["refid"] - except Exception as e: # pragma: no cover + except Exception as e: raise KeyError( - "refid in not present in '{0}'".format(blocref_info["target"]) + f"refid in not present in {blocref_info['target']!r}" ) from e - except NoUri: # pragma: no cover + except NoUri: # ignore if no URI can be determined, e.g. for LaTeX output pass @@ -540,7 +540,7 @@ def process_blocref_nodes_generic( fromdocname, brefdocname ) newnode["refuri"] += "#" + idss[0] - except NoUri: # pragma: no cover + except NoUri: # ignore if no URI can be determined, e.g. for LaTeX output pass p += newnode diff --git a/sphinx_runpython/blocdefs/sphinx_mathdef_extension.py b/sphinx_runpython/blocdefs/sphinx_mathdef_extension.py index a92d8ed..7dfdc6f 100644 --- a/sphinx_runpython/blocdefs/sphinx_mathdef_extension.py +++ b/sphinx_runpython/blocdefs/sphinx_mathdef_extension.py @@ -8,7 +8,7 @@ try: from sphinx.errors import NoUri -except ImportError: # pragma: no cover +except ImportError: from sphinx.environment import NoUri from docutils.parsers.rst import Directive from docutils.parsers.rst.directives.admonitions import BaseAdmonition @@ -95,15 +95,13 @@ def run(self): elif hasattr(env, "config") and hasattr(env.config, "mathdef_link_number"): number_format = env.config.mathdef_link_number else: - raise ValueError( # pragma: no cover - "mathdef_link_number is not defined in the configuration" - ) + raise ValueError("mathdef_link_number is not defined in the configuration") if not self.options.get("class"): self.options["class"] = ["admonition-mathdef"] # body - (mathdef,) = super(MathDef, self).run() + (mathdef,) = super(MathDef, self).run() # noqa: UP008 if isinstance(mathdef, nodes.system_message): return [mathdef] @@ -120,7 +118,7 @@ def run(self): # mid mathtag = self.options.get("tag", "").strip() if len(mathtag) == 0: - raise ValueError("tag is empty") # pragma: no cover + raise ValueError("tag is empty") if env is not None: mid = int(env.new_serialno(f"indexmathe-u-{mathtag}")) + 1 else: @@ -133,7 +131,7 @@ def run(self): label_number = number_format.format( number=number, first_letter=first_letter ) - except ValueError as e: # pragma: no cover + except ValueError as e: raise RuntimeError(f"Unable to interpret format '{number_format}'.") from e # title @@ -141,7 +139,7 @@ def run(self): if len(title) > 0: title = f"{mathtag} {label_number} : {title}" else: - raise ValueError("title is empty") # pragma: no cover + raise ValueError("title is empty") # main node ttitle = title @@ -165,9 +163,9 @@ def run(self): set_source_info(self, targetnode) try: self.state.add_target(targetid, "", targetnode, lineno) - except Exception as e: # pragma: no cover + except Exception as e: raise RuntimeError( - "Issue in\n File '{0}', line {1}\ntid={2}\ntnode={3}".format( + "Issue in\n File '{0}', line {1}\ntid={2}\ntnode={3}".format( # noqa: UP030 None if env is None else env.docname, lineno, targetid, @@ -211,8 +209,8 @@ def process_mathdefs(app, doctree): try: targetnode = node.parent[node.parent.index(node) - 1] if not isinstance(targetnode, nodes.target): - raise IndexError # pragma: no cover - except IndexError: # pragma: no cover + raise IndexError + except IndexError: targetnode = None newnode = node.deepcopy() mathtag = newnode["mathtag"] @@ -365,11 +363,11 @@ def process_mathdef_nodes(app, doctree, fromdocname): ) try: newnode["refuri"] += "#" + mathdef_info["target"]["refid"] - except Exception as e: # pragma: no cover + except Exception as e: raise KeyError( - "refid in not present in '{0}'".format(mathdef_info["target"]) + f"refid in not present in {mathdef_info['target']!r}" ) from e - except NoUri: # pragma: no cover + except NoUri: # ignore if no URI can be determined, e.g. for LaTeX output pass newnode.append(innernode) @@ -392,7 +390,7 @@ def process_mathdef_nodes(app, doctree, fromdocname): fromdocname, mathdocname ) newnode["refuri"] += "#" + idss[0] - except NoUri: # pragma: no cover + except NoUri: # ignore if no URI can be determined, e.g. for LaTeX output pass newnode.append(innernode) diff --git a/sphinx_runpython/collapse/sphinx_collapse_extension.py b/sphinx_runpython/collapse/sphinx_collapse_extension.py index 3a7bada..d55eafb 100644 --- a/sphinx_runpython/collapse/sphinx_collapse_extension.py +++ b/sphinx_runpython/collapse/sphinx_collapse_extension.py @@ -122,7 +122,7 @@ def visit_collapse_node_html(self, node): script = """function myFunction__ID__() { var x = document.getElementById("collapse__ID__"); var b = document.getElementById("colidb__ID__"); - if (x.style.display === "none") { + if (x.style.display === "none") { x.style.display = "block"; b.innerText = '__HIDE__'; } else { x.style.display = "none"; b.innerText = '__UNHIDE__'; } diff --git a/sphinx_runpython/convert.py b/sphinx_runpython/convert.py index b09c29c..5d4921a 100644 --- a/sphinx_runpython/convert.py +++ b/sphinx_runpython/convert.py @@ -43,7 +43,7 @@ def convert_ipynb_to_gallery(nbfile: str, outfile: Optional[str] = None) -> str: python_file = "".join(python_file) python_file = python_file.replace("\n%", "\n# %") - python_file = python_file.replace("’", "'") + python_file = python_file.replace("’", "'") # noqa: RUF001 python_file = python_file.replace("# %matplotlib inline", "") python_file = python_file.replace("# \n", "\n") python_file = python_file.replace(">`__", ">`_") diff --git a/sphinx_runpython/docassert/sphinx_docassert_extension.py b/sphinx_runpython/docassert/sphinx_docassert_extension.py index 4156238..0481f25 100644 --- a/sphinx_runpython/docassert/sphinx_docassert_extension.py +++ b/sphinx_runpython/docassert/sphinx_docassert_extension.py @@ -137,7 +137,7 @@ def check_item(fieldarg, content, logger): else: obj = import_object(idocname, kind=kind) try: - tsig = getattr(obj[0], "__text_signature__") + tsig = getattr(obj[0], "__text_signature__") # noqa: B009 except AttributeError: tsig = "?" if tsig != "($self, /, *args, **kwargs)": diff --git a/sphinx_runpython/epkg/sphinx_epkg_extension.py b/sphinx_runpython/epkg/sphinx_epkg_extension.py index 3a8c031..b50bf93 100644 --- a/sphinx_runpython/epkg/sphinx_epkg_extension.py +++ b/sphinx_runpython/epkg/sphinx_epkg_extension.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ @file @brief Defines a way to reference a package or a page in this package. @@ -110,7 +109,7 @@ def my_custom_links(input): except AttributeError as e: ma = "\n".join(sorted(str(_) for _ in app.config)) raise AttributeError( - "unable to find 'epkg_dictionary' in configuration. Available:\n{0}" + "unable to find 'epkg_dictionary' in configuration. Available:\n{0}" # noqa: UP030 "".format(ma) ) from e @@ -162,7 +161,7 @@ def my_custom_links(input): if found is None: msg = inliner.reporter.error( - "Unable to find a tuple with '{0}' parameters in epkg_dictionary['{1}']" + "Unable to find a tuple with '{0}' parameters in epkg_dictionary['{1}']" # noqa: UP030 "".format(expected, modname) ) prb = inliner.problematic(rawtext, rawtext, msg) @@ -176,7 +175,7 @@ def my_custom_links(input): anchor, url = found()(text) except Exception as e: raise ValueError( - "epkg accepts function or classes with __call__ overloaded. " + "epkg accepts function or classes with __call__ overloaded. " # noqa: UP030 "Found '{0}'".format(found) ) from e else: @@ -196,7 +195,7 @@ def my_custom_links(input): processed, messages = inliner.parse(extref, lineno, memo, node) if len(messages) > 0: msg = inliner.reporter.error( - "unable to interpret '{0}', messages={1}".format( + "unable to interpret '{0}', messages={1}".format( # noqa: UP030 text, ", ".join(str(_) for _ in messages) ), line=lineno, diff --git a/sphinx_runpython/ext_helper.py b/sphinx_runpython/ext_helper.py index 24ac824..750666d 100644 --- a/sphinx_runpython/ext_helper.py +++ b/sphinx_runpython/ext_helper.py @@ -70,12 +70,12 @@ def sphinx_lang(env, default_value="en"): if hasattr(env, "settings"): settings = env.settings if hasattr(settings, "language_code"): - lang = env.settings.language_code # pragma: no cover + lang = env.settings.language_code else: lang = "en" else: - settings = None # pragma: no cover - lang = "en" # pragma: no cover + settings = None + lang = "en" return lang @@ -134,7 +134,7 @@ def traverse(node, depth=0): yield (depth, ne) yield (depth, node) for n in node.children: - for r in traverse(n, depth + 1): + for r in traverse(n, depth + 1): # noqa: UP028 yield r yield (depth, nl) @@ -197,12 +197,12 @@ def get_env_state_info(self): elif hasattr(self.state.document.settings, "env"): env = self.state.document.settings.env else: - env = None # pragma: no cover + env = None reporter = self.state.document.reporter try: docname, lineno = reporter.get_source_and_line(self.lineno) - except AttributeError: # pragma: no cover + except AttributeError: docname = lineno = None if docname is not None: diff --git a/sphinx_runpython/ext_io_helper.py b/sphinx_runpython/ext_io_helper.py index 8f0c4a5..7a19aca 100644 --- a/sphinx_runpython/ext_io_helper.py +++ b/sphinx_runpython/ext_io_helper.py @@ -57,7 +57,7 @@ def _first_more_recent(f1: str, path: str) -> bool: da = re.compile("Last[-]Modified: (.+) GMT").search(s) if da is None: return True - else: # pragma: no cover + else: da = da.groups()[0] gr = re.compile( "[\\w, ]* ([ \\d]{2}) ([\\w]{3}) ([\\d]{4}) " @@ -157,7 +157,9 @@ def read_url(url: str, encoding: Optional[str] = None) -> Union[bytes, str]: import urllib.parse as urlparse res = urlparse.urlparse(url) - raise ReadUrlException(f"unable to open url '{url}' scheme: {res}\nexc: {e}") + raise ReadUrlException( # noqa: B904 + f"unable to open url '{url}' scheme: {res}\nexc: {e}" + ) if encoding is None: return content @@ -218,7 +220,7 @@ def download(url: str, path_download: str = ".", outfile: Optional[str] = None) f1.close() except urllib_error.HTTPError as e: raise ReadUrlException(f"Unable to fetch '{url}'") from e - except IOError as e: + except OSError as e: raise ReadUrlException(f"Unable to download '{url}'") from e else: down = True @@ -254,7 +256,7 @@ def download(url: str, path_download: str = ".", outfile: Optional[str] = None) fu = urllib_request.urlopen(request) except urllib_error.HTTPError as e: raise ReadUrlException(f"Unable to fetch '{url}'") from e - f = open( + f = open( # noqa: SIM115 dest, format.replace("w", "a") # pylint: disable=W1501 ) # pylint: disable=W1501 else: @@ -264,7 +266,7 @@ def download(url: str, path_download: str = ".", outfile: Optional[str] = None) fu = urllib_request.urlopen(url) except urllib_error.HTTPError as e: raise ReadUrlException(f"Unable to fetch '{url}'") from e - f = open(dest, format) + f = open(dest, format) # noqa: SIM115 open(nyet, "w").close() c = fu.read(2**21) @@ -376,11 +378,13 @@ def _local_loop(ur): if raise_exception: raise InternetException(f"Unable to retrieve content url='{url}'") from e warnings.warn( - f"Unable to retrieve content from '{url}' because of {e}", ResourceWarning + f"Unable to retrieve content from '{url}' because of {e}", + ResourceWarning, + stacklevel=0, ) return None except Exception as e: - if raise_exception: # pragma: no cover + if raise_exception: raise InternetException( f"Unable to retrieve content, url='{url}', exc={e}" ) from e @@ -388,6 +392,7 @@ def _local_loop(ur): f"Unable to retrieve content from '{url}' " f"because of unknown exception: {e}", ResourceWarning, + stacklevel=0, ) raise e @@ -399,7 +404,7 @@ def _local_loop(ur): if encoding is not None: try: content = res.decode(encoding) - except UnicodeDecodeError as e: # pragma: no cover + except UnicodeDecodeError as e: # it tries different encoding laste = [e] @@ -415,11 +420,11 @@ def _local_loop(ur): if content is None: mes = [f"Unable to parse text from '{url}'."] - mes.append("tried:" + str([encoding] + othenc)) + mes.append("tried:" + str([encoding, *othenc])) mes.append("beginning:\n" + str([res])[:50]) for e in laste: mes.append("Exception: " + str(e)) - raise ValueError("\n".join(mes)) + raise ValueError("\n".join(mes)) # noqa: B904 else: content = res else: @@ -468,9 +473,7 @@ def download_requirejs( ] elocations = [loc for loc in locations if os.path.exists(loc)] if len(elocations) == 0: - raise FileNotFoundError( # pragma: no cover - f"Unable to find requirejs in '{locations}'" - ) + raise FileNotFoundError(f"Unable to find requirejs in '{locations}'") location = elocations[0] shutil.copy(location, to) return [os.path.join(to, "require.js")] @@ -478,7 +481,7 @@ def download_requirejs( link = location try: page = read_url(link, encoding="utf8") - except ReadUrlException: # pragma: no cover + except ReadUrlException: if logger.info: logger.info("[download_requirejs] unable to read %r", location) return download_requirejs(to=to, location=None, clean=clean) @@ -486,7 +489,7 @@ def download_requirejs( reg = re.compile('href=\\"(.*?minified/require[.]js)\\"') alls = reg.findall(page) if len(alls) == 0: - raise RuntimeError( # pragma: no cover + raise RuntimeError( f"Unable to find a link on require.js file on page {page!r}." ) @@ -494,7 +497,7 @@ def download_requirejs( try: local = download(filename, to) - except ReadUrlException as e: # pragma: no cover + except ReadUrlException as e: # We implement a backup plan. new_filename = ( "https://requirejs.org/docs/release/2.3.6/minified/require.js" @@ -503,7 +506,7 @@ def download_requirejs( local = download(new_filename, to) except ReadUrlException: raise ReadUrlException( - "Unable to download '{0}' or '{1}'".format(filename, new_filename) + "Unable to download {filename!r} or {new_filename!r}" ) from e logger.info("[download_requirejs] local file %r", local) diff --git a/sphinx_runpython/ext_test_case.py b/sphinx_runpython/ext_test_case.py index 3217719..19adb0b 100644 --- a/sphinx_runpython/ext_test_case.py +++ b/sphinx_runpython/ext_test_case.py @@ -108,7 +108,7 @@ def assertRaise(self, fct: Callable, exc_type: Exception): fct() except exc_type as e: if not isinstance(e, exc_type): - raise AssertionError(f"Unexpected exception {type(e)!r}.") + raise AssertionError(f"Unexpected exception {type(e)!r}.") # noqa: B904 return raise AssertionError("No exception was raised.") @@ -133,7 +133,7 @@ def assertStartsWith(self, prefix: str, full: str): @classmethod def tearDownClass(cls): for name, line, w in cls._warns: - warnings.warn(f"\n{name}:{line}: {type(w)}\n {str(w)}") + warnings.warn(f"\n{name}:{line}: {type(w)}\n {str(w)}", stacklevel=0) def capture(self, fct: Callable): """ @@ -144,7 +144,6 @@ def capture(self, fct: Callable): """ sout = StringIO() serr = StringIO() - with redirect_stdout(sout): - with redirect_stderr(serr): - res = fct() + with redirect_stdout(sout), redirect_stderr(serr): + res = fct() return res, sout.getvalue(), serr.getvalue() diff --git a/sphinx_runpython/gdot/sphinx_gdot_extension.py b/sphinx_runpython/gdot/sphinx_gdot_extension.py index b7ccce4..2692745 100644 --- a/sphinx_runpython/gdot/sphinx_gdot_extension.py +++ b/sphinx_runpython/gdot/sphinx_gdot_extension.py @@ -112,7 +112,7 @@ def run(self): Builds the collapse text. """ # retrieves the parameters - if "format" in self.options: + if "format" in self.options: # noqa: SIM401 format = self.options["format"] else: format = "png" @@ -349,7 +349,7 @@ def copy_js_files(app): try: shutil.copy(path, file_dest) logger.info("[gdot] copy %r to %r.", path, file_dest) - except PermissionError as e: # pragma: no cover + except PermissionError as e: logger.warning( "[gdot] permission error (%r), unable to use local viz.js", e ) diff --git a/sphinx_runpython/import_object_helper.py b/sphinx_runpython/import_object_helper.py index 6ee1a3f..7d0403f 100644 --- a/sphinx_runpython/import_object_helper.py +++ b/sphinx_runpython/import_object_helper.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- """ -@file -@brief Defines a :epkg:`sphinx` extension which if all parameters are documented. +Defines a :epkg:`sphinx` extension which if all parameters are documented. """ + import inspect import warnings import sys @@ -49,10 +48,8 @@ def import_object(docname, kind, use_init=True) -> Tuple[object, str]: try: exec(codeobj, context, context) except Exception as e: - mes = ( - "Unable to compile and execute '{0}' due to \n{1}\ngiven:\n{2}".format( - code.replace("\n", "\\n"), e, docname - ) + mes = "Unable to compile and execute '{0}' due to \n{1}\ngiven:\n{2}".format( # noqa: UP030 + code.replace("\n", "\\n"), e, docname ) raise RuntimeError(mes) from e @@ -169,9 +166,9 @@ def import_path(obj, class_name=None, err_msg=None): """ try: _ = obj.__module__ - except AttributeError: + except AttributeError as e: # This is a method. - raise TypeError(f"obj is a method or a property ({obj})") + raise TypeError(f"obj is a method or a property ({obj})") from e if class_name is None: name = obj.__name__ @@ -195,7 +192,7 @@ def import_path(obj, class_name=None, err_msg=None): if found is None: raise RuntimeError( - "Unable to import object '{0}' ({1}). Full path: '{2}'{3}".format( + "Unable to import object '{0}' ({1}). Full path: '{2}'{3}".format( # noqa: UP030 name, obj, ".".join(elements), diff --git a/sphinx_runpython/language.py b/sphinx_runpython/language.py index b6850e5..02c750b 100644 --- a/sphinx_runpython/language.py +++ b/sphinx_runpython/language.py @@ -5,7 +5,7 @@ "author": "author", "blocref_node": "", "blog_entry": ( - "The original entry is located in " "<<%s>>, line %d and can be found " + "The original entry is located in <<%s>>, line %d and can be found " ), "blogpost": "blogpost", "book": "book", diff --git a/sphinx_runpython/quote/sphinx_quote_extension.py b/sphinx_runpython/quote/sphinx_quote_extension.py index 0106cca..e91fd47 100644 --- a/sphinx_runpython/quote/sphinx_quote_extension.py +++ b/sphinx_runpython/quote/sphinx_quote_extension.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from docutils import nodes from docutils.parsers.rst import directives @@ -99,14 +98,14 @@ def run(self): self.options["class"] = ["admonition-quote"] # body - (quote,) = super(QuoteNode, self).run() + (quote,) = super(QuoteNode, self).run() # noqa: UP008 if isinstance(quote, nodes.system_message): - return [quote] # pragma: no cover + return [quote] # mid tag = self.options.get("tag", "quotetag").strip() if len(tag) == 0: - raise ValueError("tag is empty") # pragma: no cover + raise ValueError("tag is empty") def __(text): if text: @@ -138,14 +137,14 @@ def __(text): indexes = [] if index: - indexes.append(index) # pragma: no cover + indexes.append(index) # add a label lid = self.options.get("lid", self.options.get("label", None)) if lid: tnl = ["", f".. _{lid}:", ""] else: - tnl = [] # pragma: no cover + tnl = [] if title1: if ado: @@ -235,7 +234,7 @@ def __(text): try: nested_parse_with_titles(self.state, content, node) - except Exception as e: # pragma: no cover + except Exception as e: from sphinx.util import logging logger = logging.getLogger("blogpost") diff --git a/sphinx_runpython/readme.py b/sphinx_runpython/readme.py index ad7aea7..37b028e 100644 --- a/sphinx_runpython/readme.py +++ b/sphinx_runpython/readme.py @@ -276,12 +276,12 @@ def filter_err(err): else: exe = os.path.join(venv, "bin", "python") if is_cmd: - cmd = " ".join([exe] + script) + cmd = " ".join([exe, *script]) out, err = run_cmd(cmd, wait=True, logf=print if verbose else None, **kwargs) err = filter_err(err) if len(err) > 0 and (skip_err_if is None or skip_err_if not in out): raise VirtualEnvError( - "unable to run cmd at {2}\n--CMD--\n{3}\n--OUT--\n{0}\n[pyqerror]" + "unable to run cmd at {2}\n--CMD--\n{3}\n--OUT--\n{0}\n[pyqerror]" # noqa: UP030 "\n{1}".format(out, err, venv, cmd) ) return out @@ -290,9 +290,9 @@ def filter_err(err): if is_file: if not os.path.exists(script): raise FileNotFoundError(script) - cmd = " ".join([exe, "-u", '"{0}"'.format(script)]) + cmd = " ".join([exe, "-u", f'"{script}"']) else: - cmd = " ".join([exe, "-u", "-c", '"{0}"'.format(script)]) + cmd = " ".join([exe, "-u", "-c", f'"{script}"']) out, err = run_cmd(cmd, wait=True, logf=print if verbose else None, **kwargs) err = filter_err(err) if len(err) > 0: @@ -363,7 +363,7 @@ def true_err(err): exe = os.path.join(exe, "bin", "python") if is_cmd: - cmd = " ".join([exe] + script) + cmd = " ".join([exe, *script]) if argv is not None: cmd += " " + " ".join(argv) out, err = run_cmd(cmd, wait=True, verbose=verbose, **kwargs) @@ -383,9 +383,9 @@ def true_err(err): if is_file: if not os.path.exists(script): raise FileNotFoundError(script) - cmd = " ".join([exe, "-u", '"{0}"'.format(script)]) + cmd = " ".join([exe, "-u", f'"{script}"']) else: - cmd = " ".join([exe, "-u", "-c", '"{0}"'.format(script)]) + cmd = " ".join([exe, "-u", "-c", f'"{script}"']) if argv is not None: cmd += " " + " ".join(argv) out, err = run_cmd(cmd, wait=True, verbose=verbose, **kwargs) @@ -432,18 +432,16 @@ def check_readme_syntax( "from docutils.parsers.rst.directives import _directives", "from docutils.writers.html4css1 import Writer", "_directives['image'] = Image", - "with open('{0}', 'r', encoding='utf8') as g: s = g.read()".format( - readme.replace("\\", "\\\\") - ), + "with open('{0}', 'r', encoding='utf8') as g: " # noqa: UP030 + "s = g.read()".format(readme.replace("\\", "\\\\")), "settings_overrides = {'output_encoding': 'unicode', 'doctitle_xform': True,", " 'initial_header_level': 2, 'warning_stream': io.StringIO()}", "parts = core.publish_parts(source=s, parser=Parser(), " " reader=Reader(), source_path=None,", " destination_path=None, writer=Writer(),", " settings_overrides=settings_overrides)", - "with open('{0}', 'w', encoding='utf8') as f: f.write(parts['whole'])".format( - outfile.replace("\\", "\\\\") - ), + "with open('{0}', 'w', encoding='utf8') as f: " # noqa: UP030 + "f.write(parts['whole'])".format(outfile.replace("\\", "\\\\")), ] file_script = os.path.join(folder, "test_" + os.path.split(readme)[-1]) diff --git a/sphinx_runpython/runpython/run_cmd.py b/sphinx_runpython/runpython/run_cmd.py index 5176b0e..5965b15 100644 --- a/sphinx_runpython/runpython/run_cmd.py +++ b/sphinx_runpython/runpython/run_cmd.py @@ -318,10 +318,9 @@ def run_cmd( delta = time.perf_counter() - last_update if tell_if_no_output is not None and delta >= tell_if_no_output: logf( - prefix_log - + "[run_cmd] No update in {0} seconds for cmd: {1}".format( - "%5.1f" % (last_update - begin), cmd - ) + prefix_log + "[run_cmd] No update in %5.1f seconds for cmd: %s", + last_update - begin, + cmd, ) last_update = time.perf_counter() full_delta = time.perf_counter() - begin @@ -329,9 +328,9 @@ def run_cmd( runloop = False logf( prefix_log - + "[run_cmd] Timeout after {0} seconds for cmd: {1}".format( - "%5.1f" % full_delta, cmd - ) + + "[run_cmd] Timeout after %5.1f seconds for cmd: %s", + full_delta, + cmd, ) break @@ -353,7 +352,9 @@ def run_cmd( stderr.close() except Exception: warnings.warn( - "Unable to close stdout and sterr.", RuntimeWarning + "Unable to close stdout and sterr.", + RuntimeWarning, + stacklevel=0, ) if catch_exit: mes = ( diff --git a/sphinx_runpython/runpython/sphinx_runpython_extension.py b/sphinx_runpython/runpython/sphinx_runpython_extension.py index ae7e2cd..6c7d162 100644 --- a/sphinx_runpython/runpython/sphinx_runpython_extension.py +++ b/sphinx_runpython/runpython/sphinx_runpython_extension.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import sys import os from contextlib import redirect_stdout, redirect_stderr @@ -40,9 +39,9 @@ def remove_extra_spaces_and_black( with open(filename, "r") as f: lines = f.readlines() encoding = None - except PermissionError as e: # pragma: no cover + except PermissionError as e: raise PermissionError(filename) from e - except UnicodeDecodeError as e: # pragma: no cover + except UnicodeDecodeError as e: try: with open(filename, "r", encoding="utf-8") as f: lines = f.readlines() @@ -57,9 +56,9 @@ def remove_extra_spaces_and_black( with open(filename, "r", encoding="utf-8-sig") as f: lines = f.readlines() encoding = "utf-8" - except PermissionError as e: # pragma: no cover + except PermissionError as e: raise PermissionError(filename) from e - except UnicodeDecodeError as e: # pragma: no cover + except UnicodeDecodeError as e: try: with open(filename, "r") as f: lines = f.readlines() @@ -75,9 +74,7 @@ def remove_extra_spaces_and_black( and len(lines) == 0 and not filename.endswith("__init__.py") ): - raise ValueError( # pragma: no cover - f"File '{filename}' is empty, encoding='{encoding}'." - ) + raise ValueError(f"File '{filename}' is empty, encoding='{encoding}'.") if filename is not None and ext in (".py", ".pyx", ".pxd"): if ( @@ -88,7 +85,7 @@ def remove_extra_spaces_and_black( with open(filename, "r", encoding="utf8") as f: try: lines = f.readlines() - except UnicodeDecodeError as e: # pragma: no cover + except UnicodeDecodeError as e: raise RuntimeError("unable to read: " + filename) from e encoding = "utf8" else: @@ -116,8 +113,9 @@ def cdiff(lines): r = format_str("\n".join(lines2), mode=FileMode()) if len(lines) > 0 and (len(lines2) == 0 or len(lines2) < len(lines) // 2): - raise ValueError( # pragma: no cover - "Resulting file is empty for '{3}',\ninitial number of lines " + raise ValueError( + "Resulting file is empty for '{3}'," # noqa: UP030 + "\ninitial number of lines " "{0} encoding='{1}' diff={2}".format( len(lines), encoding, diff, filename ) @@ -144,14 +142,14 @@ def cdiff(lines): lines2 = [_ for i, _ in enumerate(lines2) if i not in rem] if len(lines) > 0 and len(lines2[-1]) > 0: lines2.append("") - if len(lines) > 0 and len(lines2) == 0: # pragma: no cover + if len(lines) > 0 and len(lines2) == 0: raise ValueError( f"Resulting file is empty for {filename!r}," f"\ninitial number of lines {len(lines)} encoding={encoding!r} " f"len(rem)={len(rem)} diff={diff}\nBeginning:" f"\n{''.join(lines[:5 if len(lines) > 5 else len(lines)])}" ) - if len(lines2) < len(lines) // 2: # pragma: no cover + if len(lines2) < len(lines) // 2: lines2_ = [_ for _ in lines2 if _ and _ != "\n"] lines_ = [_ for _ in lines if _ and _ != "\n"] if len(lines2_) < len(lines_) // 2: @@ -191,7 +189,7 @@ def cdiff(lines): f.write("\n".join(lines2)) if not os.path.exists(filename): - raise FileNotFoundError( # pragma: no cover + raise FileNotFoundError( f"Issue when applying black with filename: '{filename}'." ) return diff @@ -315,24 +313,16 @@ def interpret(s): header.append(f"sys.{setsysvar} = True") add = 0 for path in sys.path: - if ( - path.endswith("source") - or path.endswith("source/") - or path.endswith("source\\") - ): + if path.endswith(("source", "source/", "source\\")): header.append( - "sys.path.append('{0}')".format(path.replace("\\", "\\\\")) + "sys.path.append('{}')".format(path.replace("\\", "\\\\")) ) add += 1 if add == 0: for path in sys.path: - if ( - path.endswith("src") - or path.endswith("src/") - or path.endswith("src\\") - ): + if path.endswith(("src", "src/", "src\\")): header.append( - "sys.path.append('{0}')".format(path.replace("\\", "\\\\")) + "sys.path.append('{}')".format(path.replace("\\", "\\\\")) ) add += 1 if add == 0: @@ -344,7 +334,9 @@ def interpret(s): path = os.path.join(path, "..", "..", "src") if os.path.exists(path): header.append( - "sys.path.append('{0}')".format(path.replace("\\", "\\\\")) + "sys.path.append('{}')".format( + path.replace("\\", "\\\\") + ) # noqa: UP030 ) add += 1 else: @@ -352,14 +344,18 @@ def interpret(s): path = os.path.join(path, "src") if os.path.exists(path): header.append( - "sys.path.append('{0}')".format(path.replace("\\", "\\\\")) + "sys.path.append('{}')".format( + path.replace("\\", "\\\\") + ) # noqa: UP030 ) add += 1 if add == 0: # We do nothing unless the execution failed. exc_path = RunPythonExecutionError( - "Unable to find a path to add:\n{0}".format("\n".join(sys.path)) + "Unable to find a path to add:\n{}".format( + "\n".join(sys.path) + ) # noqa: UP030 ) else: exc_path = None @@ -379,7 +375,7 @@ def interpret(s): return out, err, None except Exception as ee: if not exception: - message = ( + message = ( # noqa: UP030 "--SCRIPT--\n{0}\n--PARAMS--\n{1}\n--COMMENT--\n" "{2}\n--ERR--\n{3}\n--OUT--\n{4}\n--EXC--\n{5}" "" @@ -418,44 +414,42 @@ def interpret(s): sout = StringIO() serr = StringIO() - with redirect_stdout(sout): - with redirect_stderr(sout): - with warnings.catch_warnings(): - warning_filter(warningout) - - if chdir is not None: - current = os.getcwd() - os.chdir(chdir) - - try: - exec(obj, globs, loc) - except Exception as ee: - if chdir is not None: - os.chdir(current) - if setsysvar is not None: - del sys.__dict__[setsysvar] - if comment is None: - comment = "" - gout = sout.getvalue() - gerr = serr.getvalue() - - excs = traceback.format_exc() - lines = excs.split("\n") - excs = "\n".join( - _ for _ in lines if "sphinx_runpython_extension.py" not in _ - ) - - if not exception: - message = ( - "--SCRIPT--\n{0}\n--PARAMS--\n{1}\n--COMMENT--" - "\n{2}\n--ERR--\n{3}\n--OUT--\n{4}\n--EXC--" - "\n{5}\n--TRACEBACK--\n{6}" - ).format(script, params, comment, gout, gerr, ee, excs) - raise RunPythonExecutionError(message) from ee - return (gout + "\n" + gerr), (gerr + "\n" + excs), None - - if chdir is not None: - os.chdir(current) + with redirect_stdout(sout), redirect_stderr(sout), warnings.catch_warnings(): + warning_filter(warningout) + + if chdir is not None: + current = os.getcwd() + os.chdir(chdir) + + try: + exec(obj, globs, loc) + except Exception as ee: + if chdir is not None: + os.chdir(current) + if setsysvar is not None: + del sys.__dict__[setsysvar] + if comment is None: + comment = "" + gout = sout.getvalue() + gerr = serr.getvalue() + + excs = traceback.format_exc() + lines = excs.split("\n") + excs = "\n".join( + _ for _ in lines if "sphinx_runpython_extension.py" not in _ + ) + + if not exception: + message = ( # noqa: UP030 + "--SCRIPT--\n{0}\n--PARAMS--\n{1}\n--COMMENT--" + "\n{2}\n--ERR--\n{3}\n--OUT--\n{4}\n--EXC--" + "\n{5}\n--TRACEBACK--\n{6}" + ).format(script, params, comment, gout, gerr, ee, excs) + raise RunPythonExecutionError(message) from ee + return (gout + "\n" + gerr), (gerr + "\n" + excs), None + + if chdir is not None: + os.chdir(current) if setsysvar is not None: del sys.__dict__[setsysvar] @@ -754,7 +748,7 @@ def run(self): f'\n File "{docname}.py", line {1}\n' ) logger.warning( - f"Black ({e}) issue with {docname!r}\n---SCRIPT---\n{script}" + "Black (%r) issue with %r\n---SCRIPT---\n%s", e, docname, script ) # if an exception is raised, the documentation should report a warning @@ -798,10 +792,10 @@ def run(self): if p["store"]: # Stores modified local context. - setattr(env, "runpython_context", context) + setattr(env, "runpython_context", context) # noqa: B010 else: context = {} - setattr(env, "runpython_context", context) + setattr(env, "runpython_context", context) # noqa: B010 if out is not None: out = out.rstrip(" \n\r\t") @@ -875,7 +869,7 @@ def add_indent(content, nbind): if p["rst"]: settings_overrides = {} try: - sett.output_encoding + sett.output_encoding # noqa: B018 except KeyError: settings_overrides["output_encoding"] = "unicode" # try: @@ -883,7 +877,7 @@ def add_indent(content, nbind): # except KeyError: # settings_overrides["doctitle_xform"] = True try: - sett.warning_stream + sett.warning_stream # noqa: B018 except KeyError: settings_overrides["warning_stream"] = StringIO() # 'initial_header_level': 2, diff --git a/sphinx_runpython/sphinx_rst_builder.py b/sphinx_runpython/sphinx_rst_builder.py index 0e2bb3e..2705768 100644 --- a/sphinx_runpython/sphinx_rst_builder.py +++ b/sphinx_runpython/sphinx_rst_builder.py @@ -50,7 +50,7 @@ # from sphinx.locale import admonitionlabels, _ try: from sphinx.domains.changeset import versionlabels -except ImportError: # pragma: no cover +except ImportError: from sphinx.locale import versionlabels from sphinx.writers.text import TextTranslator, MAXWIDTH, STDINDENT @@ -128,9 +128,9 @@ def base_visit_image(self, node, image_dest=None): os.path.join(srcdir, builder.current_docname) ) if current is None or not os.path.exists(current): - raise FileNotFoundError( # pragma: no cover - "Unable to find document '{0}' current_docname='{1}'" - "".format(current, builder.current_docname) + raise FileNotFoundError( + f"Unable to find document {current!r} " + f"current_docname={builder.current_docname!r}" ) dest = os.path.dirname( os.path.join(outdir, builder.current_docname) @@ -153,8 +153,8 @@ def base_visit_image(self, node, image_dest=None): if "*" in full: files = glob.glob(full) if len(files) == 0: - raise FileNotFoundError( # pragma: no cover - f"Unable to find any file matching pattern '{full}'." + raise FileNotFoundError( + f"Unable to find any file matching pattern {full!r}." ) full = files[0] @@ -178,7 +178,7 @@ def base_visit_image(self, node, image_dest=None): dest = os.path.join(fold, name) if fold else None if dest is not None and "*" in dest: - raise RuntimeError( # pragma: no cover + raise RuntimeError( "Wrong destination '{} // {}' image_dest='{}' atts['src']='{}' " "srcdir='{}' full='{}'.".format( fold, name, image_dest, atts["src"], srcdir, full @@ -221,7 +221,7 @@ def base_visit_image(self, node, image_dest=None): try: shutil.copy(full, dest) except (FileNotFoundError, OSError) as e: - raise FileNotFoundError( # pragma: no cover + raise FileNotFoundError( f"Unable to copy from '{full}' to '{dest}'." ) from e full = dest @@ -236,10 +236,8 @@ def base_visit_image(self, node, image_dest=None): atts["full"] = full atts["dest"] = dest else: - raise ValueError( # pragma: no cover - "No image was found in node (class='{1}')\n{0}".format( - node, self.__class__.__name__ - ) + raise ValueError( + f"No image was found in node (class={self.__class__.__name__!r})\n{node}" ) # image size @@ -256,7 +254,7 @@ def base_visit_image(self, node, image_dest=None): imagepath = urllib.request.url2pathname(uri) try: img = PIL.Image.open(imagepath.encode(sys.getfilesystemencoding())) - except (IOError, UnicodeEncodeError): # pragma: no cover + except (OSError, UnicodeEncodeError): pass # TODO: warn? else: self.settings.record_dependencies.add( # pylint: disable=E1101 @@ -339,7 +337,7 @@ def new_state(self, indent=STDINDENT): self.states.append([]) self.stateindent.append(indent) - def end_state(self, wrap=True, end=[""], first=None): + def end_state(self, wrap=True, end=[""], first=None): # noqa: B006 content = self.states.pop() maxindent = sum(self.stateindent) indent = self.stateindent.pop() @@ -523,7 +521,7 @@ def depart_desc_optional(self, node): def visit_desc_annotation(self, node): content = node.astext() - if len(content) > MAXWIDTH: # pragma: no cover + if len(content) > MAXWIDTH: h = int(MAXWIDTH / 3) content = content[:h] + " ... " + content[-h:] self.add_text(content) @@ -683,7 +681,7 @@ def depart_row(self, node): def visit_entry(self, node): if hasattr(node, "morerows") or hasattr(node, "morecols"): raise NotImplementedError( - "Column or row spanning cells are " "not implemented." + "Column or row spanning cells are not implemented." ) self.new_state(0) @@ -702,7 +700,7 @@ def depart_table(self, node): lines = self._table[1:] fmted_rows = [] colwidths = self._table[0] - realwidths = list(map(lambda x: x if isinstance(x, int) else 1, colwidths[:])) + realwidths = [(x if isinstance(x, int) else 1) for x in colwidths[:]] separator = 0 # don't allow paragraphs in table cells for now for line in lines: @@ -1079,7 +1077,7 @@ def clean_refuri(uri): if "refuri" not in node: if "name" in node.attributes: self.add_text(f"`{node['name']}`_") - elif "refid" in node and node["refid"]: + elif "refid" in node and node["refid"]: # noqa: RUF019 self.add_text(f":ref:`{node['refid']}`") else: self.log_unknown(type(node), node) @@ -1231,11 +1229,13 @@ def eval_expr(self, expr): html = False latex = False if not (rst or html or latex or md): - raise ValueError("One of them should be True") # pragma: no cover + raise ValueError("One of them should be True") try: ev = eval(expr) - except Exception as e: # pragma: no cover - raise ValueError(f"Unable to interpret expression '{expr}' due to {e}.") + except Exception as e: + raise ValueError( + f"Unable to interpret expression '{expr}' due to {e}." + ) from e return ev def visit_only(self, node): @@ -1404,7 +1404,7 @@ def get_outdated_docs(self): srcmtime = os.path.getmtime(sourcename) if srcmtime > targetmtime: yield docname - except EnvironmentError: + except OSError: # source doesn't exist anymore pass diff --git a/sphinx_runpython/tools/img_export.py b/sphinx_runpython/tools/img_export.py index 84051f1..5aba6d1 100644 --- a/sphinx_runpython/tools/img_export.py +++ b/sphinx_runpython/tools/img_export.py @@ -43,7 +43,7 @@ def images2pdf( else: raise RuntimeError(f"Unable to deal with images={images!r}") elif not isinstance(images, (list, tuple)): - raise TypeError("Images must be a list.") # pragma: no cover + raise TypeError("Images must be a list.") all_images = [] for img in images: @@ -64,7 +64,9 @@ def images2pdf( print(f"[images2pdf] {i + 1}/{len(all_images)} {img!r}") st, close = ( - (open(output, "wb"), True) if isinstance(output, str) else (output, False) + (open(output, "wb"), True) # noqa: SIM115 + if isinstance(output, str) + else (output, False) ) all_images.sort() diff --git a/sphinx_runpython/tools/latex_functions.py b/sphinx_runpython/tools/latex_functions.py index 8ba9cd0..c75317c 100644 --- a/sphinx_runpython/tools/latex_functions.py +++ b/sphinx_runpython/tools/latex_functions.py @@ -59,7 +59,7 @@ def build_regex(text: Optional[str] = None) -> Dict[str, Union[str, Tuple[str, s look = f"\\\\{name} *" + "\\{(.+)\\}" * int(n) for c in "\\": pat = pat.replace(c, f"\\{c}") - for k in range(0, int(n)): + for k in range(int(n)): pat = pat.replace(f"#{k+1}", f"\\{k+1}") res[name] = (look, pat) return res From 533a74ece25d19794800b9f52893f38424e576b0 Mon Sep 17 00:00:00 2001 From: xadupre Date: Wed, 9 Oct 2024 16:07:40 +0200 Subject: [PATCH 03/13] improve --- .gitignore | 1 + CHANGELOGS.rst | 1 + _unittests/ut__main/test_cmd.py | 16 ++++++-- _unittests/ut_tools/test_latex_functions.py | 15 +++++++ sphinx_runpython/_cmd_helper.py | 45 ++++++++++++++++++++- sphinx_runpython/tools/latex_functions.py | 2 +- 6 files changed, 73 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index df9ed38..20a9325 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ _unittests/ut__main/_cache/* _unittests/ut__main/*.html _unittests/ut_runpython/*.png _unittests/ut_runpython/*.html +test_latex/* diff --git a/CHANGELOGS.rst b/CHANGELOGS.rst index 3dcff97..16c6741 100644 --- a/CHANGELOGS.rst +++ b/CHANGELOGS.rst @@ -4,6 +4,7 @@ Change Logs 0.3.0 +++++ +* :pr:`36`: add tools to remove the use of new commands in latex formula * :pr:`33`: add simple command line to convert images to pdf * :pr:`28`: add syntax to check the readme syntax * :pr:`27`: fix missing __text_signature__ in docassert diff --git a/_unittests/ut__main/test_cmd.py b/_unittests/ut__main/test_cmd.py index 483f632..9c76a6e 100644 --- a/_unittests/ut__main/test_cmd.py +++ b/_unittests/ut__main/test_cmd.py @@ -2,7 +2,7 @@ import unittest import os from sphinx_runpython.ext_test_case import ExtTestCase -from sphinx_runpython._cmd_helper import get_parser, nb2py +from sphinx_runpython._cmd_helper import get_parser, nb2py, latex_process class TestCmd(ExtTestCase): @@ -13,13 +13,21 @@ def test_cmd(self): @unittest.skipIf(platform.system() != "Linux", reason="pandoc not installed") def test_convert(self): data = os.path.join(os.path.dirname(__file__), "data") - parser = get_parser() - parser.command = "nb2py" - parser.path = data nb2py(data, verbose=1) expected = os.path.join(data, "float_and_double_rouding.py") self.assertExists(expected) + def test_latex(self): + data = os.path.join(os.path.dirname(__file__), "data") + folder = "test_latex" + if not os.path.exists(folder): + os.mkdir(folder) + latex_process(data, verbose=1, output=folder) + expected = os.path.join(folder, "strategie_avec_alea.rst") + self.assertExists(expected) + expected = os.path.join(folder, "poulet.py") + self.assertExists(expected) + if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/_unittests/ut_tools/test_latex_functions.py b/_unittests/ut_tools/test_latex_functions.py index 3ecbb5d..3fbac7c 100644 --- a/_unittests/ut_tools/test_latex_functions.py +++ b/_unittests/ut_tools/test_latex_functions.py @@ -21,6 +21,21 @@ def test_replace_pattern(self): self.assertEqual( replace_latex_command("\\vecteur{a}{b}"), "\\left(a,\\dots,b\\right)" ) + self.assertEqual( + replace_latex_command("\\pa{5\\pa{3i+3}}"), "\\left(5\\pa{3i+3}\\right)" + ) + self.assertEqual( + replace_latex_command("\\pa{5+3i}\\pa{3i+3}"), + "\\left(5+3i\\right)\\left(3i+3}\\right)", + ) + self.assertEqual( + replace_latex_command( + "\\indicatrice{ N \\supegal X } + \\cro{ X (s-p) + N (q-s)} " + "\\indicatrice{ N < X }" + ), + "{1\\!\\!1}_{ N \\geqslant X } + \\left[ X (s-p) + N (q-s)\\right]" + " {1\\!\\!1}_{ N < X }", + ) if __name__ == "__main__": diff --git a/sphinx_runpython/_cmd_helper.py b/sphinx_runpython/_cmd_helper.py index e2e81b3..c67c9f2 100644 --- a/sphinx_runpython/_cmd_helper.py +++ b/sphinx_runpython/_cmd_helper.py @@ -1,5 +1,6 @@ import glob import os +from typing import Optional from argparse import ArgumentParser from tempfile import TemporaryDirectory @@ -12,7 +13,7 @@ def get_parser(): ) parser.add_argument( "command", - help="Command to run, only 'nb2py', 'readme', 'img2pdf' are available", + help="Command to run, only 'nb2py', 'readme', 'img2pdf', 'latex' are available", ) parser.add_argument( "-p", "--path", help="Folder or file which contains the files to process" @@ -50,7 +51,7 @@ def nb2py(infolder: str, recursive: bool = False, verbose: int = 0): patterns = [infolder + "/*.ipynb", infolder + "/**/*.ipynb"] for pattern in patterns: if verbose: - print(f"nb2py: look with pattern {pattern!r}, recursive={recursive}") + print(f"[nb2py] look with pattern {pattern!r}, recursive={recursive}") for name in glob.iglob(pattern, recursive=recursive): spl = os.path.splitext(name) out = spl[0] + ".py" @@ -59,11 +60,51 @@ def nb2py(infolder: str, recursive: bool = False, verbose: int = 0): convert_ipynb_to_gallery(name, outfile=out) +def latex_process( + infolder: str, + recursive: bool = False, + output: Optional[str] = None, + verbose: int = 0, +): + from .tools.latex_functions import replace_latex_command + + if not os.path.exists(infolder): + raise FileNotFoundError(f"Unable to find {infolder!r}.") + patterns = [infolder + "/*.rst", infolder + "/**/*.py"] + for pattern in patterns: + if verbose: + print(f"[latex] look with pattern {pattern!r}, recursive={recursive}") + for name in glob.iglob(pattern, recursive=recursive): + with open(name, "r") as f: + content = f.read() + new_content = replace_latex_command(content) + if new_content != content: + if output: + new_name = os.path.join(output, os.path.split(name)[-1]) + if verbose: + print(f"[latex] write {new_name!r}") + with open(new_name, "w") as f: + f.write(new_content) + else: + if verbose: + print(f"[latex] replace inplace {name!r}") + with open(name, "w") as f: + f.write(new_content) + + def process_args(args): cmd = args.command if cmd == "nb2py": nb2py(args.path, recursive=args.recursive, verbose=args.verbose) return + if cmd == "latex": + latex_process( + args.path, + recursive=args.recursive, + verbose=args.verbose, + ouptut=args.output, + ) + return if cmd == "img2pdf": from .tools.img_export import images2pdf diff --git a/sphinx_runpython/tools/latex_functions.py b/sphinx_runpython/tools/latex_functions.py index c75317c..f6e54fa 100644 --- a/sphinx_runpython/tools/latex_functions.py +++ b/sphinx_runpython/tools/latex_functions.py @@ -72,7 +72,7 @@ def replace_latex_command( Replaces a latex by its raw expression. :param text: text - :param regex: one in the known list or None for all + :param patterns: one in the known list or None for all :return: modified text The default patterns are defined by: From 7c566ee16fd2fcc5ceb41b11a6dc6d895715a685 Mon Sep 17 00:00:00 2001 From: xadupre Date: Wed, 9 Oct 2024 16:11:28 +0200 Subject: [PATCH 04/13] comment --- sphinx_runpython/tools/latex_functions.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sphinx_runpython/tools/latex_functions.py b/sphinx_runpython/tools/latex_functions.py index f6e54fa..00c0194 100644 --- a/sphinx_runpython/tools/latex_functions.py +++ b/sphinx_runpython/tools/latex_functions.py @@ -71,6 +71,8 @@ def replace_latex_command( """ Replaces a latex by its raw expression. + Uses pylatexenc.latexwalker + :param text: text :param patterns: one in the known list or None for all :return: modified text From b3cd6cb81c8c3a1b704ca9a2858d021f1c87cebc Mon Sep 17 00:00:00 2001 From: xadupre Date: Sat, 29 Mar 2025 10:17:15 +0100 Subject: [PATCH 05/13] spell --- .github/workflows/spell-check.yml | 24 ++++++++++ _doc/api/blocdefs.rst | 18 ++++---- _doc/api/blocdefs_list.rst | 6 +-- _doc/api/quote.rst | 2 +- _doc/api/runpython.rst | 2 +- ...t_profiling.py => plot_profiling_dummy.py} | 0 .../ut_blocdefs/test_blocref_extension.py | 4 +- .../ut_blocdefs/test_exref_extension.py | 10 ++--- .../ut_blocdefs/test_faqref_extension.py | 10 ++--- .../ut_collapse/test_collapse_extension.py | 10 ++--- _unittests/ut_docassert/datadoc/clsslk.py | 2 +- .../ut_runpython/test_runpython_extension.py | 44 +++++++++---------- .../test_runpython_extension_image.py | 2 +- .../test_runpython_extension_toggle.py | 4 +- pyproject.toml | 2 +- sphinx_runpython/_cmd_helper.py | 2 +- .../blocdefs/sphinx_blocref_extension.py | 18 ++++---- .../blocdefs/sphinx_exref_extension.py | 16 +++---- .../blocdefs/sphinx_faqref_extension.py | 16 +++---- .../blocdefs/sphinx_mathdef_extension.py | 2 +- sphinx_runpython/ext_helper.py | 2 +- sphinx_runpython/ext_io_helper.py | 8 ++-- sphinx_runpython/github_link.py | 2 +- sphinx_runpython/import_object_helper.py | 2 +- sphinx_runpython/readme.py | 6 +-- sphinx_runpython/runpython/run_cmd.py | 2 +- sphinx_runpython/sphinx_rst_builder.py | 2 +- sphinx_runpython/tools/img_export.py | 6 ++- sphinx_runpython/tools/latex_functions.py | 2 +- 29 files changed, 126 insertions(+), 100 deletions(-) create mode 100644 .github/workflows/spell-check.yml rename _doc/examples/{plot_profiling.py => plot_profiling_dummy.py} (100%) diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml new file mode 100644 index 0000000..fe51c4d --- /dev/null +++ b/.github/workflows/spell-check.yml @@ -0,0 +1,24 @@ +name: Spell Check + +on: + push: + branches: + - main + pull_request: + +jobs: + spell-check: + runs-on: ubuntu-latest + + steps: + # Checkout the repository + - name: Checkout code + uses: actions/checkout@v3 + + # Install codespell + - name: Install codespell + run: pip install codespell + + # Run codespell + - name: Run codespell + run: codespell --skip="*.png,*.jpg,*.jpeg,*.gif,*.svg,*.ico,*.pdf,*.js,*.css,*.map,./_unittests/ut__main/data/*,./_doc/api/quote.rst,./sphinx_runpython/language.py" --ignore-words-list="nd,te,OT" --check-filenames diff --git a/_doc/api/blocdefs.rst b/_doc/api/blocdefs.rst index 5d2272d..4b27bd1 100644 --- a/_doc/api/blocdefs.rst +++ b/_doc/api/blocdefs.rst @@ -101,22 +101,22 @@ An example: :: .. blocref:: - :title: How to add a bloc? - :tag: bloc - :label: l-this-bloc + :title: How to add a block? + :tag: block + :label: l-this-block - A bloc... + A block... Which gives: .. blocref:: - :title: How to add a bloc? - :tag: bloc - :label: l-this-bloc + :title: How to add a block? + :tag: block + :label: l-this-block - A bloc... + A block... -A reference can be added to this bloc :ref:`Bloc A `. +A reference can be added to this block :ref:`Block A `. The title needs to be recalled. mathdef diff --git a/_doc/api/blocdefs_list.rst b/_doc/api/blocdefs_list.rst index 62b609f..d9b8a4d 100644 --- a/_doc/api/blocdefs_list.rst +++ b/_doc/api/blocdefs_list.rst @@ -2,7 +2,7 @@ blocreflist, exreflist, mathdeflist =================================== -These extensions can recall the blocs defined by +These extensions can recall the blocks defined by :ref:`l-blocdefs`. exreflist @@ -47,13 +47,13 @@ An example: :: .. blocreflist:: - :tag: bloc + :tag: block :contents: Which gives: .. blocreflist:: - :tag: bloc + :tag: block :contents: mathdeflist diff --git a/_doc/api/quote.rst b/_doc/api/quote.rst index 4c9a9dd..d142b15 100644 --- a/_doc/api/quote.rst +++ b/_doc/api/quote.rst @@ -2,7 +2,7 @@ quote ===== -A bloc to insert a quote from a book, a film... +A block to insert a quote from a book, a film... Usage ===== diff --git a/_doc/api/runpython.rst b/_doc/api/runpython.rst index 2c36846..fd5f5c0 100644 --- a/_doc/api/runpython.rst +++ b/_doc/api/runpython.rst @@ -19,7 +19,7 @@ In *conf.py*: Documentation means many examples which needs to be updated when a change happen unless the documentation runs the example itself and update its output. That's what this directive does. It adds as raw text whatever comes out -throught the standard output. +through the standard output. One example: diff --git a/_doc/examples/plot_profiling.py b/_doc/examples/plot_profiling_dummy.py similarity index 100% rename from _doc/examples/plot_profiling.py rename to _doc/examples/plot_profiling_dummy.py diff --git a/_unittests/ut_blocdefs/test_blocref_extension.py b/_unittests/ut_blocdefs/test_blocref_extension.py index 3ff5fa5..9ebbd7e 100644 --- a/_unittests/ut_blocdefs/test_blocref_extension.py +++ b/_unittests/ut_blocdefs/test_blocref_extension.py @@ -99,7 +99,7 @@ def test_blocref2(self): :tag: bug :label: id3 - this code shoud appear___ + this code should appear___ after """.replace( @@ -112,7 +112,7 @@ def test_blocref2(self): writer_name="rst", ) - t1 = "this code shoud appear" + t1 = "this code should appear" if t1 not in html: raise Exception(html) diff --git a/_unittests/ut_blocdefs/test_exref_extension.py b/_unittests/ut_blocdefs/test_exref_extension.py index 7fe5be5..049b2a7 100644 --- a/_unittests/ut_blocdefs/test_exref_extension.py +++ b/_unittests/ut_blocdefs/test_exref_extension.py @@ -17,7 +17,7 @@ def test_exref(self): :tag: bug :lid: id3 - this code shoud appear___ + this code should appear___ after """.replace( @@ -30,7 +30,7 @@ def test_exref(self): writer_name="rst", ) - t1 = "this code shoud appear" + t1 = "this code should appear" if t1 not in html: raise AssertionError("ISSUE in " + html) @@ -55,7 +55,7 @@ def test_exreflist(self): :tag: freg :lid: id3 - this code shoud appear___ + this code should appear___ middle @@ -71,7 +71,7 @@ def test_exreflist(self): html = rst2html(content, writer_name="rst") - t1 = "this code shoud appear" + t1 = "this code should appear" if t1 not in html: raise AssertionError("ISSUE in " + html) @@ -96,7 +96,7 @@ def test_exreflist_rst(self): :tag: freg :lid: id3 - this code shoud appear___ + this code should appear___ middle diff --git a/_unittests/ut_blocdefs/test_faqref_extension.py b/_unittests/ut_blocdefs/test_faqref_extension.py index 5fd3df8..eb247a1 100644 --- a/_unittests/ut_blocdefs/test_faqref_extension.py +++ b/_unittests/ut_blocdefs/test_faqref_extension.py @@ -17,7 +17,7 @@ def test_faqref(self): :tag: bug :lid: id3 - this code shoud appear___ + this code should appear___ after """.replace( @@ -30,7 +30,7 @@ def test_faqref(self): writer_name="rst", ) - t1 = "this code shoud appear" + t1 = "this code should appear" if t1 not in html: raise AssertionError("ISSUE in " + html) @@ -55,7 +55,7 @@ def test_faqreflist(self): :tag: freg :lid: id3 - this code shoud appear___ + this code should appear___ middle @@ -71,7 +71,7 @@ def test_faqreflist(self): html = rst2html(content, writer_name="rst") - t1 = "this code shoud appear" + t1 = "this code should appear" if t1 not in html: raise AssertionError("ISSUE in " + html) @@ -96,7 +96,7 @@ def test_faqreflist_rst(self): :tag: freg :lid: id3 - this code shoud appear___ + this code should appear___ middle diff --git a/_unittests/ut_collapse/test_collapse_extension.py b/_unittests/ut_collapse/test_collapse_extension.py index a0b0f76..b7cb68a 100644 --- a/_unittests/ut_collapse/test_collapse_extension.py +++ b/_unittests/ut_collapse/test_collapse_extension.py @@ -39,7 +39,7 @@ def test_collapse(self): .. collapse:: - this code shoud appear___ + this code should appear___ after """.replace( @@ -50,7 +50,7 @@ def test_collapse(self): # RST html = rst2html(content, writer_name="rst") - t1 = " this code shoud appear___" + t1 = " this code should appear___" if t1 not in html: raise AssertionError(html) @@ -72,7 +72,7 @@ def test_collapse(self): html = rst2html(content, writer_name="rst") - t1 = "this code shoud appear" + t1 = "this code should appear" if t1 not in html: raise AssertionError(html) @@ -98,7 +98,7 @@ def test_collapse_legend(self): .. collapse:: :legend: ABC/abcd - this code shoud appear___ + this code should appear___ after """.replace( @@ -133,7 +133,7 @@ def test_collapse_show(self): :legend: ABC/abcd :hide: - this code shoud appear___ + this code should appear___ after """.replace( diff --git a/_unittests/ut_docassert/datadoc/clsslk.py b/_unittests/ut_docassert/datadoc/clsslk.py index 30eac27..82a493e 100644 --- a/_unittests/ut_docassert/datadoc/clsslk.py +++ b/_unittests/ut_docassert/datadoc/clsslk.py @@ -3,7 +3,7 @@ class Estimator: Dummy estimator. :param lr: learning rate - :param alph: gradient coefficient + :param alpha: gradient coefficient """ def __init__(self, lr=0.1, alpha=0.2, beta=0.3): diff --git a/_unittests/ut_runpython/test_runpython_extension.py b/_unittests/ut_runpython/test_runpython_extension.py index 781a63d..cbaef02 100644 --- a/_unittests/ut_runpython/test_runpython_extension.py +++ b/_unittests/ut_runpython/test_runpython_extension.py @@ -44,7 +44,7 @@ def depart_rp_node(self, node): self.body.append("

depart_rp_node

") if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") content = """ test a directive @@ -55,7 +55,7 @@ def depart_rp_node(self, node): :rst: :showcode: - print(u"this code shoud appear" + u"___") + print(u"this code should appear" + u"___") import sys print(u"setsysvar: " + str( sys.__dict__.get( @@ -67,7 +67,7 @@ def depart_rp_node(self, node): html = rst2html(content, writer_name="html") - t1 = "this code shoud appear___" + t1 = "this code should appear___" if t1 not in html: raise AssertionError(html) t2 = "setsysvar: True" @@ -80,14 +80,14 @@ def depart_rp_node(self, node): if t2 not in html: raise AssertionError(html) if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") def test_runpython_numpy(self): """ this test also test the extension runpython """ if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") content = """ test a directive @@ -114,7 +114,7 @@ def test_runpython_numpy_linenos(self): this test also test the extension runpython """ if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") content = """ test a directive @@ -160,7 +160,7 @@ def depart_rp_node(self, node): self.body.append("

depart_rp_node

") if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") content = """ test a directive @@ -204,7 +204,7 @@ def depart_rp_node(self, node): self.body.append("

depart_rp_node

") if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") content = """ test a directive @@ -247,7 +247,7 @@ def depart_rp_node(self, node): self.body.append("

depart_rp_node

") if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") content = """ test a directive @@ -256,7 +256,7 @@ def depart_rp_node(self, node): .. runpython:: :setsysvar: - print(u"this code shoud appear" + u"___") + print(u"this code should appear" + u"___") import sys print(u"setsysvar: " + str(sys.__dict__.get( 'enable_disabled_documented_pieces_of_code', None))) @@ -267,7 +267,7 @@ def depart_rp_node(self, node): html = rst2html(content, writer_name="rst") - t1 = "this code shoud appear___" + t1 = "this code should appear___" for t in t1.split(): if t not in html: raise AssertionError(html) @@ -282,7 +282,7 @@ def depart_rp_node(self, node): if t2 in html: raise AssertionError(html) if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") def test_runpython_process(self): """ @@ -303,7 +303,7 @@ def depart_rp_node(self, node): self.body.append("

depart_rp_node

") if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") content = """ test a directive @@ -315,7 +315,7 @@ def depart_rp_node(self, node): :showcode: import sphinx_runpython - print(u"this code shoud appear" + u"___") + print(u"this code should appear" + u"___") import sys print(u"setsysvar: " + str(sys.__dict__.get( 'enable_disabled_documented_pieces_of_code', None))) @@ -326,7 +326,7 @@ def depart_rp_node(self, node): html = rst2html(content, writer_name="html") - t1 = "this code shoud appear___" + t1 = "this code should appear___" for t in t1.split(): if t not in html: raise AssertionError(html) @@ -341,7 +341,7 @@ def depart_rp_node(self, node): if t2 not in html: raise AssertionError(html) if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") def test_runpython_exception(self): from docutils import nodes @@ -359,7 +359,7 @@ def depart_rp_node(self, node): self.body.append("

depart_rp_node

") if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") content = """ test a directive @@ -369,7 +369,7 @@ def depart_rp_node(self, node): :showcode: :exception: - print(u"this code shoud" + u" appear") + print(u"this code should" + u" appear") z = 1/0 print(u"this one should" + u" not") """.replace( @@ -404,7 +404,7 @@ def depart_rp_node(self, node): self.body.append("

depart_rp_node

") if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") content = """ test a directive @@ -414,7 +414,7 @@ def depart_rp_node(self, node): :showcode: :assert: z == 1.1 - print(u"this code shoud" + u" appear") + print(u"this code should" + u" appear") z = 0.5 + 0.6 print(u"this one should" + u" not") """.replace( @@ -471,7 +471,7 @@ def depart_rp_node(self, node): self.body.append("

depart_rp_node

") if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") content = """ test a directive @@ -482,7 +482,7 @@ def depart_rp_node(self, node): :exception: :process: - print(u"this code shoud" + u" appear") + print(u"this code should" + u" appear") z = 1/0 print(u"this one should" + u" not") """.replace( diff --git a/_unittests/ut_runpython/test_runpython_extension_image.py b/_unittests/ut_runpython/test_runpython_extension_image.py index 99d56d0..6cb09d6 100644 --- a/_unittests/ut_runpython/test_runpython_extension_image.py +++ b/_unittests/ut_runpython/test_runpython_extension_image.py @@ -30,7 +30,7 @@ def depart_rp_node(self, node): self.body.append("

depart_rp_node

") if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") temp = os.path.abspath(os.path.dirname(__file__)) content = """ diff --git a/_unittests/ut_runpython/test_runpython_extension_toggle.py b/_unittests/ut_runpython/test_runpython_extension_toggle.py index 8a9d91a..49ba8a5 100644 --- a/_unittests/ut_runpython/test_runpython_extension_toggle.py +++ b/_unittests/ut_runpython/test_runpython_extension_toggle.py @@ -37,7 +37,7 @@ def depart_rp_node(self, node): self.add_text(".. endrunpython." + self.nl) if "enable_disabled_documented_pieces_of_code" in sys.__dict__: - raise AssertionError("this case shoud not be") + raise AssertionError("this case should not be") content = """ test a directive @@ -49,7 +49,7 @@ def depart_rp_node(self, node): :showcode: :toggle: both - print(u"this code shoud appear" + u"___") + print(u"this code should appear" + u"___") import sys print(u"setsysvar: " + str( sys.__dict__.get( diff --git a/pyproject.toml b/pyproject.toml index ba20bd7..7c9290c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ select = [ "PYI041", "RUF012", "RUF100", "RUF010", "SIM108", "SIM102", "SIM114", "SIM103", "SIM910", - "UP015", "UP027", "UP031", "UP034", "UP032" + "UP006", "UP015", "UP027", "UP031", "UP034", "UP035", "UP032" ] "_doc/examples/plot_*.py" = ["E402", "B018", "PIE808", "SIM105", "SIM117"] "_doc/notebooks/plot_*.py" = ["E402", "B018", "PIE808", "SIM105", "SIM117"] diff --git a/sphinx_runpython/_cmd_helper.py b/sphinx_runpython/_cmd_helper.py index c67c9f2..e957d66 100644 --- a/sphinx_runpython/_cmd_helper.py +++ b/sphinx_runpython/_cmd_helper.py @@ -102,7 +102,7 @@ def process_args(args): args.path, recursive=args.recursive, verbose=args.verbose, - ouptut=args.output, + output=args.output, ) return if cmd == "img2pdf": diff --git a/sphinx_runpython/blocdefs/sphinx_blocref_extension.py b/sphinx_runpython/blocdefs/sphinx_blocref_extension.py index d18d2a0..90a6200 100644 --- a/sphinx_runpython/blocdefs/sphinx_blocref_extension.py +++ b/sphinx_runpython/blocdefs/sphinx_blocref_extension.py @@ -41,8 +41,8 @@ class BlocRef(BaseAdmonition): A ``blocref`` entry, displayed in the form of an admonition. It takes the following options: - * *title*: a title for the bloc - * *tag*: a tag to have several categories of blocs + * *title*: a title for the block + * *tag*: a tag to have several categories of blocks * *lid* or *label*: a label to refer to * *index*: to add an entry to the index (comma separated) @@ -68,7 +68,7 @@ class BlocRef(BaseAdmonition): print("mignon") - All blocs can be displayed in another page by using ``blocreflist``:: + All blocks can be displayed in another page by using ``blocreflist``:: .. blocreflist:: :tag: dummy_example @@ -84,7 +84,7 @@ class BlocRef(BaseAdmonition): :tag: dummy_example :sort: title - This directive is used to highlight a bloc about + This directive is used to highlight a block about anything :class:`sphinx_runpython.blocdefs.sphinx_blocref_extension.BlocRef`, a question :class:`sphinx_runpython.blocdefs.sphinx_faqref_extension.FaqRef`, an example :class:`sphinx_runpython.blocdefs.sphinx_exref_extension.ExRef`. @@ -110,7 +110,7 @@ class BlocRef(BaseAdmonition): def _update_title(self, title, tag, lid): """ - Updates the title for the bloc itself. + Updates the title for the block itself. """ return title @@ -289,9 +289,9 @@ class BlocRefList(Directive): """ A list of all blocref entries, for a specific tag. - * tag: a tag to filter bloc having this tag - * sort: a way to sort the blocs based on the title, file, number, default: *title* - * contents: add a bullet list with links to added blocs + * tag: a tag to filter block having this tag + * sort: a way to sort the blocks based on the title, file, number, default: *title* + * contents: add a bullet list with links to added blocks Example:: @@ -520,7 +520,7 @@ def process_blocref_nodes_generic( newnode.append(nodes.Text(newnode["name"])) - # para is duplicate of the content of the bloc + # para is duplicate of the content of the block para += newnode para += nodes.Text(desc2, desc2) diff --git a/sphinx_runpython/blocdefs/sphinx_exref_extension.py b/sphinx_runpython/blocdefs/sphinx_exref_extension.py index bd2ca45..aee1ef0 100644 --- a/sphinx_runpython/blocdefs/sphinx_exref_extension.py +++ b/sphinx_runpython/blocdefs/sphinx_exref_extension.py @@ -30,8 +30,8 @@ class ExRef(BlocRef): A ``exref`` entry, displayed in the form of an admonition. It takes the following options: - * *title*: a title for the bloc - * *tag*: a tag to have several categories of blocs (optional) + * *title*: a title for the block + * *tag*: a tag to have several categories of blocks (optional) * *lid* or *label*: a label to refer to * *index*: to add an entry to the index (comma separated) @@ -60,13 +60,13 @@ class ExRef(BlocRef): print("mignon") - All blocs can be displayed in another page by using ``exreflist``:: + All blocks can be displayed in another page by using ``exreflist``:: .. exreflist:: :tag: dummy_example6 :sort: title - Only blocs tagged as ``dummy_example`` will be inserted here. + Only blocks tagged as ``dummy_example`` will be inserted here. The option ``sort`` sorts items by *title*, *number*, *file*. You also link to it by typing ``:ref:'anchor '`` which gives something like :ref:`link_to_blocref `. @@ -82,7 +82,7 @@ class ExRef(BlocRef): def run(self): """ - Calls run from @see cl BlocRef and add defaut tag. + Calls run from @see cl BlocRef and add default tag. """ if "tag" not in self.options: self.options["tag"] = "ex" @@ -102,9 +102,9 @@ class ExRefList(BlocRefList): """ A list of all *exref* entries, for a specific tag. - * tag: a tag to filter bloc having this tag - * sort: a way to sort the blocs based on the title, file, number, default: *title* - * contents: add a bullet list with links to added blocs + * tag: a tag to filter block having this tag + * sort: a way to sort the blocks based on the title, file, number, default: *title* + * contents: add a bullet list with links to added blocks Example:: diff --git a/sphinx_runpython/blocdefs/sphinx_faqref_extension.py b/sphinx_runpython/blocdefs/sphinx_faqref_extension.py index 61afbd7..874efa8 100644 --- a/sphinx_runpython/blocdefs/sphinx_faqref_extension.py +++ b/sphinx_runpython/blocdefs/sphinx_faqref_extension.py @@ -30,8 +30,8 @@ class FaqRef(BlocRef): A ``faqref`` entry, displayed in the form of an admonition. It takes the following options: - * *title*: a title for the bloc - * *tag*: a tag to have several categories of blocs (optional) + * *title*: a title for the block + * *tag*: a tag to have several categories of blocks (optional) * *lid* or *label*: a label to refer to * *index*: to add an entry to the index (comma separated) @@ -60,13 +60,13 @@ class FaqRef(BlocRef): print("mignon") - All blocs can be displayed in another page by using ``faqreflist``:: + All blocks can be displayed in another page by using ``faqreflist``:: .. faqreflist:: :tag: dummy_example6 :sort: title - Only blocs tagged as ``dummy_example`` will be inserted here. + Only blocks tagged as ``dummy_example`` will be inserted here. The option ``sort`` sorts items by *title*, *number*, *file*. You also link to it by typing ``:ref:'anchor '`` which gives something like :ref:`link_to_blocref `. @@ -84,7 +84,7 @@ def run(self): """ Calls run from :class:`sphinx_runpython.blocdefs.sphinx_blocref_extension.BlocRef` - and add defaut tag. + and add default tag. """ if "tag" not in self.options: self.options["tag"] = "faq" @@ -104,9 +104,9 @@ class FaqRefList(BlocRefList): """ A list of all *faqref* entries, for a specific tag. - * tag: a tag to filter bloc having this tag - * sort: a way to sort the blocs based on the title, file, number, default: *title* - * contents: add a bullet list with links to added blocs + * tag: a tag to filter block having this tag + * sort: a way to sort the blocks based on the title, file, number, default: *title* + * contents: add a bullet list with links to added blocks Example:: diff --git a/sphinx_runpython/blocdefs/sphinx_mathdef_extension.py b/sphinx_runpython/blocdefs/sphinx_mathdef_extension.py index 7dfdc6f..1c635e0 100644 --- a/sphinx_runpython/blocdefs/sphinx_mathdef_extension.py +++ b/sphinx_runpython/blocdefs/sphinx_mathdef_extension.py @@ -237,7 +237,7 @@ class MathDefList(Directive): A list of all mathdef entries, for a specific tag. * tag: a tag to have several categories of mathdef - * contents: add a bullet list with links to added blocs + * contents: add a bullet list with links to added blocks Example:: diff --git a/sphinx_runpython/ext_helper.py b/sphinx_runpython/ext_helper.py index 750666d..a99327d 100644 --- a/sphinx_runpython/ext_helper.py +++ b/sphinx_runpython/ext_helper.py @@ -118,7 +118,7 @@ def __init__(self, node): def traverse(node, depth=0): """ Enumerates through all children but insert a node whenever - digging or leaving the childrens nodes. + digging or leaving the children's nodes. :param node: node (from doctree) :param depth: current depth diff --git a/sphinx_runpython/ext_io_helper.py b/sphinx_runpython/ext_io_helper.py index 7a19aca..beabc7f 100644 --- a/sphinx_runpython/ext_io_helper.py +++ b/sphinx_runpython/ext_io_helper.py @@ -397,7 +397,7 @@ def _local_loop(ur): raise e if chunk is None: - if len(res) >= 2 and res[:2] == b"\x1f\x8B": + if len(res) >= 2 and res[:2] == b"\x1f\x8b": # gzip format res = gzip.decompress(res) @@ -487,13 +487,13 @@ def download_requirejs( return download_requirejs(to=to, location=None, clean=clean) reg = re.compile('href=\\"(.*?minified/require[.]js)\\"') - alls = reg.findall(page) - if len(alls) == 0: + ralls = reg.findall(page) + if len(ralls) == 0: raise RuntimeError( f"Unable to find a link on require.js file on page {page!r}." ) - filename = alls[0] + filename = ralls[0] try: local = download(filename, to) diff --git a/sphinx_runpython/github_link.py b/sphinx_runpython/github_link.py index bee526c..23a2261 100644 --- a/sphinx_runpython/github_link.py +++ b/sphinx_runpython/github_link.py @@ -37,7 +37,7 @@ def _linkcode_resolve(domain, info, package, url_fmt, revision): module = __import__(info["module"], fromlist=[class_name]) except ImportError as e: raise ImportError( - f"Unable to find {info['module']!r} wich class={class_name!r}." + f"Unable to find {info['module']!r} which class={class_name!r}." ) from e obj = attrgetter(info["fullname"])(module) diff --git a/sphinx_runpython/import_object_helper.py b/sphinx_runpython/import_object_helper.py index 7d0403f..9829e97 100644 --- a/sphinx_runpython/import_object_helper.py +++ b/sphinx_runpython/import_object_helper.py @@ -113,7 +113,7 @@ def import_object(docname, kind, use_init=True) -> Tuple[object, str]: name = spl[-1] myfunc = myfunc.__init__ if use_init else myfunc else: - raise ValueError("Unknwon value for 'kind'") + raise ValueError("Unknown value for 'kind'") return myfunc, name diff --git a/sphinx_runpython/readme.py b/sphinx_runpython/readme.py index 37b028e..0e8eb9c 100644 --- a/sphinx_runpython/readme.py +++ b/sphinx_runpython/readme.py @@ -116,7 +116,7 @@ def create_virtual_env( out, err = run_cmd(cmd, wait=True, logf=print if verbose else None) if len(err) > 0: raise VirtualEnvError( - f"Unable to create virtual environement at {where!r}" + f"Unable to create virtual environment at {where!r}" f"\nCMD:\n{cmd}\nOUT:\n{out}\n[pyqerror]\n{err}" ) @@ -236,7 +236,7 @@ def run_venv_script( **kwargs: Dict[str, Any], ) -> str: """ - Runs a script on a vritual environment (the script should be simple). + Runs a script on a virtual environment (the script should be simple). :param venv: virtual environment :param script: script as a string (not a file) @@ -314,7 +314,7 @@ def run_base_script( **kwargs: Dict[str, Any], ) -> str: """ - Runs a script with the original intepreter even if this function + Runs a script with the original interpreter even if this function is run from a virtual environment. :param script: script as a string (not a file) diff --git a/sphinx_runpython/runpython/run_cmd.py b/sphinx_runpython/runpython/run_cmd.py index 5965b15..bb0fc31 100644 --- a/sphinx_runpython/runpython/run_cmd.py +++ b/sphinx_runpython/runpython/run_cmd.py @@ -347,7 +347,7 @@ def run_cmd( if change_path is not None: os.chdir(current) try: - # we try to close the ressources + # we try to close the resources stdout.close() stderr.close() except Exception: diff --git a/sphinx_runpython/sphinx_rst_builder.py b/sphinx_runpython/sphinx_rst_builder.py index 2705768..627c359 100644 --- a/sphinx_runpython/sphinx_rst_builder.py +++ b/sphinx_runpython/sphinx_rst_builder.py @@ -412,7 +412,7 @@ def depart_rubric(self, node): self.end_state() def visit_compound(self, node): - # self.log_unknown("compount", node) + # self.log_unknown("compound", node) pass def depart_compound(self, node): diff --git a/sphinx_runpython/tools/img_export.py b/sphinx_runpython/tools/img_export.py index 5aba6d1..a00caa9 100644 --- a/sphinx_runpython/tools/img_export.py +++ b/sphinx_runpython/tools/img_export.py @@ -93,11 +93,13 @@ def images2pdf( size0 = im.size size = tuple(int(s * zoom) for s in size0) if verbose: - print(f"resizes from {size0} to {size} (formt={fmt!r}) for {img!r}") + print( + f"resizes from {size0} to {size} (format={fmt!r}) for {img!r}" + ) im = im.resize(size) if rotate != 0: if verbose: - print(f"rotates {rotate} (formt={fmt!r}) for {img!r}") + print(f"rotates {rotate} (format={fmt!r}) for {img!r}") im = im.rotate(rotate) buffer = io.BytesIO() im.save(buffer, format=fmt) diff --git a/sphinx_runpython/tools/latex_functions.py b/sphinx_runpython/tools/latex_functions.py index 00c0194..4f70b38 100644 --- a/sphinx_runpython/tools/latex_functions.py +++ b/sphinx_runpython/tools/latex_functions.py @@ -15,7 +15,7 @@ \\newcommand{\\ensemble}[2]{\\left\\{#1,\\dots,#2\\right\\}} \\newcommand{\\fleche}[1]{\\overrightarrow{#1}} \\newcommand{\\intervalle}[2]{\\left\\{#1,\\cdots,#2\\right\\}} -\\newcommand{\\independant}[0]{\\perp \\!\\!\\! \\perp} +\\newcommand{\\independent}[0]{\\perp \\!\\!\\! \\perp} \\newcommand{\\esp}{\\mathbb{E}} \\newcommand{\\espf}[2]{\\mathbb{E}_{#1}\\left(#2\\right)} \\newcommand{\\var}{\\mathbb{V}} From 5da24a097657e8abd088c1ffdf47579f645b19be Mon Sep 17 00:00:00 2001 From: xadupre Date: Sat, 29 Mar 2025 10:19:18 +0100 Subject: [PATCH 06/13] python --- .github/workflows/black-ruff.yml | 2 +- .github/workflows/documentation.yml | 4 ++-- .github/workflows/wheels-any.yml | 4 ++-- azure-pipelines.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/black-ruff.yml b/.github/workflows/black-ruff.yml index 9a04743..aaa98e3 100644 --- a/.github/workflows/black-ruff.yml +++ b/.github/workflows/black-ruff.yml @@ -4,7 +4,7 @@ jobs: black-format-check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: psf/black@stable with: options: "--diff --check" diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 12bf1c2..f272f25 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -21,9 +21,9 @@ jobs: - uses: tlylt/install-graphviz@v1 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: - python-version: '3.11' + python-version: '3.12' - name: Install pandoc run: sudo apt-get install pandoc diff --git a/.github/workflows/wheels-any.yml b/.github/workflows/wheels-any.yml index 0e72470..2e3565e 100644 --- a/.github/workflows/wheels-any.yml +++ b/.github/workflows/wheels-any.yml @@ -17,9 +17,9 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: - python-version: '3.11' + python-version: '3.12' - name: build wheel run: python -m pip wheel . diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 40ef5fc..343e005 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -5,7 +5,7 @@ jobs: strategy: matrix: Python311-Linux: - python.version: '3.11' + python.version: '3.12' maxParallel: 3 steps: From 581656952013041f7b8c44258ef6e84ce84600d9 Mon Sep 17 00:00:00 2001 From: xadupre Date: Sat, 29 Mar 2025 10:24:27 +0100 Subject: [PATCH 07/13] cache --- .github/workflows/documentation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index f272f25..309a8a4 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -35,7 +35,7 @@ jobs: run: python -m pip install -r requirements-dev.txt - name: Cache pip - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('requirements-dev.txt') }} From 07393aefcbe8de5c32dcb91093783c1aea76f27b Mon Sep 17 00:00:00 2001 From: xadupre Date: Sat, 29 Mar 2025 10:25:33 +0100 Subject: [PATCH 08/13] fix action --- .github/workflows/documentation.yml | 2 +- .github/workflows/wheels-any.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 309a8a4..1e6e1ea 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -102,6 +102,6 @@ jobs: exit 1 fi - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: path: ./dist/** diff --git a/.github/workflows/wheels-any.yml b/.github/workflows/wheels-any.yml index 2e3565e..ab58575 100644 --- a/.github/workflows/wheels-any.yml +++ b/.github/workflows/wheels-any.yml @@ -24,6 +24,6 @@ jobs: - name: build wheel run: python -m pip wheel . - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: path: ./sphinx_runpython*.whl From 0afcde5c6dc7aabccbb4d905cbab4b41fccd6e02 Mon Sep 17 00:00:00 2001 From: xadupre Date: Sat, 29 Mar 2025 11:32:40 +0100 Subject: [PATCH 09/13] fix latex --- _unittests/ut__main/test_cmd.py | 4 +- _unittests/ut_tools/test_latex_functions.py | 16 +++-- azure-pipelines.yml | 19 +++--- clean_repo.sh | 71 +++++++++++++++++++++ sphinx_runpython/_cmd_helper.py | 2 +- sphinx_runpython/ext_test_case.py | 38 ++++++++++- sphinx_runpython/process_rst.py | 2 +- sphinx_runpython/tools/latex_functions.py | 62 ++++++++++++++++-- 8 files changed, 191 insertions(+), 23 deletions(-) create mode 100644 clean_repo.sh diff --git a/_unittests/ut__main/test_cmd.py b/_unittests/ut__main/test_cmd.py index 9c76a6e..0f13721 100644 --- a/_unittests/ut__main/test_cmd.py +++ b/_unittests/ut__main/test_cmd.py @@ -1,7 +1,7 @@ import platform import unittest import os -from sphinx_runpython.ext_test_case import ExtTestCase +from sphinx_runpython.ext_test_case import ExtTestCase, hide_stdout from sphinx_runpython._cmd_helper import get_parser, nb2py, latex_process @@ -11,12 +11,14 @@ def test_cmd(self): self.assertNotEmpty(parser) @unittest.skipIf(platform.system() != "Linux", reason="pandoc not installed") + @hide_stdout() def test_convert(self): data = os.path.join(os.path.dirname(__file__), "data") nb2py(data, verbose=1) expected = os.path.join(data, "float_and_double_rouding.py") self.assertExists(expected) + @hide_stdout() def test_latex(self): data = os.path.join(os.path.dirname(__file__), "data") folder = "test_latex" diff --git a/_unittests/ut_tools/test_latex_functions.py b/_unittests/ut_tools/test_latex_functions.py index 3fbac7c..da313d7 100644 --- a/_unittests/ut_tools/test_latex_functions.py +++ b/_unittests/ut_tools/test_latex_functions.py @@ -1,5 +1,5 @@ import unittest -from sphinx_runpython.ext_test_case import ExtTestCase +from sphinx_runpython.ext_test_case import ExtTestCase, hide_stdout from sphinx_runpython.tools.latex_functions import build_regex, replace_latex_command @@ -9,6 +9,7 @@ def test_build_regex(self): regs = build_regex() self.assertEqual(regs["supegal"], "\\geqslant") + @hide_stdout() def test_replace_pattern(self): self.assertEqual(replace_latex_command("\\R"), "\\mathbb{R}") self.assertEqual(replace_latex_command("A\\R B"), "A\\mathbb{R} B") @@ -22,19 +23,22 @@ def test_replace_pattern(self): replace_latex_command("\\vecteur{a}{b}"), "\\left(a,\\dots,b\\right)" ) self.assertEqual( - replace_latex_command("\\pa{5\\pa{3i+3}}"), "\\left(5\\pa{3i+3}\\right)" + replace_latex_command("\\pa{5\\pa{3i+3}}"), + "\\left(5\\left(3i+3\\right)\\right)", ) self.assertEqual( replace_latex_command("\\pa{5+3i}\\pa{3i+3}"), - "\\left(5+3i\\right)\\left(3i+3}\\right)", + "\\left(5+3i\\right)\\left(3i+3\\right)", ) self.assertEqual( replace_latex_command( "\\indicatrice{ N \\supegal X } + \\cro{ X (s-p) + N (q-s)} " - "\\indicatrice{ N < X }" + "\\indicatrice{ N < X }", + verbose=1, ), - "{1\\!\\!1}_{ N \\geqslant X } + \\left[ X (s-p) + N (q-s)\\right]" - " {1\\!\\!1}_{ N < X }", + " {1\\!\\!1}_{\\left\\{ N \\geqslant X \\right\\}} + " + "\\left[ X (s-p) + N (q-s)\\right]" + " {1\\!\\!1}_{\\left\\{ N < X \\right\\}} ", ) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 343e005..0160f99 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -36,6 +36,7 @@ jobs: python -m pip install . -v -v -v displayName: 'install wheel' - script: | + python -m pytest --durations=10 --ignore-glob=**LONG*.py --ignore-glob=**notebook*.py displayName: 'Runs Unit Tests' - task: PublishPipelineArtifact@0 inputs: @@ -47,8 +48,8 @@ jobs: vmImage: 'ubuntu-latest' strategy: matrix: - Python310-Linux: - python.version: '3.10' + Python312-Linux: + python.version: '3.12' maxParallel: 3 steps: @@ -77,7 +78,7 @@ jobs: black --diff . displayName: 'Black' - script: | - python -m pytest -v + python -m pytest --durations=10 --ignore-glob=**LONG*.py --ignore-glob=**notebook*.py displayName: 'Runs Unit Tests' - script: | python -u setup.py bdist_wheel @@ -95,8 +96,8 @@ jobs: vmImage: 'windows-latest' strategy: matrix: - Python310-Windows: - python.version: '3.10' + Python312-Windows: + python.version: '3.12' maxParallel: 3 steps: @@ -111,7 +112,7 @@ jobs: - script: pip install -r requirements-dev.txt displayName: 'Install Requirements dev' - script: | - python -m pytest -v + python -m pytest --durations=10 --ignore-glob=**LONG*.py --ignore-glob=**notebook*.py displayName: 'Runs Unit Tests' - script: | python -u setup.py bdist_wheel @@ -126,8 +127,8 @@ jobs: vmImage: 'macOS-latest' strategy: matrix: - Python310-Mac: - python.version: '3.10' + Python312-Mac: + python.version: '3.12' maxParallel: 3 steps: @@ -155,7 +156,7 @@ jobs: - script: pip install -r requirements-dev.txt displayName: 'Install Requirements dev' - script: | - python -m pytest -v -v + python -m pytest --durations=10 --ignore-glob=**LONG*.py --ignore-glob=**notebook*.py displayName: 'Runs Unit Tests' - script: | python -u setup.py bdist_wheel diff --git a/clean_repo.sh b/clean_repo.sh new file mode 100644 index 0000000..d2a655d --- /dev/null +++ b/clean_repo.sh @@ -0,0 +1,71 @@ +rm *.onnx +rm *.json +rm *.png +rm *.csv +rm *.nsys-rep +rm *.sqlite +rm *.pte +rm *.ep +rm *.ep.txt +rm *.pkl +rm tt_* +rm plot* +rm test* -rf +rm temp* -rf +rm dump* -rf +rm *.onnx.data +rm .olive-cache -rf +rm onnx_export*.md +rm *.xlsx +rm *.sarif +rm *.svg +rm .pymon +rm nohup.out +rm output_data_bash* +rm dump_models -rf +rm dump_test_models -rf +rm neural_coder_workspace -rf +rm output_data* +rm _plot_torch_sklearn_201_knnpy.py + +rm _doc/sg_execution_times.rst + +rm _doc/examples/plot*.onnx +rm _doc/examples/plot*.txt +rm _doc/examples/ort*.onnx +rm _doc/examples/*.sarif +rm _doc/examples/*.json +rm _doc/examples/*.png +rm _doc/examples/*.csv +rm _doc/examples/*.pte +rm _doc/examples/*.xlsx +rm _doc/examples/dummy*.onnx +rm _doc/examples/*.opt.onnx +rm _doc/examples/*.dynamo.onnx +rm _doc/examples/*.script.onnx +rm _doc/examples/dump_models -rf +rm _doc/examples/dump_onx_* + +rm _doc/recipes/plot*.onnx +rm _doc/recipes/plot*.onnx.weight +rm _doc/recipes/plot*.onnx.data +rm _doc/recipes/plot*.txt +rm _doc/recipes/ort*.onnx +rm _doc/recipes/*.sarif +rm _doc/recipes/*.json +rm _doc/recipes/*.png +rm _doc/recipes/*.csv +rm _doc/recipes/*.pte +rm _doc/recipes/*.xlsx +rm _doc/recipes/dummy*.onnx +rm _doc/recipes/evaluation*-script.onnx +rm _doc/recipes/*.opt.onnx +rm _doc/recipes/*.dynamo.onnx +rm _doc/recipes/*.script.onnx +rm _doc/recipes/dump_models -rf +rm _doc/recipes/dump_onx_* + +rm _tools/bin -rf +rm _tools/mambaroot -rf +rm _tools/repos -rf +rm _tools/results -rf \ No newline at end of file diff --git a/sphinx_runpython/_cmd_helper.py b/sphinx_runpython/_cmd_helper.py index e5f6f4b..3752502 100644 --- a/sphinx_runpython/_cmd_helper.py +++ b/sphinx_runpython/_cmd_helper.py @@ -82,7 +82,7 @@ def latex_process( if not os.path.exists(infolder): raise FileNotFoundError(f"Unable to find {infolder!r}.") - patterns = [infolder + "/*.rst", infolder + "/**/*.py"] + patterns = [infolder + "/*.rst", infolder + "/*.py"] for pattern in patterns: if verbose: print(f"[latex] look with pattern {pattern!r}, recursive={recursive}") diff --git a/sphinx_runpython/ext_test_case.py b/sphinx_runpython/ext_test_case.py index 19adb0b..762068c 100644 --- a/sphinx_runpython/ext_test_case.py +++ b/sphinx_runpython/ext_test_case.py @@ -4,7 +4,7 @@ import warnings from contextlib import redirect_stderr, redirect_stdout from io import StringIO -from typing import Any, Callable, List +from typing import Any, Callable, List, Optional import numpy from numpy.testing import assert_allclose @@ -40,6 +40,42 @@ def call_f(self): return wrapper +def hide_stdout(f: Optional[Callable] = None) -> Callable: + """ + Catches warnings, hides standard output. + The function may be disabled by setting ``UNHIDE=1`` + before running the unit test. + + :param f: the function is called with the stdout as an argument + """ + + def wrapper(fct): + def call_f(self): + if os.environ.get("UNHIDE", ""): + fct(self) + return + st = StringIO() + with redirect_stdout(st), warnings.catch_warnings(): + warnings.simplefilter("ignore", (UserWarning, DeprecationWarning)) + try: + fct(self) + except AssertionError as e: + if "torch is not recent enough, file" in str(e): + raise unittest.SkipTest(str(e)) # noqa: B904 + raise + if f is not None: + f(st.getvalue()) + return None + + try: # noqa: SIM105 + call_f.__name__ = fct.__name__ + except AttributeError: + pass + return call_f + + return wrapper + + class sys_path_append: """ Stores the content of :epkg:`*py:sys:path` and diff --git a/sphinx_runpython/process_rst.py b/sphinx_runpython/process_rst.py index fef858d..84748c6 100644 --- a/sphinx_runpython/process_rst.py +++ b/sphinx_runpython/process_rst.py @@ -37,7 +37,7 @@ "git": "https://git-scm.com/", "Graphviz": "https://graphviz.org/", "HTML": "https://simple.wikipedia.org/wiki/HTML", - "nested_parse_with_titles": "http://sphinx-doc.org/extdev/markupapi.html?highlight=nested_parse_with_titles", + "nested_parse_with_titles": "https://www.sphinx-doc.org/en/master/extdev/markupapi.html?highlight=nested_parse_with_titles", "numpy": ( "https://www.numpy.org/", ("https://docs.scipy.org/doc/numpy/reference/generated/numpy.{0}.html", 1), diff --git a/sphinx_runpython/tools/latex_functions.py b/sphinx_runpython/tools/latex_functions.py index 4f70b38..acf2164 100644 --- a/sphinx_runpython/tools/latex_functions.py +++ b/sphinx_runpython/tools/latex_functions.py @@ -55,8 +55,21 @@ def build_regex(text: Optional[str] = None) -> Dict[str, Union[str, Tuple[str, s name, n, pat = match.group(1), match.group(3), match.group(4) if n is None or int(n) == 0: res[name] = pat + elif name in {"pa", "cro", "acc", "abs"}: + # These can be nested expression. + spl = line.split("#1") + begin, end = spl[0][-1], spl[-1][-2] + if begin == "{": + begin = "\\{" + if end == "}": + end = "\\}" + res[name] = ( + lambda s, name=name, begin=begin, end=end: replace_nested_bracked( + s, name=name, begin=begin, end=end + ) + ) else: - look = f"\\\\{name} *" + "\\{(.+)\\}" * int(n) + look = f"\\\\{name} *" + "\\{(.+?)\\}" * int(n) for c in "\\": pat = pat.replace(c, f"\\{c}") for k in range(int(n)): @@ -65,16 +78,47 @@ def build_regex(text: Optional[str] = None) -> Dict[str, Union[str, Tuple[str, s return res +def replace_nested_bracked(text: str, name: str, begin: str, end: str) -> str: + """ + Replaces brackets, nested brackets... + """ + find_left = f"\\{name}" + "{" + if find_left not in text: + return text + content = [[]] + i = 0 + while i < len(text): + if i + len(find_left) < len(text) and text[i : i + len(find_left)] == find_left: + content.append([]) + content[-1].append(f"\\left{begin}") + i += len(find_left) + elif text[i] == "{": + content.append([]) + content[-1].append(text[i]) + i += 1 + elif text[i] == "}": + content[-1].append( + f"\\right{end}" if content[-1][0].startswith("\\left") else text[i] + ) + content[-2].append("".join(content.pop())) + i += 1 + else: + content[-1].append(text[i]) + i += 1 + return "".join(content[0]) + + def replace_latex_command( - text: str, patterns: Optional[Dict[str, Union[str, Tuple[str, str]]]] = None + text: str, + patterns: Optional[Dict[str, Union[str, Tuple[str, str]]]] = None, + verbose: int = 0, ) -> str: """ Replaces a latex by its raw expression. - Uses pylatexenc.latexwalker - :param text: text :param patterns: one in the known list or None for all + :param verbose: verbosity :return: modified text The default patterns are defined by: @@ -100,8 +144,12 @@ def replace_latex_command( patterns = build_regex() for k, v in patterns.items(): + if verbose: + text0 = text if isinstance(v, str): text = text.replace(f"\\{k}", v) + if verbose and text != text0: + print(f"[replace_latex_command] (1) {k!r}:[{text0}] -> [{text}]") elif isinstance(v, tuple) and len(v) == 2: try: text = re.sub(v[0], v[1], text) @@ -109,6 +157,12 @@ def replace_latex_command( raise AssertionError( f"Unable to replace pattern {v[0]!r} by {v[1]!r} for text={text!r}" ) from e + if verbose and text != text0: + print(f"[replace_latex_command] (2) {k!r}:[{text0}] -> [{text}]") + elif callable(v): + text = v(text) + if verbose and text != text0: + print(f"[replace_latex_command] (3) {k!r}:[{text0}] -> [{text}]") else: raise AssertionError(f"Unable to understand v={v!r} for k={k!r}") return text From a6eb8eec22615fe00c6330abee22082da025cf35 Mon Sep 17 00:00:00 2001 From: xadupre Date: Sat, 29 Mar 2025 11:52:07 +0100 Subject: [PATCH 10/13] fix missing file --- .../ut__main/data/float_and_double_rouding.py | 242 +++++++++++ _unittests/ut__main/data/poulet.py | 178 ++++++++ .../ut__main/data/strategie_avec_alea.rst | 386 ++++++++++++++++++ _unittests/ut__main/test_cmd.py | 2 +- azure-pipelines.yml | 2 +- 5 files changed, 808 insertions(+), 2 deletions(-) create mode 100644 _unittests/ut__main/data/float_and_double_rouding.py create mode 100644 _unittests/ut__main/data/poulet.py create mode 100644 _unittests/ut__main/data/strategie_avec_alea.rst diff --git a/_unittests/ut__main/data/float_and_double_rouding.py b/_unittests/ut__main/data/float_and_double_rouding.py new file mode 100644 index 0000000..daaef20 --- /dev/null +++ b/_unittests/ut__main/data/float_and_double_rouding.py @@ -0,0 +1,242 @@ +""" +Float conversion +================ + +I came up with the following question +:math:`(float64)x < (float64)y \Longrightarrow (float32) x < (float32)y`? +What is the probability this holds? + +""" + +from jyquickhelper import add_notebook_menu + +add_notebook_menu() + + + + +###################################################################### +# Probability (float64)x == (float32)x +# ------------------------------------ + +# Let's evaluate how many time we draw a random double number equal to its +# float conversion. + + +import numpy + +rnd = numpy.random.random(100000000) +rnd.shape, rnd.dtype + +rnd32 = rnd.astype(numpy.float32).astype(numpy.float64) +equal = (rnd == rnd32).sum() +equal + + +###################################################################### +# It is very low. Let's check the reverse is true. + + +rnd32b = rnd32.astype(numpy.float64).astype(numpy.float32) +equal = (rnd32b == rnd32).sum() +equal + + +###################################################################### +# Let's study the distribution of the difference. + + +delta = rnd - rnd32 +numpy.min(delta), numpy.max(delta) + +numpy.min(rnd), numpy.max(rnd) + +import matplotlib.pyplot as plt + +plt.hist(delta, bins=1000); + + +###################################################################### +# We finally check that double operations between float numpers remain +# floats. + + +import random + +for i in range(100000): + i, j = random.randint(0, len(rnd32) - 1), random.randint(0, len(rnd32) - 1) + d32 = numpy.float64(rnd32[i] * rnd32[j]) + d64 = numpy.float64(rnd32[i]) * numpy.float64(rnd32[j]) + if d32 != d64: + raise Exception( + "Issue with somme={0} = {1} + {2}".format( + rnd32[i] + rnd32[j], rnd32[i], rnd32[j] + ) + ) + + +###################################################################### +# Interval length distribution +# ---------------------------- + +# Let's imagine now we want to define an intervalle in which a double is +# converted to the same float. Let's find out about it length. + + +def find_interval(x): + dx = numpy.abs(x - numpy.float32(x)) # usually not zero + dx /= 100 + f = numpy.float32(x) + x1 = x + while numpy.float32(x1) == f: + x1 -= dx + x2 = x + while numpy.float32(x2) == f: + x2 += dx + return x1 + dx, x2 - dx + + +length = numpy.zeros((2000,)) +for i in range(length.shape[0]): + x = rnd[i] + x1, x2 = find_interval(x) + length[i] = x2 - x1 + +min(length), max(length) + +plt.hist(length, bins=50); + + +###################################################################### +# So we can approximate this interval by something like this: + + +ql = numpy.sort(length)[int(length.shape[0] * 0.8)] +ql + + +###################################################################### +# An answer to the initial question +# --------------------------------- + +# Let's estimate +# :math:`\mathbb{P}\left(x_{64} < y_{64} \Longrightarrow x_{32} < y_{32} \; | \; |x-y| \leqslant d\right)` +# ? + + +import pandas + + +def inf_strict(x, y): + f1 = x < y + f2 = numpy.float32(x) < numpy.float32(y) + return f1, f2 + + +def count_events(fct): + rows = [] + for di in range(1, 1001): + d = di * ql / 100 + total = 0 + ok = 0 + rnd = numpy.random.random((2000 * 3,)) + for i in range(0, rnd.shape[0], 3): + s = -1 if rnd[i + 2] < 0.5 else 1 + x, y = rnd[i], rnd[i] + rnd[i + 1] * d * s + f1, f2 = fct(x, y) + if f1: + total += 1 + if f2: + ok += 1 + if (di + 10) % 100 == 0: + print(di, d, ":", ok, total) + rows.append(dict(d=d, ratio=ok * 1.0 / total, total=total)) + + return pandas.DataFrame(rows) + + +df = count_events(inf_strict) +df.head() + +df.plot(x="d", y="ratio") + +df.plot(x="d", y="ratio", logx=True) + + +###################################################################### +# An answer to a similar question: what about not strict comparison? +# ------------------------------------------------------------------ + +# Let's estimate +# :math:`\mathbb{P}\left(x_{64} \leqslant y_{64} \Longrightarrow x_{32} \leqslant y_{32} \; | \; |x-y| \leqslant d\right)` +# ? + + +def inf_equal(x, y): + f1 = x <= y + f2 = numpy.float32(x) <= numpy.float32(y) + return f1, f2 + + +df2 = count_events(inf_equal) +df2.head() + +ax = df.plot(x="d", y="ratio", logx=True, label="<") +df2.plot(x="d", y="ratio", logx=True, label="<=", ax=ax) + +def sup_strict(x, y): + f1 = x > y + f2 = numpy.float32(x) > numpy.float32(y) + return f1, f2 + + +df3 = count_events(sup_strict) +df3.head() + +ax = df.plot(x="d", y="ratio", logx=True, label="<") +df2.plot(x="d", y="ratio", logx=True, label="<=", ax=ax) +df3.plot(x="d", y="ratio", logx=True, label=">", ax=ax) + +def sup_equal(x, y): + f1 = x >= y + f2 = numpy.float32(x) >= numpy.float32(y) + return f1, f2 + + +df4 = count_events(sup_equal) +df4.head() + +ax = df.plot(x="d", y="ratio", logx=True, label="<") +df2.plot(x="d", y="ratio", logx=True, label="<=", ax=ax) +df3.plot(x="d", y="ratio", logx=True, label=">", ax=ax) +df4.plot(x="d", y="ratio", logx=True, label=">=", ax=ax) + +def inf_strict_neg(x, y): + f1 = (-x) >= (-y) + f2 = (-numpy.float32(x)) >= (-numpy.float32(y)) + return f1, f2 + + +dfn = count_events(inf_strict_neg) +dfn.head() + +ax = df.plot(x="d", y="ratio", logx=True, label="<") +dfn.plot(x="d", y="ratio", logx=True, label="-1 x >=", ax=ax) + + +###################################################################### +# Conclusion +# ---------- + +# The result is expected. As soon as two float are rounded to the same +# value, the strict inequality no longer holds. However, if you need to +# write a code which has to handle double and float (in a template for +# example), you should use not strict inequalities. It is easier to +# compare the results but you should read some article like `Is < faster +# than +# <=? `_. +# According to `Processing costs of non-strict versus strict +# comparison `_, ``<`` is +# 5-10% faster than ``<=``. + + diff --git a/_unittests/ut__main/data/poulet.py b/_unittests/ut__main/data/poulet.py new file mode 100644 index 0000000..934cf89 --- /dev/null +++ b/_unittests/ut__main/data/poulet.py @@ -0,0 +1,178 @@ +import math +import random + + +def factorielle(x): + """ + Calcule :math:`x!` de façon récursive. + """ + if x == 0: + return 1 + else: + return x * factorielle(x - 1) + + +def profit(N, X, p, q, s): + """ + Calcule le profit. + + :param N: nombre de poulets vendus + :param X: nombre de poulets achetés + :param p: prix d'achat + :param q: prix de vente + :param s: prix soldé + :return: profit + """ + if X <= N: + return X * (q - p) + else: + return X * (s - p) + N * (q - s) + + +def proba_poisson(lx, i): + """ + Calcule la probabilité :math:`\\pr{X=i}`` + lorsque :math:`X` suit une loi de Poisson de paramètre + :math:`\\lambda`. + """ + return math.exp(-lx) * (lx**i) / factorielle(i) + + +def esperance(X, p, q, s, lx): + """ + Espérance du profit en faisant varier + le nombre de poulet vendus. + + :param X: nombre de poulets achetés + :param p: prix d'achat + :param q: prix de vente + :param s: prix soldé + :param lx: paramètre :math:`\\lambda` + :return: espérance du profit + """ + res = 0.0 + for i in range(lx * 2): + res += profit(float(i), X, p, q, s) * proba_poisson(lx, i) + return res + + +def maximum(p, q, s, lx): + """ + Calcule les espérances de profit pour différents nombres + de poulets achetés. + + :param p: prix d'achat + :param q: prix de vente + :param s: prix soldé + :param lx: paramètre :math:`\\lambda` + :return: liste ``(X, profit)`` + """ + res = [] + for X in range(2 * lx): + r = esperance(X, p, q, s, lx) + res.append((X, r)) + return res + + +def find_maximum(res): + """ + Trouver le couple (nombre de poulets achetés, profit) + lorsque le profit est maximum. + + :param res: résultat de la fonction + :func:`maximum ` + :return: ``(X, profit)`` maximum + """ + m = (0, 0) + for r in res: + if r[1] > m[1]: + m = r + return m + + +def exponentielle(lx): + """ + Simule une loi exponentielle de paramètre :math:`\\lambda`. + """ + u = random.random() + return -1.0 / lx * math.log(1.0 - u) + + +def poisson(lx): + """ + Simule une loi de Poisson de paramètre :math:`\\lambda`. + """ + s = 0 + i = 0 + while s <= 1: + s += exponentielle(lx) + i += 1 + return i - 1 + + +def poisson_melange(params, coef): + """ + Simule une variable selon un mélange de loi de Poisson. + + :param params: liste de paramètre :math:`\\lambda` + :param coef: ``coef[i]`` coefficient associé + à la loi de paramètre ``params[i]`` + :return: valeur simulée + """ + s = 0 + for i, pa in enumerate(params): + p = poisson(pa) + s += p * coef[i] + return s + + +def histogramme_poisson_melange(params, coef, n=100000): + """ + Calcule un histogramme d'un mélange de loi de Poisson. + + :param params: liste de paramètre :math:`\\lambda` + :param coef: ``coef[i]`` coefficient associé + à la loi de paramètre ``params[i]`` + :return: histogramme + """ + h = [0.0 for i in range(4 * max(params))] + for _i in range(n): + x = poisson_melange(params, coef) + if x < len(h): + h[x] += 1 + s = sum(h) + for i in range(len(h)): + h[i] = float(h[i]) / s + return h + + +def f_proba_poisson_melange(): + """ + Wraps function *proba_poisson_melange* to avoid + global variable. + """ + + proba_poisson_melange_tableau = [] + + def local_proba_poisson_melange(params, coef, i): + """ + Calcule la probabilité :math:`\\pr{X=i}`` + lorsque :math:`X` suit un mélange de lois. + + :param params: liste de paramètre :math:`\\lambda` + :param coef: ``coef[i]`` coefficient associé + à la loi de paramètre ``params[i]`` + :return: valeur + """ + if not proba_poisson_melange_tableau: + proba_poisson_melange_tableau.extend( + histogramme_poisson_melange(params, coef) + ) + if i >= len(proba_poisson_melange_tableau): + return 0.0 + return proba_poisson_melange_tableau[i] + + return local_proba_poisson_melange + + +proba_poisson_melange = f_proba_poisson_melange() diff --git a/_unittests/ut__main/data/strategie_avec_alea.rst b/_unittests/ut__main/data/strategie_avec_alea.rst new file mode 100644 index 0000000..817522b --- /dev/null +++ b/_unittests/ut__main/data/strategie_avec_alea.rst @@ -0,0 +1,386 @@ + +.. _l-exemple_optim_alea: + +==================================== +Optimisation avec données aléatoires +==================================== + +.. contents:: + :local: + +Un problème simple +================== + +Un supermarché pourrait vendre en moyenne 80 poulets par +semaine s'il pouvait savoir à l'avance combien de poulets +à acheter pour satisfaire la demainde. En réalité, le magasin +se réapprovisionne une fois par semaine et lorsque la fin de +la semaine arrive, tous les poulets invendus sont soldés et +supposés vendus. Le gérant du supermarché voudrait savoir quel +est le nombre optimal de poulets à commander chaque semaine. +On suppose que le prix d'un poulet à l'achat est :math:`p`, son prix à +la vente est :math:`q>p`, son prix soldé est :math:`s`. Admettons que +le supermarché achète :math:`X` poulets, en vende au mieux :math:`N` non +soldés et :math:`X-N` soldés s'il en reste. Pour calculer son bénéfice +:math:`B`, il faut tenir compte de deux cas et du fait que le +supermarché ne peut pas vendre plus de poulets qu'il n'en a acheté : + +.. math:: + + \begin{array}{ll} + B = X (q-p) & \text{si } N \supegal X \\ + B = N (q-p) + (X-N) (s-p) = X (s-p) + N (q-s) & \text{si } N < X + \end{array} + +On peut réduire ces deux expressions à une seule en utilisant +la fonction indicatrice : + +.. math:: + + B = f(N,X,p,q,s)= X (q-p) \indicatrice{ N \supegal X } + \cro{ X (s-p) + N (q-s)} \indicatrice{ N < X } + +Si :math:`N` était connu avec certitude, il suffirait de +choisir :math:`X=N`, ce serait la réponse optimale mais +le nombre de poulets :math:`N` vendus est inconnu car il +varie chaque semaine. Pour avoir une idée plus précise, le +gérant du supermarché a délibérément acheté trop de poulets +pendant plusieurs semaines. Il s'est aperçu que la variable +aléatoire :math:`N` suit une `loi de Poisson `_ +de paramètre :math:`\lambda = 80`. On connaît seulement la +probabilité que :math:`N` soit égale à une valeur fixée. +La figure suivante montre l'allure de cette distribution. + +.. math:: + + \pr{X=i} = e^{-\lambda} \frac{ \lambda^i}{i!} + +.. image:: images/poisson.png + +Ce graphe répresente la fonction de densité d'une loi de Poisson de paramètre 80. +On observe que le pic est obtenu pour une valeur +proche de 80, c'est la valeur la plus probable. +Ceci signifie que le nombre de poulets achetés le plus probable est 80. + +Comme le nombre de poulets achetés varie d'une semaine à l'autre, +le bénéfice du supermarché varie aussi d'une semaine à l'autre. +Ce que le gérant veut optimiser, c'est la somme de ses profits +sur une année ce qui est équivalent à maximiser la moyenne de +ses profits chaque semaine. Il faut donc chercher à maximiser +l'espérence de la variable aléatoire :math:`B` à :math:`p,q,s` constant +puis à obtenir la valeur :math:`X` ayant mené à ce maximum. + +.. math:: + + \max_X \esp{B} =\max_X \esp{f(N,X,p,q,s)} = \max_X \acc{ \sum_{i=0}^{\infty} f(N,X,p,q,s) \pr{N=i} } + +Etant donné la forme de la fonction :math:`f`, il n'est pas +évident de construire une expression exacte de :math:`X^*` défini par +:math:`\max_X \esp{f(N,X,p,q,s)} = f(N,X^*,p,q,s)`. Comme :math:`l=80`, +d'après la figure précédente, on cherche :math:`X^*` dans l'ensemble +:math:`\acc{0,...,2l=180}`, aller au delà de 180 est inutile +tant la probabilité est faible. Il suffit de calculer :math:`f` pour +chacune de ces valeurs et de prendre celle qui permet d'obtenir +le maximum. Ces calculs longs et répétitifs vont être effectués par +un programme informatique qui sera découpé en fonctions comme ceci : + +.. list-table:: + :widths: 5 10 + :header-rows: 1 + + * - fonction + - objectif + * - :func:`factorielle(x) ` + - calcule :math:`x!` + * - :func:`profit(N,X,p,q,s) ` + - calcule la fonction :math:`f` + * - :func:`proba_poisson(l, i) ` + - calcule la probabilité de Poisson connaissant :math:`\lambda` + et :math:`i` + * - :func:`esperance(X,p,q,s,l) ` + - calcule l'espérance (sa moyenne) de la fonction :math:`f` + * - :func:`maximum(p,q,s,l) ` + - construit une liste de toutes les valeurs de :math:`f`` + * - :func:`find_maximum (res) ` + - cherche le maximum dans la liste retournée par la + fonction :func:`maximum ` + +Le programme obtenu ressemble à :py:mod:`poulet.py `, +les dernières lignes servent à tracer la courbe présentée par la figure qui suit. + +.. runpython:: + :showcode: + + from mlstatpy.garden.poulet import maximum + res = maximum (2,5,1,80) + # res est la courbe affichée plus bas + print(res[:4]) + +.. list-table:: + :widths: auto + :header-rows: 0 + + * - .. image:: images/poissonb.png + - .. image:: images/poissonb2.png + +Cette courbe est celle de l'évolution des profits en fonction du +nombre de poulets commandés. On suppose que +le nombre de poulets achetés suit une loi de Poisson de paramètre 80, +que les poulets sont achetés 2 euros, revendu 5 euros et soldés 1 euros. +Le maximum de 228 euros est obtenu pour 86 poulets. +La seconde courbe montre le résultat dans le cas où les poulets +soldés sont vendus 2 euros +égal au prix des poulets achetés. Le modèle montre ses limites dans ce +cas car il suppose que tous les poulets +soldés seront achetés et que les contraintes de stockage +sont négligeables. + +Modélisation de la demande +========================== + +La représentation de la demande est essentielle, c'est elle qui détermine +le résultat. Il est possible de l'affiner comme par exemple supposer que +certaines personnes achètent deux ou trois poulets et que la somme des +poulets achetés peut être décomposée comme :math:`N = N_1 + 2N_2 + 3N_3` +où :math:`N_i` est le nombre de personnes achetant :math:`i` +poulets. Dans ce cas, ce n'est plus :math:`N` qui suit une loi de +Poisson mais :math:`N_1`, :math:`N_2`, :math:`N_3` qui suivent chacune +des lois de Poisson de paramètres différents dont il faudra estimer +les paramètres. + +Cette modification implique l'écriture d'une fonction +:func:`proba_poisson_melange ` +au lieu de :func:`proba_poisson `. +La demande n'est plus une loi connue mais un mélange de lois connues +dont la densité n'a pas d'expression connue : il faut la tabuler. +Pour cela, on utilise deux propriétés sur les lois exponentielles. + +.. mathdef:: + :title: simulation d'une loi quelconque + :tag: Théorème + :lid: theoreme_inversion_variable + + Soit :math:`F=\int f` une fonction de répartition de densité + :math:`f` vérifiant :math:`f > 0`, soit :math:`U` une variable + aléatoire uniformément distribuée sur :math:`\cro{0,1}` alors + :math:`F^{-1}(U)` est variable aléatoire de densité :math:`f`. + +La démonstration est courte. +Soit :math:`X` une variable aléatoire de densité :math:`f`, +par définition, :math:`\pr{X \leqslant x} = F(x)`. Soit :math:`U` une +variable aléatoire uniformément distribué sur :math:`\cro{0,1}`, alors : + +.. math:: + :nowrap: + + \begin{eqnarray*} + \forall u \in \cro{0,1}, \; \pr{U \leqslant u} &=& u \\ + \Longleftrightarrow \pr{F^{-1}(U)\leqslant F^{-1}(u)} &=& u \\ + \Longleftrightarrow \pr{F^{-1}(U)\leqslant F^{-1}(F(t))} &=& F(t) \\ + \Longleftrightarrow \pr{F^{-1}(U)\leqslant t} &=& F(t) + \end{eqnarray*} + +Si la fonction :math:`F` n'est pas strictement croissante, +on pourra prendre :math:`F^{-1}(t) = \inf\acc{ u \sac F(u) \supegal t}`. +Ce théorème sera appliqué à une loi exponentielle de paramètre +:math:`\lambda`. La densité d'une telle loi est +:math:`f(x) = \lambda \exp{- \lambda x}`, +:math:`F(x) = \int_0^x f(t)dt = 1 - \exp^{- \lambda x}`. +On en déduit que :math:`F^{-1}(t) = -\frac{ \ln(1-t)}{\lambda}`, +par conséquent : :math:`-\frac{ \ln(1-U)}{\lambda}` suit une loi +exponentielle de paramètre :math:`\lambda` si :math:`U` est +une loi uniforme sur :math:`\cro{0,1}`. + +.. mathdef:: + :title: simulation d'une loi de Poisson + :tag: Théorème + :lid: theoreme_simulation_poisson + + On définit une suite infinie :math:`(X_i)_i>0` de loi + exponentielle de paramètre :math:`\lambda`. On définit ensuite + la série de variables aléatoires :math:`S_i = \sum_{k=1}^{i} X_k` + et enfin :math:`N(t) = \inf \acc{ i \sac S_i > t}`. + Alors la variable aléatoire :math:`N(t)` suit une loi + de Poisson de paramètre :math:`\lambda t`. + +La loi exponentielle est souvent utilisée pour modéliser le temps +d'attente d'un événement comme le temps d'attente d'un métro +une fois sur le quai. On l'utilise aussi pour modéliser la +durée de vie d'un outil, d'une ampoule par exemple. La loi de +Poisson peut par exemple modéliser le nombre d'ampoules nécessaire +pour éclairer une pièce sur une certaine durée. +Avant de démontrer le théorème, il faut définir d'abord la +`loi Gamma `_. +On pose au préalable :math:`\Gamma(\alpha) = \int_0^{\infty} u^{\alpha-1}e^{-u}du`. +Une variable aléatoire de loi Gamma de paramètres :math:`\pa{\alpha,\lambda}` +a pour densité : :math:`f(x) = \frac{\lambda^{\alpha}} {\Gamma(\alpha)}t^{\alpha-1}e^{-\lambda t}`. +La fonction :math:`\Gamma` vérifie une propriété utile par la suite : +:math:`\forall n \in \N^*, \, \Gamma(n) = (n-1)!`. + +.. mathdef:: + :title: somme de loi exponentielle iid + :tag: Théorème + :lid: theoreme_convolution_poisson + + Soit :math:`X_1,...,X_n` :math:`n` variables aléatoires indépendantes + et identiquement distribuées de loi :math:`Exp(\lambda)` alors la + somme :math:`\sum_{k=1}^n X_k` suit une loi :math:`Gamma(n,\lambda)`. + +La démonstration utilise l'unicité de la fonction caractéristique +:math:`\esp{e^{iX}}`. Il suffit de démonstrer que la fonction caractéristique +de la somme est celle d'une loi Gamma. On suppose que +:math:`X_1,...,X_n` suivent des lois exponentielles de paramètre +:math:`\lambda` et :math:`Y` suit une loi :math:`Gamma(n,\lambda)`. + +.. math:: + :nowrap: + + \begin{eqnarray*} + \esp{\exp\pa{i\sum_{k=1}^n X_k}} &=& \prod_{k=1}^n \esp{e^{iX_k}} \\ + &=& \cro{ \int_0^{\infty} \lambda e^{ix} e^{-\lambda x} dx}^n = \lambda^n \cro{\int_0^{\infty} e^{(i-\lambda) x} dx}^n \\ + &=& \lambda^n \cro{ - \frac{1}{(i-\lambda)} }^n = \cro{ \frac{ \lambda} { \lambda - i} }^n \\ + \esp{e^{iY}} &=& \int_0^{\infty} \frac{\lambda^{n}} {\Gamma(n)}t^{n-1}e^{-\lambda t} e^{it} dt = + \int_0^{\infty} \frac{\lambda^{n}} {\Gamma(n)}t^{n-1}e^{ (i-\lambda) t} dt \\ + &=& \frac{\lambda^{n}} {\Gamma(n)} \frac{\Gamma(n)}{(i-\lambda)^{n}} = \cro{ \frac{ \lambda} { \lambda - i} }^n + \end{eqnarray*} + +Ces lignes démontrent le théorème. +On démontre maintenant :ref:`simulation d'une loi de Poisson `. +La démonstration repose sur le fait que +:math:`\pr{N(t) \supegal n} \Longleftrightarrow \pr{S_n \leqslant t}`. +On en déduit que : + +.. math:: + + \pr{N(t) = n} = \pr{N(t) \supegal n} - \pr{N(t) \supegal n+1} = \pr{S_n \leqslant t} - \pr{S_{n+1} \leqslant t} + +Or d'après le théorème :ref:`somme de loi exponentielle iid `, +:math:`S_n` suit une loi :math:`Gamma(n,\lambda)`. + +.. math:: + :nowrap: + + \begin{eqnarray*} + \pr{N(t) = n} &=& \int_0^t \frac{\lambda^n} {\Gamma(n)}u^{n-1}e^{-\lambda u} du - + \int_0^t \frac{\lambda^{n+1}} {\Gamma(n+1)}u^{n}e^{-\lambda u} du \\ + &=& \int_0^t \cro{ \frac{\lambda^n} {(n-1)!} u^{n-1} e^{-\lambda u} - \frac{\lambda^{n+1}} {n!}u^{n} e^{-\lambda u} } du \\ + &=& \cro{ \frac{ \lambda^n}{n!} u^n e^{-\lambda u} }_0^t = e^{-\lambda t} \frac{ (\lambda t)^n}{n!} + \end{eqnarray*} + +Il suffit d'utiliser ce théorème pour simuler une loi de Poisson de +paramètre :math:`\lambda`, ce que fait la fonction +:func:`poisson ` suivante : + +.. runpython:: + :showcode: + + import random + import math + + def exponentielle(l): + u = random.random () + return -1.0 / l * math.log(1.0 - u) + + def poisson(l) : + s = 0 + i = 0 + while s <= 1: + s += exponentielle(l) + i += 1 + return i-1 + + print(poisson(2)) + +On vérifie que cette méthode de simulation permet de retrouver +les résultats théoriques. Pour cela, on effectue 1000 tirages d'une +variable suivant une loi de Poisson avec :math:`\lambda=10` +puis on compte le nombre de fois qu'on obtient chaque entier compris +entre 0 et 40. La figure qui suit permet de comparer les résultats obtenus. + +.. image:: images/poishis.png + +Comparaison entre une fonction de densité estimée +empiriquement pour la loi de Poisson de paramètre +:math:`\lambda=10` et sa densité théorique +:math:`f(i) = e^{-\lambda} \frac{ \lambda^i}{i!}`. + +On cherche maintenant à calculer les probabilités +:math:`\pr{N = i}` sachant que :math:`N = N_1 + 2 N_2 + 3 N_3` +et :math:`N_1 \sim \mathcal{P}(48)`, :math:`N_2 \sim \mathcal{P}(10)`, +:math:`N_3 \sim \mathcal{P}(4)`. L'addition de deux lois de Poisson +indépendantes est une loi de Poisson. En revanche, si :math:`N_1` +suit une loi de Poisson, :math:`2N_1` ne suit pas une loi de Poisson. +:math:`2N_1` est une variable paire, c'est une propriété qui n'est +jamais vérifiée par une loi de Poisson. +Il n'existe pas d'expression évidente pour la densité du mélange :math:`N`, +il faut donc simuler cette variable. C'est l'objectif de la fonction +:func:`poisson_melange `. +De la même manière, on estime l'histogramme du mélange avec cette fois-ci +un plus grand nombre de tirages (10000) pour aboutir +à la figure suivante. + +.. list-table:: + :widths: auto + :header-rows: 0 + + * - .. image:: images/poishist2.png + - .. image:: images/poishist3.png + +Comparaison entre une fonction de densité estimée empiriquement +pour un mélange de loi Poisson :math:`N = N_1 + 2 N_2 + 3 N_3` +vérifiant :math:`N_1 \sim \mathcal{P}(48)`, +:math:`N_2 \sim \mathcal{P}(10)`, :math:`N_3 \sim \mathcal{P}(4)` +avec la densité de la loi de Poisson de paramètre :math:`\lambda=80=48+2*10+3*4`. +Il apparaît que ce sont deux densités différentes, celle du mélange +étant plus applatie. La seconde image montre ce qu'on obtient lorsque +le nombre de tirages n'est pas assez important. + +On utilise ces éléments pour modéliser la demande de poulets +selon ce mélange de lois Poisson. Le premier programme est modifié +pour aboutir au suivant. + +.. image:: images/poulet10.png + +Dans le cas du mélange de lois Poisson, +le maximum est cette-fois ci obtenu pour 87 poulets et est +de 225 euros. Ces résultats sont légèrement différents +de ceux obtenus par une simple loi Poisson (80). + +Variations saisonnières et prolongations +======================================== + +Les paragraphes précédents supposent que la demande est constante +et ne dépend pas des saisons. Cette affirmation est peut-être +vraie en ce concerne les poulets mais ce n'est certainement pas +le cas des huîtres qui sont traditionnellement consommées en décembre. +Appliqué à l'exemple des poulets décrits dans cet énoncé, la loi de Poisson +appliquée à la consommation dépend maintenant de la semaine. + +Tenir compte de la saisonnalité n'est pas forcément un problème de +modélisation mais plutôt d'estimation. Au lieu d'avoir une seule +consommation moyenne, il y a en aura maintenant 52. Ceci implique d'avoir +des données en nombre suffisant pour estimer les paramètres du modèle : +la précision des résultats dépend de celle de l'estimation. Il est possible +d'estimer séparément les variations saisonnières et la demande elle-même +mais la présentation de ces techniques dépassent le cadre de ce livre, il +est préférable de se reporter à [Gouriéroux1983]_ ou [Saporta2006]_. + +Les poulets soldés ne sont pas plus mauvais que les poulets +non soldés bien que la date de péremption soit certainement plus rapprochée +de la date d'achat. On suppose qu'un gérant concurrent de ce supermarché +a eu vent de la technique d'optimisation du magasin, il connaît également +le prix du poulet et son prix soldé. Il a également accès au prix d'achat +puisqu'il se fournit chez les mêmes agriculteurs. Il lui reste à +connaître le nombre de poulets commandés et une estimation de la demande +pour savoir si les poulets de son concurrents se vendent mieux que les siens. +Il se rend dans le supermarché concurrent tous les jours où les poulets +sont soldés et les comptent. Il voudrait pouvoir en déduire le nombre de poulets vendus. + +Bibliographie +============= + +.. [Gouriéroux1983] Analyse des séries temporelles, + Christian Gouriéroux, Alain Monfort, + Editions Economica + +.. [Saporta2006] Probabilités, analyse des données et statistique, + Gilbert Saporta, Editions Technip diff --git a/_unittests/ut__main/test_cmd.py b/_unittests/ut__main/test_cmd.py index 0f13721..24016da 100644 --- a/_unittests/ut__main/test_cmd.py +++ b/_unittests/ut__main/test_cmd.py @@ -18,7 +18,7 @@ def test_convert(self): expected = os.path.join(data, "float_and_double_rouding.py") self.assertExists(expected) - @hide_stdout() + #@hide_stdout() def test_latex(self): data = os.path.join(os.path.dirname(__file__), "data") folder = "test_latex" diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0160f99..e08f283 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -4,7 +4,7 @@ jobs: vmImage: 'ubuntu-latest' strategy: matrix: - Python311-Linux: + Python312-Linux: python.version: '3.12' maxParallel: 3 From b9d09fe8d7aae0a572e19e873542207ce82e7467 Mon Sep 17 00:00:00 2001 From: xadupre Date: Sat, 29 Mar 2025 11:53:40 +0100 Subject: [PATCH 11/13] black --- _unittests/ut__main/test_cmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_unittests/ut__main/test_cmd.py b/_unittests/ut__main/test_cmd.py index 24016da..0f13721 100644 --- a/_unittests/ut__main/test_cmd.py +++ b/_unittests/ut__main/test_cmd.py @@ -18,7 +18,7 @@ def test_convert(self): expected = os.path.join(data, "float_and_double_rouding.py") self.assertExists(expected) - #@hide_stdout() + @hide_stdout() def test_latex(self): data = os.path.join(os.path.dirname(__file__), "data") folder = "test_latex" From 1b41fb99c857260d3e672c2a3702466bcfc3a614 Mon Sep 17 00:00:00 2001 From: xadupre Date: Sat, 29 Mar 2025 12:09:13 +0100 Subject: [PATCH 12/13] documentation' --- .github/workflows/documentation.yml | 8 ++++---- _doc/conf.py | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 1e6e1ea..3a67c85 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -77,9 +77,9 @@ jobs: grep ERROR doc.txt exit 1 fi - if [[ $(grep WARNING doc.txt) ]]; then + if [[ $(grep WARNING doc.txt | grep -v 'term not in glossary') ]]; then echo "Documentation produces warnings." - grep WARNING doc.txt + grep WARNING doc.txt | grep -v 'term not in glossary' exit 1 fi @@ -96,9 +96,9 @@ jobs: grep ERROR doc.txt exit 1 fi - if [[ $(grep WARNING doc.txt) ]]; then + if [[ $(grep WARNING doc.txt | grep -v 'term not in glossary') ]]; then echo "Documentation produces warnings." - grep WARNING doc.txt + grep WARNING doc.txt | grep -v 'term not in glossary' exit 1 fi diff --git a/_doc/conf.py b/_doc/conf.py index 52dc023..ac33f9f 100644 --- a/_doc/conf.py +++ b/_doc/conf.py @@ -82,6 +82,8 @@ nitpick_ignore = [ ("py:class", "False"), ("py:class", "True"), + ("py:class", "SphinxPostTransform"), + ("py:meth", "Builder.get_relative_uri"), ] nitpick_ignore_regex = [ @@ -89,6 +91,7 @@ ("py:func", ".*[.]PyCapsule[.].*"), ("py:func", ".*numpy[.].*"), ("py:func", ".*scipy[.].*"), + ("py:meth", "Builder[.].*"), ] intersphinx_mapping = { From 91a2ed0159a15675987c546a82afacbe0ec56b47 Mon Sep 17 00:00:00 2001 From: xadupre Date: Sat, 29 Mar 2025 12:15:27 +0100 Subject: [PATCH 13/13] add missing pandoc --- azure-pipelines.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e08f283..abfd50d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -15,6 +15,8 @@ jobs: architecture: 'x64' - script: sudo apt-get update displayName: 'AptGet Update' + - script: sudo apt-get install -y pandoc + displayName: 'Install Pandoc' - script: sudo apt-get install -y graphviz displayName: 'Install Graphviz' - script: python -m pip install --upgrade pip setuptools wheel