robotframework 7.1rc2__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.1rc2 → robotframework-7.2b1}/BUILD.rst +7 -7
  2. {robotframework-7.1rc2 → robotframework-7.2b1}/PKG-INFO +2 -2
  3. {robotframework-7.1rc2 → robotframework-7.2b1}/setup.py +1 -1
  4. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/__init__.py +33 -9
  5. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/deco.py +8 -6
  6. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/interfaces.py +66 -15
  7. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/parsing.py +72 -68
  8. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/conf/languages.py +4 -3
  9. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/conf/settings.py +11 -10
  10. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/errors.py +3 -3
  11. {robotframework-7.1rc2 → 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.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/log.html +1 -1
  14. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/report.html +1 -1
  15. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/testdata.js +1 -1
  16. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/template.py +0 -2
  17. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdoc.py +19 -11
  18. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/htmlwriter.py +7 -4
  19. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/model.py +7 -5
  20. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/writer.py +2 -2
  21. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/BuiltIn.py +121 -32
  22. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Collections.py +20 -7
  23. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/__init__.py +3 -3
  24. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/body.py +48 -57
  25. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/control.py +35 -4
  26. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/message.py +13 -8
  27. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/modelobject.py +26 -0
  28. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/statistics.py +13 -9
  29. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/stats.py +12 -14
  30. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/suitestatistics.py +8 -9
  31. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/tags.py +10 -0
  32. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/tagstatistics.py +7 -8
  33. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/testcase.py +1 -0
  34. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/testsuite.py +1 -0
  35. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/totalstatistics.py +14 -21
  36. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/visitor.py +29 -3
  37. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/__init__.py +3 -2
  38. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/console/dotted.py +6 -3
  39. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/console/highlighting.py +18 -10
  40. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/debugfile.py +3 -3
  41. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/filelogger.py +7 -3
  42. robotframework-7.2b1/src/robot/output/jsonlogger.py +338 -0
  43. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/librarylogger.py +12 -11
  44. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/listeners.py +49 -47
  45. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/logger.py +33 -20
  46. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/loggerapi.py +6 -0
  47. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/loggerhelper.py +29 -57
  48. robotframework-7.2b1/src/robot/output/loglevel.py +54 -0
  49. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/output.py +21 -17
  50. robotframework-7.2b1/src/robot/output/outputfile.py +174 -0
  51. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/pyloggingconf.py +2 -0
  52. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/xmllogger.py +40 -169
  53. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/blocklexers.py +25 -12
  54. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/statementlexers.py +16 -7
  55. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/tokens.py +2 -1
  56. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/model/__init__.py +1 -1
  57. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/model/blocks.py +34 -2
  58. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/model/statements.py +32 -2
  59. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/parser/blockparsers.py +7 -2
  60. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/rebot.py +10 -2
  61. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/jsmodelbuilders.py +1 -1
  62. robotframework-7.2b1/src/robot/reporting/outputwriter.py +30 -0
  63. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/__init__.py +1 -1
  64. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/executionerrors.py +9 -9
  65. robotframework-7.2b1/src/robot/result/executionresult.py +331 -0
  66. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/messagefilter.py +14 -10
  67. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/model.py +90 -18
  68. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/resultbuilder.py +2 -5
  69. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/xmlelementhandlers.py +20 -9
  70. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/run.py +18 -6
  71. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/__init__.py +1 -1
  72. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/embedded.py +7 -6
  73. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/typeconverters.py +14 -2
  74. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/typeinfo.py +23 -4
  75. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/bodyrunner.py +41 -0
  76. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/builder/settings.py +2 -1
  77. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/builder/transformers.py +46 -20
  78. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/context.py +22 -11
  79. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/librarykeyword.py +1 -1
  80. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/librarykeywordrunner.py +29 -23
  81. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/model.py +31 -4
  82. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/outputcapture.py +2 -1
  83. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/signalhandler.py +7 -3
  84. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/status.py +49 -38
  85. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/statusreporter.py +1 -1
  86. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/suiterunner.py +22 -15
  87. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/userkeywordrunner.py +4 -0
  88. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/importer.py +39 -23
  89. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/unic.py +7 -8
  90. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/evaluation.py +21 -2
  91. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/replacer.py +20 -24
  92. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/scopes.py +19 -9
  93. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/variables.py +4 -1
  94. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/version.py +1 -1
  95. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robotframework.egg-info/PKG-INFO +2 -2
  96. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robotframework.egg-info/SOURCES.txt +3 -4
  97. robotframework-7.1rc2/src/robot/htmldata/libdoc/doc_formatting.css +0 -74
  98. robotframework-7.1rc2/src/robot/htmldata/libdoc/libdoc.css +0 -747
  99. robotframework-7.1rc2/src/robot/htmldata/libdoc/libdoc.html +0 -702
  100. robotframework-7.1rc2/src/robot/htmldata/libdoc/print.css +0 -11
  101. robotframework-7.1rc2/src/robot/htmldata/libdoc/pygments.css +0 -162
  102. robotframework-7.1rc2/src/robot/reporting/outputwriter.py +0 -48
  103. robotframework-7.1rc2/src/robot/result/executionresult.py +0 -201
  104. {robotframework-7.1rc2 → robotframework-7.2b1}/AUTHORS.rst +0 -0
  105. {robotframework-7.1rc2 → robotframework-7.2b1}/CONTRIBUTING.rst +0 -0
  106. {robotframework-7.1rc2 → robotframework-7.2b1}/COPYRIGHT.txt +0 -0
  107. {robotframework-7.1rc2 → robotframework-7.2b1}/INSTALL.rst +0 -0
  108. {robotframework-7.1rc2 → robotframework-7.2b1}/LICENSE.txt +0 -0
  109. {robotframework-7.1rc2 → robotframework-7.2b1}/MANIFEST.in +0 -0
  110. {robotframework-7.1rc2 → robotframework-7.2b1}/README.rst +0 -0
  111. {robotframework-7.1rc2 → robotframework-7.2b1}/setup.cfg +0 -0
  112. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/__init__.py +0 -0
  113. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/__main__.py +0 -0
  114. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/exceptions.py +0 -0
  115. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/logger.py +0 -0
  116. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/py.typed +0 -0
  117. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/conf/__init__.py +0 -0
  118. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/conf/gatherfailed.py +0 -0
  119. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/__init__.py +0 -0
  120. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/common/__init__.py +0 -0
  121. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/common/js_disabled.css +0 -0
  122. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/common/storage.js +0 -0
  123. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/jsonwriter.py +0 -0
  124. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/lib/__init__.py +0 -0
  125. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
  126. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/lib/jquery.min.js +0 -0
  127. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
  128. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
  129. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
  130. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/libdoc/__init__.py +0 -0
  131. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/__init__.py +0 -0
  132. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/common.css +0 -0
  133. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/doc_formatting.css +0 -0
  134. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/fileloading.js +0 -0
  135. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/log.css +0 -0
  136. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/log.js +0 -0
  137. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/model.js +0 -0
  138. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/print.css +0 -0
  139. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/report.css +0 -0
  140. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/util.js +0 -0
  141. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/view.js +0 -0
  142. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/testdoc/__init__.py +0 -0
  143. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/testdoc/testdoc.css +0 -0
  144. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/testdoc/testdoc.html +0 -0
  145. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/__init__.py +0 -0
  146. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/builder.py +0 -0
  147. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/consoleviewer.py +0 -0
  148. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/datatypes.py +0 -0
  149. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/htmlutils.py +0 -0
  150. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/jsonbuilder.py +0 -0
  151. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/jsonwriter.py +0 -0
  152. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/output.py +0 -0
  153. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/robotbuilder.py +0 -0
  154. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/standardtypes.py +0 -0
  155. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/xmlbuilder.py +0 -0
  156. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/xmlwriter.py +0 -0
  157. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/DateTime.py +0 -0
  158. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Dialogs.py +0 -0
  159. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Easter.py +0 -0
  160. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/OperatingSystem.py +0 -0
  161. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Process.py +0 -0
  162. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Remote.py +0 -0
  163. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Screenshot.py +0 -0
  164. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/String.py +0 -0
  165. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Telnet.py +0 -0
  166. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/XML.py +0 -0
  167. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/__init__.py +0 -0
  168. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/dialogs_py.py +0 -0
  169. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/configurer.py +0 -0
  170. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/filter.py +0 -0
  171. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/fixture.py +0 -0
  172. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/itemlist.py +0 -0
  173. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/keyword.py +0 -0
  174. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/metadata.py +0 -0
  175. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/modifier.py +0 -0
  176. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/namepatterns.py +0 -0
  177. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/tagsetter.py +0 -0
  178. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/console/__init__.py +0 -0
  179. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/console/quiet.py +0 -0
  180. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/console/verbose.py +0 -0
  181. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/stdoutlogsplitter.py +0 -0
  182. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/__init__.py +0 -0
  183. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/__init__.py +0 -0
  184. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/context.py +0 -0
  185. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/lexer.py +0 -0
  186. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/settings.py +0 -0
  187. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/tokenizer.py +0 -0
  188. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/model/visitor.py +0 -0
  189. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/parser/__init__.py +0 -0
  190. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/parser/fileparser.py +0 -0
  191. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/parser/parser.py +0 -0
  192. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/suitestructure.py +0 -0
  193. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/pythonpathsetter.py +0 -0
  194. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/__init__.py +0 -0
  195. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/expandkeywordmatcher.py +0 -0
  196. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/jsbuildingcontext.py +0 -0
  197. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/jsexecutionresult.py +0 -0
  198. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/jswriter.py +0 -0
  199. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/logreportwriters.py +0 -0
  200. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/resultwriter.py +0 -0
  201. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/stringcache.py +0 -0
  202. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/xunitwriter.py +0 -0
  203. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/configurer.py +0 -0
  204. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/flattenkeywordmatcher.py +0 -0
  205. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/keywordremover.py +0 -0
  206. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/merger.py +0 -0
  207. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/modeldeprecation.py +0 -0
  208. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/suiteteardownfailed.py +0 -0
  209. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/visitor.py +0 -0
  210. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/__init__.py +0 -0
  211. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/argumentconverter.py +0 -0
  212. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/argumentmapper.py +0 -0
  213. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/argumentparser.py +0 -0
  214. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/argumentresolver.py +0 -0
  215. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/argumentspec.py +0 -0
  216. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/argumentvalidator.py +0 -0
  217. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/customconverters.py +0 -0
  218. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/typeinfoparser.py +0 -0
  219. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/typevalidator.py +0 -0
  220. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/builder/__init__.py +0 -0
  221. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/builder/builders.py +0 -0
  222. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/builder/parsers.py +0 -0
  223. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/dynamicmethods.py +0 -0
  224. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/importer.py +0 -0
  225. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/invalidkeyword.py +0 -0
  226. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/keywordfinder.py +0 -0
  227. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/keywordimplementation.py +0 -0
  228. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/libraryscopes.py +0 -0
  229. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/namespace.py +0 -0
  230. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/randomizer.py +0 -0
  231. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/resourcemodel.py +0 -0
  232. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/runkwregister.py +0 -0
  233. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/testlibraries.py +0 -0
  234. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/timeouts/__init__.py +0 -0
  235. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/timeouts/nosupport.py +0 -0
  236. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/timeouts/posix.py +0 -0
  237. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/timeouts/windows.py +0 -0
  238. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/testdoc.py +0 -0
  239. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/__init__.py +0 -0
  240. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/application.py +0 -0
  241. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/argumentparser.py +0 -0
  242. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/asserts.py +0 -0
  243. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/charwidth.py +0 -0
  244. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/compress.py +0 -0
  245. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/connectioncache.py +0 -0
  246. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/dotdict.py +0 -0
  247. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/encoding.py +0 -0
  248. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/encodingsniffer.py +0 -0
  249. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/error.py +0 -0
  250. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/escaping.py +0 -0
  251. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/etreewrapper.py +0 -0
  252. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/filereader.py +0 -0
  253. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/frange.py +0 -0
  254. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/htmlformatters.py +0 -0
  255. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/markuputils.py +0 -0
  256. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/markupwriters.py +0 -0
  257. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/match.py +0 -0
  258. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/misc.py +0 -0
  259. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/normalizing.py +0 -0
  260. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/notset.py +0 -0
  261. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/platform.py +0 -0
  262. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/recommendations.py +0 -0
  263. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/restreader.py +0 -0
  264. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/robotenv.py +0 -0
  265. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/robotinspect.py +0 -0
  266. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/robotio.py +0 -0
  267. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/robotpath.py +0 -0
  268. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/robottime.py +0 -0
  269. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/robottypes.py +0 -0
  270. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/setter.py +0 -0
  271. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/sortable.py +0 -0
  272. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/text.py +0 -0
  273. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/typehints.py +0 -0
  274. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/__init__.py +0 -0
  275. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/assigner.py +0 -0
  276. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/filesetter.py +0 -0
  277. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/finders.py +0 -0
  278. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/notfound.py +0 -0
  279. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/resolvable.py +0 -0
  280. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/search.py +0 -0
  281. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/store.py +0 -0
  282. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/tablesetter.py +0 -0
  283. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robotframework.egg-info/dependency_links.txt +0 -0
  284. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robotframework.egg-info/entry_points.txt +0 -0
  285. {robotframework-7.1rc2 → robotframework-7.2b1}/src/robotframework.egg-info/top_level.txt +0 -0
  286. {robotframework-7.1rc2 → robotframework-7.2b1}/tasks.py +0 -0
@@ -19,7 +19,8 @@ from robot.errors import ExecutionFailed, ExecutionStatus, DataError, PassExecut
19
19
  from robot.model import SuiteVisitor, TagPatterns
20
20
  from robot.result import (Keyword as KeywordResult, TestCase as TestResult,
21
21
  TestSuite as SuiteResult, Result)
22
- from robot.utils import is_list_like, NormalizedDict, test_or_task
22
+ from robot.utils import (is_list_like, NormalizedDict, plural_or_not as s, seq2str,
23
+ test_or_task)
23
24
  from robot.variables import VariableScopes
24
25
 
25
26
  from .bodyrunner import BodyRunner, KeywordRunner
@@ -60,7 +61,7 @@ class SuiteRunner(SuiteVisitor):
60
61
  start_time=datetime.now(),
61
62
  rpa=self.settings.rpa)
62
63
  if not self.result:
63
- self.result = Result(root_suite=result, rpa=self.settings.rpa)
64
+ self.result = Result(suite=result, rpa=self.settings.rpa)
64
65
  self.result.configure(status_rc=self.settings.status_rc,
65
66
  stat_config=self.settings.statistics_config)
66
67
  else:
@@ -125,19 +126,20 @@ class SuiteRunner(SuiteVisitor):
125
126
 
126
127
  def visit_test(self, data: TestData):
127
128
  settings = self.settings
128
- if data.tags.robot('exclude'):
129
- return
130
- if data.name in self.executed[-1]:
131
- self.output.warn(
132
- test_or_task(f"Multiple {{test}}s with name '{data.name}' executed in "
133
- f"suite '{data.parent.full_name}'.", settings.rpa))
134
- self.executed[-1][data.name] = True
135
129
  result = self.suite_result.tests.create(self._resolve_setting(data.name),
136
130
  self._resolve_setting(data.doc),
137
131
  self._resolve_setting(data.tags),
138
132
  self._get_timeout(data),
139
133
  data.lineno,
140
134
  start_time=datetime.now())
135
+ if result.tags.robot('exclude'):
136
+ self.suite_result.tests.pop()
137
+ return
138
+ if result.name in self.executed[-1]:
139
+ self.output.warn(
140
+ test_or_task(f"Multiple {{test}}s with name '{result.name}' executed "
141
+ f"in suite '{result.parent.full_name}'.", settings.rpa))
142
+ self.executed[-1][result.name] = True
141
143
  self.context.start_test(data, result)
