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
@@ -96,10 +96,10 @@ Examples:
96
96
  == Python datetime ==
97
97
 
98
98
  Python's standard
99
- [http://docs.python.org/library/datetime.html#datetime-objects|datetime]
100
- objects can be used both in input and output. In input they are recognized
101
- automatically, and in output it is possible to get them by giving ``datetime``
102
- value to ``result_format`` argument.
99
+ [https://docs.python.org/library/datetime.html#datetime.datetime|datetime]
100
+ objects can be used both in input and output. In input, they are recognized
101
+ automatically, and in output it is possible to get them by using the ``datetime``
102
+ value with the ``result_format`` argument.
103
103
 
104
104
  One nice benefit with datetime objects is that they have different time
105
105
  components available as attributes that can be easily accessed using the
@@ -115,6 +115,16 @@ Examples:
115
115
  | Should Be Equal As Integers | ${datetime.second} | 42 |
116
116
  | Should Be Equal As Integers | ${datetime.microsecond} | 123000 |
117
117
 
118
+ == Python date ==
119
+
120
+ Python's standard [https://docs.python.org/library/datetime.html#datetime.date|date]
121
+ objects are automatically recognized in input starting from Robot Framework 7.0.
122
+ They are not supported in output, but ``datetime`` objects can be converted
123
+ to ``date`` objects if needed:
124
+
125
+ | ${datetime} = | Convert Date | 2023-12-18 11:10:42 | datetime |
126
+ | Log | ${datetime.date()} | # The time part is ignored. |
127
+
118
128
  == Epoch time ==
119
129
 
120
130
  Epoch time is the time in seconds since the
@@ -283,7 +293,7 @@ are available as functions that can be easily imported:
283
293
  | seconds = convert_time(timeout)
284
294
  | # ...
285
295
 
286
- Additionally helper classes ``Date`` and ``Time`` can be used directly:
296
+ Additionally, helper classes ``Date`` and ``Time`` can be used directly:
287
297
 
288
298
  | from robot.libraries.DateTime import Date, Time
289
299
  |
@@ -293,12 +303,13 @@ Additionally helper classes ``Date`` and ``Time`` can be used directly:
293
303
  | # ...
294
304
  """
295
305
 
296
- from datetime import datetime, timedelta
306
+ import datetime
307
+ import sys
297
308
  import time
298
309
 
299
310
  from robot.version import get_version
300
- from robot.utils import (elapsed_time_to_string, is_falsy, is_number, is_string,
301
- secs_to_timestr, timestr_to_secs, type_name)
311
+ from robot.utils import (elapsed_time_to_string, secs_to_timestr, timestr_to_secs,
312
+ type_name)
302
313
 
303
314
  __version__ = get_version()
304
315
  __all__ = ['convert_time', 'convert_date', 'subtract_date_from_date',
@@ -306,8 +317,8 @@ __all__ = ['convert_time', 'convert_date', 'subtract_date_from_date',
306
317
  'add_time_to_time', 'add_time_to_date', 'get_current_date']
307
318
 
308
319
 
309
- def get_current_date(time_zone='local', increment=0,
310
- result_format='timestamp', exclude_millis=False):
320
+ def get_current_date(time_zone='local', increment=0, result_format='timestamp',
321
+ exclude_millis=False):
311
322
  """Returns current local or UTC time with an optional increment.
312
323
 
313
324
  Arguments:
@@ -333,20 +344,19 @@ def get_current_date(time_zone='local', increment=0,
333
344
  | Should Be Equal | ${date.year} | ${2014} |
334
345
  | Should Be Equal | ${date.month} | ${6} |
335
346
  """
336
- upper = time_zone.upper()
337
- if upper == 'LOCAL':
338
- dt = datetime.now()
339
- # Epoch time is same regardless the timezone. We convert `dt` to epoch time
340
- # using `time.mktime()` afterwards, and it expects time in local time.
341
- # For details: https://github.com/robotframework/robotframework/issues/3306
342
- elif upper == 'UTC' and result_format.upper() == 'EPOCH':
343
- dt = datetime.now()
344
- elif upper == 'UTC':
345
- dt = datetime.utcnow()
347
+ if time_zone.upper() == 'LOCAL' or result_format.upper() == 'EPOCH':
348
+ dt = datetime.datetime.now()
349
+ elif time_zone.upper() == 'UTC':
350
+ if sys.version_info >= (3, 12):
351
+ # `utcnow()` was deprecated in Python 3.12. We only support "naive"
352
+ # datetime objects and thus need to remove timezone information here.
353
+ dt = datetime.datetime.now(datetime.UTC).replace(tzinfo=None)
354
+ else:
355
+ dt = datetime.datetime.utcnow()
346
356
  else:
347
- raise ValueError("Unsupported timezone '%s'." % time_zone)
357
+ raise ValueError(f"Unsupported timezone '{time_zone}'.")
348
358
  date = Date(dt) + Time(increment)
349
- return date.convert(result_format, millis=is_falsy(exclude_millis))
359
+ return date.convert(result_format, millis=not exclude_millis)
350
360
 
351
361
 
352
362
  def convert_date(date, result_format='timestamp', exclude_millis=False,
@@ -368,8 +378,7 @@ def convert_date(date, result_format='timestamp', exclude_millis=False,
368
378
  | ${date} = | Convert Date | 5.28.2014 12:05 | exclude_millis=yes | date_format=%m.%d.%Y %H:%M |
369
379
  | Should Be Equal | ${date} | 2014-05-28 12:05:00 |
370
380
  """
371
- return Date(date, date_format).convert(result_format,
372
- millis=is_falsy(exclude_millis))
381
+ return Date(date, date_format).convert(result_format, millis=not exclude_millis)
373
382
 
374
383
 
375
384
  def convert_time(time, result_format='number', exclude_millis=False):
@@ -389,7 +398,7 @@ def convert_time(time, result_format='number', exclude_millis=False):
389
398
  | ${time} = | Convert Time | ${3661.5} | timer | exclude_milles=yes |
390
399
  | Should Be Equal | ${time} | 01:01:02 |
391
400
  """
392
- return Time(time).convert(result_format, millis=is_falsy(exclude_millis))
401
+ return Time(time).convert(result_format, millis=not exclude_millis)
393
402
 
394
403
 
395
404
  def subtract_date_from_date(date1, date2, result_format='number',
@@ -415,7 +424,7 @@ def subtract_date_from_date(date1, date2, result_format='number',
415
424
  | Should Be Equal | ${time} | 1 day 42 seconds |
416
425
  """
417
426
  time = Date(date1, date1_format) - Date(date2, date2_format)
418
- return time.convert(result_format, millis=is_falsy(exclude_millis))
427
+ return time.convert(result_format, millis=not exclude_millis)
419
428
 
420
429
 
421
430
  def add_time_to_date(date, time, result_format='timestamp',
@@ -439,7 +448,7 @@ def add_time_to_date(date, time, result_format='timestamp',
439
448
  | Should Be Equal | ${date} | 2014-05-28 13:07:06.115 |
440
449
  """
441
450
  date = Date(date, date_format) + Time(time)
442
- return date.convert(result_format, millis=is_falsy(exclude_millis))
451
+ return date.convert(result_format, millis=not exclude_millis)
443
452
 
444
453
 
445
454
  def subtract_time_from_date(date, time, result_format='timestamp',
@@ -463,7 +472,7 @@ def subtract_time_from_date(date, time, result_format='timestamp',
463
472
  | Should Be Equal | ${date} | 2014-05-28 12:05:03.111 |
464
473
  """
465
474
  date = Date(date, date_format) - Time(time)
466
- return date.convert(result_format, millis=is_falsy(exclude_millis))
475
+ return date.convert(result_format, millis=not exclude_millis)
467
476
 
468
477
 
469
478
  def add_time_to_time(time1, time2, result_format='number',
@@ -484,7 +493,7 @@ def add_time_to_time(time1, time2, result_format='number',
484
493
  | Should Be Equal | ${time} | 04:07:03 |
485
494
  """
486
495
  time = Time(time1) + Time(time2)
487
- return time.convert(result_format, millis=is_falsy(exclude_millis))
496
+ return time.convert(result_format, millis=not exclude_millis)
488
497
 
489
498
 
490
499
  def subtract_time_from_time(time1, time2, result_format='number',
@@ -506,7 +515,7 @@ def subtract_time_from_time(time1, time2, result_format='number',
506
515
  | Should Be Equal | ${time} | - 10s |
507
516
  """
508
517
  time = Time(time1) - Time(time2)
509
- return time.convert(result_format, millis=is_falsy(exclude_millis))
518
+ return time.convert(result_format, millis=not exclude_millis)
510
519
 
511
520
 
512
521
  class Date:
@@ -520,33 +529,38 @@ class Date:
520
529
  return self._convert_to_epoch(self.datetime)
521
530
 
522
531
  def _convert_to_datetime(self, date, input_format):
523
- if isinstance(date, datetime):
532
+ if isinstance(date, datetime.datetime):
524
533
  return date
525
- if is_number(date):
526
- return datetime.fromtimestamp(date)
527
- if is_string(date):
534
+ if isinstance(date, datetime.date):
535
+ return datetime.datetime(date.year, date.month, date.day)
536
+ if isinstance(date, (int, float)):
537
+ return self._epoch_seconds_to_datetime(date)
538
+ if isinstance(date, str):
528
539
  return self._string_to_datetime(date, input_format)
529
- raise ValueError("Unsupported input '%s'." % date)
540
+ raise ValueError(f"Unsupported input '{date}'.")
541
+
542
+ def _epoch_seconds_to_datetime(self, secs):
543
+ return datetime.datetime.fromtimestamp(secs)
530
544
 
531
545
  def _string_to_datetime(self, ts, input_format):
532
546
  if not input_format:
533
547
  ts = self._normalize_timestamp(ts)
534
548
  input_format = '%Y-%m-%d %H:%M:%S.%f'
535
- return datetime.strptime(ts, input_format)
549
+ return datetime.datetime.strptime(ts, input_format)
536
550
 
537
- def _normalize_timestamp(self, date):
538
- ts = ''.join(d for d in date if d.isdigit())
539
- if not (8 <= len(ts) <= 20):
540
- raise ValueError("Invalid timestamp '%s'." % date)
541
- ts = ts.ljust(20, '0')
542
- return '%s-%s-%s %s:%s:%s.%s' % (ts[:4], ts[4:6], ts[6:8], ts[8:10],
543
- ts[10:12], ts[12:14], ts[14:])
551
+ def _normalize_timestamp(self, timestamp):
552
+ numbers = ''.join(d for d in timestamp if d.isdigit())
553
+ if not (8 <= len(numbers) <= 20):
554
+ raise ValueError(f"Invalid timestamp '{timestamp}'.")
555
+ d = numbers[:8]
556
+ t = numbers[8:].ljust(12, '0')
557
+ return f'{d[:4]}-{d[4:6]}-{d[6:8]} {t[:2]}:{t[2:4]}:{t[4:6]}.{t[6:]}'
544
558
 
545
559
  def convert(self, format, millis=True):
546
560
  dt = self.datetime
547
561
  if not millis:
548
562
  secs = 1 if dt.microsecond >= 5e5 else 0
549
- dt = dt.replace(microsecond=0) + timedelta(seconds=secs)
563
+ dt = dt.replace(microsecond=0) + datetime.timedelta(seconds=secs)
550
564
  if '%' in format:
551
565
  return self._convert_to_custom_timestamp(dt, format)
552
566
  format = format.lower()
@@ -556,7 +570,7 @@ class Date:
556
570
  return dt
557
571
  if format == 'epoch':
558
572
  return self._convert_to_epoch(dt)
559
- raise ValueError("Unknown format '%s'." % format)
573
+ raise ValueError(f"Unknown format '{format}'.")
560
574
 
561
575
  def _convert_to_custom_timestamp(self, dt, format):
562
576
  return dt.strftime(format)
@@ -566,25 +580,25 @@ class Date:
566
580
  return dt.strftime('%Y-%m-%d %H:%M:%S')
567
581
  ms = round(dt.microsecond / 1000)
568
582
  if ms == 1000:
569
- dt += timedelta(seconds=1)
583
+ dt += datetime.timedelta(seconds=1)
570
584
  ms = 0
571
- return dt.strftime('%Y-%m-%d %H:%M:%S') + '.%03d' % ms
585
+ return dt.strftime('%Y-%m-%d %H:%M:%S') + f'.{ms:03d}'
572
586
 
573
587
  def _convert_to_epoch(self, dt):
574
- return time.mktime(dt.timetuple()) + dt.microsecond / 1e6
588
+ return dt.timestamp()
575
589
 
576
590
  def __add__(self, other):
577
591
  if isinstance(other, Time):
578
592
  return Date(self.datetime + other.timedelta)
579
- raise TypeError('Can only add Time to Date, got %s.' % type_name(other))
593
+ raise TypeError(f'Can only add Time to Date, got {type_name(other)}.')
580
594
 
581
595
  def __sub__(self, other):
582
596
  if isinstance(other, Date):
583
597
  return Time(self.datetime - other.datetime)
584
598
  if isinstance(other, Time):
585
599
  return Date(self.datetime - other.timedelta)
586
- raise TypeError('Can only subtract Date or Time from Date, got %s.'
587
- % type_name(other))
600
+ raise TypeError(f'Can only subtract Date or Time from Date, '
601
+ f'got {type_name(other)}.')
588
602
 
589
603
 
590
604
  class Time:
@@ -593,19 +607,19 @@ class Time:
593
607
  self.seconds = float(self._convert_time_to_seconds(time))
594
608
 
595
609
  def _convert_time_to_seconds(self, time):
596
- if isinstance(time, timedelta):
610
+ if isinstance(time, datetime.timedelta):
597
611
  return time.total_seconds()
598
612
  return timestr_to_secs(time, round_to=None)
599
613
 
600
614
  @property
601
615
  def timedelta(self):
602
- return timedelta(seconds=self.seconds)
616
+ return datetime.timedelta(seconds=self.seconds)
603
617
 
604
618
  def convert(self, format, millis=True):
605
619
  try:
606
- result_converter = getattr(self, '_convert_to_%s' % format.lower())
620
+ result_converter = getattr(self, f'_convert_to_{format.lower()}')
607
621
  except AttributeError:
608
- raise ValueError("Unknown format '%s'." % format)
622
+ raise ValueError(f"Unknown format '{format}'.")
609
623
  seconds = self.seconds if millis else float(round(self.seconds))
610
624
  return result_converter(seconds, millis)
611
625
 
@@ -619,18 +633,17 @@ class Time:
619
633
  return secs_to_timestr(seconds, compact=True)
620
634
 
621
635
  def _convert_to_timer(self, seconds, millis=True):
622
- return elapsed_time_to_string(seconds * 1000, include_millis=millis)
636
+ return elapsed_time_to_string(seconds, include_millis=millis, seconds=True)
623
637
 
624
638
  def _convert_to_timedelta(self, seconds, millis=True):
625
- return timedelta(seconds=seconds)
639
+ return datetime.timedelta(seconds=seconds)
626
640
 
627
641
  def __add__(self, other):
628
642
  if isinstance(other, Time):
629
643
  return Time(self.seconds + other.seconds)
630
- raise TypeError('Can only add Time to Time, got %s.' % type_name(other))
644
+ raise TypeError(f'Can only add Time to Time, got {type_name(other)}.')
631
645
 
632
646
  def __sub__(self, other):
633
647
  if isinstance(other, Time):
634
648
  return Time(self.seconds - other.seconds)
635
- raise TypeError('Can only subtract Time from Time, got %s.'
636
- % type_name(other))
649
+ raise TypeError(f'Can only subtract Time from Time, got {type_name(other)}.')
@@ -21,6 +21,7 @@ import re
21
21
  import shutil
22
22
  import tempfile
23
23
  import time
24
+ from datetime import datetime
24
25
 
25
26
  from robot.version import get_version
26
27
  from robot.api import logger
@@ -28,7 +29,7 @@ from robot.api.deco import keyword
28
29
  from robot.utils import (abspath, ConnectionCache, console_decode, del_env_var,
29
30
  get_env_var, get_env_vars, get_time, is_truthy,
30
31
  is_string, normpath, parse_time, plural_or_not,
31
- safe_str, secs_to_timestamp, secs_to_timestr, seq2str,
32
+ safe_str, secs_to_timestr, seq2str,
32
33
  set_env_var, timestr_to_secs, CONSOLE_ENCODING, WINDOWS)
33
34
 
34
35
  __version__ = get_version()
@@ -108,10 +109,10 @@ class OperatingSystem:
108
109
  operating system dependent, but typically e.g. ``~/robot`` is expanded to
109
110
  ``C:\Users\<user>\robot`` on Windows and ``/home/<user>/robot`` on Unixes.
110
111
 
111
- = ``pathlib.Path`` support =
112
+ = pathlib.Path support =
112
113
 
113
114
  Starting from Robot Framework 6.0, arguments representing paths can be given
114
- as [https://docs.python.org/3/library/pathlib.html pathlib.Path] instances
115
+ as [https://docs.python.org/3/library/pathlib.html|pathlib.Path] instances
115
116
  in addition to strings.
116
117
 
117
118
  All keywords returning paths return them as strings. This may change in
@@ -1297,8 +1298,8 @@ class OperatingSystem:
1297
1298
  if not os.path.isfile(path):
1298
1299
  self._error("Path '%s' is not a regular file." % path)
1299
1300
  os.utime(path, (mtime, mtime))
1300
- time.sleep(0.1) # Give os some time to really set these times
1301
- tstamp = secs_to_timestamp(mtime, seps=('-', ' ', ':'))
1301
+ time.sleep(0.1) # Give OS some time to really set these times.
1302
+ tstamp = datetime.fromtimestamp(mtime).isoformat(' ', timespec='seconds')
1302
1303
  self._link("Set modified time of '%%s' to %s." % tstamp, path)
1303
1304
 
1304
1305
  def get_file_size(self, path):
@@ -75,7 +75,7 @@ class Process:
75
75
  optional ``**configuration`` keyword arguments. Configuration arguments
76
76
  must be given after other arguments passed to these keywords and must
77
77
  use syntax like ``name=value``. Available configuration arguments are
78
- listed below and discussed further in sections afterwards.
78
+ listed below and discussed further in sections afterward.
79
79
 
80
80
  | = Name = | = Explanation = |
81
81
  | shell | Specifies whether to run the command in shell or not. |
@@ -96,7 +96,7 @@ class Process:
96
96
  == Running processes in shell ==
97
97
 
98
98
  The ``shell`` argument specifies whether to run the process in a shell or
99
- not. By default shell is not used, which means that shell specific commands,
99
+ not. By default, shell is not used, which means that shell specific commands,
100
100
  like ``copy`` and ``dir`` on Windows, are not available. You can, however,
101
101
  run shell scripts and batch files without using a shell.
102
102
 
@@ -129,8 +129,8 @@ class Process:
129
129
 
130
130
  == Environment variables ==
131
131
 
132
- By default the child process will get a copy of the parent process's
133
- environment variables. The ``env`` argument can be used to give the
132
+ The child process will get a copy of the parent process's environment
133
+ variables by default. The ``env`` argument can be used to give the
134
134
  child a custom environment as a Python dictionary. If there is a need
135
135
  to specify only certain environment variable, it is possible to use the
136
136
  ``env:<name>=<value>`` format to set or override only that named variables.
@@ -143,12 +143,12 @@ class Process:
143
143
 
144
144
  == Standard output and error streams ==
145
145
 
146
- By default processes are run so that their standard output and standard
146
+ By default, processes are run so that their standard output and standard
147
147
  error streams are kept in the memory. This works fine normally,
148
148
  but if there is a lot of output, the output buffers may get full and
149
149
  the program can hang.
150
150
 
151
- To avoid the above mentioned problems, it is possible to use ``stdout``
151
+ To avoid the above-mentioned problems, it is possible to use ``stdout``
152
152
  and ``stderr`` arguments to specify files on the file system where to
153
153
  redirect the outputs. This can also be useful if other processes or
154
154
  other keywords need to read or manipulate the outputs somehow.
@@ -172,8 +172,6 @@ class Process:
172
172
  This way the process will not hang even if there would be a lot of output,
173
173
  but naturally output is not available after execution either.
174
174
 
175
- Support for the special value ``DEVNULL`` is new in Robot Framework 3.2.
176
-
177
175
  Examples:
178
176
  | ${result} = | `Run Process` | program | stdout=${TEMPDIR}/stdout.txt | stderr=${TEMPDIR}/stderr.txt |
179
177
  | `Log Many` | stdout: ${result.stdout} | stderr: ${result.stderr} |
@@ -191,25 +189,23 @@ class Process:
191
189
  explained in the table below.
192
190
 
193
191
  | = Value = | = Explanation = |
194
- | String ``PIPE`` | Make stdin a pipe that can be written to. This is the default. |
195
- | String ``NONE`` | Inherit stdin from the parent process. This value is case-insensitive. |
192
+ | String ``NONE`` | Inherit stdin from the parent process. This is the default. |
193
+ | String ``PIPE`` | Make stdin a pipe that can be written to. |
196
194
  | Path to a file | Open the specified file and use it as the stdin. |
197
195
  | Any other string | Create a temporary file with the text as its content and use it as the stdin. |
198
196
  | Any non-string value | Used as-is. Could be a file descriptor, stdout of another process, etc. |
199
197
 
200
- Values ``PIPE`` and ``NONE`` are internally mapped directly to
198
+ Values ``PIPE`` and ``NONE`` are case-insensitive and internally mapped to
201
199
  ``subprocess.PIPE`` and ``None``, respectively, when calling
202
200
  [https://docs.python.org/3/library/subprocess.html#subprocess.Popen|subprocess.Popen].
203
- The default behavior may change from ``PIPE`` to ``NONE`` in future
204
- releases. If you depend on the ``PIPE`` behavior, it is a good idea to use
205
- it explicitly.
206
201
 
207
202
  Examples:
208
- | `Run Process` | command | stdin=NONE |
203
+ | `Run Process` | command | stdin=PIPE |
209
204
  | `Run Process` | command | stdin=${CURDIR}/stdin.txt |
210
205
  | `Run Process` | command | stdin=Stdin as text. |
211
206
 
212
- The support to configure ``stdin`` is new in Robot Framework 4.1.2.
207
+ The support to configure ``stdin`` is new in Robot Framework 4.1.2. Its default
208
+ value used to be ``PIPE`` until Robot Framework 7.0.
213
209
 
214
210
  == Output encoding ==
215
211
 
@@ -298,8 +294,6 @@ class Process:
298
294
  | `Terminate Process` | kill=${EMPTY} | # Empty string is false. |
299
295
  | `Terminate Process` | kill=${FALSE} | # Python ``False`` is false. |
300
296
 
301
- Considering ``OFF`` and ``0`` false is new in Robot Framework 3.1.
302
-
303
297
  = Example =
304
298
 
305
299
  | ***** Settings *****
@@ -337,9 +331,15 @@ class Process:
337
331
  configuration` for more details about configuration related to starting
338
332
  processes. Configuration related to waiting for processes consists of
339
333
  ``timeout`` and ``on_timeout`` arguments that have same semantics as
340
- with `Wait For Process` keyword. By default there is no timeout, and
334
+ with `Wait For Process` keyword. By default, there is no timeout, and
341
335
  if timeout is defined the default action on timeout is ``terminate``.
342
336
 
337
+ Process outputs are, by default, written into in-memory buffers.
338
+ If there is a lot of output, these buffers may get full causing
339
+ the process to hang. To avoid that, process outputs can be redirected
340
+ using the ``stdout`` and ``stderr`` configuration parameters. For more
341
+ information see the `Standard output and error streams` section.
342
+
343
343
  Returns a `result object` containing information about the execution.
344
344
 
345
345
  Note that possible equal signs in ``*arguments`` must be escaped
@@ -349,7 +349,7 @@ class Process:
349
349
  Examples:
350
350
  | ${result} = | Run Process | python | -c | print('Hello, world!') |
351
351
  | Should Be Equal | ${result.stdout} | Hello, world! |
352
- | ${result} = | Run Process | ${command} | stderr=STDOUT | timeout=10s |
352
+ | ${result} = | Run Process | ${command} | stdout=${CURDIR}/stdout.txt | stderr=STDOUT |
353
353
  | ${result} = | Run Process | ${command} | timeout=1min | on_timeout=continue |
354
354
  | ${result} = | Run Process | java -Dname\\=value Example | shell=True | cwd=${EXAMPLE} |
355
355
 
@@ -369,11 +369,13 @@ class Process:
369
369
 
370
370
  See `Specifying command and arguments` and `Process configuration`
371
371
  for more information about the arguments, and `Run Process` keyword
372
- for related examples.
372
+ for related examples. This includes information about redirecting
373
+ process outputs to avoid process handing due to output buffers getting
374
+ full.
373
375
 
374
376
  Makes the started process new `active process`. Returns the created
375
377
  [https://docs.python.org/3/library/subprocess.html#popen-constructor |
376
- subprocess.Popen] object which can be be used later to active this
378
+ subprocess.Popen] object which can be used later to activate this
377
379
  process. ``Popen`` attributes like ``pid`` can also be accessed directly.
378
380
 
379
381
  Processes are started so that they create a new process group. This
@@ -381,7 +383,7 @@ class Process:
381
383
 
382
384
  Examples:
383
385
 
384
- Start process and wait for it to end later using alias:
386
+ Start process and wait for it to end later using an alias:
385
387
  | `Start Process` | ${command} | alias=example |
386
388
  | # Other keywords |
387
389
  | ${result} = | `Wait For Process` | example |
@@ -492,9 +494,6 @@ class Process:
492
494
  | ${result} = | Wait For Process | timeout=1min 30s | on_timeout=kill |
493
495
  | Process Should Be Stopped | | |
494
496
  | Should Be Equal As Integers | ${result.rc} | -9 |
495
-
496
- Ignoring timeout if it is string ``NONE``, zero, or negative is new
497
- in Robot Framework 3.2.
498
497
  """
499
498
  process = self._processes[handle]
500
499
  logger.info('Waiting for process to complete.')
@@ -882,7 +881,7 @@ class ExecutionResult:
882
881
 
883
882
  class ProcessConfiguration:
884
883
 
885
- def __init__(self, cwd=None, shell=False, stdout=None, stderr=None, stdin='PIPE',
884
+ def __init__(self, cwd=None, shell=False, stdout=None, stderr=None, stdin=None,
886
885
  output_encoding='CONSOLE', alias=None, env=None, **rest):
887
886
  self.cwd = os.path.normpath(cwd) if cwd else os.path.abspath('.')
888
887
  self.shell = is_truthy(shell)
@@ -20,6 +20,7 @@ import re
20
20
  import socket
21
21
  import sys
22
22
  import xmlrpc.client
23
+ from datetime import date, datetime, timedelta
23
24
  from xml.parsers.expat import ExpatError
24
25
 
25
26
  from robot.errors import RemoteError
@@ -59,8 +60,8 @@ class Remote:
59
60
  try:
60
61
  return self._client.get_keyword_names()
61
62
  except TypeError as error:
62
- raise RuntimeError('Connecting remote server at %s failed: %s'
63
- % (self._uri, error))
63
+ raise RuntimeError(f'Connecting remote server at {self._uri} '
64
+ f'failed: {error}')
64
65
 
65
66
  def _is_lib_info_available(self):
66
67
  if not self._lib_info_initialized:
@@ -107,47 +108,53 @@ class Remote:
107
108
 
108
109
  class ArgumentCoercer:
109
110
  binary = re.compile('[\x00-\x08\x0B\x0C\x0E-\x1F]')
110
- non_ascii = re.compile('[\x80-\xff]')
111
111
 
112
112
  def coerce(self, argument):
113
113
  for handles, handler in [(is_string, self._handle_string),
114
- (is_bytes, self._handle_bytes),
115
- (is_number, self._pass_through),
114
+ (self._no_conversion_needed, self._pass_through),
115
+ (self._is_date, self._handle_date),
116
+ (self._is_timedelta, self._handle_timedelta),
116
117
  (is_dict_like, self._coerce_dict),
117
- (is_list_like, self._coerce_list),
118
- (lambda arg: True, self._to_string)]:
118
+ (is_list_like, self._coerce_list)]:
119
119
  if handles(argument):
120
120
  return handler(argument)
121
+ return self._to_string(argument)
122
+
123
+ def _no_conversion_needed(self, arg):
124
+ return is_number(arg) or is_bytes(arg) or isinstance(arg, datetime)
121
125
 
122
126
  def _handle_string(self, arg):
123
- if self._string_contains_binary(arg):
127
+ if self.binary.search(arg):
124
128
  return self._handle_binary_in_string(arg)
125
129
  return arg
126
130
 
127
- def _string_contains_binary(self, arg):
128
- return (self.binary.search(arg) or
129
- is_bytes(arg) and self.non_ascii.search(arg))
130
-
131
131
  def _handle_binary_in_string(self, arg):
132
132
  try:
133
- if not is_bytes(arg):
134
- # Map Unicode code points to bytes directly
135
- arg = arg.encode('latin-1')
133
+ # Map Unicode code points to bytes directly
134
+ return arg.encode('latin-1')
136
135
  except UnicodeError:
137
- raise ValueError('Cannot represent %r as binary.' % arg)
138
- return xmlrpc.client.Binary(arg)
139
-
140
- def _handle_bytes(self, arg):
141
- return xmlrpc.client.Binary(arg)
136
+ raise ValueError(f'Cannot represent {arg!r} as binary.')
142
137
 
143
138
  def _pass_through(self, arg):
144
139
  return arg
145
140
 
141
+ def _is_date(self, arg):
142
+ return isinstance(arg, date)
143
+
144
+ def _handle_date(self, arg):
145
+ return datetime(arg.year, arg.month, arg.day)
146
+
147
+ def _is_timedelta(self, arg):
148
+ return isinstance(arg, timedelta)
149
+
150
+ def _handle_timedelta(self, arg):
151
+ return arg.total_seconds()
152
+
146
153
  def _coerce_list(self, arg):
147
154
  return [self.coerce(item) for item in arg]
148
155
 
149
156
  def _coerce_dict(self, arg):
150
- return dict((self._to_key(key), self.coerce(arg[key])) for key in arg)
157
+ return {self._to_key(key): self.coerce(arg[key]) for key in arg}
151
158
 
152
159
  def _to_key(self, item):
153
160
  item = self._to_string(item)
@@ -159,15 +166,15 @@ class ArgumentCoercer:
159
166
  return self._handle_string(item)
160
167
 
161
168
  def _validate_key(self, key):
162
- if isinstance(key, xmlrpc.client.Binary):
163
- raise ValueError('Dictionary keys cannot be binary. Got %r.' % (key.data,))
169
+ if isinstance(key, bytes):
170
+ raise ValueError(f'Dictionary keys cannot be binary. Got {key!r}.')
164
171
 
165
172
 
166
173
  class RemoteResult:
167
174
 
168
175
  def __init__(self, result):
169
176
  if not (is_dict_like(result) and 'status' in result):
170
- raise RuntimeError('Invalid remote result dictionary: %s' % result)
177
+ raise RuntimeError(f'Invalid remote result dictionary: {result!r}')
171
178
  self.status = result['status']
172
179
  self.output = safe_str(self._get(result, 'output'))
173
180
  self.return_ = self._get(result, 'return')
@@ -181,8 +188,6 @@ class RemoteResult:
181
188
  return self._convert(value)
182
189
 
183
190
  def _convert(self, value):
184
- if isinstance(value, xmlrpc.client.Binary):
185
- return bytes(value.data)
186
191
  if is_dict_like(value):
187
192
  return DotDict((k, self._convert(v)) for k, v in value.items())
188
193
  if is_list_like(value):
@@ -204,6 +209,7 @@ class XmlRpcRemoteClient:
204
209
  else:
205
210
  transport = TimeoutHTTPTransport(timeout=self.timeout)
206
211
  server = xmlrpc.client.ServerProxy(self.uri, encoding='UTF-8',
212
+ use_builtin_types=True,
207
213
  transport=transport)
208
214
  try:
209
215
  yield server
@@ -244,12 +250,12 @@ class XmlRpcRemoteClient:
244
250
  except xmlrpc.client.Fault as err:
245
251
  message = err.faultString
246
252
  except socket.error as err:
247
- message = 'Connection to remote server broken: %s' % err
253
+ message = f'Connection to remote server broken: {err}'
248
254
  except ExpatError as err:
249
- message = ('Processing XML-RPC return value failed. '
250
- 'Most often this happens when the return value '
251
- 'contains characters that are not valid in XML. '
252
- 'Original error was: ExpatError: %s' % err)
255
+ message = (f'Processing XML-RPC return value failed. '
256
+ f'Most often this happens when the return value '
257
+ f'contains characters that are not valid in XML. '
258
+ f'Original error was: ExpatError: {err}')
253
259
  raise RuntimeError(message)
254
260
 
255
261
 
@@ -259,11 +265,9 @@ class XmlRpcRemoteClient:
259
265
  class TimeoutHTTPTransport(xmlrpc.client.Transport):
260
266
  _connection_class = http.client.HTTPConnection
261
267
 
262
- def __init__(self, use_datetime=0, timeout=None):
263
- xmlrpc.client.Transport.__init__(self, use_datetime)
264
- if not timeout:
265
- timeout = socket._GLOBAL_DEFAULT_TIMEOUT
266
- self.timeout = timeout
268
+ def __init__(self, timeout=None):
269
+ super().__init__(use_builtin_types=True)
270
+ self.timeout = timeout or socket._GLOBAL_DEFAULT_TIMEOUT
267
271
 
268
272
  def make_connection(self, host):
269
273
  if self._connection and host == self._connection[0]: