[Piglit] [PATCH 6/6] Summary.py: Convert HTMLIndex class into a generator

Dylan Baker baker.dylan.c at gmail.com
Mon Nov 4 08:53:47 PST 2013


This change does a couple of really nice things for us, first it cuts
down on the memory consumption by using a generator (which is lazy).
Further, as a part of the Summary.generate_html() method it doesn't need
to have the summary instance passed to it, reducing complexity.

Signed-off-by: Dylan Baker <baker.dylan.c at gmail.com>
---
 framework/summary.py      | 203 +++++++++++++++++-----------------------------
 templates/index_body.mako |  15 ++--
 2 files changed, 82 insertions(+), 136 deletions(-)

diff --git a/framework/summary.py b/framework/summary.py
index 4a6db43..9614def 100644
--- a/framework/summary.py
+++ b/framework/summary.py
@@ -37,132 +37,6 @@ __all__ = [
 ]
 
 
-class HTMLIndex(list):
-    """
-    Builds HTML output to be passed to the index mako template, which will be
-    rendered into HTML pages. It does this by parsing the lists provided by the
-    Summary object, and returns itself, an object with one accessor, a list of
-    html strings that will be printed by the mako template.
-    """
-
-    def __init__(self, summary, page):
-        """ Steps through the list of groups and tests from all of the results and
-        generates a list of dicts that are passed to mako and turned into HTML
-        
-        """
-        # Add the toplevel 'all' group
-        self._newRow()
-        self._groupRow("head", 0, 'all')
-        for each in summary.results:
-            self._groupResult(summary.fractions[each.name]['all'],
-                              summary.status[each.name]['all'])
-        self._endRow()
-        
-        # 'all' gets the depth of 0, so start at 1
-        depth = 1
-        group = ""
-
-        # The following loop relies on alphabetical sorting of test names
-        for test in sorted(page):
-
-            # If the current group not the same as the last group call
-            # os.path.relpath on it. This gives ".." for each group to close
-            # (reducing the depth) and a name for each group to open
-            # (increasing the depth)
-            if path.dirname(test) != group:
-                for cur in path.relpath(path.dirname(test), group).split('/'):
-                    if cur == "..":
-                        depth -= 1
-                        group = path.dirname(group)
-                    else:
-                        group = path.join(group, cur)
-                        self._newRow()
-                        self._groupRow("head", depth, group)
-                        for each in summary.results:
-                            try:
-                                self._groupResult(
-                                    summary.fractions[each.name][group],
-                                    summary.status[each.name][group])
-                            except KeyError:
-                                self._groupResult((0, 0), 'skip')
-                        depth += 1
-                        self._endRow()
-
-            # Finally add a new row for the test itself, and add the left-most
-            # name column
-            self._newRow()
-            self._testRow("group", depth, test)
-
-            # Add the result from each test result to the HTML summary If there
-            # is a KeyError (a result doesn't contain a particular test),
-            # return Not Run, with clas skip for highlighting
-            for each in summary.results:
-                try:
-                    self._testResult(each.name, test, each.tests[test]['result'])
-                except KeyError:
-                    self.append({'type': 'other',
-                                 'text': '<td class="skip">Not Run</td>'})
-            self._endRow()
-
-    def _newRow(self):
-        self.append({'type': 'newRow'})
-
-    def _endRow(self):
-        self.append({'type': 'endRow'})
-
-    def _groupRow(self, cssclass, depth, groupname):
-        """
-        Helper function for appending new groups to be written out
-        in HTML.
-
-        This particular function is used to write the left most
-        column of the summary. (the one with the indents)
-        """
-        self.append({'type': "groupRow",
-                     'class': cssclass,
-                     'indent': (1.75 * depth),
-                     'text': groupname})
-
-    def _groupResult(self, value, css):
-        """
-        Helper function for appending the results of groups to the
-        HTML summary file.
-        """
-        # "Not Run" is not a valid css class replace it with skip
-        if isinstance(css, so.NotRun):
-            css = 'skip'
-
-        self.append({'type': "groupResult",
-                     'class': css,
-                     'text': "%s/%s" % (value[0], value[1])})
-
-    def _testRow(self, cssclass, depth, groupname):
-        """
-        Helper function for appending new tests to be written out
-        in HTML.
-
-        This particular function is used to write the left most
-        column of the summary. (the one with the indents)
-        """
-        self.append({'type': "testRow",
-                     'class': cssclass,
-                     'indent': (1.75 * depth),
-                     'text': groupname})
-
-    def _testResult(self, group, href, text):
-        """
-        Helper function for writing the results of tests
-
-        This function writes the cells other than the left-most cell,
-        displaying pass/fail/crash/etc and formatting the cell to the
-        correct color.
-        """
-        self.append({'type': 'testResult',
-                     'class': text,
-                     'href': path.join(group, href + ".html"),
-                     'text': text})
-
-
 class Summary:
     """
     This Summary class creates an initial object containing lists of tests
@@ -280,6 +154,79 @@ class Summary:
         heavy lifting, this method just passes it a bunch of dicts and lists
         of dicts, which mako turns into pretty HTML.
         """