142
144
  status = TestStatus(self.suite_status, result, settings.skip_on_failure,
143
145
  settings.rpa)
@@ -154,14 +156,14 @@ class SuiteRunner(SuiteVisitor):
154
156
  if settings.rpa:
155
157
  data.error = data.error.replace('Test', 'Task')
156
158
  status.test_failed(data.error)
157
- elif data.tags.robot('skip'):
159
+ elif result.tags.robot('skip'):
158
160
  status.test_skipped(
159
- test_or_task("{Test} skipped using 'robot:skip' tag.",
160
- settings.rpa))
161
- elif self.skipped_tags.match(data.tags):
161
+ self._get_skipped_message(['robot:skip'], settings.rpa)
162
+ )
163
+ elif self.skipped_tags.match(result.tags):
162
164
  status.test_skipped(
163
- test_or_task("{Test} skipped using '--skip' command line option.",
164
- settings.rpa))
165
+ self._get_skipped_message(self.skipped_tags, settings.rpa)
166
+ )
165
167
  self._run_setup(data, status, result)
166
168
  if status.passed:
167
169
  runner = BodyRunner(self.context, templated=bool(data.template))
@@ -198,6 +200,11 @@ class SuiteRunner(SuiteVisitor):
198
200
  self.context.end_test(result)
199
201
  self._clear_result(result)
200
202
 
203
+ def _get_skipped_message(self, tags, rpa):
204
+ kind = 'tag' if getattr(tags, 'is_constant', True) else 'tag pattern'
205
+ return test_or_task(f"{{Test}} skipped using {seq2str(tags)} {kind}{s(tags)}.",
206
+ rpa)
207
+
201
208
  def _clear_result(self, result: 'SuiteResult|TestResult'):
202
209
  if result.has_setup:
203
210
  result.setup = None
@@ -85,6 +85,10 @@ class UserKeywordRunner:
85
85
  with context.timeout(timeout):
86
86
  exception, return_value = self._execute(kw, result, context)
87
87
  if exception and not exception.can_continue(context):
88
+ if context.in_teardown and exception.keyword_timeout:
89
+ # Allow execution to continue on teardowns after timeout.
90
+ # https://github.com/robotframework/robotframework/issues/3398
91
+ exception.keyword_timeout = False
88
92
  raise exception
89
93
  return_value = self._handle_return_value(return_value, variables)
90
94
  if exception:
@@ -21,6 +21,7 @@ import inspect
21
21
  from robot.errors import DataError
22
22
 
23
23
  from .error import get_error_details
24
+ from .misc import seq2str
24
25
  from .robotpath import abspath, normpath
25
26
  from .robotinspect import is_init
26
27
  from .robottypes import type_name
