robotframework 6.1.1__zip → 7.0__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 (307) hide show
  1. {robotframework-6.1.1 → robotframework-7.0}/INSTALL.rst +25 -25
  2. {robotframework-6.1.1 → robotframework-7.0}/PKG-INFO +6 -8
  3. {robotframework-6.1.1 → robotframework-7.0}/README.rst +3 -2
  4. {robotframework-6.1.1 → robotframework-7.0}/setup.py +3 -6
  5. {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/__init__.py +4 -1
  6. {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/deco.py +60 -14
  7. {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/exceptions.py +6 -6
  8. {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/interfaces.py +402 -67
  9. {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/logger.py +27 -20
  10. {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/parsing.py +4 -2
  11. robotframework-7.0/src/robot/api/py.typed +0 -0
  12. {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/gatherfailed.py +2 -2
  13. {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/languages.py +0 -9
  14. {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/settings.py +21 -14
  15. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/common/storage.js +11 -6
  16. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/htmlfilewriter.py +1 -1
  17. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.css +10 -2
  18. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.html +10 -0
  19. robotframework-7.0/src/robot/htmldata/rebot/common.css +362 -0
  20. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/doc_formatting.css +13 -7
  21. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/log.css +51 -10
  22. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/log.html +14 -23
  23. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/model.js +2 -4
  24. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/report.css +83 -19
  25. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/report.html +22 -7
  26. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/testdata.js +10 -3
  27. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/view.js +84 -0
  28. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/template.py +3 -3
  29. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/builder.py +0 -8
  30. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/datatypes.py +9 -10
  31. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/htmlutils.py +4 -7
  32. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/jsonbuilder.py +38 -20
  33. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/model.py +21 -28
  34. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/robotbuilder.py +50 -31
  35. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/standardtypes.py +9 -1
  36. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/xmlbuilder.py +35 -20
  37. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/xmlwriter.py +18 -38
  38. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/BuiltIn.py +255 -205
  39. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Collections.py +384 -240
  40. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/DateTime.py +73 -60
  41. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/OperatingSystem.py +6 -5
  42. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Process.py +26 -27
  43. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Remote.py +40 -36
  44. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/String.py +66 -76
  45. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/XML.py +66 -59
  46. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/__init__.py +2 -2
  47. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/__init__.py +5 -5
  48. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/body.py +44 -13
  49. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/configurer.py +15 -11
  50. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/control.py +226 -84
  51. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/filter.py +31 -25
  52. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/itemlist.py +9 -8
  53. robotframework-7.0/src/robot/model/keyword.py +77 -0
  54. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/message.py +19 -10
  55. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/modelobject.py +25 -7
  56. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/namepatterns.py +3 -25
  57. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/stats.py +9 -15
  58. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/tags.py +1 -1
  59. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/testcase.py +15 -27
  60. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/testsuite.py +17 -26
  61. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/visitor.py +35 -8
  62. robotframework-7.0/src/robot/output/console/dotted.py +90 -0
  63. {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/quiet.py +3 -2
  64. {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/verbose.py +61 -61
  65. {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/debugfile.py +39 -24
  66. {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/filelogger.py +18 -15
  67. {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/librarylogger.py +3 -2
  68. robotframework-7.0/src/robot/output/listeners.py +753 -0
  69. {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/logger.py +216 -80
  70. robotframework-7.0/src/robot/output/loggerapi.py +215 -0
  71. {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/loggerhelper.py +23 -56
  72. robotframework-7.0/src/robot/output/output.py +185 -0
  73. {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/stdoutlogsplitter.py +8 -5
  74. robotframework-7.0/src/robot/output/xmllogger.py +459 -0
  75. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/blocklexers.py +17 -13
  76. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/context.py +12 -2
  77. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/lexer.py +1 -1
  78. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/settings.py +6 -3
  79. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/statementlexers.py +39 -10
  80. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/tokens.py +27 -29
  81. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/model/blocks.py +19 -6
  82. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/model/statements.py +193 -94
  83. robotframework-7.0/src/robot/parsing/model/visitor.py +100 -0
  84. {robotframework-6.1.1 → robotframework-7.0}/src/robot/rebot.py +2 -0
  85. {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/expandkeywordmatcher.py +1 -1
  86. {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jsbuildingcontext.py +8 -6
  87. {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jsmodelbuilders.py +88 -61
  88. {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/logreportwriters.py +16 -10
  89. {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/outputwriter.py +18 -2
  90. {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/resultwriter.py +4 -4
  91. {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/stringcache.py +3 -3
  92. {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/xunitwriter.py +15 -21
  93. {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/__init__.py +3 -2
  94. {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/configurer.py +12 -9
  95. {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/executionresult.py +56 -8
  96. {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/flattenkeywordmatcher.py +48 -9
  97. robotframework-7.0/src/robot/result/keywordremover.py +207 -0
  98. {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/merger.py +1 -1
  99. robotframework-7.0/src/robot/result/model.py +1185 -0
  100. {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/modeldeprecation.py +9 -3
  101. {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/resultbuilder.py +46 -36
  102. {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/xmlelementhandlers.py +83 -43
  103. {robotframework-6.1.1 → robotframework-7.0}/src/robot/run.py +2 -0
  104. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/__init__.py +14 -4
  105. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/__init__.py +2 -1
  106. robotframework-7.0/src/robot/running/arguments/argumentconverter.py +100 -0
  107. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentmapper.py +26 -24
  108. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentparser.py +82 -60
  109. robotframework-7.0/src/robot/running/arguments/argumentresolver.py +158 -0
  110. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentspec.py +83 -116
  111. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentvalidator.py +33 -27
  112. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/customconverters.py +15 -12
  113. robotframework-7.0/src/robot/running/arguments/embedded.py +145 -0
  114. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/typeconverters.py +233 -213
  115. robotframework-7.0/src/robot/running/arguments/typeinfo.py +317 -0
  116. robotframework-7.0/src/robot/running/arguments/typeinfoparser.py +219 -0
  117. robotframework-7.0/src/robot/running/arguments/typevalidator.py +60 -0
  118. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/bodyrunner.py +147 -129
  119. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/builders.py +2 -1
  120. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/parsers.py +10 -11
  121. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/settings.py +9 -17
  122. robotframework-7.0/src/robot/running/builder/transformers.py +535 -0
  123. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/context.py +113 -31
  124. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/dynamicmethods.py +62 -34
  125. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/importer.py +27 -49
  126. robotframework-7.0/src/robot/running/invalidkeyword.py +67 -0
  127. robotframework-7.0/src/robot/running/keywordfinder.py +91 -0
  128. robotframework-7.0/src/robot/running/keywordimplementation.py +164 -0
  129. robotframework-7.0/src/robot/running/librarykeyword.py +392 -0
  130. robotframework-7.0/src/robot/running/librarykeywordrunner.py +250 -0
  131. robotframework-7.0/src/robot/running/libraryscopes.py +115 -0
  132. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/model.py +195 -377
  133. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/namespace.py +124 -137
  134. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/outputcapture.py +20 -12
  135. robotframework-7.0/src/robot/running/resourcemodel.py +448 -0
  136. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/statusreporter.py +16 -13
  137. robotframework-7.0/src/robot/running/suiterunner.py +265 -0
  138. robotframework-7.0/src/robot/running/testlibraries.py +500 -0
  139. robotframework-7.0/src/robot/running/userkeywordrunner.py +260 -0
  140. {robotframework-6.1.1 → robotframework-7.0}/src/robot/testdoc.py +18 -13
  141. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/__init__.py +53 -35
  142. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/connectioncache.py +64 -59
  143. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/dotdict.py +3 -0
  144. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/encodingsniffer.py +1 -1
  145. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/escaping.py +19 -19
  146. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/importer.py +2 -2
  147. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/markupwriters.py +23 -15
  148. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/misc.py +1 -2
  149. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/normalizing.py +9 -24
  150. robotframework-7.0/src/robot/utils/notset.py +33 -0
  151. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/platform.py +15 -5
  152. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotio.py +9 -9
  153. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotpath.py +1 -0
  154. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robottime.py +122 -90
  155. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robottypes.py +21 -31
  156. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/setter.py +0 -5
  157. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/text.py +7 -4
  158. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/unic.py +2 -2
  159. {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/__init__.py +2 -2
  160. {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/assigner.py +17 -19
  161. {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/evaluation.py +20 -17
  162. {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/filesetter.py +80 -80
  163. {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/replacer.py +33 -36
  164. {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/scopes.py +17 -12
  165. {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/search.py +66 -41
  166. {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/store.py +14 -16
  167. robotframework-7.0/src/robot/variables/tablesetter.py +164 -0
  168. {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/variables.py +1 -1
  169. {robotframework-6.1.1 → robotframework-7.0}/src/robot/version.py +1 -1
  170. {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/PKG-INFO +6 -8
  171. {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/SOURCES.txt +10 -8
  172. {robotframework-6.1.1 → robotframework-7.0}/tasks.py +6 -6
  173. robotframework-6.1.1/src/robot/htmldata/rebot/common.css +0 -239
  174. robotframework-6.1.1/src/robot/libraries/Reserved.py +0 -48
  175. robotframework-6.1.1/src/robot/model/keyword.py +0 -173
  176. robotframework-6.1.1/src/robot/output/console/dotted.py +0 -90
  177. robotframework-6.1.1/src/robot/output/listenerarguments.py +0 -165
  178. robotframework-6.1.1/src/robot/output/listenermethods.py +0 -113
  179. robotframework-6.1.1/src/robot/output/listeners.py +0 -174
  180. robotframework-6.1.1/src/robot/output/output.py +0 -95
  181. robotframework-6.1.1/src/robot/output/xmllogger.py +0 -354
  182. robotframework-6.1.1/src/robot/parsing/model/visitor.py +0 -67
  183. robotframework-6.1.1/src/robot/result/keywordremover.py +0 -183
  184. robotframework-6.1.1/src/robot/result/model.py +0 -957
  185. robotframework-6.1.1/src/robot/running/arguments/argumentconverter.py +0 -79
  186. robotframework-6.1.1/src/robot/running/arguments/argumentresolver.py +0 -131
  187. robotframework-6.1.1/src/robot/running/arguments/embedded.py +0 -146
  188. robotframework-6.1.1/src/robot/running/arguments/typevalidator.py +0 -56
  189. robotframework-6.1.1/src/robot/running/builder/transformers.py +0 -642
  190. robotframework-6.1.1/src/robot/running/handlers.py +0 -321
  191. robotframework-6.1.1/src/robot/running/handlerstore.py +0 -66
  192. robotframework-6.1.1/src/robot/running/librarykeywordrunner.py +0 -238
  193. robotframework-6.1.1/src/robot/running/libraryscopes.py +0 -97
  194. robotframework-6.1.1/src/robot/running/modelcombiner.py +0 -32
  195. robotframework-6.1.1/src/robot/running/suiterunner.py +0 -248
  196. robotframework-6.1.1/src/robot/running/testlibraries.py +0 -423
  197. robotframework-6.1.1/src/robot/running/usererrorhandler.py +0 -75
  198. robotframework-6.1.1/src/robot/running/userkeyword.py +0 -111
  199. robotframework-6.1.1/src/robot/running/userkeywordrunner.py +0 -274
  200. robotframework-6.1.1/src/robot/variables/tablesetter.py +0 -156
  201. {robotframework-6.1.1 → robotframework-7.0}/AUTHORS.rst +0 -0
  202. {robotframework-6.1.1 → robotframework-7.0}/BUILD.rst +0 -0
  203. {robotframework-6.1.1 → robotframework-7.0}/CONTRIBUTING.rst +0 -0
  204. {robotframework-6.1.1 → robotframework-7.0}/COPYRIGHT.txt +0 -0
  205. {robotframework-6.1.1 → robotframework-7.0}/LICENSE.txt +0 -0
  206. {robotframework-6.1.1 → robotframework-7.0}/MANIFEST.in +0 -0
  207. {robotframework-6.1.1 → robotframework-7.0}/setup.cfg +0 -0
  208. {robotframework-6.1.1 → robotframework-7.0}/src/robot/__init__.py +0 -0
  209. {robotframework-6.1.1 → robotframework-7.0}/src/robot/__main__.py +0 -0
  210. {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/__init__.py +0 -0
  211. {robotframework-6.1.1 → robotframework-7.0}/src/robot/errors.py +0 -0
  212. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/__init__.py +0 -0
  213. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/common/__init__.py +0 -0
  214. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/common/js_disabled.css +0 -0
  215. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/jsonwriter.py +0 -0
  216. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/__init__.py +0 -0
  217. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
  218. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.min.js +0 -0
  219. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
  220. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
  221. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
  222. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/__init__.py +0 -0
  223. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/doc_formatting.css +0 -0
  224. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/print.css +0 -0
  225. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/pygments.css +0 -0
  226. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/__init__.py +0 -0
  227. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/fileloading.js +0 -0
  228. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/log.js +0 -0
  229. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/print.css +0 -0
  230. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/util.js +0 -0
  231. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/testdoc/__init__.py +0 -0
  232. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.css +0 -0
  233. {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.html +0 -0
  234. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdoc.py +0 -0
  235. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/__init__.py +0 -0
  236. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/consoleviewer.py +0 -0
  237. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/htmlwriter.py +0 -0
  238. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/jsonwriter.py +0 -0
  239. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/output.py +0 -0
  240. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/writer.py +0 -0
  241. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Dialogs.py +0 -0
  242. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Easter.py +0 -0
  243. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Screenshot.py +0 -0
  244. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Telnet.py +0 -0
  245. {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/dialogs_py.py +0 -0
  246. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/fixture.py +0 -0
  247. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/metadata.py +0 -0
  248. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/modifier.py +0 -0
  249. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/statistics.py +0 -0
  250. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/suitestatistics.py +0 -0
  251. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/tagsetter.py +0 -0
  252. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/tagstatistics.py +0 -0
  253. {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/totalstatistics.py +0 -0
  254. {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/__init__.py +0 -0
  255. {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/__init__.py +0 -0
  256. {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/highlighting.py +0 -0
  257. {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/pyloggingconf.py +0 -0
  258. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/__init__.py +0 -0
  259. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/__init__.py +0 -0
  260. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/tokenizer.py +0 -0
  261. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/model/__init__.py +0 -0
  262. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/__init__.py +0 -0
  263. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/blockparsers.py +0 -0
  264. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/fileparser.py +0 -0
  265. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/parser.py +0 -0
  266. {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/suitestructure.py +0 -0
  267. {robotframework-6.1.1 → robotframework-7.0}/src/robot/pythonpathsetter.py +0 -0
  268. {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/__init__.py +0 -0
  269. {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jsexecutionresult.py +0 -0
  270. {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jswriter.py +0 -0
  271. {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/executionerrors.py +0 -0
  272. {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/messagefilter.py +0 -0
  273. {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/suiteteardownfailed.py +0 -0
  274. {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/visitor.py +0 -0
  275. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/__init__.py +0 -0
  276. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/randomizer.py +0 -0
  277. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/runkwregister.py +0 -0
  278. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/signalhandler.py +0 -0
  279. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/status.py +0 -0
  280. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/timeouts/__init__.py +0 -0
  281. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/timeouts/posix.py +0 -0
  282. {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/timeouts/windows.py +0 -0
  283. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/application.py +0 -0
  284. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/argumentparser.py +0 -0
  285. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/asserts.py +0 -0
  286. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/charwidth.py +0 -0
  287. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/compress.py +0 -0
  288. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/encoding.py +0 -0
  289. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/error.py +0 -0
  290. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/etreewrapper.py +0 -0
  291. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/filereader.py +0 -0
  292. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/frange.py +0 -0
  293. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/htmlformatters.py +0 -0
  294. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/markuputils.py +0 -0
  295. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/match.py +0 -0
  296. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/recommendations.py +0 -0
  297. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/restreader.py +0 -0
  298. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotenv.py +0 -0
  299. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotinspect.py +0 -0
  300. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/sortable.py +0 -0
  301. {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/typehints.py +0 -0
  302. {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/finders.py +0 -0
  303. {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/notfound.py +0 -0
  304. {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/resolvable.py +0 -0
  305. {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/dependency_links.txt +0 -0
  306. {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/entry_points.txt +0 -0
  307. {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/top_level.txt +0 -0
@@ -34,8 +34,7 @@ else:
34
34
  from robot.api import logger
35
35
  from robot.api.deco import keyword
36
36
  from robot.libraries.BuiltIn import BuiltIn
37
- from robot.utils import (asserts, ET, ETSource, is_bytes, is_falsy, is_string,
38
- is_truthy, plural_or_not as s)
37
+ from robot.utils import asserts, ET, ETSource, plural_or_not as s
39
38
  from robot.version import get_version
40
39
 
41
40
 
@@ -53,7 +52,7 @@ class XML:
53
52
  The library has the following main usages:
54
53
 
55
54
  - Parsing an XML file, or a string containing XML, into an XML element
56
- structure and finding certain elements from it for for further analysis
55
+ structure and finding certain elements from it for further analysis
57
56
  (e.g. `Parse XML` and `Get Element` keywords).
58
57
  - Getting text or attributes of elements
59
58
  (e.g. `Get Element Text` and `Get Element Attribute`).
@@ -75,10 +74,10 @@ class XML:
75
74
  children and their children. Possible comments and processing instructions
76
75
  in the source XML are removed.
77
76
 
78
- XML is not validated during parsing even if has a schema defined. How
77
+ XML is not validated during parsing even if it has a schema defined. How
79
78
  possible doctype elements are handled otherwise depends on the used XML
80
79
  module and on the platform. The standard ElementTree strips doctypes
81
- altogether but when `using lxml` they are preserved when XML is saved.
80
+ altogether, but when `using lxml` they are preserved when XML is saved.
82
81
 
83
82
  The element structure returned by `Parse XML`, as well as elements
84
83
  returned by keywords such as `Get Element`, can be used as the ``source``
@@ -95,8 +94,6 @@ class XML:
95
94
  escaped by doubling it (``\\\\``). Using the built-in variable ``${/}``
96
95
  naturally works too.
97
96
 
98
- Note: Support for XML as bytes is new in Robot Framework 3.2.
99
-
100
97
  = Using lxml =
101
98
 
102
99
  By default, this library uses Python's standard
@@ -168,7 +165,7 @@ class XML:
168
165
 
169
166
  If lxml support is enabled when `importing` the library, the whole
170
167
  [http://www.w3.org/TR/xpath/|xpath 1.0 standard] is supported.
171
- That includes everything listed below but also lot of other useful
168
+ That includes everything listed below but also a lot of other useful
172
169
  constructs.
173
170
 
174
171
  == Tag names ==
@@ -304,7 +301,7 @@ class XML:
304
301
  = Handling XML namespaces =
305
302
 
306
303
  ElementTree and lxml handle possible namespaces in XML documents by adding
307
- the namespace URI to tag names in so called Clark Notation. That is
304
+ the namespace URI to tag names in so-called Clark Notation. That is
308
305
  inconvenient especially with xpaths, and by default this library strips
309
306
  those namespaces away and moves them to ``xmlns`` attribute instead. That
310
307
  can be avoided by passing ``keep_clark_notation`` argument to `Parse XML`
@@ -433,8 +430,6 @@ class XML:
433
430
  | `Parse XML` | ${XML} | keep_clark_notation=${EMPTY} | # Empty string is false. |
434
431
  | `Parse XML` | ${XML} | keep_clark_notation=${FALSE} | # Python ``False`` is false. |
435
432
 
436
- Considering ``OFF`` and ``0`` false is new in Robot Framework 3.1.
437
-
438
433
  == Pattern matching ==
439
434
 
440
435
  Some keywords, for example `Elements Should Match`, support so called
@@ -450,9 +445,6 @@ class XML:
450
445
  Unlike with glob patterns normally, path separator characters ``/`` and
451
446
  ``\\`` and the newline character ``\\n`` are matches by the above
452
447
  wildcards.
453
-
454
- Support for brackets like ``[abc]`` and ``[!a-z]`` is new in
455
- Robot Framework 3.1
456
448
  """
457
449
  ROBOT_LIBRARY_SCOPE = 'GLOBAL'
458
450
  ROBOT_LIBRARY_VERSION = get_version()
@@ -470,7 +462,6 @@ class XML:
470
462
  If lxml mode is enabled but the module is not installed, this library
471
463
  emits a warning and reverts back to using the standard ElementTree.
472
464
  """
473
- use_lxml = is_truthy(use_lxml)
474
465
  if use_lxml and lxml_etree:
475
466
  self.etree = lxml_etree
476
467
  self.modern_etree = True
@@ -523,8 +514,8 @@ class XML:
523
514
  strip = (lxml_etree.Comment, lxml_etree.ProcessingInstruction)
524
515
  lxml_etree.strip_elements(tree, *strip, **dict(with_tail=False))
525
516
  root = tree.getroot()
526
- if not is_truthy(keep_clark_notation):
527
- self._ns_stripper.strip(root, preserve=is_falsy(strip_namespaces))
517
+ if not keep_clark_notation:
518
+ self._ns_stripper.strip(root, preserve=not strip_namespaces)
528
519
  return root
529
520
 
530
521
  def get_element(self, source, xpath='.'):
@@ -565,10 +556,10 @@ class XML:
565
556
 
566
557
  def _wrong_number_of_matches(self, count, xpath):
567
558
  if not count:
568
- return "No element matching '%s' found." % xpath
559
+ return f"No element matching '{xpath}' found."
569
560
  if count == 1:
570
- return "One element matching '%s' found." % xpath
571
- return "Multiple elements (%d) matching '%s' found." % (count, xpath)
561
+ return f"One element matching '{xpath}' found."
562
+ return f"Multiple elements ({count}) matching '{xpath}' found."
572
563
 
573
564
  def get_elements(self, source, xpath):
574
565
  """Returns a list of elements in the ``source`` matching the ``xpath``.
@@ -619,7 +610,7 @@ class XML:
619
610
  See also `Element Should Exist` and `Element Should Not Exist`.
620
611
  """
621
612
  count = len(self.get_elements(source, xpath))
622
- logger.info("%d element%s matched '%s'." % (count, s(count), xpath))
613
+ logger.info(f"{count} element{s(count)} matched '{xpath}'.")
623
614
  return count
624
615
 
625
616
  def element_should_exist(self, source, xpath='.', message=None):
@@ -685,7 +676,7 @@ class XML:
685
676
  """
686
677
  element = self.get_element(source, xpath)
687
678
  text = ''.join(self._yield_texts(element))
688
- if is_truthy(normalize_whitespace):
679
+ if normalize_whitespace:
689
680
  text = self._normalize_whitespace(text)
690
681
  return text
691
682
 
@@ -854,7 +845,7 @@ class XML:
854
845
  """
855
846
  attr = self.get_element_attribute(source, name, xpath)
856
847
  if attr is None:
857
- raise AssertionError("Attribute '%s' does not exist." % name)
848
+ raise AssertionError(f"Attribute '{name}' does not exist.")
858
849
  should_match(attr, pattern, message, values=False)
859
850
 
860
851
  def element_should_not_have_attribute(self, source, name, xpath='.', message=None):
@@ -876,11 +867,11 @@ class XML:
876
867
  """
877
868
  attr = self.get_element_attribute(source, name, xpath)
878
869
  if attr is not None:
879
- raise AssertionError(message or "Attribute '%s' exists and "
880
- "has value '%s'." % (name, attr))
870
+ raise AssertionError(message or
871
+ f"Attribute '{name}' exists and has value '{attr}'.")
881
872
 
882
873
  def elements_should_be_equal(self, source, expected, exclude_children=False,
883
- normalize_whitespace=False):
874
+ normalize_whitespace=False, sort_children=False):
884
875
  """Verifies that the given ``source`` element is equal to ``expected``.
885
876
 
886
877
  Both ``source`` and ``expected`` can be given as a path to an XML file,
@@ -890,12 +881,14 @@ class XML:
890
881
 
891
882
  The keyword passes if the ``source`` element and ``expected`` element
892
883
  are equal. This includes testing the tag names, texts, and attributes
893
- of the elements. By default also child elements are verified the same
884
+ of the elements. By default, also child elements are verified the same
894
885
  way, but this can be disabled by setting ``exclude_children`` to a
895
- true value (see `Boolean arguments`).
886
+ true value (see `Boolean arguments`). Child elements are expected to
887
+ be in the same order, but that can be changed by giving ``sort_children``
888
+ a true value. Notice that elements are sorted solely based on tag names.
896
889
 
897
890
  All texts inside the given elements are verified, but possible text
898
- outside them is not. By default texts must match exactly, but setting
891
+ outside them is not. By default, texts must match exactly, but setting
899
892
  ``normalize_whitespace`` to a true value makes text verification
900
893
  independent on newlines, tabs, and the amount of spaces. For more
901
894
  details about handling text see `Get Element Text` keyword and
@@ -915,12 +908,14 @@ class XML:
915
908
  the ``.`` at the end that is the `tail` text of the ``<i>`` element.
916
909
 
917
910
  See also `Elements Should Match`.
911
+
912
+ ``sort_children`` is new in Robot Framework 7.0.
918
913
  """
919
- self._compare_elements(source, expected, should_be_equal,
920
- exclude_children, normalize_whitespace)
914
+ self._compare_elements(source, expected, should_be_equal, exclude_children,
915
+ sort_children, normalize_whitespace)
921
916
 
922
917
  def elements_should_match(self, source, expected, exclude_children=False,
923
- normalize_whitespace=False):
918
+ normalize_whitespace=False, sort_children=False):
924
919
  """Verifies that the given ``source`` element matches ``expected``.
925
920
 
926
921
  This keyword works exactly like `Elements Should Be Equal` except that
@@ -937,16 +932,22 @@ class XML:
937
932
 
938
933
  See `Elements Should Be Equal` for more examples.
939
934
  """
940
- self._compare_elements(source, expected, should_match,
941
- exclude_children, normalize_whitespace)
935
+ self._compare_elements(source, expected, should_match, exclude_children,
936
+ sort_children, normalize_whitespace)
942
937
 
943
938
  def _compare_elements(self, source, expected, comparator, exclude_children,
944
- normalize_whitespace):
945
- normalizer = self._normalize_whitespace \
946
- if is_truthy(normalize_whitespace) else None
947
- comparator = ElementComparator(comparator, normalizer, exclude_children)
939
+ sort_children, normalize_whitespace):
940
+ normalizer = self._normalize_whitespace if normalize_whitespace else None
941
+ sorter = self._sort_children if sort_children else None
942
+ comparator = ElementComparator(comparator, normalizer, sorter, exclude_children)
948
943
  comparator.compare(self.get_element(source), self.get_element(expected))
949
944
 
945
+ def _sort_children(self, element):
946
+ tails = [child.tail for child in element]
947
+ element[:] = sorted(element, key=lambda child: child.tag)
948
+ for child, tail in zip(element, tails):
949
+ child.tail = tail
950
+
950
951
  def set_element_tag(self, source, tag, xpath='.'):
951
952
  """Sets the tag of the specified element.
952
953
 
@@ -1219,7 +1220,7 @@ class XML:
1219
1220
 
1220
1221
  def _remove_element(self, root, element, remove_tail=False):
1221
1222
  parent = self._find_parent(root, element)
1222
- if not is_truthy(remove_tail):
1223
+ if not remove_tail:
1223
1224
  self._preserve_tail(element, parent)
1224
1225
  parent.remove(element)
1225
1226
 
@@ -1269,7 +1270,7 @@ class XML:
1269
1270
  element = self.get_element(source, xpath)
1270
1271
  tail = element.tail
1271
1272
  element.clear()
1272
- if not is_truthy(clear_tail):
1273
+ if not clear_tail:
1273
1274
  element.tail = tail
1274
1275
  return source
1275
1276
 
@@ -1279,7 +1280,7 @@ class XML:
1279
1280
  The element to copy is specified using ``source`` and ``xpath``. They
1280
1281
  have exactly the same semantics as with `Get Element` keyword.
1281
1282
 
1282
- If the copy or the original element is modified afterwards, the changes
1283
+ If the copy or the original element is modified afterward, the changes
1283
1284
  have no effect on the other.
1284
1285
 
1285
1286
  Examples using ``${XML}`` structure from `Example`:
@@ -1308,6 +1309,8 @@ class XML:
1308
1309
  See also `Log Element` and `Save XML`.
1309
1310
  """
1310
1311
  source = self.get_element(source, xpath)
1312
+ if self.lxml_etree:
1313
+ source = self._ns_stripper.unstrip(source)
1311
1314
  string = self.etree.tostring(source, encoding='UTF-8').decode('UTF-8')
1312
1315
  string = re.sub(r'^<\?xml .*\?>', '', string).strip()
1313
1316
  if encoding:
@@ -1365,8 +1368,7 @@ class XML:
1365
1368
  output.write(self.etree.tostring(tree, **config))
1366
1369
  else:
1367
1370
  tree.write(output, **config)
1368
- logger.info('XML saved to <a href="file://%s">%s</a>.' % (path, path),
1369
- html=True)
1371
+ logger.info(f'XML saved to <a href="file://{path}">{path}</a>.', html=True)
1370
1372
 
1371
1373
  def evaluate_xpath(self, source, expression, context='.'):
1372
1374
  """Evaluates the given xpath expression and returns results.
@@ -1420,7 +1422,7 @@ class NameSpaceStripper:
1420
1422
  elem = copy.deepcopy(elem)
1421
1423
  ns = elem.attrib.pop('xmlns', current_ns)
1422
1424
  if ns:
1423
- elem.tag = '{%s}%s' % (ns, elem.tag)
1425
+ elem.tag = f'{{{ns}}}{elem.tag}'
1424
1426
  for child in elem:
1425
1427
  self.unstrip(child, ns, copied=True)
1426
1428
  return elem
@@ -1460,10 +1462,12 @@ class ElementFinder:
1460
1462
 
1461
1463
  class ElementComparator:
1462
1464
 
1463
- def __init__(self, comparator, normalizer=None, exclude_children=False):
1464
- self._comparator = comparator
1465
- self._normalizer = normalizer or (lambda text: text)
1466
- self._exclude_children = is_truthy(exclude_children)
1465
+ def __init__(self, comparator, normalizer=None, child_sorter=None,
1466
+ exclude_children=False):
1467
+ self.comparator = comparator
1468
+ self.normalizer = normalizer or (lambda text: text)
1469
+ self.child_sorter = child_sorter
1470
+ self.exclude_children = exclude_children
1467
1471
 
1468
1472
  def compare(self, actual, expected, location=None):
1469
1473
  if not location:
@@ -1473,7 +1477,7 @@ class ElementComparator:
1473
1477
  self._compare_texts(actual, expected, location)
1474
1478
  if location.is_not_root:
1475
1479
  self._compare_tails(actual, expected, location)
1476
- if not self._exclude_children:
1480
+ if not self.exclude_children:
1477
1481
  self._compare_children(actual, expected, location)
1478
1482
 
1479
1483
  def _compare_tags(self, actual, expected, location):
@@ -1482,9 +1486,9 @@ class ElementComparator:
1482
1486
 
1483
1487
  def _compare(self, actual, expected, message, location, comparator=None):
1484
1488
  if location.is_not_root:
1485
- message = "%s at '%s'" % (message, location.path)
1489
+ message = f"{message} at '{location.path}'"
1486
1490
  if not comparator:
1487
- comparator = self._comparator
1491
+ comparator = self.comparator
1488
1492
  comparator(actual, expected, message)
1489
1493
 
1490
1494
  def _compare_attributes(self, actual, expected, location):
@@ -1492,14 +1496,14 @@ class ElementComparator:
1492
1496
  'Different attribute names', location, should_be_equal)
1493
1497
  for key in actual.attrib:
1494
1498
  self._compare(actual.attrib[key], expected.attrib[key],
1495
- "Different value for attribute '%s'" % key, location)
1499
+ f"Different value for attribute '{key}'", location)
1496
1500
 
1497
1501
  def _compare_texts(self, actual, expected, location):
1498
1502
  self._compare(self._text(actual.text), self._text(expected.text),
1499
1503
  'Different text', location)
1500
1504
 
1501
1505
  def _text(self, text):
1502
- return self._normalizer(text or '')
1506
+ return self.normalizer(text or '')
1503
1507
 
1504
1508
  def _compare_tails(self, actual, expected, location):
1505
1509
  self._compare(self._text(actual.tail), self._text(expected.tail),
@@ -1508,6 +1512,9 @@ class ElementComparator:
1508
1512
  def _compare_children(self, actual, expected, location):
1509
1513
  self._compare(len(actual), len(expected), 'Different number of child elements',
1510
1514
  location, should_be_equal)
1515
+ if self.child_sorter:
1516
+ self.child_sorter(actual)
1517
+ self.child_sorter(expected)
1511
1518
  for act, exp in zip(actual, expected):
1512
1519
  self.compare(act, exp, location.child(act.tag))
1513
1520
 
@@ -1517,12 +1524,12 @@ class Location:
1517
1524
  def __init__(self, path, is_root=True):
1518
1525
  self.path = path
1519
1526
  self.is_not_root = not is_root
1520
- self._children = {}
1527
+ self.children = {}
1521
1528
 
1522
1529
  def child(self, tag):
1523
- if tag not in self._children:
1524
- self._children[tag] = 1
1530
+ if tag not in self.children:
1531
+ self.children[tag] = 1
1525
1532
  else:
1526
- self._children[tag] += 1
1527
- tag += '[%d]' % self._children[tag]
1528
- return Location('%s/%s' % (self.path, tag), is_root=False)
1533
+ self.children[tag] += 1
1534
+ tag += f'[{self.children[tag]}]'
1535
+ return Location(f'{self.path}/{tag}', is_root=False)
@@ -27,5 +27,5 @@ the http://robotframework.org web site.
27
27
  """
28
28
 
29
29
  STDLIBS = frozenset(('BuiltIn', 'Collections', 'DateTime', 'Dialogs', 'Easter',
30
- 'OperatingSystem', 'Process', 'Remote', 'Reserved',
31
- 'Screenshot', 'String', 'Telnet', 'XML'))
30
+ 'OperatingSystem', 'Process', 'Remote', 'Screenshot',
31
+ 'String', 'Telnet', 'XML'))
@@ -25,16 +25,16 @@ elsewhere.
25
25
  This package is considered stable.
26
26
  """
27
27
 
28
- from .body import BaseBody, Body, BodyItem, BaseBranches
28
+ from .body import BaseBody, Body, BodyItem, BaseBranches, BaseIterations
29
29
  from .configurer import SuiteConfigurer
30
- from .control import Break, Continue, Error, For, If, IfBranch, Return, Try, TryBranch, While
30
+ from .control import (Break, Continue, Error, For, ForIteration, If, IfBranch,
31
+ Return, Try, TryBranch, Var, While, WhileIteration)
31
32
  from .fixture import create_fixture
32
33
  from .itemlist import ItemList
33
- from .keyword import Keyword, Keywords
34
- from .message import Message, Messages
34
+ from .keyword import Arguments, Keyword
35
+ from .message import Message, MessageLevel, Messages
35
36
  from .modelobject import DataDict, ModelObject
36
37
  from .modifier import ModelModifier
37
- from .namepatterns import SuiteNamePatterns, TestNamePatterns
38
38
  from .statistics import Statistics
39
39
  from .tags import Tags, TagPattern, TagPatterns
40
40
  from .testcase import TestCase, TestCases
@@ -23,10 +23,9 @@ from .itemlist import ItemList
23
23
  from .modelobject import DataDict, full_name, ModelObject
24
24
 
25
25
  if TYPE_CHECKING:
26
- from robot.result.model import ForIteration, WhileIteration
27
- from robot.running.model import UserKeyword, ResourceFile
28
- from .control import (Break, Continue, Error, For, If, IfBranch, Return,
29
- Try, TryBranch, While)
26
+ from robot.running.model import ResourceFile, UserKeyword
27
+ from .control import (Break, Continue, Error, For, ForIteration, If, IfBranch,
28
+ Return, Try, TryBranch, Var, While, WhileIteration)
30
29
  from .keyword import Keyword
31
30
  from .message import Message
32
31
  from .testcase import TestCase
@@ -35,19 +34,21 @@ if TYPE_CHECKING:
35
34
 
36
35
  BodyItemParent = Union['TestSuite', 'TestCase', 'UserKeyword', 'For', 'ForIteration',
37
36
  'If', 'IfBranch', 'Try', 'TryBranch', 'While', 'WhileIteration',
38
- 'Keyword', 'Return', 'Continue', 'Break', 'Error', None]
37
+ 'Keyword', 'Var', 'Return', 'Continue', 'Break', 'Error', None]
39
38
  BI = TypeVar('BI', bound='BodyItem')
40
39
  KW = TypeVar('KW', bound='Keyword')
41
40
  F = TypeVar('F', bound='For')
42
41
  W = TypeVar('W', bound='While')
43
42
  I = TypeVar('I', bound='If')
44
43
  T = TypeVar('T', bound='Try')
44
+ V = TypeVar('V', bound='Var')
45
45
  R = TypeVar('R', bound='Return')
46
46
  C = TypeVar('C', bound='Continue')
47
47
  B = TypeVar('B', bound='Break')
48
48
  M = TypeVar('M', bound='Message')
49
49
  E = TypeVar('E', bound='Error')
50
50
  IT = TypeVar('IT', bound='IfBranch|TryBranch')
51
+ FW = TypeVar('FW', bound='ForIteration|WhileIteration')
51
52
 
52
53
 
53
54
  class BodyItem(ModelObject):
@@ -65,11 +66,13 @@ class BodyItem(ModelObject):
65
66
  EXCEPT = 'EXCEPT'
66
67
  FINALLY = 'FINALLY'
67
68
  WHILE = 'WHILE'
69
+ VAR = 'VAR'
68
70
  RETURN = 'RETURN'
69
71
  CONTINUE = 'CONTINUE'
70
72
  BREAK = 'BREAK'
71
73
  ERROR = 'ERROR'
72
74
  MESSAGE = 'MESSAGE'
75
+ KEYWORD_TYPES = (KEYWORD, SETUP, TEARDOWN)
73
76
  type = None
74
77
  __slots__ = ['parent']
75
78
 
@@ -111,7 +114,7 @@ class BodyItem(ModelObject):
111
114
  raise NotImplementedError
112
115
 
113
116
 
114
- class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, R, C, B, M, E]):
117
+ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, V, R, C, B, M, E]):
115
118
  """Base class for Body and Branches objects."""
116
119
  __slots__ = []
117
120
  # Set using 'BaseBody.register' when these classes are created.
@@ -120,6 +123,7 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, R, C, B, M, E]):
120
123
  while_class: Type[W] = KnownAtRuntime
121
124
  if_class: Type[I] = KnownAtRuntime
122
125
  try_class: Type[T] = KnownAtRuntime
126
+ var_class: Type[V] = KnownAtRuntime
123
127
  return_class: Type[R] = KnownAtRuntime
124
128
  continue_class: Type[C] = KnownAtRuntime
125
129
  break_class: Type[B] = KnownAtRuntime
@@ -132,7 +136,7 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, R, C, B, M, E]):
132
136
 
133
137
  def _item_from_dict(self, data: DataDict) -> BodyItem:
134
138
  item_type = data.get('type', None)
135
- if not item_type:
139
+ if item_type is None:
136
140
  item_class = self.keyword_class
137
141
  elif item_type == BodyItem.IF_ELSE_ROOT:
138
142
  item_class = self.if_class
@@ -159,7 +163,7 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, R, C, B, M, E]):
159
163
  f"Use item specific methods like 'create_keyword' instead."
160
164
  )
161
165
 
162
- def _create(self, cls: 'Type[BI]', name: str, args: 'tuple[Any]',
166
+ def _create(self, cls: 'Type[BI]', name: str, args: 'tuple[Any, ...]',
163
167
  kwargs: 'dict[str, Any]') -> BI:
164
168
  if cls is KnownAtRuntime:
165
169
  raise TypeError(f"'{full_name(self)}' object does not support '{name}'.")
@@ -185,6 +189,10 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, R, C, B, M, E]):
185
189
  def create_while(self, *args, **kwargs) -> while_class:
186
190
  return self._create(self.while_class, 'create_while', args, kwargs)
187
191
 
192
+ @copy_signature(var_class)
193
+ def create_var(self, *args, **kwargs) -> var_class:
194
+ return self._create(self.var_class, 'create_var', args, kwargs)
195
+
188
196
  @copy_signature(return_class)
189
197
  def create_return(self, *args, **kwargs) -> return_class:
190
198
  return self._create(self.return_class, 'create_return', args, kwargs)
@@ -267,8 +275,8 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, R, C, B, M, E]):
267
275
  return steps
268
276
 
269
277
 
270
- class Body(BaseBody['Keyword', 'For', 'While', 'If', 'Try', 'Return', 'Continue',
271
- 'Break', 'Message', 'Error']):
278
+ class Body(BaseBody['Keyword', 'For', 'While', 'If', 'Try', 'Var', 'Return',
279
+ 'Continue', 'Break', 'Message', 'Error']):
272
280
  """A list-like object representing a body of a test, keyword, etc.
273
281
 
274
282
  Body contains the keywords and other structures such as FOR loops.
@@ -276,19 +284,19 @@ class Body(BaseBody['Keyword', 'For', 'While', 'If', 'Try', 'Return', 'Continue'
276
284
  pass
277
285
 
278
286
 
287
+ # BaseBranches cannot extend Generic[IT] directly with BaseBody[...].
279
288
  class BranchType(Generic[IT]):
280
- """Class that wrapps `Generic` as python doesn't allow multple generic inheritance"""
281
289
  pass
282
290
 
283
291
 
284
- class BaseBranches(BaseBody[KW, F, W, I, T, R, C, B, M, E], BranchType[IT]):
292
+ class BaseBranches(BaseBody[KW, F, W, I, T, V, R, C, B, M, E], BranchType[IT]):
285
293
  """A list-like object representing IF and TRY branches."""
286
294
  __slots__ = ['branch_class']
287
295
  branch_type: Type[IT] = KnownAtRuntime
288
296
 
289
297
  def __init__(self, branch_class: Type[IT],
290
298
  parent: BodyItemParent = None,
291
- items: 'Iterable[BodyItem|DataDict]' = ()):
299
+ items: 'Iterable[IT|DataDict]' = ()):
292
300
  self.branch_class = branch_class
293
301
  super().__init__(parent, items)
294
302
 
@@ -298,3 +306,26 @@ class BaseBranches(BaseBody[KW, F, W, I, T, R, C, B, M, E], BranchType[IT]):
298
306
  @copy_signature(branch_type)
299
307
  def create_branch(self, *args, **kwargs) -> IT:
300
308
  return self._create(self.branch_class, 'create_branch', args, kwargs)
309
+
310
+
311
+ # BaseIterations cannot extend Generic[IT] directly with BaseBody[...].
312
+ class IterationType(Generic[FW]):
313
+ pass
314
+
315
+
316
+ class BaseIterations(BaseBody[KW, F, W, I, T, V, R, C, B, M, E], IterationType[FW]):
317
+ __slots__ = ['iteration_class']
318
+ iteration_type: Type[FW] = KnownAtRuntime
319
+
320
+ def __init__(self, iteration_class: Type[FW],
321
+ parent: BodyItemParent = None,
322
+ items: 'Iterable[FW|DataDict]' = ()):
323
+ self.iteration_class = iteration_class
324
+ super().__init__(parent, items)
325
+
326
+ def _item_from_dict(self, data: DataDict) -> FW:
327
+ return self.iteration_class.from_dict(data)
328
+
329
+ @copy_signature(iteration_type)
330
+ def create_iteration(self, *args, **kwargs) -> FW:
331
+ return self._create(self.iteration_class, 'iteration_class', args, kwargs)
@@ -66,22 +66,26 @@ class SuiteConfigurer(SuiteVisitor):
66
66
  parts = [{False: 'tests', True: 'tasks', None: 'tests or tasks'}[rpa],
67
67
  self._get_test_selector_msgs(),
68
68
  self._get_suite_selector_msg()]
69
- raise DataError("Suite '%s' contains no %s."
70
- % (name, ' '.join(p for p in parts if p)))
69
+ raise DataError(f"Suite '{name}' contains no "
70
+ f"{' '.join(p for p in parts if p)}.")
71
71
 
72
72
  def _get_test_selector_msgs(self):
73
73
  parts = []
74
- for explanation, selector in [('matching tags', self.include_tags),
75
- ('not matching tags', self.exclude_tags),
76
- ('matching name', self.include_tests)]:
77
- if selector:
78
- parts.append(self._format_selector_msg(explanation, selector))
79
- return seq2str(parts, quote='')
74
+ for separator, explanation, selectors in [
75
+ (None, 'matching name', self.include_tests),
76
+ ('or', 'matching tags', self.include_tags),
77
+ ('and', 'not matching tags', self.exclude_tags)
78
+ ]:
79
+ if selectors:
80
+ if parts:
81
+ parts.append(separator)
82
+ parts.append(self._format_selector_msg(explanation, selectors))
83
+ return ' '.join(parts)
80
84
 
81
- def _format_selector_msg(self, explanation, selector):
82
- if len(selector) == 1 and explanation[-1] == 's':
85
+ def _format_selector_msg(self, explanation, selectors):
86
+ if len(selectors) == 1 and explanation[-1] == 's':
83
87
  explanation = explanation[:-1]
84
- return '%s %s' % (explanation, seq2str(selector, lastsep=' or '))
88
+ return f"{explanation} {seq2str(selectors, lastsep=' or ')}"
85
89
 
86
90
  def _get_suite_selector_msg(self):
87
91
  if not self.include_suites: