From 2ba22d4d9a3e578f65e8a763120cbf1a786ed127 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Sun, 6 Jan 2019 10:42:12 +0000 Subject: [PATCH 1/6] create NotebookFormatter class --- pandas/io/formats/format.py | 9 ++-- pandas/io/formats/html.py | 95 +++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 50 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index f8ee9c273fd59..f4ce44320bdd4 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -730,10 +730,11 @@ def to_html(self, classes=None, notebook=False, border=None): .. versionadded:: 0.19.0 """ - from pandas.io.formats.html import HTMLFormatter - html_renderer = HTMLFormatter(self, classes=classes, notebook=notebook, - border=border, table_id=self.table_id, - render_links=self.render_links) + from pandas.io.formats.html import HTMLFormatter, NotebookFormatter + Klass = NotebookFormatter if notebook else HTMLFormatter + html_renderer = Klass( + self, classes=classes, border=border, table_id=self.table_id, + render_links=self.render_links) if hasattr(self.buf, 'write'): html_renderer.write_result(self.buf) elif isinstance(self.buf, compat.string_types): diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index 90f1dbe704806..798bcad9dbc2e 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -25,7 +25,7 @@ class HTMLFormatter(TableFormatter): indent_delta = 2 - def __init__(self, formatter, classes=None, notebook=False, border=None, + def __init__(self, formatter, classes=None, border=None, table_id=None, render_links=False): self.fmt = formatter self.classes = classes @@ -36,7 +36,6 @@ def __init__(self, formatter, classes=None, notebook=False, border=None, self.bold_rows = self.fmt.kwds.get('bold_rows', False) self.escape = self.fmt.kwds.get('escape', True) self.show_dimensions = self.fmt.show_dimensions - self.notebook = notebook if border is None: border = get_option('display.html.border') self.border = border @@ -137,48 +136,7 @@ def write_tr(self, line, indent=0, indent_delta=0, header=False, indent -= indent_delta self.write('', indent) - def write_style(self): - # We use the "scoped" attribute here so that the desired - # style properties for the data frame are not then applied - # throughout the entire notebook. - template_first = """\ - """ - template_select = """\ - .dataframe %s { - %s: %s; - }""" - element_props = [('tbody tr th:only-of-type', - 'vertical-align', - 'middle'), - ('tbody tr th', - 'vertical-align', - 'top')] - if isinstance(self.columns, ABCMultiIndex): - element_props.append(('thead tr th', - 'text-align', - 'left')) - if self.show_row_idx_names: - element_props.append(('thead tr:last-of-type th', - 'text-align', - 'right')) - else: - element_props.append(('thead th', - 'text-align', - 'right')) - template_mid = '\n\n'.join(map(lambda t: template_select % t, - element_props)) - template = dedent('\n'.join((template_first, - template_mid, - template_last))) - self.write(template) - def write_result(self, buf): - if self.notebook: - self.write('
') - self.write_style() - self._write_table() if self.should_show_dimensions: @@ -188,9 +146,6 @@ def write_result(self, buf): by=by, cols=len(self.frame.columns))) - if self.notebook: - self.write('
') - buffer_put_lines(buf, self.elements) def _write_table(self, indent=0): @@ -516,3 +471,51 @@ def _write_hierarchical_rows(self, fmt_values, indent): row.insert(self.row_levels + self.fmt.tr_col_num, '...') self.write_tr(row, indent, self.indent_delta, tags=None, nindex_levels=frame.index.nlevels) + + +class NotebookFormatter(HTMLFormatter): + + def write_style(self): + # We use the "scoped" attribute here so that the desired + # style properties for the data frame are not then applied + # throughout the entire notebook. + template_first = """\ + """ + template_select = """\ + .dataframe %s { + %s: %s; + }""" + element_props = [('tbody tr th:only-of-type', + 'vertical-align', + 'middle'), + ('tbody tr th', + 'vertical-align', + 'top')] + if isinstance(self.columns, ABCMultiIndex): + element_props.append(('thead tr th', + 'text-align', + 'left')) + if self.show_row_idx_names: + element_props.append(('thead tr:last-of-type th', + 'text-align', + 'right')) + else: + element_props.append(('thead th', + 'text-align', + 'right')) + template_mid = '\n\n'.join(map(lambda t: template_select % t, + element_props)) + template = dedent('\n'.join((template_first, + template_mid, + template_last))) + self.write(template) + + def write_result(self, buf): + self.write('
') + self.write_style() + super().write_result(buf) + self.write('
') + + buffer_put_lines(buf, self.elements) From 49bcf9bc13fddb0b298dc18550aa9d98ce07c32a Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Sun, 6 Jan 2019 10:58:49 +0000 Subject: [PATCH 2/6] move buffer_put_lines call to format.py --- pandas/io/formats/format.py | 8 ++++---- pandas/io/formats/html.py | 14 ++++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index f4ce44320bdd4..04ec9c56e2d6a 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -732,14 +732,14 @@ def to_html(self, classes=None, notebook=False, border=None): """ from pandas.io.formats.html import HTMLFormatter, NotebookFormatter Klass = NotebookFormatter if notebook else HTMLFormatter - html_renderer = Klass( + html = Klass( self, classes=classes, border=border, table_id=self.table_id, - render_links=self.render_links) + render_links=self.render_links).render() if hasattr(self.buf, 'write'): - html_renderer.write_result(self.buf) + buffer_put_lines(self.buf, html) elif isinstance(self.buf, compat.string_types): with open(self.buf, 'w') as f: - html_renderer.write_result(f) + buffer_put_lines(f, html) else: raise TypeError('buf is not a file name and it has no write ' ' method') diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index 798bcad9dbc2e..1fb950388aaf3 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -16,8 +16,7 @@ from pandas.core.config import get_option from pandas.io.common import _is_url -from pandas.io.formats.format import ( - TableFormatter, buffer_put_lines, get_level_lengths) +from pandas.io.formats.format import TableFormatter, get_level_lengths from pandas.io.formats.printing import pprint_thing @@ -136,7 +135,7 @@ def write_tr(self, line, indent=0, indent_delta=0, header=False, indent -= indent_delta self.write('', indent) - def write_result(self, buf): + def render(self): self._write_table() if self.should_show_dimensions: @@ -146,7 +145,7 @@ def write_result(self, buf): by=by, cols=len(self.frame.columns))) - buffer_put_lines(buf, self.elements) + return self.elements def _write_table(self, indent=0): _classes = ['dataframe'] # Default class. @@ -512,10 +511,9 @@ def write_style(self): template_last))) self.write(template) - def write_result(self, buf): + def render(self): self.write('
') self.write_style() - super().write_result(buf) + super().render() self.write('
') - - buffer_put_lines(buf, self.elements) + return self.elements From ddfd81748b7130b727b512ad25d929eb4b7a55b9 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Sun, 6 Jan 2019 11:07:36 +0000 Subject: [PATCH 3/6] remove unnecessary function arguments --- pandas/io/formats/format.py | 4 +--- pandas/io/formats/html.py | 7 +++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 04ec9c56e2d6a..bdeed58d856cc 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -732,9 +732,7 @@ def to_html(self, classes=None, notebook=False, border=None): """ from pandas.io.formats.html import HTMLFormatter, NotebookFormatter Klass = NotebookFormatter if notebook else HTMLFormatter - html = Klass( - self, classes=classes, border=border, table_id=self.table_id, - render_links=self.render_links).render() + html = Klass(self, classes=classes, border=border).render() if hasattr(self.buf, 'write'): buffer_put_lines(self.buf, html) elif isinstance(self.buf, compat.string_types): diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index 1fb950388aaf3..dbdb313ce5154 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -24,8 +24,7 @@ class HTMLFormatter(TableFormatter): indent_delta = 2 - def __init__(self, formatter, classes=None, border=None, - table_id=None, render_links=False): + def __init__(self, formatter, classes=None, border=None): self.fmt = formatter self.classes = classes @@ -38,8 +37,8 @@ def __init__(self, formatter, classes=None, border=None, if border is None: border = get_option('display.html.border') self.border = border - self.table_id = table_id - self.render_links = render_links + self.table_id = self.fmt.table_id + self.render_links = self.fmt.render_links @property def show_row_idx_names(self): From ef62b8fe59796ec6a02b816c4f449ed7a3d95a12 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Sun, 6 Jan 2019 12:21:07 +0000 Subject: [PATCH 4/6] fix py2 failures --- pandas/io/formats/html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index dbdb313ce5154..86f61ffb68865 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -513,6 +513,6 @@ def write_style(self): def render(self): self.write('
') self.write_style() - super().render() + super(HTMLFormatter, self).render() self.write('
') return self.elements From c36382ccbe247f9b8316c6742617d45669d2f904 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Sun, 6 Jan 2019 12:24:58 +0000 Subject: [PATCH 5/6] fix --- pandas/io/formats/html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index 86f61ffb68865..206284ab8bf49 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -513,6 +513,6 @@ def write_style(self): def render(self): self.write('
') self.write_style() - super(HTMLFormatter, self).render() + super(NotebookFormatter, self).render() self.write('
') return self.elements From 2b0e24edf1bab9bb4db5a2d4b46f52ba5a9ee160 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Sun, 6 Jan 2019 16:39:09 +0000 Subject: [PATCH 6/6] add docstrings --- pandas/io/formats/html.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index 206284ab8bf49..f41749e0a7745 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -21,6 +21,14 @@ class HTMLFormatter(TableFormatter): + """ + Internal class for formatting output data in html. + This class is intended for shared functionality between + DataFrame.to_html() and DataFrame._repr_html_(). + Any logic in common with other output formatting methods + should ideally be inherited from classes in format.py + and this class responsible for only producing html markup. + """ indent_delta = 2 @@ -472,6 +480,11 @@ def _write_hierarchical_rows(self, fmt_values, indent): class NotebookFormatter(HTMLFormatter): + """ + Internal class for formatting output data in html for display in Jupyter + Notebooks. This class is intended for functionality specific to + DataFrame._repr_html_() and DataFrame.to_html(notebook=True) + """ def write_style(self): # We use the "scoped" attribute here so that the desired