robotframework 7.1rc2__zip → 7.2b1__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-7.1rc2 → robotframework-7.2b1}/BUILD.rst +7 -7
- {robotframework-7.1rc2 → robotframework-7.2b1}/PKG-INFO +2 -2
- {robotframework-7.1rc2 → robotframework-7.2b1}/setup.py +1 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/__init__.py +33 -9
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/deco.py +8 -6
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/interfaces.py +66 -15
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/parsing.py +72 -68
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/conf/languages.py +4 -3
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/conf/settings.py +11 -10
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/errors.py +3 -3
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/htmlfilewriter.py +3 -0
- robotframework-7.2b1/src/robot/htmldata/libdoc/libdoc.html +408 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/log.html +1 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/report.html +1 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/testdata.js +1 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/template.py +0 -2
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdoc.py +19 -11
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/htmlwriter.py +7 -4
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/model.py +7 -5
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/writer.py +2 -2
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/BuiltIn.py +121 -32
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Collections.py +20 -7
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/__init__.py +3 -3
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/body.py +48 -57
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/control.py +35 -4
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/message.py +13 -8
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/modelobject.py +26 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/statistics.py +13 -9
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/stats.py +12 -14
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/suitestatistics.py +8 -9
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/tags.py +10 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/tagstatistics.py +7 -8
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/testcase.py +1 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/testsuite.py +1 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/totalstatistics.py +14 -21
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/visitor.py +29 -3
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/__init__.py +3 -2
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/console/dotted.py +6 -3
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/console/highlighting.py +18 -10
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/debugfile.py +3 -3
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/filelogger.py +7 -3
- robotframework-7.2b1/src/robot/output/jsonlogger.py +338 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/librarylogger.py +12 -11
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/listeners.py +49 -47
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/logger.py +33 -20
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/loggerapi.py +6 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/loggerhelper.py +29 -57
- robotframework-7.2b1/src/robot/output/loglevel.py +54 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/output.py +21 -17
- robotframework-7.2b1/src/robot/output/outputfile.py +174 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/pyloggingconf.py +2 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/xmllogger.py +40 -169
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/blocklexers.py +25 -12
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/statementlexers.py +16 -7
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/tokens.py +2 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/model/__init__.py +1 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/model/blocks.py +34 -2
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/model/statements.py +32 -2
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/parser/blockparsers.py +7 -2
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/rebot.py +10 -2
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/jsmodelbuilders.py +1 -1
- robotframework-7.2b1/src/robot/reporting/outputwriter.py +30 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/__init__.py +1 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/executionerrors.py +9 -9
- robotframework-7.2b1/src/robot/result/executionresult.py +331 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/messagefilter.py +14 -10
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/model.py +90 -18
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/resultbuilder.py +2 -5
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/xmlelementhandlers.py +20 -9
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/run.py +18 -6
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/__init__.py +1 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/embedded.py +7 -6
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/typeconverters.py +14 -2
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/typeinfo.py +23 -4
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/bodyrunner.py +41 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/builder/settings.py +2 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/builder/transformers.py +46 -20
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/context.py +22 -11
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/librarykeyword.py +1 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/librarykeywordrunner.py +29 -23
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/model.py +31 -4
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/outputcapture.py +2 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/signalhandler.py +7 -3
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/status.py +49 -38
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/statusreporter.py +1 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/suiterunner.py +22 -15
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/userkeywordrunner.py +4 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/importer.py +39 -23
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/unic.py +7 -8
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/evaluation.py +21 -2
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/replacer.py +20 -24
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/scopes.py +19 -9
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/variables.py +4 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/version.py +1 -1
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robotframework.egg-info/PKG-INFO +2 -2
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robotframework.egg-info/SOURCES.txt +3 -4
- robotframework-7.1rc2/src/robot/htmldata/libdoc/doc_formatting.css +0 -74
- robotframework-7.1rc2/src/robot/htmldata/libdoc/libdoc.css +0 -747
- robotframework-7.1rc2/src/robot/htmldata/libdoc/libdoc.html +0 -702
- robotframework-7.1rc2/src/robot/htmldata/libdoc/print.css +0 -11
- robotframework-7.1rc2/src/robot/htmldata/libdoc/pygments.css +0 -162
- robotframework-7.1rc2/src/robot/reporting/outputwriter.py +0 -48
- robotframework-7.1rc2/src/robot/result/executionresult.py +0 -201
- {robotframework-7.1rc2 → robotframework-7.2b1}/AUTHORS.rst +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/CONTRIBUTING.rst +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/COPYRIGHT.txt +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/INSTALL.rst +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/LICENSE.txt +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/MANIFEST.in +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/README.rst +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/setup.cfg +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/__main__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/exceptions.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/logger.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/api/py.typed +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/conf/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/conf/gatherfailed.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/common/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/common/js_disabled.css +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/common/storage.js +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/jsonwriter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/lib/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/lib/jquery.min.js +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/libdoc/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/common.css +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/doc_formatting.css +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/fileloading.js +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/log.css +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/log.js +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/model.js +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/print.css +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/report.css +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/util.js +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/rebot/view.js +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/testdoc/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/testdoc/testdoc.css +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/htmldata/testdoc/testdoc.html +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/builder.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/consoleviewer.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/datatypes.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/htmlutils.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/jsonbuilder.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/jsonwriter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/output.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/robotbuilder.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/standardtypes.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/xmlbuilder.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libdocpkg/xmlwriter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/DateTime.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Dialogs.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Easter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/OperatingSystem.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Process.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Remote.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Screenshot.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/String.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/Telnet.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/XML.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/libraries/dialogs_py.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/configurer.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/filter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/fixture.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/itemlist.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/keyword.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/metadata.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/modifier.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/namepatterns.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/model/tagsetter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/console/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/console/quiet.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/console/verbose.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/output/stdoutlogsplitter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/context.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/lexer.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/settings.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/lexer/tokenizer.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/model/visitor.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/parser/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/parser/fileparser.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/parser/parser.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/parsing/suitestructure.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/pythonpathsetter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/expandkeywordmatcher.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/jsbuildingcontext.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/jsexecutionresult.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/jswriter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/logreportwriters.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/resultwriter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/stringcache.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/reporting/xunitwriter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/configurer.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/flattenkeywordmatcher.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/keywordremover.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/merger.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/modeldeprecation.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/suiteteardownfailed.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/result/visitor.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/argumentconverter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/argumentmapper.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/argumentparser.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/argumentresolver.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/argumentspec.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/argumentvalidator.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/customconverters.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/typeinfoparser.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/arguments/typevalidator.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/builder/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/builder/builders.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/builder/parsers.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/dynamicmethods.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/importer.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/invalidkeyword.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/keywordfinder.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/keywordimplementation.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/libraryscopes.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/namespace.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/randomizer.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/resourcemodel.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/runkwregister.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/testlibraries.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/timeouts/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/timeouts/nosupport.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/timeouts/posix.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/running/timeouts/windows.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/testdoc.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/application.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/argumentparser.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/asserts.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/charwidth.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/compress.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/connectioncache.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/dotdict.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/encoding.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/encodingsniffer.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/error.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/escaping.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/etreewrapper.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/filereader.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/frange.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/htmlformatters.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/markuputils.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/markupwriters.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/match.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/misc.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/normalizing.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/notset.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/platform.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/recommendations.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/restreader.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/robotenv.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/robotinspect.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/robotio.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/robotpath.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/robottime.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/robottypes.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/setter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/sortable.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/text.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/utils/typehints.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/__init__.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/assigner.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/filesetter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/finders.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/notfound.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/resolvable.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/search.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/store.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robot/variables/tablesetter.py +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robotframework.egg-info/dependency_links.txt +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robotframework.egg-info/entry_points.txt +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/src/robotframework.egg-info/top_level.txt +0 -0
- {robotframework-7.1rc2 → robotframework-7.2b1}/tasks.py +0 -0
|
@@ -19,7 +19,7 @@ from robot.parsing import File, ModelVisitor, Token
|
|
|
19
19
|
from robot.utils import NormalizedDict
|
|
20
20
|
from robot.variables import VariableMatches
|
|
21
21
|
|
|
22
|
-
from ..model import For, If, IfBranch, TestSuite, TestCase, Try, TryBranch, While
|
|
22
|
+
from ..model import For, Group, If, IfBranch, TestSuite, TestCase, Try, TryBranch, While
|
|
23
23
|
from ..resourcemodel import ResourceFile, UserKeyword
|
|
24
24
|
from .settings import FileSettings
|
|
25
25
|
|
|
@@ -62,6 +62,15 @@ class SettingsBuilder(ModelVisitor):
|
|
|
62
62
|
self.settings.default_tags = node.values
|
|
63
63
|
|
|
64
64
|
def visit_TestTags(self, node):
|
|
65
|
+
for tag in node.values:
|
|
66
|
+
if tag.startswith('-'):
|
|
67
|
+
LOGGER.warn(
|
|
68
|
+
f"Error in file '{self.suite.source}' on line {node.lineno}: "
|
|
69
|
+
f"Setting tags starting with a hyphen like '{tag}' using the "
|
|
70
|
+
f"'Test Tags' setting is deprecated. In Robot Framework 8.0 this "
|
|
71
|
+
f"syntax will be used for removing tags. Escape the tag like "
|
|
72
|
+
f"'\\{tag}' to use the literal value and to avoid this warning."
|
|
73
|
+
)
|
|
65
74
|
self.settings.test_tags = node.values
|
|
66
75
|
|
|
67
76
|
def visit_KeywordTags(self, node):
|
|
@@ -167,7 +176,7 @@ class ResourceBuilder(ModelVisitor):
|
|
|
167
176
|
|
|
168
177
|
class BodyBuilder(ModelVisitor):
|
|
169
178
|
|
|
170
|
-
def __init__(self, model: 'TestCase|UserKeyword|For|If|Try|While|None' = None):
|
|
179
|
+
def __init__(self, model: 'TestCase|UserKeyword|For|If|Try|While|Group|None' = None):
|
|
171
180
|
self.model = model
|
|
172
181
|
|
|
173
182
|
def visit_For(self, node):
|
|
@@ -176,6 +185,9 @@ class BodyBuilder(ModelVisitor):
|
|
|
176
185
|
def visit_While(self, node):
|
|
177
186
|
WhileBuilder(self.model).build(node)
|
|
178
187
|
|
|
188
|
+
def visit_Group(self, node):
|
|
189
|
+
GroupBuilder(self.model).build(node)
|
|
190
|
+
|
|
179
191
|
def visit_If(self, node):
|
|
180
192
|
IfBuilder(self.model).build(node)
|
|
181
193
|
|
|
@@ -240,7 +252,7 @@ class TestCaseBuilder(BodyBuilder):
|
|
|
240
252
|
|
|
241
253
|
def _set_template(self, parent, template):
|
|
242
254
|
for item in parent.body:
|
|
243
|
-
if item.type
|
|
255
|
+
if item.type in (item.FOR, item.GROUP):
|
|
244
256
|
self._set_template(item, template)
|
|
245
257
|
elif item.type == item.IF_ELSE_ROOT:
|
|
246
258
|
for branch in item.body:
|
|
@@ -365,7 +377,7 @@ class KeywordBuilder(BodyBuilder):
|
|
|
365
377
|
class ForBuilder(BodyBuilder):
|
|
366
378
|
model: For
|
|
367
379
|
|
|
368
|
-
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While'):
|
|
380
|
+
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While|Group'):
|
|
369
381
|
super().__init__(parent.body.create_for())
|
|
370
382
|
|
|
371
383
|
def build(self, node):
|
|
@@ -387,7 +399,7 @@ class ForBuilder(BodyBuilder):
|
|
|
387
399
|
class IfBuilder(BodyBuilder):
|
|
388
400
|
model: 'IfBranch|None'
|
|
389
401
|
|
|
390
|
-
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While'):
|
|
402
|
+
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While|Group'):
|
|
391
403
|
super().__init__()
|
|
392
404
|
self.root = parent.body.create_if()
|
|
393
405
|
|
|
@@ -427,14 +439,13 @@ class IfBuilder(BodyBuilder):
|
|
|
427
439
|
class TryBuilder(BodyBuilder):
|
|
428
440
|
model: 'TryBranch|None'
|
|
429
441
|
|
|
430
|
-
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While'):
|
|
442
|
+
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While|Group'):
|
|
431
443
|
super().__init__()
|
|
432
444
|
self.root = parent.body.create_try()
|
|
433
|
-
self.template_error = None
|
|
434
445
|
|
|
435
446
|
def build(self, node):
|
|
436
|
-
self.root.config(lineno=node.lineno
|
|
437
|
-
|
|
447
|
+
self.root.config(lineno=node.lineno,
|
|
448
|
+
error=format_error(self._get_errors(node)))
|
|
438
449
|
while node:
|
|
439
450
|
self.model = self.root.body.create_branch(node.type, node.patterns,
|
|
440
451
|
node.pattern_type, node.assign,
|
|
@@ -442,10 +453,6 @@ class TryBuilder(BodyBuilder):
|
|
|
442
453
|
for step in node.body:
|
|
443
454
|
self.visit(step)
|
|
444
455
|
node = node.next
|
|
445
|
-
if self.template_error:
|
|
446
|
-
errors += (self.template_error,)
|
|
447
|
-
if errors:
|
|
448
|
-
self.root.error = format_error(errors)
|
|
449
456
|
return self.root
|
|
450
457
|
|
|
451
458
|
def _get_errors(self, node):
|
|
@@ -456,21 +463,40 @@ class TryBuilder(BodyBuilder):
|
|
|
456
463
|
errors += node.end.errors
|
|
457
464
|
return errors
|
|
458
465
|
|
|
459
|
-
def visit_TemplateArguments(self, node):
|
|
460
|
-
self.template_error = 'Templates cannot be used with TRY.'
|
|
461
|
-
|
|
462
466
|
|
|
463
467
|
class WhileBuilder(BodyBuilder):
|
|
464
468
|
model: While
|
|
465
469
|
|
|
466
|
-
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While'):
|
|
470
|
+
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While|Group'):
|
|
467
471
|
super().__init__(parent.body.create_while())
|
|
468
472
|
|
|
473
|
+
def build(self, node):
|
|
474
|
+
self.model.config(condition=node.condition,
|
|
475
|
+
limit=node.limit,
|
|
476
|
+
on_limit=node.on_limit,
|
|
477
|
+
on_limit_message=node.on_limit_message,
|
|
478
|
+
lineno=node.lineno,
|
|
479
|
+
error=format_error(self._get_errors(node)))
|
|
480
|
+
for step in node.body:
|
|
481
|
+
self.visit(step)
|
|
482
|
+
return self.model
|
|
483
|
+
|
|
484
|
+
def _get_errors(self, node):
|
|
485
|
+
errors = node.header.errors + node.errors
|
|
486
|
+
if node.end:
|
|
487
|
+
errors += node.end.errors
|
|
488
|
+
return errors
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
class GroupBuilder(BodyBuilder):
|
|
492
|
+
model: Group
|
|
493
|
+
|
|
494
|
+
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While|Group'):
|
|
495
|
+
super().__init__(parent.body.create_group())
|
|
496
|
+
|
|
469
497
|
def build(self, node):
|
|
470
498
|
error = format_error(self._get_errors(node))
|
|
471
|
-
self.model.config(
|
|
472
|
-
on_limit=node.on_limit, on_limit_message=node.on_limit_message,
|
|
473
|
-
lineno=node.lineno, error=error)
|
|
499
|
+
self.model.config(name=node.name, lineno=node.lineno, error=error)
|
|
474
500
|
for step in node.body:
|
|
475
501
|
self.visit(step)
|
|
476
502
|
return self.model
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
-
import inspect
|
|
17
16
|
import asyncio
|
|
17
|
+
import inspect
|
|
18
|
+
import sys
|
|
18
19
|
from contextlib import contextmanager
|
|
19
20
|
|
|
20
21
|
from robot.errors import DataError, ExecutionFailed
|
|
@@ -95,7 +96,6 @@ EXECUTION_CONTEXTS = ExecutionContexts()
|
|
|
95
96
|
|
|
96
97
|
|
|
97
98
|
class _ExecutionContext:
|
|
98
|
-
_started_keywords_threshold = 100
|
|
99
99
|
|
|
100
100
|
def __init__(self, suite, namespace, output, dry_run=False, asynchronous=None):
|
|
101
101
|
self.suite = suite
|
|
@@ -180,8 +180,11 @@ class _ExecutionContext:
|
|
|
180
180
|
return self.namespace.variables
|
|
181
181
|
|
|
182
182
|
def continue_on_failure(self, default=False):
|
|
183
|
-
parents =
|
|
184
|
-
|
|
183
|
+
parents = [result for _, result, implementation in reversed(self.steps)
|
|
184
|
+
if implementation and implementation.type == 'USER KEYWORD']
|
|
185
|
+
if self.test:
|
|
186
|
+
parents.append(self.test)
|
|
187
|
+
for index, parent in enumerate(parents):
|
|
185
188
|
robot = parent.tags.robot
|
|
186
189
|
if index == 0 and robot('stop-on-failure'):
|
|
187
190
|
return False
|
|
@@ -195,10 +198,10 @@ class _ExecutionContext:
|
|
|
195
198
|
|
|
196
199
|
@property
|
|
197
200
|
def allow_loop_control(self):
|
|
198
|
-
for _,
|
|
199
|
-
if
|
|
201
|
+
for _, result, _ in reversed(self.steps):
|
|
202
|
+
if result.type == 'ITERATION':
|
|
200
203
|
return True
|
|
201
|
-
if
|
|
204
|
+
if result.type == 'KEYWORD' and result.owner != 'BuiltIn':
|
|
202
205
|
return False
|
|
203
206
|
return False
|
|
204
207
|
|
|
@@ -249,10 +252,8 @@ class _ExecutionContext:
|
|
|
249
252
|
self.timeout_occurred = False
|
|
250
253
|
|
|
251
254
|
def start_body_item(self, data, result, implementation=None):
|
|
252
|
-
self.
|
|
253
|
-
|
|
254
|
-
raise DataError('Maximum limit of started keywords and control '
|
|
255
|
-
'structures exceeded.')
|
|
255
|
+
self._prevent_execution_close_to_recursion_limit()
|
|
256
|
+
self.steps.append((data, result, implementation))
|
|
256
257
|
output = self.output
|
|
257
258
|
args = (data, result)
|
|
258
259
|
if implementation:
|
|
@@ -274,6 +275,7 @@ class _ExecutionContext:
|
|
|
274
275
|
method = {
|
|
275
276
|
result.FOR: output.start_for,
|
|
276
277
|
result.WHILE: output.start_while,
|
|
278
|
+
result.GROUP: output.start_group,
|
|
277
279
|
result.IF_ELSE_ROOT: output.start_if,
|
|
278
280
|
result.IF: output.start_if_branch,
|
|
279
281
|
result.ELSE: output.start_if_branch,
|
|
@@ -290,6 +292,14 @@ class _ExecutionContext:
|
|
|
290
292
|
}[result.type]
|
|
291
293
|
method(*args)
|
|
292
294
|
|
|
295
|
+
def _prevent_execution_close_to_recursion_limit(self):
|
|
296
|
+
try:
|
|
297
|
+
sys._getframe(sys.getrecursionlimit() - 100)
|
|
298
|
+
except (ValueError, AttributeError):
|
|
299
|
+
pass
|
|
300
|
+
else:
|
|
301
|
+
raise DataError('Recursive execution stopped.')
|
|
302
|
+
|
|
293
303
|
def end_body_item(self, data, result, implementation=None):
|
|
294
304
|
output = self.output
|
|
295
305
|
args = (data, result)
|
|
@@ -312,6 +322,7 @@ class _ExecutionContext:
|
|
|
312
322
|
method = {
|
|
313
323
|
result.FOR: output.end_for,
|
|
314
324
|
result.WHILE: output.end_while,
|
|
325
|
+
result.GROUP: output.end_group,
|
|
315
326
|
result.IF_ELSE_ROOT: output.end_if,
|
|
316
327
|
result.IF: output.end_if_branch,
|
|
317
328
|
result.ELSE: output.end_if_branch,
|
|
@@ -82,7 +82,7 @@ class LibraryKeyword(KeywordImplementation):
|
|
|
82
82
|
return EmbeddedArgumentsRunner(self, name)
|
|
83
83
|
if self._resolve_args_until is not None:
|
|
84
84
|
dry_run = RUN_KW_REGISTER.get_dry_run(self.owner.real_name, self.name)
|
|
85
|
-
return RunKeywordRunner(self,
|
|
85
|
+
return RunKeywordRunner(self, dry_run_children=dry_run)
|
|
86
86
|
return LibraryKeywordRunner(self, languages=languages)
|
|
87
87
|
|
|
88
88
|
def resolve_arguments(self, args: 'Sequence[str|Any]',
|
|
@@ -131,23 +131,27 @@ class LibraryKeywordRunner:
|
|
|
131
131
|
kw = self.keyword.bind(data)
|
|
132
132
|
assignment = VariableAssignment(data.assign)
|
|
133
133
|
self._config_result(result, data, kw, assignment)
|
|
134
|
-
with StatusReporter(data, result, context,
|
|
134
|
+
with StatusReporter(data, result, context, implementation=kw,
|
|
135
|
+
run=self._get_initial_dry_run_status(kw)):
|
|
135
136
|
assignment.validate_assignment()
|
|
136
137
|
if self._executed_in_dry_run(kw):
|
|
137
138
|
self._run(data, kw, context)
|
|
138
139
|
else:
|
|
139
140
|
self._resolve_arguments(data, kw)
|
|
140
|
-
|
|
141
|
+
self._dry_run(data, kw, result, context)
|
|
141
142
|
|
|
142
|
-
def
|
|
143
|
-
|
|
144
|
-
pass
|
|
143
|
+
def _get_initial_dry_run_status(self, kw):
|
|
144
|
+
return self._executed_in_dry_run(kw)
|
|
145
145
|
|
|
146
146
|
def _executed_in_dry_run(self, kw: 'LibraryKeyword'):
|
|
147
147
|
return (kw.owner.name == 'BuiltIn'
|
|
148
148
|
and kw.name in ('Import Library', 'Set Library Search Order',
|
|
149
149
|
'Set Tags', 'Remove Tags', 'Import Resource'))
|
|
150
150
|
|
|
151
|
+
def _dry_run(self, data: KeywordData, kw: 'LibraryKeyword', result: KeywordResult,
|
|
152
|
+
context):
|
|
153
|
+
pass
|
|
154
|
+
|
|
151
155
|
|
|
152
156
|
class EmbeddedArgumentsRunner(LibraryKeywordRunner):
|
|
153
157
|
|
|
@@ -167,9 +171,9 @@ class EmbeddedArgumentsRunner(LibraryKeywordRunner):
|
|
|
167
171
|
|
|
168
172
|
class RunKeywordRunner(LibraryKeywordRunner):
|
|
169
173
|
|
|
170
|
-
def __init__(self, keyword: 'LibraryKeyword',
|
|
174
|
+
def __init__(self, keyword: 'LibraryKeyword', dry_run_children=False):
|
|
171
175
|
super().__init__(keyword)
|
|
172
|
-
self.
|
|
176
|
+
self._dry_run_children = dry_run_children
|
|
173
177
|
|
|
174
178
|
def _get_timeout(self, context):
|
|
175
179
|
# These keywords are not affected by timeouts. Keywords they execute are.
|
|
@@ -183,25 +187,31 @@ class RunKeywordRunner(LibraryKeywordRunner):
|
|
|
183
187
|
finally:
|
|
184
188
|
STOP_SIGNAL_MONITOR.stop_running_keyword()
|
|
185
189
|
|
|
186
|
-
def
|
|
187
|
-
|
|
190
|
+
def _get_initial_dry_run_status(self, kw):
|
|
191
|
+
return self._dry_run_children or super()._get_initial_dry_run_status(kw)
|
|
192
|
+
|
|
193
|
+
def _dry_run(self, data: KeywordData, kw: 'LibraryKeyword', result: KeywordResult,
|
|
194
|
+
context):
|
|
188
195
|
wrapper = UserKeyword(name=kw.name,
|
|
189
|
-
doc="Wraps keywords executed by '{kw.name}' in dry-run.",
|
|
196
|
+
doc=f"Wraps keywords executed by '{kw.name}' in dry-run.",
|
|
190
197
|
parent=kw.parent)
|
|
191
|
-
|
|
192
|
-
|
|
198
|
+
for child in self._get_dry_run_children(kw, data.args):
|
|
199
|
+
if not contains_variable(child.name):
|
|
200
|
+
child.lineno = data.lineno
|
|
201
|
+
wrapper.body.append(child)
|
|
193
202
|
BodyRunner(context).run(wrapper, result)
|
|
194
203
|
|
|
195
|
-
def
|
|
196
|
-
if not self.
|
|
204
|
+
def _get_dry_run_children(self, kw: 'LibraryKeyword', args):
|
|
205
|
+
if not self._dry_run_children:
|
|
197
206
|
return []
|
|
198
207
|
if kw.name == 'Run Keyword If':
|
|
199
|
-
return self.
|
|
208
|
+
return self._get_dry_run_children_for_run_keyword_if(args)
|
|
200
209
|
if kw.name == 'Run Keywords':
|
|
201
|
-
return self.
|
|
202
|
-
|
|
210
|
+
return self._get_dry_run_children_for_run_keyword(args)
|
|
211
|
+
index = kw.args.positional.index('name')
|
|
212
|
+
return [KeywordData(name=args[index], args=args[index+1:])]
|
|
203
213
|
|
|
204
|
-
def
|
|
214
|
+
def _get_dry_run_children_for_run_keyword_if(self, given_args):
|
|
205
215
|
for kw_call in self._get_run_kw_if_calls(given_args):
|
|
206
216
|
if kw_call:
|
|
207
217
|
yield KeywordData(name=kw_call[0], args=kw_call[1:])
|
|
@@ -235,7 +245,7 @@ class RunKeywordRunner(LibraryKeywordRunner):
|
|
|
235
245
|
return True
|
|
236
246
|
return any(is_list_variable(item) for item in kw_call)
|
|
237
247
|
|
|
238
|
-
def
|
|
248
|
+
def _get_dry_run_children_for_run_keyword(self, given_args):
|
|
239
249
|
for kw_call in self._get_run_kws_calls(given_args):
|
|
240
250
|
yield KeywordData(name=kw_call[0], args=kw_call[1:])
|
|
241
251
|
|
|
@@ -250,7 +260,3 @@ class RunKeywordRunner(LibraryKeywordRunner):
|
|
|
250
260
|
yield kw_call
|
|
251
261
|
if given_args:
|
|
252
262
|
yield given_args
|
|
253
|
-
|
|
254
|
-
def _get_dry_run_keywords_based_on_name(self, kw: 'LibraryKeyword', given_args):
|
|
255
|
-
index = kw.args.positional.index('name')
|
|
256
|
-
return [KeywordData(name=given_args[index], args=given_args[index+1:])]
|
|
@@ -46,7 +46,7 @@ from robot.output import LOGGER, Output, pyloggingconf
|
|
|
46
46
|
from robot.utils import format_assign_message, setter
|
|
47
47
|
from robot.variables import VariableResolver
|
|
48
48
|
|
|
49
|
-
from .bodyrunner import ForRunner, IfRunner, KeywordRunner, TryRunner, WhileRunner
|
|
49
|
+
from .bodyrunner import ForRunner, GroupRunner, IfRunner, KeywordRunner, TryRunner, WhileRunner
|
|
50
50
|
from .randomizer import Randomizer
|
|
51
51
|
from .statusreporter import StatusReporter
|
|
52
52
|
|
|
@@ -58,15 +58,15 @@ if TYPE_CHECKING:
|
|
|
58
58
|
|
|
59
59
|
IT = TypeVar('IT', bound='IfBranch|TryBranch')
|
|
60
60
|
BodyItemParent = Union['TestSuite', 'TestCase', 'UserKeyword', 'For', 'If', 'IfBranch',
|
|
61
|
-
'Try', 'TryBranch', 'While', None]
|
|
61
|
+
'Try', 'TryBranch', 'While', 'Group', None]
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
class Body(model.BaseBody['Keyword', 'For', 'While', 'If', 'Try', 'Var', 'Return',
|
|
64
|
+
class Body(model.BaseBody['Keyword', 'For', 'While', 'Group', 'If', 'Try', 'Var', 'Return',
|
|
65
65
|
'Continue', 'Break', 'model.Message', 'Error']):
|
|
66
66
|
__slots__ = ()
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
class Branches(model.BaseBranches['Keyword', 'For', 'While', 'If', 'Try', 'Var', 'Return',
|
|
69
|
+
class Branches(model.BaseBranches['Keyword', 'For', 'While', 'Group', 'If', 'Try', 'Var', 'Return',
|
|
70
70
|
'Continue', 'Break', 'model.Message', 'Error', IT]):
|
|
71
71
|
__slots__ = ()
|
|
72
72
|
|
|
@@ -259,6 +259,33 @@ class While(model.While, WithSource):
|
|
|
259
259
|
iteration = WhileIteration(self, self.lineno, self.error)
|
|
260
260
|
iteration.body = [item.to_dict() for item in self.body]
|
|
261
261
|
return iteration
|
|
262
|
+
self.error = error
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
@Body.register
|
|
266
|
+
class Group(model.Group, WithSource):
|
|
267
|
+
__slots__ = ['lineno', 'error']
|
|
268
|
+
body_class = Body
|
|
269
|
+
|
|
270
|
+
def __init__(self, name: str = '',
|
|
271
|
+
parent: BodyItemParent = None,
|
|
272
|
+
lineno: 'int|None' = None,
|
|
273
|
+
error: 'str|None' = None):
|
|
274
|
+
super().__init__(name, parent)
|
|
275
|
+
self.lineno = lineno
|
|
276
|
+
self.error = error
|
|
277
|
+
|
|
278
|
+
def to_dict(self) -> DataDict:
|
|
279
|
+
data = super().to_dict()
|
|
280
|
+
if self.lineno:
|
|
281
|
+
data['lineno'] = self.lineno
|
|
282
|
+
if self.error:
|
|
283
|
+
data['error'] = self.error
|
|
284
|
+
return data
|
|
285
|
+
|
|
286
|
+
def run(self, result, context, run=True, templated=False):
|
|
287
|
+
result = result.body.create_group(self.name)
|
|
288
|
+
return GroupRunner(context, run, templated).run(self, result)
|
|
262
289
|
|
|
263
290
|
|
|
264
291
|
class IfBranch(model.IfBranch, WithSource):
|
|
@@ -52,7 +52,8 @@ class OutputCapturer:
|
|
|
52
52
|
LOGGER.log_output(stdout)
|
|
53
53
|
if stderr:
|
|
54
54
|
LOGGER.log_output(stderr)
|
|
55
|
-
|
|
55
|
+
if sys.__stderr__:
|
|
56
|
+
sys.__stderr__.write(console_encode(stderr, stream=sys.__stderr__))
|
|
56
57
|
|
|
57
58
|
def _release(self):
|
|
58
59
|
stdout = self.stdout.release()
|
|
@@ -31,14 +31,18 @@ class _StopSignalMonitor:
|
|
|
31
31
|
|
|
32
32
|
def __call__(self, signum, frame):
|
|
33
33
|
self._signal_count += 1
|
|
34
|
-
LOGGER.info('Received signal:
|
|
34
|
+
LOGGER.info(f'Received signal: {signum}.')
|
|
35
35
|
if self._signal_count > 1:
|
|
36
|
-
|
|
36
|
+
self._write_to_stderr('Execution forcefully stopped.')
|
|
37
37
|
raise SystemExit()
|
|
38
|
-
|
|
38
|
+
self._write_to_stderr('Second signal will force exit.')
|
|
39
39
|
if self._running_keyword:
|
|
40
40
|
self._stop_execution_gracefully()
|
|
41
41
|
|
|
42
|
+
def _write_to_stderr(self, message):
|
|
43
|
+
if sys.__stderr__:
|
|
44
|
+
sys.__stderr__.write(message + '\n')
|
|
45
|
+
|
|
42
46
|
def _stop_execution_gracefully(self):
|
|
43
47
|
raise ExecutionFailed('Execution terminated by signal', exit=True)
|
|
44
48
|
|
|
@@ -13,9 +13,11 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
+
from abc import ABC
|
|
17
|
+
|
|
16
18
|
from robot.errors import PassExecution
|
|
17
19
|
from robot.model import TagPatterns
|
|
18
|
-
from robot.utils import html_escape, test_or_task
|
|
20
|
+
from robot.utils import html_escape, plural_or_not as s, seq2str, test_or_task
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
class Failure:
|
|
@@ -29,9 +31,13 @@ class Failure:
|
|
|
29
31
|
self.teardown_skipped = None
|
|
30
32
|
|
|
31
33
|
def __bool__(self):
|
|
32
|
-
return
|
|
33
|
-
self.setup
|
|
34
|
-
|
|
34
|
+
return (
|
|
35
|
+
self.setup is not None
|
|
36
|
+
or self.test is not None
|
|
37
|
+
or self.teardown is not None
|
|
38
|
+
or self.setup_skipped is not None
|
|
39
|
+
or self.test_skipped is not None
|
|
40
|
+
or self.teardown_skipped is not None
|
|
35
41
|
)
|
|
36
42
|
|
|
37
43
|
|
|
@@ -45,10 +51,10 @@ class Exit:
|
|
|
45
51
|
self.error = False
|
|
46
52
|
self.fatal = False
|
|
47
53
|
|
|
48
|
-
def failure_occurred(self, fatal=False):
|
|
54
|
+
def failure_occurred(self, fatal=False, suite_setup=False):
|
|
49
55
|
if fatal:
|
|
50
56
|
self.fatal = True
|
|
51
|
-
if self.failure_mode:
|
|
57
|
+
if self.failure_mode and not suite_setup:
|
|
52
58
|
self.failure = True
|
|
53
59
|
|
|
54
60
|
def error_occurred(self):
|
|
@@ -63,7 +69,7 @@ class Exit:
|
|
|
63
69
|
return bool(self.failure or self.error or self.fatal)
|
|
64
70
|
|
|
65
71
|
|
|
66
|
-
class
|
|
72
|
+
class ExecutionStatus(ABC):
|
|
67
73
|
|
|
68
74
|
def __init__(self, parent, exit=None):
|
|
69
75
|
self.parent = parent
|
|
@@ -71,7 +77,6 @@ class _ExecutionStatus:
|
|
|
71
77
|
self.failure = Failure()
|
|
72
78
|
self.skipped = False
|
|
73
79
|
self._teardown_allowed = False
|
|
74
|
-
self._rpa = False
|
|
75
80
|
|
|
76
81
|
@property
|
|
77
82
|
def failed(self):
|
|
@@ -92,7 +97,8 @@ class _ExecutionStatus:
|
|
|
92
97
|
self.skipped = True
|
|
93
98
|
else:
|
|
94
99
|
self.failure.setup = msg
|
|
95
|
-
self.exit.failure_occurred(error.exit
|
|
100
|
+
self.exit.failure_occurred(error.exit,
|
|
101
|
+
suite_setup=isinstance(self, SuiteStatus))
|
|
96
102
|
self._teardown_allowed = True
|
|
97
103
|
|
|
98
104
|
def teardown_executed(self, error=None):
|
|
@@ -147,7 +153,7 @@ class _ExecutionStatus:
|
|
|
147
153
|
return ParentMessage(self.parent).message
|
|
148
154
|
|
|
149
155
|
|
|
150
|
-
class SuiteStatus(
|
|
156
|
+
class SuiteStatus(ExecutionStatus):
|
|
151
157
|
|
|
152
158
|
def __init__(self, parent=None, exit_on_failure=False, exit_on_error=False,
|
|
153
159
|
skip_teardown_on_exit=False):
|
|
@@ -161,19 +167,19 @@ class SuiteStatus(_ExecutionStatus):
|
|
|
161
167
|
return SuiteMessage(self).message
|
|
162
168
|
|
|
163
169
|
|
|
164
|
-
class TestStatus(
|
|
170
|
+
class TestStatus(ExecutionStatus):
|
|
165
171
|
|
|
166
|
-
def __init__(self, parent, test, skip_on_failure=
|
|
172
|
+
def __init__(self, parent, test, skip_on_failure=(), rpa=False):
|
|
167
173
|
super().__init__(parent)
|
|
168
|
-
self.
|
|
169
|
-
self.
|
|
170
|
-
self.
|
|
174
|
+
self.test = test
|
|
175
|
+
self.skip_on_failure_tags = TagPatterns(skip_on_failure)
|
|
176
|
+
self.rpa = rpa
|
|
171
177
|
|
|
172
178
|
def test_failed(self, message=None, error=None):
|
|
173
179
|
if error is not None:
|
|
174
180
|
message = str(error)
|
|
175
181
|
skip = error.skip
|
|
176
|
-
fatal = error.exit
|
|
182
|
+
fatal = error.exit or self.test.tags.robot('exit-on-failure')
|
|
177
183
|
else:
|
|
178
184
|
skip = fatal = False
|
|
179
185
|
if skip:
|
|
@@ -198,26 +204,32 @@ class TestStatus(_ExecutionStatus):
|
|
|
198
204
|
return False
|
|
199
205
|
|
|
200
206
|
def _skip_on_failure(self):
|
|
201
|
-
return (self.
|
|
202
|
-
or self.
|
|
203
|
-
and TagPatterns(self._skip_on_failure_tags).match(self._test.tags))
|
|
207
|
+
return (self.test.tags.robot('skip-on-failure')
|
|
208
|
+
or self.skip_on_failure_tags.match(self.test.tags))
|
|
204
209
|
|
|
205
|
-
def _skip_on_fail_msg(self,
|
|
210
|
+
def _skip_on_fail_msg(self, fail_msg):
|
|
211
|
+
if self.test.tags.robot('skip-on-failure'):
|
|
212
|
+
tags = ['robot:skip-on-failure']
|
|
213
|
+
kind = 'tag'
|
|
214
|
+
else:
|
|
215
|
+
tags = self.skip_on_failure_tags
|
|
216
|
+
kind = 'tag' if tags.is_constant else 'tag pattern'
|
|
206
217
|
return test_or_task(
|
|
207
|
-
"{
|
|
208
|
-
"
|
|
218
|
+
f"Failed {{test}} skipped using {seq2str(tags)} {kind}{s(tags)}.\n\n"
|
|
219
|
+
f"Original failure:\n{fail_msg}", rpa=self.rpa
|
|
209
220
|
)
|
|
210
221
|
|
|
211
222
|
def _my_message(self):
|
|
212
223
|
return TestMessage(self).message
|
|
213
224
|
|
|
214
225
|
|
|
215
|
-
class
|
|
216
|
-
setup_message =
|
|
217
|
-
setup_skipped_message =
|
|
218
|
-
teardown_skipped_message =
|
|
219
|
-
teardown_message =
|
|
220
|
-
also_teardown_message =
|
|
226
|
+
class Message(ABC):
|
|
227
|
+
setup_message = ''
|
|
228
|
+
setup_skipped_message = ''
|
|
229
|
+
teardown_skipped_message = ''
|
|
230
|
+
teardown_message = ''
|
|
231
|
+
also_teardown_message = ''
|
|
232
|
+
also_teardown_skip_message = ''
|
|
221
233
|
|
|
222
234
|
def __init__(self, status):
|
|
223
235
|
self.failure = status.failure
|
|
@@ -230,11 +242,11 @@ class _Message:
|
|
|
230
242
|
|
|
231
243
|
def _get_message_before_teardown(self):
|
|
232
244
|
if self.failure.setup_skipped:
|
|
233
|
-
return self._format_setup_or_teardown_message(
|
|
234
|
-
|
|
245
|
+
return self._format_setup_or_teardown_message(self.setup_skipped_message,
|
|
246
|
+
self.failure.setup_skipped)
|
|
235
247
|
if self.failure.setup:
|
|
236
|
-
return self._format_setup_or_teardown_message(
|
|
237
|
-
|
|
248
|
+
return self._format_setup_or_teardown_message(self.setup_message,
|
|
249
|
+
self.failure.setup)
|
|
238
250
|
return self.failure.test_skipped or self.failure.test or ''
|
|
239
251
|
|
|
240
252
|
def _format_setup_or_teardown_message(self, prefix, message):
|
|
@@ -267,7 +279,7 @@ class _Message:
|
|
|
267
279
|
return self.also_teardown_skip_message % (teardown, message)
|
|
268
280
|
|
|
269
281
|
|
|
270
|
-
class TestMessage(
|
|
282
|
+
class TestMessage(Message):
|
|
271
283
|
setup_message = 'Setup failed:\n%s'
|
|
272
284
|
teardown_message = 'Teardown failed:\n%s'
|
|
273
285
|
setup_skipped_message = '%s'
|
|
@@ -275,12 +287,11 @@ class TestMessage(_Message):
|
|
|
275
287
|
also_teardown_message = '%s\n\nAlso teardown failed:\n%s'
|
|
276
288
|
also_teardown_skip_message = 'Skipped in teardown:\n%s\n\nEarlier message:\n%s'
|
|
277
289
|
exit_on_fatal_message = 'Test execution stopped due to a fatal error.'
|
|
278
|
-
exit_on_failure_message =
|
|
279
|
-
'Failure occurred and exit-on-failure mode is in use.'
|
|
290
|
+
exit_on_failure_message = 'Failure occurred and exit-on-failure mode is in use.'
|
|
280
291
|
exit_on_error_message = 'Error occurred and exit-on-error mode is in use.'
|
|
281
292
|
|
|
282
293
|
def __init__(self, status):
|
|
283
|
-
|
|
294
|
+
super().__init__(status)
|
|
284
295
|
self.exit = status.exit
|
|
285
296
|
|
|
286
297
|
@property
|
|
@@ -297,7 +308,7 @@ class TestMessage(_Message):
|
|
|
297
308
|
return ''
|
|
298
309
|
|
|
299
310
|
|
|
300
|
-
class SuiteMessage(
|
|
311
|
+
class SuiteMessage(Message):
|
|
301
312
|
setup_message = 'Suite setup failed:\n%s'
|
|
302
313
|
setup_skipped_message = 'Skipped in suite setup:\n%s'
|
|
303
314
|
teardown_skipped_message = 'Skipped in suite teardown:\n%s'
|
|
@@ -316,4 +327,4 @@ class ParentMessage(SuiteMessage):
|
|
|
316
327
|
def __init__(self, status):
|
|
317
328
|
while status.parent and status.parent.failed:
|
|
318
329
|
status = status.parent
|
|
319
|
-
|
|
330
|
+
super().__init__(status)
|
|
@@ -62,7 +62,7 @@ class StatusReporter:
|
|
|
62
62
|
result.status = failure.status
|
|
63
63
|
if not isinstance(failure, (BreakLoop, ContinueLoop, ReturnFromKeyword)):
|
|
64
64
|
result.message = failure.message
|
|
65
|
-
if self.initial_test_status == 'PASS':
|
|
65
|
+
if self.initial_test_status == 'PASS' and result.status != 'NOT RUN':
|
|
66
66
|
context.test.status = result.status
|
|
67
67
|
result.elapsed_time = datetime.now() - result.start_time
|
|
68
68
|
orig_status = (result.status, result.message)
|