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
|
@@ -17,6 +17,7 @@ import re
|
|
|
17
17
|
from typing import (Any, Callable, cast, Generic, Iterable, Type, TYPE_CHECKING,
|
|
18
18
|
TypeVar, Union)
|
|
19
19
|
|
|
20
|
+
from robot.errors import DataError
|
|
20
21
|
from robot.utils import copy_signature, KnownAtRuntime
|
|
21
22
|
|
|
22
23
|
from .itemlist import ItemList
|
|
@@ -24,8 +25,8 @@ from .modelobject import DataDict, full_name, ModelObject
|
|
|
24
25
|
|
|
25
26
|
if TYPE_CHECKING:
|
|
26
27
|
from robot.running.model import ResourceFile, UserKeyword
|
|
27
|
-
from .control import (Break, Continue, Error, For, ForIteration,
|
|
28
|
-
Return, Try, TryBranch, Var, While, WhileIteration)
|
|
28
|
+
from .control import (Break, Continue, Error, For, ForIteration, Group, If,
|
|
29
|
+
IfBranch, Return, Try, TryBranch, Var, While, WhileIteration)
|
|
29
30
|
from .keyword import Keyword
|
|
30
31
|
from .message import Message
|
|
31
32
|
from .testcase import TestCase
|
|
@@ -33,12 +34,14 @@ if TYPE_CHECKING:
|
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
BodyItemParent = Union['TestSuite', 'TestCase', 'UserKeyword', 'For', 'ForIteration',
|
|
36
|
-
'If', 'IfBranch', 'Try', 'TryBranch', 'While', '
|
|
37
|
-
'Keyword', 'Var', 'Return', 'Continue',
|
|
37
|
+
'If', 'IfBranch', 'Try', 'TryBranch', 'While', 'Group',
|
|
38
|
+
'WhileIteration', 'Keyword', 'Var', 'Return', 'Continue',
|
|
39
|
+
'Break', 'Error', None]
|
|
38
40
|
BI = TypeVar('BI', bound='BodyItem')
|
|
39
41
|
KW = TypeVar('KW', bound='Keyword')
|
|
40
42
|
F = TypeVar('F', bound='For')
|
|
41
43
|
W = TypeVar('W', bound='While')
|
|
44
|
+
G = TypeVar('G', bound='Group')
|
|
42
45
|
I = TypeVar('I', bound='If')
|
|
43
46
|
T = TypeVar('T', bound='Try')
|
|
44
47
|
V = TypeVar('V', bound='Var')
|
|
@@ -52,28 +55,7 @@ FW = TypeVar('FW', bound='ForIteration|WhileIteration')
|
|
|
52
55
|
|
|
53
56
|
|
|
54
57
|
class BodyItem(ModelObject):
|
|
55
|
-
|
|
56
|
-
SETUP = 'SETUP'
|
|
57
|
-
TEARDOWN = 'TEARDOWN'
|
|
58
|
-
FOR = 'FOR'
|
|
59
|
-
ITERATION = 'ITERATION'
|
|
60
|
-
IF_ELSE_ROOT = 'IF/ELSE ROOT'
|
|
61
|
-
IF = 'IF'
|
|
62
|
-
ELSE_IF = 'ELSE IF'
|
|
63
|
-
ELSE = 'ELSE'
|
|
64
|
-
TRY_EXCEPT_ROOT = 'TRY/EXCEPT ROOT'
|
|
65
|
-
TRY = 'TRY'
|
|
66
|
-
EXCEPT = 'EXCEPT'
|
|
67
|
-
FINALLY = 'FINALLY'
|
|
68
|
-
WHILE = 'WHILE'
|
|
69
|
-
VAR = 'VAR'
|
|
70
|
-
RETURN = 'RETURN'
|
|
71
|
-
CONTINUE = 'CONTINUE'
|
|
72
|
-
BREAK = 'BREAK'
|
|
73
|
-
ERROR = 'ERROR'
|
|
74
|
-
MESSAGE = 'MESSAGE'
|
|
75
|
-
KEYWORD_TYPES = (KEYWORD, SETUP, TEARDOWN)
|
|
76
|
-
type = None
|
|
58
|
+
body: 'BaseBody'
|
|
77
59
|
__slots__ = ['parent']
|
|
78
60
|
|
|
79
61
|
@property
|
|
@@ -99,28 +81,27 @@ class BodyItem(ModelObject):
|
|
|
99
81
|
# or linking to warnings and errors won't work.
|
|
100
82
|
steps = []
|
|
101
83
|
if getattr(parent, 'has_setup', False):
|
|
102
|
-
steps.append(parent.setup)
|
|
84
|
+
steps.append(parent.setup)
|
|
103
85
|
if hasattr(parent, 'body'):
|
|
104
|
-
steps.extend(
|
|
105
|
-
parent.body.flatten() # type: ignore - Use Protocol with RF 7.
|
|
106
|
-
if step.type != self.MESSAGE)
|
|
86
|
+
steps.extend(parent.body.flatten(messages=False))
|
|
107
87
|
if getattr(parent, 'has_teardown', False):
|
|
108
|
-
steps.append(parent.teardown)
|
|
88
|
+
steps.append(parent.teardown)
|
|
109
89
|
index = steps.index(self) if self in steps else len(steps)
|
|
110
|
-
|
|
111
|
-
return f'{
|
|
90
|
+
pid = parent.id # IF/TRY root id is None. Avoid calling property twice.
|
|
91
|
+
return f'{pid}-k{index + 1}' if pid else f'k{index + 1}'
|
|
112
92
|
|
|
113
93
|
def to_dict(self) -> DataDict:
|
|
114
94
|
raise NotImplementedError
|
|
115
95
|
|
|
116
96
|
|
|
117
|
-
class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, V, R, C, B, M, E]):
|
|
97
|
+
class BaseBody(ItemList[BodyItem], Generic[KW, F, W, G, I, T, V, R, C, B, M, E]):
|
|
118
98
|
"""Base class for Body and Branches objects."""
|
|
119
|
-
__slots__ =
|
|
99
|
+
__slots__ = ()
|
|
120
100
|
# Set using 'BaseBody.register' when these classes are created.
|
|
121
101
|
keyword_class: Type[KW] = KnownAtRuntime
|
|
122
102
|
for_class: Type[F] = KnownAtRuntime
|
|
123
103
|
while_class: Type[W] = KnownAtRuntime
|
|
104
|
+
group_class: Type[G] = KnownAtRuntime
|
|
124
105
|
if_class: Type[I] = KnownAtRuntime
|
|
125
106
|
try_class: Type[T] = KnownAtRuntime
|
|
126
107
|
var_class: Type[V] = KnownAtRuntime
|
|
@@ -189,6 +170,10 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, V, R, C, B, M, E]):
|
|
|
189
170
|
def create_while(self, *args, **kwargs) -> while_class:
|
|
190
171
|
return self._create(self.while_class, 'create_while', args, kwargs)
|
|
191
172
|
|
|
173
|
+
@copy_signature(group_class)
|
|
174
|
+
def create_group(self, *args, **kwargs) -> group_class:
|
|
175
|
+
return self._create(self.group_class, 'create_group', args, kwargs)
|
|
176
|
+
|
|
192
177
|
@copy_signature(var_class)
|
|
193
178
|
def create_var(self, *args, **kwargs) -> var_class:
|
|
194
179
|
return self._create(self.var_class, 'create_var', args, kwargs)
|
|
@@ -214,7 +199,7 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, V, R, C, B, M, E]):
|
|
|
214
199
|
return self._create(self.error_class, 'create_error', args, kwargs)
|
|
215
200
|
|
|
216
201
|
def filter(self, keywords: 'bool|None' = None, messages: 'bool|None' = None,
|
|
217
|
-
predicate: 'Callable[[T], bool]|None' = None):
|
|
202
|
+
predicate: 'Callable[[T], bool]|None' = None) -> 'list[BodyItem]':
|
|
218
203
|
"""Filter body items based on type and/or custom predicate.
|
|
219
204
|
|
|
220
205
|
To include or exclude items based on types, give matching arguments
|
|
@@ -238,9 +223,6 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, V, R, C, B, M, E]):
|
|
|
238
223
|
use ``body.filter(keywords=False``, messages=False)``. For more detailed
|
|
239
224
|
filtering it is possible to use ``predicate``.
|
|
240
225
|
"""
|
|
241
|
-
if messages is not None and self.message_class is KnownAtRuntime:
|
|
242
|
-
raise TypeError(f"'{full_name(self)}' object does not support "
|
|
243
|
-
f"filtering by 'messages'.")
|
|
244
226
|
return self._filter([(self.keyword_class, keywords),
|
|
245
227
|
(self.message_class, messages)], predicate)
|
|
246
228
|
|
|
@@ -258,38 +240,41 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, V, R, C, B, M, E]):
|
|
|
258
240
|
items = [item for item in items if predicate(item)]
|
|
259
241
|
return items
|
|
260
242
|
|
|
261
|
-
def flatten(self) -> 'list[BodyItem]':
|
|
243
|
+
def flatten(self, **filter_config) -> 'list[BodyItem]':
|
|
262
244
|
"""Return steps so that IF and TRY structures are flattened.
|
|
263
245
|
|
|
264
246
|
Basically the IF/ELSE and TRY/EXCEPT root elements are replaced
|
|
265
|
-
with their branches. This is how they are shown in log
|
|
247
|
+
with their branches. This is how they are shown in the log file.
|
|
248
|
+
|
|
249
|
+
``filter_config`` can be used to filter steps using the :meth:`filter`
|
|
250
|
+
method before flattening. New in Robot Framework 7.2.
|
|
266
251
|
"""
|
|
267
252
|
roots = BodyItem.IF_ELSE_ROOT, BodyItem.TRY_EXCEPT_ROOT
|
|
268
|
-
steps =
|
|
269
|
-
|
|
253
|
+
steps = self if not filter_config else self.filter(**filter_config)
|
|
254
|
+
flat = []
|
|
255
|
+
for item in steps:
|
|
270
256
|
if item.type in roots:
|
|
271
|
-
|
|
272
|
-
steps.extend(item.body)
|
|
257
|
+
flat.extend(item.body)
|
|
273
258
|
else:
|
|
274
|
-
|
|
275
|
-
return
|
|
259
|
+
flat.append(item)
|
|
260
|
+
return flat
|
|
276
261
|
|
|
277
262
|
|
|
278
|
-
class Body(BaseBody['Keyword', 'For', 'While', '
|
|
279
|
-
|
|
263
|
+
class Body(BaseBody['Keyword', 'For', 'While', 'Group', 'If', 'Try', 'Var',
|
|
264
|
+
'Return', 'Continue', 'Break', 'Message', 'Error']):
|
|
280
265
|
"""A list-like object representing a body of a test, keyword, etc.
|
|
281
266
|
|
|
282
267
|
Body contains the keywords and other structures such as FOR loops.
|
|
283
268
|
"""
|
|
284
|
-
|
|
269
|
+
__slots__ = ()
|
|
285
270
|
|
|
286
271
|
|
|
287
272
|
# BaseBranches cannot extend Generic[IT] directly with BaseBody[...].
|
|
288
273
|
class BranchType(Generic[IT]):
|
|
289
|
-
|
|
274
|
+
__slots__ = ()
|
|
290
275
|
|
|
291
276
|
|
|
292
|
-
class BaseBranches(BaseBody[KW, F, W, I, T, V, R, C, B, M, E], BranchType[IT]):
|
|
277
|
+
class BaseBranches(BaseBody[KW, F, W, G, I, T, V, R, C, B, M, E], BranchType[IT]):
|
|
293
278
|
"""A list-like object representing IF and TRY branches."""
|
|
294
279
|
__slots__ = ['branch_class']
|
|
295
280
|
branch_type: Type[IT] = KnownAtRuntime
|
|
@@ -300,8 +285,11 @@ class BaseBranches(BaseBody[KW, F, W, I, T, V, R, C, B, M, E], BranchType[IT]):
|
|
|
300
285
|
self.branch_class = branch_class
|
|
301
286
|
super().__init__(parent, items)
|
|
302
287
|
|
|
303
|
-
def _item_from_dict(self, data: DataDict) ->
|
|
304
|
-
|
|
288
|
+
def _item_from_dict(self, data: DataDict) -> BodyItem:
|
|
289
|
+
try:
|
|
290
|
+
return self.branch_class.from_dict(data)
|
|
291
|
+
except DataError:
|
|
292
|
+
return super()._item_from_dict(data)
|
|
305
293
|
|
|
306
294
|
@copy_signature(branch_type)
|
|
307
295
|
def create_branch(self, *args, **kwargs) -> IT:
|
|
@@ -310,10 +298,10 @@ class BaseBranches(BaseBody[KW, F, W, I, T, V, R, C, B, M, E], BranchType[IT]):
|
|
|
310
298
|
|
|
311
299
|
# BaseIterations cannot extend Generic[IT] directly with BaseBody[...].
|
|
312
300
|
class IterationType(Generic[FW]):
|
|
313
|
-
|
|
301
|
+
__slots__ = ()
|
|
314
302
|
|
|
315
303
|
|
|
316
|
-
class BaseIterations(BaseBody[KW, F, W, I, T, V, R, C, B, M, E], IterationType[FW]):
|
|
304
|
+
class BaseIterations(BaseBody[KW, F, W, G, I, T, V, R, C, B, M, E], IterationType[FW]):
|
|
317
305
|
__slots__ = ['iteration_class']
|
|
318
306
|
iteration_type: Type[FW] = KnownAtRuntime
|
|
319
307
|
|
|
@@ -323,7 +311,10 @@ class BaseIterations(BaseBody[KW, F, W, I, T, V, R, C, B, M, E], IterationType[F
|
|
|
323
311
|
self.iteration_class = iteration_class
|
|
324
312
|
super().__init__(parent, items)
|
|
325
313
|
|
|
326
|
-
def _item_from_dict(self, data: DataDict) ->
|
|
314
|
+
def _item_from_dict(self, data: DataDict) -> BodyItem:
|
|
315
|
+
# Non-iteration data is typically caused by listeners.
|
|
316
|
+
if data.get('type') != 'ITERATION':
|
|
317
|
+
return super()._item_from_dict(data)
|
|
327
318
|
return self.iteration_class.from_dict(data)
|
|
328
319
|
|
|
329
320
|
@copy_signature(iteration_type)
|
|
@@ -31,13 +31,13 @@ IT = TypeVar('IT', bound='IfBranch|TryBranch')
|
|
|
31
31
|
FW = TypeVar('FW', bound='ForIteration|WhileIteration')
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
class Branches(BaseBranches['Keyword', 'For', 'While', '
|
|
35
|
-
'Continue', 'Break', 'Message', 'Error', IT]):
|
|
34
|
+
class Branches(BaseBranches['Keyword', 'For', 'While', 'Group', 'If', 'Try', 'Var',
|
|
35
|
+
'Return', 'Continue', 'Break', 'Message', 'Error', IT]):
|
|
36
36
|
__slots__ = ()
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
class Iterations(BaseIterations['Keyword', 'For', 'While', '
|
|
40
|
-
'Continue', 'Break', 'Message', 'Error', FW]):
|
|
39
|
+
class Iterations(BaseIterations['Keyword', 'For', 'While', 'Group', 'If', 'Try', 'Var',
|
|
40
|
+
'Return', 'Continue', 'Break', 'Message', 'Error', FW]):
|
|
41
41
|
__slots__ = ()
|
|
42
42
|
|
|
43
43
|
|
|
@@ -229,6 +229,37 @@ class While(BodyItem):
|
|
|
229
229
|
return ' '.join(parts)
|
|
230
230
|
|
|
231
231
|
|
|
232
|
+
@Body.register
|
|
233
|
+
class Group(BodyItem):
|
|
234
|
+
"""Represents ``GROUP``."""
|
|
235
|
+
type = BodyItem.GROUP
|
|
236
|
+
body_class = Body
|
|
237
|
+
repr_args = ('name',)
|
|
238
|
+
__slots__ = ['name']
|
|
239
|
+
|
|
240
|
+
def __init__(self, name: str = '',
|
|
241
|
+
parent: BodyItemParent = None):
|
|
242
|
+
self.name = name
|
|
243
|
+
self.parent = parent
|
|
244
|
+
self.body = ()
|
|
245
|
+
|
|
246
|
+
@setter
|
|
247
|
+
def body(self, body: 'Sequence[BodyItem|DataDict]') -> Body:
|
|
248
|
+
return self.body_class(self, body)
|
|
249
|
+
|
|
250
|
+
def visit(self, visitor: SuiteVisitor):
|
|
251
|
+
visitor.visit_group(self)
|
|
252
|
+
|
|
253
|
+
def to_dict(self) -> DataDict:
|
|
254
|
+
return {'type': self.type, 'name': self.name, 'body': self.body.to_dicts()}
|
|
255
|
+
|
|
256
|
+
def __str__(self) -> str:
|
|
257
|
+
parts = ['GROUP']
|
|
258
|
+
if self.name:
|
|
259
|
+
parts.append(self.name)
|
|
260
|
+
return ' '.join(parts)
|
|
261
|
+
|
|
262
|
+
|
|
232
263
|
class IfBranch(BodyItem):
|
|
233
264
|
"""Represents individual ``IF``, ``ELSE IF`` or ``ELSE`` branch."""
|
|
234
265
|
body_class = Body
|
|
@@ -61,7 +61,10 @@ class Message(BodyItem):
|
|
|
61
61
|
def id(self):
|
|
62
62
|
if not self.parent:
|
|
63
63
|
return 'm1'
|
|
64
|
-
|
|
64
|
+
if hasattr(self.parent, 'messages'):
|
|
65
|
+
messages = self.parent.messages
|
|
66
|
+
else:
|
|
67
|
+
messages = self.parent.body.filter(messages=True)
|
|
65
68
|
index = messages.index(self) if self in messages else len(messages)
|
|
66
69
|
return f'{self.parent.id}-m{index + 1}'
|
|
67
70
|
|
|
@@ -69,12 +72,14 @@ class Message(BodyItem):
|
|
|
69
72
|
""":mod:`Visitor interface <robot.model.visitor>` entry-point."""
|
|
70
73
|
visitor.visit_message(self)
|
|
71
74
|
|
|
75
|
+
def to_dict(self):
|
|
76
|
+
data = {'message': self.message,
|
|
77
|
+
'level': self.level}
|
|
78
|
+
if self.html:
|
|
79
|
+
data['html'] = True
|
|
80
|
+
if self.timestamp:
|
|
81
|
+
data['timestamp'] = self.timestamp.isoformat()
|
|
82
|
+
return data
|
|
83
|
+
|
|
72
84
|
def __str__(self):
|
|
73
85
|
return self.message
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
class Messages(ItemList):
|
|
77
|
-
__slots__ = []
|
|
78
|
-
|
|
79
|
-
def __init__(self, message_class=Message, parent=None, messages=None):
|
|
80
|
-
ItemList.__init__(self, message_class, {'parent': parent}, messages)
|
|
@@ -27,6 +27,32 @@ DataDict = Dict[str, Any]
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class ModelObject(metaclass=SetterAwareType):
|
|
30
|
+
SUITE = 'SUITE'
|
|
31
|
+
TEST = 'TEST'
|
|
32
|
+
TASK = TEST
|
|
33
|
+
KEYWORD = 'KEYWORD'
|
|
34
|
+
SETUP = 'SETUP'
|
|
35
|
+
TEARDOWN = 'TEARDOWN'
|
|
36
|
+
FOR = 'FOR'
|
|
37
|
+
ITERATION = 'ITERATION'
|
|
38
|
+
IF_ELSE_ROOT = 'IF/ELSE ROOT'
|
|
39
|
+
IF = 'IF'
|
|
40
|
+
ELSE_IF = 'ELSE IF'
|
|
41
|
+
ELSE = 'ELSE'
|
|
42
|
+
TRY_EXCEPT_ROOT = 'TRY/EXCEPT ROOT'
|
|
43
|
+
TRY = 'TRY'
|
|
44
|
+
EXCEPT = 'EXCEPT'
|
|
45
|
+
FINALLY = 'FINALLY'
|
|
46
|
+
WHILE = 'WHILE'
|
|
47
|
+
GROUP = 'GROUP'
|
|
48
|
+
VAR = 'VAR'
|
|
49
|
+
RETURN = 'RETURN'
|
|
50
|
+
CONTINUE = 'CONTINUE'
|
|
51
|
+
BREAK = 'BREAK'
|
|
52
|
+
ERROR = 'ERROR'
|
|
53
|
+
MESSAGE = 'MESSAGE'
|
|
54
|
+
KEYWORD_TYPES = (KEYWORD, SETUP, TEARDOWN)
|
|
55
|
+
type: str
|
|
30
56
|
repr_args = ()
|
|
31
57
|
__slots__ = []
|
|
32
58
|
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
-
from .totalstatistics import TotalStatisticsBuilder
|
|
17
|
-
from .suitestatistics import SuiteStatisticsBuilder
|
|
18
|
-
from .tagstatistics import TagStatisticsBuilder
|
|
16
|
+
from .totalstatistics import TotalStatistics, TotalStatisticsBuilder
|
|
17
|
+
from .suitestatistics import SuiteStatistics, SuiteStatisticsBuilder
|
|
18
|
+
from .tagstatistics import TagStatistics, TagStatisticsBuilder
|
|
19
19
|
from .visitor import SuiteVisitor
|
|
20
20
|
|
|
21
21
|
|
|
@@ -34,12 +34,16 @@ class Statistics:
|
|
|
34
34
|
tag_stat_exclude, tag_stat_combine,
|
|
35
35
|
tag_doc, tag_stat_link)
|
|
36
36
|
suite.visit(StatisticsBuilder(total_builder, suite_builder, tag_builder))
|
|
37
|
-
|
|
38
|
-
self.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
self.total: TotalStatistics = total_builder.stats
|
|
38
|
+
self.suite: SuiteStatistics = suite_builder.stats
|
|
39
|
+
self.tags: TagStatistics = tag_builder.stats
|
|
40
|
+
|
|
41
|
+
def to_dict(self):
|
|
42
|
+
return {
|
|
43
|
+
'total': self.total.stat.get_attributes(include_label=True),
|
|
44
|
+
'suites': [s.get_attributes(include_label=True) for s in self.suite],
|
|
45
|
+
'tags': [t.get_attributes(include_label=True) for t in self.tags],
|
|
46
|
+
}
|
|
43
47
|
|
|
44
48
|
def visit(self, visitor):
|
|
45
49
|
visitor.visit_statistics(self)
|
|
@@ -15,8 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
from datetime import timedelta
|
|
17
17
|
|
|
18
|
-
from robot.utils import
|
|
19
|
-
is_string, normalize)
|
|
18
|
+
from robot.utils import elapsed_time_to_string, html_escape, normalize, Sortable
|
|
20
19
|
|
|
21
20
|
from .tags import TagPattern
|
|
22
21
|
|
|
@@ -40,28 +39,27 @@ class Stat(Sortable):
|
|
|
40
39
|
self._norm_name = normalize(name, ignore='_')
|
|
41
40
|
|
|
42
41
|
def get_attributes(self, include_label=False, include_elapsed=False,
|
|
43
|
-
exclude_empty=True, values_as_strings=False,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
exclude_empty=True, values_as_strings=False, html_escape=False):
|
|
43
|
+
attrs = {
|
|
44
|
+
**({'label': self.name} if include_label else {}),
|
|
45
|
+
**self._get_custom_attrs(),
|
|
46
|
+
**{'pass': self.passed, 'fail': self.failed, 'skip': self.skipped},
|
|
47
|
+
}
|
|
49
48
|
if include_elapsed:
|
|
50
49
|
attrs['elapsed'] = elapsed_time_to_string(self.elapsed, include_millis=False)
|
|
51
50
|
if exclude_empty:
|
|
52
|
-
attrs =
|
|
51
|
+
attrs = {k: v for k, v in attrs.items() if v not in ('', None)}
|
|
53
52
|
if values_as_strings:
|
|
54
|
-
attrs =
|
|
55
|
-
for k, v in attrs.items())
|
|
53
|
+
attrs = {k: str(v if v is not None else '') for k, v in attrs.items()}
|
|
56
54
|
if html_escape:
|
|
57
|
-
attrs =
|
|
55
|
+
attrs = {k: self._html_escape(v) for k, v in attrs.items()}
|
|
58
56
|
return attrs
|
|
59
57
|
|
|
60
58
|
def _get_custom_attrs(self):
|
|
61
59
|
return {}
|
|
62
60
|
|
|
63
61
|
def _html_escape(self, item):
|
|
64
|
-
return html_escape(item) if
|
|
62
|
+
return html_escape(item) if isinstance(item, str) else item
|
|
65
63
|
|
|
66
64
|
@property
|
|
67
65
|
def total(self):
|
|
@@ -109,7 +107,7 @@ class SuiteStat(Stat):
|
|
|
109
107
|
self._name = suite.name
|
|
110
108
|
|
|
111
109
|
def _get_custom_attrs(self):
|
|
112
|
-
return {'
|
|
110
|
+
return {'name': self._name, 'id': self.id}
|
|
113
111
|
|
|
114
112
|
def _update_elapsed(self, test):
|
|
115
113
|
pass
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
+
from typing import Iterator
|
|
17
|
+
|
|
16
18
|
from .stats import SuiteStat
|
|
17
19
|
|
|
18
20
|
|
|
@@ -20,30 +22,27 @@ class SuiteStatistics:
|
|
|
20
22
|
"""Container for suite statistics."""
|
|
21
23
|
|
|
22
24
|
def __init__(self, suite):
|
|
23
|
-
#: Instance of :class:`~robot.model.stats.SuiteStat`.
|
|
24
25
|
self.stat = SuiteStat(suite)
|
|
25
|
-
|
|
26
|
-
self.suites = []
|
|
26
|
+
self.suites: list[SuiteStatistics] = []
|
|
27
27
|
|
|
28
28
|
def visit(self, visitor):
|
|
29
29
|
visitor.visit_suite_statistics(self)
|
|
30
30
|
|
|
31
|
-
def __iter__(self):
|
|
31
|
+
def __iter__(self) -> Iterator[SuiteStat]:
|
|
32
32
|
yield self.stat
|
|
33
33
|
for child in self.suites:
|
|
34
|
-
|
|
35
|
-
yield stat
|
|
34
|
+
yield from child
|
|
36
35
|
|
|
37
36
|
|
|
38
37
|
class SuiteStatisticsBuilder:
|
|
39
38
|
|
|
40
39
|
def __init__(self, suite_stat_level):
|
|
41
40
|
self._suite_stat_level = suite_stat_level
|
|
42
|
-
self._stats_stack = []
|
|
43
|
-
self.stats = None
|
|
41
|
+
self._stats_stack: list[SuiteStatistics] = []
|
|
42
|
+
self.stats: SuiteStatistics | None = None
|
|
44
43
|
|
|
45
44
|
@property
|
|
46
|
-
def current(self):
|
|
45
|
+
def current(self) -> 'SuiteStatistics|None':
|
|
47
46
|
return self._stats_stack[-1] if self._stats_stack else None
|
|
48
47
|
|
|
49
48
|
def start_suite(self, suite):
|
|
@@ -108,6 +108,10 @@ class TagPatterns(Sequence['TagPattern']):
|
|
|
108
108
|
def __init__(self, patterns: Iterable[str] = ()):
|
|
109
109
|
self._patterns = tuple(TagPattern.from_string(p) for p in Tags(patterns))
|
|
110
110
|
|
|
111
|
+
@property
|
|
112
|
+
def is_constant(self):
|
|
113
|
+
return all(p.is_constant for p in self._patterns)
|
|
114
|
+
|
|
111
115
|
def match(self, tags: Iterable[str]) -> bool:
|
|
112
116
|
if not self._patterns:
|
|
113
117
|
return False
|
|
@@ -132,6 +136,7 @@ class TagPatterns(Sequence['TagPattern']):
|
|
|
132
136
|
|
|
133
137
|
|
|
134
138
|
class TagPattern(ABC):
|
|
139
|
+
is_constant = False
|
|
135
140
|
|
|
136
141
|
@classmethod
|
|
137
142
|
def from_string(cls, pattern: str) -> 'TagPattern':
|
|
@@ -166,6 +171,11 @@ class SingleTagPattern(TagPattern):
|
|
|
166
171
|
self._matcher = Matcher(normalize(pattern, ignore='_'),
|
|
167
172
|
caseless=False, spaceless=False)
|
|
168
173
|
|
|
174
|
+
@property
|
|
175
|
+
def is_constant(self):
|
|
176
|
+
pattern = self._matcher.pattern
|
|
177
|
+
return not ('*' in pattern or '?' in pattern or '[' in pattern)
|
|
178
|
+
|
|
169
179
|
def match(self, tags: Iterable[str]) -> bool:
|
|
170
180
|
tags = normalize_tags(tags)
|
|
171
181
|
return self._matcher.match_any(tags)
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
-
from itertools import chain
|
|
17
16
|
import re
|
|
17
|
+
from itertools import chain
|
|
18
18
|
|
|
19
19
|
from robot.utils import NormalizedDict
|
|
20
20
|
|
|
@@ -26,10 +26,7 @@ class TagStatistics:
|
|
|
26
26
|
"""Container for tag statistics."""
|
|
27
27
|
|
|
28
28
|
def __init__(self, combined_stats):
|
|
29
|
-
#: Dictionary, where key is the name of the tag as a string and value
|
|
30
|
-
#: is an instance of :class:`~robot.model.stats.TagStat`.
|
|
31
29
|
self.tags = NormalizedDict(ignore='_')
|
|
32
|
-
#: List of :class:`~robot.model.stats.CombinedTagStat` objects.
|
|
33
30
|
self.combined = combined_stats
|
|
34
31
|
|
|
35
32
|
def visit(self, visitor):
|
|
@@ -127,21 +124,23 @@ class TagStatLink:
|
|
|
127
124
|
return link, title
|
|
128
125
|
|
|
129
126
|
def _replace_groups(self, link, title, match):
|
|
130
|
-
for index, group in enumerate(match.groups()):
|
|
131
|
-
placefolder = '
|
|
127
|
+
for index, group in enumerate(match.groups(), start=1):
|
|
128
|
+
placefolder = f'%{index}'
|
|
132
129
|
link = link.replace(placefolder, group)
|
|
133
130
|
title = title.replace(placefolder, group)
|
|
134
131
|
return link, title
|
|
135
132
|
|
|
136
133
|
def _get_match_regexp(self, pattern):
|
|
137
|
-
pattern = '
|
|
134
|
+
pattern = ''.join(self._yield_match_pattern(pattern))
|
|
138
135
|
return re.compile(pattern, re.IGNORECASE)
|
|
139
136
|
|
|
140
137
|
def _yield_match_pattern(self, pattern):
|
|
138
|
+
yield '^'
|
|
141
139
|
for token in self._match_pattern_tokenizer.split(pattern):
|
|
142
140
|
if token.startswith('?'):
|
|
143
|
-
yield '(
|
|
141
|
+
yield f'({"."*len(token)})'
|
|
144
142
|
elif token == '*':
|
|
145
143
|
yield '(.*)'
|
|
146
144
|
else:
|
|
147
145
|
yield re.escape(token)
|
|
146
|
+
yield '$'
|
|
@@ -40,6 +40,7 @@ class TestCase(ModelObject, Generic[KW]):
|
|
|
40
40
|
Extended by :class:`robot.running.model.TestCase` and
|
|
41
41
|
:class:`robot.result.model.TestCase`.
|
|
42
42
|
"""
|
|
43
|
+
type = 'TEST'
|
|
43
44
|
body_class = Body
|
|
44
45
|
# See model.TestSuite on removing the type ignore directive
|
|
45
46
|
fixture_class: Type[KW] = Keyword # type: ignore
|
|
@@ -42,6 +42,7 @@ class TestSuite(ModelObject, Generic[KW, TC]):
|
|
|
42
42
|
Extended by :class:`robot.running.model.TestSuite` and
|
|
43
43
|
:class:`robot.result.model.TestSuite`.
|
|
44
44
|
"""
|
|
45
|
+
type = 'SUITE'
|
|
45
46
|
# FIXME: Type Ignore declarations: Typevars only accept subclasses of the bound class
|
|
46
47
|
# assigning `Type[KW]` to `Keyword` results in an error. In RF 7 the class should be
|
|
47
48
|
# made impossible to instantiate directly, and the assignments can be replaced with
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
from collections.abc import Iterator
|
|
17
17
|
|
|
18
|
-
from robot.utils import test_or_task
|
|
18
|
+
from robot.utils import plural_or_not, test_or_task
|
|
19
19
|
|
|
20
20
|
from .stats import TotalStat
|
|
21
21
|
from .visitor import SuiteVisitor
|
|
@@ -26,33 +26,33 @@ class TotalStatistics:
|
|
|
26
26
|
|
|
27
27
|
def __init__(self, rpa: bool = False):
|
|
28
28
|
#: Instance of :class:`~robot.model.stats.TotalStat` for all the tests.
|
|
29
|
-
self.
|
|
29
|
+
self.stat = TotalStat(test_or_task('All {Test}s', rpa))
|
|
30
30
|
self._rpa = rpa
|
|
31
31
|
|
|
32
32
|
def visit(self, visitor):
|
|
33
|
-
visitor.visit_total_statistics(self.
|
|
33
|
+
visitor.visit_total_statistics(self.stat)
|
|
34
34
|
|
|
35
35
|
def __iter__(self) -> 'Iterator[TotalStat]':
|
|
36
|
-
yield self.
|
|
36
|
+
yield self.stat
|
|
37
37
|
|
|
38
38
|
@property
|
|
39
39
|
def total(self) -> int:
|
|
40
|
-
return self.
|
|
40
|
+
return self.stat.total
|
|
41
41
|
|
|
42
42
|
@property
|
|
43
43
|
def passed(self) -> int:
|
|
44
|
-
return self.
|
|
44
|
+
return self.stat.passed
|
|
45
45
|
|
|
46
46
|
@property
|
|
47
47
|
def skipped(self) -> int:
|
|
48
|
-
return self.
|
|
48
|
+
return self.stat.skipped
|
|
49
49
|
|
|
50
50
|
@property
|
|
51
51
|
def failed(self) -> int:
|
|
52
|
-
return self.
|
|
52
|
+
return self.stat.failed
|
|
53
53
|
|
|
54
54
|
def add_test(self, test):
|
|
55
|
-
self.
|
|
55
|
+
self.stat.add_test(test)
|
|
56
56
|
|
|
57
57
|
@property
|
|
58
58
|
def message(self) -> str:
|
|
@@ -61,18 +61,11 @@ class TotalStatistics:
|
|
|
61
61
|
For example::
|
|
62
62
|
2 tests, 1 passed, 1 failed
|
|
63
63
|
"""
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return ((template + ', %d skipped')
|
|
70
|
-
% (total, test_or_task, end, passed, failed, skipped))
|
|
71
|
-
return template % (total, test_or_task, end, passed, failed)
|
|
72
|
-
|
|
73
|
-
def _get_counts(self):
|
|
74
|
-
ending = 's' if self.total != 1 else ''
|
|
75
|
-
return self.total, ending, self.passed, self.failed, self.skipped
|
|
64
|
+
kind = test_or_task('test', self._rpa) + plural_or_not(self.total)
|
|
65
|
+
msg = f'{self.total} {kind}, {self.passed} passed, {self.failed} failed'
|
|
66
|
+
if self.skipped:
|
|
67
|
+
msg += f', {self.skipped} skipped'
|
|
68
|
+
return msg
|
|
76
69
|
|
|
77
70
|
|
|
78
71
|
class TotalStatisticsBuilder(SuiteVisitor):
|