robotframework 7.1.1__zip → 7.2b1__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. {robotframework-7.1.1 → robotframework-7.2b1}/BUILD.rst +2 -2
  2. {robotframework-7.1.1 → robotframework-7.2b1}/PKG-INFO +2 -2
  3. {robotframework-7.1.1 → robotframework-7.2b1}/setup.py +1 -1
  4. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/api/__init__.py +33 -9
  5. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/api/deco.py +8 -6
  6. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/api/interfaces.py +21 -4
  7. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/api/parsing.py +72 -68
  8. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/conf/languages.py +4 -3
  9. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/conf/settings.py +11 -10
  10. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/errors.py +3 -1
  11. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/htmlfilewriter.py +3 -0
  12. robotframework-7.2b1/src/robot/htmldata/libdoc/libdoc.html +408 -0
  13. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/log.html +1 -1
  14. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/report.html +1 -1
  15. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/testdata.js +1 -1
  16. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdoc.py +19 -11
  17. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/htmlwriter.py +7 -4
  18. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/model.py +7 -5
  19. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/writer.py +2 -2
  20. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/BuiltIn.py +109 -32
  21. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/Collections.py +18 -4
  22. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/__init__.py +3 -3
  23. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/body.py +48 -57
  24. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/control.py +35 -4
  25. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/message.py +13 -8
  26. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/modelobject.py +26 -0
  27. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/statistics.py +13 -9
  28. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/stats.py +12 -14
  29. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/suitestatistics.py +8 -9
  30. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/tags.py +10 -0
  31. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/tagstatistics.py +7 -8
  32. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/testcase.py +1 -0
  33. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/testsuite.py +1 -0
  34. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/totalstatistics.py +14 -21
  35. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/visitor.py +29 -3
  36. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/__init__.py +3 -2
  37. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/console/dotted.py +6 -3
  38. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/debugfile.py +3 -3
  39. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/filelogger.py +7 -3
  40. robotframework-7.2b1/src/robot/output/jsonlogger.py +338 -0
  41. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/librarylogger.py +12 -11
  42. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/listeners.py +49 -47
  43. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/logger.py +33 -20
  44. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/loggerapi.py +6 -0
  45. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/loggerhelper.py +26 -55
  46. robotframework-7.2b1/src/robot/output/loglevel.py +54 -0
  47. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/output.py +21 -17
  48. robotframework-7.2b1/src/robot/output/outputfile.py +174 -0
  49. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/pyloggingconf.py +2 -0
  50. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/xmllogger.py +40 -169
  51. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/lexer/blocklexers.py +25 -12
  52. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/lexer/statementlexers.py +16 -7
  53. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/lexer/tokens.py +2 -1
  54. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/model/__init__.py +1 -1
  55. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/model/blocks.py +34 -2
  56. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/model/statements.py +32 -2
  57. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/parser/blockparsers.py +7 -2
  58. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/rebot.py +10 -2
  59. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/reporting/jsmodelbuilders.py +1 -1
  60. robotframework-7.2b1/src/robot/reporting/outputwriter.py +30 -0
  61. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/__init__.py +1 -1
  62. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/executionerrors.py +9 -9
  63. robotframework-7.2b1/src/robot/result/executionresult.py +331 -0
  64. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/messagefilter.py +14 -10
  65. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/model.py +90 -18
  66. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/resultbuilder.py +2 -5
  67. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/xmlelementhandlers.py +20 -9
  68. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/run.py +18 -6
  69. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/__init__.py +1 -1
  70. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/embedded.py +7 -6
  71. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/typeconverters.py +14 -2
  72. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/typeinfo.py +22 -2
  73. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/bodyrunner.py +41 -0
  74. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/builder/settings.py +2 -1
  75. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/builder/transformers.py +46 -20
  76. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/context.py +22 -11
  77. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/librarykeyword.py +1 -1
  78. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/librarykeywordrunner.py +29 -23
  79. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/model.py +31 -4
  80. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/status.py +42 -35
  81. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/statusreporter.py +1 -1
  82. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/suiterunner.py +22 -15
  83. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/importer.py +39 -23
  84. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/unic.py +7 -8
  85. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/evaluation.py +21 -2
  86. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/replacer.py +20 -24
  87. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/scopes.py +17 -8
  88. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/variables.py +4 -1
  89. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/version.py +1 -1
  90. {robotframework-7.1.1 → robotframework-7.2b1}/src/robotframework.egg-info/PKG-INFO +2 -2
  91. {robotframework-7.1.1 → robotframework-7.2b1}/src/robotframework.egg-info/SOURCES.txt +3 -4
  92. robotframework-7.1.1/src/robot/htmldata/libdoc/doc_formatting.css +0 -74
  93. robotframework-7.1.1/src/robot/htmldata/libdoc/libdoc.css +0 -747
  94. robotframework-7.1.1/src/robot/htmldata/libdoc/libdoc.html +0 -702
  95. robotframework-7.1.1/src/robot/htmldata/libdoc/print.css +0 -11
  96. robotframework-7.1.1/src/robot/htmldata/libdoc/pygments.css +0 -162
  97. robotframework-7.1.1/src/robot/reporting/outputwriter.py +0 -48
  98. robotframework-7.1.1/src/robot/result/executionresult.py +0 -201
  99. {robotframework-7.1.1 → robotframework-7.2b1}/AUTHORS.rst +0 -0
  100. {robotframework-7.1.1 → robotframework-7.2b1}/CONTRIBUTING.rst +0 -0
  101. {robotframework-7.1.1 → robotframework-7.2b1}/COPYRIGHT.txt +0 -0
  102. {robotframework-7.1.1 → robotframework-7.2b1}/INSTALL.rst +0 -0
  103. {robotframework-7.1.1 → robotframework-7.2b1}/LICENSE.txt +0 -0
  104. {robotframework-7.1.1 → robotframework-7.2b1}/MANIFEST.in +0 -0
  105. {robotframework-7.1.1 → robotframework-7.2b1}/README.rst +0 -0
  106. {robotframework-7.1.1 → robotframework-7.2b1}/setup.cfg +0 -0
  107. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/__init__.py +0 -0
  108. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/__main__.py +0 -0
  109. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/api/exceptions.py +0 -0
  110. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/api/logger.py +0 -0
  111. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/api/py.typed +0 -0
  112. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/conf/__init__.py +0 -0
  113. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/conf/gatherfailed.py +0 -0
  114. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/__init__.py +0 -0
  115. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/common/__init__.py +0 -0
  116. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/common/js_disabled.css +0 -0
  117. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/common/storage.js +0 -0
  118. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/jsonwriter.py +0 -0
  119. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/lib/__init__.py +0 -0
  120. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
  121. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/lib/jquery.min.js +0 -0
  122. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
  123. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
  124. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
  125. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/libdoc/__init__.py +0 -0
  126. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/__init__.py +0 -0
  127. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/common.css +0 -0
  128. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/doc_formatting.css +0 -0
  129. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/fileloading.js +0 -0
  130. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/log.css +0 -0
  131. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/log.js +0 -0
  132. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/model.js +0 -0
  133. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/print.css +0 -0
  134. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/report.css +0 -0
  135. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/util.js +0 -0
  136. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/rebot/view.js +0 -0
  137. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/template.py +0 -0
  138. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/testdoc/__init__.py +0 -0
  139. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/testdoc/testdoc.css +0 -0
  140. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/htmldata/testdoc/testdoc.html +0 -0
  141. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/__init__.py +0 -0
  142. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/builder.py +0 -0
  143. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/consoleviewer.py +0 -0
  144. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/datatypes.py +0 -0
  145. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/htmlutils.py +0 -0
  146. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/jsonbuilder.py +0 -0
  147. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/jsonwriter.py +0 -0
  148. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/output.py +0 -0
  149. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/robotbuilder.py +0 -0
  150. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/standardtypes.py +0 -0
  151. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/xmlbuilder.py +0 -0
  152. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libdocpkg/xmlwriter.py +0 -0
  153. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/DateTime.py +0 -0
  154. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/Dialogs.py +0 -0
  155. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/Easter.py +0 -0
  156. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/OperatingSystem.py +0 -0
  157. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/Process.py +0 -0
  158. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/Remote.py +0 -0
  159. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/Screenshot.py +0 -0
  160. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/String.py +0 -0
  161. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/Telnet.py +0 -0
  162. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/XML.py +0 -0
  163. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/__init__.py +0 -0
  164. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/libraries/dialogs_py.py +0 -0
  165. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/configurer.py +0 -0
  166. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/filter.py +0 -0
  167. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/fixture.py +0 -0
  168. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/itemlist.py +0 -0
  169. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/keyword.py +0 -0
  170. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/metadata.py +0 -0
  171. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/modifier.py +0 -0
  172. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/namepatterns.py +0 -0
  173. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/model/tagsetter.py +0 -0
  174. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/console/__init__.py +0 -0
  175. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/console/highlighting.py +0 -0
  176. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/console/quiet.py +0 -0
  177. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/console/verbose.py +0 -0
  178. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/output/stdoutlogsplitter.py +0 -0
  179. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/__init__.py +0 -0
  180. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/lexer/__init__.py +0 -0
  181. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/lexer/context.py +0 -0
  182. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/lexer/lexer.py +0 -0
  183. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/lexer/settings.py +0 -0
  184. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/lexer/tokenizer.py +0 -0
  185. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/model/visitor.py +0 -0
  186. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/parser/__init__.py +0 -0
  187. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/parser/fileparser.py +0 -0
  188. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/parser/parser.py +0 -0
  189. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/parsing/suitestructure.py +0 -0
  190. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/pythonpathsetter.py +0 -0
  191. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/reporting/__init__.py +0 -0
  192. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/reporting/expandkeywordmatcher.py +0 -0
  193. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/reporting/jsbuildingcontext.py +0 -0
  194. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/reporting/jsexecutionresult.py +0 -0
  195. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/reporting/jswriter.py +0 -0
  196. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/reporting/logreportwriters.py +0 -0
  197. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/reporting/resultwriter.py +0 -0
  198. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/reporting/stringcache.py +0 -0
  199. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/reporting/xunitwriter.py +0 -0
  200. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/configurer.py +0 -0
  201. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/flattenkeywordmatcher.py +0 -0
  202. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/keywordremover.py +0 -0
  203. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/merger.py +0 -0
  204. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/modeldeprecation.py +0 -0
  205. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/suiteteardownfailed.py +0 -0
  206. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/result/visitor.py +0 -0
  207. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/__init__.py +0 -0
  208. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/argumentconverter.py +0 -0
  209. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/argumentmapper.py +0 -0
  210. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/argumentparser.py +0 -0
  211. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/argumentresolver.py +0 -0
  212. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/argumentspec.py +0 -0
  213. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/argumentvalidator.py +0 -0
  214. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/customconverters.py +0 -0
  215. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/typeinfoparser.py +0 -0
  216. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/arguments/typevalidator.py +0 -0
  217. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/builder/__init__.py +0 -0
  218. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/builder/builders.py +0 -0
  219. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/builder/parsers.py +0 -0
  220. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/dynamicmethods.py +0 -0
  221. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/importer.py +0 -0
  222. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/invalidkeyword.py +0 -0
  223. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/keywordfinder.py +0 -0
  224. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/keywordimplementation.py +0 -0
  225. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/libraryscopes.py +0 -0
  226. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/namespace.py +0 -0
  227. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/outputcapture.py +0 -0
  228. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/randomizer.py +0 -0
  229. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/resourcemodel.py +0 -0
  230. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/runkwregister.py +0 -0
  231. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/signalhandler.py +0 -0
  232. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/testlibraries.py +0 -0
  233. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/timeouts/__init__.py +0 -0
  234. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/timeouts/nosupport.py +0 -0
  235. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/timeouts/posix.py +0 -0
  236. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/timeouts/windows.py +0 -0
  237. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/running/userkeywordrunner.py +0 -0
  238. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/testdoc.py +0 -0
  239. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/__init__.py +0 -0
  240. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/application.py +0 -0
  241. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/argumentparser.py +0 -0
  242. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/asserts.py +0 -0
  243. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/charwidth.py +0 -0
  244. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/compress.py +0 -0
  245. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/connectioncache.py +0 -0
  246. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/dotdict.py +0 -0
  247. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/encoding.py +0 -0
  248. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/encodingsniffer.py +0 -0
  249. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/error.py +0 -0
  250. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/escaping.py +0 -0
  251. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/etreewrapper.py +0 -0
  252. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/filereader.py +0 -0
  253. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/frange.py +0 -0
  254. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/htmlformatters.py +0 -0
  255. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/markuputils.py +0 -0
  256. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/markupwriters.py +0 -0
  257. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/match.py +0 -0
  258. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/misc.py +0 -0
  259. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/normalizing.py +0 -0
  260. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/notset.py +0 -0
  261. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/platform.py +0 -0
  262. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/recommendations.py +0 -0
  263. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/restreader.py +0 -0
  264. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/robotenv.py +0 -0
  265. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/robotinspect.py +0 -0
  266. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/robotio.py +0 -0
  267. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/robotpath.py +0 -0
  268. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/robottime.py +0 -0
  269. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/robottypes.py +0 -0
  270. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/setter.py +0 -0
  271. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/sortable.py +0 -0
  272. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/text.py +0 -0
  273. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/utils/typehints.py +0 -0
  274. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/__init__.py +0 -0
  275. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/assigner.py +0 -0
  276. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/filesetter.py +0 -0
  277. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/finders.py +0 -0
  278. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/notfound.py +0 -0
  279. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/resolvable.py +0 -0
  280. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/search.py +0 -0
  281. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/store.py +0 -0
  282. {robotframework-7.1.1 → robotframework-7.2b1}/src/robot/variables/tablesetter.py +0 -0
  283. {robotframework-7.1.1 → robotframework-7.2b1}/src/robotframework.egg-info/dependency_links.txt +0 -0
  284. {robotframework-7.1.1 → robotframework-7.2b1}/src/robotframework.egg-info/entry_points.txt +0 -0
  285. {robotframework-7.1.1 → robotframework-7.2b1}/src/robotframework.egg-info/top_level.txt +0 -0
  286. {robotframework-7.1.1 → robotframework-7.2b1}/tasks.py +0 -0
@@ -22,7 +22,7 @@ from typing import cast, Iterator, Sequence, TextIO, Union
22
22
  from robot.utils import file_writer, test_or_task
23
23
 
24
24
  from .statements import (Break, Continue, ElseHeader, ElseIfHeader, End, ExceptHeader,
25
- Error, FinallyHeader, ForHeader, IfHeader, KeywordCall,
25
+ Error, FinallyHeader, ForHeader, GroupHeader, IfHeader, KeywordCall,
26
26
  KeywordName, Node, ReturnSetting, ReturnStatement,
27
27
  SectionHeader, Statement, TemplateArguments, TestCaseName,
28
28
  TryHeader, Var, WhileHeader)
@@ -99,7 +99,7 @@ class Block(Container, ABC):
99
99
  def _body_is_empty(self):
100
100
  # This works with tests, keywords, and blocks inside them, not with sections.
101
101
  valid = (KeywordCall, TemplateArguments, Var, Continue, Break, ReturnSetting,
102
- ReturnStatement, NestedBlock, Error)
102
+ Group, ReturnStatement, NestedBlock, Error)
103
103
  return not any(isinstance(node, valid) for node in self.body)
104
104
 
105
105
 
@@ -328,6 +328,7 @@ class Try(NestedBlock):
328
328
  if self.type == Token.TRY:
329
329
  self._validate_structure()
330
330
  self._validate_end()
331
+ TemplatesNotAllowed('TRY').check(self)
331
332
 
332
333
  def _validate_body(self):
333
334
  if self._body_is_empty():
@@ -395,6 +396,21 @@ class While(NestedBlock):
395
396
  self.errors += ('WHILE loop cannot be empty.',)
396
397
  if not self.end:
397
398
  self.errors += ('WHILE loop must have closing END.',)
399
+ TemplatesNotAllowed('WHILE').check(self)
400
+
401
+
402
+ class Group(NestedBlock):
403
+ header: GroupHeader
404
+
405
+ @property
406
+ def name(self) -> str:
407
+ return self.header.name
408
+
409
+ def validate(self, ctx: 'ValidationContext'):
410
+ if self._body_is_empty():
411
+ self.errors += ('GROUP cannot be empty.',)
412
+ if not self.end:
413
+ self.errors += ('GROUP must have closing END.',)
398
414
 
399
415
 
400
416
  class ModelWriter(ModelVisitor):
@@ -504,3 +520,19 @@ class LastStatementFinder(ModelVisitor):
504
520
 
505
521
  def visit_Statement(self, statement: Statement):
506
522
  self.statement = statement
523
+
524
+
525
+ class TemplatesNotAllowed(ModelVisitor):
526
+
527
+ def __init__(self, kind: str):
528
+ self.kind = kind
529
+ self.found = False
530
+
531
+ def check(self, model: Node):
532
+ self.found = False
533
+ self.visit(model)
534
+ if self.found:
535
+ model.errors += (f'{self.kind} does not support templates.',)
536
+
537
+ def visit_TemplateArguments(self, node: None):
538
+ self.found = True
@@ -1204,6 +1204,35 @@ class WhileHeader(Statement):
1204
1204
  self._validate_options()
1205
1205
 
1206
1206
 
1207
+ @Statement.register
1208
+ class GroupHeader(Statement):
1209
+ type = Token.GROUP
1210
+
1211
+ @classmethod
1212
+ def from_params(cls, name: str = '',
1213
+ indent: str = FOUR_SPACES, separator: str = FOUR_SPACES,
1214
+ eol: str = EOL) -> 'GroupHeader':
1215
+ tokens = [Token(Token.SEPARATOR, indent),
1216
+ Token(Token.GROUP)]
1217
+ if name:
1218
+ tokens.extend(
1219
+ [Token(Token.SEPARATOR, separator),
1220
+ Token(Token.ARGUMENT, name)]
1221
+ )
1222
+ tokens.append(Token(Token.EOL, eol))
1223
+ return cls(tokens)
1224
+
1225
+ @property
1226
+ def name(self) -> str:
1227
+ return ', '.join(self.get_values(Token.ARGUMENT))
1228
+
1229
+ def validate(self, ctx: 'ValidationContext'):
1230
+ names = self.get_values(Token.ARGUMENT)
1231
+ if len(names) > 1:
1232
+ self.errors += (f"GROUP accepts only one argument as name, got {len(names)} "
1233
+ f"arguments {seq2str(names)}.",)
1234
+
1235
+
1207
1236
  @Statement.register
1208
1237
  class Var(Statement):
1209
1238
  type = Token.VAR
@@ -1343,8 +1372,9 @@ class Config(Statement):
1343
1372
 
1344
1373
  @property
1345
1374
  def language(self) -> 'Language|None':
1346
- value = self.get_value(Token.CONFIG)
1347
- return Language.from_name(value[len('language:'):]) if value else None
1375
+ value = ' '.join(self.get_values(Token.CONFIG))
1376
+ lang = value.split(':', 1)[1].strip()
1377
+ return Language.from_name(lang) if lang else None
1348
1378
 
1349
1379
 
1350
1380
  @Statement.register
@@ -16,7 +16,7 @@
16
16
  from abc import ABC, abstractmethod
17
17
 
18
18
  from ..lexer import Token
19
- from ..model import (Block, Container, End, For, If, Keyword, NestedBlock,
19
+ from ..model import (Block, Container, End, For, Group, If, Keyword, NestedBlock,
20
20
  Statement, TestCase, Try, While)
21
21
 
22
22
 
@@ -44,10 +44,11 @@ class BlockParser(Parser, ABC):
44
44
  super().__init__(model)
45
45
  self.parsers: 'dict[str, type[NestedBlockParser]]' = {
46
46
  Token.FOR: ForParser,
47
+ Token.WHILE: WhileParser,
47
48
  Token.IF: IfParser,
48
49
  Token.INLINE_IF: IfParser,
49
50
  Token.TRY: TryParser,
50
- Token.WHILE: WhileParser
51
+ Token.GROUP: GroupParser
51
52
  }
52
53
 
53
54
  def handles(self, statement: Statement) -> bool:
@@ -101,6 +102,10 @@ class WhileParser(NestedBlockParser):
101
102
  model: While
102
103
 
103
104
 
105
+ class GroupParser(NestedBlockParser):
106
+ model: Group
107
+
108
+
104
109
  class IfParser(NestedBlockParser):
105
110
  model: If
106
111
 
@@ -122,7 +122,6 @@ Options
122
122
  --processemptysuite Processes output also if the top level suite is
123
123
  empty. Useful e.g. with --include/--exclude when it
124
124
  is not an error that there are no matches.
125
- Use --skiponfailure when starting execution instead.
126
125
  -d --outputdir dir Where to create output files. The default is the
127
126
  directory where Rebot is run from and the given path
128
127
  is considered relative to that unless it is absolute.
@@ -183,7 +182,6 @@ Options
183
182
  pattern. Documentation is shown in `Test Details` and
184
183
  also as a tooltip in `Statistics by Tag`. Pattern can
185
184
  use `*`, `?` and `[]` as wildcards like --test.
186
- Documentation can contain formatting like --doc.
187
185
  Examples: --tagdoc mytag:Example
188
186
  --tagdoc "owner-*:Original author"
189
187
  --tagstatlink pattern:link:title * Add external links into `Statistics by
@@ -307,6 +305,16 @@ ROBOT_SYSLOG_LEVEL Log level to use when writing to the syslog file.
307
305
  Available levels are the same as for --loglevel
308
306
  command line option and the default is INFO.
309
307
 
308
+ Return Codes
309
+ ============
310
+
311
+ 0 All tests passed.
312
+ 1-249 Returned number of tests failed.
313
+ 250 250 or more failures.
314
+ 251 Help or version information printed.
315
+ 252 Invalid data or command line options.
316
+ 255 Unexpected internal error.
317
+
310
318
  Examples
311
319
  ========
312
320
 
@@ -25,7 +25,7 @@ STATUSES = {'FAIL': 0, 'PASS': 1, 'SKIP': 2, 'NOT RUN': 3}
25
25
  KEYWORD_TYPES = {'KEYWORD': 0, 'SETUP': 1, 'TEARDOWN': 2,
26
26
  'FOR': 3, 'ITERATION': 4, 'IF': 5, 'ELSE IF': 6, 'ELSE': 7,
27
27
  'RETURN': 8, 'VAR': 9, 'TRY': 10, 'EXCEPT': 11, 'FINALLY': 12,
28
- 'WHILE': 13, 'CONTINUE': 14, 'BREAK': 15, 'ERROR': 16}
28
+ 'WHILE': 13, 'GROUP': 14, 'CONTINUE': 15, 'BREAK': 16, 'ERROR': 17}
29
29
 
30
30
 
31
31
  class JsModelBuilder:
@@ -0,0 +1,30 @@
1
+ # Copyright 2008-2015 Nokia Networks
2
+ # Copyright 2016- Robot Framework Foundation
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ from robot.output.xmllogger import XmlLogger, LegacyXmlLogger
17
+
18
+
19
+ class OutputWriter(XmlLogger):
20
+ generator = 'Rebot'
21
+
22
+ def end_result(self, result):
23
+ self.close()
24
+
25
+
26
+ class LegacyOutputWriter(LegacyXmlLogger):
27
+ generator = 'Rebot'
28
+
29
+ def end_result(self, result):
30
+ self.close()
@@ -38,7 +38,7 @@ __ http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#
38
38
  """
39
39
 
40
40
  from .executionresult import Result
41
- from .model import (Break, Continue, Error, For, ForIteration, If, IfBranch, Keyword,
41
+ from .model import (Break, Continue, Error, For, ForIteration, Group, If, IfBranch, Keyword,
42
42
  Message, Return, TestCase, TestSuite, Try, TryBranch, Var, While,
43
43
  WhileIteration)
44
44
  from .resultbuilder import ExecutionResult, ExecutionResultBuilder
@@ -13,6 +13,8 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
+ from typing import Iterator, Sequence
17
+
16
18
  from robot.model import ItemList, Message
17
19
  from robot.utils import setter
18
20
 
@@ -24,31 +26,29 @@ class ExecutionErrors:
24
26
  """
25
27
  id = 'errors'
26
28
 
27
- def __init__(self, messages=None):
28
- #: A :class:`list-like object <robot.model.itemlist.ItemList>` of
29
- #: :class:`~robot.model.message.Message` instances.
29
+ def __init__(self, messages: Sequence[Message] = ()):
30
30
  self.messages = messages
31
31
 
32
32
  @setter
33
- def messages(self, messages):
33
+ def messages(self, messages) -> ItemList[Message]:
34
34
  return ItemList(Message, {'parent': self}, items=messages)
35
35
 
36
- def add(self, other):
36
+ def add(self, other: 'ExecutionErrors'):
37
37
  self.messages.extend(other.messages)
38
38
 
39
39
  def visit(self, visitor):
40
40
  visitor.visit_errors(self)
41
41
 
42
- def __iter__(self):
42
+ def __iter__(self) -> Iterator[Message]:
43
43
  return iter(self.messages)
44
44
 
45
- def __len__(self):
45
+ def __len__(self) -> int:
46
46
  return len(self.messages)
47
47
 
48
- def __getitem__(self, index):
48
+ def __getitem__(self, index) -> Message:
49
49
  return self.messages[index]
50
50
 
51
- def __str__(self):
51
+ def __str__(self) -> str:
52
52
  if not self:
53
53
  return 'No execution errors'
54
54
  if len(self) == 1:
@@ -0,0 +1,331 @@
1
+ # Copyright 2008-2015 Nokia Networks
2
+ # Copyright 2016- Robot Framework Foundation
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ from datetime import datetime
17
+ from pathlib import Path
18
+ from typing import overload, TextIO
19
+
20
+ from robot.errors import DataError
21
+ from robot.model import Statistics
22
+ from robot.model.modelobject import JsonDumper, JsonLoader # FIXME: Expose via `robot.model` or move to `robot.utils`.
23
+ from robot.utils import setter
24
+ from robot.version import get_full_version
25
+
26
+ from .executionerrors import ExecutionErrors
27
+ from .model import TestSuite
28
+
29
+
30
+ def is_json_source(source) -> bool:
31
+ if isinstance(source, bytes):
32
+ # ISO-8859-1 is most likely *not* the right encoding, but decoding bytes
33
+ # with it always succeeds and characters we care about ought to be correct
34
+ # at least if the right encoding is UTF-8 or any ISO-8859-x encoding.
35
+ source = source.decode('ISO-8859-1')
36
+ if isinstance(source, str):
37
+ source = source.strip()
38
+ first, last = (source[0], source[-1]) if source else ('', '')
39
+ if (first, last) == ('{', '}'):
40
+ return True
41
+ if (first, last) == ('<', '>'):
42
+ return False
43
+ path = Path(source)
44
+ elif isinstance(source, Path):
45
+ path = source
46
+ elif hasattr(source, 'name') and isinstance(source.name, str):
47
+ path = Path(source.name)
48
+ else:
49
+ return False
50
+ return bool(path and path.suffix.lower() == '.json')
51
+
52
+
53
+ class Result:
54
+ """Test execution results.
55
+
56
+ Can be created based on XML output files using the
57
+ :func:`~.resultbuilder.ExecutionResult`
58
+ factory method. Also returned by the
59
+ :meth:`robot.running.TestSuite.run <robot.running.model.TestSuite.run>`
60
+ method.
61
+ """
62
+
63
+ def __init__(self, source: 'Path|str|None' = None,
64
+ suite: 'TestSuite|None' = None,
65
+ errors: 'ExecutionErrors|None' = None,
66
+ rpa: 'bool|None' = None,
67
+ generator: str = 'unknown',
68
+ generation_time: 'datetime|str|None' = None):
69
+ self.source = Path(source) if isinstance(source, str) else source
70
+ self.suite = suite or TestSuite()
71
+ self.errors = errors or ExecutionErrors()
72
+ self.rpa = rpa
73
+ self.generator = generator
74
+ self.generation_time = generation_time
75
+ self._status_rc = True
76
+ self._stat_config = {}
77
+
78
+ @setter
79
+ def rpa(self, rpa: 'bool|None') -> 'bool|None':
80
+ if rpa is not None:
81
+ self._set_suite_rpa(self.suite, rpa)
82
+ return rpa
83
+
84
+ def _set_suite_rpa(self, suite, rpa):
85
+ suite.rpa = rpa
86
+ for child in suite.suites:
87
+ self._set_suite_rpa(child, rpa)
88
+
89
+ @setter
90
+ def generation_time(self, timestamp: 'datetime|str|None') -> 'datetime|None':
91
+ if datetime is None:
92
+ return None
93
+ if isinstance(timestamp, str):
94
+ return datetime.fromisoformat(timestamp)
95
+ return timestamp
96
+
97
+ @property
98
+ def statistics(self) -> Statistics:
99
+ """Execution statistics.
100
+
101
+ Statistics are created based on the contained ``suite`` and possible
102
+ :func:`configuration <configure>`.
103
+
104
+ Statistics are created every time this property is accessed. Saving
105
+ them to a variable is thus often a good idea to avoid re-creating
106
+ them unnecessarily::
107
+
108
+ from robot.api import ExecutionResult
109
+
110
+ result = ExecutionResult('output.xml')
111
+ result.configure(stat_config={'suite_stat_level': 2,
112
+ 'tag_stat_combine': 'tagANDanother'})
113
+ stats = result.statistics
114
+ print(stats.total.failed)
115
+ print(stats.total.passed)
116
+ print(stats.tags.combined[0].total)
117
+ """
118
+ return Statistics(self.suite, rpa=self.rpa, **self._stat_config)
119
+
120
+ @property
121
+ def return_code(self) -> int:
122
+ """Execution return code.
123
+
124
+ By default, returns the number of failed tests or tasks (max 250),
125
+ but can be :func:`configured <configure>` to always return 0.
126
+ """
127
+ if self._status_rc:
128
+ return min(self.suite.statistics.failed, 250)
129
+ return 0
130
+
131
+ @property
132
+ def generated_by_robot(self) -> bool:
133
+ return self.generator.split()[0].upper() == 'ROBOT'
134
+
135
+ def configure(self, status_rc=True, suite_config=None, stat_config=None):
136
+ """Configures the result object and objects it contains.
137
+
138
+ :param status_rc: If set to ``False``, :attr:`return_code` always
139
+ returns 0.
140
+ :param suite_config: A dictionary of configuration options passed
141
+ to :meth:`~.result.testsuite.TestSuite.configure` method of
142
+ the contained ``suite``.
143
+ :param stat_config: A dictionary of configuration options used when
144
+ creating :attr:`statistics`.
145
+ """
146
+ if suite_config:
147
+ self.suite.configure(**suite_config)
148
+ self._status_rc = status_rc
149
+ self._stat_config = stat_config or {}
150
+
151
+ @classmethod
152
+ def from_json(cls, source: 'str|bytes|TextIO|Path',
153
+ rpa: 'bool|None' = None) -> 'Result':
154
+ """Construct a result object from JSON data.
155
+
156
+ The data is given as the ``source`` parameter. It can be:
157
+
158
+ - a string (or bytes) containing the data directly,
159
+ - an open file object where to read the data from, or
160
+ - a path (``pathlib.Path`` or string) to a UTF-8 encoded file to read.
161
+
162
+ Data can contain either:
163
+
164
+ - full result data (contains suite information, execution errors, etc.)
165
+ got, for example, from the :meth:`to_json` method, or
166
+ - only suite information got, for example, from
167
+ :meth:`result.testsuite.TestSuite.to_json <TestSuite.to_json>`.
168
+
169
+ :attr:`statistics` are populated automatically based on suite information
170
+ and thus ignored if they are present in the data.
171
+
172
+ The ``rpa`` argument can be used to override the RPA mode. The mode is
173
+ got from the data by default.
174
+
175
+ New in Robot Framework 7.2.
176
+ """
177
+ try:
178
+ data = JsonLoader().load(source)
179
+ except (TypeError, ValueError) as err:
180
+ raise DataError(f'Loading JSON data failed: {err}')
181
+ if 'suite' in data:
182
+ result = cls._from_full_json(data)
183
+ else:
184
+ result = cls._from_suite_json(data)
185
+ result.rpa = data.get('rpa', False) if rpa is None else rpa
186
+ if isinstance(source, Path):
187
+ result.source = source
188
+ elif isinstance(source, str) and source[0] != '{' and Path(source).exists():
189
+ result.source = Path(source)
190
+ return result
191
+
192
+ @classmethod
193
+ def _from_full_json(cls, data) -> 'Result':
194
+ return Result(suite=TestSuite.from_dict(data['suite']),
195
+ errors=ExecutionErrors(data.get('errors')),
196
+ generator=data.get('generator'),
197
+ generation_time=data.get('generated'))
198
+
199
+ @classmethod
200
+ def _from_suite_json(cls, data) -> 'Result':
201
+ return Result(suite=TestSuite.from_dict(data))
202
+
203
+ @overload
204
+ def to_json(self, file: None = None, *,
205
+ include_statistics: bool = True,
206
+ ensure_ascii: bool = False, indent: int = 0,
207
+ separators: 'tuple[str, str]' = (',', ':')) -> str:
208
+ ...
209
+
210
+ @overload
211
+ def to_json(self, file: 'TextIO|Path|str', *,
212
+ include_statistics: bool = True,
213
+ ensure_ascii: bool = False, indent: int = 0,
214
+ separators: 'tuple[str, str]' = (',', ':')) -> None:
215
+ ...
216
+
217
+ def to_json(self, file: 'None|TextIO|Path|str' = None, *,
218
+ include_statistics: bool = True,
219
+ ensure_ascii: bool = False, indent: int = 0,
220
+ separators: 'tuple[str, str]' = (',', ':')) -> 'str|None':
221
+ """Serialize results into JSON.
222
+
223
+ The ``file`` parameter controls what to do with the resulting JSON data.
224
+ It can be:
225
+
226
+ - ``None`` (default) to return the data as a string,
227
+ - an open file object where to write the data to, or
228
+ - a path (``pathlib.Path`` or string) to a file where to write
229
+ the data using UTF-8 encoding.
230
+
231
+ The ``include_statistics`` controls including statistics information
232
+ in the resulting JSON data. Statistics are not needed if the serialized
233
+ JSON data is converted back to a ``Result`` object, but they can be
234
+ useful for external tools.
235
+
236
+ The remaining optional parameters are used for JSON formatting.
237
+ They are passed directly to the underlying json__ module, but
238
+ the defaults differ from what ``json`` uses.
239
+
240
+ New in Robot Framework 7.2.
241
+
242
+ __ https://docs.python.org/3/library/json.html
243
+ """
244
+ data = {'generator': get_full_version('Rebot'),
245
+ 'generated': datetime.now().isoformat(),
246
+ 'rpa': self.rpa,
247
+ 'suite': self.suite.to_dict()}
248
+ if include_statistics:
249
+ data['statistics'] = self.statistics.to_dict()
250
+ data['errors'] = self.errors.messages.to_dicts()
251
+ return JsonDumper(ensure_ascii=ensure_ascii, indent=indent,
252
+ separators=separators).dump(data, file)
253
+
254
+ def save(self, target=None, legacy_output=False):
255
+ """Save results as XML or JSON file.
256
+
257
+ :param target: Target where to save results to. Can be a path
258
+ (``pathlib.Path`` or ``str``) or an open file object. If omitted,
259
+ uses the :attr:`source` which overwrites the original file.
260
+ :param legacy_output: Save XML results in Robot Framework 6.x compatible
261
+ format. New in Robot Framework 7.0.
262
+
263
+ File type is got based on the ``target``. The type is JSON if the ``target``
264
+ is a path that has a ``.json`` suffix or if it is an open file that has
265
+ a ``name`` attribute with a ``.json`` suffix. Otherwise, the type is XML.
266
+
267
+ It is also possible to use :meth:`to_json` for JSON serialization. Compared
268
+ to this method, it allows returning the JSON in addition to writing it
269
+ into a file, and it also supports customizing JSON formatting.
270
+
271
+ Support for saving results in JSON is new in Robot Framework 7.0.
272
+ Originally only suite information was saved in that case, but starting
273
+ from Robot Framework 7.2, also JSON results contain full result data
274
+ including, for example, execution errors and statistics.
275
+ """
276
+ from robot.reporting.outputwriter import LegacyOutputWriter, OutputWriter
277
+
278
+ target = target or self.source
279
+ if not target:
280
+ raise ValueError('Path required.')
281
+ if is_json_source(target):
282
+ self.to_json(target)
283
+ else:
284
+ writer = OutputWriter if not legacy_output else LegacyOutputWriter
285
+ self.visit(writer(target, rpa=self.rpa))
286
+
287
+ def visit(self, visitor):
288
+ """An entry point to visit the whole result object.
289
+
290
+ :param visitor: An instance of :class:`~.visitor.ResultVisitor`.
291
+
292
+ Visitors can gather information, modify results, etc. See
293
+ :mod:`~robot.result` package for a simple usage example.
294
+
295
+ Notice that it is also possible to call :meth:`result.suite.visit
296
+ <robot.result.testsuite.TestSuite.visit>` if there is no need to
297
+ visit the contained ``statistics`` or ``errors``.
298
+ """
299
+ visitor.visit_result(self)
300
+
301
+ def handle_suite_teardown_failures(self):
302
+ """Internal usage only."""
303
+ if self.generated_by_robot:
304
+ self.suite.handle_suite_teardown_failures()
305
+
306
+ def set_execution_mode(self, other):
307
+ """Set execution mode based on other result. Internal usage only."""
308
+ if other.rpa is None:
309
+ pass
310
+ elif self.rpa is None:
311
+ self.rpa = other.rpa
312
+ elif self.rpa is not other.rpa:
313
+ this, that = ('task', 'test') if other.rpa else ('test', 'task')
314
+ raise DataError("Conflicting execution modes. File '%s' has %ss "
315
+ "but files parsed earlier have %ss. Use '--rpa' "
316
+ "or '--norpa' options to set the execution mode "
317
+ "explicitly." % (other.source, this, that))
318
+
319
+
320
+ class CombinedResult(Result):
321
+ """Combined results of multiple test executions."""
322
+
323
+ def __init__(self, results=None):
324
+ super().__init__()
325
+ for result in results or ():
326
+ self.add_result(result)
327
+
328
+ def add_result(self, other):
329
+ self.set_execution_mode(other)
330
+ self.suite.suites.append(other.suite)
331
+ self.errors.add(other.errors)
@@ -13,21 +13,25 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- from robot.output.loggerhelper import IsLogged
16
+ from robot import output
17
17
 
18
- from robot.model import SuiteVisitor
18
+ from .visitor import ResultVisitor
19
19
 
20
20
 
21
- class MessageFilter(SuiteVisitor):
21
+ class MessageFilter(ResultVisitor):
22
+
23
+ def __init__(self, level='TRACE'):
24
+ log_level = output.LogLevel(level or 'TRACE')
25
+ self.log_all = log_level.level == 'TRACE'
26
+ self.is_logged = log_level.is_logged
22
27
 
23
- def __init__(self, log_level=None):
24
- self.is_logged = IsLogged(log_level or 'TRACE')
25
28
 
26
29
  def start_suite(self, suite):
27
- if self.is_logged.level == 'TRACE':
30
+ if self.log_all:
28
31
  return False
29
32
 
30
- def start_keyword(self, keyword):
31
- for item in list(keyword.body):
32
- if item.type == item.MESSAGE and not self.is_logged(item.level):
33
- keyword.body.remove(item)
33
+ def start_body_item(self, item):
34
+ if hasattr(item, 'body'):
35
+ for msg in item.body.filter(messages=True):
36
+ if not self.is_logged(msg):
37
+ item.body.remove(msg)