robotframework 7.0.1rc2__zip → 7.1rc1__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 (280) hide show
  1. {robotframework-7.0.1rc2/src/robotframework.egg-info → robotframework-7.1rc1}/PKG-INFO +3 -2
  2. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/setup.py +2 -1
  3. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/api/interfaces.py +32 -0
  4. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/conf/languages.py +73 -18
  5. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/conf/settings.py +1 -1
  6. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/model.js +22 -33
  7. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/jsonbuilder.py +1 -1
  8. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/BuiltIn.py +16 -3
  9. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/DateTime.py +3 -2
  10. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/Dialogs.py +12 -4
  11. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/OperatingSystem.py +4 -4
  12. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/Process.py +7 -3
  13. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/String.py +4 -1
  14. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/dialogs_py.py +17 -1
  15. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/modelobject.py +1 -6
  16. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/console/dotted.py +1 -1
  17. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/console/highlighting.py +69 -56
  18. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/console/verbose.py +3 -3
  19. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/listeners.py +61 -217
  20. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/logger.py +30 -14
  21. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/loggerapi.py +11 -0
  22. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/loggerhelper.py +6 -1
  23. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/output.py +2 -1
  24. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/model/statements.py +1 -1
  25. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/executionresult.py +1 -0
  26. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/model.py +1 -1
  27. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/resultbuilder.py +12 -11
  28. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/xmlelementhandlers.py +12 -0
  29. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/__init__.py +1 -1
  30. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/argumentresolver.py +15 -11
  31. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/argumentspec.py +2 -2
  32. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/argumentvalidator.py +0 -8
  33. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/embedded.py +2 -2
  34. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/invalidkeyword.py +4 -1
  35. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/keywordimplementation.py +9 -5
  36. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/librarykeyword.py +19 -9
  37. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/librarykeywordrunner.py +25 -19
  38. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/model.py +45 -26
  39. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/namespace.py +20 -26
  40. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/resourcemodel.py +9 -1
  41. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/statusreporter.py +9 -4
  42. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/testlibraries.py +2 -2
  43. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/userkeywordrunner.py +10 -7
  44. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/encodingsniffer.py +3 -1
  45. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/robottime.py +5 -3
  46. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/evaluation.py +1 -4
  47. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/tablesetter.py +17 -20
  48. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/version.py +1 -1
  49. {robotframework-7.0.1rc2 → robotframework-7.1rc1/src/robotframework.egg-info}/PKG-INFO +3 -2
  50. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/AUTHORS.rst +0 -0
  51. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/BUILD.rst +0 -0
  52. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/CONTRIBUTING.rst +0 -0
  53. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/COPYRIGHT.txt +0 -0
  54. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/INSTALL.rst +0 -0
  55. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/LICENSE.txt +0 -0
  56. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/MANIFEST.in +0 -0
  57. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/README.rst +0 -0
  58. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/setup.cfg +0 -0
  59. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/__init__.py +0 -0
  60. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/__main__.py +0 -0
  61. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/api/__init__.py +0 -0
  62. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/api/deco.py +0 -0
  63. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/api/exceptions.py +0 -0
  64. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/api/logger.py +0 -0
  65. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/api/parsing.py +0 -0
  66. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/api/py.typed +0 -0
  67. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/conf/__init__.py +0 -0
  68. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/conf/gatherfailed.py +0 -0
  69. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/errors.py +0 -0
  70. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/__init__.py +0 -0
  71. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/common/__init__.py +0 -0
  72. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/common/js_disabled.css +0 -0
  73. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/common/storage.js +0 -0
  74. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/htmlfilewriter.py +0 -0
  75. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/jsonwriter.py +0 -0
  76. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/lib/__init__.py +0 -0
  77. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
  78. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/lib/jquery.min.js +0 -0
  79. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
  80. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
  81. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
  82. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/libdoc/__init__.py +0 -0
  83. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/libdoc/doc_formatting.css +0 -0
  84. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/libdoc/libdoc.css +0 -0
  85. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/libdoc/libdoc.html +0 -0
  86. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/libdoc/print.css +0 -0
  87. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/libdoc/pygments.css +0 -0
  88. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/__init__.py +0 -0
  89. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/common.css +0 -0
  90. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/doc_formatting.css +0 -0
  91. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/fileloading.js +0 -0
  92. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/log.css +0 -0
  93. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/log.html +0 -0
  94. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/log.js +0 -0
  95. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/print.css +0 -0
  96. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/report.css +0 -0
  97. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/report.html +0 -0
  98. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/testdata.js +0 -0
  99. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/util.js +0 -0
  100. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/rebot/view.js +0 -0
  101. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/template.py +0 -0
  102. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/testdoc/__init__.py +0 -0
  103. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/testdoc/testdoc.css +0 -0
  104. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/htmldata/testdoc/testdoc.html +0 -0
  105. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdoc.py +0 -0
  106. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/__init__.py +0 -0
  107. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/builder.py +0 -0
  108. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/consoleviewer.py +0 -0
  109. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/datatypes.py +0 -0
  110. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/htmlutils.py +0 -0
  111. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/htmlwriter.py +0 -0
  112. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/jsonwriter.py +0 -0
  113. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/model.py +0 -0
  114. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/output.py +0 -0
  115. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/robotbuilder.py +0 -0
  116. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/standardtypes.py +0 -0
  117. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/writer.py +0 -0
  118. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/xmlbuilder.py +0 -0
  119. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libdocpkg/xmlwriter.py +0 -0
  120. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/Collections.py +0 -0
  121. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/Easter.py +0 -0
  122. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/Remote.py +0 -0
  123. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/Screenshot.py +0 -0
  124. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/Telnet.py +0 -0
  125. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/XML.py +0 -0
  126. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/libraries/__init__.py +0 -0
  127. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/__init__.py +0 -0
  128. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/body.py +0 -0
  129. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/configurer.py +0 -0
  130. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/control.py +0 -0
  131. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/filter.py +0 -0
  132. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/fixture.py +0 -0
  133. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/itemlist.py +0 -0
  134. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/keyword.py +0 -0
  135. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/message.py +0 -0
  136. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/metadata.py +0 -0
  137. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/modifier.py +0 -0
  138. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/namepatterns.py +0 -0
  139. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/statistics.py +0 -0
  140. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/stats.py +0 -0
  141. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/suitestatistics.py +0 -0
  142. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/tags.py +0 -0
  143. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/tagsetter.py +0 -0
  144. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/tagstatistics.py +0 -0
  145. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/testcase.py +0 -0
  146. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/testsuite.py +0 -0
  147. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/totalstatistics.py +0 -0
  148. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/model/visitor.py +0 -0
  149. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/__init__.py +0 -0
  150. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/console/__init__.py +0 -0
  151. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/console/quiet.py +0 -0
  152. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/debugfile.py +0 -0
  153. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/filelogger.py +0 -0
  154. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/librarylogger.py +0 -0
  155. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/pyloggingconf.py +0 -0
  156. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/stdoutlogsplitter.py +0 -0
  157. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/output/xmllogger.py +0 -0
  158. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/__init__.py +0 -0
  159. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/lexer/__init__.py +0 -0
  160. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/lexer/blocklexers.py +0 -0
  161. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/lexer/context.py +0 -0
  162. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/lexer/lexer.py +0 -0
  163. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/lexer/settings.py +0 -0
  164. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/lexer/statementlexers.py +0 -0
  165. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/lexer/tokenizer.py +0 -0
  166. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/lexer/tokens.py +0 -0
  167. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/model/__init__.py +0 -0
  168. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/model/blocks.py +0 -0
  169. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/model/visitor.py +0 -0
  170. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/parser/__init__.py +0 -0
  171. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/parser/blockparsers.py +0 -0
  172. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/parser/fileparser.py +0 -0
  173. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/parser/parser.py +0 -0
  174. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/parsing/suitestructure.py +0 -0
  175. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/pythonpathsetter.py +0 -0
  176. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/rebot.py +0 -0
  177. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/reporting/__init__.py +0 -0
  178. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/reporting/expandkeywordmatcher.py +0 -0
  179. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/reporting/jsbuildingcontext.py +0 -0
  180. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/reporting/jsexecutionresult.py +0 -0
  181. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/reporting/jsmodelbuilders.py +0 -0
  182. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/reporting/jswriter.py +0 -0
  183. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/reporting/logreportwriters.py +0 -0
  184. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/reporting/outputwriter.py +0 -0
  185. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/reporting/resultwriter.py +0 -0
  186. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/reporting/stringcache.py +0 -0
  187. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/reporting/xunitwriter.py +0 -0
  188. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/__init__.py +0 -0
  189. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/configurer.py +0 -0
  190. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/executionerrors.py +0 -0
  191. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/flattenkeywordmatcher.py +0 -0
  192. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/keywordremover.py +0 -0
  193. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/merger.py +0 -0
  194. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/messagefilter.py +0 -0
  195. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/modeldeprecation.py +0 -0
  196. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/suiteteardownfailed.py +0 -0
  197. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/result/visitor.py +0 -0
  198. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/run.py +0 -0
  199. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/__init__.py +0 -0
  200. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/argumentconverter.py +0 -0
  201. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/argumentmapper.py +0 -0
  202. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/argumentparser.py +0 -0
  203. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/customconverters.py +0 -0
  204. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/typeconverters.py +0 -0
  205. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/typeinfo.py +0 -0
  206. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/typeinfoparser.py +0 -0
  207. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/arguments/typevalidator.py +0 -0
  208. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/bodyrunner.py +0 -0
  209. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/builder/__init__.py +0 -0
  210. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/builder/builders.py +0 -0
  211. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/builder/parsers.py +0 -0
  212. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/builder/settings.py +0 -0
  213. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/builder/transformers.py +0 -0
  214. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/context.py +0 -0
  215. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/dynamicmethods.py +0 -0
  216. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/importer.py +0 -0
  217. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/keywordfinder.py +0 -0
  218. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/libraryscopes.py +0 -0
  219. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/outputcapture.py +0 -0
  220. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/randomizer.py +0 -0
  221. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/runkwregister.py +0 -0
  222. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/signalhandler.py +0 -0
  223. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/status.py +0 -0
  224. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/suiterunner.py +0 -0
  225. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/timeouts/__init__.py +0 -0
  226. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/timeouts/nosupport.py +0 -0
  227. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/timeouts/posix.py +0 -0
  228. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/running/timeouts/windows.py +0 -0
  229. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/testdoc.py +0 -0
  230. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/__init__.py +0 -0
  231. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/application.py +0 -0
  232. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/argumentparser.py +0 -0
  233. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/asserts.py +0 -0
  234. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/charwidth.py +0 -0
  235. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/compress.py +0 -0
  236. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/connectioncache.py +0 -0
  237. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/dotdict.py +0 -0
  238. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/encoding.py +0 -0
  239. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/error.py +0 -0
  240. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/escaping.py +0 -0
  241. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/etreewrapper.py +0 -0
  242. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/filereader.py +0 -0
  243. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/frange.py +0 -0
  244. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/htmlformatters.py +0 -0
  245. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/importer.py +0 -0
  246. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/markuputils.py +0 -0
  247. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/markupwriters.py +0 -0
  248. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/match.py +0 -0
  249. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/misc.py +0 -0
  250. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/normalizing.py +0 -0
  251. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/notset.py +0 -0
  252. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/platform.py +0 -0
  253. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/recommendations.py +0 -0
  254. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/restreader.py +0 -0
  255. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/robotenv.py +0 -0
  256. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/robotinspect.py +0 -0
  257. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/robotio.py +0 -0
  258. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/robotpath.py +0 -0
  259. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/robottypes.py +0 -0
  260. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/setter.py +0 -0
  261. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/sortable.py +0 -0
  262. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/text.py +0 -0
  263. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/typehints.py +0 -0
  264. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/utils/unic.py +0 -0
  265. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/__init__.py +0 -0
  266. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/assigner.py +0 -0
  267. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/filesetter.py +0 -0
  268. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/finders.py +0 -0
  269. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/notfound.py +0 -0
  270. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/replacer.py +0 -0
  271. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/resolvable.py +0 -0
  272. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/scopes.py +0 -0
  273. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/search.py +0 -0
  274. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/store.py +0 -0
  275. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robot/variables/variables.py +0 -0
  276. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robotframework.egg-info/SOURCES.txt +0 -0
  277. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robotframework.egg-info/dependency_links.txt +0 -0
  278. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robotframework.egg-info/entry_points.txt +0 -0
  279. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/src/robotframework.egg-info/top_level.txt +0 -0
  280. {robotframework-7.0.1rc2 → robotframework-7.1rc1}/tasks.py +0 -0
@@ -211,5 +211,16 @@ class LoggerApi:
211
211
  def imported(self, import_type: str, name: str, attrs):
212
212
  pass
213
213
 
214
+ def library_import(self, library: 'running.TestLibrary',
215
+ importer: 'running.Import'):
216
+ pass
217
+
218
+ def resource_import(self, resource: 'running.ResourceFile',
219
+ importer: 'running.Import'):
220
+ pass
221
+
222
+ def variables_import(self, attrs: dict, importer: 'running.Import'):
223
+ pass
224
+
214
225
  def close(self):
215
226
  pass
@@ -141,7 +141,12 @@ class IsLogged:
141
141
  self.__init__(level)
142
142
  return old
143
143
 
144
- def _level_to_int(self, level):
144
+ @classmethod
145
+ def validate_level(cls, level):
146
+ cls._level_to_int(level)
147
+
148
+ @classmethod
149
+ def _level_to_int(cls, level):
145
150
  try:
146
151
  return LEVELS[level.upper()]
147
152
  except KeyError:
@@ -18,7 +18,7 @@ from .debugfile import DebugFile
18
18
  from .listeners import Listeners, LibraryListeners
19
19
  from .logger import LOGGER
20
20
  from .loggerapi import LoggerApi
21
- from .loggerhelper import AbstractLogger
21
+ from .loggerhelper import AbstractLogger, IsLogged
22
22
  from .xmllogger import XmlLoggerAdapter