@@ -43,9 +44,10 @@ class Importer:
43
44
  """
44
45
  self._type = type or ''
45
46
  self._logger = logger or NoLogger()
46
- self._importers = (ByPathImporter(logger),
47
- NonDottedImporter(logger),
48
- DottedImporter(logger))
47
+ library_import = type and type.upper() == 'LIBRARY'
48
+ self._importers = (ByPathImporter(logger, library_import),
49
+ NonDottedImporter(logger, library_import),
50
+ DottedImporter(logger, library_import))
49
51
  self._by_path_importer = self._importers[0]
50
52
 
51
53
  def import_class_or_module(self, name_or_path, instantiate_with_args=None,
@@ -162,15 +164,14 @@ class Importer:
162
164
  self._raise_import_failed(path, err)
163
165
 
164
166
  def _log_import_succeeded(self, item, name, source):
165
- import_type = '%s ' % self._type.lower() if self._type else ''
167
+ prefix = f'Imported {self._type.lower()}' if self._type else 'Imported'
166
168
  item_type = 'module' if inspect.ismodule(item) else 'class'
167
- location = ("'%s'" % source) if source else 'unknown location'
168
- self._logger.info("Imported %s%s '%s' from %s."
169
- % (import_type, item_type, name, location))
169
+ source = f"'{source}'" if source else 'unknown location'
170
+ self._logger.info(f"{prefix} {item_type} '{name}' from {source}.")
170
171
 
171
172
  def _raise_import_failed(self, name, error):
172
173
  prefix = f'Importing {self._type.lower()}' if self._type else 'Importing'
173
- raise DataError(f"{prefix} '{name}' failed: {error.message}")
174
+ raise DataError(f"{prefix} '{name}' failed: {error}")
174
175
 
175
176
  def _instantiate_if_needed(self, imported, args):
176
177
  if args is None:
@@ -190,7 +191,8 @@ class Importer:
190
191
  try:
191
192
  return imported(*positional, **dict(named))
192
193
  except Exception:
193
- raise DataError('Creating instance failed: %s\n%s' % get_error_details())
194
+ message, traceback = get_error_details()
195
+ raise DataError(f'Creating instance failed: {message}\n{traceback}')
194
196
 
195
197
  def _get_arg_spec(self, imported):
196
198
  # Avoid cyclic import. Yuck.
@@ -205,8 +207,9 @@ class Importer:
205
207
 
206
208
  class _Importer:
207
209
 
208
- def __init__(self, logger):
209
- self._logger = logger
210
+ def __init__(self, logger, library_import=False):
211
+ self.logger = logger
212
+ self.library_import = library_import
210
213
 
211
214
  def _import(self, name, fromlist=None):
212
215
  if name in sys.builtin_module_names:
@@ -223,11 +226,25 @@ class _Importer:
223
226
  def _verify_type(self, imported):
224
227
  if inspect.isclass(imported) or inspect.ismodule(imported):
225
228
  return imported
226
- raise DataError('Expected class or module, got %s.' % type_name(imported))
227
-
228
- def _get_class_from_module(self, module, name=None):
229
- klass = getattr(module, name or module.__name__, None)
230
- return klass if inspect.isclass(klass) else None
229
+ raise DataError(f'Expected class or module, got {type_name(imported)}.')
230
+
231
+ def _get_possible_class(self, module, name=None):
232
+ cls = self._get_class_matching_module_name(module, name)
233
+ if not cls and self.library_import:
234
+ cls = self._get_decorated_library_class_in_imported_module(module)
235
+ return cls or module
236
+
237
+ def _get_class_matching_module_name(self, module, name):
238
+ cls = getattr(module, name or module.__name__, None)
239
+ return cls if inspect.isclass(cls) else None
240
+
241
+ def _get_decorated_library_class_in_imported_module(self, module):
242
+ def predicate(item):
243
+ return (inspect.isclass(item)
244
+ and hasattr(item, 'ROBOT_AUTO_KEYWORDS')
245
+ and item.__module__ == module.__name__)
246
+ classes = [cls for _, cls in inspect.getmembers(module, predicate)]
247
+ return classes[0] if len(classes) == 1 else None
231
248
 
232
249
  def _get_source(self, imported):
233
250
  try:
@@ -248,7 +265,7 @@ class ByPathImporter(_Importer):
248
265
  self._remove_wrong_module_from_sys_modules(path)
249
266
  imported = self._import_by_path(path)
250
267
  if get_class:
251
- imported = self._get_class_from_module(imported) or imported
268
+ imported = self._get_possible_class(imported)
252
269
  return self._verify_type(imported), path
253
270
 
254
271
  def _verify_import_path(self, path):
@@ -264,8 +281,8 @@ class ByPathImporter(_Importer):
264
281
  importing_package = os.path.splitext(path)[1] == ''
265
282
  if self._wrong_module_imported(name, importing_from, importing_package):
266
283
  del sys.modules[name]
267
- self._logger.info("Removed module '%s' from sys.modules to import "
268
- "fresh module." % name)
284
+ self.logger.info(f"Removed module '{name}' from sys.modules to import "
285
+ f"a fresh module.")
269
286
 
270
287
  def _split_path_to_module(self, path):
271
288
  module_dir, module_file = os.path.split(abspath(path))
@@ -307,7 +324,7 @@ class NonDottedImporter(_Importer):
307
324
  def import_(self, name, get_class=True):
308
325
  imported = self._import(name)
309
326
  if get_class:
310
- imported = self._get_class_from_module(imported) or imported
327
+ imported = self._get_possible_class(imported)
311
328
  return self._verify_type(imported), self._get_source(imported)
312
329
 
313
330
 
@@ -322,10 +339,9 @@ class DottedImporter(_Importer):
322
339
  try:
323
340
  imported = getattr(parent, lib_name)
324
341
  except AttributeError:
325
- raise DataError("Module '%s' does not contain '%s'."
326
- % (parent_name, lib_name))
342
+ raise DataError(f"Module '{parent_name}' does not contain '{lib_name}'.")
327
343
  if get_class:
328
- imported = self._get_class_from_module(imported, lib_name) or imported
344
+ imported = self._get_possible_class(imported, lib_name)
329
345
  return self._verify_type(imported), self._get_source(imported)
330
346
 
331
347
 
@@ -26,13 +26,11 @@ def _safe_str(item):
26
26
  if isinstance(item, str):
27
27
  return item
28
28
  if isinstance(item, (bytes, bytearray)):
29
- try:
30
- return item.decode('ASCII')
31
- except UnicodeError:
32
- return ''.join(chr(b) if b < 128 else '\\x%x' % b for b in item)
29
+ # Map each byte to Unicode code point with same ordinal.
30
+ return item.decode('latin-1')
33
31
  try:
34
32
  return str(item)
35
- except:
33
+ except Exception:
36
34
  return _unrepresentable_object(item)
37
35
 
38
36
 
@@ -45,7 +43,7 @@ class PrettyRepr(PrettyPrinter):
45
43
  def format(self, object, context, maxlevels, level):
46
44
  try:
47
45
  return PrettyPrinter.format(self, object, context, maxlevels, level)
48
- except:
46
+ except Exception:
49
47
  return _unrepresentable_object(object), True, False
50
48
 
51
49
  # Don't split strings: https://stackoverflow.com/questions/31485402
@@ -63,5 +61,6 @@ class PrettyRepr(PrettyPrinter):
63
61
 
64
62
  def _unrepresentable_object(item):
65
63
  from .error import get_error_message
66
- return "<Unrepresentable object %s. Error: %s>" \
67
- % (item.__class__.__name__, get_error_message())
64
+
65
+ error = get_error_message()
66
+ return f'<Unrepresentable object {type(item).__name__}. Error: {error}>'
@@ -115,14 +115,33 @@ def _recommend_special_variables(expression):
115
115
  return ''
116
116
  example = []
117
117
  for match in matches:
118
- example[-1:] += [match.before, match.identifier, match.base, match.after]
119
- example = ''.join(example)
118
+ example[-1:] = [match.before, match.identifier + match.base, match.after]
119
+ example = ''.join(_remove_possible_quoting(example))
120
120
  return (f"Variables in the original expression {expression!r} were resolved "
121
121
  f"before the expression was evaluated. Try using {example!r} "
122
122
  f"syntax to avoid that. See Evaluating Expressions appendix in "
123
123
  f"Robot Framework User Guide for more details.")
124
124
 
125
125
 
126
+ def _remove_possible_quoting(example_tokens):
127
+ before = var = after = None
128
+ for index, item in enumerate(example_tokens):
129
+ if index == 0:
130
+ before = item
131
+ elif index % 2 == 1:
132
+ var = item
133
+ else:
134
+ after = item
135
+ if before[-3:] in ('"""', "'''") and after[:3] == before[-3:]:
136
+ before, after = before[:-3], after[3:]
137
+ elif before[-1:] in ('"', "'") and after[:1] == before[-1:]:
138
+ before, after = before[:-1], after[1:]
139
+ yield before
140
+ yield var
141
+ before = after
142
+ yield after
143
+
144
+
126
145
  class EvaluationNamespace(MutableMapping):
127
146
 
128
147
  def __init__(self, variable_store, namespace):
@@ -59,14 +59,11 @@ class VariableReplacer:
59
59
  result = []
60
60
  for item in items:
61
61
  match = search_variable(item, ignore_errors=ignore_errors)
62
- if not match:
63
- result.append(unescape(item))
62
+ value = self._replace(match, ignore_errors)
63
+ if match.is_list_variable() and is_list_like(value):
64
+ result.extend(value)
64
65
  else:
65
- value = self._replace_scalar(match, ignore_errors)
66
- if match.is_list_variable() and is_list_like(value):
67
- result.extend(value)
68
- else:
69
- result.append(value)
66
+ result.append(value)
70
67
  return result
71
68
 
72
69
  def replace_scalar(self, item, ignore_errors=False):
@@ -80,37 +77,36 @@ class VariableReplacer:
80
77
  match = item
81
78
  else:
82
79
  match = search_variable(item, ignore_errors=ignore_errors)
83
- if not match:
84
- return unescape(match.string)
85
- return self._replace_scalar(match, ignore_errors)
86
-
87
- def _replace_scalar(self, match, ignore_errors=False):
88
- if match.is_variable():
89
- return self._get_variable_value(match, ignore_errors)
90
- return self._replace_string(match, unescape, ignore_errors)
80
+ return self._replace(match, ignore_errors)
91
81
 
92
82
  def replace_string(self, item, custom_unescaper=None, ignore_errors=False):
93
83
  """Replaces variables from a string. Result is always a string.
94
84
 
95
85
  Input can also be an already found VariableMatch.
96
86
  """
97
- unescaper = custom_unescaper or unescape
98
87
  if isinstance(item, VariableMatch):
99
88
  match = item
100
89
  else:
101
90
  match = search_variable(item, ignore_errors=ignore_errors)
102
- if not match:
103
- return safe_str(unescaper(match.string))
104
- return self._replace_string(match, unescaper, ignore_errors)
91
+ result = self._replace(match, ignore_errors, custom_unescaper or unescape)
92
+ return safe_str(result)
105
93
 
106
- def _replace_string(self, match, unescaper, ignore_errors):
94
+ def _replace(self, match, ignore_errors, unescaper=unescape):
95
+ if not match:
96
+ return unescaper(match.string)
97
+ if match.is_variable():
98
+ return self._get_variable_value(match, ignore_errors)
107
99
  parts = []