+        def html_list(page):
+            """ Generate content to be passed to mako
+
+            This method generates data to be passed to the index_body mako
+            template.
+
+            """
+            new_row = {'type': 'newRow'}
+            end_row = {'type': 'endRow'}
+
+            # Create the toplevel 'all' group
+            yield new_row
+            yield {'type': "groupRow", 'indent': 0, 'text': 'all'}
+            for each in self.results:
+                yield {'type': 'groupResult',
+                       'text': self.fractions[each.name]['all'],
+                       'class': self.status[each.name]['all']}
+            yield end_row
+
+            # set a starting depth of 1, 0 is used for 'all' so 1 is the
+            # next available group
+            depth = 1
+            group = ""
+
+            # The following loop relies on alphabetical sorting of test names
+            for test in sorted(self.tests[page]):
+
+                # If the current group not the same as the last group call
+                # os.path.relpath on it. This gives ".." for each group to close
+                # (reducing the depth) and a name for each group to open
+                # (increasing the depth)
+                if path.dirname(test) != group:
+                    for cur in path.relpath(path.dirname(test), group).split('/'):
+                        if cur == "..":
+                            depth -= 1
+                            group = path.dirname(group)
+                        else:
+                            group = path.join(group, cur)
+                            yield new_row
+                            yield {"type": "groupRow",
+                                   "indent": (1.75 * depth),
+                                   "text": group}
+                            for each in self.results:
+                                yield {'type': "groupResult",
+                                       'text': self.fractions[each.name].get(group, (0, 0)),
+                                       'class': self.status[each.name].get(group, "skip")}
+
+                            depth += 1
+                            yield end_row
+
+                # Finally add a new row for the test itself, and add the left-most
+                # name column
+                yield new_row
+                yield {'type': "testRow",
+                       'indent': (1.75 * depth),
+                       'text': test}
+
+                # Add the result from each test result to the HTML summary If there
+                # is a KeyError (a result doesn't contain a particular test),
+                # return Not Run, with clas skip for highlighting
+                for each in self.results:
+                    try:
+                        yield {'type': 'testResult',
+                               'class': each.tests[test]['result'],
+                               'href': path.join(each.name, test + ".html"),
+                               'text': each.tests[test]['result']}
+                    except KeyError:
+                        yield {'type': 'testResult',
+                               'class': "skip",
+                               'href': None,
+                               'text': "Not Run"}
+
+                yield end_row
 
         # Lookup all templates in the template dir
         templates = TemplateLookup(directories=["templates"],
@@ -351,7 +298,7 @@ class Summary:
                                         pages=pages,
                                         colnum=len(self.results)))
             out.write(index_columns.render(zips=names))
-            out.write(index_body.render(results=HTMLIndex(self, self.tests['all']),
+            out.write(index_body.render(results=html_list('all'),
                                         exclude=exclude))
             out.write(index_close.render())
 
@@ -366,7 +313,7 @@ class Summary:
                         colnum=len(self.results)))
                     out.write(index_columns.render(zips=names))
                     out.write(index_body.render(
-                        results=HTMLIndex(self, self.tests[page]),
+                        results=html_list(page),
                         exclude=exclude))
                     out.write(index_close.render())
                 # otherwise provide an empty page
diff --git a/templates/index_body.mako b/templates/index_body.mako
index 9e67311..0c1dc54 100644
--- a/templates/index_body.mako
+++ b/templates/index_body.mako
@@ -5,25 +5,26 @@
       </tr>
       % elif line['type'] == "groupRow":
         <td>
-          <div class="${line['class']}" style="margin-left: ${line['indent']}em">
+          <div class="head" style="margin-left: ${line['indent']}em">
             <b>${line['text']}</b>
           </div>
         </td>
       % elif line['type'] == "testRow":
         <td>
-          <div class="${line['class']}" style="margin-left: ${line['indent']}em">
+          <div class="group" style="margin-left: ${line['indent']}em">
             ${line['text']}
           </div>
         </td>
       % elif line['type'] == "groupResult":
         <td class="${line['class']}">
-          <b>${line['text']}</b>
+          <b>${line['text'][0]}/${line['text'][1]}</b>
         </td>
       % elif line['type'] == "testResult":
         <td class="${line['class']}">
-        ## If the result is in the excluded results page list from
-        ## argparse, just print the text, otherwise add the link
-        % if line['class'] not in exclude:
+        ## If there is no href then the type is "Not Run"
+        ## If the class is in exclude, then the user specified in argparse
+        ## not to generate a page for that result
+        % if line['href'] and line['class'] not in exclude:
           <a href="${line['href']}">
             ${line['text']}
           </a>
@@ -31,7 +32,5 @@
           ${line['text']}
         % endif
         </td>
-      % elif line['type'] == "other":
-        ${line['text']}
       % endif
     % endfor
-- 
1.8.1.5



More information about the Piglit mailing list