robotframework 6.1rc1__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.1rc1 → robotframework-7.0}/INSTALL.rst +25 -25
  2. {robotframework-6.1rc1 → robotframework-7.0}/PKG-INFO +6 -8
  3. {robotframework-6.1rc1 → robotframework-7.0}/README.rst +3 -2
  4. {robotframework-6.1rc1 → robotframework-7.0}/setup.py +3 -6
  5. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/__init__.py +4 -1
  6. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/deco.py +60 -14
  7. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/exceptions.py +6 -6
  8. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/interfaces.py +403 -68
  9. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/logger.py +27 -20
  10. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/parsing.py +4 -2
  11. robotframework-7.0/src/robot/api/py.typed +0 -0
  12. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/gatherfailed.py +2 -2
  13. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/languages.py +61 -25
  14. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/settings.py +21 -14
  15. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/common/storage.js +11 -6
  16. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/htmlfilewriter.py +1 -1
  17. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.css +10 -2
  18. {robotframework-6.1rc1 → 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.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/doc_formatting.css +13 -7
  21. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/log.css +51 -10
  22. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/log.html +14 -23
  23. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/model.js +2 -4
  24. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/report.css +83 -19
  25. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/report.html +22 -7
  26. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/testdata.js +10 -3
  27. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/view.js +84 -0
  28. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/template.py +3 -3
  29. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/builder.py +0 -8
  30. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/datatypes.py +9 -10
  31. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/htmlutils.py +4 -7
  32. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/jsonbuilder.py +38 -20
  33. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/model.py +21 -28
  34. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/robotbuilder.py +50 -31
  35. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/standardtypes.py +9 -1
  36. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/xmlbuilder.py +35 -20
  37. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/xmlwriter.py +18 -38
  38. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/BuiltIn.py +255 -205
  39. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Collections.py +384 -240
  40. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/DateTime.py +73 -60
  41. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/OperatingSystem.py +6 -5
  42. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Process.py +26 -27
  43. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Remote.py +40 -36
  44. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/String.py +66 -76
  45. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/XML.py +66 -59
  46. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/__init__.py +2 -2
  47. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/dialogs_py.py +14 -2
  48. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/__init__.py +5 -5
  49. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/body.py +44 -13
  50. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/configurer.py +19 -15
  51. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/control.py +230 -88
  52. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/filter.py +31 -25
  53. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/itemlist.py +9 -8
  54. robotframework-7.0/src/robot/model/keyword.py +77 -0
  55. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/message.py +19 -10
  56. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/modelobject.py +27 -15
  57. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/modifier.py +1 -1
  58. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/namepatterns.py +3 -25
  59. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/stats.py +9 -15
  60. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/tags.py +1 -1
  61. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/testcase.py +15 -27
  62. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/testsuite.py +44 -28
  63. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/visitor.py +35 -8
  64. robotframework-7.0/src/robot/output/console/dotted.py +90 -0
  65. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/quiet.py +3 -2
  66. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/verbose.py +61 -61
  67. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/debugfile.py +39 -24
  68. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/filelogger.py +18 -15
  69. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/librarylogger.py +3 -2
  70. robotframework-7.0/src/robot/output/listeners.py +753 -0
  71. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/logger.py +216 -80
  72. robotframework-7.0/src/robot/output/loggerapi.py +215 -0
  73. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/loggerhelper.py +23 -56
  74. robotframework-7.0/src/robot/output/output.py +185 -0
  75. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/stdoutlogsplitter.py +8 -5
  76. robotframework-7.0/src/robot/output/xmllogger.py +459 -0
  77. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/blocklexers.py +17 -13
  78. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/context.py +12 -2
  79. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/lexer.py +1 -1
  80. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/settings.py +6 -3
  81. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/statementlexers.py +39 -10
  82. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/tokens.py +27 -29
  83. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/model/blocks.py +19 -6
  84. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/model/statements.py +193 -94
  85. robotframework-7.0/src/robot/parsing/model/visitor.py +100 -0
  86. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/rebot.py +2 -0
  87. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/expandkeywordmatcher.py +1 -1
  88. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jsbuildingcontext.py +8 -6
  89. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jsmodelbuilders.py +88 -61
  90. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/logreportwriters.py +16 -10
  91. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/outputwriter.py +18 -2
  92. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/resultwriter.py +4 -4
  93. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/stringcache.py +3 -3
  94. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/xunitwriter.py +15 -21
  95. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/__init__.py +3 -2
  96. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/configurer.py +12 -9
  97. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/executionresult.py +56 -8
  98. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/flattenkeywordmatcher.py +48 -9
  99. robotframework-7.0/src/robot/result/keywordremover.py +207 -0
  100. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/merger.py +1 -1
  101. robotframework-7.0/src/robot/result/model.py +1185 -0
  102. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/modeldeprecation.py +9 -3
  103. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/resultbuilder.py +46 -36
  104. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/xmlelementhandlers.py +83 -43
  105. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/run.py +3 -1
  106. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/__init__.py +14 -4
  107. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/__init__.py +2 -1
  108. robotframework-7.0/src/robot/running/arguments/argumentconverter.py +100 -0
  109. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentmapper.py +26 -24
  110. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentparser.py +85 -61
  111. robotframework-7.0/src/robot/running/arguments/argumentresolver.py +158 -0
  112. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentspec.py +83 -116
  113. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentvalidator.py +33 -27
  114. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/customconverters.py +15 -12
  115. robotframework-7.0/src/robot/running/arguments/embedded.py +145 -0
  116. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/typeconverters.py +268 -220
  117. robotframework-7.0/src/robot/running/arguments/typeinfo.py +317 -0
  118. robotframework-7.0/src/robot/running/arguments/typeinfoparser.py +219 -0
  119. robotframework-7.0/src/robot/running/arguments/typevalidator.py +60 -0
  120. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/bodyrunner.py +147 -129
  121. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/builders.py +17 -26
  122. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/parsers.py +17 -11
  123. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/settings.py +9 -17
  124. robotframework-7.0/src/robot/running/builder/transformers.py +535 -0
  125. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/context.py +113 -31
  126. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/dynamicmethods.py +62 -34
  127. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/importer.py +27 -49
  128. robotframework-7.0/src/robot/running/invalidkeyword.py +67 -0
  129. robotframework-7.0/src/robot/running/keywordfinder.py +91 -0
  130. robotframework-7.0/src/robot/running/keywordimplementation.py +164 -0
  131. robotframework-7.0/src/robot/running/librarykeyword.py +392 -0
  132. robotframework-7.0/src/robot/running/librarykeywordrunner.py +250 -0
  133. robotframework-7.0/src/robot/running/libraryscopes.py +115 -0
  134. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/model.py +198 -337
  135. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/namespace.py +124 -137
  136. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/outputcapture.py +20 -12
  137. robotframework-7.0/src/robot/running/resourcemodel.py +448 -0
  138. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/statusreporter.py +16 -13
  139. robotframework-7.0/src/robot/running/suiterunner.py +265 -0
  140. robotframework-7.0/src/robot/running/testlibraries.py +500 -0
  141. robotframework-7.0/src/robot/running/userkeywordrunner.py +260 -0
  142. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/testdoc.py +18 -13
  143. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/__init__.py +53 -35
  144. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/connectioncache.py +64 -59
  145. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/dotdict.py +3 -0
  146. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/encodingsniffer.py +9 -4
  147. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/escaping.py +19 -19
  148. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/importer.py +2 -2
  149. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/markupwriters.py +23 -15
  150. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/misc.py +1 -2
  151. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/normalizing.py +9 -24
  152. robotframework-7.0/src/robot/utils/notset.py +33 -0
  153. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/platform.py +15 -5
  154. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotio.py +9 -9
  155. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotpath.py +1 -0
  156. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robottime.py +122 -90
  157. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robottypes.py +21 -31
  158. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/setter.py +0 -5
  159. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/text.py +7 -4
  160. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/unic.py +2 -2
  161. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/__init__.py +2 -2
  162. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/assigner.py +17 -19
  163. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/evaluation.py +20 -17
  164. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/filesetter.py +80 -80
  165. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/replacer.py +33 -36
  166. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/scopes.py +17 -12
  167. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/search.py +66 -41
  168. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/store.py +14 -16
  169. robotframework-7.0/src/robot/variables/tablesetter.py +164 -0
  170. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/variables.py +1 -1
  171. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/version.py +1 -1
  172. {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/PKG-INFO +6 -8
  173. {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/SOURCES.txt +10 -8
  174. {robotframework-6.1rc1 → robotframework-7.0}/tasks.py +6 -6
  175. robotframework-6.1rc1/src/robot/htmldata/rebot/common.css +0 -239
  176. robotframework-6.1rc1/src/robot/libraries/Reserved.py +0 -48
  177. robotframework-6.1rc1/src/robot/model/keyword.py +0 -173
  178. robotframework-6.1rc1/src/robot/output/console/dotted.py +0 -90
  179. robotframework-6.1rc1/src/robot/output/listenerarguments.py +0 -165
  180. robotframework-6.1rc1/src/robot/output/listenermethods.py +0 -113
  181. robotframework-6.1rc1/src/robot/output/listeners.py +0 -174
  182. robotframework-6.1rc1/src/robot/output/output.py +0 -95
  183. robotframework-6.1rc1/src/robot/output/xmllogger.py +0 -354
  184. robotframework-6.1rc1/src/robot/parsing/model/visitor.py +0 -67
  185. robotframework-6.1rc1/src/robot/result/keywordremover.py +0 -183
  186. robotframework-6.1rc1/src/robot/result/model.py +0 -957
  187. robotframework-6.1rc1/src/robot/running/arguments/argumentconverter.py +0 -79
  188. robotframework-6.1rc1/src/robot/running/arguments/argumentresolver.py +0 -131
  189. robotframework-6.1rc1/src/robot/running/arguments/embedded.py +0 -146
  190. robotframework-6.1rc1/src/robot/running/arguments/typevalidator.py +0 -56
  191. robotframework-6.1rc1/src/robot/running/builder/transformers.py +0 -642
  192. robotframework-6.1rc1/src/robot/running/handlers.py +0 -321
  193. robotframework-6.1rc1/src/robot/running/handlerstore.py +0 -66
  194. robotframework-6.1rc1/src/robot/running/librarykeywordrunner.py +0 -238
  195. robotframework-6.1rc1/src/robot/running/libraryscopes.py +0 -97
  196. robotframework-6.1rc1/src/robot/running/modelcombiner.py +0 -32
  197. robotframework-6.1rc1/src/robot/running/suiterunner.py +0 -249
  198. robotframework-6.1rc1/src/robot/running/testlibraries.py +0 -420
  199. robotframework-6.1rc1/src/robot/running/usererrorhandler.py +0 -75
  200. robotframework-6.1rc1/src/robot/running/userkeyword.py +0 -111
  201. robotframework-6.1rc1/src/robot/running/userkeywordrunner.py +0 -274
  202. robotframework-6.1rc1/src/robot/variables/tablesetter.py +0 -156
  203. {robotframework-6.1rc1 → robotframework-7.0}/AUTHORS.rst +0 -0
  204. {robotframework-6.1rc1 → robotframework-7.0}/BUILD.rst +0 -0
  205. {robotframework-6.1rc1 → robotframework-7.0}/CONTRIBUTING.rst +0 -0
  206. {robotframework-6.1rc1 → robotframework-7.0}/COPYRIGHT.txt +0 -0
  207. {robotframework-6.1rc1 → robotframework-7.0}/LICENSE.txt +0 -0
  208. {robotframework-6.1rc1 → robotframework-7.0}/MANIFEST.in +0 -0
  209. {robotframework-6.1rc1 → robotframework-7.0}/setup.cfg +0 -0
  210. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/__init__.py +0 -0
  211. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/__main__.py +0 -0
  212. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/__init__.py +0 -0
  213. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/errors.py +0 -0
  214. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/__init__.py +0 -0
  215. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/common/__init__.py +0 -0
  216. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/common/js_disabled.css +0 -0
  217. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/jsonwriter.py +0 -0
  218. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/__init__.py +0 -0
  219. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
  220. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.min.js +0 -0
  221. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
  222. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
  223. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
  224. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/__init__.py +0 -0
  225. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/doc_formatting.css +0 -0
  226. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/print.css +0 -0
  227. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/pygments.css +0 -0
  228. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/__init__.py +0 -0
  229. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/fileloading.js +0 -0
  230. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/log.js +0 -0
  231. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/print.css +0 -0
  232. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/util.js +0 -0
  233. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/testdoc/__init__.py +0 -0
  234. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.css +0 -0
  235. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.html +0 -0
  236. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdoc.py +0 -0
  237. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/__init__.py +0 -0
  238. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/consoleviewer.py +0 -0
  239. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/htmlwriter.py +0 -0
  240. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/jsonwriter.py +0 -0
  241. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/output.py +0 -0
  242. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/writer.py +0 -0
  243. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Dialogs.py +0 -0
  244. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Easter.py +0 -0
  245. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Screenshot.py +0 -0
  246. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Telnet.py +0 -0
  247. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/fixture.py +0 -0
  248. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/metadata.py +0 -0
  249. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/statistics.py +0 -0
  250. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/suitestatistics.py +0 -0
  251. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/tagsetter.py +0 -0
  252. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/tagstatistics.py +0 -0
  253. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/totalstatistics.py +0 -0
  254. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/__init__.py +0 -0
  255. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/__init__.py +0 -0
  256. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/highlighting.py +0 -0
  257. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/pyloggingconf.py +0 -0
  258. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/__init__.py +0 -0
  259. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/__init__.py +0 -0
  260. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/tokenizer.py +0 -0
  261. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/model/__init__.py +0 -0
  262. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/__init__.py +0 -0
  263. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/blockparsers.py +0 -0
  264. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/fileparser.py +0 -0
  265. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/parser.py +0 -0
  266. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/suitestructure.py +0 -0
  267. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/pythonpathsetter.py +0 -0
  268. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/__init__.py +0 -0
  269. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jsexecutionresult.py +0 -0
  270. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jswriter.py +0 -0
  271. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/executionerrors.py +0 -0
  272. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/messagefilter.py +0 -0
  273. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/suiteteardownfailed.py +0 -0
  274. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/visitor.py +0 -0
  275. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/__init__.py +0 -0
  276. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/randomizer.py +0 -0
  277. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/runkwregister.py +0 -0
  278. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/signalhandler.py +0 -0
  279. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/status.py +0 -0
  280. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/timeouts/__init__.py +0 -0
  281. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/timeouts/posix.py +0 -0
  282. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/timeouts/windows.py +0 -0
  283. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/application.py +0 -0
  284. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/argumentparser.py +0 -0
  285. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/asserts.py +0 -0
  286. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/charwidth.py +0 -0
  287. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/compress.py +0 -0
  288. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/encoding.py +0 -0
  289. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/error.py +0 -0
  290. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/etreewrapper.py +0 -0
  291. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/filereader.py +0 -0
  292. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/frange.py +0 -0
  293. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/htmlformatters.py +0 -0
  294. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/markuputils.py +0 -0
  295. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/match.py +0 -0
  296. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/recommendations.py +0 -0
  297. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/restreader.py +0 -0
  298. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotenv.py +0 -0
  299. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotinspect.py +0 -0
  300. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/sortable.py +0 -0
  301. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/typehints.py +0 -0
  302. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/finders.py +0 -0
  303. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/notfound.py +0 -0
  304. {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/resolvable.py +0 -0
  305. {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/dependency_links.txt +0 -0
  306. {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/entry_points.txt +0 -0
  307. {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/top_level.txt +0 -0
@@ -15,101 +15,140 @@
15
15
 
16
16
  import sys
17
17
  from enum import Enum
18
- from typing import Union, Tuple
18
+ from typing import Any, Callable, Iterator, Mapping, Sequence
19
19
 
20
- from robot.utils import has_args, is_union, safe_str, setter, type_repr
20
+ from robot.utils import NOT_SET, safe_str, setter, SetterAwareType
21
21
 
22
22
  from .argumentconverter import ArgumentConverter
23
23
  from .argumentmapper import ArgumentMapper
24
24
  from .argumentresolver import ArgumentResolver
25
+ from .typeinfo import TypeInfo
25
26
  from .typevalidator import TypeValidator
26
27
 
27
28
 
28
- class ArgumentSpec:
29
-
30
- def __init__(self, name=None, type='Keyword', positional_only=None,
31
- positional_or_named=None, var_positional=None, named_only=None,
32
- var_named=None, defaults=None, types=None):
29
+ class ArgumentSpec(metaclass=SetterAwareType):
30
+ __slots__ = ['_name', 'type', 'positional_only', 'positional_or_named',
31
+ 'var_positional', 'named_only', 'var_named', 'embedded', 'defaults']
32
+
33
+ def __init__(self, name: 'str|Callable[[], str]|None' = None,
34
+ type: str = 'Keyword',
35
+ positional_only: Sequence[str] = (),
36
+ positional_or_named: Sequence[str] = (),
37
+ var_positional: 'str|None' = None,
38
+ named_only: Sequence[str] = (),
39
+ var_named: 'str|None' = None,
40
+ defaults: 'Mapping[str, Any]|None' = None,
41
+ embedded: Sequence[str] = (),
42
+ types: 'Mapping[str, TypeInfo]|None' = None,
43
+ return_type: 'TypeInfo|None' = None):
33
44
  self.name = name
34
45
  self.type = type
35
- self.positional_only = positional_only or []
36
- self.positional_or_named = positional_or_named or []
46
+ self.positional_only = tuple(positional_only)
47
+ self.positional_or_named = tuple(positional_or_named)
37
48
  self.var_positional = var_positional
38
- self.named_only = named_only or []
49
+ self.named_only = tuple(named_only)
39
50
  self.var_named = var_named
51
+ self.embedded = tuple(embedded)
40
52
  self.defaults = defaults or {}
41
53
  self.types = types
54
+ self.return_type = return_type
55
+
56
+ @property
57
+ def name(self) -> 'str|None':
58
+ return self._name if not callable(self._name) else self._name()
59
+
60
+ @name.setter
61
+ def name(self, name: 'str|Callable[[], str]|None'):
62
+ self._name = name
42
63
 
43
64
  @setter
44
- def types(self, types):
65
+ def types(self, types) -> 'dict[str, TypeInfo]|None':
45
66
  return TypeValidator(self).validate(types)
46
67
 
68
+ @setter
69
+ def return_type(self, hint) -> 'TypeInfo|None':
70
+ if hint in (None, type(None)):
71
+ return None
72
+ if isinstance(hint, TypeInfo):
73
+ return hint
74
+ return TypeInfo.from_type_hint(hint)
75
+
47
76
  @property
48
- def positional(self):
77
+ def positional(self) -> 'tuple[str, ...]':
49
78
  return self.positional_only + self.positional_or_named
50
79
 
51
80
  @property
52
- def minargs(self):
81
+ def named(self) -> 'tuple[str, ...]':
82
+ return self.named_only + self.positional_or_named
83
+
84
+ @property
85
+ def minargs(self) -> int:
53
86
  return len([arg for arg in self.positional if arg not in self.defaults])
54
87
 
55
88
  @property
56
- def maxargs(self):
89
+ def maxargs(self) -> int:
57
90
  return len(self.positional) if not self.var_positional else sys.maxsize
58
91
 
59
92
  @property
60
- def argument_names(self):
61
- return (self.positional_only +
62
- self.positional_or_named +
63
- ([self.var_positional] if self.var_positional else []) +
64
- self.named_only +
65
- ([self.var_named] if self.var_named else []))
93
+ def argument_names(self) -> 'tuple[str, ...]':
94
+ var_positional = (self.var_positional,) if self.var_positional else ()
95
+ var_named = (self.var_named,) if self.var_named else ()
96
+ return (self.positional_only + self.positional_or_named + var_positional +
97
+ self.named_only + var_named)
66
98
 
67
99
  def resolve(self, arguments, variables=None, converters=None,
68
- resolve_named=True, resolve_variables_until=None,
69
- dict_to_kwargs=False, languages=None):
70
- resolver = ArgumentResolver(self, resolve_named,
71
- resolve_variables_until, dict_to_kwargs)
100
+ resolve_named=True, resolve_args_until=None,
101
+ dict_to_kwargs=False, languages=None) -> 'tuple[list, list]':
102
+ resolver = ArgumentResolver(self, resolve_named, resolve_args_until,
103
+ dict_to_kwargs)
72
104
  positional, named = resolver.resolve(arguments, variables)
73
105
  return self.convert(positional, named, converters, dry_run=not variables,
74
106
  languages=languages)
75
107
 
76
- def convert(self, positional, named, converters=None, dry_run=False, languages=None):
108
+ def convert(self, positional, named, converters=None, dry_run=False,
109
+ languages=None) -> 'tuple[list, list]':
77
110
  if self.types or self.defaults:
78
111
  converter = ArgumentConverter(self, converters, dry_run, languages)
79
112
  positional, named = converter.convert(positional, named)
80
113
  return positional, named
81
114
 
82
- def map(self, positional, named, replace_defaults=True):
115
+ def map(self, positional, named, replace_defaults=True) -> 'tuple[list, list]':
83
116
  mapper = ArgumentMapper(self)
84
117
  return mapper.map(positional, named, replace_defaults)
85
118
 
86
- def __iter__(self):
87
- notset = ArgInfo.NOTSET
119
+ def copy(self) -> 'ArgumentSpec':
120
+ types = dict(self.types) if self.types is not None else None
121
+ return type(self)(self.name, self.type, self.positional_only,
122
+ self.positional_or_named, self.var_positional,
123
+ self.named_only, self.var_named, dict(self.defaults),
124
+ self.embedded, types, self.return_type)
125
+
126
+ def __iter__(self) -> Iterator['ArgInfo']:
88
127
  get_type = (self.types or {}).get
89
128
  get_default = self.defaults.get
90
129
  for arg in self.positional_only:
91
130
  yield ArgInfo(ArgInfo.POSITIONAL_ONLY, arg,
92
- get_type(arg, notset), get_default(arg, notset))
131
+ get_type(arg), get_default(arg, NOT_SET))
93
132
  if self.positional_only:
94
133
  yield ArgInfo(ArgInfo.POSITIONAL_ONLY_MARKER)
95
134
  for arg in self.positional_or_named:
96
135
  yield ArgInfo(ArgInfo.POSITIONAL_OR_NAMED, arg,
97
- get_type(arg, notset), get_default(arg, notset))
136
+ get_type(arg), get_default(arg, NOT_SET))
98
137
  if self.var_positional:
99
138
  yield ArgInfo(ArgInfo.VAR_POSITIONAL, self.var_positional,
100
- get_type(self.var_positional, notset))
139
+ get_type(self.var_positional))
101
140
  elif self.named_only:
102
141
  yield ArgInfo(ArgInfo.NAMED_ONLY_MARKER)
103
142
  for arg in self.named_only:
104
143
  yield ArgInfo(ArgInfo.NAMED_ONLY, arg,
105
- get_type(arg, notset), get_default(arg, notset))
144
+ get_type(arg), get_default(arg, NOT_SET))
106
145
  if self.var_named:
107
146
  yield ArgInfo(ArgInfo.VAR_NAMED, self.var_named,
108
- get_type(self.var_named, notset))
147
+ get_type(self.var_named))
109
148
 
110
149
  def __bool__(self):
111
150
  return any([self.positional_only, self.positional_or_named, self.var_positional,
112
- self.named_only, self.var_named])
151
+ self.named_only, self.var_named, self.return_type])
113
152
 
