def run_code(code, code_path, ns=None, function_name=None): """ Import a Python module from a path, and run the function given by name, if function_name is not None. """ # Change the working directory to the directory of the example, so # it can get at its data files, if any. Add its path to sys.path # so it can import any helper modules sitting beside it. if six.PY2: pwd = os.getcwdu() else: pwd = os.getcwd() old_sys_path = list(sys.path) if setup.config.plot_working_directory is not None: try: os.chdir(setup.config.plot_working_directory) except OSError as err: raise OSError(str(err) + '\n`plot_working_directory` option in' 'Sphinx configuration file must be a valid ' 'directory path') except TypeError as err: raise TypeError(str(err) + '\n`plot_working_directory` option in ' 'Sphinx configuration file must be a string or ' 'None') sys.path.insert(0, setup.config.plot_working_directory) elif code_path is not None: dirname = os.path.abspath(os.path.dirname(code_path)) os.chdir(dirname) sys.path.insert(0, dirname) # Reset sys.argv old_sys_argv = sys.argv sys.argv = [code_path] # Redirect stdout stdout = sys.stdout if six.PY3: sys.stdout = io.StringIO() else: sys.stdout = cStringIO.StringIO() # Assign a do-nothing print function to the namespace. There # doesn't seem to be any other way to provide a way to (not) print # that works correctly across Python 2 and 3. def _dummy_print(*arg, **kwarg): pass try: try: code = unescape_doctest(code) if ns is None: ns = {} if not ns: if setup.config.plot_pre_code is None: six.exec_(six.text_type("import numpy as np\n" + "from matplotlib import pyplot as plt\n"), ns) else: six.exec_(six.text_type(setup.config.plot_pre_code), ns) ns['print'] = _dummy_print if "__main__" in code: six.exec_("__name__ = '__main__'", ns) code = remove_coding(code) six.exec_(code, ns) if function_name is not None: six.exec_(function_name + "()", ns) except (Exception, SystemExit) as err: raise PlotError(traceback.format_exc()) finally: os.chdir(pwd) sys.argv = old_sys_argv sys.path[:] = old_sys_path sys.stdout = stdout return ns