From da08c86b8c12d1ed7bf8b453fac066e83528e098 Mon Sep 17 00:00:00 2001 From: Peter Killick Date: Wed, 15 May 2019 15:12:32 +0100 Subject: [PATCH 1/5] Add repr_html for CubeLists --- lib/iris/cube.py | 5 ++ lib/iris/experimental/representation.py | 82 +++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/lib/iris/cube.py b/lib/iris/cube.py index 137aa68586..e13df8220c 100644 --- a/lib/iris/cube.py +++ b/lib/iris/cube.py @@ -231,6 +231,11 @@ def __repr__(self): """Runs repr on every cube.""" return '[%s]' % ',\n'.join([repr(cube) for cube in self]) + def _repr_html_(self): + from iris.experimental.representation import CubeListRepresentation + representer = CubeListRepresentation(self) + return representer.repr_html() + # TODO #370 Which operators need overloads? def __add__(self, other): return CubeList(list.__add__(self, other)) diff --git a/lib/iris/experimental/representation.py b/lib/iris/experimental/representation.py index 5adef1f06e..e3751abdd9 100644 --- a/lib/iris/experimental/representation.py +++ b/lib/iris/experimental/representation.py @@ -306,3 +306,85 @@ def repr_html(self): id=self.cube_id, shape=shape, content=content) + + +class CubeListRepresentation(object): + _template = """ + + +{contents} + """ + + _accordian_panel = """ + +
+

{content}

+
+ """ + + def __init__(self, cubelist): + self.cubelist = cubelist + self.cubelist_id = id(self.cubelist) + self.cubelist_str_split = str(self.cubelist).split('\n') + + def make_content(self): + html = [] + for i, cube in enumerate(self.cubelist): + title = '{i}: {summary}'.format(i=i, + summary=cube.summary(shorten=True)) + content = cube._repr_html_() + html.append(self._accordian_panel.format(uid=self.cubelist_id, + title=title, + content=content)) + return '\n'.join(html) + + def repr_html(self): + contents = self.make_content() + return self._template.format(uid=self.cubelist_id, + contents=contents) From fe4dcb50261638ceaec4f423b2ede72c1891af53 Mon Sep 17 00:00:00 2001 From: Peter Killick Date: Wed, 15 May 2019 16:35:35 +0100 Subject: [PATCH 2/5] Add some testing --- lib/iris/experimental/representation.py | 6 +- .../test_CubeListRepresentation.py | 83 +++++++++++++++++++ 2 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 lib/iris/tests/unit/experimental/representation/test_CubeListRepresentation.py diff --git a/lib/iris/experimental/representation.py b/lib/iris/experimental/representation.py index e3751abdd9..097ff3ce13 100644 --- a/lib/iris/experimental/representation.py +++ b/lib/iris/experimental/representation.py @@ -371,7 +371,6 @@ class CubeListRepresentation(object): def __init__(self, cubelist): self.cubelist = cubelist self.cubelist_id = id(self.cubelist) - self.cubelist_str_split = str(self.cubelist).split('\n') def make_content(self): html = [] @@ -382,9 +381,10 @@ def make_content(self): html.append(self._accordian_panel.format(uid=self.cubelist_id, title=title, content=content)) - return '\n'.join(html) + return html def repr_html(self): contents = self.make_content() + contents_str = '\n'.join(contents) return self._template.format(uid=self.cubelist_id, - contents=contents) + contents=contents_str) diff --git a/lib/iris/tests/unit/experimental/representation/test_CubeListRepresentation.py b/lib/iris/tests/unit/experimental/representation/test_CubeListRepresentation.py new file mode 100644 index 0000000000..b0d7cbb773 --- /dev/null +++ b/lib/iris/tests/unit/experimental/representation/test_CubeListRepresentation.py @@ -0,0 +1,83 @@ +# (C) British Crown Copyright 2019, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for the `iris.cube.CubeRepresentation` class.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +from iris.cube import CubeList +import iris.tests.stock as stock + +from iris.experimental.representation import CubeListRepresentation + + +@tests.skip_data +class Test__instantiation(tests.IrisTest): + def setUp(self): + self.cubes = CubeList([stock.simple_3d()]) + self.representer = CubeListRepresentation(self.cubes) + + def test_ids(self): + self.assertEqual(id(self.cubes), self.representer.cubelist_id) + + +@tests.skip_data +class Test_make_content(tests.IrisTest): + def setUp(self): + self.cubes = CubeList([stock.simple_3d(), + stock.lat_lon_cube()]) + self.representer = CubeListRepresentation(self.cubes) + self.content = self.representer.make_content() + + def test_repr_len(self): + self.assertEqual(len(self.cubes), len(self.content)) + + def test_summary_lines(self): + names = [c.name() for c in self.cubes] + for name, content in zip(names, self.content): + self.assertIn(name, content) + + def test__cube_name_summary_consistency(self): + # Just check the first cube in the CubeList. + single_cube_html = self.content[0] + first_contents_line = single_cube_html.split('\n')[1] + # Get the cube name out of the repr html... + cube_name = first_contents_line.split('>0: ')[1].split('/')[0] + # ... and prettify it (to be the same as in the following cube repr). + pretty_cube_name = cube_name.strip().replace('_', ' ').title() + self.assertIn(pretty_cube_name, single_cube_html) + + +@tests.skip_data +class Test_repr_html(tests.IrisTest): + def setUp(self): + self.cubes = CubeList([stock.simple_3d(), + stock.lat_lon_cube()]) + self.representer = CubeListRepresentation(self.cubes) + + def test_html_length(self): + html = self.representer.repr_html() + n_html_elems = html.count(' tag per cube. + self.assertEqual(len(self.cubes), n_html_elems) + + +if __name__ == '__main__': + tests.main() \ No newline at end of file From e9fc66fc6f16e360b187024d8533c9372388ef57 Mon Sep 17 00:00:00 2001 From: Peter Killick Date: Wed, 15 May 2019 16:44:11 +0100 Subject: [PATCH 3/5] Stickler --- lib/iris/experimental/representation.py | 2 +- .../experimental/representation/test_CubeListRepresentation.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/iris/experimental/representation.py b/lib/iris/experimental/representation.py index 097ff3ce13..6ae9dfaae5 100644 --- a/lib/iris/experimental/representation.py +++ b/lib/iris/experimental/representation.py @@ -365,7 +365,7 @@ class CubeListRepresentation(object):

{content}

-
+ """ def __init__(self, cubelist): diff --git a/lib/iris/tests/unit/experimental/representation/test_CubeListRepresentation.py b/lib/iris/tests/unit/experimental/representation/test_CubeListRepresentation.py index b0d7cbb773..a9cf07ef9b 100644 --- a/lib/iris/tests/unit/experimental/representation/test_CubeListRepresentation.py +++ b/lib/iris/tests/unit/experimental/representation/test_CubeListRepresentation.py @@ -80,4 +80,4 @@ def test_html_length(self): if __name__ == '__main__': - tests.main() \ No newline at end of file + tests.main() From 1f6038e8881b402c0c8f5755288c3ac6f3d6a6ea Mon Sep 17 00:00:00 2001 From: Peter Killick Date: Fri, 23 Aug 2019 11:26:41 +0100 Subject: [PATCH 4/5] License header --- lib/iris/experimental/representation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/iris/experimental/representation.py b/lib/iris/experimental/representation.py index 6ae9dfaae5..2ffe709c42 100644 --- a/lib/iris/experimental/representation.py +++ b/lib/iris/experimental/representation.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2018, Met Office +# (C) British Crown Copyright 2018 - 2019, Met Office # # This file is part of Iris. # From 0693b3ef7bff048f52b3d5468c44a6cc1378ed8e Mon Sep 17 00:00:00 2001 From: Peter Killick Date: Tue, 27 Aug 2019 13:53:01 +0100 Subject: [PATCH 5/5] Update css to use jupyter vars --- lib/iris/experimental/representation.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/iris/experimental/representation.py b/lib/iris/experimental/representation.py index 2ffe709c42..b16d79d5de 100644 --- a/lib/iris/experimental/representation.py +++ b/lib/iris/experimental/representation.py @@ -312,30 +312,34 @@ class CubeListRepresentation(object): _template = """