def load_cells_params(self): if self.args.cells: # module and function name passed with args.cells parameter pathname, func_name = self.set_cells(self.args.cells) logging.info('Loading cells from {}'.format(self.args.cells)) uid = '{}:{}'.format(os.path.abspath(pathname), func_name) self.cells_name = self.args.cells else: # Notebook class extended, .cells method contains the target cell # Let's make sure that this is the case... if self.__class__ == Notebook: fatal( 'Notebook class not extended and cells parameter is missing' ) logging.info('Loading notebook {}'.format(self.__class__.__name__)) uid = '{}:{}'.format( os.path.abspath(inspect.getfile(self.__class__)), self.__class__.__name__) # Process parameters passed by custom arguments arg_spec = inspect.getargspec(self.cells) func_params = arg_spec.args # Get default parameters default_params = arg_spec.defaults self.kwargs = {} if default_params: default_args_with_value = dict( zip(func_params[-len(default_params):], default_params)) logging.debug( 'Found default values {}'.format(default_args_with_value)) # Add default values to kwargs self.kwargs.update(default_args_with_value) if not self.args.cells: # self is always present in case of subclassed Notebook, since cells(self, ...) is a method. func_params.remove('self') for param in func_params: self.kwargs[param] = getattr(self.args, param, None) # Process parameters passed with --param if self.args.param: for param in self.args.param: k, v = param.split('=', 1) self.kwargs[k] = v # Check parameters completeness for param in func_params: if self.kwargs[param] is None: fatal('Notebook parameter {} required but not found'.format( param)) logging.info('Parameters: {}'.format(self.kwargs)) self.add(self.cells, **self.kwargs) return uid
def run(self): """ Run notebook as an application :param params: parameters to inject in the notebook :return: """ if not self.args: self.parse_args() added_cells_func = False try: if self.args.with_generate_cellsfunc: self.add_cells_funcion(self.args.cells) added_cells_func = True if self.args.log_level: logging.getLogger().setLevel( logging.getLevelName(self.args.log_level)) logging.debug('Enabled {} logging level'.format( self.args.log_level)) if self.args.import_ipynb: check_isfile(self.args.import_ipynb) logging.info('Loading Jupyter notebook {}'.format( self.args.import_ipynb)) self.nb = nbf.read(self.args.import_ipynb, as_version=4) uid = self.args.import_ipynb else: uid = self.load_cells_params() logging.debug("Unique id: '{}'".format(uid)) logging.info('Disable cache: {}'.format(self.args.disable_cache)) logging.info('Ignore cache: {}'.format(self.args.ignore_cache)) if self.args.export_pynb and not self.args.no_exec: fatal('--export-pynb requires --no-exec') if self.args.kernel: self.set_kernel(self.args.kernel) self.process(uid=uid, add_footer=not self.args.disable_footer, no_exec=self.args.no_exec, disable_cache=self.args.disable_cache, ignore_cache=self.args.ignore_cache) if self.args.export_html: self.export_html(self.args.export_html) if self.args.export_ipynb: self.export_ipynb(self.args.export_ipynb) if self.args.export_pynb: self.export_pynb(self.args.export_pynb) finally: if added_cells_func: self.remove_cells_funcion(self.args.cells)
def run(self): """ Run notebook as an application :param params: parameters to inject in the notebook :return: """ if not self.args: self.parse_args() logging.info(self.long_name) if self.args.debug: logging.getLogger().setLevel(logging.DEBUG) logging.debug('Enabled DEBUG logging level') if self.args.import_ipynb: check_isfile(self.args.import_ipynb) logging.info('Loading Jupyter notebook {}'.format( self.args.import_ipynb)) self.nb = nbf.read(self.args.import_ipynb, as_version=4) uid = self.args.import_ipynb else: uid = self.load_cells_params() logging.debug("Unique id: '{}'".format(uid)) logging.info('Disable cache: {}'.format(self.args.disable_cache)) logging.info('Ignore cache: {}'.format(self.args.ignore_cache)) if self.args.export_pynb and not self.args.no_exec: fatal('--export-pynb requires --no-exec') self.process(uid=uid, no_exec=self.args.no_exec, disable_cache=self.args.disable_cache, ignore_cache=self.args.ignore_cache) if self.args.export_html: self.export_html(self.args.export_html) if self.args.export_ipynb: self.export_ipynb(self.args.export_ipynb) if self.args.export_pynb: self.export_pynb(self.args.export_pynb)
def set_cells(self, cells_location): """ Set self.cells to function :cells in file pathname.py :param cells_location: cells location, format 'pathname.py:cells' :return: """ if ':' in cells_location: pathname, func_name = cells_location.split(':') else: pathname = cells_location func_name = 'cells' check_isfile(pathname) try: self.cells = get_func(func_name, pathname) except SyntaxError as e: fatal(traceback.format_exc(limit=1)) return pathname, func_name
def set_cells(self, cells_location): """ Set self.cells to function :cells in file pathname.py :param cells_location: cells location, format 'pathname.py:cells' :return: """ if ':' in cells_location: pathname, func_name = cells_location.split(':') else: pathname = cells_location func_name = 'cells' check_isfile(pathname) try: self.cells = get_func(func_name, pathname) except Exception as e: logging.error(traceback.format_exc()) fatal("Function '{}' not found in '{}': {}".format( func_name, pathname, e)) return pathname, func_name
def add(self, func, **kwargs): """ Parse func's function source code as Python and Markdown cells. :param func: Python function to parse :param kwargs: variables to inject as first Python cell :return: """ params = set(kwargs.keys()) func_params = set(inspect.getargspec(func).args) # ignore self, which is present when extending Notebook. if 'self' in func_params: func_params.remove('self') if params != func_params: fatal('Params {} not matching cells function params {}'.format( list(params), list(func_params))) lines = inspect.getsourcelines(func)[0][1:] buffer = "" indent_count = None inside_markdown = False return_found = False for line in lines: # remove base indentation of function 'func' if len(line.strip()) > 0: if not indent_count: indent_count = 0 for c in line: if c not in [' ', '\t']: break else: indent_count += 1 line = line[indent_count:] if not inside_markdown and line.strip() == "return": logging.info( 'Encountered "return" statement, ignoring the rest of the notebook.' ) break if line.strip() == "'''": # if md block begin/end, or new cell... if len(buffer.strip()) > 0: if not inside_markdown: # if md block begin: new markdown block! flush buffer self.add_cell_code(buffer) else: # if md block end: markdown block completed! flush buffer self.add_cell_markdown(buffer) buffer = "" inside_markdown = not inside_markdown else: buffer += line if len(buffer.strip()) > 0: if not inside_markdown: self.add_cell_code(buffer) else: self.add_cell_markdown(buffer) if len(kwargs) > 0: # We have parameters to inject into the notebook. # If the first cell is Markdown, assume that is the title and # insert parameters as 2nd cell. Otherwise, as 1st cell. if len(self.nb['cells'] ) > 0 and self.nb['cells'][0].cell_type == 'markdown': self.add_cell_params(kwargs, 1) else: self.add_cell_params(kwargs, 0)