robotframework 6.1.1__zip → 7.0a1__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 (288) hide show
  1. {robotframework-6.1.1/src/robotframework.egg-info → robotframework-7.0a1}/PKG-INFO +3 -6
  2. {robotframework-6.1.1 → robotframework-7.0a1}/setup.py +2 -5
  3. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/api/interfaces.py +35 -48
  4. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/api/parsing.py +4 -2
  5. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/conf/gatherfailed.py +2 -2
  6. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/conf/languages.py +0 -9
  7. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/conf/settings.py +8 -5
  8. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/log.css +4 -0
  9. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/log.html +9 -1
  10. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/model.js +2 -4
  11. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/testdata.js +10 -3
  12. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/template.py +3 -3
  13. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/builder.py +0 -8
  14. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/datatypes.py +9 -10
  15. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/htmlutils.py +4 -7
  16. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/jsonbuilder.py +14 -10
  17. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/model.py +13 -25
  18. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/robotbuilder.py +13 -3
  19. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/xmlbuilder.py +8 -8
  20. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/xmlwriter.py +12 -38
  21. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/BuiltIn.py +215 -189
  22. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Collections.py +2 -9
  23. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/DateTime.py +1 -1
  24. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/OperatingSystem.py +4 -3
  25. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Process.py +26 -27
  26. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Remote.py +40 -36
  27. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/String.py +4 -4
  28. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/XML.py +7 -8
  29. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/__init__.py +2 -2
  30. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/__init__.py +4 -4
  31. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/body.py +14 -6
  32. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/configurer.py +15 -11
  33. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/control.py +151 -81
  34. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/filter.py +31 -25
  35. robotframework-7.0a1/src/robot/model/keyword.py +70 -0
  36. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/message.py +19 -10
  37. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/namepatterns.py +3 -25
  38. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/stats.py +9 -15
  39. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/tags.py +1 -1
  40. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/testcase.py +12 -21
  41. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/testsuite.py +16 -22
  42. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/visitor.py +35 -8
  43. robotframework-7.0a1/src/robot/output/console/dotted.py +90 -0
  44. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/console/quiet.py +3 -2
  45. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/console/verbose.py +60 -60
  46. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/debugfile.py +36 -23
  47. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/filelogger.py +16 -13
  48. robotframework-7.0a1/src/robot/output/listeners.py +586 -0
  49. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/logger.py +164 -77
  50. robotframework-7.0a1/src/robot/output/loggerapi.py +152 -0
  51. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/loggerhelper.py +23 -56
  52. robotframework-7.0a1/src/robot/output/output.py +158 -0
  53. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/stdoutlogsplitter.py +8 -5
  54. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/xmllogger.py +163 -109
  55. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/blocklexers.py +17 -13
  56. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/context.py +12 -2
  57. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/lexer.py +1 -1
  58. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/settings.py +6 -3
  59. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/statementlexers.py +39 -10
  60. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/tokens.py +27 -29
  61. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/model/blocks.py +19 -6
  62. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/model/statements.py +184 -84
  63. robotframework-7.0a1/src/robot/parsing/model/visitor.py +102 -0
  64. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/expandkeywordmatcher.py +1 -1
  65. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/jsbuildingcontext.py +8 -6
  66. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/jsmodelbuilders.py +88 -61
  67. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/stringcache.py +4 -3
  68. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/xunitwriter.py +15 -21
  69. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/__init__.py +3 -2
  70. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/configurer.py +12 -9
  71. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/flattenkeywordmatcher.py +8 -8
  72. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/keywordremover.py +71 -54
  73. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/merger.py +1 -1
  74. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/model.py +400 -316
  75. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/modeldeprecation.py +9 -3
  76. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/resultbuilder.py +21 -23
  77. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/xmlelementhandlers.py +76 -40
  78. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/__init__.py +1 -1
  79. robotframework-7.0a1/src/robot/running/arguments/argumentconverter.py +101 -0
  80. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/argumentmapper.py +16 -14
  81. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/argumentresolver.py +41 -33
  82. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/argumentspec.py +24 -90
  83. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/argumentvalidator.py +34 -27
  84. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/customconverters.py +14 -11
  85. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/embedded.py +23 -26
  86. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/typeconverters.py +175 -213
  87. robotframework-7.0a1/src/robot/running/arguments/typeinfo.py +367 -0
  88. robotframework-7.0a1/src/robot/running/arguments/typevalidator.py +62 -0
  89. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/bodyrunner.py +83 -68
  90. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/builder/parsers.py +8 -10
  91. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/builder/settings.py +9 -17
  92. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/builder/transformers.py +166 -308
  93. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/context.py +80 -25
  94. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/handlers.py +11 -16
  95. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/handlerstore.py +1 -1
  96. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/librarykeywordrunner.py +9 -17
  97. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/model.py +109 -32
  98. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/namespace.py +18 -19
  99. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/statusreporter.py +13 -12
  100. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/suiterunner.py +15 -17
  101. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/testlibraries.py +33 -40
  102. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/usererrorhandler.py +8 -8
  103. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/userkeyword.py +13 -8
  104. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/userkeywordrunner.py +18 -21
  105. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/testdoc.py +18 -13
  106. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/__init__.py +50 -35
  107. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/connectioncache.py +64 -59
  108. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/encodingsniffer.py +1 -1
  109. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/escaping.py +11 -9
  110. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/markupwriters.py +20 -13
  111. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/normalizing.py +9 -24
  112. robotframework-7.0a1/src/robot/utils/notset.py +33 -0
  113. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/platform.py +15 -5
  114. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/robotpath.py +1 -0
  115. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/robottime.py +120 -88
  116. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/robottypes.py +16 -31
  117. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/setter.py +0 -5
  118. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/text.py +7 -4
  119. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/unic.py +2 -2
  120. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/__init__.py +2 -2
  121. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/assigner.py +17 -19
  122. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/evaluation.py +20 -17
  123. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/filesetter.py +80 -80
  124. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/replacer.py +33 -36
  125. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/scopes.py +3 -3
  126. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/search.py +66 -41
  127. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/store.py +14 -16
  128. robotframework-7.0a1/src/robot/variables/tablesetter.py +164 -0
  129. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/variables.py +1 -1
  130. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/version.py +1 -1
  131. {robotframework-6.1.1 → robotframework-7.0a1/src/robotframework.egg-info}/PKG-INFO +3 -6
  132. {robotframework-6.1.1 → robotframework-7.0a1}/src/robotframework.egg-info/SOURCES.txt +3 -4
  133. {robotframework-6.1.1 → robotframework-7.0a1}/tasks.py +6 -6
  134. robotframework-6.1.1/src/robot/libraries/Reserved.py +0 -48
  135. robotframework-6.1.1/src/robot/model/keyword.py +0 -173
  136. robotframework-6.1.1/src/robot/output/console/dotted.py +0 -90
  137. robotframework-6.1.1/src/robot/output/listenerarguments.py +0 -165
  138. robotframework-6.1.1/src/robot/output/listenermethods.py +0 -113
  139. robotframework-6.1.1/src/robot/output/listeners.py +0 -174
  140. robotframework-6.1.1/src/robot/output/output.py +0 -95
  141. robotframework-6.1.1/src/robot/parsing/model/visitor.py +0 -67
  142. robotframework-6.1.1/src/robot/running/arguments/argumentconverter.py +0 -79
  143. robotframework-6.1.1/src/robot/running/arguments/typevalidator.py +0 -56
  144. robotframework-6.1.1/src/robot/running/modelcombiner.py +0 -32
  145. robotframework-6.1.1/src/robot/variables/tablesetter.py +0 -156
  146. {robotframework-6.1.1 → robotframework-7.0a1}/AUTHORS.rst +0 -0
  147. {robotframework-6.1.1 → robotframework-7.0a1}/BUILD.rst +0 -0
  148. {robotframework-6.1.1 → robotframework-7.0a1}/CONTRIBUTING.rst +0 -0
  149. {robotframework-6.1.1 → robotframework-7.0a1}/COPYRIGHT.txt +0 -0
  150. {robotframework-6.1.1 → robotframework-7.0a1}/INSTALL.rst +0 -0
  151. {robotframework-6.1.1 → robotframework-7.0a1}/LICENSE.txt +0 -0
  152. {robotframework-6.1.1 → robotframework-7.0a1}/MANIFEST.in +0 -0
  153. {robotframework-6.1.1 → robotframework-7.0a1}/README.rst +0 -0
  154. {robotframework-6.1.1 → robotframework-7.0a1}/setup.cfg +0 -0
  155. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/__init__.py +0 -0
  156. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/__main__.py +0 -0
  157. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/api/__init__.py +0 -0
  158. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/api/deco.py +0 -0
  159. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/api/exceptions.py +0 -0
  160. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/api/logger.py +0 -0
  161. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/conf/__init__.py +0 -0
  162. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/errors.py +0 -0
  163. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/__init__.py +0 -0
  164. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/common/__init__.py +0 -0
  165. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/common/js_disabled.css +0 -0
  166. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/common/storage.js +0 -0
  167. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/htmlfilewriter.py +0 -0
  168. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/jsonwriter.py +0 -0
  169. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/lib/__init__.py +0 -0
  170. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
  171. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/lib/jquery.min.js +0 -0
  172. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
  173. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
  174. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
  175. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/libdoc/__init__.py +0 -0
  176. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/libdoc/doc_formatting.css +0 -0
  177. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/libdoc/libdoc.css +0 -0
  178. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/libdoc/libdoc.html +0 -0
  179. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/libdoc/print.css +0 -0
  180. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/libdoc/pygments.css +0 -0
  181. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/__init__.py +0 -0
  182. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/common.css +0 -0
  183. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/doc_formatting.css +0 -0
  184. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/fileloading.js +0 -0
  185. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/log.js +0 -0
  186. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/print.css +0 -0
  187. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/report.css +0 -0
  188. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/report.html +0 -0
  189. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/util.js +0 -0
  190. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/view.js +0 -0
  191. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/testdoc/__init__.py +0 -0
  192. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/testdoc/testdoc.css +0 -0
  193. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/testdoc/testdoc.html +0 -0
  194. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdoc.py +0 -0
  195. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/__init__.py +0 -0
  196. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/consoleviewer.py +0 -0
  197. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/htmlwriter.py +0 -0
  198. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/jsonwriter.py +0 -0
  199. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/output.py +0 -0
  200. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/standardtypes.py +0 -0
  201. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/writer.py +0 -0
  202. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Dialogs.py +0 -0
  203. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Easter.py +0 -0
  204. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Screenshot.py +0 -0
  205. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Telnet.py +0 -0
  206. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/dialogs_py.py +0 -0
  207. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/fixture.py +0 -0
  208. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/itemlist.py +0 -0
  209. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/metadata.py +0 -0
  210. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/modelobject.py +0 -0
  211. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/modifier.py +0 -0
  212. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/statistics.py +0 -0
  213. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/suitestatistics.py +0 -0
  214. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/tagsetter.py +0 -0
  215. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/tagstatistics.py +0 -0
  216. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/totalstatistics.py +0 -0
  217. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/__init__.py +0 -0
  218. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/console/__init__.py +0 -0
  219. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/console/highlighting.py +0 -0
  220. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/librarylogger.py +0 -0
  221. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/pyloggingconf.py +0 -0
  222. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/__init__.py +0 -0
  223. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/__init__.py +0 -0
  224. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/tokenizer.py +0 -0
  225. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/model/__init__.py +0 -0
  226. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/parser/__init__.py +0 -0
  227. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/parser/blockparsers.py +0 -0
  228. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/parser/fileparser.py +0 -0
  229. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/parser/parser.py +0 -0
  230. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/suitestructure.py +0 -0
  231. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/pythonpathsetter.py +0 -0
  232. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/rebot.py +0 -0
  233. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/__init__.py +0 -0
  234. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/jsexecutionresult.py +0 -0
  235. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/jswriter.py +0 -0
  236. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/logreportwriters.py +0 -0
  237. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/outputwriter.py +0 -0
  238. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/resultwriter.py +0 -0
  239. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/executionerrors.py +0 -0
  240. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/executionresult.py +0 -0
  241. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/messagefilter.py +0 -0
  242. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/suiteteardownfailed.py +0 -0
  243. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/visitor.py +0 -0
  244. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/run.py +0 -0
  245. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/__init__.py +0 -0
  246. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/argumentparser.py +0 -0
  247. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/builder/__init__.py +0 -0
  248. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/builder/builders.py +0 -0
  249. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/dynamicmethods.py +0 -0
  250. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/importer.py +0 -0
  251. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/libraryscopes.py +0 -0
  252. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/outputcapture.py +0 -0
  253. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/randomizer.py +0 -0
  254. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/runkwregister.py +0 -0
  255. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/signalhandler.py +0 -0
  256. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/status.py +0 -0
  257. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/timeouts/__init__.py +0 -0
  258. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/timeouts/posix.py +0 -0
  259. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/timeouts/windows.py +0 -0
  260. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/application.py +0 -0
  261. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/argumentparser.py +0 -0
  262. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/asserts.py +0 -0
  263. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/charwidth.py +0 -0
  264. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/compress.py +0 -0
  265. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/dotdict.py +0 -0
  266. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/encoding.py +0 -0
  267. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/error.py +0 -0
  268. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/etreewrapper.py +0 -0
  269. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/filereader.py +0 -0
  270. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/frange.py +0 -0
  271. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/htmlformatters.py +0 -0
  272. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/importer.py +0 -0
  273. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/markuputils.py +0 -0
  274. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/match.py +0 -0
  275. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/misc.py +0 -0
  276. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/recommendations.py +0 -0
  277. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/restreader.py +0 -0
  278. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/robotenv.py +0 -0
  279. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/robotinspect.py +0 -0
  280. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/robotio.py +0 -0
  281. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/sortable.py +0 -0
  282. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/typehints.py +0 -0
  283. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/finders.py +0 -0
  284. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/notfound.py +0 -0
  285. {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/resolvable.py +0 -0
  286. {robotframework-6.1.1 → robotframework-7.0a1}/src/robotframework.egg-info/dependency_links.txt +0 -0
  287. {robotframework-6.1.1 → robotframework-7.0a1}/src/robotframework.egg-info/entry_points.txt +0 -0
  288. {robotframework-6.1.1 → robotframework-7.0a1}/src/robotframework.egg-info/top_level.txt +0 -0
@@ -14,6 +14,7 @@
14
14
  # limitations under the License.
15
15
 
16
16
  import builtins
17
+ import re
17
18
  import token
18
19
  from collections.abc import MutableMapping
19
20
  from io import StringIO
@@ -22,7 +23,7 @@ from tokenize import generate_tokens, untokenize
22
23
  from robot.errors import DataError
23
24
  from robot.utils import get_error_message, type_name
24
25
 
25
- from .search import search_variable
26
+ from .search import VariableMatches
26
27
  from .notfound import variable_not_found
27
28
 
28
29
 
@@ -44,12 +45,18 @@ def evaluate_expression(expression, variables, modules=None, namespace=None,
44
45
  return _evaluate(expression, variables.store, modules, namespace)
45
46
  except DataError as err:
46
47
  error = str(err)
47
- recommendation = ''
48
- except Exception:
48
+ variable_recommendation = ''
49
+ except Exception as err:
49
50
  error = get_error_message()
50
- recommendation = _recommend_special_variables(original)
51
- raise DataError(f"Evaluating expression '{expression}' failed: {error}\n\n"
52
- f"{recommendation}".strip())
51
+ variable_recommendation = ''
52
+ if isinstance(err, NameError) and 'RF_VAR_' in error:
53
+ name = re.search(r'RF_VAR_([\w_]*)', error).group(1)
54
+ error = (f"Robot Framework variable '${name}' is used in a scope "
55
+ f"where it cannot be seen.")
56
+ else:
57
+ variable_recommendation = _recommend_special_variables(original)
58
+ raise DataError(f'Evaluating expression {expression!r} failed: {error}\n\n'
59
+ f'{variable_recommendation}'.strip())
53
60
 
54
61
 
55
62
  def _evaluate(expression, variable_store, modules=None, namespace=None):
@@ -106,19 +113,15 @@ def _import_modules(module_names):
106
113
 
107
114
 
108
115
  def _recommend_special_variables(expression):
109
- example = []
110
- remaining = expression
111
- while True:
112
- match = search_variable(remaining)
113
- if not match:
114
- break
115
- example[-1:] = [match.before, match.identifier, match.base, match.after]
116
- remaining = example[-1]
117
- if not example:
116
+ matches = VariableMatches(expression)
117
+ if not matches:
118
118
  return ''
119
+ example = []
120
+ for match in matches:
121
+ example[-1:] += [match.before, match.identifier, match.base, match.after]
119
122
  example = ''.join(example)
120
- return (f"Variables in the original expression '{expression}' were resolved "
121
- f"before the expression was evaluated. Try using '{example}' "
123
+ return (f"Variables in the original expression {expression!r} were resolved "
124
+ f"before the expression was evaluated. Try using {example!r} "
122
125
  f"syntax to avoid that. See Evaluating Expressions appendix in "
123
126
  f"Robot Framework User Guide for more details.")
124
127
 
@@ -23,14 +23,16 @@ except ImportError:
23
23
 
24
24
  from robot.errors import DataError
25
25
  from robot.output import LOGGER
26
- from robot.utils import (get_error_message, is_dict_like, is_list_like,
27
- is_string, seq2str2, type_name, DotDict, Importer)
26
+ from robot.utils import (DotDict, get_error_message, Importer, is_dict_like,
27
+ is_list_like, type_name)
28
+
29
+ from .store import VariableStore
28
30
 
29
31
 
30
32
  class VariableFileSetter:
31
33
 
32
- def __init__(self, store):
33
- self._store = store
34
+ def __init__(self, store: VariableStore):
35
+ self.store = store
34
36
 
35
37
  def set(self, path_or_variables, args=None, overwrite=False):
36
38
  variables = self._import_if_needed(path_or_variables, args)
@@ -38,10 +40,9 @@ class VariableFileSetter:
38
40
  return variables
39
41
 
40
42
  def _import_if_needed(self, path_or_variables, args=None):
41
- if not is_string(path_or_variables):
43
+ if not isinstance(path_or_variables, str):
42
44
  return path_or_variables
43
- LOGGER.info("Importing variable file '%s' with args %s"
44
- % (path_or_variables, args))
45
+ LOGGER.info(f"Importing variable file '{path_or_variables}' with args {args}.")
45
46
  if path_or_variables.lower().endswith(('.yaml', '.yml')):
46
47
  importer = YamlImporter()
47
48
  elif path_or_variables.lower().endswith('.json'):
@@ -50,48 +51,14 @@ class VariableFileSetter:
50
51
  importer = PythonImporter()
51
52
  try:
52
53
  return importer.import_variables(path_or_variables, args)
53
- except:
54
- args = 'with arguments %s ' % seq2str2(args) if args else ''
55
- raise DataError("Processing variable file '%s' %sfailed: %s"
56
- % (path_or_variables, args, get_error_message()))
54
+ except Exception:
55
+ args = f'with arguments {args} ' if args else ''
56
+ raise DataError(f"Processing variable file '{path_or_variables}' "
57
+ f"{args}failed: {get_error_message()}")
57
58
 
58
59
  def _set(self, variables, overwrite=False):
59
60
  for name, value in variables:
60
- self._store.add(name, value, overwrite)
61
-
62
-
63
- class YamlImporter:
64
-
65
- def import_variables(self, path, args=None):
66
- if args:
67
- raise DataError('YAML variable files do not accept arguments.')
68
- variables = self._import(path)
69
- return [('${%s}' % name, self._dot_dict(value))
70
- for name, value in variables]
71
-
72
- def _import(self, path):
73
- with io.open(path, encoding='UTF-8') as stream:
74
- variables = self._load_yaml(stream)
75
- if not is_dict_like(variables):
76
- raise DataError('YAML variable file must be a mapping, got %s.'
77
- % type_name(variables))
78
- return variables.items()
79
-
80
- def _load_yaml(self, stream):
81
- if not yaml:
82
- raise DataError('Using YAML variable files requires PyYAML module '
83
- 'to be installed. Typically you can install it '
84
- 'by running `pip install pyyaml`.')
85
- if yaml.__version__.split('.')[0] == '3':
86
- return yaml.load(stream)
87
- return yaml.full_load(stream)
88
-
89
- def _dot_dict(self, value):
90
- if is_dict_like(value):
91
- return DotDict((k, self._dot_dict(v)) for k, v in value.items())
92
- if is_list_like(value):
93
- return [self._dot_dict(v) for v in value]
94
- return value
61
+ self.store.add(name, value, overwrite, decorated=False)
95
62
 
96
63
 
97
64
  class PythonImporter:
@@ -102,24 +69,29 @@ class PythonImporter:
102
69
  return self._get_variables(var_file, args)
103
70
 
104
71
  def _get_variables(self, var_file, args):
105
- if self._is_dynamic(var_file):
106
- variables = self._get_dynamic(var_file, args)
107
- else:
72
+ get_variables = (getattr(var_file, 'get_variables', None) or
73
+ getattr(var_file, 'getVariables', None))
74
+ if get_variables:
75
+ variables = self._get_dynamic(get_variables, args)
76
+ elif not args:
108
77
  variables = self._get_static(var_file)
78
+ else:
79
+ raise DataError('Static variable files do not accept arguments.')
109
80
  return list(self._decorate_and_validate(variables))
110
81
 
111
- def _is_dynamic(self, var_file):
112
- return (hasattr(var_file, 'get_variables') or
113
- hasattr(var_file, 'getVariables'))
114
-
115
- def _get_dynamic(self, var_file, args):
116
- get_variables = (getattr(var_file, 'get_variables', None) or
117
- getattr(var_file, 'getVariables'))
118
- variables = get_variables(*args)
82
+ def _get_dynamic(self, get_variables, args):
83
+ positional, named = self._resolve_arguments(get_variables, args)
84
+ variables = get_variables(*positional, **dict(named))
119
85
  if is_dict_like(variables):
120
86
  return variables.items()
121
- raise DataError("Expected '%s' to return dict-like value, got %s."
122
- % (get_variables.__name__, type_name(variables)))
87
+ raise DataError(f"Expected '{get_variables.__name__}' to return "
88
+ f"a dictionary-like value, got {type_name(variables)}.")
89
+
90
+ def _resolve_arguments(self, get_variables, args):
91
+ # Avoid cyclic import. Yuck.
92
+ from robot.running.arguments import PythonArgumentParser
93
+ spec = PythonArgumentParser('variable file').parse(get_variables)
94
+ return spec.resolve(args)
123
95
 
124
96
  def _get_static(self, var_file):
125
97
  names = [attr for attr in dir(var_file) if not attr.startswith('_')]
@@ -132,40 +104,35 @@ class PythonImporter:
132
104
 
133
105
  def _decorate_and_validate(self, variables):
134
106
  for name, value in variables:
135
- name = self._decorate(name)
136
- self._validate(name, value)
107
+ if name.startswith('LIST__'):
108
+ if not is_list_like(value):
109
+ raise DataError(f"Invalid variable '{name}': Expected a "
110
+ f"list-like value, got {type_name(value)}.")
111
+ name = name[6:]
112
+ value = list(value)
113
+ elif name.startswith('DICT__'):
114
+ if not is_dict_like(value):
115
+ raise DataError(f"Invalid variable '{name}': Expected a "
116
+ f"dictionary-like value, got {type_name(value)}.")
117
+ name = name[6:]
118
+ value = DotDict(value)
137
119
  yield name, value
138
120
 
139
- def _decorate(self, name):
140
- if name.startswith('LIST__'):
141
- return '@{%s}' % name[6:]
142
- if name.startswith('DICT__'):
143
- return '&{%s}' % name[6:]
144
- return '${%s}' % name
145
-
146
- def _validate(self, name, value):
147
- if name[0] == '@' and not is_list_like(value):
148
- raise DataError("Invalid variable '%s': Expected list-like value, "
149
- "got %s." % (name, type_name(value)))
150
- if name[0] == '&' and not is_dict_like(value):
151
- raise DataError("Invalid variable '%s': Expected dict-like value, "
152
- "got %s." % (name, type_name(value)))
153
-
154
121
 
155
122
  class JsonImporter:
123
+
156
124
  def import_variables(self, path, args=None):
157
125
  if args:
158
126
  raise DataError('JSON variable files do not accept arguments.')
159
127
  variables = self._import(path)
160
- return [('${%s}' % name, self._dot_dict(value))
161
- for name, value in variables]
128
+ return [(name, self._dot_dict(value)) for name, value in variables]
162
129
 
163
130
  def _import(self, path):
164
131
  with io.open(path, encoding='UTF-8') as stream:
165
132
  variables = json.load(stream)
166
133
  if not is_dict_like(variables):
167
- raise DataError('JSON variable file must be a mapping, got %s.'
168
- % type_name(variables))
134
+ raise DataError(f'JSON variable file must be a mapping, '
135
+ f'got {type_name(variables)}.')
169
136
  return variables.items()
170
137
 
171
138
  def _dot_dict(self, value):
@@ -174,3 +141,36 @@ class JsonImporter:
174
141
  if is_list_like(value):
175
142
  return [self._dot_dict(v) for v in value]
176
143
  return value
144
+
145
+
146
+ class YamlImporter:
147
+
148
+ def import_variables(self, path, args=None):
149
+ if args:
150
+ raise DataError('YAML variable files do not accept arguments.')
151
+ variables = self._import(path)
152
+ return [(name, self._dot_dict(value)) for name, value in variables]
153
+
154
+ def _import(self, path):
155
+ with io.open(path, encoding='UTF-8') as stream:
156
+ variables = self._load_yaml(stream)
157
+ if not is_dict_like(variables):
158
+ raise DataError(f'YAML variable file must be a mapping, '
159
+ f'got {type_name(variables)}.')
160
+ return variables.items()
161
+
162
+ def _load_yaml(self, stream):
163
+ if not yaml:
164
+ raise DataError('Using YAML variable files requires PyYAML module '
165
+ 'to be installed. Typically you can install it '
166
+ 'by running `pip install pyyaml`.')
167
+ if yaml.__version__.split('.')[0] == '3':
168
+ return yaml.load(stream)
169
+ return yaml.full_load(stream)
170
+
171
+ def _dot_dict(self, value):
172
+ if is_dict_like(value):
173
+ return DotDict((k, self._dot_dict(v)) for k, v in value.items())
174
+ if is_list_like(value):
175
+ return [self._dot_dict(v) for v in value]
176
+ return value
@@ -42,33 +42,32 @@ class VariableReplacer:
42
42
  items = list(items or [])
43
43
  if replace_until is not None:
44
44
  return self._replace_list_until(items, replace_until, ignore_errors)
45
- return list(self._replace_list(items, ignore_errors))
45
+ return self._replace_list(items, ignore_errors)
46
46
 
47
- def _replace_list_until(self, items, replace_until, ignore_errors):
47
+ def _replace_list_until(self, items, limit, ignore_errors):
48
48
  # @{list} variables can contain more or less arguments than needed.
49
49
  # Therefore, we need to go through items one by one, and escape
50
50
  # possible extra items we got.
51
51
  replaced = []
52
- while len(replaced) < replace_until and items:
52
+ while len(replaced) < limit and items:
53
53
  replaced.extend(self._replace_list([items.pop(0)], ignore_errors))
54
- if len(replaced) > replace_until:
55
- replaced[replace_until:] = [escape(item)
56
- for item in replaced[replace_until:]]
54
+ if len(replaced) > limit:
55
+ replaced[limit:] = [escape(item) for item in replaced[limit:]]
57
56
  return replaced + items
58
57
 
59
58
  def _replace_list(self, items, ignore_errors):
59
+ result = []
60
60
  for item in items:
61
- for value in self._replace_list_item(item, ignore_errors):
62
- yield value
63
-
64
- def _replace_list_item(self, item, ignore_errors):
65
- match = search_variable(item, ignore_errors=ignore_errors)
66
- if not match:
67
- return [unescape(match.string)]
68
- value = self.replace_scalar(match, ignore_errors)
69
- if match.is_list_variable() and is_list_like(value):
70
- return value
71
- return [value]
61
+ match = search_variable(item, ignore_errors=ignore_errors)
62
+ if not match:
63
+ result.append(unescape(item))
64
+ 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)
70
+ return result
72
71
 
73
72
  def replace_scalar(self, item, ignore_errors=False):
74
73
  """Replaces variables from a scalar item.
@@ -77,20 +76,18 @@ class VariableReplacer:
77
76
  its value is returned. Otherwise, possible variables are replaced with
78
77
  'replace_string'. Result may be any object.
79
78
  """
80
- match = self._search_variable(item, ignore_errors=ignore_errors)
79
+ if isinstance(item, VariableMatch):
80
+ match = item
81
+ else:
82
+ match = search_variable(item, ignore_errors=ignore_errors)
81
83
  if not match:
82
84
  return unescape(match.string)
83
85
  return self._replace_scalar(match, ignore_errors)
84
86
 
85
- def _search_variable(self, item, ignore_errors):
86
- if isinstance(item, VariableMatch):
87
- return item
88
- return search_variable(item, ignore_errors=ignore_errors)
89
-
90
87
  def _replace_scalar(self, match, ignore_errors=False):
91
- if not match.is_variable():
92
- return self.replace_string(match, ignore_errors=ignore_errors)
93
- return self._get_variable_value(match, ignore_errors)
88
+ if match.is_variable():
89
+ return self._get_variable_value(match, ignore_errors)
90
+ return self._replace_string(match, unescape, ignore_errors)
94
91
 
95
92
  def replace_string(self, item, custom_unescaper=None, ignore_errors=False):
96
93
  """Replaces variables from a string. Result is always a string.
@@ -98,7 +95,10 @@ class VariableReplacer:
98
95
  Input can also be an already found VariableMatch.
99
96
  """
100
97
  unescaper = custom_unescaper or unescape
101
- match = self._search_variable(item, ignore_errors=ignore_errors)
98
+ if isinstance(item, VariableMatch):
99
+ match = item
100
+ else:
101
+ match = search_variable(item, ignore_errors=ignore_errors)
102
102
  if not match:
103
103
  return safe_str(unescaper(match.string))
104
104
  return self._replace_string(match, unescaper, ignore_errors)
@@ -106,10 +106,8 @@ class VariableReplacer:
106
106
  def _replace_string(self, match, unescaper, ignore_errors):
107
107
  parts = []
108
108
  while match:
109
- parts.extend([
110
- unescaper(match.before),
111
- safe_str(self._get_variable_value(match, ignore_errors))
112
- ])
109
+ parts.append(unescaper(match.before))
110
+ parts.append(safe_str(self._get_variable_value(match, ignore_errors)))
113
111
  match = search_variable(match.after, ignore_errors=ignore_errors)
114
112
  parts.append(unescaper(match.string))
115
113
  return ''.join(parts)
@@ -126,17 +124,16 @@ class VariableReplacer:
126
124
  if match.items:
127
125
  value = self._get_variable_item(match, value)
128
126
  try:
129
- value = self._validate_value(match, value)
127
+ return self._validate_value(match, value)
130
128
  except VariableError:
131
129
  raise
132
130
  except Exception:
133
131
  error = get_error_message()
134
132
  raise VariableError(f"Resolving variable '{match}' failed: {error}")
135
133
  except DataError:
136
- if not ignore_errors:
137
- raise
138
- value = unescape(match.match)
139
- return value
134
+ if ignore_errors:
135
+ return unescape(match.match)
136
+ raise
140
137
 
141
138
  def _get_variable_item(self, match, value):
142
139
  name = match.name
@@ -113,9 +113,9 @@ class VariableScopes:
113
113
  else:
114
114
  scope.set_from_file(variables, overwrite=overwrite)
115
115
 
116
- def set_from_variable_table(self, variables, overwrite=False):
116
+ def set_from_variable_section(self, variables, overwrite=False):
117
117
  for scope in self._scopes_until_suite:
118
- scope.set_from_variable_table(variables, overwrite)
118
+ scope.set_from_variable_section(variables, overwrite)
119
119
 
120
120
  def resolve_delayed(self):
121
121
  for scope in self._scopes_until_suite:
@@ -154,7 +154,7 @@ class VariableScopes:
154
154
  self.current[name] = value
155
155
  self._variables_set.set_keyword(name, value)
156
156
 
157
- def set_local_variable(self, name, value):
157
+ def set_local(self, name, value):
158
158
  self.current[name] = value
159
159
 
160
160
  def as_dict(self, decoration=True):
@@ -14,59 +14,79 @@
14
14
  # limitations under the License.
15
15
 
16
16
  import re
17
+ from typing import Iterator, Sequence
17
18
 
18
19
  from robot.errors import VariableError
19
20
  from robot.utils import is_string
20
21
 
21
22
 
22
- def search_variable(string, identifiers='$@&%*', ignore_errors=False):
23
+ def search_variable(string: str, identifiers: Sequence[str] = '$@&%*',
24
+ ignore_errors: bool = False) -> 'VariableMatch':
23
25
  if not (is_string(string) and '{' in string):
24
26
  return VariableMatch(string)
25
27
  return _search_variable(string, identifiers, ignore_errors)
26
28
 
27
29
 
28
- def contains_variable(string, identifiers='$@&'):
30
+ def contains_variable(string: str, identifiers: Sequence[str] = '$@&') -> bool:
29
31
  match = search_variable(string, identifiers, ignore_errors=True)
30
32
  return bool(match)
31
33
 
32
34
 
33
- def is_variable(string, identifiers='$@&'):
35
+ def is_variable(string: str, identifiers: Sequence[str] = '$@&') -> bool:
34
36
  match = search_variable(string, identifiers, ignore_errors=True)
35
37
  return match.is_variable()
36
38
 
37
39
 
38
- def is_scalar_variable(string):
40
+ def is_scalar_variable(string: str) -> bool:
39
41
  return is_variable(string, '$')
40
42
 
41
43
 
42
- def is_list_variable(string):
44
+ def is_list_variable(string: str) -> bool:
43
45
  return is_variable(string, '@')
44
46
 
45
47
 
46
- def is_dict_variable(string):
48
+ def is_dict_variable(string: str) -> bool:
47
49
  return is_variable(string, '&')
48
50
 
49
51
 
50
- def is_assign(string, identifiers='$@&', allow_assign_mark=False, allow_items=False):
52
+ def is_assign(string: str,
53
+ identifiers: Sequence[str] = '$@&',
54
+ allow_assign_mark: bool = False,
55
+ allow_nested: bool = False,
56
+ allow_items: bool = False) -> bool:
51
57
  match = search_variable(string, identifiers, ignore_errors=True)
52
- return match.is_assign(allow_assign_mark, allow_items=allow_items)
58
+ return match.is_assign(allow_assign_mark, allow_nested, allow_items)
53
59
 
54
60
 
55
- def is_scalar_assign(string, allow_assign_mark=False, allow_items=False):
56
- return is_assign(string, '$', allow_assign_mark, allow_items)
61
+ def is_scalar_assign(string: str,
62
+ allow_assign_mark: bool = False,
63
+ allow_nested: bool = False,
64
+ allow_items: bool = False) -> bool:
65
+ return is_assign(string, '$', allow_assign_mark, allow_nested, allow_items)
57
66
 
58
67
 
59
- def is_list_assign(string, allow_assign_mark=False, allow_items=False):
60
- return is_assign(string, '@', allow_assign_mark, allow_items)
68
+ def is_list_assign(string: str,
69
+ allow_assign_mark: bool = False,
70
+ allow_nested: bool = False,
71
+ allow_items: bool = False) -> bool:
72
+ return is_assign(string, '@', allow_assign_mark, allow_nested, allow_items)
61
73
 
62
74
 
63
- def is_dict_assign(string, allow_assign_mark=False, allow_items=False):
64
- return is_assign(string, '&', allow_assign_mark, allow_items)
75
+ def is_dict_assign(string: str,
76
+ allow_assign_mark: bool = False,
77
+ allow_nested: bool = False,
78
+ allow_items: bool = False) -> bool:
79
+ return is_assign(string, '&', allow_assign_mark, allow_nested, allow_items)
65
80
 
66
81
 
67
82
  class VariableMatch:
68
83
 
69
- def __init__(self, string, identifier=None, base=None, items=(), start=-1, end=-1):
84
+ def __init__(self, string: str,
85
+ identifier: 'str|None' = None,
86
+ base: 'str|None' = None,
87
+ items: 'tuple[str, ...]' = (),
88
+ start: int = -1,
89
+ end: int = -1):
70
90
  self.string = string
71
91
  self.identifier = identifier
72
92
  self.base = base
@@ -84,66 +104,70 @@ class VariableMatch:
84
104
  )
85
105
 
86
106
  @property
87
- def name(self):
88
- return '%s{%s}' % (self.identifier, self.base) if self else None
107
+ def name(self) -> 'str|None':
108
+ return f'{self.identifier}{{{self.base}}}' if self.identifier else None
89
109
 
90
110
  @property
91
- def before(self):
111
+ def before(self) -> str:
92
112
  return self.string[:self.start] if self.identifier else self.string
93
113
 
94
114
  @property
95
- def match(self):
115
+ def match(self) -> 'str|None':
96
116
  return self.string[self.start:self.end] if self.identifier else None
97
117
 
98
118
  @property
99
- def after(self):
100
- return self.string[self.end:] if self.identifier else None
119
+ def after(self) -> str:
120
+ return self.string[self.end:] if self.identifier else ''
101
121
 
102
- def is_variable(self):
122
+ def is_variable(self) -> bool:
103
123
  return bool(self.identifier
104
124
  and self.base
105
125
  and self.start == 0
106
126
  and self.end == len(self.string))
107
127
 
108
- def is_scalar_variable(self):
128
+ def is_scalar_variable(self) -> bool:
109
129
  return self.identifier == '$' and self.is_variable()
110
130
 
111
- def is_list_variable(self):
131
+ def is_list_variable(self) -> bool:
112
132
  return self.identifier == '@' and self.is_variable()
113
133
 
114
- def is_dict_variable(self):
134
+ def is_dict_variable(self) -> bool:
115
135
  return self.identifier == '&' and self.is_variable()
116
136
 
117
- def is_assign(self,
118
- allow_assign_mark=False, allow_nested=False, allow_items=False):
137
+ def is_assign(self, allow_assign_mark: bool = False, allow_nested: bool = False,
138
+ allow_items: bool = False) -> bool:
119
139
  if allow_assign_mark and self.string.endswith('='):
120
140
  match = search_variable(self.string[:-1].rstrip(), ignore_errors=True)
121
- return match.is_assign(allow_items=allow_items)
141
+ return match.is_assign(allow_nested=allow_nested, allow_items=allow_items)
122
142
  return (self.is_variable()
123
143
  and self.identifier in '$@&'
124
144
  and (allow_items or not self.items)
125
145
  and (allow_nested or not search_variable(self.base)))
126
146
 
127
- def is_scalar_assign(self, allow_assign_mark=False, allow_nested=False):
147
+ def is_scalar_assign(self, allow_assign_mark: bool = False,
148
+ allow_nested: bool = False) -> bool:
128
149
  return self.identifier == '$' and self.is_assign(allow_assign_mark, allow_nested)
129
150
 
130
- def is_list_assign(self, allow_assign_mark=False, allow_nested=False):
151
+ def is_list_assign(self, allow_assign_mark: bool = False,
152
+ allow_nested: bool = False) -> bool:
131
153
  return self.identifier == '@' and self.is_assign(allow_assign_mark, allow_nested)
132
154
 
133
- def is_dict_assign(self, allow_assign_mark=False, allow_nested=False):
155
+ def is_dict_assign(self, allow_assign_mark: bool = False,
156
+ allow_nested: bool = False) -> bool:
134
157
  return self.identifier == '&' and self.is_assign(allow_assign_mark, allow_nested)
135
158
 
136
- def __bool__(self):
159
+ def __bool__(self) -> bool:
137
160
  return self.identifier is not None
138
161
 
139
- def __str__(self):
162
+ def __str__(self) -> str:
140
163
  if not self:
141
164
  return '<no match>'
142
165
  items = ''.join('[%s]' % i for i in self.items) if self.items else ''
143
166
  return '%s{%s}%s' % (self.identifier, self.base, items)
144
167
 
145
168
 
146
- def _search_variable(string, identifiers, ignore_errors=False):
169
+ def _search_variable(string: str, identifiers: Sequence[str],
170
+ ignore_errors: bool = False) -> VariableMatch:
147
171
  start = _find_variable_start(string, identifiers)
148
172
  if start < 0:
149
173
  return VariableMatch(string)
@@ -194,7 +218,7 @@ def _search_variable(string, identifiers, ignore_errors=False):
194
218
  raise VariableError(f"Variable '{incomplete}' was not closed properly.")
195
219
  raise VariableError(f"Variable item '{incomplete}' was not closed properly.")
196
220
 
197
- return match if match else VariableMatch(match)
221
+ return match
198
222
 
199
223
 
200
224
  def _find_variable_start(string, identifiers):
@@ -233,26 +257,27 @@ def unescape_variable_syntax(item):
233
257
  return re.sub(r'(\\+)(?=(.+))', handle_escapes, item)
234
258
 
235
259
 
236
- class VariableIterator:
260
+ class VariableMatches:
237
261
 
238
- def __init__(self, string, identifiers='$@&%', ignore_errors=False):
262
+ def __init__(self, string: str, identifiers: Sequence[str] = '$@&%',
263
+ ignore_errors: bool = False):
239
264
  self.string = string
240
265
  self.identifiers = identifiers
241
266
  self.ignore_errors = ignore_errors
242
267
 
243
- def __iter__(self):
268
+ def __iter__(self) -> Iterator[VariableMatch]:
244
269
  remaining = self.string
245
270
  while True:
246
271
  match = search_variable(remaining, self.identifiers, self.ignore_errors)
247
272
  if not match:
248
273
  break
249
274
  remaining = match.after
250
- yield match.before, match.match, remaining
275
+ yield match
251
276
 
252
- def __len__(self):
277
+ def __len__(self) -> int:
253
278
  return sum(1 for _ in self)
254
279
 
255
- def __bool__(self):
280
+ def __bool__(self) -> bool:
256
281
  try:
257
282
  next(iter(self))
258
283
  except StopIteration: