diff --git a/doc/ext/notebook.py b/doc/ext/notebook.py index 6507020c..c062585b 100644 --- a/doc/ext/notebook.py +++ b/doc/ext/notebook.py @@ -29,13 +29,43 @@ sample = """{ }""" +def remove_continuous_duplicates(code): + """ Remove duplicates of elements appearing consecutively. + + Parameters + ---------- + code : list of str + + Returns + ------- + modified_code : list of str + + Notes + ----- + We create a new list and add elements to it which do not have + duplicates appearing consecutively. + One use case here, + 'import xyz\n\n\n print 2' becomes 'import xyz\n print 2' + + """ + modified_code = [] + modified_code = [self.code[i] for i in range(len(self.code)) if i == 0 or self.code[i] != self.code[i-1]] + return modified_code + + class Notebook(): """ - Notebook object for generating an IPython notebook + Notebook object for generating an IPython notebook, from an example Python file. + + Parameters + ---------- + example_file : str + Path for example file. + """ - def __init__(self, sample_notebook_path, example_file): + def __init__(self, example_file): # Object variables, gives the ability to personalise per object # cell type code self.cell_code = { @@ -59,7 +89,7 @@ class Notebook(): } self.cell_type = {'input': self.cell_code, 'source': self.cell_md} - self.keys = {'input_code': 'input', 'input_markdown': 'source'} + self.valuetype_to_celltype = {'code': 'input', 'markdown': 'source'} with open(example_file, 'r') as pythonfile: self.template = json.loads(sample) self.code = pythonfile.readlines() @@ -67,32 +97,64 @@ class Notebook(): # this aids in extraction of text segments self.code.append('\n') - def fetchkey(self, type_of_value): - """ Returns the key required for insertion into notebook, - based on the type of value. - """ - return self.keys[type_of_value] + def fetch_key(self, type_of_value): + """ Find the key required for insertion into notebook. - def filter_continuous_duplication(self): - """ Clusters multiple '\n's into one. - For ex - 'import xyz\n\n\n print 2' becomes 'import xyz\n print 2' """ - modified_code = [] - modified_code = [self.code[i] for i in range(len(self.code)) if i == 0 or self.code[i] != self.code[i-1]] - return modified_code + Parameters + ---------- + type_of_value : str + Type of data, to be inserted in a cell. + + Returns + ------- + str + Key which reflects what is the cell type. + + Notes + ----- + type_of_value is either, 'code', which maps to cell of type + code('input') or 'markdown', which maps to cell of type markdown('source'). - def addcell(self, segment_number, value, type_of_value='input_code'): - """ Adds a notebook cell, by updating the json template. - Cell differs with type of value. """ - if type_of_value in ['input_markdown', 'input_code']: - key = self.fetchkey(type_of_value) + return self.valuetype_to_celltype[type_of_value] + + def add_cell(self, segment_number, value, type_of_value='code'): + """ Adds a notebook cell. + + Parameters + ---------- + segment_number : int + Newline separated sections in example file, are segments. + Code and markdown written together in such a section are, + treated as different segments. Each cell has content from + one section. + value : str + The actual content to be saved in the cell. + type_of_value : str, optional + The type of content in the segment. + The default value will add a cell of type code. + + Notes + ----- + The cell is only added in the notebook if the segment is of type, + markdown or code. + + """ + if type_of_value in ['markdown', 'code']: + key = self.fetch_key(type_of_value) self.template["worksheets"][0]["cells"].append(copy.deepcopy(self.cell_type[key])) self.template["worksheets"][0]["cells"][segment_number][key] = value - def json(self, notebook_path): - """ Writes the template to file (json) """ - with open(notebook_path, 'w') as output: - json.dump(self.template, output, indent=2) + def json(self): + """ Dumps the template JSON to string. + + Returns + ------- + str + The template JSON converted to a string with a two char indent. + + """ + return json.dump(self.template, indent=2) def python_to_notebook(example_file, notebook_dir, notebook_path): @@ -100,23 +162,22 @@ def python_to_notebook(example_file, notebook_dir, notebook_path): Parameters ---------- - example_file : 'str' - path for source Python file - notebook_dir : 'str' - directory for saving the notebook files - notebook_path : 'str' - path for saving the notebook file (includes the filename) - """ - sample_notebook_path = notebook_dir.pjoin('sample.ipynb') + example_file : str + Path for source Python file. + notebook_dir : str + Directory for saving the notebook files. + notebook_path : str + Path for saving the notebook file (includes the filename). - nb = Notebook(sample_notebook_path, example_file) + """ + nb = Notebook(example_file) segment_number = 0 segment_has_begun = True docstring = False source = [] - modified_code = nb.filter_continuous_duplication() + modified_code = remove_continuous_duplicates(nb.code) for line in modified_code: # A linebreak indicates a segment has ended. @@ -127,15 +188,15 @@ def python_to_notebook(example_file, notebook_dir, notebook_path): segment_number += 1 # we've found text segments within the docstring if docstring is True: - nb.addcell(segment_number, source, 'input_markdown') + nb.add_cell(segment_number, source, 'markdown') else: - nb.addcell(segment_number, source, 'input_code') + nb.add_cell(segment_number, source, 'code') source = [] # if it's a comment elif line.strip().startswith('#'): segment_number += 1 line = line.strip(' #') - nb.addcell(segment_number, line, 'input_markdown') + nb.add_cell(segment_number, line, 'markdown') elif line == '"""\n': if docstring is False: docstring = True @@ -146,10 +207,11 @@ def python_to_notebook(example_file, notebook_dir, notebook_path): # Write leftover docstring if any left if source: segment_number += 1 - nb.addcell(segment_number, source, 'input_markdown') + nb.add_cell(segment_number, source, 'markdown') source = [] else: # some text segment is continuing, so add to source source.append(line) - nb.json(notebook_path) + with open(notebook_path, 'w') as output: + output.write(nb.json(notebook_path))