robotframework 6.1.1__zip → 7.0__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {robotframework-6.1.1 → robotframework-7.0}/INSTALL.rst +25 -25
- {robotframework-6.1.1 → robotframework-7.0}/PKG-INFO +6 -8
- {robotframework-6.1.1 → robotframework-7.0}/README.rst +3 -2
- {robotframework-6.1.1 → robotframework-7.0}/setup.py +3 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/__init__.py +4 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/deco.py +60 -14
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/exceptions.py +6 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/interfaces.py +402 -67
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/logger.py +27 -20
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/parsing.py +4 -2
- robotframework-7.0/src/robot/api/py.typed +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/gatherfailed.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/languages.py +0 -9
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/settings.py +21 -14
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/common/storage.js +11 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/htmlfilewriter.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.css +10 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.html +10 -0
- robotframework-7.0/src/robot/htmldata/rebot/common.css +362 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/doc_formatting.css +13 -7
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/log.css +51 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/log.html +14 -23
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/model.js +2 -4
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/report.css +83 -19
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/report.html +22 -7
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/testdata.js +10 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/view.js +84 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/template.py +3 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/builder.py +0 -8
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/datatypes.py +9 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/htmlutils.py +4 -7
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/jsonbuilder.py +38 -20
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/model.py +21 -28
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/robotbuilder.py +50 -31
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/standardtypes.py +9 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/xmlbuilder.py +35 -20
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/xmlwriter.py +18 -38
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/BuiltIn.py +255 -205
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Collections.py +384 -240
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/DateTime.py +73 -60
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/OperatingSystem.py +6 -5
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Process.py +26 -27
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Remote.py +40 -36
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/String.py +66 -76
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/XML.py +66 -59
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/__init__.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/__init__.py +5 -5
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/body.py +44 -13
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/configurer.py +15 -11
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/control.py +226 -84
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/filter.py +31 -25
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/itemlist.py +9 -8
- robotframework-7.0/src/robot/model/keyword.py +77 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/message.py +19 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/modelobject.py +25 -7
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/namepatterns.py +3 -25
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/stats.py +9 -15
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/tags.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/testcase.py +15 -27
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/testsuite.py +17 -26
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/visitor.py +35 -8
- robotframework-7.0/src/robot/output/console/dotted.py +90 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/quiet.py +3 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/verbose.py +61 -61
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/debugfile.py +39 -24
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/filelogger.py +18 -15
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/librarylogger.py +3 -2
- robotframework-7.0/src/robot/output/listeners.py +753 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/logger.py +216 -80
- robotframework-7.0/src/robot/output/loggerapi.py +215 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/loggerhelper.py +23 -56
- robotframework-7.0/src/robot/output/output.py +185 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/stdoutlogsplitter.py +8 -5
- robotframework-7.0/src/robot/output/xmllogger.py +459 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/blocklexers.py +17 -13
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/context.py +12 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/lexer.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/settings.py +6 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/statementlexers.py +39 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/tokens.py +27 -29
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/model/blocks.py +19 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/model/statements.py +193 -94
- robotframework-7.0/src/robot/parsing/model/visitor.py +100 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/rebot.py +2 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/expandkeywordmatcher.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jsbuildingcontext.py +8 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jsmodelbuilders.py +88 -61
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/logreportwriters.py +16 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/outputwriter.py +18 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/resultwriter.py +4 -4
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/stringcache.py +3 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/xunitwriter.py +15 -21
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/__init__.py +3 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/configurer.py +12 -9
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/executionresult.py +56 -8
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/flattenkeywordmatcher.py +48 -9
- robotframework-7.0/src/robot/result/keywordremover.py +207 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/merger.py +1 -1
- robotframework-7.0/src/robot/result/model.py +1185 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/modeldeprecation.py +9 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/resultbuilder.py +46 -36
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/xmlelementhandlers.py +83 -43
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/run.py +2 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/__init__.py +14 -4
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/__init__.py +2 -1
- robotframework-7.0/src/robot/running/arguments/argumentconverter.py +100 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentmapper.py +26 -24
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentparser.py +82 -60
- robotframework-7.0/src/robot/running/arguments/argumentresolver.py +158 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentspec.py +83 -116
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentvalidator.py +33 -27
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/customconverters.py +15 -12
- robotframework-7.0/src/robot/running/arguments/embedded.py +145 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/typeconverters.py +233 -213
- robotframework-7.0/src/robot/running/arguments/typeinfo.py +317 -0
- robotframework-7.0/src/robot/running/arguments/typeinfoparser.py +219 -0
- robotframework-7.0/src/robot/running/arguments/typevalidator.py +60 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/bodyrunner.py +147 -129
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/builders.py +2 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/parsers.py +10 -11
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/settings.py +9 -17
- robotframework-7.0/src/robot/running/builder/transformers.py +535 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/context.py +113 -31
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/dynamicmethods.py +62 -34
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/importer.py +27 -49
- robotframework-7.0/src/robot/running/invalidkeyword.py +67 -0
- robotframework-7.0/src/robot/running/keywordfinder.py +91 -0
- robotframework-7.0/src/robot/running/keywordimplementation.py +164 -0
- robotframework-7.0/src/robot/running/librarykeyword.py +392 -0
- robotframework-7.0/src/robot/running/librarykeywordrunner.py +250 -0
- robotframework-7.0/src/robot/running/libraryscopes.py +115 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/model.py +195 -377
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/namespace.py +124 -137
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/outputcapture.py +20 -12
- robotframework-7.0/src/robot/running/resourcemodel.py +448 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/statusreporter.py +16 -13
- robotframework-7.0/src/robot/running/suiterunner.py +265 -0
- robotframework-7.0/src/robot/running/testlibraries.py +500 -0
- robotframework-7.0/src/robot/running/userkeywordrunner.py +260 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/testdoc.py +18 -13
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/__init__.py +53 -35
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/connectioncache.py +64 -59
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/dotdict.py +3 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/encodingsniffer.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/escaping.py +19 -19
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/importer.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/markupwriters.py +23 -15
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/misc.py +1 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/normalizing.py +9 -24
- robotframework-7.0/src/robot/utils/notset.py +33 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/platform.py +15 -5
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotio.py +9 -9
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotpath.py +1 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robottime.py +122 -90
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robottypes.py +21 -31
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/setter.py +0 -5
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/text.py +7 -4
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/unic.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/__init__.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/assigner.py +17 -19
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/evaluation.py +20 -17
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/filesetter.py +80 -80
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/replacer.py +33 -36
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/scopes.py +17 -12
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/search.py +66 -41
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/store.py +14 -16
- robotframework-7.0/src/robot/variables/tablesetter.py +164 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/variables.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/version.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/PKG-INFO +6 -8
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/SOURCES.txt +10 -8
- {robotframework-6.1.1 → robotframework-7.0}/tasks.py +6 -6
- robotframework-6.1.1/src/robot/htmldata/rebot/common.css +0 -239
- robotframework-6.1.1/src/robot/libraries/Reserved.py +0 -48
- robotframework-6.1.1/src/robot/model/keyword.py +0 -173
- robotframework-6.1.1/src/robot/output/console/dotted.py +0 -90
- robotframework-6.1.1/src/robot/output/listenerarguments.py +0 -165
- robotframework-6.1.1/src/robot/output/listenermethods.py +0 -113
- robotframework-6.1.1/src/robot/output/listeners.py +0 -174
- robotframework-6.1.1/src/robot/output/output.py +0 -95
- robotframework-6.1.1/src/robot/output/xmllogger.py +0 -354
- robotframework-6.1.1/src/robot/parsing/model/visitor.py +0 -67
- robotframework-6.1.1/src/robot/result/keywordremover.py +0 -183
- robotframework-6.1.1/src/robot/result/model.py +0 -957
- robotframework-6.1.1/src/robot/running/arguments/argumentconverter.py +0 -79
- robotframework-6.1.1/src/robot/running/arguments/argumentresolver.py +0 -131
- robotframework-6.1.1/src/robot/running/arguments/embedded.py +0 -146
- robotframework-6.1.1/src/robot/running/arguments/typevalidator.py +0 -56
- robotframework-6.1.1/src/robot/running/builder/transformers.py +0 -642
- robotframework-6.1.1/src/robot/running/handlers.py +0 -321
- robotframework-6.1.1/src/robot/running/handlerstore.py +0 -66
- robotframework-6.1.1/src/robot/running/librarykeywordrunner.py +0 -238
- robotframework-6.1.1/src/robot/running/libraryscopes.py +0 -97
- robotframework-6.1.1/src/robot/running/modelcombiner.py +0 -32
- robotframework-6.1.1/src/robot/running/suiterunner.py +0 -248
- robotframework-6.1.1/src/robot/running/testlibraries.py +0 -423
- robotframework-6.1.1/src/robot/running/usererrorhandler.py +0 -75
- robotframework-6.1.1/src/robot/running/userkeyword.py +0 -111
- robotframework-6.1.1/src/robot/running/userkeywordrunner.py +0 -274
- robotframework-6.1.1/src/robot/variables/tablesetter.py +0 -156
- {robotframework-6.1.1 → robotframework-7.0}/AUTHORS.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/BUILD.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/CONTRIBUTING.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/COPYRIGHT.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/LICENSE.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/MANIFEST.in +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/setup.cfg +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/__main__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/errors.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/common/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/common/js_disabled.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/jsonwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/doc_formatting.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/print.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/pygments.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/fileloading.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/log.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/print.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/util.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/testdoc/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.html +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdoc.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/consoleviewer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/htmlwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/jsonwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/output.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/writer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Dialogs.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Easter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Screenshot.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Telnet.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/dialogs_py.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/fixture.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/metadata.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/modifier.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/statistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/suitestatistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/tagsetter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/tagstatistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/totalstatistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/highlighting.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/pyloggingconf.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/tokenizer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/model/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/blockparsers.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/fileparser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/parser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/suitestructure.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/pythonpathsetter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jsexecutionresult.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jswriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/executionerrors.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/messagefilter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/suiteteardownfailed.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/visitor.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/randomizer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/runkwregister.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/signalhandler.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/status.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/timeouts/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/timeouts/posix.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/timeouts/windows.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/application.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/argumentparser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/asserts.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/charwidth.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/compress.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/encoding.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/error.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/etreewrapper.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/filereader.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/frange.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/htmlformatters.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/markuputils.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/match.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/recommendations.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/restreader.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotenv.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotinspect.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/sortable.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/typehints.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/finders.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/notfound.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/resolvable.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/dependency_links.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/entry_points.txt +0 -0
- {robotframework-6.1.1 → 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
|
-
[
|
|
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
|
|
102
|
-
value
|
|
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
|
-
|
|
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,
|
|
301
|
-
|
|
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
|
-
|
|
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
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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 '
|
|
357
|
+
raise ValueError(f"Unsupported timezone '{time_zone}'.")
|
|
348
358
|
date = Date(dt) + Time(increment)
|
|
349
|
-
return date.convert(result_format, 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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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
|
|
526
|
-
return datetime.
|
|
527
|
-
if
|
|
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 '
|
|
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,
|
|
538
|
-
|
|
539
|
-
if not (8 <= len(
|
|
540
|
-
raise ValueError("Invalid timestamp '
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
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 '
|
|
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') + '
|
|
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
|
|
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
|
|
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,
|
|
587
|
-
|
|
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_
|
|
620
|
+
result_converter = getattr(self, f'_convert_to_{format.lower()}')
|
|
607
621
|
except AttributeError:
|
|
608
|
-
raise ValueError("Unknown 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
|
|
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
|
|
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
|
|
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,
|
|
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
|
-
=
|
|
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
|
|
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)
|
|
1301
|
-
tstamp =
|
|
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
|
|
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
|
-
|
|
133
|
-
|
|
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
|
|
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 ``
|
|
195
|
-
| String ``
|
|
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
|
|
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=
|
|
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} |
|
|
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
|
|
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=
|
|
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
|
|
63
|
-
|
|
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
|
-
(
|
|
115
|
-
(
|
|
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.
|
|
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
|
-
|
|
134
|
-
|
|
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
|
|
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
|
|
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,
|
|
163
|
-
raise ValueError('Dictionary keys cannot be binary. Got
|
|
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:
|
|
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:
|
|
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:
|
|
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,
|
|
263
|
-
|
|
264
|
-
|
|
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]:
|