13
13
# See the License for the specific language governing permissions and
14
14
# limitations under the License.
15
15
16
+ from typing import Sequence
16
17
from xml .etree import ElementTree as ET
17
18
18
19
from robot .errors import DataError
27
28
from .xmlelementhandlers import XmlElementHandler
28
29
29
30
30
- def ExecutionResult (* sources , ** options ):
31
+ def ExecutionResult (
32
+ * sources ,
33
+ merge : bool = False ,
34
+ include_keywords : bool = True ,
35
+ flattened_keywords : Sequence [str ] = (),
36
+ rpa : "bool|None" = None ,
37
+ ):
31
38
"""Factory method to constructs :class:`~.executionresult.Result` objects.
32
39
33
40
:param sources: XML or JSON source(s) containing execution results.
34
41
Can be specified as paths (``pathlib.Path`` or ``str``), opened file
35
42
objects, or strings/bytes containing XML/JSON directly.
36
- :param options: Configuration options.
37
- Using ``merge=True`` causes multiple results to be combined so that
38
- tests in the latter results replace the ones in the original.
39
- Setting ``rpa`` either to ``True`` (RPA mode) or ``False`` (test
40
- automation) sets execution mode explicitly. By default, it is got
43
+ :param merge: When ``True`` and multiple sources are given, results are merged
44
+ instead of combined.
45
+ :param include_keywords: When ``False``, keyword and control structure information
46
+ is not parsed. This can save considerable amount of time and memory.
47
+ :param flattened_keywords: List of patterns controlling what keywords
48
+ and control structures to flatten. See the documentation of
49
+ the ``--flattenkeywords`` option for more details.
50
+ :param rpa: Setting ``rpa`` either to ``True`` (RPA mode) or ``False`` (test
51
+ automation) sets the execution mode explicitly. By default, the mode is got
41
52
from processed output files and conflicting modes cause an error.
42
- Other options are passed directly to the
43
- :class:`ExecutionResultBuilder` object used internally.
44
53
:returns: :class:`~.executionresult.Result` instance.
45
54
46
55
A source is considered to be JSON in these cases:
@@ -53,7 +62,12 @@ def ExecutionResult(*sources, **options):
53
62
"""
54
63
if not sources :
55
64
raise DataError ("One or more data source needed." )
56
- if options .pop ("merge" , False ):
65
+ options = {
66
+ "include_keywords" : include_keywords ,
67
+ "flattened_keywords" : flattened_keywords ,
68
+ "rpa" : rpa ,
69
+ }
70
+ if merge :
57
71
return _merge_results (sources [0 ], sources [1 :], options )
58
72
if len (sources ) > 1 :
59
73
return _combine_results (sources , options )
@@ -63,8 +77,8 @@ def ExecutionResult(*sources, **options):
63
77
def _merge_results (original , merged , options ):
64
78
result = ExecutionResult (original , ** options )
65
79
merger = Merger (result , rpa = result .rpa )
66
- for path in merged :
67
- merged = ExecutionResult (path , ** options )
80
+ for source in merged :
81
+ merged = ExecutionResult (source , ** options )
68
82
merger .merge (merged )
69
83
return result
70
84
@@ -75,40 +89,44 @@ def _combine_results(sources, options):
75
89
76
90
def _single_result (source , options ):
77
91
if is_json_source (source ):
78
- return _json_result (source , options )
79
- return _xml_result (source , options )
92
+ return _json_result (source , ** options )
93
+ return _xml_result (source , ** options )
80
94
81
95
82
- def _json_result (source , options ):
96
+ def _json_result (source , include_keywords , flattened_keywords , rpa ):
83
97
try :
84
- return Result .from_json (source , rpa = options . get ( " rpa" ) )
98
+ return Result .from_json (source , rpa = rpa )
85
99
except IOError as err :
86
100
error = err .strerror
87
101
except Exception :
88
102
error = get_error_message ()
89
103
raise DataError (f"Reading JSON source '{ source } ' failed: { error } " )
90
104
91
105
92
- def _xml_result (source , options ):
106
+ def _xml_result (source , include_keywords , flattened_keywords , rpa ):
93
107
ets = ETSource (source )
94
- result = Result (source , rpa = options .pop ("rpa" , None ))
108
+ builder = ExecutionResultBuilder (ets , include_keywords , flattened_keywords )
109
+ result = Result (source , rpa = rpa )
95
110
try :
96
- return ExecutionResultBuilder ( ets , ** options ) .build (result )
111
+ return builder .build (result )
97
112
except IOError as err :
98
113
error = err .strerror
99
114
except Exception :
100
115
error = get_error_message ()
101
116
raise DataError (f"Reading XML source '{ ets } ' failed: { error } " )
102
117
103
118
119
+ # TODO:
120
+ # - Rename e.g. to XmlExecutionResultBuilder. Probably best done in a major release.
121
+ # - Add Result.from_xml as a more convenient API. Could be done in RF 7.4.
104
122
class ExecutionResultBuilder :
105
123
"""Builds :class:`~.executionresult.Result` objects based on XML output files.
106
124
107
125
Instead of using this builder directly, it is recommended to use the
108
126
:func:`ExecutionResult` factory method.
109
127
"""
110
128
111
- def __init__ (self , source , include_keywords = True , flattened_keywords = None ):
129
+ def __init__ (self , source , include_keywords = True , flattened_keywords = () ):
112
130
"""
113
131
:param source: Path to the XML output file to build
114
132
:class:`~.executionresult.Result` objects from.
0 commit comments