23
23
 
24
24
 
@@ -179,6 +179,7 @@ class Output(AbstractLogger, LoggerApi):
179
179
  self.write(msg, 'TRACE')
180
180
 
181
181
  def set_log_level(self, level):
182
+ IsLogged.validate_level(level)
182
183
  pyloggingconf.set_level(level)
183
184
  self.listeners.set_log_level(level)
184
185
  self.library_listeners.set_log_level(level)
@@ -1208,7 +1208,7 @@ class WhileHeader(Statement):
1208
1208
  class Var(Statement):
1209
1209
  type = Token.VAR
1210
1210
  options = {
1211
- 'scope': ('GLOBAL', 'SUITE', 'TEST', 'TASK', 'LOCAL'),
1211
+ 'scope': ('LOCAL', 'TEST', 'TASK', 'SUITE', 'SUITES', 'GLOBAL'),
1212
1212
  'separator': None
1213
1213
  }
1214
1214
 
@@ -64,6 +64,7 @@ class Result:
64
64
  #: :class:`~.executionerrors.ExecutionErrors` object.
65
65
  self.errors = errors or ExecutionErrors()
66
66
  self.generated_by_robot = True
67
+ self.generation_time = None
67
68
  self._status_rc = True
68
69
  self._stat_config = {}
69
70
  self.rpa = rpa
@@ -1133,7 +1133,7 @@ class TestSuite(model.TestSuite[Keyword, TestCase], StatusMixin):
1133
1133
  if output is None:
1134
1134
  output = StringIO()
1135
1135
  elif isinstance(output, (Path, str)):
1136
- output = open(output, 'w')
1136
+ output = open(output, 'w', encoding='UTF-8')
1137
1137
  close = True
1138
1138
  return output, close
1139
1139
 
@@ -13,8 +13,6 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- from pathlib import Path
17
-
18
16
  from robot.errors import DataError
19
17
  from robot.model import SuiteVisitor
20
18
  from robot.utils import ET, ETSource, get_error_message
@@ -82,9 +80,13 @@ def _single_result(source, options):
82
80
  def _json_result(source, options):
83
81
  try:
84
82
  suite = TestSuite.from_json(source)
83
+ except IOError as err:
84
+ error = err.strerror
85
85
  except Exception:
86
- raise DataError(f"Reading JSON source '{source}' failed: {get_error_message()}")
87
- return Result(source, suite, rpa=options.pop('rpa', None))
86
+ error = get_error_message()
87
+ else:
88
+ return Result(source, suite, rpa=options.pop('rpa', None))
89
+ raise DataError(f"Reading JSON source '{source}' failed: {error}")
88
90
 
89
91
 
90
92
  def _xml_result(source, options):
@@ -150,27 +152,27 @@ class ExecutionResultBuilder:
150
152
  elem.clear()
151
153
 
152
154
  def _omit_keywords(self, context):
153
- omitted_kws = 0
155
+ omitted_elements = {'kw', 'for', 'while', 'if', 'try'}
156
+ omitted = 0
154
157
  for event, elem in context:
155
158
  # Teardowns aren't omitted yet to allow checking suite teardown status.
156
159
  # They'll be removed later when not needed in `build()`.
157
- omit = elem.tag in ('kw', 'for', 'if') and elem.get('type') != 'TEARDOWN'
160
+ omit = elem.tag in omitted_elements and elem.get('type') != 'TEARDOWN'
158
161
  start = event == 'start'
159
162
  if omit and start:
160
- omitted_kws += 1
161
- if not omitted_kws:
163
+ omitted += 1
164
+ if not omitted:
162
165
  yield event, elem
163
166
  elif not start:
164
167
  elem.clear()
165
168
  if omit and not start:
166
- omitted_kws -= 1
169
+ omitted -= 1
167
170
 
168
171
  def _flatten_keywords(self, context, flattened):
169
172
  # Performance optimized. Do not change without profiling!
170
173
  name_match, by_name = self._get_matcher(FlattenByNameMatcher, flattened)
171
174
  type_match, by_type = self._get_matcher(FlattenByTypeMatcher, flattened)
172
175
  started = -1 # if 0 or more, we are flattening
173
- tags = []
174
176
  containers = {'kw', 'for', 'while', 'iter', 'if', 'try'}
175
177
  inside = 0 # to make sure we don't read tags from a test
176
178
  for event, elem in context:
@@ -185,7 +187,6 @@ class ExecutionResultBuilder:
185
187
  started = 0
186
188
  elif by_type and type_match(tag):
187
189
  started = 0
188
- tags = []
189
190
  else:
190
191
  if tag in containers:
191
192
  inside -= 1
@@ -60,6 +60,9 @@ class ElementHandler:
60
60
 
61
61
  def _legacy_timestamp(self, elem, attr_name):
62
62
  ts = elem.get(attr_name)
63
+ return self._parse_legacy_timestamp(ts)
64
+
65
+ def _parse_legacy_timestamp(self, ts):
63
66
  if ts == 'N/A' or not ts:
64
67
  return None
65
68
  ts = ts.ljust(24, '0')
@@ -85,10 +88,19 @@ class RobotHandler(ElementHandler):
85
88
  def start(self, elem, result):
86
89
  generator = elem.get('generator', 'unknown').split()[0].upper()
87
90
  result.generated_by_robot = generator == 'ROBOT'
91
+ result.generation_time = self._parse_generation_time(elem.get('generated'))
88
92
  if result.rpa is None:
89
93
  result.rpa = elem.get('rpa', 'false') == 'true'
90
94
  return result
91
95
 
96
+ def _parse_generation_time(self, generated):
97
+ if not generated:
98
+ return None
99
+ try:
100
+ return datetime.fromisoformat(generated)
101
+ except ValueError:
102
+ return self._parse_legacy_timestamp(generated)
103
+
92
104
 
93
105
  @ElementHandler.register
94
106
  class SuiteHandler(ElementHandler):
@@ -123,6 +123,6 @@ from .librarykeyword import LibraryKeyword
123
123
  from .model import (Break, Continue, Error, For, ForIteration, If, IfBranch, Keyword,
124
124
  Return, TestCase, TestSuite, Try, TryBranch, Var, While,
125
125
  WhileIteration)
126
- from .resourcemodel import ResourceFile, UserKeyword
126
+ from .resourcemodel import Import, ResourceFile, UserKeyword, Variable
127
127
  from .runkwregister import RUN_KW_REGISTER
128
128
  from .testlibraries import TestLibrary
@@ -38,8 +38,11 @@ class ArgumentResolver:
38
38
  self.dict_to_kwargs = DictToKwargs(spec, dict_to_kwargs)
39
39
  self.argument_validator = ArgumentValidator(spec)
40
40
 
41
- def resolve(self, arguments, variables=None):
42
- positional, named = self.named_resolver.resolve(arguments, variables)
41
+ def resolve(self, args, named_args=None, variables=None):
42
+ if named_args is None:
43
+ positional, named = self.named_resolver.resolve(args, variables)
44
+ else:
45
+ positional, named = args, list(named_args.items())
43
46
  positional, named = self.variable_replacer.replace(positional, named, variables)
44
47
  positional, named = self.dict_to_kwargs.handle(positional, named)
45
48
  self.argument_validator.validate(positional, named, dryrun=variables is None)
@@ -52,14 +55,15 @@ class NamedArgumentResolver:
52
55
  self.spec = spec
53
56
 
54
57
  def resolve(self, arguments, variables=None):
55
- spec = self.spec
56
- positional = list(arguments[:len(spec.embedded)])
58
+ known_positional_count = max(len(self.spec.positional_only),
59
+ len(self.spec.embedded))
60
+ positional = list(arguments[:known_positional_count])
57
61
  named = []
58
- for arg in arguments[len(spec.embedded):]:
62
+ for arg in arguments[known_positional_count:]:
59
63
  if is_dict_variable(arg):
60
64
  named.append(arg)
61
65
  else:
62
- name, value = self._split_named(arg, named, variables, spec)
66
+ name, value = self._split_named(arg, named, variables)
63
67
  if name is not None:
64
68
  named.append((name, value))
65
69
  elif named:
@@ -68,23 +72,23 @@ class NamedArgumentResolver:
68
72
  positional.append(value)
69
73
  return positional, named
70
74
 
71
- def _split_named(self, arg, previous_named, variables, spec):
75
+ def _split_named(self, arg, previous_named, variables):
72
76
  if isinstance(arg, Argument):
73
77
  return arg.name, arg.value
74
78
  name, value = split_from_equals(arg)
75
- if value is None or not self._is_named(name, previous_named, variables, spec):
79
+ if value is None or not self._is_named(name, previous_named, variables):
76
80
  return None, arg
77
81
  return name, value
78
82
 
79
- def _is_named(self, name, previous_named, variables, spec):
80
- if previous_named or spec.var_named:
83
+ def _is_named(self, name, previous_named, variables):
84
+ if previous_named or self.spec.var_named:
81
85
  return True
82
86
  if variables:
83
87
  try:
84
88
  name = variables.replace_scalar(name)
85
89
  except DataError:
86
90
  return False
87
- return name in spec.named
91
+ return name in self.spec.named
88
92
 
89
93
  def _raise_positional_after_named(self):
90
94
  raise DataError(f"{self.spec.type.capitalize()} '{self.spec.name}' "
@@ -96,12 +96,12 @@ class ArgumentSpec(metaclass=SetterAwareType):
96
96
  return (self.positional_only + self.positional_or_named + var_positional +
97
97
  self.named_only + var_named)
98
98
 
99
- def resolve(self, arguments, variables=None, converters=None,
99
+ def resolve(self, args, named_args=None, variables=None, converters=None,
100
100
  resolve_named=True, resolve_args_until=None,
101
101
  dict_to_kwargs=False, languages=None) -> 'tuple[list, list]':
102
102
  resolver = ArgumentResolver(self, resolve_named, resolve_args_until,
103
103
  dict_to_kwargs)
104
- positional, named = resolver.resolve(arguments, variables)
104
+ positional, named = resolver.resolve(args, named_args, variables)
105
105
  return self.convert(positional, named, converters, dry_run=not variables,
106
106
  languages=languages)
107
107
 
@@ -34,7 +34,6 @@ class ArgumentValidator:
34
34
  any(is_dict_variable(arg) for arg in named)):
35
35
  return
36
36
  self._validate_no_multiple_values(positional, named, self.spec)
37
- self._validate_no_positional_only_as_named(named, self.spec)
38
37
  self._validate_positional_limits(positional, named, self.spec)
39
38
  self._validate_no_mandatory_missing(positional, named, self.spec)
40
39
  self._validate_no_named_only_missing(named, self.spec)
@@ -49,13 +48,6 @@ class ArgumentValidator:
49
48
  name = f"'{self.spec.name}' " if self.spec.name else ''
50
49
  raise DataError(f"{self.spec.type.capitalize()} {name}{message}.")
51
50
 
52
- def _validate_no_positional_only_as_named(self, named, spec):
53
- if not spec.var_named:
54
- for name in named:
55
- if name in spec.positional_only:
56
- self._raise_error(f"does not accept argument '{name}' as named "
57
- f"argument")
58
-
59
51
  def _validate_positional_limits(self, positional, named, spec):
60
52
  count = len(positional) + self._named_positionals(named, spec)
61
53
  if not spec.minargs <= count <= spec.maxargs:
@@ -80,7 +80,7 @@ class EmbeddedArgumentParser:
80
80
  args = []
81
81
  custom_patterns = {}
82
82
  after = string
83
- for match in VariableMatches(string, identifiers='$'):
83
+ for match in VariableMatches(' '.join(string.split()), identifiers='$'):
84
84
  arg, pattern, is_custom = self._get_name_and_pattern(match.base)
85
85
  args.append(arg)
86
86
  if is_custom:
@@ -139,7 +139,7 @@ class EmbeddedArgumentParser:
139
139
 
140
140
  def _compile_regexp(self, pattern: str) -> re.Pattern:
141
141
  try:
142
- return re.compile(''.join(pattern), re.IGNORECASE)
142
+ return re.compile(pattern.replace(r'\ ', r'\s'), re.IGNORECASE)
143
143
  except Exception:
144
144
  raise DataError(f"Compiling embedded arguments regexp failed: "
145
145
  f"{get_error_message()}")
@@ -54,9 +54,12 @@ class InvalidKeywordRunner:
54
54
 
55
55
  def run(self, data: KeywordData, result: KeywordResult, context, run=True):
56
56
  kw = self.keyword.bind(data)
57
+ args = tuple(data.args)
58
+ if data.named_args:
59
+ args += tuple(f'{n}={v}' for n, v in data.named_args.items())
57
60
  result.config(name=self.name,
58
61
  owner=kw.owner.name if kw.owner else None,
59
- args=data.args,
62
+ args=args,
60
63
  assign=tuple(VariableAssignment(data.assign)),
61
64
  type=data.type)
62
65
  with StatusReporter(data, result, context, run, implementation=kw):
@@ -14,7 +14,7 @@
14
14
  # limitations under the License.
15
15
 
16
16
  from pathlib import Path
17
- from typing import Any, Literal, Sequence, TYPE_CHECKING
17
+ from typing import Any, Literal, Mapping, Sequence, TYPE_CHECKING
18
18
 
19
19
  from robot.model import ModelObject, Tags
20
20
  from robot.utils import eq, getshortdoc, setter
@@ -23,6 +23,8 @@ from .arguments import ArgInfo, ArgumentSpec, EmbeddedArguments
23
23
  from .model import BodyItemParent, Keyword
24
24
 
25
25
  if TYPE_CHECKING:
26
+ from robot.conf import LanguagesLike
27
+
26
28
  from .librarykeywordrunner import LibraryKeywordRunner
27
29
  from .resourcemodel import ResourceFile
28
30
  from .testlibraries import TestLibrary
@@ -141,11 +143,13 @@ class KeywordImplementation(ModelObject):
141
143
  return self.embedded.match(name) is not None
142
144
  return eq(self.name, name, ignore='_')
143
145
 
144
- def resolve_arguments(self, args: Sequence[str], variables=None,
145
- languages=None) -> 'tuple[list, list]':
146
- return self.args.resolve(args, variables, languages=languages)
146
+ def resolve_arguments(self, args: 'Sequence[str|Any]',
147
+ named_args: 'Mapping[str, Any]|None' = None,
148
+ variables=None,
149
+ languages: 'LanguagesLike' = None) -> 'tuple[list, list]':
150
+ return self.args.resolve(args, named_args, variables, languages=languages)
147
151
 
148
- def create_runner(self, name: 'str|None', languages=None) \
152
+ def create_runner(self, name: 'str|None', languages: 'LanguagesLike' = None) \
149
153
  -> 'LibraryKeywordRunner|UserKeywordRunner':
150
154
  raise NotImplementedError
151
155
 
@@ -16,7 +16,7 @@
16
16
  import inspect
17
17
  from os.path import normpath
18
18
  from pathlib import Path
19
- from typing import Any, Callable, Generic, Sequence, TypeVar, TYPE_CHECKING
19
+ from typing import Any, Callable, Generic, Mapping, Sequence, TypeVar, TYPE_CHECKING
20
20
 
21
21
  from robot.model import Tags
22
22
  from robot.errors import DataError
@@ -29,10 +29,13 @@ from .dynamicmethods import (GetKeywordArguments, GetKeywordDocumentation,
29
29
  RunKeyword)
30
30
  from .model import BodyItemParent, Keyword
31
31
  from .keywordimplementation import KeywordImplementation
32
- from .librarykeywordrunner import EmbeddedArgumentsRunner, LibraryKeywordRunner, RunKeywordRunner
32
+ from .librarykeywordrunner import (EmbeddedArgumentsRunner, LibraryKeywordRunner,
33
+ RunKeywordRunner)
33
34
  from .runkwregister import RUN_KW_REGISTER
34
35
 
35
36
  if TYPE_CHECKING:
37
+ from robot.conf import LanguagesLike
38
+
36
39
  from .testlibraries import DynamicLibrary, TestLibrary
37
40
 
38
41
 
@@ -73,7 +76,8 @@ class LibraryKeyword(KeywordImplementation):
73
76
  return start_lineno + increment
74
77
  return start_lineno
75
78
 
76
- def create_runner(self, name: 'str|None', languages=None) -> LibraryKeywordRunner:
79
+ def create_runner(self, name: 'str|None',
80
+ languages: 'LanguagesLike' = None) -> LibraryKeywordRunner:
77
81
  if self.embedded:
78
82
  return EmbeddedArgumentsRunner(self, name)
79
83
  if self._resolve_args_until is not None:
@@ -81,10 +85,13 @@ class LibraryKeyword(KeywordImplementation):
81
85
  return RunKeywordRunner(self, execute_in_dry_run=dry_run)
82
86
  return LibraryKeywordRunner(self, languages=languages)
83
87
 
84
- def resolve_arguments(self, args: Sequence[str], variables=None,
85
- languages=None) -> 'tuple[list, list]':
88
+ def resolve_arguments(self, args: 'Sequence[str|Any]',
89
+ named_args: 'Mapping[str, Any]|None' = None,
90
+ variables=None,
91
+ languages: 'LanguagesLike' = None) -> 'tuple[list, list]':
86
92
  resolve_args_until = self._resolve_args_until
87
- positional, named = self.args.resolve(args, variables, self.owner.converters,
93
+ positional, named = self.args.resolve(args, named_args, variables,
94
+ self.owner.converters,
88
95
  resolve_named=resolve_args_until is None,
89
96
  resolve_args_until=resolve_args_until,
90
97
  languages=languages)
@@ -198,9 +205,12 @@ class DynamicKeyword(LibraryKeyword):
198
205
  def from_name(cls, name: str, owner: 'DynamicLibrary') -> 'DynamicKeyword':
199
206
  return DynamicKeywordCreator(name, owner).create()
200
207
 
201
- def resolve_arguments(self, arguments, variables=None,
202
- languages=None) -> 'tuple[list, list]':
203
- positional, named = super().resolve_arguments(arguments, variables, languages)
208
+ def resolve_arguments(self, args: 'Sequence[str|Any]',
209
+ named_args: 'Mapping[str, Any]|None' = None,
210
+ variables=None,
211
+ languages: 'LanguagesLike' = None) -> 'tuple[list, list]':
212
+ positional, named = super().resolve_arguments(args, named_args, variables,
213
+ languages)
204
214
  if not self.owner.supports_named_args:
205
215
  positional, named = self.args.map(positional, named)
206
216
  return positional, named
@@ -49,32 +49,38 @@ class LibraryKeywordRunner:
49
49
  with StatusReporter(data, result, context, run, implementation=kw):
50
50
  if run:
51
51
  with assignment.assigner(context) as assigner:
52
- return_value = self._run(kw, data.args, result, context)
52
+ return_value = self._run(data, kw, context)
53
53
  assigner.assign(return_value)
54
54
  return return_value
55
55
 
56
56
  def _config_result(self, result: KeywordResult, data: KeywordData,
57
57
  kw: 'LibraryKeyword', assignment):
58
+ args = tuple(data.args)
59
+ if data.named_args:
60
+ args += tuple(f'{n}={v}' for n, v in data.named_args.items())
58
61
  result.config(name=self.name,
59
62
  owner=kw.owner.name,
60
63
  doc=kw.short_doc,
61
- args=data.args,
64
+ args=args,
62
65
  assign=tuple(assignment),
63
66
  tags=kw.tags,
64
67
  type=data.type)
65
68
 
66
- def _run(self, kw: 'LibraryKeyword', args, result: KeywordResult, context):
69
+ def _run(self, data: KeywordData, kw: 'LibraryKeyword', context):
67
70
  if self.pre_run_messages:
68
71
  for message in self.pre_run_messages:
69
72
  context.output.message(message)
70
73
  variables = context.variables if not context.dry_run else None
71
- positional, named = kw.resolve_arguments(args, variables, self.languages)
74
+ positional, named = self._resolve_arguments(data, kw, variables)
72
75
  context.output.trace(lambda: self._trace_log_args(positional, named),
73
76
  write_if_flat=False)
74
77
  if kw.error:
75
78
  raise DataError(kw.error)
76
79
  return self._execute(kw.method, positional, named, context)
77
80
 
81
+ def _resolve_arguments(self, data: KeywordData, kw: 'LibraryKeyword', variables=None):
82
+ return kw.resolve_arguments(data.args, data.named_args, variables, self.languages)
83
+
78
84
  def _trace_log_args(self, positional, named):
79
85
  args = [prepr(arg) for arg in positional]
80
86
  args += ['%s=%s' % (safe_str(n), prepr(v)) for n, v in named]
@@ -127,18 +133,20 @@ class LibraryKeywordRunner:
127
133
  self._config_result(result, data, kw, assignment)
128
134
  with StatusReporter(data, result, context, run=False, implementation=kw):
129
135
  assignment.validate_assignment()
130
- self._dry_run(kw, data.args, result, context)
136
+ if self._executed_in_dry_run(kw):
137
+ self._run(data, kw, context)
138
+ else:
139
+ self._resolve_arguments(data, kw)
140
+ self._end_dry_run(data, kw, result, context)
131
141
 
132
- def _dry_run(self, kw: 'LibraryKeyword', args, result: KeywordResult, context):
133
- if self._executed_in_dry_run(kw):
134
- self._run(kw, args, result, context)
135
- else:
136
- kw.resolve_arguments(args, languages=self.languages)
142
+ def _end_dry_run(self, data: KeywordData, kw: 'LibraryKeyword',
143
+ result: KeywordResult, context):
144
+ pass
137
145
 
138
146
  def _executed_in_dry_run(self, kw: 'LibraryKeyword'):
139
147
  return (kw.owner.name == 'BuiltIn'
140
148
  and kw.name in ('Import Library', 'Set Library Search Order',
141
- 'Set Tags', 'Remove Tags'))
149
+ 'Set Tags', 'Remove Tags', 'Import Resource'))
142
150
 
143
151
 
144
152
  class EmbeddedArgumentsRunner(LibraryKeywordRunner):
@@ -147,11 +155,9 @@ class EmbeddedArgumentsRunner(LibraryKeywordRunner):
147
155
  super().__init__(keyword, name)
148
156
  self.embedded_args = keyword.embedded.match(name).groups()
149
157
 
150
- def _run(self, kw: 'LibraryKeyword', args, result: KeywordResult, context):
151
- return super()._run(kw, self.embedded_args + args, result, context)
152
-
153
- def _dry_run(self, kw: 'LibraryKeyword', args, result: KeywordResult, context):
154
- return super()._dry_run(kw, self.embedded_args + args, result, context)
158
+ def _resolve_arguments(self, data: KeywordData, kw: 'LibraryKeyword', variables=None):
159
+ return kw.resolve_arguments(self.embedded_args + data.args, data.named_args,
160
+ variables, self.languages)
155
161
 
156
162
  def _config_result(self, result: KeywordResult, data: KeywordData,
157
163
  kw: 'LibraryKeyword', assignment):
@@ -177,12 +183,12 @@ class RunKeywordRunner(LibraryKeywordRunner):
177
183
  finally:
178
184
  STOP_SIGNAL_MONITOR.stop_running_keyword()
179
185
 
180
- def _dry_run(self, kw: 'LibraryKeyword', args, result: KeywordResult, context):
181
- super()._dry_run(kw, args, result, context)
186
+ def _end_dry_run(self, data: KeywordData, kw: 'LibraryKeyword',
187
+ result: KeywordResult, context):
182
188
  wrapper = UserKeyword(name=kw.name,
183
189
  doc="Wraps keywords executed by '{kw.name}' in dry-run.",
184
190
  parent=kw.parent)
185
- wrapper.body = [k for k in self._get_dry_run_keywords(kw, args)
191
+ wrapper.body = [k for k in self._get_dry_run_keywords(kw, data.args)
186
192
  if not contains_variable(k.name)]
187
193
  BodyRunner(context).run(wrapper, result)
188
194
 
@@ -43,7 +43,7 @@ from robot.conf import RobotSettings
43
43
  from robot.errors import BreakLoop, ContinueLoop, DataError, ReturnFromKeyword, VariableError
44
44
  from robot.model import BodyItem, DataDict, TestSuites
45
45
  from robot.output import LOGGER, Output, pyloggingconf
46
- from robot.utils import setter
46
+ from robot.utils import format_assign_message, setter
47
47
  from robot.variables import VariableResolver
48
48
 
49
49
  from .bodyrunner import ForRunner, IfRunner, KeywordRunner, TryRunner, WhileRunner
@@ -84,7 +84,13 @@ class Argument:
84
84
  """A temporary API for creating named arguments with non-string values.
85
85
 
86
86
  This class was added in RF 7.0.1 (#5031) after a failed attempt to add a public
87
- API for this purpose in RF 7.0 (#5000). A better, public API is planned for RF 7.1.
87
+ API for this purpose in RF 7.0 (#5000). A better public API that allows passing
88
+ named arguments separately was added in RF 7.1 (#5143).
89
+
90
+ If you need to support also RF 7.0, you can pass named arguments as two-item tuples
91
+ like `(name, value)` and positional arguments as one-item tuples like `(value,)`.
92
+ That approach does not work anymore in RF 7.0.1, though, so the code needs to be
93
+ conditional depending on Robot Framework version.
88
94
 
89
95
  The main limitation of this class is that it is not compatible with the JSON model.
90
96
  The current plan is to remove this in the future, possibly already in RF 8.0, but
@@ -116,24 +122,33 @@ class Keyword(model.Keyword, WithSource):
116
122
  The actual keyword that is executed depends on the context where this model
117
123
  is executed.
118
124
 
119
- Arguments originating from normal Robot Framework data are stored as list of
120
- strings in the exact same format as in the data. This means that arguments can
121
- have variables and escape characters, and that named arguments are specified
122
- using the ``name=value`` syntax.
125
+ Arguments originating from normal Robot Framework data are stored in the
126
+ :attr:`args` attribute as a tuple of strings in the exact same format as in
127
+ the data. This means that arguments can have variables and escape characters,
128
+ and that named arguments are specified using the ``name=value`` syntax.
129
+
130
+ When creating keywords programmatically, it is possible to set :attr:`named_args`
131
+ separately and use :attr:`args` only for positional arguments. Argument values
132
+ do not need to be strings, but also in this case strings can contain variables
133
+ and normal Robot Framework escaping rules must be taken into account.
123
134
  """
124
- __slots__ = ['lineno']
135
+ __slots__ = ['named_args', 'lineno']
125
136
 
126
137
  def __init__(self, name: str = '',
127
138
  args: 'Sequence[str|Argument|Any]' = (),
139
+ named_args: 'Mapping[str, Any]|None' = None,
128
140
  assign: Sequence[str] = (),
129
141
  type: str = BodyItem.KEYWORD,
130
142
  parent: BodyItemParent = None,
131
143
  lineno: 'int|None' = None):
132
144
  super().__init__(name, args, assign, type, parent)
145
+ self.named_args = named_args
133
146
  self.lineno = lineno
134
147
 
135
148
  def to_dict(self) -> DataDict:
136
149
  data = super().to_dict()
150
+ if self.named_args is not None:
151
+ data['named_args'] = self.named_args
137
152
  if self.lineno:
138
153
  data['lineno'] = self.lineno
139
154
  return data
@@ -359,35 +374,39 @@ class Var(model.Var, WithSource):
359
374
  def run(self, result, context, run=True, templated=False):
360
375
  result = result.body.create_var(self.name, self.value, self.scope, self.separator)
361
376
  with StatusReporter(self, result, context, run):
362
- if run:
363
- if self.error:
364
- raise DataError(self.error, syntax=True)
365
- if not context.dry_run:
366
- scope = self._get_scope(context.variables)
367
- setter = getattr(context.variables, f'set_{scope}')
368
- try:
369
- resolver = VariableResolver.from_variable(self)
370
- setter(self._resolve_name(self.name, context.variables),
371
- resolver.resolve(context.variables))
372
- except DataError as err:
373
- raise VariableError(f"Setting variable '{self.name}' failed: {err}")
377
+ if self.error and run:
378
+ raise DataError(self.error, syntax=True)
379
+ if not run or context.dry_run:
380
+ return
381
+ scope, config = self._get_scope(context.variables)
382
+ set_variable = getattr(context.variables, f'set_{scope}')
383
+ try:
384
+ name, value = self._resolve_name_and_value(context.variables)
385
+ set_variable(name, value, **config)
386
+ context.info(format_assign_message(name, value))
387
+ except DataError as err:
388
+ raise VariableError(f"Setting variable '{self.name}' failed: {err}")
374
389
 
375
390
  def _get_scope(self, variables):
376
391
  if not self.scope:
377
- return 'local'
392
+ return 'local', {}
378
393
  try:
379
394
  scope = variables.replace_string(self.scope)
380
395
  if scope.upper() == 'TASK':
381
- return 'test'
382
- if scope.upper() in ('GLOBAL', 'SUITE', 'TEST', 'LOCAL'):
383
- return scope.lower()
396
+ return 'test', {}
397
+ if scope.upper() == 'SUITES':
398
+ return 'suite', {'children': True}
399
+ if scope.upper() in ('LOCAL', 'TEST', 'SUITE', 'GLOBAL'):
400
+ return scope.lower(), {}
384
401
  raise DataError(f"Value '{scope}' is not accepted. Valid values are "
385
- f"'GLOBAL', 'SUITE', 'TEST', 'TASK' and 'LOCAL'.")
402
+ f"'LOCAL', 'TEST', 'TASK', 'SUITE', 'SUITES' and 'GLOBAL'.")
386
403
  except DataError as err:
387
404
  raise DataError(f"Invalid VAR scope: {err}")
388
405
 
389
- def _resolve_name(self, name, variables):
390
- return name[:2] + variables.replace_string(name[2:-1]) + '}'
406
+ def _resolve_name_and_value(self, variables):
407
+ name = self.name[:2] + variables.replace_string(self.name[2:-1]) + '}'
408
+ value = VariableResolver.from_variable(self).resolve(variables)
409
+ return name, value
391
410
 
392
411
  def to_dict(self) -> DataDict:
393
412
  data = super().to_dict()