114
153
  def __str__(self):
115
154
  return ', '.join(str(arg) for arg in self)
@@ -117,7 +156,6 @@ class ArgumentSpec:
117
156
 
118
157
  class ArgInfo:
119
158
  """Contains argument information. Only used by Libdoc."""
120
- NOTSET = object()
121
159
  POSITIONAL_ONLY = 'POSITIONAL_ONLY'
122
160
  POSITIONAL_ONLY_MARKER = 'POSITIONAL_ONLY_MARKER'
123
161
  POSITIONAL_OR_NAMED = 'POSITIONAL_OR_NAMED'
@@ -126,32 +164,26 @@ class ArgInfo:
126
164
  NAMED_ONLY = 'NAMED_ONLY'
127
165
  VAR_NAMED = 'VAR_NAMED'
128
166
 
129
- def __init__(self, kind, name='', type=NOTSET, default=NOTSET):
167
+ def __init__(self, kind: str,
168
+ name: str = '',
169
+ type: 'TypeInfo|None' = None,
170
+ default: Any = NOT_SET):
130
171
  self.kind = kind
131
172
  self.name = name
132
- self.type = TypeInfo.from_type(type)
173
+ self.type = type or TypeInfo()
133
174
  self.default = default
134
175
 
135
176
  @property
136
- def required(self):
177
+ def required(self) -> bool:
137
178
  if self.kind in (self.POSITIONAL_ONLY,
138
179
  self.POSITIONAL_OR_NAMED,
139
180
  self.NAMED_ONLY):
140
- return self.default is self.NOTSET
181
+ return self.default is NOT_SET
141
182
  return False
142
183
 
143
184
  @property
144
- def types_reprs(self):
145
- """Deprecated. Use :attr:`type` instead."""
146
- if not self.type:
147
- return []
148
- if self.type.is_union:
149
- return [str(t) for t in self.type.nested]
150
- return [str(self.type)]
151
-
152
- @property
153
- def default_repr(self):
154
- if self.default is self.NOTSET:
185
+ def default_repr(self) -> 'str|None':
186
+ if self.default is NOT_SET:
155
187
  return None
156
188
  if isinstance(self.default, Enum):
157
189
  return self.default.name
@@ -172,71 +204,6 @@ class ArgInfo:
172
204
  default_sep = ' = '
173
205
  else:
174
206
  default_sep = '='
175
- if self.default is not self.NOTSET:
207
+ if self.default is not NOT_SET:
176
208
  ret = f'{ret}{default_sep}{self.default_repr}'
177
209
  return ret
178
-
179
-
180
- Type = Union[type, str, tuple, type(ArgInfo.NOTSET)]
181
-
182
-
183
- class TypeInfo:
184
- """Represents argument type. Only used by Libdoc.
185
-
186
- With unions and parametrized types, :attr:`nested` contains nested types.
187
- """
188
- NOTSET = ArgInfo.NOTSET
189
-
190
- def __init__(self, type: Type = NOTSET, nested: Tuple['TypeInfo'] = ()):
191
- self.type = type
192
- self.nested = nested
193
-
194
- @property
195
- def name(self) -> str:
196
- if isinstance(self.type, str):
197
- return self.type
198
- return type_repr(self.type, nested=False)
199
-
200
- @property
201
- def is_union(self) -> bool:
202
- if isinstance(self.type, str):
203
- return self.type == 'Union'
204
- return is_union(self.type, allow_tuple=True)
205
-
206
- @classmethod
207
- def from_type(cls, type: Type) -> 'TypeInfo':
208
- if type is cls.NOTSET:
209
- return cls()
210
- if isinstance(type, dict):
211
- return cls.from_dict(type)
212
- if isinstance(type, (tuple, list)):
213
- if not type:
214
- return cls()
215
- if len(type) == 1:
216
- return cls(type[0])
217
- nested = tuple(cls.from_type(t) for t in type)
218
- return cls('Union', nested)
219
- if has_args(type):
220
- nested = tuple(cls.from_type(t) for t in type.__args__)
221
- return cls(type, nested)
222
- return cls(type)
223
-
224
- @classmethod
225
- def from_dict(cls, data: dict) -> 'TypeInfo':
226
- if not data:
227
- return cls()
228
- nested = tuple(cls.from_dict(n) for n in data['nested'])
229
- return cls(data['name'], nested)
230
-
231
- def __str__(self):
232
- if self.is_union:
233
- return ' | '.join(str(n) for n in self.nested)
234
- if isinstance(self.type, str):
235
- if self.nested:
236
- nested = ', '.join(str(n) for n in self.nested)
237
- return f'{self.name}[{nested}]'
238
- return self.name
239
- return type_repr(self.type)
240
-
241
- def __bool__(self):
242
- return self.type is not self.NOTSET
@@ -13,44 +13,48 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
+ from typing import TYPE_CHECKING
17
+
16
18
  from robot.errors import DataError
17
- from robot.utils import plural_or_not, seq2str
19
+ from robot.utils import plural_or_not as s, seq2str
18
20
  from robot.variables import is_dict_variable, is_list_variable
19
21
 
22
+ if TYPE_CHECKING:
23
+ from .argumentspec import ArgumentSpec
24
+
20
25
 
21
26
  class ArgumentValidator:
22
27
 
23
- def __init__(self, argspec):
24
- """:type argspec: :py:class:`robot.running.arguments.ArgumentSpec`"""
25
- self._argspec = argspec
28
+ def __init__(self, arg_spec: 'ArgumentSpec'):
29
+ self.spec = arg_spec
26
30
 
27
31
  def validate(self, positional, named, dryrun=False):
28
32
  named = set(name for name, value in named)
29
33
  if dryrun and (any(is_list_variable(arg) for arg in positional) or
30
34
  any(is_dict_variable(arg) for arg in named)):
31
35
  return
32
- self._validate_no_multiple_values(positional, named, self._argspec)
33
- self._validate_no_positional_only_as_named(named, self._argspec)
34
- self._validate_positional_limits(positional, named, self._argspec)
35
- self._validate_no_mandatory_missing(positional, named, self._argspec)
36
- self._validate_no_named_only_missing(named, self._argspec)
37
- self._validate_no_extra_named(named, self._argspec)
36
+ self._validate_no_multiple_values(positional, named, self.spec)
37
+ self._validate_no_positional_only_as_named(named, self.spec)
38
+ self._validate_positional_limits(positional, named, self.spec)
39
+ self._validate_no_mandatory_missing(positional, named, self.spec)
40
+ self._validate_no_named_only_missing(named, self.spec)
41
+ self._validate_no_extra_named(named, self.spec)
38
42
 
39
43
  def _validate_no_multiple_values(self, positional, named, spec):
40
- for name in spec.positional[:len(positional)]:
44
+ for name in spec.positional[:len(positional)-len(spec.embedded)]:
41
45
  if name in named and name not in spec.positional_only:
42
- self._raise_error("got multiple values for argument '%s'" % name)
46
+ self._raise_error(f"got multiple values for argument '{name}'")
43
47
 
44
48
  def _raise_error(self, message):
45
- raise DataError("%s '%s' %s." % (self._argspec.type.capitalize(),
46
- self._argspec.name, message))
49
+ name = f"'{self.spec.name}' " if self.spec.name else ''
50
+ raise DataError(f"{self.spec.type.capitalize()} {name}{message}.")
47
51
 
48
52
  def _validate_no_positional_only_as_named(self, named, spec):
49
53
  if not spec.var_named:
50
54
  for name in named:
51
55
  if name in spec.positional_only:
52
- self._raise_error("does not accept argument '%s' as named "
53
- "argument" % name)
56
+ self._raise_error(f"does not accept argument '{name}' as named "
57
+ f"argument")
54
58
 
55
59
  def _validate_positional_limits(self, positional, named, spec):
56
60
  count = len(positional) + self._named_positionals(named, spec)
@@ -61,32 +65,34 @@ class ArgumentValidator:
61
65
  return sum(1 for n in named if n in spec.positional_or_named)
