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.
- {robotframework-6.1rc1 → robotframework-7.0}/INSTALL.rst +25 -25
- {robotframework-6.1rc1 → robotframework-7.0}/PKG-INFO +6 -8
- {robotframework-6.1rc1 → robotframework-7.0}/README.rst +3 -2
- {robotframework-6.1rc1 → robotframework-7.0}/setup.py +3 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/__init__.py +4 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/deco.py +60 -14
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/exceptions.py +6 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/interfaces.py +403 -68
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/logger.py +27 -20
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/parsing.py +4 -2
- robotframework-7.0/src/robot/api/py.typed +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/gatherfailed.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/languages.py +61 -25
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/settings.py +21 -14
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/common/storage.js +11 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/htmlfilewriter.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.css +10 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.html +10 -0
- robotframework-7.0/src/robot/htmldata/rebot/common.css +362 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/doc_formatting.css +13 -7
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/log.css +51 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/log.html +14 -23
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/model.js +2 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/report.css +83 -19
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/report.html +22 -7
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/testdata.js +10 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/view.js +84 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/template.py +3 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/builder.py +0 -8
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/datatypes.py +9 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/htmlutils.py +4 -7
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/jsonbuilder.py +38 -20
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/model.py +21 -28
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/robotbuilder.py +50 -31
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/standardtypes.py +9 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/xmlbuilder.py +35 -20
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/xmlwriter.py +18 -38
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/BuiltIn.py +255 -205
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Collections.py +384 -240
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/DateTime.py +73 -60
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/OperatingSystem.py +6 -5
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Process.py +26 -27
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Remote.py +40 -36
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/String.py +66 -76
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/XML.py +66 -59
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/__init__.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/dialogs_py.py +14 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/__init__.py +5 -5
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/body.py +44 -13
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/configurer.py +19 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/control.py +230 -88
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/filter.py +31 -25
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/itemlist.py +9 -8
- robotframework-7.0/src/robot/model/keyword.py +77 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/message.py +19 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/modelobject.py +27 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/modifier.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/namepatterns.py +3 -25
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/stats.py +9 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/tags.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/testcase.py +15 -27
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/testsuite.py +44 -28
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/visitor.py +35 -8
- robotframework-7.0/src/robot/output/console/dotted.py +90 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/quiet.py +3 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/verbose.py +61 -61
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/debugfile.py +39 -24
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/filelogger.py +18 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/librarylogger.py +3 -2
- robotframework-7.0/src/robot/output/listeners.py +753 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/logger.py +216 -80
- robotframework-7.0/src/robot/output/loggerapi.py +215 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/loggerhelper.py +23 -56
- robotframework-7.0/src/robot/output/output.py +185 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/stdoutlogsplitter.py +8 -5
- robotframework-7.0/src/robot/output/xmllogger.py +459 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/blocklexers.py +17 -13
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/context.py +12 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/lexer.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/settings.py +6 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/statementlexers.py +39 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/tokens.py +27 -29
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/model/blocks.py +19 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/model/statements.py +193 -94
- robotframework-7.0/src/robot/parsing/model/visitor.py +100 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/rebot.py +2 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/expandkeywordmatcher.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jsbuildingcontext.py +8 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jsmodelbuilders.py +88 -61
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/logreportwriters.py +16 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/outputwriter.py +18 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/resultwriter.py +4 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/stringcache.py +3 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/xunitwriter.py +15 -21
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/__init__.py +3 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/configurer.py +12 -9
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/executionresult.py +56 -8
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/flattenkeywordmatcher.py +48 -9
- robotframework-7.0/src/robot/result/keywordremover.py +207 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/merger.py +1 -1
- robotframework-7.0/src/robot/result/model.py +1185 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/modeldeprecation.py +9 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/resultbuilder.py +46 -36
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/xmlelementhandlers.py +83 -43
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/run.py +3 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/__init__.py +14 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/__init__.py +2 -1
- robotframework-7.0/src/robot/running/arguments/argumentconverter.py +100 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentmapper.py +26 -24
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentparser.py +85 -61
- robotframework-7.0/src/robot/running/arguments/argumentresolver.py +158 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentspec.py +83 -116
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentvalidator.py +33 -27
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/customconverters.py +15 -12
- robotframework-7.0/src/robot/running/arguments/embedded.py +145 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/typeconverters.py +268 -220
- 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.1rc1 → robotframework-7.0}/src/robot/running/bodyrunner.py +147 -129
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/builders.py +17 -26
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/parsers.py +17 -11
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/settings.py +9 -17
- robotframework-7.0/src/robot/running/builder/transformers.py +535 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/context.py +113 -31
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/dynamicmethods.py +62 -34
- {robotframework-6.1rc1 → 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.1rc1 → robotframework-7.0}/src/robot/running/model.py +198 -337
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/namespace.py +124 -137
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/outputcapture.py +20 -12
- robotframework-7.0/src/robot/running/resourcemodel.py +448 -0
- {robotframework-6.1rc1 → 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.1rc1 → robotframework-7.0}/src/robot/testdoc.py +18 -13
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/__init__.py +53 -35
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/connectioncache.py +64 -59
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/dotdict.py +3 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/encodingsniffer.py +9 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/escaping.py +19 -19
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/importer.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/markupwriters.py +23 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/misc.py +1 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/normalizing.py +9 -24
- robotframework-7.0/src/robot/utils/notset.py +33 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/platform.py +15 -5
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotio.py +9 -9
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotpath.py +1 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robottime.py +122 -90
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robottypes.py +21 -31
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/setter.py +0 -5
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/text.py +7 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/unic.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/__init__.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/assigner.py +17 -19
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/evaluation.py +20 -17
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/filesetter.py +80 -80
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/replacer.py +33 -36
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/scopes.py +17 -12
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/search.py +66 -41
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/store.py +14 -16
- robotframework-7.0/src/robot/variables/tablesetter.py +164 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/variables.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/version.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/PKG-INFO +6 -8
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/SOURCES.txt +10 -8
- {robotframework-6.1rc1 → robotframework-7.0}/tasks.py +6 -6
- robotframework-6.1rc1/src/robot/htmldata/rebot/common.css +0 -239
- robotframework-6.1rc1/src/robot/libraries/Reserved.py +0 -48
- robotframework-6.1rc1/src/robot/model/keyword.py +0 -173
- robotframework-6.1rc1/src/robot/output/console/dotted.py +0 -90
- robotframework-6.1rc1/src/robot/output/listenerarguments.py +0 -165
- robotframework-6.1rc1/src/robot/output/listenermethods.py +0 -113
- robotframework-6.1rc1/src/robot/output/listeners.py +0 -174
- robotframework-6.1rc1/src/robot/output/output.py +0 -95
- robotframework-6.1rc1/src/robot/output/xmllogger.py +0 -354
- robotframework-6.1rc1/src/robot/parsing/model/visitor.py +0 -67
- robotframework-6.1rc1/src/robot/result/keywordremover.py +0 -183
- robotframework-6.1rc1/src/robot/result/model.py +0 -957
- robotframework-6.1rc1/src/robot/running/arguments/argumentconverter.py +0 -79
- robotframework-6.1rc1/src/robot/running/arguments/argumentresolver.py +0 -131
- robotframework-6.1rc1/src/robot/running/arguments/embedded.py +0 -146
- robotframework-6.1rc1/src/robot/running/arguments/typevalidator.py +0 -56
- robotframework-6.1rc1/src/robot/running/builder/transformers.py +0 -642
- robotframework-6.1rc1/src/robot/running/handlers.py +0 -321
- robotframework-6.1rc1/src/robot/running/handlerstore.py +0 -66
- robotframework-6.1rc1/src/robot/running/librarykeywordrunner.py +0 -238
- robotframework-6.1rc1/src/robot/running/libraryscopes.py +0 -97
- robotframework-6.1rc1/src/robot/running/modelcombiner.py +0 -32
- robotframework-6.1rc1/src/robot/running/suiterunner.py +0 -249
- robotframework-6.1rc1/src/robot/running/testlibraries.py +0 -420
- robotframework-6.1rc1/src/robot/running/usererrorhandler.py +0 -75
- robotframework-6.1rc1/src/robot/running/userkeyword.py +0 -111
- robotframework-6.1rc1/src/robot/running/userkeywordrunner.py +0 -274
- robotframework-6.1rc1/src/robot/variables/tablesetter.py +0 -156
- {robotframework-6.1rc1 → robotframework-7.0}/AUTHORS.rst +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/BUILD.rst +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/CONTRIBUTING.rst +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/COPYRIGHT.txt +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/LICENSE.txt +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/MANIFEST.in +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/setup.cfg +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/__main__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/errors.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/common/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/common/js_disabled.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/jsonwriter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/doc_formatting.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/print.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/pygments.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/fileloading.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/log.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/print.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/util.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/testdoc/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.html +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdoc.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/consoleviewer.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/htmlwriter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/jsonwriter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/output.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/writer.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Dialogs.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Easter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Screenshot.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Telnet.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/fixture.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/metadata.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/statistics.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/suitestatistics.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/tagsetter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/tagstatistics.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/totalstatistics.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/highlighting.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/pyloggingconf.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/tokenizer.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/model/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/blockparsers.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/fileparser.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/parser.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/suitestructure.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/pythonpathsetter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jsexecutionresult.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jswriter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/executionerrors.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/messagefilter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/suiteteardownfailed.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/visitor.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/randomizer.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/runkwregister.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/signalhandler.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/status.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/timeouts/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/timeouts/posix.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/timeouts/windows.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/application.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/argumentparser.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/asserts.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/charwidth.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/compress.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/encoding.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/error.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/etreewrapper.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/filereader.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/frange.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/htmlformatters.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/markuputils.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/match.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/recommendations.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/restreader.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotenv.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotinspect.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/sortable.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/typehints.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/finders.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/notfound.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/resolvable.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/dependency_links.txt +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/entry_points.txt +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/top_level.txt +0 -0
|
@@ -17,6 +17,7 @@ import difflib
|
|
|
17
17
|
import re
|
|
18
18
|
import time
|
|
19
19
|
from collections import OrderedDict
|
|
20
|
+
from collections.abc import Sequence
|
|
20
21
|
|
|
21
22
|
from robot.api import logger, SkipExecution
|
|
22
23
|
from robot.api.deco import keyword
|
|
@@ -25,7 +26,6 @@ from robot.errors import (BreakLoop, ContinueLoop, DataError, ExecutionFailed,
|
|
|
25
26
|
ReturnFromKeyword, VariableError)
|
|
26
27
|
from robot.running import Keyword, RUN_KW_REGISTER
|
|
27
28
|
from robot.running.context import EXECUTION_CONTEXTS
|
|
28
|
-
from robot.running.usererrorhandler import UserErrorHandler
|
|
29
29
|
from robot.utils import (DotDict, escape, format_assign_message, get_error_message,
|
|
30
30
|
get_time, html_escape, is_falsy, is_integer, is_list_like,
|
|
31
31
|
is_string, is_truthy, Matcher, normalize,
|
|
@@ -36,7 +36,7 @@ from robot.utils import (DotDict, escape, format_assign_message, get_error_messa
|
|
|
36
36
|
from robot.utils.asserts import assert_equal, assert_not_equal
|
|
37
37
|
from robot.variables import (evaluate_expression, is_dict_variable,
|
|
38
38
|
is_list_variable, search_variable,
|
|
39
|
-
|
|
39
|
+
DictVariableResolver, VariableResolver)
|
|
40
40
|
from robot.version import get_version
|
|
41
41
|
|
|
42
42
|
|
|
@@ -153,8 +153,8 @@ class _Converter(_BuiltInBase):
|
|
|
153
153
|
return int(item, self._convert_to_integer(base))
|
|
154
154
|
return int(item)
|
|
155
155
|
except:
|
|
156
|
-
raise RuntimeError("'
|
|
157
|
-
|
|
156
|
+
raise RuntimeError(f"'{orig}' cannot be converted to an integer: "
|
|
157
|
+
f"{get_error_message()}")
|
|
158
158
|
|
|
159
159
|
def _get_base(self, item, base):
|
|
160
160
|
if not is_string(item):
|
|
@@ -300,8 +300,8 @@ class _Converter(_BuiltInBase):
|
|
|
300
300
|
try:
|
|
301
301
|
return float(self._convert_to_integer(item))
|
|
302
302
|
except RuntimeError:
|
|
303
|
-
raise RuntimeError("'
|
|
304
|
-
"point number:
|
|
303
|
+
raise RuntimeError(f"'{item}' cannot be converted to a floating "
|
|
304
|
+
f"point number: {error}")
|
|
305
305
|
|
|
306
306
|
def convert_to_string(self, item):
|
|
307
307
|
"""Converts the given item to a Unicode string.
|
|
@@ -380,12 +380,12 @@ class _Converter(_BuiltInBase):
|
|
|
380
380
|
"""
|
|
381
381
|
try:
|
|
382
382
|
try:
|
|
383
|
-
ordinals = getattr(self, '_get_ordinals_from_
|
|
383
|
+
ordinals = getattr(self, f'_get_ordinals_from_{input_type}')
|
|
384
384
|
except AttributeError:
|
|
385
|
-
raise RuntimeError("Invalid input type '
|
|
385
|
+
raise RuntimeError(f"Invalid input type '{input_type}'.")
|
|
386
386
|
return bytes(bytearray(o for o in ordinals(input)))
|
|
387
387
|
except:
|
|
388
|
-
raise RuntimeError("Creating bytes failed:
|
|
388
|
+
raise RuntimeError("Creating bytes failed: " + get_error_message())
|
|
389
389
|
|
|
390
390
|
def _get_ordinals_from_text(self, input):
|
|
391
391
|
for char in input:
|
|
@@ -395,8 +395,7 @@ class _Converter(_BuiltInBase):
|
|
|
395
395
|
def _test_ordinal(self, ordinal, original, type):
|
|
396
396
|
if 0 <= ordinal <= 255:
|
|
397
397
|
return ordinal
|
|
398
|
-
raise RuntimeError("
|
|
399
|
-
% (type, original))
|
|
398
|
+
raise RuntimeError(f"{type} '{original}' cannot be represented as a byte.")
|
|
400
399
|
|
|
401
400
|
def _get_ordinals_from_int(self, input):
|
|
402
401
|
if is_string(input):
|
|
@@ -422,7 +421,7 @@ class _Converter(_BuiltInBase):
|
|
|
422
421
|
return input
|
|
423
422
|
input = ''.join(input.split())
|
|
424
423
|
if len(input) % length != 0:
|
|
425
|
-
raise RuntimeError('Expected input to be multiple of
|
|
424
|
+
raise RuntimeError(f'Expected input to be multiple of {length}.')
|
|
426
425
|
return (input[i:i+length] for i in range(0, len(input), length))
|
|
427
426
|
|
|
428
427
|
def create_list(self, *items):
|
|
@@ -472,7 +471,7 @@ class _Converter(_BuiltInBase):
|
|
|
472
471
|
"""
|
|
473
472
|
separate, combined = self._split_dict_items(items)
|
|
474
473
|
result = DotDict(self._format_separate_dict_items(separate))
|
|
475
|
-
combined =
|
|
474
|
+
combined = DictVariableResolver(combined).resolve(self._variables)
|
|
476
475
|
result.update(combined)
|
|
477
476
|
return result
|
|
478
477
|
|
|
@@ -488,8 +487,8 @@ class _Converter(_BuiltInBase):
|
|
|
488
487
|
def _format_separate_dict_items(self, separate):
|
|
489
488
|
separate = self._variables.replace_list(separate)
|
|
490
489
|
if len(separate) % 2 != 0:
|
|
491
|
-
raise DataError('Expected even number of keys and values,
|
|
492
|
-
|
|
490
|
+
raise DataError(f'Expected even number of keys and values, '
|
|
491
|
+
f'got {len(separate)}.')
|
|
493
492
|
return [separate[i:i+2] for i in range(0, len(separate), 2)]
|
|
494
493
|
|
|
495
494
|
|
|
@@ -527,7 +526,7 @@ class _Verify(_BuiltInBase):
|
|
|
527
526
|
See `Fatal Error` if you need to stop the whole test execution.
|
|
528
527
|
"""
|
|
529
528
|
self._set_and_remove_tags(tags)
|
|
530
|
-
raise AssertionError(msg) if msg else AssertionError()
|
|
529
|
+
raise AssertionError(msg) if msg is not None else AssertionError()
|
|
531
530
|
|
|
532
531
|
def fatal_error(self, msg=None):
|
|
533
532
|
"""Stops the whole test execution.
|
|
@@ -549,7 +548,7 @@ class _Verify(_BuiltInBase):
|
|
|
549
548
|
and how ``msg`` can be used to override the default error message.
|
|
550
549
|
"""
|
|
551
550
|
if self._is_true(condition):
|
|
552
|
-
raise AssertionError(msg or "'
|
|
551
|
+
raise AssertionError(msg or f"'{condition}' should not be true.")
|
|
553
552
|
|
|
554
553
|
def should_be_true(self, condition, msg=None):
|
|
555
554
|
"""Fails if the given condition is not true.
|
|
@@ -580,7 +579,7 @@ class _Verify(_BuiltInBase):
|
|
|
580
579
|
| Should Be True | $status == 'PASS' | # Expected string must be quoted |
|
|
581
580
|
"""
|
|
582
581
|
if not self._is_true(condition):
|
|
583
|
-
raise AssertionError(msg or "'
|
|
582
|
+
raise AssertionError(msg or f"'{condition}' should be true.")
|
|
584
583
|
|
|
585
584
|
def should_be_equal(self, first, second, msg=None, values=True,
|
|
586
585
|
ignore_case=False, formatter='str', strip_spaces=False,
|
|
@@ -627,8 +626,8 @@ class _Verify(_BuiltInBase):
|
|
|
627
626
|
self._log_types_at_info_if_different(first, second)
|
|
628
627
|
if is_string(first) and is_string(second):
|
|
629
628
|
if ignore_case:
|
|
630
|
-
first = first.
|
|
631
|
-
second = second.
|
|
629
|
+
first = first.casefold()
|
|
630
|
+
second = second.casefold()
|
|
632
631
|
if strip_spaces:
|
|
633
632
|
first = self._strip_spaces(first, strip_spaces)
|
|
634
633
|
second = self._strip_spaces(second, strip_spaces)
|
|
@@ -655,14 +654,14 @@ class _Verify(_BuiltInBase):
|
|
|
655
654
|
second_lines = second.splitlines(True)
|
|
656
655
|
if len(first_lines) < 3 or len(second_lines) < 3:
|
|
657
656
|
return
|
|
658
|
-
self.log("
|
|
657
|
+
self.log(f"{first.rstrip()}\n\n!=\n\n{second.rstrip()}")
|
|
659
658
|
diffs = list(difflib.unified_diff(first_lines, second_lines,
|
|
660
659
|
fromfile='first', tofile='second',
|
|
661
660
|
lineterm=''))
|
|
662
661
|
diffs[3:] = [item[0] + formatter(item[1:]).rstrip() for item in diffs[3:]]
|
|
663
662
|
prefix = 'Multiline strings are different:'
|
|
664
663
|
if msg:
|
|
665
|
-
prefix = '
|
|
664
|
+
prefix = f'{msg}: {prefix}'
|
|
666
665
|
raise AssertionError('\n'.join([prefix] + diffs))
|
|
667
666
|
|
|
668
667
|
def _include_values(self, values):
|
|
@@ -709,8 +708,8 @@ class _Verify(_BuiltInBase):
|
|
|
709
708
|
self._log_types_at_info_if_different(first, second)
|
|
710
709
|
if is_string(first) and is_string(second):
|
|
711
710
|
if ignore_case:
|
|
712
|
-
first = first.
|
|
713
|
-
second = second.
|
|
711
|
+
first = first.casefold()
|
|
712
|
+
second = second.casefold()
|
|
714
713
|
if strip_spaces:
|
|
715
714
|
first = self._strip_spaces(first, strip_spaces)
|
|
716
715
|
second = self._strip_spaces(second, strip_spaces)
|
|
@@ -845,8 +844,8 @@ class _Verify(_BuiltInBase):
|
|
|
845
844
|
first = safe_str(first)
|
|
846
845
|
second = safe_str(second)
|
|
847
846
|
if ignore_case:
|
|
848
|
-
first = first.
|
|
849
|
-
second = second.
|
|
847
|
+
first = first.casefold()
|
|
848
|
+
second = second.casefold()
|
|
850
849
|
if strip_spaces:
|
|
851
850
|
first = self._strip_spaces(first, strip_spaces)
|
|
852
851
|
second = self._strip_spaces(second, strip_spaces)
|
|
@@ -886,8 +885,8 @@ class _Verify(_BuiltInBase):
|
|
|
886
885
|
first = safe_str(first)
|
|
887
886
|
second = safe_str(second)
|
|
888
887
|
if ignore_case:
|
|
889
|
-
first = first.
|
|
890
|
-
second = second.
|
|
888
|
+
first = first.casefold()
|
|
889
|
+
second = second.casefold()
|
|
891
890
|
if strip_spaces:
|
|
892
891
|
first = self._strip_spaces(first, strip_spaces)
|
|
893
892
|
second = self._strip_spaces(second, strip_spaces)
|
|
@@ -906,8 +905,8 @@ class _Verify(_BuiltInBase):
|
|
|
906
905
|
of the ``ignore_case``, ``strip_spaces``, and ``collapse_spaces`` options.
|
|
907
906
|
"""
|
|
908
907
|
if ignore_case:
|
|
909
|
-
str1 = str1.
|
|
910
|
-
str2 = str2.
|
|
908
|
+
str1 = str1.casefold()
|
|
909
|
+
str2 = str2.casefold()
|
|
911
910
|
if strip_spaces:
|
|
912
911
|
str1 = self._strip_spaces(str1, strip_spaces)
|
|
913
912
|
str2 = self._strip_spaces(str2, strip_spaces)
|
|
@@ -927,8 +926,8 @@ class _Verify(_BuiltInBase):
|
|
|
927
926
|
of the ``ignore_case``, ``strip_spaces``, and ``collapse_spaces`` options.
|
|
928
927
|
"""
|
|
929
928
|
if ignore_case:
|
|
930
|
-
str1 = str1.
|
|
931
|
-
str2 = str2.
|
|
929
|
+
str1 = str1.casefold()
|
|
930
|
+
str2 = str2.casefold()
|
|
932
931
|
if strip_spaces:
|
|
933
932
|
str1 = self._strip_spaces(str1, strip_spaces)
|
|
934
933
|
str2 = self._strip_spaces(str2, strip_spaces)
|
|
@@ -949,8 +948,8 @@ class _Verify(_BuiltInBase):
|
|
|
949
948
|
of the ``ignore_case``, ``strip_spaces``, and ``collapse_spaces`` options.
|
|
950
949
|
"""
|
|
951
950
|
if ignore_case:
|
|
952
|
-
str1 = str1.
|
|
953
|
-
str2 = str2.
|
|
951
|
+
str1 = str1.casefold()
|
|
952
|
+
str2 = str2.casefold()
|
|
954
953
|
if strip_spaces:
|
|
955
954
|
str1 = self._strip_spaces(str1, strip_spaces)
|
|
956
955
|
str2 = self._strip_spaces(str2, strip_spaces)
|
|
@@ -970,8 +969,8 @@ class _Verify(_BuiltInBase):
|
|
|
970
969
|
of the ``ignore_case``, ``strip_spaces``, and ``collapse_spaces`` options.
|
|
971
970
|
"""
|
|
972
971
|
if ignore_case:
|
|
973
|
-
str1 = str1.
|
|
974
|
-
str2 = str2.
|
|
972
|
+
str1 = str1.casefold()
|
|
973
|
+
str2 = str2.casefold()
|
|
975
974
|
if strip_spaces:
|
|
976
975
|
str1 = self._strip_spaces(str1, strip_spaces)
|
|
977
976
|
str2 = self._strip_spaces(str2, strip_spaces)
|
|
@@ -1018,11 +1017,11 @@ class _Verify(_BuiltInBase):
|
|
|
1018
1017
|
# case-insensitive comparisons.
|
|
1019
1018
|
orig_container = container
|
|
1020
1019
|
if ignore_case and is_string(item):
|
|
1021
|
-
item = item.
|
|
1020
|
+
item = item.casefold()
|
|
1022
1021
|
if is_string(container):
|
|
1023
|
-
container = container.
|
|
1022
|
+
container = container.casefold()
|
|
1024
1023
|
elif is_list_like(container):
|
|
1025
|
-
container = set(x.
|
|
1024
|
+
container = set(x.casefold() if is_string(x) else x for x in container)
|
|
1026
1025
|
if strip_spaces and is_string(item):
|
|
1027
1026
|
item = self._strip_spaces(item, strip_spaces)
|
|
1028
1027
|
if is_string(container):
|
|
@@ -1074,11 +1073,11 @@ class _Verify(_BuiltInBase):
|
|
|
1074
1073
|
"""
|
|
1075
1074
|
orig_container = container
|
|
1076
1075
|
if ignore_case and is_string(item):
|
|
1077
|
-
item = item.
|
|
1076
|
+
item = item.casefold()
|
|
1078
1077
|
if is_string(container):
|
|
1079
|
-
container = container.
|
|
1078
|
+
container = container.casefold()
|
|
1080
1079
|
elif is_list_like(container):
|
|
1081
|
-
container = set(x.
|
|
1080
|
+
container = set(x.casefold() if is_string(x) else x for x in container)
|
|
1082
1081
|
if strip_spaces and is_string(item):
|
|
1083
1082
|
item = self._strip_spaces(item, strip_spaces)
|
|
1084
1083
|
if is_string(container):
|
|
@@ -1123,17 +1122,17 @@ class _Verify(_BuiltInBase):
|
|
|
1123
1122
|
strip_spaces = configuration.pop('strip_spaces', False)
|
|
1124
1123
|
collapse_spaces = is_truthy(configuration.pop('collapse_spaces', False))
|
|
1125
1124
|
if configuration:
|
|
1126
|
-
raise RuntimeError("Unsupported configuration parameter
|
|
1127
|
-
|
|
1125
|
+
raise RuntimeError(f"Unsupported configuration parameter{s(configuration)}: "
|
|
1126
|
+
f"{seq2str(sorted(configuration))}.")
|
|
1128
1127
|
if not items:
|
|
1129
1128
|
raise RuntimeError('One or more items required.')
|
|
1130
1129
|
orig_container = container
|
|
1131
1130
|
if ignore_case:
|
|
1132
|
-
items = [x.
|
|
1131
|
+
items = [x.casefold() if is_string(x) else x for x in items]
|
|
1133
1132
|
if is_string(container):
|
|
1134
|
-
container = container.
|
|
1133
|
+
container = container.casefold()
|
|
1135
1134
|
elif is_list_like(container):
|
|
1136
|
-
container = set(x.
|
|
1135
|
+
container = set(x.casefold() if is_string(x) else x for x in container)
|
|
1137
1136
|
if strip_spaces:
|
|
1138
1137
|
items = [self._strip_spaces(x, strip_spaces) for x in items]
|
|
1139
1138
|
if is_string(container):
|
|
@@ -1181,17 +1180,17 @@ class _Verify(_BuiltInBase):
|
|
|
1181
1180
|
strip_spaces = configuration.pop('strip_spaces', False)
|
|
1182
1181
|
collapse_spaces = is_truthy(configuration.pop('collapse_spaces', False))
|
|
1183
1182
|
if configuration:
|
|
1184
|
-
raise RuntimeError("Unsupported configuration parameter
|
|
1185
|
-
|
|
1183
|
+
raise RuntimeError(f"Unsupported configuration parameter{s(configuration)}: "
|
|
1184
|
+
f"{seq2str(sorted(configuration))}.")
|
|
1186
1185
|
if not items:
|
|
1187
1186
|
raise RuntimeError('One or more items required.')
|
|
1188
1187
|
orig_container = container
|
|
1189
1188
|
if ignore_case:
|
|
1190
|
-
items = [x.
|
|
1189
|
+
items = [x.casefold() if is_string(x) else x for x in items]
|
|
1191
1190
|
if is_string(container):
|
|
1192
|
-
container = container.
|
|
1191
|
+
container = container.casefold()
|
|
1193
1192
|
elif is_list_like(container):
|
|
1194
|
-
container = set(x.
|
|
1193
|
+
container = set(x.casefold() if is_string(x) else x for x in container)
|
|
1195
1194
|
if strip_spaces:
|
|
1196
1195
|
items = [self._strip_spaces(x, strip_spaces) for x in items]
|
|
1197
1196
|
if is_string(container):
|
|
@@ -1247,11 +1246,11 @@ class _Verify(_BuiltInBase):
|
|
|
1247
1246
|
orig_container = container
|
|
1248
1247
|
if is_string(item):
|
|
1249
1248
|
if ignore_case:
|
|
1250
|
-
item = item.
|
|
1249
|
+
item = item.casefold()
|
|
1251
1250
|
if is_string(container):
|
|
1252
|
-
container = container.
|
|
1251
|
+
container = container.casefold()
|
|
1253
1252
|
elif is_list_like(container):
|
|
1254
|
-
container = [x.
|
|
1253
|
+
container = [x.casefold() if is_string(x) else x for x in container]
|
|
1255
1254
|
if strip_spaces:
|
|
1256
1255
|
item = self._strip_spaces(item, strip_spaces)
|
|
1257
1256
|
if is_string(container):
|
|
@@ -1266,8 +1265,8 @@ class _Verify(_BuiltInBase):
|
|
|
1266
1265
|
container = [self._collapse_spaces(x) for x in container]
|
|
1267
1266
|
x = self.get_count(container, item)
|
|
1268
1267
|
if not msg:
|
|
1269
|
-
msg = "
|
|
1270
|
-
|
|
1268
|
+
msg = (f"{orig_container!r} contains '{item}' {x} time{s(x)}, "
|
|
1269
|
+
f"not {count} time{s(count)}.")
|
|
1271
1270
|
self.should_be_equal_as_integers(x, count, msg, values=False)
|
|
1272
1271
|
|
|
1273
1272
|
def get_count(self, container, item):
|
|
@@ -1284,10 +1283,10 @@ class _Verify(_BuiltInBase):
|
|
|
1284
1283
|
try:
|
|
1285
1284
|
container = list(container)
|
|
1286
1285
|
except:
|
|
1287
|
-
raise RuntimeError("Converting '
|
|
1288
|
-
|
|
1286
|
+
raise RuntimeError(f"Converting '{container}' to list failed: "
|
|
1287
|
+
f"{get_error_message()}")
|
|
1289
1288
|
count = container.count(item)
|
|
1290
|
-
self.log('Item found from container
|
|
1289
|
+
self.log(f'Item found from container {count} time{s(count)}.')
|
|
1291
1290
|
return count
|
|
1292
1291
|
|
|
1293
1292
|
def should_not_match(self, string, pattern, msg=None, values=True,
|
|
@@ -1407,7 +1406,7 @@ class _Verify(_BuiltInBase):
|
|
|
1407
1406
|
Empty`.
|
|
1408
1407
|
"""
|
|
1409
1408
|
length = self._get_length(item)
|
|
1410
|
-
self.log('Length is
|
|
1409
|
+
self.log(f'Length is {length}.')
|
|
1411
1410
|
return length
|
|
1412
1411
|
|
|
1413
1412
|
def _get_length(self, item):
|
|
@@ -1431,7 +1430,7 @@ class _Verify(_BuiltInBase):
|
|
|
1431
1430
|
except RERAISED_EXCEPTIONS:
|
|
1432
1431
|
raise
|
|
1433
1432
|
except:
|
|
1434
|
-
raise RuntimeError("Could not get length of '
|
|
1433
|
+
raise RuntimeError(f"Could not get length of '{item}'.")
|
|
1435
1434
|
|
|
1436
1435
|
def length_should_be(self, item, length, msg=None):
|
|
1437
1436
|
"""Verifies that the length of the given item is correct.
|
|
@@ -1442,8 +1441,8 @@ class _Verify(_BuiltInBase):
|
|
|
1442
1441
|
length = self._convert_to_integer(length)
|
|
1443
1442
|
actual = self.get_length(item)
|
|
1444
1443
|
if actual != length:
|
|
1445
|
-
raise AssertionError(msg or "Length of '
|
|
1446
|
-
|
|
1444
|
+
raise AssertionError(msg or f"Length of '{item}' should be {length} "
|
|
1445
|
+
f"but is {actual}.")
|
|
1447
1446
|
|
|
1448
1447
|
def should_be_empty(self, item, msg=None):
|
|
1449
1448
|
"""Verifies that the given item is empty.
|
|
@@ -1452,7 +1451,7 @@ class _Verify(_BuiltInBase):
|
|
|
1452
1451
|
default error message can be overridden with the ``msg`` argument.
|
|
1453
1452
|
"""
|
|
1454
1453
|
if self.get_length(item) > 0:
|
|
1455
|
-
raise AssertionError(msg or "'
|
|
1454
|
+
raise AssertionError(msg or f"'{item}' should be empty.")
|
|
1456
1455
|
|
|
1457
1456
|
def should_not_be_empty(self, item, msg=None):
|
|
1458
1457
|
"""Verifies that the given item is not empty.
|
|
@@ -1461,18 +1460,18 @@ class _Verify(_BuiltInBase):
|
|
|
1461
1460
|
default error message can be overridden with the ``msg`` argument.
|
|
1462
1461
|
"""
|
|
1463
1462
|
if self.get_length(item) == 0:
|
|
1464
|
-
raise AssertionError(msg or "'
|
|
1463
|
+
raise AssertionError(msg or f"'{item}' should not be empty.")
|
|
1465
1464
|
|
|
1466
1465
|
def _get_string_msg(self, item1, item2, custom_message, include_values,
|
|
1467
1466
|
delimiter, quote_item1=True, quote_item2=True):
|
|
1468
1467
|
if custom_message and not self._include_values(include_values):
|
|
1469
1468
|
return custom_message
|
|
1470
|
-
item1 = "'
|
|
1471
|
-
item2 = "'
|
|
1472
|
-
default_message = '
|
|
1469
|
+
item1 = f"'{safe_str(item1)}'" if quote_item1 else safe_str(item1)
|
|
1470
|
+
item2 = f"'{safe_str(item2)}'" if quote_item2 else safe_str(item2)
|
|
1471
|
+
default_message = f'{item1} {delimiter} {item2}'
|
|
1473
1472
|
if not custom_message:
|
|
1474
1473
|
return default_message
|
|
1475
|
-
return '
|
|
1474
|
+
return f'{custom_message}: {default_message}'
|
|
1476
1475
|
|
|
1477
1476
|
|
|
1478
1477
|
class _Variables(_BuiltInBase):
|
|
@@ -1533,7 +1532,7 @@ class _Variables(_BuiltInBase):
|
|
|
1533
1532
|
def log_variables(self, level='INFO'):
|
|
1534
1533
|
"""Logs all variables in the current scope with given log level."""
|
|
1535
1534
|
variables = self.get_variables()
|
|
1536
|
-
for name in sorted(variables, key=lambda s: s[2:-1].
|
|
1535
|
+
for name in sorted(variables, key=lambda s: s[2:-1].casefold()):
|
|
1537
1536
|
name, value = self._get_logged_variable(name, variables)
|
|
1538
1537
|
msg = format_assign_message(name, value, cut_long=False)
|
|
1539
1538
|
self.log(msg, level)
|
|
@@ -1542,12 +1541,15 @@ class _Variables(_BuiltInBase):
|
|
|
1542
1541
|
value = variables[name]
|
|
1543
1542
|
try:
|
|
1544
1543
|
if name[0] == '@':
|
|
1545
|
-
|
|
1544
|
+
if isinstance(value, Sequence):
|
|
1545
|
+
value = list(value)
|
|
1546
|
+
else: # Don't consume iterables.
|
|
1547
|
+
name = '$' + name[1:]
|
|
1546
1548
|
if name[0] == '&':
|
|
1547
1549
|
value = OrderedDict(value)
|
|
1548
1550
|
except RERAISED_EXCEPTIONS:
|
|
1549
1551
|
raise
|
|
1550
|
-
except:
|
|
1552
|
+
except Exception:
|
|
1551
1553
|
name = '$' + name[1:]
|
|
1552
1554
|
return name, value
|
|
1553
1555
|
|
|
@@ -1569,7 +1571,7 @@ class _Variables(_BuiltInBase):
|
|
|
1569
1571
|
self._variables.replace_scalar(name)
|
|
1570
1572
|
except VariableError:
|
|
1571
1573
|
raise AssertionError(self._variables.replace_string(msg)
|
|
1572
|
-
if msg else "Variable '
|
|
1574
|
+
if msg else f"Variable '{name}' does not exist.")
|
|
1573
1575
|
|
|
1574
1576
|
@run_keyword_variant(resolve=0)
|
|
1575
1577
|
def variable_should_not_exist(self, name, msg=None):
|
|
@@ -1591,14 +1593,14 @@ class _Variables(_BuiltInBase):
|
|
|
1591
1593
|
pass
|
|
1592
1594
|
else:
|
|
1593
1595
|
raise AssertionError(self._variables.replace_string(msg)
|
|
1594
|
-
if msg else "Variable '
|
|
1596
|
+
if msg else f"Variable '{name}' exists.")
|
|
1595
1597
|
|
|
1596
1598
|
def replace_variables(self, text):
|
|
1597
1599
|
"""Replaces variables in the given text with their current values.
|
|
1598
1600
|
|
|
1599
1601
|
If the text contains undefined variables, this keyword fails.
|
|
1600
1602
|
If the given ``text`` contains only a single variable, its value is
|
|
1601
|
-
returned as-is and it can be any object. Otherwise this keyword
|
|
1603
|
+
returned as-is and it can be any object. Otherwise, this keyword
|
|
1602
1604
|
always returns a string.
|
|
1603
1605
|
|
|
1604
1606
|
Example:
|
|
@@ -1621,16 +1623,23 @@ class _Variables(_BuiltInBase):
|
|
|
1621
1623
|
It is recommended to use `Create List` when creating new lists.
|
|
1622
1624
|
|
|
1623
1625
|
Examples:
|
|
1624
|
-
| ${hi} =
|
|
1625
|
-
| ${hi2} =
|
|
1626
|
-
| ${var1}
|
|
1627
|
-
| @{list} =
|
|
1628
|
-
| ${item1}
|
|
1626
|
+
| ${hi} = Set Variable Hello, world!
|
|
1627
|
+
| ${hi2} = Set Variable I said: ${hi}
|
|
1628
|
+
| ${var1} ${var2} = Set Variable Hello world
|
|
1629
|
+
| @{list} = Set Variable ${list with some items}
|
|
1630
|
+
| ${item1} ${item2} = Set Variable ${list with 2 items}
|
|
1629
1631
|
|
|
1630
1632
|
Variables created with this keyword are available only in the
|
|
1631
1633
|
scope where they are created. See `Set Global Variable`,
|
|
1632
1634
|
`Set Test Variable` and `Set Suite Variable` for information on how to
|
|
1633
1635
|
set variables so that they are available also in a larger scope.
|
|
1636
|
+
|
|
1637
|
+
*NOTE:* The ``VAR`` syntax introduced in Robot Framework 7.0 is generally
|
|
1638
|
+
recommended over this keyword. The basic usage is shown below and the Robot
|
|
1639
|
+
Framework User Guide explains the syntax in detail.
|
|
1640
|
+
|
|
1641
|
+
| VAR ${hi} Hello, world!
|
|
1642
|
+
| VAR ${hi2} I said: ${hi}
|
|
1634
1643
|
"""
|
|
1635
1644
|
if len(values) == 0:
|
|
1636
1645
|
return ''
|
|
@@ -1670,10 +1679,13 @@ class _Variables(_BuiltInBase):
|
|
|
1670
1679
|
``${name}``.
|
|
1671
1680
|
|
|
1672
1681
|
See also `Set Global Variable` and `Set Test Variable`.
|
|
1682
|
+
|
|
1683
|
+
*NOTE:* The ``VAR`` syntax introduced in Robot Framework 7.0 is recommended
|
|
1684
|
+
over this keyword.
|
|
1673
1685
|
"""
|
|
1674
1686
|
name = self._get_var_name(name)
|
|
1675
1687
|
value = self._get_var_value(name, values)
|
|
1676
|
-
self._variables.
|
|
1688
|
+
self._variables.set_local(name, value)
|
|
1677
1689
|
self._log_set_variable(name, value)
|
|
1678
1690
|
|
|
1679
1691
|
@run_keyword_variant(resolve=0)
|
|
@@ -1696,6 +1708,9 @@ class _Variables(_BuiltInBase):
|
|
|
1696
1708
|
|
|
1697
1709
|
When creating automated tasks, not tests, it is possible to use `Set
|
|
1698
1710
|
Task Variable`. See also `Set Global Variable` and `Set Local Variable`.
|
|
1711
|
+
|
|
1712
|
+
*NOTE:* The ``VAR`` syntax introduced in Robot Framework 7.0 is recommended
|
|
1713
|
+
over this keyword.
|
|
1699
1714
|
"""
|
|
1700
1715
|
name = self._get_var_name(name)
|
|
1701
1716
|
value = self._get_var_value(name, values)
|
|
@@ -1708,6 +1723,9 @@ class _Variables(_BuiltInBase):
|
|
|
1708
1723
|
|
|
1709
1724
|
This is an alias for `Set Test Variable` that is more applicable when
|
|
1710
1725
|
creating tasks, not tests.
|
|
1726
|
+
|
|
1727
|
+
*NOTE:* The ``VAR`` syntax introduced in Robot Framework 7.0 is recommended
|
|
1728
|
+
over this keyword.
|
|
1711
1729
|
"""
|
|
1712
1730
|
self.set_test_variable(name, *values)
|
|
1713
1731
|
|
|
@@ -1760,6 +1778,14 @@ class _Variables(_BuiltInBase):
|
|
|
1760
1778
|
| Set Suite Variable &DICT &{EMPTY}
|
|
1761
1779
|
|
|
1762
1780
|
See also `Set Global Variable`, `Set Test Variable` and `Set Local Variable`.
|
|
1781
|
+
|
|
1782
|
+
*NOTE:* The ``VAR`` syntax introduced in Robot Framework 7.0 is recommended
|
|
1783
|
+
over this keyword. The basic usage is shown below and the Robot Framework
|
|
1784
|
+
User Guide explains the syntax in detail.
|
|
1785
|
+
|
|
1786
|
+
| VAR ${SCALAR} Hello, world! scope=SUITE
|
|
1787
|
+
| VAR @{LIST} First item Second item scope=SUITE
|
|
1788
|
+
| VAR &{DICT} key=value foo=bar scope=SUITE
|
|
1763
1789
|
"""
|
|
1764
1790
|
name = self._get_var_name(name)
|
|
1765
1791
|
if values and is_string(values[-1]) and values[-1].startswith('children='):
|
|
@@ -1793,6 +1819,9 @@ class _Variables(_BuiltInBase):
|
|
|
1793
1819
|
section for information why it is recommended to give the variable name
|
|
1794
1820
|
in escaped format like ``$name`` or ``\${name}`` instead of the normal
|
|
1795
1821
|
``${name}``.
|
|
1822
|
+
|
|
1823
|
+
*NOTE:* The ``VAR`` syntax introduced in Robot Framework 7.0 is recommended
|
|
1824
|
+
over this keyword.
|
|
1796
1825
|
"""
|
|
1797
1826
|
name = self._get_var_name(name)
|
|
1798
1827
|
value = self._get_var_value(name, values)
|
|
@@ -1814,7 +1843,7 @@ class _Variables(_BuiltInBase):
|
|
|
1814
1843
|
match.resolve_base(self._variables)
|
|
1815
1844
|
valid = match.is_assign() if require_assign else match.is_variable()
|
|
1816
1845
|
if not valid:
|
|
1817
|
-
raise DataError("Invalid variable name '
|
|
1846
|
+
raise DataError(f"Invalid variable name '{name}'.")
|
|
1818
1847
|
return str(match)
|
|
1819
1848
|
|
|
1820
1849
|
def _resolve_var_name(self, name):
|
|
@@ -1823,7 +1852,7 @@ class _Variables(_BuiltInBase):
|
|
|
1823
1852
|
if len(name) < 2 or name[0] not in '$@&':
|
|
1824
1853
|
raise ValueError
|
|
1825
1854
|
if name[1] != '{':
|
|
1826
|
-
name = '
|
|
1855
|
+
name = f'{name[0]}{{{name[1:]}}}'
|
|
1827
1856
|
match = search_variable(name, identifiers='$@&', ignore_errors=True)
|
|
1828
1857
|
match.resolve_base(self._variables)
|
|
1829
1858
|
if not match.is_assign():
|
|
@@ -1839,11 +1868,12 @@ class _Variables(_BuiltInBase):
|
|
|
1839
1868
|
# handling non-string values somehow. For details see
|
|
1840
1869
|
# https://github.com/robotframework/robotframework/issues/1919
|
|
1841
1870
|
if len(values) != 1 or is_list_variable(values[0]):
|
|
1842
|
-
raise DataError("Setting list value to scalar variable '
|
|
1843
|
-
"is not supported anymore. Create list "
|
|
1844
|
-
"
|
|
1871
|
+
raise DataError(f"Setting list value to scalar variable '{name}' "
|
|
1872
|
+
f"is not supported anymore. Create list variable "
|
|
1873
|
+
f"'@{name[1:]}' instead.")
|
|
1845
1874
|
return self._variables.replace_scalar(values[0])
|
|
1846
|
-
|
|
1875
|
+
resolver = VariableResolver.from_name_and_value(name, values)
|
|
1876
|
+
return resolver.resolve(self._variables)
|
|
1847
1877
|
|
|
1848
1878
|
def _log_set_variable(self, name, value):
|
|
1849
1879
|
self.log(format_assign_message(name, value))
|
|
@@ -1870,14 +1900,19 @@ class _RunKeyword(_BuiltInBase):
|
|
|
1870
1900
|
ctx = self._context
|
|
1871
1901
|
if not (ctx.dry_run or self._accepts_embedded_arguments(name, ctx)):
|
|
1872
1902
|
name, args = self._replace_variables_in_name([name] + list(args))
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1903
|
+
if ctx.steps:
|
|
1904
|
+
data, result = ctx.steps[-1]
|
|
1905
|
+
lineno = data.lineno
|
|
1906
|
+
else: # Called, typically by a listener, when no keyword started.
|
|
1907
|
+
data = lineno = None
|
|
1908
|
+
result = ctx.test or (ctx.suite.setup if not ctx.suite.has_tests
|
|
1909
|
+
else ctx.suite.teardown)
|
|
1910
|
+
kw = Keyword(name, args=args, parent=data, lineno=lineno)
|
|
1911
|
+
return kw.run(result, ctx)
|
|
1877
1912
|
|
|
1878
1913
|
def _accepts_embedded_arguments(self, name, ctx):
|
|
1879
1914
|
if '{' in name:
|
|
1880
|
-
runner = ctx.get_runner(name)
|
|
1915
|
+
runner = ctx.get_runner(name, recommend_on_failure=False)
|
|
1881
1916
|
return runner and hasattr(runner, 'embedded_args')
|
|
1882
1917
|
return False
|
|
1883
1918
|
|
|
@@ -2048,7 +2083,7 @@ class _RunKeyword(_BuiltInBase):
|
|
|
2048
2083
|
index = list(args).index(control_word)
|
|
2049
2084
|
branch = self._variables.replace_list(args[index+1:], required)
|
|
2050
2085
|
if len(branch) < required:
|
|
2051
|
-
raise DataError('
|
|
2086
|
+
raise DataError(f'{control_word} requires {required_error}.')
|
|
2052
2087
|
return args[:index], branch
|
|
2053
2088
|
|
|
2054
2089
|
@run_keyword_variant(resolve=1, dry_run=True)
|
|
@@ -2105,7 +2140,7 @@ class _RunKeyword(_BuiltInBase):
|
|
|
2105
2140
|
"""
|
|
2106
2141
|
status, message = self.run_keyword_and_ignore_error(name, *args)
|
|
2107
2142
|
if status == 'FAIL':
|
|
2108
|
-
logger.warn("Executing keyword '
|
|
2143
|
+
logger.warn(f"Executing keyword '{name}' failed:\n{message}")
|
|
2109
2144
|
return status, message
|
|
2110
2145
|
|
|
2111
2146
|
@run_keyword_variant(resolve=0, dry_run=True)
|
|
@@ -2206,11 +2241,9 @@ class _RunKeyword(_BuiltInBase):
|
|
|
2206
2241
|
raise
|
|
2207
2242
|
error = err.message
|
|
2208
2243
|
else:
|
|
2209
|
-
raise AssertionError("Expected error '
|
|
2210
|
-
% expected_error)
|
|
2244
|
+
raise AssertionError(f"Expected error '{expected_error}' did not occur.")
|
|
2211
2245
|
if not self._error_is_expected(error, expected_error):
|
|
2212
|
-
raise AssertionError("Expected error '
|
|
2213
|
-
% (expected_error, error))
|
|
2246
|
+
raise AssertionError(f"Expected error '{expected_error}' but got '{error}'.")
|
|
2214
2247
|
return error
|
|
2215
2248
|
|
|
2216
2249
|
def _error_is_expected(self, error, expected_error):
|
|
@@ -2218,7 +2251,7 @@ class _RunKeyword(_BuiltInBase):
|
|
|
2218
2251
|
matchers = {'GLOB': glob,
|
|
2219
2252
|
'EQUALS': lambda s, p: s == p,
|
|
2220
2253
|
'STARTS': lambda s, p: s.startswith(p),
|
|
2221
|
-
'REGEXP': lambda s, p: re.
|
|
2254
|
+
'REGEXP': lambda s, p: re.fullmatch(p, s) is not None}
|
|
2222
2255
|
prefixes = tuple(prefix + ':' for prefix in matchers)
|
|
2223
2256
|
if not expected_error.startswith(prefixes):
|
|
2224
2257
|
return glob(error, expected_error)
|
|
@@ -2287,21 +2320,20 @@ class _RunKeyword(_BuiltInBase):
|
|
|
2287
2320
|
|
|
2288
2321
|
def _keywords_repeated_by_count(self, count, name, args):
|
|
2289
2322
|
if count <= 0:
|
|
2290
|
-
self.log("Keyword '
|
|
2323
|
+
self.log(f"Keyword '{name}' repeated zero times.")
|
|
2291
2324
|
for i in range(count):
|
|
2292
|
-
self.log("Repeating keyword, round
|
|
2325
|
+
self.log(f"Repeating keyword, round {i+1}/{count}.")
|
|
2293
2326
|
yield name, args
|
|
2294
2327
|
|
|
2295
2328
|
def _keywords_repeated_by_timeout(self, timeout, name, args):
|
|
2296
2329
|
if timeout <= 0:
|
|
2297
|
-
self.log("Keyword '
|
|
2298
|
-
|
|
2330
|
+
self.log(f"Keyword '{name}' repeated zero times.")
|
|
2331
|
+
round = 0
|
|
2299
2332
|
maxtime = time.time() + timeout
|
|
2300
2333
|
while time.time() < maxtime:
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
secs_to_timestr(maxtime - time.time(), compact=True)))
|
|
2334
|
+
round += 1
|
|
2335
|
+
remaining = secs_to_timestr(maxtime - time.time(), compact=True)
|
|
2336
|
+
self.log(f"Repeating keyword, round {round}, {remaining} remaining.")
|
|
2305
2337
|
yield name, args
|
|
2306
2338
|
|
|
2307
2339
|
@run_keyword_variant(resolve=2, dry_run=True)
|
|
@@ -2320,7 +2352,7 @@ class _RunKeyword(_BuiltInBase):
|
|
|
2320
2352
|
``5 times``, ``10 x``). ``retry_interval`` must always be given in
|
|
2321
2353
|
Robot Framework's time format.
|
|
2322
2354
|
|
|
2323
|
-
By default ``retry_interval`` is the time to wait _after_ a keyword has
|
|
2355
|
+
By default, ``retry_interval`` is the time to wait _after_ a keyword has
|
|
2324
2356
|
failed. For example, if the first run takes 2 seconds and the retry
|
|
2325
2357
|
interval is 3 seconds, the second run starts 5 seconds after the first
|
|
2326
2358
|
run started. If ``retry_interval`` start with prefix ``strict:``, the
|
|
@@ -2344,7 +2376,7 @@ class _RunKeyword(_BuiltInBase):
|
|
|
2344
2376
|
Running the same keyword multiple times inside this keyword can create
|
|
2345
2377
|
lots of output and considerably increase the size of the generated
|
|
2346
2378
|
output files. It is possible to remove unnecessary keywords from
|
|
2347
|
-
the outputs using ``--
|
|
2379
|
+
the outputs using the ``--remove-keywords WUKS`` command line option.
|
|
2348
2380
|
|
|
2349
2381
|
Support for "strict" retry interval is new in Robot Framework 4.1.
|
|
2350
2382
|
"""
|
|
@@ -2354,11 +2386,11 @@ class _RunKeyword(_BuiltInBase):
|
|
|
2354
2386
|
except ValueError:
|
|
2355
2387
|
timeout = timestr_to_secs(retry)
|
|
2356
2388
|
maxtime = time.time() + timeout
|
|
2357
|
-
message = 'for
|
|
2389
|
+
message = f'for {secs_to_timestr(timeout)}'
|
|
2358
2390
|
else:
|
|
2359
2391
|
if count <= 0:
|
|
2360
|
-
raise ValueError('Retry count
|
|
2361
|
-
message = '
|
|
2392
|
+
raise ValueError(f'Retry count {count} is not positive.')
|
|
2393
|
+
message = f'{count} time{s(count)}'
|
|
2362
2394
|
if is_string(retry_interval) and normalize(retry_interval).startswith('strict:'):
|
|
2363
2395
|
retry_interval = retry_interval.split(':', 1)[1].strip()
|
|
2364
2396
|
strict_interval = True
|
|
@@ -2374,16 +2406,19 @@ class _RunKeyword(_BuiltInBase):
|
|
|
2374
2406
|
raise
|
|
2375
2407
|
count -= 1
|
|
2376
2408
|
if time.time() > maxtime > 0 or count == 0:
|
|
2377
|
-
|
|
2378
|
-
|
|
2409
|
+
name = self._variables.replace_scalar(name)
|
|
2410
|
+
raise AssertionError(f"Keyword '{name}' failed after retrying "
|
|
2411
|
+
f"{message}. The last error was: {err}")
|
|
2379
2412
|
finally:
|
|
2380
2413
|
if strict_interval:
|
|
2381
|
-
|
|
2382
|
-
sleep_time = retry_interval -
|
|
2414
|
+
execution_time = time.time() - start_time
|
|
2415
|
+
sleep_time = retry_interval - execution_time
|
|
2383
2416
|
if sleep_time < 0:
|
|
2384
|
-
logger.warn(
|
|
2385
|
-
|
|
2386
|
-
|
|
2417
|
+
logger.warn(
|
|
2418
|
+
f"Keyword execution time {secs_to_timestr(execution_time)} "
|
|
2419
|
+
f"is longer than retry interval "
|
|
2420
|
+
f"{secs_to_timestr(retry_interval)}."
|
|
2421
|
+
)
|
|
2387
2422
|
self._sleep_in_parts(sleep_time)
|
|
2388
2423
|
|
|
2389
2424
|
@run_keyword_variant(resolve=1)
|
|
@@ -2426,19 +2461,21 @@ class _RunKeyword(_BuiltInBase):
|
|
|
2426
2461
|
Use `Get Variable Value` if you need to set variables
|
|
2427
2462
|
dynamically based on whether a variable exist or not.
|
|
2428
2463
|
"""
|
|
2429
|
-
values =
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2464
|
+
values = list(values)
|
|
2465
|
+
while True:
|
|
2466
|
+
values = self._verify_values_for_set_variable_if(values)
|
|
2467
|
+
if self._is_true(condition):
|
|
2468
|
+
return self._variables.replace_scalar(values[0])
|
|
2469
|
+
if len(values) == 1:
|
|
2470
|
+
return None
|
|
2471
|
+
if len(values) == 2:
|
|
2472
|
+
return self._variables.replace_scalar(values[1])
|
|
2473
|
+
condition, *values = values[1:]
|
|
2474
|
+
condition = self._variables.replace_scalar(condition)
|
|
2475
|
+
|
|
2476
|
+
def _verify_values_for_set_variable_if(self, values):
|
|
2438
2477
|
if not values:
|
|
2439
|
-
|
|
2440
|
-
return [None]
|
|
2441
|
-
raise RuntimeError('At least one value is required')
|
|
2478
|
+
raise RuntimeError('At least one value is required.')
|
|
2442
2479
|
if is_list_variable(values[0]):
|
|
2443
2480
|
values[:1] = [escape(item) for item in self._variables[values[0]]]
|
|
2444
2481
|
return self._verify_values_for_set_variable_if(values)
|
|
@@ -2520,10 +2557,9 @@ class _RunKeyword(_BuiltInBase):
|
|
|
2520
2557
|
if suite.statistics.failed > 0:
|
|
2521
2558
|
return self.run_keyword(name, *args)
|
|
2522
2559
|
|
|
2523
|
-
def _get_suite_in_teardown(self,
|
|
2560
|
+
def _get_suite_in_teardown(self, kw):
|
|
2524
2561
|
if not self._context.in_suite_teardown:
|
|
2525
|
-
raise RuntimeError("Keyword '
|
|
2526
|
-
% kwname)
|
|
2562
|
+
raise RuntimeError(f"Keyword '{kw}' can only be used in suite teardown.")
|
|
2527
2563
|
return self._context.suite
|
|
2528
2564
|
|
|
2529
2565
|
|
|
@@ -2872,7 +2908,7 @@ class _Control(_BuiltInBase):
|
|
|
2872
2908
|
Passing execution in the middle of a test, setup or teardown should be
|
|
2873
2909
|
used with care. In the worst case it leads to tests that skip all the
|
|
2874
2910
|
parts that could actually uncover problems in the tested application.
|
|
2875
|
-
In cases where execution cannot continue
|
|
2911
|
+
In cases where execution cannot continue due to external factors,
|
|
2876
2912
|
it is often safer to fail the test case and make it non-critical.
|
|
2877
2913
|
"""
|
|
2878
2914
|
message = message.strip()
|
|
@@ -2880,7 +2916,7 @@ class _Control(_BuiltInBase):
|
|
|
2880
2916
|
raise RuntimeError('Message cannot be empty.')
|
|
2881
2917
|
self._set_and_remove_tags(tags)
|
|
2882
2918
|
log_message, level = self._get_logged_test_message_and_level(message)
|
|
2883
|
-
self.log('Execution passed with message:\n
|
|
2919
|
+
self.log(f'Execution passed with message:\n{log_message}', level)
|
|
2884
2920
|
raise PassExecution(message)
|
|
2885
2921
|
|
|
2886
2922
|
@run_keyword_variant(resolve=1)
|
|
@@ -2931,7 +2967,7 @@ class _Misc(_BuiltInBase):
|
|
|
2931
2967
|
if seconds < 0:
|
|
2932
2968
|
seconds = 0
|
|
2933
2969
|
self._sleep_in_parts(seconds)
|
|
2934
|
-
self.log('Slept
|
|
2970
|
+
self.log(f'Slept {secs_to_timestr(seconds)}.')
|
|
2935
2971
|
if reason:
|
|
2936
2972
|
self.log(reason)
|
|
2937
2973
|
|
|
@@ -3050,8 +3086,8 @@ class _Misc(_BuiltInBase):
|
|
|
3050
3086
|
'len': len,
|
|
3051
3087
|
'type': lambda x: type(x).__name__}[formatter.lower()]
|
|
3052
3088
|
except KeyError:
|
|
3053
|
-
raise ValueError("Invalid formatter '
|
|
3054
|
-
"'str', 'repr', 'ascii', 'len', and 'type'."
|
|
3089
|
+
raise ValueError(f"Invalid formatter '{formatter}'. Available "
|
|
3090
|
+
f"'str', 'repr', 'ascii', 'len', and 'type'.")
|
|
3055
3091
|
|
|
3056
3092
|
@run_keyword_variant(resolve=0)
|
|
3057
3093
|
def log_many(self, *messages):
|
|
@@ -3078,7 +3114,7 @@ class _Misc(_BuiltInBase):
|
|
|
3078
3114
|
yield item
|
|
3079
3115
|
elif match.is_dict_variable():
|
|
3080
3116
|
for name, value in value.items():
|
|
3081
|
-
yield '
|
|
3117
|
+
yield f'{name}={value}'
|
|
3082
3118
|
else:
|
|
3083
3119
|
yield value
|
|
3084
3120
|
|
|
@@ -3128,23 +3164,34 @@ class _Misc(_BuiltInBase):
|
|
|
3128
3164
|
pass
|
|
3129
3165
|
|
|
3130
3166
|
def set_log_level(self, level):
|
|
3131
|
-
"""Sets the log threshold to the specified level
|
|
3167
|
+
"""Sets the log threshold to the specified level.
|
|
3132
3168
|
|
|
3133
3169
|
Messages below the level will not logged. The default logging level is
|
|
3134
|
-
INFO, but it can be overridden with the command line option
|
|
3135
|
-
|
|
3170
|
+
INFO, but it can be overridden with the ``--loglevel`` command line option.
|
|
3171
|
+
The available levels are TRACE, DEBUG, INFO (default), WARN, ERROR and NONE
|
|
3172
|
+
(no logging).
|
|
3136
3173
|
|
|
3137
|
-
The
|
|
3138
|
-
|
|
3174
|
+
The old level is returned and can be used for setting the level back
|
|
3175
|
+
later. An alternative way to reset the level is using the dedicated
|
|
3176
|
+
`Reset Log Level` keyword.
|
|
3139
3177
|
"""
|
|
3140
|
-
|
|
3141
|
-
old = self._context.output.set_log_level(level)
|
|
3142
|
-
except DataError as err:
|
|
3143
|
-
raise RuntimeError(str(err))
|
|
3178
|
+
old = self._context.output.set_log_level(level)
|
|
3144
3179
|
self._namespace.variables.set_global('${LOG_LEVEL}', level.upper())
|
|
3145
|
-
self.log('Log level changed from
|
|
3180
|
+
self.log(f'Log level changed from {old} to {level.upper()}.', level='DEBUG')
|
|
3146
3181
|
return old
|
|
3147
3182
|
|
|
3183
|
+
def reset_log_level(self):
|
|
3184
|
+
"""Resets the log level to the original value.
|
|
3185
|
+
|
|
3186
|
+
The original log level is set from the command line with the ``--loglevel``
|
|
3187
|
+
option and is INFO by default. The active log level can be changed using
|
|
3188
|
+
the `Set Log Level` keyword.
|
|
3189
|
+
|
|
3190
|
+
New in Robot Framework 7.0.
|
|
3191
|
+
"""
|
|
3192
|
+
level = self._context.output.initial_log_level
|
|
3193
|
+
return self.set_log_level(level)
|
|
3194
|
+
|
|
3148
3195
|
def reload_library(self, name_or_instance):
|
|
3149
3196
|
"""Rechecks what keywords the specified library provides.
|
|
3150
3197
|
|
|
@@ -3155,9 +3202,8 @@ class _Misc(_BuiltInBase):
|
|
|
3155
3202
|
the library. The latter is especially useful if the library itself
|
|
3156
3203
|
calls this keyword as a method.
|
|
3157
3204
|
"""
|
|
3158
|
-
|
|
3159
|
-
self.log('Reloaded library
|
|
3160
|
-
len(library)))
|
|
3205
|
+
lib = self._namespace.reload_library(name_or_instance)
|
|
3206
|
+
self.log(f'Reloaded library {lib.name} with {len(lib.keywords)} keywords.')
|
|
3161
3207
|
|
|
3162
3208
|
@run_keyword_variant(resolve=0)
|
|
3163
3209
|
def import_library(self, name, *args):
|
|
@@ -3297,11 +3343,11 @@ class _Misc(_BuiltInBase):
|
|
|
3297
3343
|
See also `Variable Should Exist`.
|
|
3298
3344
|
"""
|
|
3299
3345
|
try:
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
raise AssertionError(msg or
|
|
3346
|
+
kw = self._namespace.get_runner(name, recommend_on_failure=False).keyword
|
|
3347
|
+
if kw.error:
|
|
3348
|
+
raise DataError(kw.error)
|
|
3349
|
+
except DataError as err:
|
|
3350
|
+
raise AssertionError(msg or err.message)
|
|
3305
3351
|
|
|
3306
3352
|
def get_time(self, format='timestamp', time_='NOW'):
|
|
3307
3353
|
"""Returns the given time in the requested format.
|
|
@@ -3523,7 +3569,7 @@ class _Misc(_BuiltInBase):
|
|
|
3523
3569
|
if self._context.in_test_teardown:
|
|
3524
3570
|
self._variables.set_test("${TEST_MESSAGE}", test.message)
|
|
3525
3571
|
message, level = self._get_logged_test_message_and_level(test.message)
|
|
3526
|
-
self.log('Set test message to:\n
|
|
3572
|
+
self.log(f'Set test message to:\n{message}', level)
|
|
3527
3573
|
|
|
3528
3574
|
def _get_new_text(self, old, new, append, handle_html=False):
|
|
3529
3575
|
if not is_string(new):
|
|
@@ -3534,10 +3580,10 @@ class _Misc(_BuiltInBase):
|
|
|
3534
3580
|
if new.startswith('*HTML*'):
|
|
3535
3581
|
new = new[6:].lstrip()
|
|
3536
3582
|
if not old.startswith('*HTML*'):
|
|
3537
|
-
old = '*HTML*
|
|
3583
|
+
old = f'*HTML* {html_escape(old)}'
|
|
3538
3584
|
elif old.startswith('*HTML*'):
|
|
3539
3585
|
new = html_escape(new)
|
|
3540
|
-
return '
|
|
3586
|
+
return f'{old} {new}'
|
|
3541
3587
|
|
|
3542
3588
|
def _get_logged_test_message_and_level(self, message):
|
|
3543
3589
|
if message.startswith('*HTML*'):
|
|
@@ -3561,12 +3607,12 @@ class _Misc(_BuiltInBase):
|
|
|
3561
3607
|
"used in suite setup or teardown.")
|
|
3562
3608
|
test.doc = self._get_new_text(test.doc, doc, append)
|
|
3563
3609
|
self._variables.set_test('${TEST_DOCUMENTATION}', test.doc)
|
|
3564
|
-
self.log('Set test documentation to:\n
|
|
3610
|
+
self.log(f'Set test documentation to:\n{test.doc}')
|
|
3565
3611
|
|
|
3566
3612
|
def set_suite_documentation(self, doc, append=False, top=False):
|
|
3567
3613
|
"""Sets documentation for the current test suite.
|
|
3568
3614
|
|
|
3569
|
-
By default the possible existing documentation is overwritten, but
|
|
3615
|
+
By default, the possible existing documentation is overwritten, but
|
|
3570
3616
|
this can be changed using the optional ``append`` argument similarly
|
|
3571
3617
|
as with `Set Test Message` keyword.
|
|
3572
3618
|
|
|
@@ -3581,12 +3627,12 @@ class _Misc(_BuiltInBase):
|
|
|
3581
3627
|
suite = self._get_context(top).suite
|
|
3582
3628
|
suite.doc = self._get_new_text(suite.doc, doc, append)
|
|
3583
3629
|
self._variables.set_suite('${SUITE_DOCUMENTATION}', suite.doc, top)
|
|
3584
|
-
self.log('Set suite documentation to:\n
|
|
3630
|
+
self.log(f'Set suite documentation to:\n{suite.doc}')
|
|
3585
3631
|
|
|
3586
3632
|
def set_suite_metadata(self, name, value, append=False, top=False):
|
|
3587
3633
|
"""Sets metadata for the current test suite.
|
|
3588
3634
|
|
|
3589
|
-
By default possible existing metadata values are overwritten, but
|
|
3635
|
+
By default, possible existing metadata values are overwritten, but
|
|
3590
3636
|
this can be changed using the optional ``append`` argument similarly
|
|
3591
3637
|
as with `Set Test Message` keyword.
|
|
3592
3638
|
|
|
@@ -3604,7 +3650,7 @@ class _Misc(_BuiltInBase):
|
|
|
3604
3650
|
original = metadata.get(name, '')
|
|
3605
3651
|
metadata[name] = self._get_new_text(original, value, append)
|
|
3606
3652
|
self._variables.set_suite('${SUITE_METADATA}', metadata.copy(), top)
|
|
3607
|
-
self.log("Set suite metadata '
|
|
3653
|
+
self.log(f"Set suite metadata '{name}' to value '{metadata[name]}'.")
|
|
3608
3654
|
|
|
3609
3655
|
def set_tags(self, *tags):
|
|
3610
3656
|
"""Adds given ``tags`` for the current test or all tests in a suite.
|
|
@@ -3629,7 +3675,7 @@ class _Misc(_BuiltInBase):
|
|
|
3629
3675
|
ctx.suite.set_tags(tags, persist=True)
|
|
3630
3676
|
else:
|
|
3631
3677
|
raise RuntimeError("'Set Tags' cannot be used in suite teardown.")
|
|
3632
|
-
self.log('Set tag
|
|
3678
|
+
self.log(f'Set tag{s(tags)} {seq2str((tags))}.')
|
|
3633
3679
|
|
|
3634
3680
|
def remove_tags(self, *tags):
|
|
3635
3681
|
"""Removes given ``tags`` from the current test or all tests in a suite.
|
|
@@ -3657,7 +3703,7 @@ class _Misc(_BuiltInBase):
|
|
|
3657
3703
|
ctx.suite.set_tags(remove=tags, persist=True)
|
|
3658
3704
|
else:
|
|
3659
3705
|
raise RuntimeError("'Remove Tags' cannot be used in suite teardown.")
|
|
3660
|
-
self.log('Removed tag
|
|
3706
|
+
self.log(f'Removed tag{s(tags)} {seq2str((tags))}.')
|
|
3661
3707
|
|
|
3662
3708
|
def get_library_instance(self, name=None, all=False):
|
|
3663
3709
|
"""Returns the currently active instance of the specified library.
|
|
@@ -3672,8 +3718,7 @@ class _Misc(_BuiltInBase):
|
|
|
3672
3718
|
| seleniumlib = BuiltIn().get_library_instance('SeleniumLibrary')
|
|
3673
3719
|
| title = seleniumlib.get_title()
|
|
3674
3720
|
| if not title.startswith(expected):
|
|
3675
|
-
| raise AssertionError("Title '
|
|
3676
|
-
| % (title, expected))
|
|
3721
|
+
| raise AssertionError(f"Title '{title}' did not start with '{expected}'.")
|
|
3677
3722
|
|
|
3678
3723
|
It is also possible to use this keyword in the test data and
|
|
3679
3724
|
pass the returned library instance to another keyword. If a
|
|
@@ -3716,40 +3761,6 @@ class BuiltIn(_Verify, _Converter, _Variables, _RunKeyword, _Control, _Misc):
|
|
|
3716
3761
|
HTML in messages is not limited to BuiltIn library but works with any
|
|
3717
3762
|
error message.
|
|
3718
3763
|
|
|
3719
|
-
= Using variables with keywords creating or accessing variables =
|
|
3720
|
-
|
|
3721
|
-
This library has special keywords `Set Global Variable`, `Set Suite Variable`,
|
|
3722
|
-
`Set Test Variable` and `Set Local Variable` for creating variables in
|
|
3723
|
-
different scopes. These keywords take the variable name and its value as
|
|
3724
|
-
arguments. The name can be given using the normal ``${variable}`` syntax or
|
|
3725
|
-
in escaped format either like ``$variable`` or ``\${variable}``. For example,
|
|
3726
|
-
these are typically equivalent and create new suite level variable
|
|
3727
|
-
``${name}`` with value ``value``:
|
|
3728
|
-
|
|
3729
|
-
| Set Suite Variable ${name} value
|
|
3730
|
-
| Set Suite Variable $name value
|
|
3731
|
-
| Set Suite Variable \${name} value
|
|
3732
|
-
|
|
3733
|
-
A problem with using the normal ``${variable}`` syntax is that these
|
|
3734
|
-
keywords cannot easily know is the idea to create a variable with exactly
|
|
3735
|
-
that name or does that variable actually contain the name of the variable
|
|
3736
|
-
to create. If the variable does not initially exist, it will always be
|
|
3737
|
-
created. If it exists and its value is a variable name either in the normal
|
|
3738
|
-
or in the escaped syntax, variable with _that_ name is created instead.
|
|
3739
|
-
For example, if ``${name}`` variable would exist and contain value
|
|
3740
|
-
``$example``, these examples would create different variables:
|
|
3741
|
-
|
|
3742
|
-
| Set Suite Variable ${name} value # Creates ${example}.
|
|
3743
|
-
| Set Suite Variable $name value # Creates ${name}.
|
|
3744
|
-
| Set Suite Variable \${name} value # Creates ${name}.
|
|
3745
|
-
|
|
3746
|
-
Because the behavior when using the normal ``${variable}`` syntax depends
|
|
3747
|
-
on the possible existing value of the variable, it is *highly recommended
|
|
3748
|
-
to use the escaped ``$variable`` or ``\${variable}`` format instead*.
|
|
3749
|
-
|
|
3750
|
-
This same problem occurs also with special keywords for accessing variables
|
|
3751
|
-
`Get Variable Value`, `Variable Should Exist` and `Variable Should Not Exist`.
|
|
3752
|
-
|
|
3753
3764
|
= Evaluating expressions =
|
|
3754
3765
|
|
|
3755
3766
|
Many keywords, such as `Evaluate`, `Run Keyword If` and `Should Be True`,
|
|
@@ -3814,6 +3825,45 @@ class BuiltIn(_Verify, _Converter, _Variables, _RunKeyword, _Control, _Misc):
|
|
|
3814
3825
|
to move the logic into a library. That eases maintenance and can also
|
|
3815
3826
|
enhance execution speed.
|
|
3816
3827
|
|
|
3828
|
+
= Using variables with keywords creating or accessing variables =
|
|
3829
|
+
|
|
3830
|
+
This library has special keywords `Set Global Variable`, `Set Suite Variable`,
|
|
3831
|
+
`Set Test Variable` and `Set Local Variable` for creating variables in
|
|
3832
|
+
different scopes. These keywords take the variable name and its value as
|
|
3833
|
+
arguments. The name can be given using the normal ``${variable}`` syntax or
|
|
3834
|
+
in escaped format either like ``$variable`` or ``\${variable}``. For example,
|
|
3835
|
+
these are typically equivalent and create new suite level variable
|
|
3836
|
+
``${name}`` with value ``value``:
|
|
3837
|
+
|
|
3838
|
+
| Set Suite Variable ${name} value
|
|
3839
|
+
| Set Suite Variable $name value
|
|
3840
|
+
| Set Suite Variable \${name} value
|
|
3841
|
+
|
|
3842
|
+
A problem with using the normal ``${variable}`` syntax is that these
|
|
3843
|
+
keywords cannot easily know is the idea to create a variable with exactly
|
|
3844
|
+
that name or does that variable actually contain the name of the variable
|
|
3845
|
+
to create. If the variable does not initially exist, it will always be
|
|
3846
|
+
created. If it exists and its value is a variable name either in the normal
|
|
3847
|
+
or in the escaped syntax, variable with _that_ name is created instead.
|
|
3848
|
+
For example, if ``${name}`` variable would exist and contain value
|
|
3849
|
+
``$example``, these examples would create different variables:
|
|
3850
|
+
|
|
3851
|
+
| Set Suite Variable ${name} value # Creates ${example}.
|
|
3852
|
+
| Set Suite Variable $name value # Creates ${name}.
|
|
3853
|
+
| Set Suite Variable \${name} value # Creates ${name}.
|
|
3854
|
+
|
|
3855
|
+
Because the behavior when using the normal ``${variable}`` syntax depends
|
|
3856
|
+
on the possible existing value of the variable, it is *highly recommended
|
|
3857
|
+
to use the escaped ``$variable`` or ``\${variable}`` format instead*.
|
|
3858
|
+
|
|
3859
|
+
This same problem occurs also with special keywords for accessing variables
|
|
3860
|
+
`Get Variable Value`, `Variable Should Exist` and `Variable Should Not Exist`.
|
|
3861
|
+
|
|
3862
|
+
*NOTE:* It is recommended to use the ``VAR`` syntax introduced in Robot
|
|
3863
|
+
Framework 7.0 for creating variables in different scopes instead of the
|
|
3864
|
+
`Set Global/Suite/Test/Local Variable` keywords. It makes creating variables
|
|
3865
|
+
uniform and avoids all the problems discussed above.
|
|
3866
|
+
|
|
3817
3867
|
= Boolean arguments =
|
|
3818
3868
|
|
|
3819
3869
|
Some keywords accept arguments that are handled as Boolean values true or
|