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
@@ -19,7 +19,7 @@ from robot.parsing import File, ModelVisitor, Token
19
19
  from robot.utils import NormalizedDict
20
20
  from robot.variables import VariableMatches
21
21
 
22
- from ..model import For, If, IfBranch, TestSuite, TestCase, Try, TryBranch, While
22
+ from ..model import For, Group, If, IfBranch, TestSuite, TestCase, Try, TryBranch, While
23
23
  from ..resourcemodel import ResourceFile, UserKeyword
24
24
  from .settings import FileSettings
25
25
 
@@ -62,6 +62,15 @@ class SettingsBuilder(ModelVisitor):
62
62
  self.settings.default_tags = node.values
63
63
 
64
64
  def visit_TestTags(self, node):
65
+ for tag in node.values:
66
+ if tag.startswith('-'):
67
+ LOGGER.warn(
68
+ f"Error in file '{self.suite.source}' on line {node.lineno}: "
69
+ f"Setting tags starting with a hyphen like '{tag}' using the "
70
+ f"'Test Tags' setting is deprecated. In Robot Framework 8.0 this "
71
+ f"syntax will be used for removing tags. Escape the tag like "
72
+ f"'\\{tag}' to use the literal value and to avoid this warning."
73
+ )
65
74
  self.settings.test_tags = node.values
66
75
 
67
76
  def visit_KeywordTags(self, node):
@@ -167,7 +176,7 @@ class ResourceBuilder(ModelVisitor):
167
176
 
168
177
  class BodyBuilder(ModelVisitor):
169
178
 
170
- def __init__(self, model: 'TestCase|UserKeyword|For|If|Try|While|None' = None):
179
+ def __init__(self, model: 'TestCase|UserKeyword|For|If|Try|While|Group|None' = None):
171
180
  self.model = model
172
181
 
173
182
  def visit_For(self, node):
@@ -176,6 +185,9 @@ class BodyBuilder(ModelVisitor):
176
185
  def visit_While(self, node):
177
186
  WhileBuilder(self.model).build(node)
178
187
 
188
+ def visit_Group(self, node):
189
+ GroupBuilder(self.model).build(node)
190
+
179
191
  def visit_If(self, node):
180
192
  IfBuilder(self.model).build(node)
181
193
 
@@ -240,7 +252,7 @@ class TestCaseBuilder(BodyBuilder):
240
252
 
241
253
  def _set_template(self, parent, template):
242
254
  for item in parent.body:
243
- if item.type == item.FOR:
255
+ if item.type in (item.FOR, item.GROUP):
244
256
  self._set_template(item, template)
245
257
  elif item.type == item.IF_ELSE_ROOT:
246
258
  for branch in item.body:
@@ -365,7 +377,7 @@ class KeywordBuilder(BodyBuilder):
365
377
  class ForBuilder(BodyBuilder):
366
378
  model: For
367
379
 
368
- def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While'):
380
+ def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While|Group'):
369
381
  super().__init__(parent.body.create_for())
370
382
 
371
383
  def build(self, node):
@@ -387,7 +399,7 @@ class ForBuilder(BodyBuilder):
387
399
  class IfBuilder(BodyBuilder):
388
400
  model: 'IfBranch|None'
389
401
 
390
- def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While'):
402
+ def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While|Group'):
391
403
  super().__init__()
392
404
  self.root = parent.body.create_if()
393
405
 
@@ -427,14 +439,13 @@ class IfBuilder(BodyBuilder):
427
439
  class TryBuilder(BodyBuilder):
428
440
  model: 'TryBranch|None'
429
441
 
430
- def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While'):
442
+ def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While|Group'):
431
443
  super().__init__()
432
444
  self.root = parent.body.create_try()
433
- self.template_error = None
434
445
 
435
446
  def build(self, node):
436
- self.root.config(lineno=node.lineno)
437
- errors = self._get_errors(node)
447
+ self.root.config(lineno=node.lineno,
448
+ error=format_error(self._get_errors(node)))
438
449
  while node:
439
450
  self.model = self.root.body.create_branch(node.type, node.patterns,
440
451
  node.pattern_type, node.assign,
@@ -442,10 +453,6 @@ class TryBuilder(BodyBuilder):
442
453
  for step in node.body:
443
454
  self.visit(step)
444
455
  node = node.next
445
- if self.template_error:
446
- errors += (self.template_error,)
447
- if errors:
448
- self.root.error = format_error(errors)
449
456
  return self.root
450
457
 
451
458
  def _get_errors(self, node):
@@ -456,21 +463,40 @@ class TryBuilder(BodyBuilder):
456
463
  errors += node.end.errors
457
464
  return errors
458
465
 
459
- def visit_TemplateArguments(self, node):
460
- self.template_error = 'Templates cannot be used with TRY.'
461
-
462
466
 
463
467
  class WhileBuilder(BodyBuilder):
464
468
  model: While
465
469
 
466
- def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While'):
470
+ def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While|Group'):
467
471
  super().__init__(parent.body.create_while())
468
472
 
473
+ def build(self, node):
474
+ self.model.config(condition=node.condition,
475
+ limit=node.limit,
476
+ on_limit=node.on_limit,
477
+ on_limit_message=node.on_limit_message,
478
+ lineno=node.lineno,
479
+ error=format_error(self._get_errors(node)))
480
+ for step in node.body:
481
+ self.visit(step)
482
+ return self.model
483
+
484
+ def _get_errors(self, node):
485
+ errors = node.header.errors + node.errors
486
+ if node.end:
487
+ errors += node.end.errors
488
+ return errors
489
+
490
+
491
+ class GroupBuilder(BodyBuilder):
492
+ model: Group
493
+
494
+ def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While|Group'):
495
+ super().__init__(parent.body.create_group())
496
+
469
497
  def build(self, node):
470
498
  error = format_error(self._get_errors(node))
471
- self.model.config(condition=node.condition, limit=node.limit,
472
- on_limit=node.on_limit, on_limit_message=node.on_limit_message,
473
- lineno=node.lineno, error=error)
499
+ self.model.config(name=node.name, lineno=node.lineno, error=error)
474
500
  for step in node.body:
475
501
  self.visit(step)
476
502
  return self.model
@@ -13,8 +13,9 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- import inspect
17
16
  import asyncio
17
+ import inspect
18
+ import sys
18
19
  from contextlib import contextmanager
19
20
 
20
21
  from robot.errors import DataError, ExecutionFailed
@@ -95,7 +96,6 @@ EXECUTION_CONTEXTS = ExecutionContexts()
95
96
 
96
97
 
97
98
  class _ExecutionContext:
98
- _started_keywords_threshold = 100
99
99
 
100
100
  def __init__(self, suite, namespace, output, dry_run=False, asynchronous=None):
101
101
  self.suite = suite
@@ -180,8 +180,11 @@ class _ExecutionContext:
180
180
  return self.namespace.variables
181
181
 
182
182
  def continue_on_failure(self, default=False):
183
- parents = ([self.test] if self.test else []) + self.user_keywords
184
- for index, parent in enumerate(reversed(parents)):
183
+ parents = [result for _, result, implementation in reversed(self.steps)
184
+ if implementation and implementation.type == 'USER KEYWORD']
185
+ if self.test:
186
+ parents.append(self.test)
187
+ for index, parent in enumerate(parents):
185
188
  robot = parent.tags.robot
186
189
  if index == 0 and robot('stop-on-failure'):
187
190
  return False
@@ -195,10 +198,10 @@ class _ExecutionContext:
195
198
 
196
199
  @property
197
200
  def allow_loop_control(self):
198
- for _, step in reversed(self.steps):
199
- if step.type == 'ITERATION':
201
+ for _, result, _ in reversed(self.steps):
202
+ if result.type == 'ITERATION':
200
203
  return True
201
- if step.type == 'KEYWORD' and step.owner != 'BuiltIn':
204
+ if result.type == 'KEYWORD' and result.owner != 'BuiltIn':
202
205
  return False
203
206
  return False
204
207
 
@@ -249,10 +252,8 @@ class _ExecutionContext:
249
252
  self.timeout_occurred = False
250
253
 
251
254
  def start_body_item(self, data, result, implementation=None):
252
- self.steps.append((data, result))
253
- if len(self.steps) > self._started_keywords_threshold:
254
- raise DataError('Maximum limit of started keywords and control '
255
- 'structures exceeded.')
255
+ self._prevent_execution_close_to_recursion_limit()
256
+ self.steps.append((data, result, implementation))
256
257
  output = self.output
257
258
  args = (data, result)
258
259
  if implementation:
@@ -274,6 +275,7 @@ class _ExecutionContext:
274
275
  method = {
275
276
  result.FOR: output.start_for,
276
277
  result.WHILE: output.start_while,
278
+ result.GROUP: output.start_group,
277
279
  result.IF_ELSE_ROOT: output.start_if,
278
280
  result.IF: output.start_if_branch,
279
281
  result.ELSE: output.start_if_branch,
@@ -290,6 +292,14 @@ class _ExecutionContext:
290
292
  }[result.type]
291
293
  method(*args)
292
294
 
295
+ def _prevent_execution_close_to_recursion_limit(self):
296
+ try:
297
+ sys._getframe(sys.getrecursionlimit() - 100)
298
+ except (ValueError, AttributeError):
299
+ pass
300
+ else:
301
+ raise DataError('Recursive execution stopped.')
302
+
293
303
  def end_body_item(self, data, result, implementation=None):
294
304
  output = self.output
295
305
  args = (data, result)
@@ -312,6 +322,7 @@ class _ExecutionContext:
312
322
  method = {
313
323
  result.FOR: output.end_for,
314
324
  result.WHILE: output.end_while,
325
+ result.GROUP: output.end_group,
315
326
  result.IF_ELSE_ROOT: output.end_if,
316
327
  result.IF: output.end_if_branch,
317
328
  result.ELSE: output.end_if_branch,
@@ -82,7 +82,7 @@ class LibraryKeyword(KeywordImplementation):
82
82
  return EmbeddedArgumentsRunner(self, name)
83
83
  if self._resolve_args_until is not None:
84
84
  dry_run = RUN_KW_REGISTER.get_dry_run(self.owner.real_name, self.name)
85
- return RunKeywordRunner(self, execute_in_dry_run=dry_run)
85
+ return RunKeywordRunner(self, dry_run_children=dry_run)
86
86
  return LibraryKeywordRunner(self, languages=languages)
87
87
 
88
88
  def resolve_arguments(self, args: 'Sequence[str|Any]',
@@ -131,23 +131,27 @@ class LibraryKeywordRunner:
131
131
  kw = self.keyword.bind(data)
132
132
  assignment = VariableAssignment(data.assign)
133
133
  self._config_result(result, data, kw, assignment)
134
- with StatusReporter(data, result, context, run=False, implementation=kw):
134
+ with StatusReporter(data, result, context, implementation=kw,
135
+ run=self._get_initial_dry_run_status(kw)):
135
136
  assignment.validate_assignment()
136
137
  if self._executed_in_dry_run(kw):
137
138
  self._run(data, kw, context)
138
139
  else:
139
140
  self._resolve_arguments(data, kw)
140
- self._end_dry_run(data, kw, result, context)
141
+ self._dry_run(data, kw, result, context)
141
142
 
142
- def _end_dry_run(self, data: KeywordData, kw: 'LibraryKeyword',
143
- result: KeywordResult, context):
144
- pass
143
+ def _get_initial_dry_run_status(self, kw):
144
+ return self._executed_in_dry_run(kw)
145
145
 
146
146
  def _executed_in_dry_run(self, kw: 'LibraryKeyword'):
147
147
  return (kw.owner.name == 'BuiltIn'
148
148
  and kw.name in ('Import Library', 'Set Library Search Order',
149
149
  'Set Tags', 'Remove Tags', 'Import Resource'))
150
150
 
151
+ def _dry_run(self, data: KeywordData, kw: 'LibraryKeyword', result: KeywordResult,
152
+ context):
153
+ pass
154
+
151
155
 
152
156
  class EmbeddedArgumentsRunner(LibraryKeywordRunner):
153
157
 
@@ -167,9 +171,9 @@ class EmbeddedArgumentsRunner(LibraryKeywordRunner):
167
171
 
168
172
  class RunKeywordRunner(LibraryKeywordRunner):
169
173
 
170
- def __init__(self, keyword: 'LibraryKeyword', execute_in_dry_run=False):
174
+ def __init__(self, keyword: 'LibraryKeyword', dry_run_children=False):
171
175
  super().__init__(keyword)
172
- self.execute_in_dry_run = execute_in_dry_run
176
+ self._dry_run_children = dry_run_children
173
177
 
174
178
  def _get_timeout(self, context):
175
179
  # These keywords are not affected by timeouts. Keywords they execute are.
@@ -183,25 +187,31 @@ class RunKeywordRunner(LibraryKeywordRunner):
183
187
  finally:
184
188
  STOP_SIGNAL_MONITOR.stop_running_keyword()
185
189
 
186
- def _end_dry_run(self, data: KeywordData, kw: 'LibraryKeyword',
187
- result: KeywordResult, context):
190
+ def _get_initial_dry_run_status(self, kw):
191
+ return self._dry_run_children or super()._get_initial_dry_run_status(kw)
192
+
193
+ def _dry_run(self, data: KeywordData, kw: 'LibraryKeyword', result: KeywordResult,
194
+ context):
188
195
  wrapper = UserKeyword(name=kw.name,
189
- doc="Wraps keywords executed by '{kw.name}' in dry-run.",
196
+ doc=f"Wraps keywords executed by '{kw.name}' in dry-run.",
190
197
  parent=kw.parent)
191
- wrapper.body = [k for k in self._get_dry_run_keywords(kw, data.args)
192
- if not contains_variable(k.name)]
198
+ for child in self._get_dry_run_children(kw, data.args):
199
+ if not contains_variable(child.name):
200
+ child.lineno = data.lineno
201
+ wrapper.body.append(child)
193
202
  BodyRunner(context).run(wrapper, result)
194
203
 
195
- def _get_dry_run_keywords(self, kw: 'LibraryKeyword', args):
196
- if not self.execute_in_dry_run:
204
+ def _get_dry_run_children(self, kw: 'LibraryKeyword', args):
205
+ if not self._dry_run_children:
197
206
  return []
198
207
  if kw.name == 'Run Keyword If':
199
- return self._get_dry_run_keywords_for_run_keyword_if(args)
208
+ return self._get_dry_run_children_for_run_keyword_if(args)
200
209
  if kw.name == 'Run Keywords':
201
- return self._get_dry_run_keywords_for_run_keyword(args)
202
- return self._get_dry_run_keywords_based_on_name(kw, args)
210
+ return self._get_dry_run_children_for_run_keyword(args)
211
+ index = kw.args.positional.index('name')
212
+ return [KeywordData(name=args[index], args=args[index+1:])]
203
213
 
204
- def _get_dry_run_keywords_for_run_keyword_if(self, given_args):
214
+ def _get_dry_run_children_for_run_keyword_if(self, given_args):
205
215
  for kw_call in self._get_run_kw_if_calls(given_args):
206
216
  if kw_call:
207
217
  yield KeywordData(name=kw_call[0], args=kw_call[1:])
@@ -235,7 +245,7 @@ class RunKeywordRunner(LibraryKeywordRunner):
235
245
  return True
236
246
  return any(is_list_variable(item) for item in kw_call)
237
247
 
238
- def _get_dry_run_keywords_for_run_keyword(self, given_args):
248
+ def _get_dry_run_children_for_run_keyword(self, given_args):
239
249
  for kw_call in self._get_run_kws_calls(given_args):
240
250
  yield KeywordData(name=kw_call[0], args=kw_call[1:])
241
251
 
@@ -250,7 +260,3 @@ class RunKeywordRunner(LibraryKeywordRunner):
250
260
  yield kw_call
251
261
  if given_args:
252
262
  yield given_args
253
-
254
- def _get_dry_run_keywords_based_on_name(self, kw: 'LibraryKeyword', given_args):
255
- index = kw.args.positional.index('name')
256
- return [KeywordData(name=given_args[index], args=given_args[index+1:])]
@@ -46,7 +46,7 @@ from robot.output import LOGGER, Output, pyloggingconf
46
46
  from robot.utils import format_assign_message, setter
47
47
  from robot.variables import VariableResolver
48
48
 
49
- from .bodyrunner import ForRunner, IfRunner, KeywordRunner, TryRunner, WhileRunner
49
+ from .bodyrunner import ForRunner, GroupRunner, IfRunner, KeywordRunner, TryRunner, WhileRunner
50
50
  from .randomizer import Randomizer
51
51
  from .statusreporter import StatusReporter
52
52
 
@@ -58,15 +58,15 @@ if TYPE_CHECKING:
58
58
 
59
59
  IT = TypeVar('IT', bound='IfBranch|TryBranch')
60
60
  BodyItemParent = Union['TestSuite', 'TestCase', 'UserKeyword', 'For', 'If', 'IfBranch',
61
- 'Try', 'TryBranch', 'While', None]
61
+ 'Try', 'TryBranch', 'While', 'Group', None]
62
62
 
63
63
 
64
- class Body(model.BaseBody['Keyword', 'For', 'While', 'If', 'Try', 'Var', 'Return',
64
+ class Body(model.BaseBody['Keyword', 'For', 'While', 'Group', 'If', 'Try', 'Var', 'Return',
65
65
  'Continue', 'Break', 'model.Message', 'Error']):
66
66
  __slots__ = ()
67
67
 
68
68
 
69
- class Branches(model.BaseBranches['Keyword', 'For', 'While', 'If', 'Try', 'Var', 'Return',
69
+ class Branches(model.BaseBranches['Keyword', 'For', 'While', 'Group', 'If', 'Try', 'Var', 'Return',
70
70
  'Continue', 'Break', 'model.Message', 'Error', IT]):
71
71
  __slots__ = ()
72
72
 
@@ -259,6 +259,33 @@ class While(model.While, WithSource):
259
259
  iteration = WhileIteration(self, self.lineno, self.error)
260
260
  iteration.body = [item.to_dict() for item in self.body]
261
261
  return iteration
262
+ self.error = error
263
+
264
+
265
+ @Body.register
266
+ class Group(model.Group, WithSource):
267
+ __slots__ = ['lineno', 'error']
268
+ body_class = Body
269
+
270
+ def __init__(self, name: str = '',
271
+ parent: BodyItemParent = None,
272
+ lineno: 'int|None' = None,
273
+ error: 'str|None' = None):
274
+ super().__init__(name, parent)
275
+ self.lineno = lineno
276
+ self.error = error
277
+
278
+ def to_dict(self) -> DataDict:
279
+ data = super().to_dict()
280
+ if self.lineno:
281
+ data['lineno'] = self.lineno
282
+ if self.error:
283
+ data['error'] = self.error
284
+ return data
285
+
286
+ def run(self, result, context, run=True, templated=False):
287
+ result = result.body.create_group(self.name)
288
+ return GroupRunner(context, run, templated).run(self, result)
262
289
 
263
290
 
264
291
  class IfBranch(model.IfBranch, WithSource):
@@ -13,9 +13,11 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
+ from abc import ABC
17
+
16
18
  from robot.errors import PassExecution
17
19
  from robot.model import TagPatterns
18
- from robot.utils import html_escape, test_or_task
20
+ from robot.utils import html_escape, plural_or_not as s, seq2str, test_or_task
19
21
 
20
22
 
21
23
  class Failure:
@@ -49,10 +51,10 @@ class Exit:
49
51
  self.error = False
50
52
  self.fatal = False
51
53
 
52
- def failure_occurred(self, fatal=False):
54
+ def failure_occurred(self, fatal=False, suite_setup=False):
53
55
  if fatal:
54
56
  self.fatal = True
55
- if self.failure_mode:
57
+ if self.failure_mode and not suite_setup:
56
58
  self.failure = True
57
59
 
58
60
  def error_occurred(self):
@@ -67,7 +69,7 @@ class Exit:
67
69
  return bool(self.failure or self.error or self.fatal)
68
70
 
69
71
 
70
- class _ExecutionStatus:
72
+ class ExecutionStatus(ABC):
71
73
 
72
74
  def __init__(self, parent, exit=None):
73
75
  self.parent = parent
@@ -75,7 +77,6 @@ class _ExecutionStatus:
75
77
  self.failure = Failure()
76
78
  self.skipped = False
77
79
  self._teardown_allowed = False
78
- self._rpa = False
79
80
 
80
81
  @property
81
82
  def failed(self):
@@ -96,7 +97,8 @@ class _ExecutionStatus:
96
97
  self.skipped = True
97
98
  else:
98
99
  self.failure.setup = msg
99
- self.exit.failure_occurred(error.exit)
100
+ self.exit.failure_occurred(error.exit,
101
+ suite_setup=isinstance(self, SuiteStatus))
100
102
  self._teardown_allowed = True
101
103
 
102
104
  def teardown_executed(self, error=None):
@@ -151,7 +153,7 @@ class _ExecutionStatus:
151
153
  return ParentMessage(self.parent).message
152
154
 
153
155
 
154
- class SuiteStatus(_ExecutionStatus):
156
+ class SuiteStatus(ExecutionStatus):
155
157
 
156
158
  def __init__(self, parent=None, exit_on_failure=False, exit_on_error=False,
157
159
  skip_teardown_on_exit=False):
@@ -165,19 +167,19 @@ class SuiteStatus(_ExecutionStatus):
165
167
  return SuiteMessage(self).message
166
168
 
167
169
 
168
- class TestStatus(_ExecutionStatus):
170
+ class TestStatus(ExecutionStatus):
169
171
 
170
- def __init__(self, parent, test, skip_on_failure=None, rpa=False):
172
+ def __init__(self, parent, test, skip_on_failure=(), rpa=False):
171
173
  super().__init__(parent)
172
- self._test = test
173
- self._skip_on_failure_tags = skip_on_failure
174
- self._rpa = rpa
174
+ self.test = test
175
+ self.skip_on_failure_tags = TagPatterns(skip_on_failure)
176
+ self.rpa = rpa
175
177
 
176
178
  def test_failed(self, message=None, error=None):
177
179
  if error is not None:
178
180
  message = str(error)
179
181
  skip = error.skip
180
- fatal = error.exit
182
+ fatal = error.exit or self.test.tags.robot('exit-on-failure')
181
183
  else:
182
184
  skip = fatal = False
183
185
  if skip:
@@ -202,26 +204,32 @@ class TestStatus(_ExecutionStatus):
202
204
  return False
203
205
 
204
206
  def _skip_on_failure(self):
205
- return (self._test.tags.robot('skip-on-failure')
206
- or self._skip_on_failure_tags
207
- and TagPatterns(self._skip_on_failure_tags).match(self._test.tags))
207
+ return (self.test.tags.robot('skip-on-failure')
208
+ or self.skip_on_failure_tags.match(self.test.tags))
208
209
 
209
- def _skip_on_fail_msg(self, msg):
210
+ def _skip_on_fail_msg(self, fail_msg):
211
+ if self.test.tags.robot('skip-on-failure'):
212
+ tags = ['robot:skip-on-failure']
213
+ kind = 'tag'
214
+ else:
215
+ tags = self.skip_on_failure_tags
216
+ kind = 'tag' if tags.is_constant else 'tag pattern'
210
217
  return test_or_task(
211
- "{Test} failed but skip-on-failure mode was active and it was marked "
212
- "skipped.\n\nOriginal failure:\n%s" % msg, rpa=self._rpa
218
+ f"Failed {{test}} skipped using {seq2str(tags)} {kind}{s(tags)}.\n\n"
219
+ f"Original failure:\n{fail_msg}", rpa=self.rpa
213
220
  )
214
221
 
215
222
  def _my_message(self):
216
223
  return TestMessage(self).message
217
224
 
218
225
 
219
- class _Message:
220
- setup_message = NotImplemented
221
- setup_skipped_message = NotImplemented
222
- teardown_skipped_message = NotImplemented
223
- teardown_message = NotImplemented
224
- also_teardown_message = NotImplemented
226
+ class Message(ABC):
227
+ setup_message = ''
228
+ setup_skipped_message = ''
229
+ teardown_skipped_message = ''
230
+ teardown_message = ''
231
+ also_teardown_message = ''
232
+ also_teardown_skip_message = ''
225
233
 
226
234
  def __init__(self, status):
227
235
  self.failure = status.failure
@@ -234,11 +242,11 @@ class _Message:
234
242
 
235
243
  def _get_message_before_teardown(self):
236
244
  if self.failure.setup_skipped:
237
- return self._format_setup_or_teardown_message(
238
- self.setup_skipped_message, self.failure.setup_skipped)
245
+ return self._format_setup_or_teardown_message(self.setup_skipped_message,
246
+ self.failure.setup_skipped)
239
247
  if self.failure.setup:
240
- return self._format_setup_or_teardown_message(
241
- self.setup_message, self.failure.setup)
248
+ return self._format_setup_or_teardown_message(self.setup_message,
249
+ self.failure.setup)
242
250
  return self.failure.test_skipped or self.failure.test or ''
243
251
 
244
252
  def _format_setup_or_teardown_message(self, prefix, message):
@@ -271,7 +279,7 @@ class _Message:
271
279
  return self.also_teardown_skip_message % (teardown, message)
272
280
 
273
281
 
274
- class TestMessage(_Message):
282
+ class TestMessage(Message):
275
283
  setup_message = 'Setup failed:\n%s'
276
284
  teardown_message = 'Teardown failed:\n%s'
277
285
  setup_skipped_message = '%s'
@@ -279,12 +287,11 @@ class TestMessage(_Message):
279
287
  also_teardown_message = '%s\n\nAlso teardown failed:\n%s'
280
288
  also_teardown_skip_message = 'Skipped in teardown:\n%s\n\nEarlier message:\n%s'
281
289
  exit_on_fatal_message = 'Test execution stopped due to a fatal error.'
282
- exit_on_failure_message = \
283
- 'Failure occurred and exit-on-failure mode is in use.'
290
+ exit_on_failure_message = 'Failure occurred and exit-on-failure mode is in use.'
284
291
  exit_on_error_message = 'Error occurred and exit-on-error mode is in use.'
285
292
 
286
293
  def __init__(self, status):
287
- _Message.__init__(self, status)
294
+ super().__init__(status)
288
295
  self.exit = status.exit
289
296
 
290
297
  @property
@@ -301,7 +308,7 @@ class TestMessage(_Message):
301
308
  return ''
302
309
 
303
310
 
304
- class SuiteMessage(_Message):
311
+ class SuiteMessage(Message):
305
312
  setup_message = 'Suite setup failed:\n%s'
306
313
  setup_skipped_message = 'Skipped in suite setup:\n%s'
307
314
  teardown_skipped_message = 'Skipped in suite teardown:\n%s'
@@ -320,4 +327,4 @@ class ParentMessage(SuiteMessage):
320
327
  def __init__(self, status):
321
328
  while status.parent and status.parent.failed:
322
329
  status = status.parent
323
- SuiteMessage.__init__(self, status)
330
+ super().__init__(status)
@@ -62,7 +62,7 @@ class StatusReporter:
62
62
  result.status = failure.status
63
63
  if not isinstance(failure, (BreakLoop, ContinueLoop, ReturnFromKeyword)):
64
64
  result.message = failure.message
65
- if self.initial_test_status == 'PASS':
65
+ if self.initial_test_status == 'PASS' and result.status != 'NOT RUN':
66
66
  context.test.status = result.status
67
67
  result.elapsed_time = datetime.now() - result.start_time
68
68
  orig_status = (result.status, result.message)