3 new revisions:

Revision: 73982a8643a5
Branch:   default
Author:   Pekka Klärck
Date:     Fri Oct 19 13:52:35 2012
Log: result building: Build combined results lazily. Reduces memory consump...
http://code.google.com/p/robotframework/source/detail?r=73982a8643a5

Revision: 1082c9352c10
Branch:   default
Author:   Pekka Klärck
Date:     Fri Oct 19 15:05:14 2012
Log:      Result building: Omit keywords if building only report....
http://code.google.com/p/robotframework/source/detail?r=1082c9352c10

Revision: 32635aed62d8
Branch:   default
Author:   Pekka Klärck
Date:     Fri Oct 19 15:23:00 2012
Log:      Refactored result parsing after latest enhancements....
http://code.google.com/p/robotframework/source/detail?r=32635aed62d8

==============================================================================
Revision: 73982a8643a5
Branch:   default
Author:   Pekka Klärck
Date:     Fri Oct 19 13:52:35 2012
Log: result building: Build combined results lazily. Reduces memory consumption a little.
http://code.google.com/p/robotframework/source/detail?r=73982a8643a5

Modified:
 /src/robot/result/executionresult.py
 /src/robot/result/resultbuilder.py

=======================================
--- /src/robot/result/executionresult.py        Wed Mar 14 05:58:57 2012
+++ /src/robot/result/executionresult.py        Fri Oct 19 13:52:35 2012
@@ -64,7 +64,7 @@

 class CombinedResult(Result):

-    def __init__(self, *others):
+    def __init__(self, others):
         Result.__init__(self)
         for other in others:
             self.add_result(other)
=======================================
--- /src/robot/result/resultbuilder.py  Sat Jun 30 16:02:25 2012
+++ /src/robot/result/resultbuilder.py  Fri Oct 19 13:52:35 2012
@@ -33,7 +33,7 @@
     if not sources:
         raise DataError('One or more data source needed.')
     if len(sources) > 1:
-        return CombinedResult(*[ExecutionResult(src) for src in sources])
+        return CombinedResult(ExecutionResult(src) for src in sources)
     source = ETSource(sources[0])
     try:
         return ExecutionResultBuilder(source).build(Result(sources[0]))

==============================================================================
Revision: 1082c9352c10
Branch:   default
Author:   Pekka Klärck
Date:     Fri Oct 19 15:05:14 2012
Log:      Result building: Omit keywords if building only report.

Update issue 1261
Status: Started
Changed the code so that if only report is generated, keywords in output.xml
are nor processed at all. I want to still refactor the code a little and
thus I don't close this issue yet.

The performance impact of the change is pretty huge. In the case mentioned
in the original description, total time is now 1 minute and maximum memory
63 MB.
http://code.google.com/p/robotframework/source/detail?r=1082c9352c10

Modified:
 /src/robot/reporting/resultwriter.py
 /src/robot/result/resultbuilder.py

=======================================
--- /src/robot/reporting/resultwriter.py        Mon Jun 25 07:41:07 2012
+++ /src/robot/reporting/resultwriter.py        Fri Oct 19 15:05:14 2012
@@ -81,7 +81,11 @@
     @property
     def result(self):
         if self._result is None:
-            self._result = ExecutionResult(*self._data_sources)
+            include_keywords = bool(self._settings.log or
+                                    self._settings.output or
+                                    self._settings.xunit)
+ self._result = ExecutionResult(include_keywords=include_keywords,
+                                           *self._data_sources)
             self._result.configure(self._settings.status_rc,
                                    self._settings.suite_config,
                                    self._settings.statistics_config)
=======================================
--- /src/robot/result/resultbuilder.py  Fri Oct 19 13:52:35 2012
+++ /src/robot/result/resultbuilder.py  Fri Oct 19 15:05:14 2012
@@ -22,10 +22,13 @@
 from .executionresult import Result, CombinedResult