108
100
  while match:
109
- parts.append(unescaper(match.before))
110
- parts.append(safe_str(self._get_variable_value(match, ignore_errors)))
101
+ if match.before:
102
+ parts.append(unescaper(match.before))
103
+ parts.append(self._get_variable_value(match, ignore_errors))
111
104
  match = search_variable(match.after, ignore_errors=ignore_errors)
112
- parts.append(unescaper(match.string))
113
- return ''.join(parts)
105
+ if match.string:
106
+ parts.append(unescaper(match.string))
107
+ if all(isinstance(p, (bytes, bytearray)) for p in parts):
108
+ return b''.join(parts)
109
+ return ''.join(safe_str(p) for p in parts)
114
110
 
115
111
  def _get_variable_value(self, match, ignore_errors):
116
112
  match.resolve_base(self, ignore_errors)
@@ -16,7 +16,6 @@
16
16
  import os
17
17
  import tempfile
18
18
 
19
- from robot.errors import VariableError
20
19
  from robot.model import Tags
21
20
  from robot.output import LOGGER
22
21
  from robot.utils import abspath, find_file, get_error_details, DotDict, NormalizedDict
@@ -31,6 +30,7 @@ class VariableScopes:
31
30
  self._global = GlobalVariables(settings)
32
31
  self._suite = None
33
32
  self._test = None
33
+ self._suite_locals = []
34
34
  self._scopes = [self._global]
35
35
  self._variables_set = SetVariables()
36
36
 
@@ -59,16 +59,18 @@ class VariableScopes:
59
59
  def start_suite(self):
60
60
  self._suite = self._global.copy()
61
61
  self._scopes.append(self._suite)
62
+ self._suite_locals.append(NormalizedDict(ignore='_'))
62
63
  self._variables_set.start_suite()
63
64
  self._variables_set.update(self._suite)
64
65
 
65
66
  def end_suite(self):
66
67
  self._scopes.pop()
68
+ self._suite_locals.pop()
67
69
  self._suite = self._scopes[-1] if len(self._scopes) > 1 else None
68
70
  self._variables_set.end_suite()
69
71
 
70
72
  def start_test(self):
71
- self._test = self._suite.copy()
73
+ self._test = self._suite.copy(exclude=self._suite_locals[-1])
72
74
  self._scopes.append(self._test)
73
75
  self._variables_set.start_test()
74
76
 
@@ -78,7 +80,8 @@ class VariableScopes:
78
80
  self._variables_set.end_test()
79
81
 
80
82
  def start_keyword(self):
81
- kw = self._suite.copy()
83
+ exclude = self._suite_locals[-1] if self._test else ()
84
+ kw = self._suite.copy(exclude)
82
85
  self._variables_set.start_keyword()
83
86
  self._variables_set.update(kw)
84
87
  self._scopes.append(kw)
@@ -141,13 +144,19 @@ class VariableScopes:
141
144
  for scope in self._scopes_until_suite:
142
145
  name, value = self._set_global_suite_or_test(scope, name, value)
143
146
  self._variables_set.set_suite(name, value, children)
147
+ # Override possible "suite local variables" (i.e. test variables set on
148
+ # suite level) if real suite level variable is set.
149
+ if name in self._suite_locals[-1]:
150
+ self._suite_locals[-1].pop(name)
144
151
 
145
152
  def set_test(self, name, value):
146
- if self._test is None:
147
- raise VariableError('Cannot set test variable when no test is started.')
148
- for scope in self._scopes_until_test:
149
- name, value = self._set_global_suite_or_test(scope, name, value)
150
- self._variables_set.set_test(name, value)
153
+ if self._test:
154
+ for scope in self._scopes_until_test:
155
+ name, value = self._set_global_suite_or_test(scope, name, value)
156
+ self._variables_set.set_test(name, value)
157
+ else:
158
+ self.set_suite(name, value)
159
+ self._suite_locals[-1][name] = None
151
160
 
152
161
  def set_keyword(self, name, value):
153
162
  self.current[name] = value
@@ -192,7 +201,8 @@ class GlobalVariables(Variables):
192
201
  'include': Tags(settings.include),
193
202
  'exclude': Tags(settings.exclude),
194
203
  'skip': Tags(settings.skip),
195
- 'skip_on_failure': Tags(settings.skip_on_failure)
204
+ 'skip_on_failure': Tags(settings.skip_on_failure),
205
+ 'console_width': settings.console_width
196
206
  })),
197
207
  ('${/}', os.sep),
198
208
  ('${:}', os.pathsep),
@@ -68,9 +68,12 @@ class Variables:
68
68
  def clear(self):
69
69
  self.store.clear()
70
70
 
71
- def copy(self):
71
+ def copy(self, exclude=None):
72
72
  variables = Variables()
73
73
  variables.store.data = self.store.data.copy()
74
+ if exclude:
75
+ for name in exclude:
76
+ variables.store.data.pop(name[2:-1])
74
77
  return variables
75
78
 
76
79
  def update(self, variables):
@@ -18,7 +18,7 @@ import sys
18
18
 