62
66
 
63
67
  def _raise_wrong_count(self, count, spec):
64
- minend = plural_or_not(spec.minargs)
65
- if spec.minargs == spec.maxargs:
66
- expected = '%d argument%s' % (spec.minargs, minend)
68
+ embedded = len(spec.embedded)
69
+ minargs = spec.minargs - embedded
70
+ maxargs = spec.maxargs - embedded
71
+ if minargs == maxargs:
72
+ expected = f'{minargs} argument{s(minargs)}'
67
73
  elif not spec.var_positional:
68
- expected = '%d to %d arguments' % (spec.minargs, spec.maxargs)
74
+ expected = f'{minargs} to {maxargs} arguments'
69
75
  else:
70
- expected = 'at least %d argument%s' % (spec.minargs, minend)
76
+ expected = f'at least {minargs} argument{s(minargs)}'
71
77
  if spec.var_named or spec.named_only:
72
78
  expected = expected.replace('argument', 'non-named argument')
73
- self._raise_error("expected %s, got %d" % (expected, count))
79
+ self._raise_error(f"expected {expected}, got {count - embedded}")
74
80
 
75
81
  def _validate_no_mandatory_missing(self, positional, named, spec):
76
82
  for name in spec.positional[len(positional):]:
77
83
  if name not in spec.defaults and name not in named:
78
- self._raise_error("missing value for argument '%s'" % name)
84
+ self._raise_error(f"missing value for argument '{name}'")
79
85
 
80
86
  def _validate_no_named_only_missing(self, named, spec):
81
87
  defined = set(named) | set(spec.defaults)
82
88
  missing = [arg for arg in spec.named_only if arg not in defined]
83
89
  if missing:
84
- self._raise_error("missing named-only argument%s %s"
85
- % (plural_or_not(missing), seq2str(sorted(missing))))
90
+ self._raise_error(f"missing named-only argument{s(missing)} "
91
+ f"{seq2str(sorted(missing))}")
86
92
 
87
93
  def _validate_no_extra_named(self, named, spec):
88
94
  if not spec.var_named:
89
95
  extra = set(named) - set(spec.positional_or_named) - set(spec.named_only)
90
96
  if extra:
91
- self._raise_error("got unexpected named argument%s %s"
92
- % (plural_or_not(extra), seq2str(sorted(extra))))
97
+ self._raise_error(f"got unexpected named argument{s(extra)} "
98
+ f"{seq2str(sorted(extra))}")
@@ -13,9 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- from robot.utils import getdoc, is_union, seq2str, type_name
17
-
18
- from .argumentparser import PythonArgumentParser
16
+ from robot.utils import getdoc, seq2str, type_name
19
17
 
20
18
 
21
19
  class CustomArgumentConverters:
@@ -24,12 +22,14 @@ class CustomArgumentConverters:
24
22
  self.converters = converters
25
23
 
26
24
  @classmethod
27
- def from_dict(cls, converters, library):
25
+ def from_dict(cls, converters, library=None):
28
26
  valid = []
29
27
  for type_, conv in converters.items():
30
28
  try:
31
29
  info = ConverterInfo.for_converter(type_, conv, library)
32
30
  except TypeError as err:
31
+ if library is None:
32
+ raise
33
33
  library.report_error(str(err))
34
34
  else:
35
35
  valid.append(info)
@@ -78,20 +78,23 @@ class ConverterInfo:
78
78
  raise TypeError(f'Custom converters must be callable, converter for '
79
79
  f'{type_name(type_)} is {type_name(converter)}.')
80
80
  spec = cls._get_arg_spec(converter)
81
- arg_type = spec.types.get(spec.positional and spec.positional[0] or spec.var_positional)
82
- if arg_type is None:
81
+ type_info = spec.types.get(spec.positional[0] if spec.positional
82
+ else spec.var_positional)
83
+ if type_info is None:
83
84
  accepts = ()
84
- elif is_union(arg_type):
85
- accepts = arg_type.__args__
86
- elif hasattr(arg_type, '__origin__'):
87
- accepts = (arg_type.__origin__,)
85
+ elif type_info.is_union:
86
+ accepts = type_info.nested
88
87
  else:
89
- accepts = (arg_type,)
88
+ accepts = (type_info,)
89
+ accepts = tuple(info.type for info in accepts)
90
90
  pass_library = spec.minargs == 2 or spec.var_positional
91
91
  return cls(type_, converter, accepts, library if pass_library else None)
92
92
 
93
93
  @classmethod
94
94
  def _get_arg_spec(cls, converter):
95
+ # Avoid cyclic import. Yuck.
96
+ from .argumentparser import PythonArgumentParser
97
+
95
98
  spec = PythonArgumentParser(type='Converter').parse(converter)
96
99
  if spec.minargs > 2:
97
100
  required = seq2str([a for a in spec.positional if a not in spec.defaults])
@@ -109,5 +112,5 @@ class ConverterInfo:
109
112
  def convert(self, value):
110
113
  if not self.library:
111
114
  return self.converter(value)
112
- return self.converter(value, self.library.get_instance())
115
+ return self.converter(value, self.library.instance)
113
116
 
@@ -0,0 +1,145 @@
1
+ # Copyright 2008-2015 Nokia Networks
2
+ # Copyright 2016- Robot Framework Foundation
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import re
17
+ from typing import Any, Mapping, Sequence
18
+
19
+ from robot.errors import DataError
20
+ from robot.utils import get_error_message
21
+ from robot.variables import VariableMatches
22
+
23
+ from ..context import EXECUTION_CONTEXTS
24
+
25
+
26
+ class EmbeddedArguments:
27
+
28
+ def __init__(self, name: re.Pattern,
29
+ args: Sequence[str] = (),
30
+ custom_patterns: 'Mapping[str, str]|None' = None):
31
+ self.name = name
32
+ self.args = tuple(args)
33
+ self.custom_patterns = custom_patterns or None
34
+
35
+ @classmethod
36
+ def from_name(cls, name: str) -> 'EmbeddedArguments|None':
37
+ return EmbeddedArgumentParser().parse(name) if '${' in name else None
38
+
39
+ def match(self, name: str) -> 're.Match|None':
40
+ return self.name.fullmatch(name)
41
+
42
+ def map(self, args: Sequence[Any]) -> 'list[tuple[str, Any]]':
43
+ self.validate(args)
44
+ return list(zip(self.args, args))
45
+
46
+ def validate(self, args: Sequence[Any]):
47
+ """Validate that embedded args match custom regexps.
48
+
49
+ Initial validation is done already when matching keywords, but this
50
+ validation makes sure arguments match also if they are given as variables.
51
+
52
+ Currently, argument not matching only causes a deprecation warning, but
53
+ that will be changed to ``ValueError`` in RF 8.0:
54
+ https://github.com/robotframework/robotframework/issues/4069
55
+ """
56
+ if not self.custom_patterns:
57
+ return
58
+ for name, value in zip(self.args, args):
59
+ if name in self.custom_patterns and isinstance(value, str):
60
+ pattern = self.custom_patterns[name]
61
+ if not re.fullmatch(pattern, value):
62
+ # TODO: Change to `raise ValueError(...)` in RF 8.0.
63
+ context = EXECUTION_CONTEXTS.current
64
+ context.warn(f"Embedded argument '{name}' got value {value!r} "
65
+ f"that does not match custom pattern {pattern!r}. "
66
+ f"The argument is still accepted, but this behavior "
67
+ f"will change in Robot Framework 8.0.")
68
+
69
+
70
+ class EmbeddedArgumentParser:
71
+ _regexp_extension = re.compile(r'(?<!\\)\(\?.+\)')
72
+ _regexp_group_start = re.compile(r'(?<!\\)\((.*?)\)')
73
+ _escaped_curly = re.compile(r'(\\+)([{}])')
74
+ _regexp_group_escape = r'(?:\1)'
75
+ _default_pattern = '.*?'
76
+ _variable_pattern = r'\$\{[^\}]+\}'
77
+
78
+ def parse(self, string: str) -> 'EmbeddedArguments|None':
79
+ name_parts = ['^']
80
+ args = []
81
+ custom_patterns = {}
82
+ after = string
83
+ for match in VariableMatches(string, identifiers='$'):
84
+ arg, pattern, is_custom = self._get_name_and_pattern(match.base)
85
+ args.append(arg)
86
+ if is_custom:
87
+ custom_patterns[arg] = pattern
88
+ pattern = self._format_custom_regexp(pattern)
89
+ name_parts.extend([re.escape(match.before), f'({pattern})'])
90
+ after = match.after
91
+ if not args:
92
+ return None
93
+ name_parts.extend([re.escape(after), '$'])
94
+ name = self._compile_regexp(''.join(name_parts))
95
+ return EmbeddedArguments(name, args, custom_patterns)
96
+
97
+ def _get_name_and_pattern(self, name: str) -> 'tuple[str, str, bool]':
98
+ if ':' in name:
99
+ name, pattern = name.split(':', 1)
100
+ custom = True
101
+ else:
102
+ pattern = self._default_pattern
103
+ custom = False
104
+ return name, pattern, custom
105
+
106
+ def _format_custom_regexp(self, pattern: str) -> str:
107
+ for formatter in (self._regexp_extensions_are_not_allowed,
108
+ self._make_groups_non_capturing,
109
+ self._unescape_curly_braces,
110
+ self._escape_escapes,
111
+ self._add_automatic_variable_pattern):
112
+ pattern = formatter(pattern)
113
+ return pattern
114
+
115
+ def _regexp_extensions_are_not_allowed(self, pattern: str) -> str:
116
+ if self._regexp_extension.search(pattern):
117
+ raise DataError('Regexp extensions are not allowed in embedded arguments.')
118
+ return pattern
119
+
120
+ def _make_groups_non_capturing(self, pattern: str) -> str:
121
+ return self._regexp_group_start.sub(self._regexp_group_escape, pattern)
122
+
123
+ def _unescape_curly_braces(self, pattern: str) -> str:
124
+ # Users must escape possible lone curly braces in patters (e.g. `${x:\{}`)
125
+ # or otherwise the variable syntax is invalid.
126
+ def unescape(match):
127
+ backslashes = len(match.group(1))
128
+ return '\\' * (backslashes // 2 * 2) + match.group(2)
129
+ return self._escaped_curly.sub(unescape, pattern)
130
+
131
+ def _escape_escapes(self, pattern: str) -> str:
132
+ # When keywords are matched, embedded arguments have not yet been
133
+ # resolved which means possible escapes are still doubled. We thus
134
+ # need to double them in the pattern as well.
135
+ return pattern.replace(r'\\', r'\\\\')
136
+
137
+ def _add_automatic_variable_pattern(self, pattern: str) -> str:
138
+ return f'{pattern}|{self._variable_pattern}'
139
+
140
+ def _compile_regexp(self, pattern: str) -> re.Pattern:
141
+ try:
142
+ return re.compile(''.join(pattern), re.IGNORECASE)
143
+ except Exception:
144
+ raise DataError(f"Compiling embedded arguments regexp failed: "
145
+ f"{get_error_message()}")