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
|
@@ -105,9 +105,9 @@ removed altogether if they get in the way.
|
|
|
105
105
|
from typing import TYPE_CHECKING
|
|
106
106
|
|
|
107
107
|
if TYPE_CHECKING:
|
|
108
|
-
from robot.model import (Break, BodyItem, Continue, Error, For,
|
|
109
|
-
Keyword, Message, Return, TestCase, TestSuite,
|
|
110
|
-
TryBranch, Var, While)
|
|
108
|
+
from robot.model import (Break, BodyItem, Continue, Error, For, Group, If,
|
|
109
|
+
IfBranch, Keyword, Message, Return, TestCase, TestSuite,
|
|
110
|
+
Try, TryBranch, Var, While)
|
|
111
111
|
from robot.result import ForIteration, WhileIteration
|
|
112
112
|
|
|
113
113
|
|
|
@@ -427,6 +427,32 @@ class SuiteVisitor:
|
|
|
427
427
|
"""
|
|
428
428
|
self.end_body_item(iteration)
|
|
429
429
|
|
|
430
|
+
def visit_group(self, group: 'Group'):
|
|
431
|
+
"""Visits GROUP elements.
|
|
432
|
+
|
|
433
|
+
Can be overridden to allow modifying the passed in ``group`` without
|
|
434
|
+
calling :meth:`start_group` or :meth:`end_group` nor visiting body.
|
|
435
|
+
"""
|
|
436
|
+
if self.start_group(group) is not False:
|
|
437
|
+
group.body.visit(self)
|
|
438
|
+
self.end_group(group)
|
|
439
|
+
|
|
440
|
+
def start_group(self, group: 'Group') -> 'bool|None':
|
|
441
|
+
"""Called when a GROUP element starts.
|
|
442
|
+
|
|
443
|
+
By default, calls :meth:`start_body_item` which, by default, does nothing.
|
|
444
|
+
|
|
445
|
+
Can return explicit ``False`` to stop visiting.
|
|
446
|
+
"""
|
|
447
|
+
return self.start_body_item(group)
|
|
448
|
+
|
|
449
|
+
def end_group(self, group: 'Group'):
|
|
450
|
+
"""Called when a GROUP element ends.
|
|
451
|
+
|
|
452
|
+
By default, calls :meth:`end_body_item` which, by default, does nothing.
|
|
453
|
+
"""
|
|
454
|
+
self.end_body_item(group)
|
|
455
|
+
|
|
430
456
|
def visit_var(self, var: 'Var'):
|
|
431
457
|
"""Visits a VAR elements."""
|
|
432
458
|
if self.start_var(var) is not False:
|
|
@@ -19,7 +19,8 @@ Not part of the public API, and also subject to change in the future when
|
|
|
19
19
|
test execution is refactored.
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
from .output import Output
|
|
23
22
|
from .logger import LOGGER
|
|
24
|
-
from .xmllogger import XmlLogger
|
|
25
23
|
from .loggerhelper import LEVELS, Message
|
|
24
|
+
from .loglevel import LogLevel
|
|
25
|
+
from .output import Output
|
|
26
|
+
from .xmllogger import XmlLogger
|
|
@@ -14,14 +14,17 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
16
|
import sys
|
|
17
|
+
from typing import TYPE_CHECKING
|
|
17
18
|
|
|
18
19
|
from robot.model import SuiteVisitor
|
|
19
|
-
from robot.result import TestCase, TestSuite
|
|
20
20
|
from robot.utils import plural_or_not as s, secs_to_timestr
|
|
21
21
|
|
|
22
22
|
from .highlighting import HighlightingStream
|
|
23
23
|
from ..loggerapi import LoggerApi
|
|
24
24
|
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from robot.result import TestCase, TestSuite
|
|
27
|
+
|
|
25
28
|
|
|
26
29
|
class DottedOutput(LoggerApi):
|
|
27
30
|
|
|
@@ -72,7 +75,7 @@ class StatusReporter(SuiteVisitor):
|
|
|
72
75
|
self.stream = stream
|
|
73
76
|
self.width = width
|
|
74
77
|
|
|
75
|
-
def report(self, suite: TestSuite):
|
|
78
|
+
def report(self, suite: 'TestSuite'):
|
|
76
79
|
suite.visit(self)
|
|
77
80
|
stats = suite.statistics
|
|
78
81
|
ts = ('test' if not suite.rpa else 'task') + s(stats.total)
|
|
@@ -83,7 +86,7 @@ class StatusReporter(SuiteVisitor):
|
|
|
83
86
|
self.stream.highlight(suite.status + ed, suite.status)
|
|
84
87
|
self.stream.write(f'\n{stats.message}\n')
|
|
85
88
|
|
|
86
|
-
def visit_test(self, test: TestCase):
|
|
89
|
+
def visit_test(self, test: 'TestCase'):
|
|
87
90
|
if test.failed and not test.tags.robot('exit'):
|
|
88
91
|
self.stream.write('-' * self.width + '\n')
|
|
89
92
|
self.stream.highlight('FAIL')
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
|
|
20
20
|
import errno
|
|
21
21
|
import os
|
|
22
|
-
import socket
|
|
23
22
|
import sys
|
|
24
23
|
from contextlib import contextmanager
|
|
25
24
|
try:
|
|
@@ -44,10 +43,12 @@ from robot.utils import console_encode, isatty, WINDOWS
|
|
|
44
43
|
class HighlightingStream:
|
|
45
44
|
|
|
46
45
|
def __init__(self, stream, colors='AUTO', links='AUTO'):
|
|
47
|
-
self.stream = stream
|
|
46
|
+
self.stream = stream or NullStream()
|
|
48
47
|
self._highlighter = self._get_highlighter(stream, colors, links)
|
|
49
48
|
|
|
50
49
|
def _get_highlighter(self, stream, colors, links):
|
|
50
|
+
if not stream:
|
|
51
|
+
return NoHighlighting()
|
|
51
52
|
options = {'AUTO': Highlighter if isatty(stream) else NoHighlighting,
|
|
52
53
|
'ON': Highlighter,
|
|
53
54
|
'OFF': NoHighlighting,
|
|
@@ -103,7 +104,7 @@ class HighlightingStream:
|
|
|
103
104
|
def error(self, message, level):
|
|
104
105
|
self.write('[ ', flush=False)
|
|
105
106
|
self.highlight(level, flush=False)
|
|
106
|
-
self.write(' ]
|
|
107
|
+
self.write(f' ] {message}\n')
|
|
107
108
|
|
|
108
109
|
@contextmanager
|
|
109
110
|
def _highlighting(self, status):
|
|
@@ -120,10 +121,19 @@ class HighlightingStream:
|
|
|
120
121
|
highlighter.reset()
|
|
121
122
|
|
|
122
123
|
def result_file(self, kind, path):
|
|
123
|
-
path = self._highlighter.link(path)
|
|
124
|
+
path = self._highlighter.link(path) if path else 'NONE'
|
|
124
125
|
self.write(f"{kind + ':':8} {path}\n")
|
|
125
126
|
|
|
126
127
|
|
|
128
|
+
class NullStream:
|
|
129
|
+
|
|
130
|
+
def write(self, text):
|
|
131
|
+
pass
|
|
132
|
+
|
|
133
|
+
def flush(self):
|
|
134
|
+
pass
|
|
135
|
+
|
|
136
|
+
|
|
127
137
|
def Highlighter(stream, links=True):
|
|
128
138
|
if os.sep == '/':
|
|
129
139
|
return AnsiHighlighter(stream, links)
|
|
@@ -163,12 +173,7 @@ class AnsiHighlighter:
|
|
|
163
173
|
uri = path.as_uri()
|
|
164
174
|
except ValueError:
|
|
165
175
|
return path
|
|
166
|
-
#
|
|
167
|
-
# Windows Terminal doesn't yet support the host component, though:
|
|
168
|
-
# https://github.com/microsoft/terminal/issues/14116
|
|
169
|
-
if uri[:8] == 'file:///' and not WINDOWS:
|
|
170
|
-
uri = f'file://{socket.getfqdn()}/{uri[8:]}'
|
|
171
|
-
# The hyperlink format is documented here:
|
|
176
|
+
# Terminal hyperlink syntax is documented here:
|
|
172
177
|
# https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
|
|
173
178
|
return f'\033]8;;{uri}\033\\{path}\033]8;;\033\\'
|
|
174
179
|
|
|
@@ -178,6 +183,9 @@ class AnsiHighlighter:
|
|
|
178
183
|
|
|
179
184
|
class NoHighlighting(AnsiHighlighter):
|
|
180
185
|
|
|
186
|
+
def __init__(self, stream=None, links=True):
|
|
187
|
+
super().__init__(stream, links)
|
|
188
|
+
|
|
181
189
|
def link(self, path):
|
|
182
190
|
return path
|
|
183
191
|
|
|
@@ -20,7 +20,7 @@ from robot.utils import file_writer, seq2str2
|
|
|
20
20
|
|
|
21
21
|
from .logger import LOGGER
|
|
22
22
|
from .loggerapi import LoggerApi
|
|
23
|
-
from .
|
|
23
|
+
from .loglevel import LogLevel
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
def DebugFile(path):
|
|
@@ -45,7 +45,7 @@ class _DebugFileWriter(LoggerApi):
|
|
|
45
45
|
self._kw_level = 0
|
|
46
46
|
self._separator_written_last = False
|
|
47
47
|
self._outfile = outfile
|
|
48
|
-
self._is_logged =
|
|
48
|
+
self._is_logged = LogLevel('DEBUG').is_logged
|
|
49
49
|
|
|
50
50
|
def start_suite(self, data, result):
|
|
51
51
|
self._separator('SUITE')
|
|
@@ -91,7 +91,7 @@ class _DebugFileWriter(LoggerApi):
|
|
|
91
91
|
self._kw_level -= 1
|
|
92
92
|
|
|
93
93
|
def log_message(self, msg):
|
|
94
|
-
if self._is_logged(msg
|
|
94
|
+
if self._is_logged(msg):
|
|
95
95
|
self._write(f'{msg.timestamp} - {msg.level} - {msg.message}')
|
|
96
96
|
|
|
97
97
|
def close(self):
|
|
@@ -15,21 +15,25 @@
|
|
|
15
15
|
|
|
16
16
|
from robot.utils import file_writer
|
|
17
17
|
|
|
18
|
-
from .loggerhelper import AbstractLogger
|
|
19
18
|
from .loggerapi import LoggerApi
|
|
19
|
+
from .loggerhelper import AbstractLogger
|
|
20
|
+
from .loglevel import LogLevel
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class FileLogger(AbstractLogger, LoggerApi):
|
|
23
24
|
|
|
24
25
|
def __init__(self, path, level):
|
|
25
|
-
|
|
26
|
+
self._log_level = LogLevel(level)
|
|
26
27
|
self._writer = self._get_writer(path) # unit test hook
|
|
27
28
|
|
|
28
29
|
def _get_writer(self, path):
|
|
29
30
|
return file_writer(path, usage='syslog')
|
|
30
31
|
|
|
32
|
+
def set_level(self, level):
|
|
33
|
+
self._log_level.set(level)
|
|
34
|
+
|
|
31
35
|
def message(self, msg):
|
|
32
|
-
if self.
|
|
36
|
+
if self._log_level.is_logged(msg) and not self._writer.closed:
|
|
33
37
|
entry = '%s | %s | %s\n' % (msg.timestamp, msg.level.ljust(5),
|
|
34
38
|
msg.message)
|
|
35
39
|
self._writer.write(entry)
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# Copyright 2008-2015 Nokia Networks
|
|
2
|
+
# Copyright 2016- Robot Framework Foundation
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
from collections.abc import Mapping, Sequence
|
|
18
|
+
from datetime import datetime
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import TextIO
|
|
21
|
+
|
|
22
|
+
from robot.version import get_full_version
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class JsonLogger:
|
|
26
|
+
|
|
27
|
+
def __init__(self, file: TextIO, rpa: bool = False):
|
|
28
|
+
self.writer = JsonWriter(file)
|
|
29
|
+
self.writer.start_dict(generator=get_full_version('Robot'),
|
|
30
|
+
generated=datetime.now().isoformat(),
|
|
31
|
+
rpa=Raw(self.writer.encode(rpa)))
|
|
32
|
+
self.containers = []
|
|
33
|
+
|
|
34
|
+
def start_suite(self, suite):
|
|
35
|
+
if not self.containers:
|
|
36
|
+
name = 'suite'
|
|
37
|
+
container = None
|
|
38
|
+
else:
|
|
39
|
+
name = None
|
|
40
|
+
container = 'suites'
|
|
41
|
+
self._start(container, name, id=suite.id)
|
|
42
|
+
|
|
43
|
+
def end_suite(self, suite):
|
|
44
|
+
self._end(name=suite.name,
|
|
45
|
+
doc=suite.doc,
|
|
46
|
+
metadata=suite.metadata,
|
|
47
|
+
source=suite.source,
|
|
48
|
+
rpa=suite.rpa,
|
|
49
|
+
**self._status(suite))
|
|
50
|
+
|
|
51
|
+
def start_test(self, test):
|
|
52
|
+
self._start('tests', id=test.id)
|
|
53
|
+
|
|
54
|
+
def end_test(self, test):
|
|
55
|
+
self._end(name=test.name,
|
|
56
|
+
doc=test.doc,
|
|
57
|
+
tags=test.tags,
|
|
58
|
+
lineno=test.lineno,
|
|
59
|
+
timeout=str(test.timeout) if test.timeout else None,
|
|
60
|
+
**self._status(test))
|
|
61
|
+
|
|
62
|
+
def start_keyword(self, kw):
|
|
63
|
+
if kw.type in ('SETUP', 'TEARDOWN'):
|
|
64
|
+
self._end_container()
|
|
65
|
+
name = kw.type.lower()
|
|
66
|
+
container = None
|
|
67
|
+
else:
|
|
68
|
+
name = None
|
|
69
|
+
container = 'body'
|
|
70
|
+
self._start(container, name)
|
|
71
|
+
|
|
72
|
+
def end_keyword(self, kw):
|
|
73
|
+
self._end(name=kw.name,
|
|
74
|
+
owner=kw.owner,
|
|
75
|
+
source_name=kw.source_name,
|
|
76
|
+
args=[str(a) for a in kw.args],
|
|
77
|
+
assign=kw.assign,
|
|
78
|
+
tags=kw.tags,
|
|
79
|
+
doc=kw.doc,
|
|
80
|
+
timeout=str(kw.timeout) if kw.timeout else None,
|
|
81
|
+
**self._status(kw))
|
|
82
|
+
|
|
83
|
+
def start_for(self, item):
|
|
84
|
+
self._start(type=item.type)
|
|
85
|
+
|
|
86
|
+
def end_for(self, item):
|
|
87
|
+
self._end(flavor=item.flavor,
|
|
88
|
+
start=item.start,
|
|
89
|
+
mode=item.mode,
|
|
90
|
+
fill=UnlessNone(item.fill),
|
|
91
|
+
assign=item.assign,
|
|
92
|
+
values=item.values,
|
|
93
|
+
**self._status(item))
|
|
94
|
+
|
|
95
|
+
def start_for_iteration(self, item):
|
|
96
|
+
self._start(type=item.type)
|
|
97
|
+
|
|
98
|
+
def end_for_iteration(self, item):
|
|
99
|
+
self._end(assign=item.assign, **self._status(item))
|
|
100
|
+
|
|
101
|
+
def start_while(self, item):
|
|
102
|
+
self._start(type=item.type)
|
|
103
|
+
|
|
104
|
+
def end_while(self, item):
|
|
105
|
+
self._end(condition=item.condition,
|
|
106
|
+
limit=item.limit,
|
|
107
|
+
on_limit=item.on_limit,
|
|
108
|
+
on_limit_message=item.on_limit_message,
|
|
109
|
+
**self._status(item))
|
|
110
|
+
|
|
111
|
+
def start_while_iteration(self, item):
|
|
112
|
+
self._start(type=item.type)
|
|
113
|
+
|
|
114
|
+
def end_while_iteration(self, item):
|
|
115
|
+
self._end(**self._status(item))
|
|
116
|
+
|
|
117
|
+
def start_if(self, item):
|
|
118
|
+
self._start(type=item.type)
|
|
119
|
+
|
|
120
|
+
def end_if(self, item):
|
|
121
|
+
self._end(**self._status(item))
|
|
122
|
+
|
|
123
|
+
def start_if_branch(self, item):
|
|
124
|
+
self._start(type=item.type)
|
|
125
|
+
|
|
126
|
+
def end_if_branch(self, item):
|
|
127
|
+
self._end(condition=item.condition, **self._status(item))
|
|
128
|
+
|
|
129
|
+
def start_try(self, item):
|
|
130
|
+
self._start(type=item.type)
|
|
131
|
+
|
|
132
|
+
def end_try(self, item):
|
|
133
|
+
self._end(**self._status(item))
|
|
134
|
+
|
|
135
|
+
def start_try_branch(self, item):
|
|
136
|
+
self._start(type=item.type)
|
|
137
|
+
|
|
138
|
+
def end_try_branch(self, item):
|
|
139
|
+
self._end(patterns=item.patterns,
|
|
140
|
+
pattern_type=item.pattern_type,
|
|
141
|
+
assign=item.assign,
|
|
142
|
+
**self._status(item))
|
|
143
|
+
|
|
144
|
+
def start_group(self, item):
|
|
145
|
+
self._start(type=item.type)
|
|
146
|
+
|
|
147
|
+
def end_group(self, item):
|
|
148
|
+
self._end(name=item.name,
|
|
149
|
+
**self._status(item))
|
|
150
|
+
|
|
151
|
+
def start_var(self, item):
|
|
152
|
+
self._start(type=item.type)
|
|
153
|
+
|
|
154
|
+
def end_var(self, item):
|
|
155
|
+
self._end(name=item.name,
|
|
156
|
+
scope=item.scope,
|
|
157
|
+
separator=UnlessNone(item.separator),
|
|
158
|
+
value=item.value,
|
|
159
|
+
**self._status(item))
|
|
160
|
+
|
|
161
|
+
def start_return(self, item):
|
|
162
|
+
self._start(type=item.type)
|
|
163
|
+
|
|
164
|
+
def end_return(self, item):
|
|
165
|
+
self._end(values=item.values, **self._status(item))
|
|
166
|
+
|
|
167
|
+
def start_continue(self, item):
|
|
168
|
+
self._start(type=item.type)
|
|
169
|
+
|
|
170
|
+
def end_continue(self, item):
|
|
171
|
+
self._end(**self._status(item))
|
|
172
|
+
|
|
173
|
+
def start_break(self, item):
|
|
174
|
+
self._start(type=item.type)
|
|
175
|
+
|
|
176
|
+
def end_break(self, item):
|
|
177
|
+
self._end(**self._status(item))
|
|
178
|
+
|
|
179
|
+
def start_error(self, item):
|
|
180
|
+
self._start(type=item.type)
|
|
181
|
+
|
|
182
|
+
def end_error(self, item):
|
|
183
|
+
self._end(values=item.values, **self._status(item))
|
|
184
|
+
|
|
185
|
+
def message(self, msg):
|
|
186
|
+
self._dict(**msg.to_dict())
|
|
187
|
+
|
|
188
|
+
def errors(self, messages):
|
|
189
|
+
self._list('errors', [m.to_dict(include_type=False) for m in messages])
|
|
190
|
+
|
|
191
|
+
def statistics(self, stats):
|
|
192
|
+
data = stats.to_dict()
|
|
193
|
+
self._start(None, 'statistics')
|
|
194
|
+
self._dict(None, 'total', **data['total'])
|
|
195
|
+
self._list('suites', data['suites'])
|
|
196
|
+
self._list('tags', data['tags'])
|
|
197
|
+
self._end()
|
|
198
|
+
|
|
199
|
+
def close(self):
|
|
200
|
+
self.writer.end_dict()
|
|
201
|
+
self.writer.close()
|
|
202
|
+
|
|
203
|
+
def _status(self, item):
|
|
204
|
+
return {'status': item.status,
|
|
205
|
+
'message': item.message,
|
|
206
|
+
'start_time': item.start_time.isoformat() if item.start_time else None,
|
|
207
|
+
'elapsed_time': Raw(format(item.elapsed_time.total_seconds(), 'f'))}
|
|
208
|
+
|
|
209
|
+
def _dict(self, container: 'str|None' = 'body', name: 'str|None' = None, /,
|
|
210
|
+
**items):
|
|
211
|
+
self._start(container, name, **items)
|
|
212
|
+
self._end()
|
|
213
|
+
|
|
214
|
+
def _list(self, name: 'str|None', items: list):
|
|
215
|
+
self.writer.start_list(name)
|
|
216
|
+
for item in items:
|
|
217
|
+
self._dict(None, None, **item)
|
|
218
|
+
self.writer.end_list()
|
|
219
|
+
|
|
220
|
+
def _start(self, container: 'str|None' = 'body', name: 'str|None' = None, /,
|
|
221
|
+
**items):
|
|
222
|
+
if container:
|
|
223
|
+
self._start_container(container)
|
|
224
|
+
self.writer.start_dict(name, **items)
|
|
225
|
+
self.containers.append(None)
|
|
226
|
+
|
|
227
|
+
def _start_container(self, container):
|
|
228
|
+
if self.containers[-1] != container:
|
|
229
|
+
if self.containers[-1]:
|
|
230
|
+
self.writer.end_list()
|
|
231
|
+
self.writer.start_list(container)
|
|
232
|
+
self.containers[-1] = container
|
|
233
|
+
|
|
234
|
+
def _end(self, **items):
|
|
235
|
+
self._end_container()
|
|
236
|
+
self.containers.pop()
|
|
237
|
+
self.writer.end_dict(**items)
|
|
238
|
+
|
|
239
|
+
def _end_container(self):
|
|
240
|
+
if self.containers[-1]:
|
|
241
|
+
self.writer.end_list()
|
|
242
|
+
self.containers[-1] = None
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
class JsonWriter:
|
|
246
|
+
|
|
247
|
+
def __init__(self, file):
|
|
248
|
+
self.encode = json.JSONEncoder(check_circular=False,
|
|
249
|
+
separators=(',', ':'),
|
|
250
|
+
default=self._handle_custom).encode
|
|
251
|
+
self.file = file
|
|
252
|
+
self.comma = False
|
|
253
|
+
self.newline = False
|
|
254
|
+
|
|
255
|
+
def _handle_custom(self, value):
|
|
256
|
+
if isinstance(value, Path):
|
|
257
|
+
return str(value)
|
|
258
|
+
if isinstance(value, Mapping):
|
|
259
|
+
return dict(value)
|
|
260
|
+
if isinstance(value, Sequence):
|
|
261
|
+
return list(value)
|
|
262
|
+
raise TypeError(type(value).__name__)
|
|
263
|
+
|
|
264
|
+
def start_dict(self, name=None, /, **items):
|
|
265
|
+
self._start(name, '{')
|
|
266
|
+
self.items(**items)
|
|
267
|
+
|
|
268
|
+
def _start(self, name, char):
|
|
269
|
+
self._newline(newline=name is not None)
|
|
270
|
+
self._name(name)
|
|
271
|
+
self._write(char)
|
|
272
|
+
self.comma = False
|
|
273
|
+
|
|
274
|
+
def _newline(self, comma: 'bool|None' = None, newline: 'bool|None' = None):
|
|
275
|
+
if (self.comma if comma is None else comma):
|
|
276
|
+
self._write(',')
|
|
277
|
+
if (self.newline if newline is None else newline):
|
|
278
|
+
self._write('\n')
|
|
279
|
+
self.newline = True
|
|
280
|
+
|
|
281
|
+
def _name(self, name):
|
|
282
|
+
if name:
|
|
283
|
+
self._write(f'"{name}":')
|
|
284
|
+
|
|
285
|
+
def _write(self, text):
|
|
286
|
+
self.file.write(text)
|
|
287
|
+
|
|
288
|
+
def end_dict(self, **items):
|
|
289
|
+
self.items(**items)
|
|
290
|
+
self._end('}')
|
|
291
|
+
|
|
292
|
+
def _end(self, char, newline=True):
|
|
293
|
+
self._newline(comma=False, newline=newline)
|
|
294
|
+
self._write(char)
|
|
295
|
+
self.comma = True
|
|
296
|
+
|
|
297
|
+
def start_list(self, name=None, /):
|
|
298
|
+
self._start(name, '[')
|
|
299
|
+
|
|
300
|
+
def end_list(self):
|
|
301
|
+
self._end(']', newline=False)
|
|
302
|
+
|
|
303
|
+
def items(self, **items):
|
|
304
|
+
for name, value in items.items():
|
|
305
|
+
self._item(value, name)
|
|
306
|
+
|
|
307
|
+
def _item(self, value, name=None):
|
|
308
|
+
if isinstance(value, UnlessNone) and value:
|
|
309
|
+
value = value.value
|
|
310
|
+
elif not (value or value == 0 and not isinstance(value, bool)):
|
|
311
|
+
return
|
|
312
|
+
if isinstance(value, Raw):
|
|
313
|
+
value = value.value
|
|
314
|
+
else:
|
|
315
|
+
value = self.encode(value)
|
|
316
|
+
self._newline()
|
|
317
|
+
self._name(name)
|
|
318
|
+
self._write(value)
|
|
319
|
+
self.comma = True
|
|
320
|
+
|
|
321
|
+
def close(self):
|
|
322
|
+
self._write('\n')
|
|
323
|
+
self.file.close()
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
class Raw:
|
|
327
|
+
|
|
328
|
+
def __init__(self, value):
|
|
329
|
+
self.value = value
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
class UnlessNone:
|
|
333
|
+
|
|
334
|
+
def __init__(self, value):
|
|
335
|
+
self.value = value
|
|
336
|
+
|
|
337
|
+
def __bool__(self):
|
|
338
|
+
return self.value is not None
|
|
@@ -19,29 +19,30 @@ This is exposed via :py:mod:`robot.api.logger`. Implementation must reside
|
|
|
19
19
|
here to avoid cyclic imports.
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
import
|
|
23
|
-
from typing import
|
|
22
|
+
from threading import current_thread
|
|
23
|
+
from typing import Any
|
|
24
|
+
|
|
25
|
+
from robot.utils import safe_str
|
|
24
26
|
|
|
25
27
|
from .logger import LOGGER
|
|
26
28
|
from .loggerhelper import Message, write_to_console
|
|
27
29
|
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
# This constant is used by BackgroundLogger.
|
|
32
|
+
# https://github.com/robotframework/robotbackgroundlogger
|
|
33
|
+
LOGGING_THREADS = ['MainThread', 'RobotFrameworkTimeoutThread']
|
|
30
34
|
|
|
31
35
|
|
|
32
|
-
def write(msg:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
# https://github.com/robotframework/robotframework/issues/1505
|
|
36
|
-
if callable(msg):
|
|
37
|
-
msg = str(msg)
|
|
36
|
+
def write(msg: Any, level: str, html: bool = False):
|
|
37
|
+
if not isinstance(msg, str):
|
|
38
|
+
msg = safe_str(msg)
|
|
38
39
|
if level.upper() not in ('TRACE', 'DEBUG', 'INFO', 'HTML', 'WARN', 'ERROR'):
|
|
39
40
|
if level.upper() == 'CONSOLE':
|
|
40
41
|
level = 'INFO'
|
|
41
42
|
console(msg)
|
|
42
43
|
else:
|
|
43
|
-
raise RuntimeError("Invalid log level '
|
|
44
|
-
if
|
|
44
|
+
raise RuntimeError(f"Invalid log level '{level}'.")
|
|
45
|
+
if current_thread().name in LOGGING_THREADS:
|
|
45
46
|
LOGGER.log_message(Message(msg, level, html))
|
|
46
47
|
|
|
47
48
|
|