robotframework 7.3.1__tar.gz → 7.3.2__tar.gz
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.3.1 → robotframework-7.3.2}/BUILD.rst +1 -1
- {robotframework-7.3.1 → robotframework-7.3.2}/PKG-INFO +2 -2
- {robotframework-7.3.1 → robotframework-7.3.2}/setup.py +1 -1
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/BuiltIn.py +5 -2
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/executionresult.py +51 -13
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/flattenkeywordmatcher.py +37 -1
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/resultbuilder.py +59 -53
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/suiteteardownfailed.py +6 -6
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/bodyrunner.py +3 -1
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/namespace.py +25 -7
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/json.py +51 -7
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/version.py +1 -1
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robotframework.egg-info/PKG-INFO +2 -2
- {robotframework-7.3.1 → robotframework-7.3.2}/AUTHORS.rst +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/CONTRIBUTING.rst +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/COPYRIGHT.txt +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/INSTALL.rst +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/LICENSE.txt +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/MANIFEST.in +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/README.rst +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/pyproject.toml +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/setup.cfg +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/__main__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/api/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/api/deco.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/api/exceptions.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/api/interfaces.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/api/logger.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/api/parsing.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/api/py.typed +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/conf/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/conf/gatherfailed.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/conf/languages.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/conf/settings.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/errors.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/common/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/common/js_disabled.css +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/common/storage.js +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/htmlfilewriter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/jsonwriter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/lib/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/lib/jquery.min.js +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/libdoc/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/libdoc/libdoc.html +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/common.css +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/doc_formatting.css +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/fileloading.js +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/log.css +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/log.html +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/log.js +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/model.js +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/print.css +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/report.css +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/report.html +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/testdata.js +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/util.js +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/rebot/view.js +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/template.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/testdoc/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/testdoc/testdoc.css +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/htmldata/testdoc/testdoc.html +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdoc.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/builder.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/consoleviewer.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/datatypes.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/htmlutils.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/htmlwriter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/jsonbuilder.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/jsonwriter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/languages.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/model.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/output.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/robotbuilder.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/standardtypes.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/writer.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/xmlbuilder.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libdocpkg/xmlwriter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/Collections.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/DateTime.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/Dialogs.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/Easter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/OperatingSystem.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/Process.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/Remote.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/Screenshot.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/String.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/Telnet.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/XML.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/libraries/dialogs_py.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/logo.png +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/body.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/configurer.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/control.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/filter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/fixture.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/itemlist.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/keyword.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/message.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/metadata.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/modelobject.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/modifier.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/namepatterns.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/statistics.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/stats.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/suitestatistics.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/tags.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/tagsetter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/tagstatistics.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/testcase.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/testsuite.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/totalstatistics.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/model/visitor.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/console/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/console/dotted.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/console/highlighting.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/console/quiet.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/console/verbose.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/debugfile.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/filelogger.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/jsonlogger.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/librarylogger.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/listeners.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/logger.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/loggerapi.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/loggerhelper.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/loglevel.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/output.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/outputfile.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/pyloggingconf.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/stdoutlogsplitter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/output/xmllogger.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/lexer/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/lexer/blocklexers.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/lexer/context.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/lexer/lexer.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/lexer/settings.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/lexer/statementlexers.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/lexer/tokenizer.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/lexer/tokens.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/model/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/model/blocks.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/model/statements.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/model/visitor.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/parser/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/parser/blockparsers.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/parser/fileparser.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/parser/parser.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/parsing/suitestructure.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/pythonpathsetter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/rebot.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/reporting/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/reporting/expandkeywordmatcher.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/reporting/jsbuildingcontext.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/reporting/jsexecutionresult.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/reporting/jsmodelbuilders.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/reporting/jswriter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/reporting/logreportwriters.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/reporting/outputwriter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/reporting/resultwriter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/reporting/stringcache.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/reporting/xunitwriter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/configurer.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/executionerrors.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/keywordremover.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/merger.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/messagefilter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/model.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/modeldeprecation.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/visitor.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/result/xmlelementhandlers.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/run.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/argumentconverter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/argumentmapper.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/argumentparser.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/argumentresolver.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/argumentspec.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/argumentvalidator.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/customconverters.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/embedded.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/typeconverters.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/typeinfo.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/typeinfoparser.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/arguments/typevalidator.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/builder/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/builder/builders.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/builder/parsers.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/builder/settings.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/builder/transformers.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/context.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/dynamicmethods.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/importer.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/invalidkeyword.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/keywordfinder.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/keywordimplementation.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/librarykeyword.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/librarykeywordrunner.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/libraryscopes.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/model.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/outputcapture.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/randomizer.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/resourcemodel.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/runkwregister.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/signalhandler.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/status.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/statusreporter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/suiterunner.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/testlibraries.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/timeouts/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/timeouts/nosupport.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/timeouts/posix.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/timeouts/runner.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/timeouts/timeout.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/timeouts/windows.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/running/userkeywordrunner.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/testdoc.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/application.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/argumentparser.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/asserts.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/charwidth.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/compress.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/connectioncache.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/dotdict.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/encoding.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/encodingsniffer.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/error.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/escaping.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/etreewrapper.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/filereader.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/frange.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/htmlformatters.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/importer.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/markuputils.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/markupwriters.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/match.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/misc.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/normalizing.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/notset.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/platform.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/recommendations.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/restreader.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/robotenv.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/robotinspect.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/robotio.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/robotpath.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/robottime.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/robottypes.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/setter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/sortable.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/text.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/typehints.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/utils/unic.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/__init__.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/assigner.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/evaluation.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/filesetter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/finders.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/notfound.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/replacer.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/resolvable.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/scopes.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/search.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/store.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/tablesetter.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robot/variables/variables.py +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robotframework.egg-info/SOURCES.txt +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robotframework.egg-info/dependency_links.txt +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robotframework.egg-info/entry_points.txt +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/src/robotframework.egg-info/top_level.txt +0 -0
- {robotframework-7.3.1 → robotframework-7.3.2}/tasks.py +0 -0
|
@@ -282,6 +282,6 @@ Announcements
|
|
|
282
282
|
2. `Forum <https://forum.robotframework.org/>`_.
|
|
283
283
|
|
|
284
284
|
3. `LinkedIn group <https://www.linkedin.com/groups/3710899/>`_. A personal
|
|
285
|
-
|
|
285
|
+
LinkedIn post is a good idea at least with bigger releases.
|
|
286
286
|
|
|
287
287
|
4. `robotframework-users <https://groups.google.com/group/robotframework-users>`_
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: robotframework
|
|
3
|
-
Version: 7.3.
|
|
3
|
+
Version: 7.3.2
|
|
4
4
|
Summary: Generic automation framework for acceptance testing and robotic process automation (RPA)
|
|
5
5
|
Home-page: https://robotframework.org
|
|
6
6
|
Download-URL: https://pypi.org/project/robotframework
|
|
@@ -10,7 +10,7 @@ License: Apache License 2.0
|
|
|
10
10
|
Project-URL: Source, https://github.com/robotframework/robotframework
|
|
11
11
|
Project-URL: Issue Tracker, https://github.com/robotframework/robotframework/issues
|
|
12
12
|
Project-URL: Documentation, https://robotframework.org/robotframework
|
|
13
|
-
Project-URL: Release Notes, https://github.com/robotframework/robotframework/blob/master/doc/releasenotes/rf-7.3.
|
|
13
|
+
Project-URL: Release Notes, https://github.com/robotframework/robotframework/blob/master/doc/releasenotes/rf-7.3.2.rst
|
|
14
14
|
Project-URL: Slack, http://slack.robotframework.org
|
|
15
15
|
Keywords: robotframework automation testautomation rpa testing acceptancetesting atdd bdd
|
|
16
16
|
Platform: any
|
|
@@ -6,7 +6,7 @@ from setuptools import find_packages, setup
|
|
|
6
6
|
|
|
7
7
|
# Version number typically updated by running `invoke set-version <version>`.
|
|
8
8
|
# Run `invoke --help set-version` or see tasks.py for details.
|
|
9
|
-
VERSION = "7.3.
|
|
9
|
+
VERSION = "7.3.2"
|
|
10
10
|
with open(join(dirname(abspath(__file__)), "README.rst")) as f:
|
|
11
11
|
LONG_DESCRIPTION = f.read()
|
|
12
12
|
base_url = "https://github.com/robotframework/robotframework/blob/master"
|
|
@@ -2184,11 +2184,14 @@ class _RunKeyword(_BuiltInBase):
|
|
|
2184
2184
|
# to 'Keyword.run', but then it would be better if 'Run Keyword' would support
|
|
2185
2185
|
# 'NONE' as a special value to not run anything similarly as setup/teardown.
|
|
2186
2186
|
replaced = ctx.variables.replace_scalar(name, ignore_errors=ctx.in_teardown)
|
|
2187
|
-
|
|
2188
|
-
if hasattr(runner, "embedded_args"):
|
|
2187
|
+
if self._accepts_embedded(replaced, ctx) and self._accepts_embedded(name, ctx):
|
|
2189
2188
|
return name, args
|
|
2190
2189
|
return replaced, args
|
|
2191
2190
|
|
|
2191
|
+
def _accepts_embedded(self, name, ctx):
|
|
2192
|
+
runner = ctx.get_runner(name, recommend_on_failure=False)
|
|
2193
|
+
return hasattr(runner, "embedded_args")
|
|
2194
|
+
|
|
2192
2195
|
def _replace_variables_in_name_with_list_variable(self, name, args, ctx):
|
|
2193
2196
|
# TODO: This seems to be the only place where `replace_until` is used.
|
|
2194
2197
|
# That functionality should be removed from `replace_list` and implemented
|
|
@@ -15,14 +15,15 @@
|
|
|
15
15
|
|
|
16
16
|
from datetime import datetime
|
|
17
17
|
from pathlib import Path
|
|
18
|
-
from typing import overload, TextIO
|
|
18
|
+
from typing import overload, Sequence, TextIO
|
|
19
19
|
|
|
20
20
|
from robot.errors import DataError
|
|
21
|
-
from robot.model import Statistics
|
|
21
|
+
from robot.model import Statistics, SuiteVisitor
|
|
22
22
|
from robot.utils import JsonDumper, JsonLoader, setter
|
|
23
23
|
from robot.version import get_full_version
|
|
24
24
|
|
|
25
25
|
from .executionerrors import ExecutionErrors
|
|
26
|
+
from .flattenkeywordmatcher import Flattener
|
|
26
27
|
from .model import TestSuite
|
|
27
28
|
|
|
28
29
|
|
|
@@ -154,17 +155,27 @@ class Result:
|
|
|
154
155
|
def from_json(
|
|
155
156
|
cls,
|
|
156
157
|
source: "str|bytes|TextIO|Path",
|
|
158
|
+
include_keywords: bool = True,
|
|
159
|
+
flattened_keywords: Sequence[str] = (),
|
|
157
160
|
rpa: "bool|None" = None,
|
|
158
161
|
) -> "Result":
|
|
159
162
|
"""Construct a result object from JSON data.
|
|
160
163
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
:param source: JSON data as a string or bytes containing the data
|
|
165
|
+
directly, an open file object where to read the data from, or a path
|
|
166
|
+
(``pathlib.Path`` or string) to a UTF-8 encoded file to read.
|
|
167
|
+
:param include_keywords: When ``False``, keyword and control structure
|
|
168
|
+
information is not parsed. This can save considerable amount of time
|
|
169
|
+
and memory. New in RF 7.3.2.
|
|
170
|
+
:param flattened_keywords: List of patterns controlling what keywords
|
|
171
|
+
and control structures to flatten. See the documentation of
|
|
172
|
+
the ``--flattenkeywords`` option for more details. New in RF 7.3.2.
|
|
173
|
+
:param rpa: Setting ``rpa`` either to ``True`` (RPA mode) or ``False``
|
|
174
|
+
(test automation) sets the execution mode explicitly. By default,
|
|
175
|
+
the mode is got from the parsed data.
|
|
176
|
+
:returns: :class:`Result` instance.
|
|
177
|
+
|
|
178
|
+
The data can contain either:
|
|
168
179
|
|
|
169
180
|
- full result data (contains suite information, execution errors, etc.)
|
|
170
181
|
got, for example, from the :meth:`to_json` method, or
|
|
@@ -174,13 +185,11 @@ class Result:
|
|
|
174
185
|
:attr:`statistics` are populated automatically based on suite information
|
|
175
186
|
and thus ignored if they are present in the data.
|
|
176
187
|
|
|
177
|
-
The ``rpa`` argument can be used to override the RPA mode. The mode is
|
|
178
|
-
got from the data by default.
|
|
179
|
-
|
|
180
188
|
New in Robot Framework 7.2.
|
|
181
189
|
"""
|
|
190
|
+
loader = cls._get_json_loader(include_keywords)
|
|
182
191
|
try:
|
|
183
|
-
data =
|
|
192
|
+
data = loader.load(source)
|
|
184
193
|
except (TypeError, ValueError) as err:
|
|
185
194
|
raise DataError(f"Loading JSON data failed: {err}")
|
|
186
195
|
if "suite" in data:
|
|
@@ -192,8 +201,27 @@ class Result:
|
|
|
192
201
|
result.source = source
|
|
193
202
|
elif isinstance(source, str) and source[0] != "{" and Path(source).exists():
|
|
194
203
|
result.source = Path(source)
|
|
204
|
+
result.handle_suite_teardown_failures()
|
|
205
|
+
if not include_keywords:
|
|
206
|
+
result.suite.visit(KeywordRemover())
|
|
207
|
+
if flattened_keywords:
|
|
208
|
+
result.suite.visit(Flattener(flattened_keywords))
|
|
195
209
|
return result
|
|
196
210
|
|
|
211
|
+
@classmethod
|
|
212
|
+
def _get_json_loader(cls, include_keywords: bool) -> JsonLoader:
|
|
213
|
+
if include_keywords:
|
|
214
|
+
return JsonLoader()
|
|
215
|
+
|
|
216
|
+
def remove_keywords(obj):
|
|
217
|
+
obj.pop("body", None)
|
|
218
|
+
obj.pop("setup", None)
|
|
219
|
+
# Teardowns cannot be removed yet, because we need to check suite
|
|
220
|
+
# teardown status. They are removed later using KeywordRemover.
|
|
221
|
+
return obj
|
|
222
|
+
|
|
223
|
+
return JsonLoader(object_hook=remove_keywords)
|
|
224
|
+
|
|
197
225
|
@classmethod
|
|
198
226
|
def _from_full_json(cls, data) -> "Result":
|
|
199
227
|
return Result(
|
|
@@ -355,3 +383,13 @@ class CombinedResult(Result):
|
|
|
355
383
|
self.set_execution_mode(other)
|
|
356
384
|
self.suite.suites.append(other.suite)
|
|
357
385
|
self.errors.add(other.errors)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
class KeywordRemover(SuiteVisitor):
|
|
389
|
+
|
|
390
|
+
def start_suite(self, suite):
|
|
391
|
+
suite.setup = suite.teardown = None
|
|
392
|
+
|
|
393
|
+
def visit_test(self, test):
|
|
394
|
+
test.setup = test.teardown = None
|
|
395
|
+
test.body = []
|
|
@@ -57,7 +57,8 @@ class FlattenByTypeMatcher:
|
|
|
57
57
|
if "while" in flatten:
|
|
58
58
|
self.types.add("while")
|
|
59
59
|
if "iteration" in flatten or "foritem" in flatten:
|
|
60
|
-
self.types.add("iter")
|
|
60
|
+
self.types.add("iter") # Matches output.xml tag.
|
|
61
|
+
self.types.add("iteration") # Matches model object type.
|
|
61
62
|
|
|
62
63
|
def match(self, tag):
|
|
63
64
|
return tag in self.types
|
|
@@ -97,6 +98,34 @@ class FlattenByTagMatcher:
|
|
|
97
98
|
return bool(self._matcher)
|
|
98
99
|
|
|
99
100
|
|
|
101
|
+
class Flattener(SuiteVisitor):
|
|
102
|
+
|
|
103
|
+
def __init__(self, flatten):
|
|
104
|
+
self.name_matcher = FlattenByNameMatcher(flatten)
|
|
105
|
+
self.tag_matcher = FlattenByTagMatcher(flatten)
|
|
106
|
+
self.type_matcher = FlattenByTypeMatcher(flatten)
|
|
107
|
+
|
|
108
|
+
def start_suite(self, suite):
|
|
109
|
+
return bool(self)
|
|
110
|
+
|
|
111
|
+
def start_keyword(self, kw):
|
|
112
|
+
if self.name_matcher and self.name_matcher.match(kw.name, kw.owner):
|
|
113
|
+
self._flatten(kw)
|
|
114
|
+
if self.tag_matcher and self.tag_matcher.match(kw.tags):
|
|
115
|
+
self._flatten(kw)
|
|
116
|
+
|
|
117
|
+
def start_body_item(self, item):
|
|
118
|
+
if self.type_matcher and self.type_matcher.match(item.type.lower()):
|
|
119
|
+
self._flatten(item)
|
|
120
|
+
|
|
121
|
+
def _flatten(self, item):
|
|
122
|
+
item.message = create_flatten_message(item.message)
|
|
123
|
+
item.body = MessageFinder(item).messages
|
|
124
|
+
|
|
125
|
+
def __bool__(self):
|
|
126
|
+
return bool(self.name_matcher or self.tag_matcher or self.type_matcher)
|
|
127
|
+
|
|
128
|
+
|
|
100
129
|
class FlattenByTags(SuiteVisitor):
|
|
101
130
|
|
|
102
131
|
def __init__(self, flatten):
|
|
@@ -122,3 +151,10 @@ class MessageFinder(SuiteVisitor):
|
|
|
122
151
|
|
|
123
152
|
def visit_message(self, message):
|
|
124
153
|
self.messages.append(message)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# TODO: Refactor this module in RF 7.4.
|
|
157
|
+
# - Currently code working with XML tags and model objects is somewhat messy.
|
|
158
|
+
# Either separate it better or make it more generic.
|
|
159
|
+
# - MessageFinder API is now that nice.
|
|
160
|
+
# - The module doesn't anymore contain only matchers so it should be renamed.
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
+
from typing import Sequence
|
|
16
17
|
from xml.etree import ElementTree as ET
|
|
17
18
|
|
|
18
19
|
from robot.errors import DataError
|
|
19
|
-
from robot.model import SuiteVisitor
|
|
20
20
|
from robot.utils import ETSource, get_error_message
|
|
21
21
|
|
|
22
|
-
from .executionresult import CombinedResult, is_json_source, Result
|
|
22
|
+
from .executionresult import CombinedResult, is_json_source, KeywordRemover, Result
|
|
23
23
|
from .flattenkeywordmatcher import (
|
|
24
24
|
create_flatten_message, FlattenByNameMatcher, FlattenByTags, FlattenByTypeMatcher
|
|
25
25
|
)
|
|
@@ -27,20 +27,28 @@ from .merger import Merger
|
|
|
27
27
|
from .xmlelementhandlers import XmlElementHandler
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
def ExecutionResult(
|
|
30
|
+
def ExecutionResult(
|
|
31
|
+
*sources,
|
|
32
|
+
merge: bool = False,
|
|
33
|
+
include_keywords: bool = True,
|
|
34
|
+
flattened_keywords: Sequence[str] = (),
|
|
35
|
+
rpa: "bool|None" = None,
|
|
36
|
+
):
|
|
31
37
|
"""Factory method to constructs :class:`~.executionresult.Result` objects.
|
|
32
38
|
|
|
33
39
|
:param sources: XML or JSON source(s) containing execution results.
|
|
34
40
|
Can be specified as paths (``pathlib.Path`` or ``str``), opened file
|
|
35
41
|
objects, or strings/bytes containing XML/JSON directly.
|
|
36
|
-
:param
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
:param merge: When ``True`` and multiple sources are given, results are merged
|
|
43
|
+
instead of combined.
|
|
44
|
+
:param include_keywords: When ``False``, keyword and control structure information
|
|
45
|
+
is not parsed. This can save considerable amount of time and memory.
|
|
46
|
+
:param flattened_keywords: List of patterns controlling what keywords
|
|
47
|
+
and control structures to flatten. See the documentation of
|
|
48
|
+
the ``--flattenkeywords`` option for more details.
|
|
49
|
+
:param rpa: Setting ``rpa`` either to ``True`` (RPA mode) or ``False`` (test
|
|
50
|
+
automation) sets the execution mode explicitly. By default, the mode is got
|
|
41
51
|
from processed output files and conflicting modes cause an error.
|
|
42
|
-
Other options are passed directly to the
|
|
43
|
-
:class:`ExecutionResultBuilder` object used internally.
|
|
44
52
|
:returns: :class:`~.executionresult.Result` instance.
|
|
45
53
|
|
|
46
54
|
A source is considered to be JSON in these cases:
|
|
@@ -53,7 +61,12 @@ def ExecutionResult(*sources, **options):
|
|
|
53
61
|
"""
|
|
54
62
|
if not sources:
|
|
55
63
|
raise DataError("One or more data source needed.")
|
|
56
|
-
|
|
64
|
+
options = {
|
|
65
|
+
"include_keywords": include_keywords,
|
|
66
|
+
"flattened_keywords": flattened_keywords,
|
|
67
|
+
"rpa": rpa,
|
|
68
|
+
}
|
|
69
|
+
if merge:
|
|
57
70
|
return _merge_results(sources[0], sources[1:], options)
|
|
58
71
|
if len(sources) > 1:
|
|
59
72
|
return _combine_results(sources, options)
|
|
@@ -63,8 +76,8 @@ def ExecutionResult(*sources, **options):
|
|
|
63
76
|
def _merge_results(original, merged, options):
|
|
64
77
|
result = ExecutionResult(original, **options)
|
|
65
78
|
merger = Merger(result, rpa=result.rpa)
|
|
66
|
-
for
|
|
67
|
-
merged = ExecutionResult(
|
|
79
|
+
for source in merged:
|
|
80
|
+
merged = ExecutionResult(source, **options)
|
|
68
81
|
merger.merge(merged)
|
|
69
82
|
return result
|
|
70
83
|
|
|
@@ -75,13 +88,13 @@ def _combine_results(sources, options):
|
|
|
75
88
|
|
|
76
89
|
def _single_result(source, options):
|
|
77
90
|
if is_json_source(source):
|
|
78
|
-
return _json_result(source, options)
|
|
79
|
-
return _xml_result(source, options)
|
|
91
|
+
return _json_result(source, **options)
|
|
92
|
+
return _xml_result(source, **options)
|
|
80
93
|
|
|
81
94
|
|
|
82
|
-
def _json_result(source,
|
|
95
|
+
def _json_result(source, include_keywords, flattened_keywords, rpa):
|
|
83
96
|
try:
|
|
84
|
-
return Result.from_json(source, rpa
|
|
97
|
+
return Result.from_json(source, include_keywords, flattened_keywords, rpa)
|
|
85
98
|
except IOError as err:
|
|
86
99
|
error = err.strerror
|
|
87
100
|
except Exception:
|
|
@@ -89,11 +102,12 @@ def _json_result(source, options):
|
|
|
89
102
|
raise DataError(f"Reading JSON source '{source}' failed: {error}")
|
|
90
103
|
|
|
91
104
|
|
|
92
|
-
def _xml_result(source,
|
|
105
|
+
def _xml_result(source, include_keywords, flattened_keywords, rpa):
|
|
93
106
|
ets = ETSource(source)
|
|
94
|
-
|
|
107
|
+
builder = ExecutionResultBuilder(ets, include_keywords, flattened_keywords)
|
|
108
|
+
result = Result(source, rpa=rpa)
|
|
95
109
|
try:
|
|
96
|
-
return
|
|
110
|
+
return builder.build(result)
|
|
97
111
|
except IOError as err:
|
|
98
112
|
error = err.strerror
|
|
99
113
|
except Exception:
|
|
@@ -101,6 +115,9 @@ def _xml_result(source, options):
|
|
|
101
115
|
raise DataError(f"Reading XML source '{ets}' failed: {error}")
|
|
102
116
|
|
|
103
117
|
|
|
118
|
+
# TODO:
|
|
119
|
+
# - Rename e.g. to XmlExecutionResultBuilder. Probably best done in a major release.
|
|
120
|
+
# - Add Result.from_xml as a more convenient API. Could be done in RF 7.4.
|
|
104
121
|
class ExecutionResultBuilder:
|
|
105
122
|
"""Builds :class:`~.executionresult.Result` objects based on XML output files.
|
|
106
123
|
|
|
@@ -108,7 +125,7 @@ class ExecutionResultBuilder:
|
|
|
108
125
|
:func:`ExecutionResult` factory method.
|
|
109
126
|
"""
|
|
110
127
|
|
|
111
|
-
def __init__(self, source, include_keywords=True, flattened_keywords=
|
|
128
|
+
def __init__(self, source, include_keywords=True, flattened_keywords=()):
|
|
112
129
|
"""
|
|
113
130
|
:param source: Path to the XML output file to build
|
|
114
131
|
:class:`~.executionresult.Result` objects from.
|
|
@@ -134,7 +151,7 @@ class ExecutionResultBuilder:
|
|
|
134
151
|
# flatten based on them when parsing output.xml.
|
|
135
152
|
result.suite.visit(FlattenByTags(self._flattened_keywords))
|
|
136
153
|
if not self._include_keywords:
|
|
137
|
-
result.suite.visit(
|
|
154
|
+
result.suite.visit(KeywordRemover())
|
|
138
155
|
return result
|
|
139
156
|
|
|
140
157
|
def _parse(self, source, start, end):
|
|
@@ -151,11 +168,11 @@ class ExecutionResultBuilder:
|
|
|
151
168
|
elem.clear()
|
|
152
169
|
|
|
153
170
|
def _omit_keywords(self, context):
|
|
154
|
-
omitted_elements = {"kw", "for", "while", "if", "try"}
|
|
171
|
+
omitted_elements = {"kw", "for", "while", "if", "try", "group", "variable"}
|
|
155
172
|
omitted = 0
|
|
156
173
|
for event, elem in context:
|
|
157
|
-
# Teardowns
|
|
158
|
-
# They
|
|
174
|
+
# Teardowns cannot be removed yet, because we need to check suite
|
|
175
|
+
# teardown status. They are removed later using KeywordRemover.
|
|
159
176
|
omit = elem.tag in omitted_elements and elem.get("type") != "TEARDOWN"
|
|
160
177
|
start = event == "start"
|
|
161
178
|
if omit and start:
|
|
@@ -172,44 +189,33 @@ class ExecutionResultBuilder:
|
|
|
172
189
|
name_match, by_name = self._get_matcher(FlattenByNameMatcher, flattened)
|
|
173
190
|
type_match, by_type = self._get_matcher(FlattenByTypeMatcher, flattened)
|
|
174
191
|
started = -1 # If 0 or more, we are flattening.
|
|
175
|
-
|
|
176
|
-
inside = 0 # To make sure we don't read tags from a test.
|
|
192
|
+
include_on_top = {"doc", "tag", "timeout", "status"}
|
|
177
193
|
for event, elem in context:
|
|
178
194
|
tag = elem.tag
|
|
179
195
|
if event == "start":
|
|
180
|
-
if
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
196
|
+
if started >= 0:
|
|
197
|
+
started += 1
|
|
198
|
+
elif (
|
|
199
|
+
by_name
|
|
200
|
+
and tag == "kw"
|
|
201
|
+
and name_match(
|
|
185
202
|
elem.get("name", ""),
|
|
186
203
|
elem.get("owner") or elem.get("library"),
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if started <= 0 or tag == "msg":
|
|
204
|
+
# 'library' is for RF < 7 compatibility
|
|
205
|
+
)
|
|
206
|
+
):
|
|
207
|
+
started = 0
|
|
208
|
+
elif by_type and type_match(tag):
|
|
209
|
+
started = 0
|
|
210
|
+
elif started == 1 and tag == "status":
|
|
211
|
+
elem.text = create_flatten_message(elem.text)
|
|
212
|
+
if started <= 0 or (started == 1 and tag in include_on_top) or tag == "msg":
|
|
197
213
|
yield event, elem
|
|
198
214
|
else:
|
|
199
215
|
elem.clear()
|
|
200
|
-
if started >= 0 and event == "end"
|
|
216
|
+
if started >= 0 and event == "end":
|
|
201
217
|
started -= 1
|
|
202
218
|
|
|
203
219
|
def _get_matcher(self, matcher_class, flattened):
|
|
204
220
|
matcher = matcher_class(flattened)
|
|
205
221
|
return matcher.match, bool(matcher)
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
class RemoveKeywords(SuiteVisitor):
|
|
209
|
-
|
|
210
|
-
def start_suite(self, suite):
|
|
211
|
-
suite.setup = None
|
|
212
|
-
suite.teardown = None
|
|
213
|
-
|
|
214
|
-
def visit_test(self, test):
|
|
215
|
-
test.body = []
|
|
@@ -19,12 +19,12 @@ from robot.model import SuiteVisitor
|
|
|
19
19
|
class SuiteTeardownFailureHandler(SuiteVisitor):
|
|
20
20
|
|
|
21
21
|
def end_suite(self, suite):
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
if suite.has_teardown:
|
|
23
|
+
teardown = suite.teardown
|
|
24
|
+
if teardown.status == teardown.FAIL:
|
|
25
|
+
suite.suite_teardown_failed(teardown.message)
|
|
26
|
+
if teardown.status == teardown.SKIP:
|
|
27
|
+
suite.suite_teardown_skipped(teardown.message)
|
|
28
28
|
|
|
29
29
|
def visit_test(self, test):
|
|
30
30
|
pass
|
|
@@ -108,7 +108,9 @@ class KeywordRunner:
|
|
|
108
108
|
# BuiltIn.run_keyword has the same logic.
|
|
109
109
|
runner = context.get_runner(name, recommend_on_failure=self._run)
|
|
110
110
|
if hasattr(runner, "embedded_args") and name != data.name:
|
|
111
|
-
|
|
111
|
+
candidate = context.get_runner(data.name)
|
|
112
|
+
if hasattr(candidate, "embedded_args"):
|
|
113
|
+
runner = candidate
|
|
112
114
|
return runner
|
|
113
115
|
|
|
114
116
|
|
|
@@ -17,6 +17,7 @@ import copy
|
|
|
17
17
|
import os
|
|
18
18
|
from collections import OrderedDict
|
|
19
19
|
|
|
20
|
+
from robot.conf import Languages
|
|
20
21
|
from robot.errors import DataError, KeywordError
|
|
21
22
|
from robot.libraries import STDLIBS
|
|
22
23
|
from robot.output import LOGGER, Message
|
|
@@ -231,7 +232,7 @@ class Namespace:
|
|
|
231
232
|
|
|
232
233
|
class KeywordStore:
|
|
233
234
|
|
|
234
|
-
def __init__(self, suite_file, languages):
|
|
235
|
+
def __init__(self, suite_file, languages: Languages):
|
|
235
236
|
self.suite_file = suite_file
|
|
236
237
|
self.libraries = OrderedDict()
|
|
237
238
|
self.resources = ImportCache()
|
|
@@ -300,6 +301,9 @@ class KeywordStore:
|
|
|
300
301
|
runner = None
|
|
301
302
|
if strip_bdd_prefix:
|
|
302
303
|
runner = self._get_bdd_style_runner(name)
|
|
304
|
+
if runner:
|
|
305
|
+
runner = copy.copy(runner)
|
|
306
|
+
runner.name = name
|
|
303
307
|
if not runner:
|
|
304
308
|
runner = self._get_runner_from_suite_file(name)
|
|
305
309
|
if not runner and "." in name:
|
|
@@ -309,13 +313,27 @@ class KeywordStore:
|
|
|
309
313
|
return runner
|
|
310
314
|
|
|
311
315
|
def _get_bdd_style_runner(self, name):
|
|
316
|
+
# TODO: Consider using 'startswith' instead of regexps for checking does any
|
|
317
|
+
# prefix match. That ought to make that check a bit faster (especially if the
|
|
318
|
+
# tuple of prefixes is pre-built in 'Languages'), but finding the keyword if
|
|
319
|
+
# there's a match can be a bit slower. It also makes it explicit that prefixes
|
|
320
|
+
# are constants, not patterns, and allows deprecating 'bdd_prefix_regexp'.
|
|
312
321
|
match = self.languages.bdd_prefix_regexp.match(name)
|
|
313
|
-
if match:
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
322
|
+
if not match:
|
|
323
|
+
return None
|
|
324
|
+
runner = self._get_runner(name[match.end() :], strip_bdd_prefix=False)
|
|
325
|
+
if runner:
|
|
326
|
+
return runner
|
|
327
|
+
# Some prefix matched, but there was no matching keyword. Go through all
|
|
328
|
+
# prefixes individually to see were there possibly multiple matching ones.
|
|
329
|
+
# https://github.com/robotframework/robotframework/issues/5456
|
|
330
|
+
name = " ".join(name.split()).title() # Normalize spaces and case.
|
|
331
|
+
for prefix in sorted(self.languages.bdd_prefixes, key=len, reverse=True):
|
|
332
|
+
prefix += " "
|
|
333
|
+
if name.startswith(prefix):
|
|
334
|
+
runner = self._get_runner(name[len(prefix) :], strip_bdd_prefix=False)
|
|
335
|
+
if runner:
|
|
336
|
+
return runner
|
|
319
337
|
return None
|
|
320
338
|
|
|
321
339
|
def _get_implicit_runner(self, name):
|
|
@@ -15,15 +15,48 @@
|
|
|
15
15
|
|
|
16
16
|
import json
|
|
17
17
|
from pathlib import Path
|
|
18
|
-
from typing import
|
|
18
|
+
from typing import Dict, overload, TextIO
|
|
19
19
|
|
|
20
20
|
from .error import get_error_message
|
|
21
21
|
from .robottypes import type_name
|
|
22
22
|
|
|
23
|
-
DataDict = Dict[str,
|
|
23
|
+
DataDict = Dict[str, object]
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class JsonLoader:
|
|
27
|
+
"""Generic JSON object loader.
|
|
28
|
+
|
|
29
|
+
JSON source can be a string or bytes, a path or an open file object.
|
|
30
|
+
The top level JSON item must always be a dictionary.
|
|
31
|
+
|
|
32
|
+
Supports the same configuration parameters as the underlying `json.load`__
|
|
33
|
+
except for ``object_pairs_hook``. As a special feature, handles duplicate
|
|
34
|
+
items so that lists are merged.
|
|
35
|
+
|
|
36
|
+
__ https://docs.python.org/3/library/json.html#json.load
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, **config):
|
|
40
|
+
self.config = self._add_hook_to_merge_duplicate_lists(config)
|
|
41
|
+
|
|
42
|
+
def _add_hook_to_merge_duplicate_lists(self, config):
|
|
43
|
+
object_hook = config.get("object_hook")
|
|
44
|
+
object_pairs_hook = config.get("object_pairs_hook")
|
|
45
|
+
if object_pairs_hook:
|
|
46
|
+
raise ValueError("'object_pairs_hook' is not supported.")
|
|
47
|
+
|
|
48
|
+
def merge_duplicate_lists(items: "list[tuple[str, object]]") -> DataDict:
|
|
49
|
+
data = {}
|
|
50
|
+
for name, value in items:
|
|
51
|
+
if name in data and isinstance(value, list):
|
|
52
|
+
data[name].extend(value)
|
|
53
|
+
else:
|
|
54
|
+
data[name] = value
|
|
55
|
+
return object_hook(data) if object_hook else data
|
|
56
|
+
|
|
57
|
+
config["object_pairs_hook"] = merge_duplicate_lists
|
|
58
|
+
return config
|
|
59
|
+
|
|
27
60
|
def load(self, source: "str|bytes|TextIO|Path") -> DataDict:
|
|
28
61
|
try:
|
|
29
62
|
data = self._load(source)
|
|
@@ -33,21 +66,30 @@ class JsonLoader:
|
|
|
33
66
|
raise TypeError(f"Expected dictionary, got {type_name(data)}.")
|
|
34
67
|
return data
|
|
35
68
|
|
|
36
|
-
def _load(self, source):
|
|
69
|
+
def _load(self, source: "str|bytes|TextIO|Path") -> object:
|
|
37
70
|
if self._is_path(source):
|
|
38
71
|
with open(source, encoding="UTF-8") as file:
|
|
39
|
-
return json.load(file)
|
|
72
|
+
return json.load(file, **self.config)
|
|
40
73
|
if hasattr(source, "read"):
|
|
41
|
-
return json.load(source)
|
|
42
|
-
return json.loads(source)
|
|
74
|
+
return json.load(source, **self.config)
|
|
75
|
+
return json.loads(source, **self.config)
|
|
43
76
|
|
|
44
|
-
def _is_path(self, source):
|
|
77
|
+
def _is_path(self, source: "str|bytes|TextIO|Path") -> bool:
|
|
45
78
|
if isinstance(source, Path):
|
|
46
79
|
return True
|
|
47
80
|
return isinstance(source, str) and "{" not in source
|
|
48
81
|
|
|
49
82
|
|
|
50
83
|
class JsonDumper:
|
|
84
|
+
"""Generic JSON dumper.
|
|
85
|
+
|
|
86
|
+
JSON can be written to a file given as a path or as an open file object.
|
|
87
|
+
If no output is given, JSON is returned as a string.
|
|
88
|
+
|
|
89
|
+
Supports the same configuration as the underlying `json.dump`__.
|
|
90
|
+
|
|
91
|
+
__ https://docs.python.org/3/library/json.html#json.load
|
|
92
|
+
"""
|
|
51
93
|
|
|
52
94
|
def __init__(self, **config):
|
|
53
95
|
self.config = config
|
|
@@ -64,8 +106,10 @@ class JsonDumper:
|
|
|
64
106
|
elif isinstance(output, (str, Path)):
|
|
65
107
|
with open(output, "w", encoding="UTF-8") as file:
|
|
66
108
|
json.dump(data, file, **self.config)
|
|
109
|
+
return None
|
|
67
110
|
elif hasattr(output, "write"):
|
|
68
111
|
json.dump(data, output, **self.config)
|
|
112
|
+
return None
|
|
69
113
|
else:
|
|
70
114
|
raise TypeError(
|
|
71
115
|
f"Output should be None, path or open file, got {type_name(output)}."
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: robotframework
|
|
3
|
-
Version: 7.3.
|
|
3
|
+
Version: 7.3.2
|
|
4
4
|
Summary: Generic automation framework for acceptance testing and robotic process automation (RPA)
|
|
5
5
|
Home-page: https://robotframework.org
|
|
6
6
|
Download-URL: https://pypi.org/project/robotframework
|
|
@@ -10,7 +10,7 @@ License: Apache License 2.0
|
|
|
10
10
|
Project-URL: Source, https://github.com/robotframework/robotframework
|
|
11
11
|
Project-URL: Issue Tracker, https://github.com/robotframework/robotframework/issues
|
|
12
12
|
Project-URL: Documentation, https://robotframework.org/robotframework
|
|
13
|
-
Project-URL: Release Notes, https://github.com/robotframework/robotframework/blob/master/doc/releasenotes/rf-7.3.
|
|
13
|
+
Project-URL: Release Notes, https://github.com/robotframework/robotframework/blob/master/doc/releasenotes/rf-7.3.2.rst
|
|
14
14
|
Project-URL: Slack, http://slack.robotframework.org
|
|
15
15
|
Keywords: robotframework automation testautomation rpa testing acceptancetesting atdd bdd
|
|
16
16
|
Platform: any
|
|
File without changes
|
|
File without changes
|
|
File without changes
|