# -*- coding: utf-8 -*-
"""
Some automation helpers to test notebooks and check they are still working fine.
:githublink:`%|py|6`
"""
import os
from pyquickhelper.loghelper import noLOG
from pyquickhelper.ipythonhelper import execute_notebook_list
import pyensae
[docs]def ls_notebooks(subfolder):
"""
Lists the notebooks in a particular subfolder.
:param subfolder: subfolder (related to this module)
:return: list of files
:githublink:`%|py|18`
"""
this = os.path.abspath(os.path.dirname(__file__))
docnote = os.path.join(
this,
"..",
"..",
"..",
"_doc",
"notebooks",
subfolder)
notes = [
os.path.normpath(
os.path.join(
docnote,
_)) for _ in os.listdir(docnote)]
keepnote = []
for note in notes:
ext = os.path.splitext(note)[-1]
if ext != ".ipynb":
continue
keepnote.append(note)
return keepnote
[docs]def get_additional_paths():
"""
Returns a list of paths to add before running the notebooks,
paths to :epkg:`pyquickhelper`, :epkg:`pyensae`.
:return: list of paths
:githublink:`%|py|49`
"""
import pyquickhelper
import jyquickhelper
addpath = [os.path.dirname(pyquickhelper.__file__),
os.path.dirname(pyensae.__file__),
os.path.dirname(jyquickhelper.__file__),
os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."),
]
addpath = [os.path.normpath(os.path.join(_, "..")) for _ in addpath]
return addpath
[docs]def clean_function_notebook(code):
"""
Cleans cells when unittesting notebooks.
:param code: cell content
:return: modified code
:githublink:`%|py|67`
"""
code = code.replace(
'run_cmd("exemple.xlsx"',
'skip_run_cmd("exemple.xlsx"')
skip = ["faire une chose avec la probabilité 0.7",
"# déclenche une exception",
"# pour lancer Excel",
"for k in list_exercice_1 :",
"return ....",
"return [ .... ]",
"def __init__(self, ...) :",
"if random.random() <= 0.7 :",
"dictionnaire_depart.items() [0]",
"iterateur(0,10) [0]",
"# ...... à remplir",
'String.Join(",", a.Select(c=>c.ToString()).ToArray())',
"# elle n'existe pas encore",
"from ggplot import *",
# ggplot calls method show and it opens window blocking the offline
# execution
]
rep = [("# ...", "pass # "),
("%timeit", "#%timeit"),
]
spl = ["# ......",
"# elle n'existe pas encore",
]
for s in skip:
if s in code:
return ""
for s in spl:
if s in code:
code = code.split(s)[0]
for s in rep:
code = code.replace(s[0], s[1])
return code
[docs]def execute_notebooks(folder, notebooks, filter, # pylint: disable= W0622
clean_function=None,
fLOG=noLOG,
deepfLOG=noLOG,
valid_cell=None):
"""
Executes a list of notebooks.
:param folder: folder
:param notebooks: list of notebooks
:param filter: function which validate the notebooks
:param clean_function: cleaning function to apply to the code before running it
:param fLOG: logging function
:param deepfLOG: logging function used to run the notebook
:param valid_cell: to disable the execution of a cell
:return: dictionary tuple (statistics, { notebook_file: (isSuccess, outout) })
The signature of function ``filter`` is::
def filter( i, filename) : return True or False
:githublink:`%|py|130`
"""
def _valid_cell(cell):
if valid_cell is not None:
if not valid_cell(cell):
return False
if "%system" in cell:
return False
if "df.plot(...)" in cell:
return False
if 'df["difference"] = ...' in cell:
return False
if 'print(next(it))' in cell:
return False
return True
addpaths = get_additional_paths()
if filter:
notebooks = [_ for i, _ in enumerate(notebooks) if filter(i, _)]
if len(notebooks) == 0:
raise ValueError("Empty list of notebooks.")
return execute_notebook_list(
folder, notebooks, fLOG=fLOG, valid=_valid_cell, additional_path=addpaths)