def test_run_tutorial(path): """ There are a lot of examples in tutorial, and all of them should be working. Notes ----- IPython notebook is converted to Python script, so tqdm bars and plotting is removed. """ # pylint: disable=exec-used with warnings.catch_warnings(): warnings.simplefilter("ignore") from nbconvert import PythonExporter # pylint: disable=import-outside-toplevel code, _ = PythonExporter().from_filename(path) code_ = [] for line in code.split('\n'): if not line.startswith('#'): if not any(bs in line for bs in BAD_PREFIXES): line = line.replace("bar='notebook'", "bar=False") line = line.replace("in tqdm_notebook", "in ") code_.append(line) code = '\n'.join(code_) exec(code, {})
def test_run_tutorial(): """ There are a lot of examples in tutorial, and all of them should be working. Notes ----- IPython notebook is converted to Python script, so tqdm bars and plotting is removed. """ # pylint: disable=exec-used tutorials_dir = './../../examples/tutorials/' notebook = '09_solving_PDE_with_NN.ipynb' file = tutorials_dir + notebook with warnings.catch_warnings(): warnings.simplefilter("ignore") from nbconvert import PythonExporter code, _ = PythonExporter().from_filename(file) code_ = [] for line in code.split('\n'): if not line.startswith('#'): if not any(bs in line for bs in BAD_PREFIXES): code_.append(line.replace('in tqdm_notebook', 'in ')) code = '\n'.join(code_) exec(code, {})
def test_run_notebooks(path, microbatch, device): """ There are a lot of examples in different notebooks, and all of them should be working. Parameters ---------- path : str Location of notebook to run. microbatch : int or None If None, then no microbatch is applied. If int, then size of microbatch used. device : str or None If None, then default device behaviour is used. If str, then any option of device configuration from :class:`.tf.TFModel` is supported. Notes ----- `device` is moved to separate parameter in order to work properly with `parametrize`. """ # pylint: disable=exec-used if path.startswith(TUTORIALS_DIR) and 'CPU' not in device: pytest.skip("Tutorials don't utilize device config.") with warnings.catch_warnings(): warnings.simplefilter("ignore") from nbconvert import PythonExporter code, _ = PythonExporter().from_filename(path) code_ = [] for line in code.split('\n'): if not line.startswith('#'): flag = sum([name in line for name in BAD_PREFIXES]) if flag == 0: code_.append(line) code = '\n'.join(code_) exec(code, {'MICROBATCH': microbatch, 'DEVICE': device})
def pylint_notebook(path=None, options='', printer=print, ignore_comments=True, ignore_codes=None, keep_script=False, return_report=False): """ Run pylint on entire Jupyter notebook. Under the hood, the notebook is converted to regular `.py` script, special IPython commands like magics removed, and then pylint is executed. If run outside Jupyter notebook, returns 1. Parameters ---------- path : str, optional Path to run linter on. If not provided, the callee notebook is linted. options : str Additional flags for linter execution, for example, the pylint configuration options. printer : callable Method for displaying results. ignore_comments : bool Whether to ignore markdown cells and comments in code. ignore_codes : sequence Pylint errors to ignore. By default, `invalid-name`, `import-error` and `wrong-import-position` are disabled. keep_script : bool Whether to keep temporal `.py` file after command execution. return_report : bool If True, then this function returns the string representation of produced report. If False, then 0 is returned. """ if not in_notebook(): return 1 from nbconvert import PythonExporter from pylint import epylint as lint path = path or get_notebook_path() options = options if options.startswith(' ') else ' ' + options ignore_codes = ignore_codes or [ 'invalid-name', 'import-error', 'wrong-import-position' ] # Convert the notebook contents to raw string without outputs code, _ = PythonExporter().from_filename(path) # Unwrap code lines from line/cell magics code_list = [] cell_codes, cell_counter = [], 0 cell_code_lines, cell_code_counter = [], 1 for line in code.split('\n'): # Line magics: remove autoreload if line.startswith('get_ipython().run_line_magic'): if 'autoreload' in line: line = '' else: line = line[line.find(',') + 3:-2] # Cell magics: contain multiple lines if line.startswith('get_ipython().run_cell_magic'): line = line[line.find(',') + 1:] line = line[line.find(',') + 3:-2] lines = line.split('\\n') else: lines = [line] # Update all the containers for part in lines: code_list.append(part) cell_codes.append(cell_counter) cell_code_lines.append(cell_code_counter) cell_code_counter += 1 if line.startswith('# In['): cell_counter += 1 cell_code_counter = 0 code = '\n'.join(code_list) # Create temporal file with code, run pylint on it temp_name = os.path.splitext(path)[0] + '.py' with open(temp_name, 'w') as temp_file: temp_file.write(code) pylint_stdout, pylint_stderr = lint.py_run(temp_name + options, return_std=True) errors = pylint_stderr.getvalue() report = pylint_stdout.getvalue() if errors: printer('Errors \n', errors) # Create a better repr of pylint report: remove markdown-related warnings report_ = [] for error_line in report.split('\n'): if temp_name in error_line: error_line = error_line.replace(temp_name, 'nb') code_line_number = int(error_line.split(':')[1]) code_line = code_list[code_line_number - 1] # Ignore markdown and comments if ignore_comments and code_line.startswith('#'): continue # Ignore codes if sum(code in error_line for code in ignore_codes): continue # Create report message cell_number = cell_codes[code_line_number - 1] cell_code_number = cell_code_lines[code_line_number - 1] - 1 error_code = error_line[error_line.find('(') + 1:error_line.find('(') + 6] error_msg = error_line[error_line.find(')') + 2:] report_msg = f'Cell {cell_number}, line {cell_code_number}, error code {error_code}:' report_msg += f'\nPylint message: {error_msg}\nCode line ::: {code_line}\n' report_.append(report_msg) if 'rated' in error_line: report_.insert(0, error_line.strip(' ')) report_.insert(1, '-' * (len(error_line) - 1)) report_.insert(2, '') printer('\n'.join(report_)) # Cleanup if not keep_script: os.remove(temp_name) if return_report: return '\n'.join(report_) return 0