19
19
  # Version number typically updated by running `invoke set-version <version>`.
20
20
  # Run `invoke --help set-version` or see tasks.py for details.
21
- VERSION = '7.1rc2'
21
+ VERSION = '7.2b1'
22
22
 
23
23
 
24
24
  def get_version(naked=False):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: robotframework
3
- Version: 7.1rc2
3
+ Version: 7.2b1
4
4
  Summary: Generic automation framework for acceptance testing and robotic process automation (RPA)
5
5
  Home-page: https://robotframework.org
6
6
  Author: Pekka Klärck
@@ -10,7 +10,7 @@ Download-URL: https://pypi.org/project/robotframework
10
10
  Project-URL: Source, https://github.com/robotframework/robotframework
11
11
  Project-URL: Issue Tracker, https://github.com/robotframework/robotframework/issues
12
12
  Project-URL: Documentation, https://robotframework.org/robotframework
13
- Project-URL: Release Notes, https://github.com/robotframework/robotframework/blob/master/doc/releasenotes/rf-7.1rc2.rst
13
+ Project-URL: Release Notes, https://github.com/robotframework/robotframework/blob/master/doc/releasenotes/rf-7.2b1.rst
14
14
  Project-URL: Slack, http://slack.robotframework.org
15
15
  Description: Robot Framework
16
16
  ===============
@@ -42,11 +42,7 @@ src/robot/htmldata/lib/jquery.tablesorter.min.js
42
42
  src/robot/htmldata/lib/jquery.tmpl.min.js
43
43
  src/robot/htmldata/lib/jsxcompressor.min.js
44
44
  src/robot/htmldata/libdoc/__init__.py
45
- src/robot/htmldata/libdoc/doc_formatting.css
46
- src/robot/htmldata/libdoc/libdoc.css
47
45
  src/robot/htmldata/libdoc/libdoc.html
48
- src/robot/htmldata/libdoc/print.css
49
- src/robot/htmldata/libdoc/pygments.css
50
46
  src/robot/htmldata/rebot/__init__.py
51
47
  src/robot/htmldata/rebot/common.css
52
48
  src/robot/htmldata/rebot/doc_formatting.css
@@ -119,12 +115,15 @@ src/robot/model/visitor.py
119
115
  src/robot/output/__init__.py
120
116
  src/robot/output/debugfile.py
121
117
  src/robot/output/filelogger.py
118
+ src/robot/output/jsonlogger.py
122
119
  src/robot/output/librarylogger.py
123
120
  src/robot/output/listeners.py
124
121
  src/robot/output/logger.py
125
122
  src/robot/output/loggerapi.py
126
123
  src/robot/output/loggerhelper.py
124
+ src/robot/output/loglevel.py
127
125
  src/robot/output/output.py
126
+ src/robot/output/outputfile.py
128
127
  src/robot/output/pyloggingconf.py
129
128
  src/robot/output/stdoutlogsplitter.py
130
129
  src/robot/output/xmllogger.py
@@ -1,74 +0,0 @@
1
- #introduction-container > h2,
2
- .doc > h1,
3
- .doc > h2,
4
- .section > h1,
5
- .section > h2 {
6
- margin-top: 4rem;
7
- margin-bottom: 1rem;
8
- }
9
-
10
- .doc > h3, .section > h3 {
11
- margin-top: 3rem;
12
- margin-bottom: 1rem;
13
- }
14
-
15
- .doc > h4, .section > h4 {
16
- margin-top: 2rem;
17
- margin-bottom: 1rem;
18
- }
19
-
20
- .doc > p, .section > p {
21
- margin-top: 1rem;
22
- margin-bottom: 0.5rem;
23
- }
24
- .doc > *:first-child {
25
- margin-top: 0.1em;
26
- }
27
- .doc table {
28
- border: none;
29
- background: transparent;
30
- border-collapse: collapse;
31
- empty-cells: show;
32
- font-size: 0.9em;
33
- overflow-y: auto;
34
- display: block;
35
- }
36
- .doc table th, .doc table td {
37
- border: 1px solid var(--border-color);
38
- background: transparent;
39
- padding: 0.1em 0.3em;
40
- height: 1.2em;
41
- }
42
- .doc table th {
43
- text-align: center;
44
- letter-spacing: 0.1em;
45
- }
46
- .doc pre {
47
- font-size: 1.1em;
48
- letter-spacing: 0.05em;
49
- background: var(--light-background-color);
50
- overflow-y: auto;
51
- padding: 0.3rem;
52
- border-radius: 3px;
53
- }
54
-
55
- .doc code,
56
- .docutils.literal {
57
- font-size: 1.1em;
58
- letter-spacing: 0.05em;
59
- background: var(--light-background-color);
60
- padding: 1px;
61
- border-radius: 3px;
62
- }
63
- .doc li {
64
- list-style-position: inside;
65
- list-style-type: square;
66
- }
67
- .doc img {
68
- border: 1px solid #ccc;
69
- }
70
- .doc hr {
71
- background: #ccc;
72
- height: 1px;
73
- border: 0;
74
- }