From 3df97e361af5a94d83b94d778fe0e6280332f936 Mon Sep 17 00:00:00 2001 From: David Hall Date: Thu, 22 Feb 2018 21:31:37 -0800 Subject: [PATCH 01/10] ENH: Add Styler.disable_mathjax() method (#19824). This prevents MathJax from processing table contents. --- pandas/io/formats/style.py | 22 ++++++++++++++++++++-- pandas/io/formats/templates/html.tpl | 12 ++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 525f487d8aa39..60ce018b4f2fb 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -63,6 +63,8 @@ class Styler(object): a unique identifier to avoid CSS collisons; generated automatically caption: str, default None caption to attach to the table + disabled_mathjax: bool, default False + prevent MathJax from processing table contents Attributes ---------- @@ -111,7 +113,7 @@ class Styler(object): template = env.get_template("html.tpl") def __init__(self, data, precision=None, table_styles=None, uuid=None, - caption=None, table_attributes=None): + caption=None, disabled_mathjax=False, table_attributes=None): self.ctx = defaultdict(list) self._todo = [] @@ -129,6 +131,7 @@ def __init__(self, data, precision=None, table_styles=None, uuid=None, self.uuid = uuid self.table_styles = table_styles self.caption = caption + self.disabled_mathjax = disabled_mathjax if precision is None: precision = get_option('display.precision') self.precision = precision @@ -181,6 +184,7 @@ def _translate(self): """ table_styles = self.table_styles or [] caption = self.caption + disabled_mathjax = self.disabled_mathjax ctx = self.ctx precision = self.precision hidden_index = self.hidden_index @@ -327,7 +331,8 @@ def format_attr(pair): return dict(head=head, cellstyle=cellstyle, body=body, uuid=uuid, precision=precision, table_styles=table_styles, - caption=caption, table_attributes=self.table_attributes) + caption=caption, disabled_mathjax=disabled_mathjax, + table_attributes=self.table_attributes) def format(self, formatter, subset=None): """ @@ -431,6 +436,7 @@ def render(self, **kwargs): * precision * table_styles * caption + * disabled_mathjax * table_attributes """ self._compute() @@ -465,6 +471,7 @@ def _update_ctx(self, attrs): def _copy(self, deepcopy=False): styler = Styler(self.data, precision=self.precision, caption=self.caption, uuid=self.uuid, + disabled_mathjax=self.disabled_mathjax, table_styles=self.table_styles) if deepcopy: styler.ctx = copy.deepcopy(self.ctx) @@ -794,6 +801,17 @@ def set_table_styles(self, table_styles): self.table_styles = table_styles return self + def disable_mathjax(self): + """ + Prevent MathJax from processing table contents. + + Returns + ------- + self : Styler + """ + self.disabled_mathjax = True + return self + def hide_index(self): """ Hide any indices from rendering. diff --git a/pandas/io/formats/templates/html.tpl b/pandas/io/formats/templates/html.tpl index 706db1ecdd961..0942d93484a5b 100644 --- a/pandas/io/formats/templates/html.tpl +++ b/pandas/io/formats/templates/html.tpl @@ -23,7 +23,11 @@ {%- endblock cellstyle %} {%- endblock style %} -{%- block before_table %}{% endblock before_table %} +{%- block before_table %} +{%- if disabled_mathjax -%} +
+{%- endif -%} +{% endblock before_table %} {%- block table %} {%- block caption %} @@ -67,4 +71,8 @@ {%- endblock tbody %}
{%- endblock table %} -{%- block after_table %}{% endblock after_table %} +{%- block after_table %} +{%- if disabled_mathjax -%} +
+{%- endif -%} +{% endblock after_table %} From f48f5875b8b1b3deb5b74b759366f941f2aa9057 Mon Sep 17 00:00:00 2001 From: David Hall Date: Fri, 23 Feb 2018 17:35:45 -0800 Subject: [PATCH 02/10] Revert "ENH: Add Styler.disable_mathjax() method (#19824)." This reverts commit 3df97e361af5a94d83b94d778fe0e6280332f936. --- pandas/io/formats/style.py | 22 ++-------------------- pandas/io/formats/templates/html.tpl | 12 ++---------- 2 files changed, 4 insertions(+), 30 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 60ce018b4f2fb..525f487d8aa39 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -63,8 +63,6 @@ class Styler(object): a unique identifier to avoid CSS collisons; generated automatically caption: str, default None caption to attach to the table - disabled_mathjax: bool, default False - prevent MathJax from processing table contents Attributes ---------- @@ -113,7 +111,7 @@ class Styler(object): template = env.get_template("html.tpl") def __init__(self, data, precision=None, table_styles=None, uuid=None, - caption=None, disabled_mathjax=False, table_attributes=None): + caption=None, table_attributes=None): self.ctx = defaultdict(list) self._todo = [] @@ -131,7 +129,6 @@ def __init__(self, data, precision=None, table_styles=None, uuid=None, self.uuid = uuid self.table_styles = table_styles self.caption = caption - self.disabled_mathjax = disabled_mathjax if precision is None: precision = get_option('display.precision') self.precision = precision @@ -184,7 +181,6 @@ def _translate(self): """ table_styles = self.table_styles or [] caption = self.caption - disabled_mathjax = self.disabled_mathjax ctx = self.ctx precision = self.precision hidden_index = self.hidden_index @@ -331,8 +327,7 @@ def format_attr(pair): return dict(head=head, cellstyle=cellstyle, body=body, uuid=uuid, precision=precision, table_styles=table_styles, - caption=caption, disabled_mathjax=disabled_mathjax, - table_attributes=self.table_attributes) + caption=caption, table_attributes=self.table_attributes) def format(self, formatter, subset=None): """ @@ -436,7 +431,6 @@ def render(self, **kwargs): * precision * table_styles * caption - * disabled_mathjax * table_attributes """ self._compute() @@ -471,7 +465,6 @@ def _update_ctx(self, attrs): def _copy(self, deepcopy=False): styler = Styler(self.data, precision=self.precision, caption=self.caption, uuid=self.uuid, - disabled_mathjax=self.disabled_mathjax, table_styles=self.table_styles) if deepcopy: styler.ctx = copy.deepcopy(self.ctx) @@ -801,17 +794,6 @@ def set_table_styles(self, table_styles): self.table_styles = table_styles return self - def disable_mathjax(self): - """ - Prevent MathJax from processing table contents. - - Returns - ------- - self : Styler - """ - self.disabled_mathjax = True - return self - def hide_index(self): """ Hide any indices from rendering. diff --git a/pandas/io/formats/templates/html.tpl b/pandas/io/formats/templates/html.tpl index 0942d93484a5b..706db1ecdd961 100644 --- a/pandas/io/formats/templates/html.tpl +++ b/pandas/io/formats/templates/html.tpl @@ -23,11 +23,7 @@ {%- endblock cellstyle %} {%- endblock style %} -{%- block before_table %} -{%- if disabled_mathjax -%} -
-{%- endif -%} -{% endblock before_table %} +{%- block before_table %}{% endblock before_table %} {%- block table %} {%- block caption %} @@ -71,8 +67,4 @@ {%- endblock tbody %}
{%- endblock table %} -{%- block after_table %} -{%- if disabled_mathjax -%} -
-{%- endif -%} -{% endblock after_table %} +{%- block after_table %}{% endblock after_table %} From 9d97bfd025b3ba1fd9859758eb341bf81a67fa66 Mon Sep 17 00:00:00 2001 From: David Hall Date: Sat, 24 Feb 2018 07:33:57 -0800 Subject: [PATCH 03/10] ENH: Add display.html.use_mathjax option (#19824). Default value is True to maintain existing behavior. --- doc/source/options.rst | 4 ++++ pandas/core/config_init.py | 8 ++++++++ pandas/core/frame.py | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/doc/source/options.rst b/doc/source/options.rst index cce16a5396377..58569352db315 100644 --- a/doc/source/options.rst +++ b/doc/source/options.rst @@ -402,6 +402,10 @@ display.html.table_schema False Whether to publish a Table display.html.border 1 A ``border=value`` attribute is inserted in the ```` tag for the DataFrame HTML repr. +display.html.use_mathjax True When True, IPython notebook will process + table contents using MathJax, rendering + mathematical expressions enclosed by the + dollar symbol. io.excel.xls.writer xlwt The default Excel writer engine for 'xls' files. io.excel.xlsm.writer openpyxl The default Excel writer engine for diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index da42cdbf10233..872d9da800e77 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -207,6 +207,12 @@ def use_numexpr_cb(key): (currently both are identical) """ +pc_html_use_mathjax_doc = """\ +: boolean + When True, IPython notebook will process table contents using MathJax, + rendering mathematical expressions enclosed by the dollar symbol. + (default: True) +""" pc_width_doc = """ : int @@ -358,6 +364,8 @@ def table_schema_cb(key): validator=is_bool, cb=table_schema_cb) cf.register_option('html.border', 1, pc_html_border_doc, validator=is_int) + cf.register_option('html.use_mathjax', True, pc_html_use_mathjax_doc, + validator=is_bool) with cf.config_prefix('html'): cf.register_option('border', 1, pc_html_border_doc, diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 2aae4dffbeaaf..6c027723360b9 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -674,8 +674,14 @@ def _repr_html_(self): max_rows = get_option("display.max_rows") max_cols = get_option("display.max_columns") show_dimensions = get_option("display.show_dimensions") + use_mathjax = get_option("display.html.use_mathjax") + + classes = [] + if not use_mathjax: + classes.append('tex2jax_ignore') return self.to_html(max_rows=max_rows, max_cols=max_cols, + classes=classes, show_dimensions=show_dimensions, notebook=True) else: return None From 89659cdd383f5ee9b6ca3d5e5b0f9634dd2bfda2 Mon Sep 17 00:00:00 2001 From: David Hall Date: Sat, 24 Feb 2018 09:13:00 -0800 Subject: [PATCH 04/10] Added release note --- doc/source/whatsnew/v0.23.0.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index 603e4e6ce0522..aee54b705422c 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -296,6 +296,7 @@ Other Enhancements - :class:`IntervalIndex` and its associated constructor methods (``from_arrays``, ``from_breaks``, ``from_tuples``) have gained a ``dtype`` parameter (:issue:`19262`) - Added :func:`SeriesGroupBy.is_monotonic_increasing` and :func:`SeriesGroupBy.is_monotonic_decreasing` (:issue:`17015`) - :func:`DataFrame.from_dict` now accepts a ``columns`` argument that can be used to specify the column names when ``orient='index'`` is used (:issue:`18529`) +- Added option ``display.html.use_mathjax`` so that MathJax can be disabled when rendering DataFrames in Jupyter notebooks (:issue:`19856`, :issue:`#19824`) .. _whatsnew_0230.api_breaking: From 95f7d1417ca5114dd714eecd8aa91e06f69d21bb Mon Sep 17 00:00:00 2001 From: David Hall Date: Sat, 24 Feb 2018 09:49:54 -0800 Subject: [PATCH 05/10] Fix release note --- doc/source/whatsnew/v0.23.0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index aee54b705422c..e42d65900de82 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -296,7 +296,7 @@ Other Enhancements - :class:`IntervalIndex` and its associated constructor methods (``from_arrays``, ``from_breaks``, ``from_tuples``) have gained a ``dtype`` parameter (:issue:`19262`) - Added :func:`SeriesGroupBy.is_monotonic_increasing` and :func:`SeriesGroupBy.is_monotonic_decreasing` (:issue:`17015`) - :func:`DataFrame.from_dict` now accepts a ``columns`` argument that can be used to specify the column names when ``orient='index'`` is used (:issue:`18529`) -- Added option ``display.html.use_mathjax`` so that MathJax can be disabled when rendering DataFrames in Jupyter notebooks (:issue:`19856`, :issue:`#19824`) +- Added option ``display.html.use_mathjax`` so `MathJax `_ can be disabled when rendering tables in ``Jupyter`` notebooks (:issue:`19856`, :issue:`19824`) .. _whatsnew_0230.api_breaking: From 5c71bf1a217b25b9074bb15045c60c923ae5554c Mon Sep 17 00:00:00 2001 From: David Hall Date: Sat, 24 Feb 2018 09:57:06 -0800 Subject: [PATCH 06/10] Replace IPython with Jupyter in docs --- doc/source/options.rst | 2 +- pandas/core/config_init.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/options.rst b/doc/source/options.rst index 58569352db315..a82be4d84bf3f 100644 --- a/doc/source/options.rst +++ b/doc/source/options.rst @@ -402,7 +402,7 @@ display.html.table_schema False Whether to publish a Table display.html.border 1 A ``border=value`` attribute is inserted in the ``
`` tag for the DataFrame HTML repr. -display.html.use_mathjax True When True, IPython notebook will process +display.html.use_mathjax True When True, Jupyter notebook will process table contents using MathJax, rendering mathematical expressions enclosed by the dollar symbol. diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index 872d9da800e77..0edbf892172a9 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -209,7 +209,7 @@ def use_numexpr_cb(key): pc_html_use_mathjax_doc = """\ : boolean - When True, IPython notebook will process table contents using MathJax, + When True, Jupyter notebook will process table contents using MathJax, rendering mathematical expressions enclosed by the dollar symbol. (default: True) """ From 9b287aaaaffed06400291f6ac67a908fae72306b Mon Sep 17 00:00:00 2001 From: David Hall Date: Sat, 24 Feb 2018 10:32:27 -0800 Subject: [PATCH 07/10] Move logic from DataFrame to HTMLFormatter --- pandas/core/frame.py | 6 ------ pandas/io/formats/format.py | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 6c027723360b9..2aae4dffbeaaf 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -674,14 +674,8 @@ def _repr_html_(self): max_rows = get_option("display.max_rows") max_cols = get_option("display.max_columns") show_dimensions = get_option("display.show_dimensions") - use_mathjax = get_option("display.html.use_mathjax") - - classes = [] - if not use_mathjax: - classes.append('tex2jax_ignore') return self.to_html(max_rows=max_rows, max_cols=max_cols, - classes=classes, show_dimensions=show_dimensions, notebook=True) else: return None diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 621641747f376..50b4f11634b78 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1209,6 +1209,9 @@ def write_result(self, buf): frame = self.frame _classes = ['dataframe'] # Default class. + use_mathjax = get_option("display.html.use_mathjax") + if not use_mathjax: + _classes.append('tex2jax_ignore') if self.classes is not None: if isinstance(self.classes, str): self.classes = self.classes.split() From 400f211b40966c996924ef6826d1570c1cd80912 Mon Sep 17 00:00:00 2001 From: David Hall Date: Wed, 28 Feb 2018 19:23:47 -0800 Subject: [PATCH 08/10] Add tests for both format and style versions of _repr_html_() --- pandas/tests/io/formats/test_format.py | 7 +++++++ pandas/tests/io/formats/test_style.py | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py index dddba5b425c3b..badfd438c9150 100644 --- a/pandas/tests/io/formats/test_format.py +++ b/pandas/tests/io/formats/test_format.py @@ -1434,6 +1434,13 @@ def test_repr_html(self): tm.reset_display_options() + def test_repr_html_mathjax(self): + df = DataFrame([[1, 2], [3, 4]]) + assert 'tex2jax_ignore' not in df._repr_html_() + + with pd.option_context('display.html.use_mathjax', False): + assert 'tex2jax_ignore' in df._repr_html_() + def test_repr_html_wide(self): max_cols = get_option('display.max_columns') df = DataFrame(tm.rands_array(25, size=(10, max_cols - 1))) diff --git a/pandas/tests/io/formats/test_style.py b/pandas/tests/io/formats/test_style.py index bedb11d4fc4ae..06c7e2dd861b6 100644 --- a/pandas/tests/io/formats/test_style.py +++ b/pandas/tests/io/formats/test_style.py @@ -46,6 +46,12 @@ def test_init_series(self): def test_repr_html_ok(self): self.styler._repr_html_() + def test_repr_html_mathjax(self): + assert 'tex2jax_ignore' not in self.styler._repr_html_() + + with pd.option_context('display.html.use_mathjax', False): + assert 'tex2jax_ignore' in self.styler._repr_html_() + def test_update_ctx(self): self.styler._update_ctx(self.attrs) expected = {(0, 0): ['color: red'], From 15961e1cd8c3431003bc1fd9b64758ab030ed02e Mon Sep 17 00:00:00 2001 From: David Hall Date: Wed, 28 Feb 2018 22:00:00 -0800 Subject: [PATCH 09/10] Inject tex2jax_ignore into table class attribute in Styler. --- pandas/io/formats/style.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 525f487d8aa39..f876ceb8a26bf 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -325,9 +325,19 @@ def format_attr(pair): .format(row=r, col=c)}) body.append(row_es) + table_attr = self.table_attributes + use_mathjax = get_option("display.html.use_mathjax") + if not use_mathjax: + table_attr = table_attr or '' + if 'class="' in table_attr: + table_attr = table_attr.replace('class="', + 'class="tex2jax_ignore ') + else: + table_attr += ' class="tex2jax_ignore"' + return dict(head=head, cellstyle=cellstyle, body=body, uuid=uuid, precision=precision, table_styles=table_styles, - caption=caption, table_attributes=self.table_attributes) + caption=caption, table_attributes=table_attr) def format(self, formatter, subset=None): """ From 771e9a68422832e6a552e330f0e61c651833a6b7 Mon Sep 17 00:00:00 2001 From: Jeff Reback Date: Thu, 1 Mar 2018 18:05:23 -0500 Subject: [PATCH 10/10] issue number --- pandas/tests/io/formats/test_style.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/tests/io/formats/test_style.py b/pandas/tests/io/formats/test_style.py index 06c7e2dd861b6..f9b7d4915acef 100644 --- a/pandas/tests/io/formats/test_style.py +++ b/pandas/tests/io/formats/test_style.py @@ -47,6 +47,7 @@ def test_repr_html_ok(self): self.styler._repr_html_() def test_repr_html_mathjax(self): + # gh-19824 assert 'tex2jax_ignore' not in self.styler._repr_html_() with pd.option_context('display.html.use_mathjax', False):