-def ExecutionResult(*sources):
+def ExecutionResult(*sources, **options):
"""Constructs :class:`Result` object based on execution result xml file(s).

     :param sources: The Robot Framework output xml file(s).
+    :param options: Configuration options passed to
+ :py:class:`~ExecutionResultBuilder` as keyword arguments.
+                    New in 2.7.5.
     :returns: :py:class:`~.executionresult.Result` instance.

     See :py:mod:`robot.result` for usage example.
@@ -33,10 +36,10 @@
     if not sources:
         raise DataError('One or more data source needed.')
     if len(sources) > 1:
-        return CombinedResult(ExecutionResult(src) for src in sources)
+ return CombinedResult(ExecutionResult(src, **options) for src in sources)
     source = ETSource(sources[0])
     try:
-        return ExecutionResultBuilder(source).build(Result(sources[0]))
+ return ExecutionResultBuilder(source, **options).build(Result(sources[0]))
     except IOError, err:
         error = err.strerror
     except:
@@ -46,16 +49,35 @@

 class ExecutionResultBuilder(object):

-    def __init__(self, source):
+    def __init__(self, source, include_keywords=True):
         self._source = source \
             if isinstance(source, ETSource) else ETSource(source)
+        self._include_keywords = include_keywords

     def build(self, result):
         handler = XmlElementHandler(result)
         # Faster attribute lookup inside for loop
         start, end = handler.start, handler.end
         with self._source as source:
- for event, elem in ET.iterparse(source, events=('start', 'end')):
+            for event, elem in self._get_context(source):
                 start(elem) if event == 'start' else end(elem)
SuiteTeardownFailureHandler(result.generator).visit_suite(result.suite)
         return result
+
+    def _get_context(self, source):
+        context = ET.iterparse(source, events=('start', 'end'))
+        if not self._include_keywords:
+            context = self._omit_keywords(context)
+        return context
+
+    def _omit_keywords(self, context):
+        kws = 0
+        for event, elem in context:
+            if event == 'start' and elem.tag == 'kw':
+                kws += 1
+            if not kws:
+                yield event, elem
+            else:
+                elem.clear()
+            if event == 'end' and elem.tag == 'kw':
+                kws -= 1

==============================================================================
Revision: 32635aed62d8
Branch:   default
Author:   Pekka Klärck
Date:     Fri Oct 19 15:23:00 2012
Log:      Refactored result parsing after latest enhancements.

Update issue 1261
Status: Done
Refactored the code a little. Issue ought to be done.
http://code.google.com/p/robotframework/source/detail?r=32635aed62d8

Modified:
 /src/robot/result/resultbuilder.py
 /src/robot/result/xmlelementhandlers.py

=======================================
--- /src/robot/result/resultbuilder.py  Fri Oct 19 15:05:14 2012
+++ /src/robot/result/resultbuilder.py  Fri Oct 19 15:23:00 2012
@@ -36,15 +36,21 @@
     if not sources:
         raise DataError('One or more data source needed.')
     if len(sources) > 1:
- return CombinedResult(ExecutionResult(src, **options) for src in sources)
-    source = ETSource(sources[0])
+        return _combined_result(sources, options)
+    return _single_result(sources[0], options)
+
+def _combined_result(sources, options):
+ return CombinedResult(ExecutionResult(src, **options) for src in sources)
+
+def _single_result(source, options):
+    ets = ETSource(source)
     try:
- return ExecutionResultBuilder(source, **options).build(Result(sources[0]))
+        return ExecutionResultBuilder(ets, **options).build(Result(source))
     except IOError, err:
         error = err.strerror
     except:
         error = get_error_message()
- raise DataError("Reading XML source '%s' failed: %s" % (unicode(source), error)) + raise DataError("Reading XML source '%s' failed: %s" % (unicode(ets), error))


 class ExecutionResultBuilder(object):
@@ -56,19 +62,21 @@

     def build(self, result):
         handler = XmlElementHandler(result)
-        # Faster attribute lookup inside for loop
-        start, end = handler.start, handler.end
         with self._source as source:
-            for event, elem in self._get_context(source):
-                start(elem) if event == 'start' else end(elem)
+            self._parse(source, handler.start, handler.end)
SuiteTeardownFailureHandler(result.generator).visit_suite(result.suite)
         return result

-    def _get_context(self, source):
+    def _parse(self, source, start, end):
         context = ET.iterparse(source, events=('start', 'end'))
         if not self._include_keywords:
             context = self._omit_keywords(context)
-        return context
+        for event, elem in context:
+            if event == 'start':
+                start(elem)
+            else:
+                end(elem)
+                elem.clear()

     def _omit_keywords(self, context):
         kws = 0
=======================================
--- /src/robot/result/xmlelementhandlers.py     Tue Jun 26 02:53:35 2012
+++ /src/robot/result/xmlelementhandlers.py     Fri Oct 19 15:23:00 2012
@@ -27,7 +27,6 @@
     def end(self, elem):
         result, handler = self._stack.pop()
         handler.end(elem, result)
-        elem.clear()


 class _Handler(object):

Reply via email to