robotframework 6.1.1__zip → 7.0__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {robotframework-6.1.1 → robotframework-7.0}/INSTALL.rst +25 -25
- {robotframework-6.1.1 → robotframework-7.0}/PKG-INFO +6 -8
- {robotframework-6.1.1 → robotframework-7.0}/README.rst +3 -2
- {robotframework-6.1.1 → robotframework-7.0}/setup.py +3 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/__init__.py +4 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/deco.py +60 -14
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/exceptions.py +6 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/interfaces.py +402 -67
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/logger.py +27 -20
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/parsing.py +4 -2
- robotframework-7.0/src/robot/api/py.typed +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/gatherfailed.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/languages.py +0 -9
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/settings.py +21 -14
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/common/storage.js +11 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/htmlfilewriter.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.css +10 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.html +10 -0
- robotframework-7.0/src/robot/htmldata/rebot/common.css +362 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/doc_formatting.css +13 -7
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/log.css +51 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/log.html +14 -23
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/model.js +2 -4
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/report.css +83 -19
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/report.html +22 -7
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/testdata.js +10 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/view.js +84 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/template.py +3 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/builder.py +0 -8
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/datatypes.py +9 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/htmlutils.py +4 -7
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/jsonbuilder.py +38 -20
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/model.py +21 -28
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/robotbuilder.py +50 -31
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/standardtypes.py +9 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/xmlbuilder.py +35 -20
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/xmlwriter.py +18 -38
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/BuiltIn.py +255 -205
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Collections.py +384 -240
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/DateTime.py +73 -60
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/OperatingSystem.py +6 -5
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Process.py +26 -27
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Remote.py +40 -36
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/String.py +66 -76
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/XML.py +66 -59
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/__init__.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/__init__.py +5 -5
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/body.py +44 -13
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/configurer.py +15 -11
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/control.py +226 -84
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/filter.py +31 -25
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/itemlist.py +9 -8
- robotframework-7.0/src/robot/model/keyword.py +77 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/message.py +19 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/modelobject.py +25 -7
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/namepatterns.py +3 -25
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/stats.py +9 -15
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/tags.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/testcase.py +15 -27
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/testsuite.py +17 -26
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/visitor.py +35 -8
- robotframework-7.0/src/robot/output/console/dotted.py +90 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/quiet.py +3 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/verbose.py +61 -61
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/debugfile.py +39 -24
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/filelogger.py +18 -15
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/librarylogger.py +3 -2
- robotframework-7.0/src/robot/output/listeners.py +753 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/logger.py +216 -80
- robotframework-7.0/src/robot/output/loggerapi.py +215 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/loggerhelper.py +23 -56
- robotframework-7.0/src/robot/output/output.py +185 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/stdoutlogsplitter.py +8 -5
- robotframework-7.0/src/robot/output/xmllogger.py +459 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/blocklexers.py +17 -13
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/context.py +12 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/lexer.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/settings.py +6 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/statementlexers.py +39 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/tokens.py +27 -29
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/model/blocks.py +19 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/model/statements.py +193 -94
- robotframework-7.0/src/robot/parsing/model/visitor.py +100 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/rebot.py +2 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/expandkeywordmatcher.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jsbuildingcontext.py +8 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jsmodelbuilders.py +88 -61
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/logreportwriters.py +16 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/outputwriter.py +18 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/resultwriter.py +4 -4
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/stringcache.py +3 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/xunitwriter.py +15 -21
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/__init__.py +3 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/configurer.py +12 -9
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/executionresult.py +56 -8
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/flattenkeywordmatcher.py +48 -9
- robotframework-7.0/src/robot/result/keywordremover.py +207 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/merger.py +1 -1
- robotframework-7.0/src/robot/result/model.py +1185 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/modeldeprecation.py +9 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/resultbuilder.py +46 -36
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/xmlelementhandlers.py +83 -43
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/run.py +2 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/__init__.py +14 -4
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/__init__.py +2 -1
- robotframework-7.0/src/robot/running/arguments/argumentconverter.py +100 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentmapper.py +26 -24
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentparser.py +82 -60
- robotframework-7.0/src/robot/running/arguments/argumentresolver.py +158 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentspec.py +83 -116
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentvalidator.py +33 -27
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/customconverters.py +15 -12
- robotframework-7.0/src/robot/running/arguments/embedded.py +145 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/typeconverters.py +233 -213
- robotframework-7.0/src/robot/running/arguments/typeinfo.py +317 -0
- robotframework-7.0/src/robot/running/arguments/typeinfoparser.py +219 -0
- robotframework-7.0/src/robot/running/arguments/typevalidator.py +60 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/bodyrunner.py +147 -129
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/builders.py +2 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/parsers.py +10 -11
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/settings.py +9 -17
- robotframework-7.0/src/robot/running/builder/transformers.py +535 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/context.py +113 -31
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/dynamicmethods.py +62 -34
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/importer.py +27 -49
- robotframework-7.0/src/robot/running/invalidkeyword.py +67 -0
- robotframework-7.0/src/robot/running/keywordfinder.py +91 -0
- robotframework-7.0/src/robot/running/keywordimplementation.py +164 -0
- robotframework-7.0/src/robot/running/librarykeyword.py +392 -0
- robotframework-7.0/src/robot/running/librarykeywordrunner.py +250 -0
- robotframework-7.0/src/robot/running/libraryscopes.py +115 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/model.py +195 -377
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/namespace.py +124 -137
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/outputcapture.py +20 -12
- robotframework-7.0/src/robot/running/resourcemodel.py +448 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/statusreporter.py +16 -13
- robotframework-7.0/src/robot/running/suiterunner.py +265 -0
- robotframework-7.0/src/robot/running/testlibraries.py +500 -0
- robotframework-7.0/src/robot/running/userkeywordrunner.py +260 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/testdoc.py +18 -13
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/__init__.py +53 -35
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/connectioncache.py +64 -59
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/dotdict.py +3 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/encodingsniffer.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/escaping.py +19 -19
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/importer.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/markupwriters.py +23 -15
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/misc.py +1 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/normalizing.py +9 -24
- robotframework-7.0/src/robot/utils/notset.py +33 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/platform.py +15 -5
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotio.py +9 -9
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotpath.py +1 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robottime.py +122 -90
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robottypes.py +21 -31
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/setter.py +0 -5
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/text.py +7 -4
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/unic.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/__init__.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/assigner.py +17 -19
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/evaluation.py +20 -17
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/filesetter.py +80 -80
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/replacer.py +33 -36
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/scopes.py +17 -12
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/search.py +66 -41
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/store.py +14 -16
- robotframework-7.0/src/robot/variables/tablesetter.py +164 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/variables.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/version.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/PKG-INFO +6 -8
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/SOURCES.txt +10 -8
- {robotframework-6.1.1 → robotframework-7.0}/tasks.py +6 -6
- robotframework-6.1.1/src/robot/htmldata/rebot/common.css +0 -239
- robotframework-6.1.1/src/robot/libraries/Reserved.py +0 -48
- robotframework-6.1.1/src/robot/model/keyword.py +0 -173
- robotframework-6.1.1/src/robot/output/console/dotted.py +0 -90
- robotframework-6.1.1/src/robot/output/listenerarguments.py +0 -165
- robotframework-6.1.1/src/robot/output/listenermethods.py +0 -113
- robotframework-6.1.1/src/robot/output/listeners.py +0 -174
- robotframework-6.1.1/src/robot/output/output.py +0 -95
- robotframework-6.1.1/src/robot/output/xmllogger.py +0 -354
- robotframework-6.1.1/src/robot/parsing/model/visitor.py +0 -67
- robotframework-6.1.1/src/robot/result/keywordremover.py +0 -183
- robotframework-6.1.1/src/robot/result/model.py +0 -957
- robotframework-6.1.1/src/robot/running/arguments/argumentconverter.py +0 -79
- robotframework-6.1.1/src/robot/running/arguments/argumentresolver.py +0 -131
- robotframework-6.1.1/src/robot/running/arguments/embedded.py +0 -146
- robotframework-6.1.1/src/robot/running/arguments/typevalidator.py +0 -56
- robotframework-6.1.1/src/robot/running/builder/transformers.py +0 -642
- robotframework-6.1.1/src/robot/running/handlers.py +0 -321
- robotframework-6.1.1/src/robot/running/handlerstore.py +0 -66
- robotframework-6.1.1/src/robot/running/librarykeywordrunner.py +0 -238
- robotframework-6.1.1/src/robot/running/libraryscopes.py +0 -97
- robotframework-6.1.1/src/robot/running/modelcombiner.py +0 -32
- robotframework-6.1.1/src/robot/running/suiterunner.py +0 -248
- robotframework-6.1.1/src/robot/running/testlibraries.py +0 -423
- robotframework-6.1.1/src/robot/running/usererrorhandler.py +0 -75
- robotframework-6.1.1/src/robot/running/userkeyword.py +0 -111
- robotframework-6.1.1/src/robot/running/userkeywordrunner.py +0 -274
- robotframework-6.1.1/src/robot/variables/tablesetter.py +0 -156
- {robotframework-6.1.1 → robotframework-7.0}/AUTHORS.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/BUILD.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/CONTRIBUTING.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/COPYRIGHT.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/LICENSE.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/MANIFEST.in +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/setup.cfg +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/__main__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/errors.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/common/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/common/js_disabled.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/jsonwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/doc_formatting.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/print.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/pygments.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/fileloading.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/log.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/print.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/util.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/testdoc/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.html +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdoc.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/consoleviewer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/htmlwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/jsonwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/output.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/writer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Dialogs.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Easter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Screenshot.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Telnet.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/dialogs_py.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/fixture.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/metadata.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/modifier.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/statistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/suitestatistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/tagsetter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/tagstatistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/totalstatistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/highlighting.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/pyloggingconf.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/tokenizer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/model/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/blockparsers.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/fileparser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/parser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/suitestructure.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/pythonpathsetter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jsexecutionresult.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jswriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/executionerrors.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/messagefilter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/suiteteardownfailed.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/visitor.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/randomizer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/runkwregister.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/signalhandler.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/status.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/timeouts/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/timeouts/posix.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/timeouts/windows.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/application.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/argumentparser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/asserts.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/charwidth.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/compress.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/encoding.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/error.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/etreewrapper.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/filereader.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/frange.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/htmlformatters.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/markuputils.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/match.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/recommendations.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/restreader.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotenv.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotinspect.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/sortable.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/typehints.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/finders.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/notfound.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/resolvable.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/dependency_links.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/entry_points.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/top_level.txt +0 -0
|
@@ -13,17 +13,19 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
+
import re
|
|
17
|
+
|
|
16
18
|
from robot.output import LEVELS
|
|
19
|
+
from robot.result import Error, Keyword, Message, Return
|
|
17
20
|
|
|
18
21
|
from .jsbuildingcontext import JsBuildingContext
|
|
19
22
|
from .jsexecutionresult import JsExecutionResult
|
|
20
23
|
|
|
21
|
-
|
|
22
24
|
STATUSES = {'FAIL': 0, 'PASS': 1, 'SKIP': 2, 'NOT RUN': 3}
|
|
23
25
|
KEYWORD_TYPES = {'KEYWORD': 0, 'SETUP': 1, 'TEARDOWN': 2,
|
|
24
26
|
'FOR': 3, 'ITERATION': 4, 'IF': 5, 'ELSE IF': 6, 'ELSE': 7,
|
|
25
|
-
'RETURN': 8, '
|
|
26
|
-
'
|
|
27
|
+
'RETURN': 8, 'VAR': 9, 'TRY': 10, 'EXCEPT': 11, 'FINALLY': 12,
|
|
28
|
+
'WHILE': 13, 'CONTINUE': 14, 'BREAK': 15, 'ERROR': 16}
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
class JsModelBuilder:
|
|
@@ -47,49 +49,61 @@ class JsModelBuilder:
|
|
|
47
49
|
)
|
|
48
50
|
|
|
49
51
|
|
|
50
|
-
class
|
|
52
|
+
class Builder:
|
|
53
|
+
robot_note = re.compile('<span class="robot-note">(.*)</span>')
|
|
51
54
|
|
|
52
|
-
def __init__(self, context):
|
|
55
|
+
def __init__(self, context: JsBuildingContext):
|
|
53
56
|
self._context = context
|
|
54
57
|
self._string = self._context.string
|
|
55
58
|
self._html = self._context.html
|
|
56
59
|
self._timestamp = self._context.timestamp
|
|
57
60
|
|
|
58
|
-
def _get_status(self, item):
|
|
61
|
+
def _get_status(self, item, note_only=False):
|
|
59
62
|
model = (STATUSES[item.status],
|
|
60
|
-
self._timestamp(item.
|
|
61
|
-
item.
|
|
62
|
-
msg =
|
|
63
|
+
self._timestamp(item.start_time),
|
|
64
|
+
round(item.elapsed_time.total_seconds() * 1000))
|
|
65
|
+
msg = item.message
|
|
63
66
|
if not msg:
|
|
64
67
|
return model
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
if note_only:
|
|
69
|
+
if msg.startswith('*HTML*'):
|
|
70
|
+
match = self.robot_note.search(msg)
|
|
71
|
+
if match:
|
|
72
|
+
index = self._string(match.group(1))
|
|
73
|
+
return model + (index,)
|
|
74
|
+
return model
|
|
75
|
+
if msg.startswith('*HTML*'):
|
|
76
|
+
index = self._string(msg[6:].lstrip(), escape=False)
|
|
67
77
|
else:
|
|
68
|
-
|
|
69
|
-
return model + (
|
|
78
|
+
index = self._string(msg)
|
|
79
|
+
return model + (index,)
|
|
70
80
|
|
|
71
|
-
def
|
|
81
|
+
def _build_body(self, body, split=False):
|
|
72
82
|
splitting = self._context.start_splitting_if_needed(split)
|
|
73
|
-
# tuple([<listcomp
|
|
74
|
-
model = tuple([self.
|
|
83
|
+
# tuple([<listcomp>]) is faster than tuple(<genex>) with short lists.
|
|
84
|
+
model = tuple([self._build_body_item(item) for item in body])
|
|
75
85
|
return model if not splitting else self._context.end_splitting(model)
|
|
76
86
|
|
|
77
|
-
def
|
|
87
|
+
def _build_body_item(self, item):
|
|
78
88
|
raise NotImplementedError
|
|
79
89
|
|
|
80
90
|
|
|
81
|
-
class SuiteBuilder(
|
|
91
|
+
class SuiteBuilder(Builder):
|
|
82
92
|
|
|
83
93
|
def __init__(self, context):
|
|
84
|
-
|
|
94
|
+
super().__init__(context)
|
|
85
95
|
self._build_suite = self.build
|
|
86
96
|
self._build_test = TestBuilder(context).build
|
|
87
|
-
self.
|
|
97
|
+
self._build_body_item = BodyItemBuilder(context).build
|
|
88
98
|
|
|
89
99
|
def build(self, suite):
|
|
90
100
|
with self._context.prune_input(suite.tests, suite.suites):
|
|
91
101
|
stats = self._get_statistics(suite) # Must be done before pruning
|
|
92
|
-
|
|
102
|
+
fixture = []
|
|
103
|
+
if suite.has_setup:
|
|
104
|
+
fixture.append(suite.setup)
|
|
105
|
+
if suite.has_teardown:
|
|
106
|
+
fixture.append(suite.teardown)
|
|
93
107
|
return (self._string(suite.name, attr=True),
|
|
94
108
|
self._string(suite.source),
|
|
95
109
|
self._context.relative_source(suite.source),
|
|
@@ -98,7 +112,7 @@ class SuiteBuilder(_Builder):
|
|
|
98
112
|
self._get_status(suite),
|
|
99
113
|
tuple(self._build_suite(s) for s in suite.suites),
|
|
100
114
|
tuple(self._build_test(t) for t in suite.tests),
|
|
101
|
-
tuple(self.
|
|
115
|
+
tuple(self._build_body_item(kw, split=True) for kw in fixture),
|
|
102
116
|
stats)
|
|
103
117
|
|
|
104
118
|
def _yield_metadata(self, suite):
|
|
@@ -111,63 +125,76 @@ class SuiteBuilder(_Builder):
|
|
|
111
125
|
return (stats.total, stats.passed, stats.failed, stats.skipped)
|
|
112
126
|
|
|
113
127
|
|
|
114
|
-
class TestBuilder(
|
|
128
|
+
class TestBuilder(Builder):
|
|
115
129
|
|
|
116
130
|
def __init__(self, context):
|
|
117
|
-
|
|
118
|
-
self.
|
|
131
|
+
super().__init__(context)
|
|
132
|
+
self._build_body_item = BodyItemBuilder(context).build
|
|
119
133
|
|
|
120
134
|
def build(self, test):
|
|
121
|
-
|
|
135
|
+
body = self._get_body_items(test)
|
|
122
136
|
with self._context.prune_input(test.body):
|
|
123
137
|
return (self._string(test.name, attr=True),
|
|
124
138
|
self._string(test.timeout),
|
|
125
139
|
self._html(test.doc),
|
|
126
140
|
tuple(self._string(t) for t in test.tags),
|
|
127
141
|
self._get_status(test),
|
|
128
|
-
self.
|
|
142
|
+
self._build_body(body, split=True))
|
|
129
143
|
|
|
130
|
-
def
|
|
131
|
-
|
|
132
|
-
if test.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return kws
|
|
144
|
+
def _get_body_items(self, test):
|
|
145
|
+
body = test.body.flatten()
|
|
146
|
+
if test.has_setup:
|
|
147
|
+
body.insert(0, test.setup)
|
|
148
|
+
if test.has_teardown:
|
|
149
|
+
body.append(test.teardown)
|
|
150
|
+
return body
|
|
138
151
|
|
|
139
152
|
|
|
140
|
-
class
|
|
153
|
+
class BodyItemBuilder(Builder):
|
|
141
154
|
|
|
142
155
|
def __init__(self, context):
|
|
143
|
-
|
|
144
|
-
self.
|
|
156
|
+
super().__init__(context)
|
|
157
|
+
self._build_body_item = self.build
|
|
145
158
|
self._build_message = MessageBuilder(context).build
|
|
146
159
|
|
|
147
160
|
def build(self, item, split=False):
|
|
148
|
-
if item
|
|
161
|
+
if isinstance(item, Message):
|
|
149
162
|
return self._build_message(item)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
163
|
+
with self._context.prune_input(item.body):
|
|
164
|
+
if isinstance (item, Keyword):
|
|
165
|
+
return self._build_keyword(item, split)
|
|
166
|
+
if isinstance(item, (Return, Error)):
|
|
167
|
+
return self._build(item, args=' '.join(item.values), split=split)
|
|
168
|
+
return self._build(item, item._log_name, split=split)
|
|
169
|
+
|
|
170
|
+
def _build_keyword(self, kw: Keyword, split):
|
|
153
171
|
self._context.check_expansion(kw)
|
|
154
|
-
|
|
155
|
-
if
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
172
|
+
body = kw.body.flatten()
|
|
173
|
+
if kw.has_setup:
|
|
174
|
+
body.insert(0, kw.setup)
|
|
175
|
+
if kw.has_teardown:
|
|
176
|
+
body.append(kw.teardown)
|
|
177
|
+
return self._build(kw, kw.name, kw.owner, kw.timeout, kw.doc,
|
|
178
|
+
' '.join(kw.args), ' '.join(kw.assign),
|
|
179
|
+
', '.join(kw.tags), body, split=split)
|
|
180
|
+
|
|
181
|
+
def _build(self, item, name='', owner='', timeout='', doc='', args='', assign='',
|
|
182
|
+
tags='', body=None, split=False):
|
|
183
|
+
if body is None:
|
|
184
|
+
body = item.body.flatten()
|
|
185
|
+
return (KEYWORD_TYPES[item.type],
|
|
186
|
+
self._string(name, attr=True),
|
|
187
|
+
self._string(owner, attr=True),
|
|
188
|
+
self._string(timeout),
|
|
189
|
+
self._html(doc),
|
|
190
|
+
self._string(args),
|
|
191
|
+
self._string(assign),
|
|
192
|
+
self._string(tags),
|
|
193
|
+
self._get_status(item, note_only=True),
|
|
194
|
+
self._build_body(body, split))
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class MessageBuilder(Builder):
|
|
171
198
|
|
|
172
199
|
def build(self, msg):
|
|
173
200
|
if msg.level in ('WARN', 'ERROR'):
|
|
@@ -196,10 +223,10 @@ class StatisticsBuilder:
|
|
|
196
223
|
for stat in stats)
|
|
197
224
|
|
|
198
225
|
|
|
199
|
-
class ErrorsBuilder(
|
|
226
|
+
class ErrorsBuilder(Builder):
|
|
200
227
|
|
|
201
228
|
def __init__(self, context):
|
|
202
|
-
|
|
229
|
+
super().__init__(context)
|
|
203
230
|
self._build_message = ErrorMessageBuilder(context).build
|
|
204
231
|
|
|
205
232
|
def build(self, errors):
|
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
+
from pathlib import Path
|
|
16
17
|
from os.path import basename, splitext
|
|
17
18
|
|
|
18
19
|
from robot.htmldata import HtmlFileWriter, ModelWriter, LOG, REPORT
|
|
19
|
-
from robot.utils import file_writer
|
|
20
|
+
from robot.utils import file_writer
|
|
20
21
|
|
|
21
22
|
from .jswriter import JsResultWriter, SplitLogWriter
|
|
22
23
|
|
|
@@ -27,9 +28,9 @@ class _LogReportWriter:
|
|
|
27
28
|
def __init__(self, js_model):
|
|
28
29
|
self._js_model = js_model
|
|
29
30
|
|
|
30
|
-
def _write_file(self, path, config, template):
|
|
31
|
+
def _write_file(self, path: Path, config, template):
|
|
31
32
|
outfile = file_writer(path, usage=self.usage) \
|
|
32
|
-
if
|
|
33
|
+
if isinstance(path, Path) else path # unit test hook
|
|
33
34
|
with outfile:
|
|
34
35
|
model_writer = RobotModelWriter(outfile, self._js_model, config)
|
|
35
36
|
writer = HtmlFileWriter(outfile, model_writer)
|
|
@@ -39,26 +40,31 @@ class _LogReportWriter:
|
|
|
39
40
|
class LogWriter(_LogReportWriter):
|
|
40
41
|
usage = 'log'
|
|
41
42
|
|
|
42
|
-
def write(self, path, config):
|
|
43
|
+
def write(self, path: 'Path|str', config):
|
|
44
|
+
if isinstance(path, str):
|
|
45
|
+
path = Path(path)
|
|
43
46
|
self._write_file(path, config, LOG)
|
|
44
47
|
if self._js_model.split_results:
|
|
45
|
-
self._write_split_logs(
|
|
48
|
+
self._write_split_logs(path)
|
|
46
49
|
|
|
47
|
-
def _write_split_logs(self,
|
|
50
|
+
def _write_split_logs(self, path: Path):
|
|
48
51
|
for index, (keywords, strings) in enumerate(self._js_model.split_results,
|
|
49
52
|
start=1):
|
|
50
|
-
|
|
53
|
+
name = f'{path.stem}-{index}.js'
|
|
54
|
+
self._write_split_log(index, keywords, strings, path.with_name(name))
|
|
51
55
|
|
|
52
|
-
def _write_split_log(self, index, keywords, strings, path):
|
|
56
|
+
def _write_split_log(self, index, keywords, strings, path: Path):
|
|
53
57
|
with file_writer(path, usage=self.usage) as outfile:
|
|
54
58
|
writer = SplitLogWriter(outfile)
|
|
55
|
-
writer.write(keywords, strings, index,
|
|
59
|
+
writer.write(keywords, strings, index, path.name)
|
|
56
60
|
|
|
57
61
|
|
|
58
62
|
class ReportWriter(_LogReportWriter):
|
|
59
63
|
usage = 'report'
|
|
60
64
|
|
|
61
|
-
def write(self, path, config):
|
|
65
|
+
def write(self, path: 'Path|str', config):
|
|
66
|
+
if isinstance(path, str):
|
|
67
|
+
path = Path(path)
|
|
62
68
|
self._write_file(path, config, REPORT)
|
|
63
69
|
|
|
64
70
|
|
|
@@ -13,13 +13,29 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
-
from robot.output.xmllogger import XmlLogger
|
|
16
|
+
from robot.output.xmllogger import XmlLogger, LegacyXmlLogger
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class OutputWriter(XmlLogger):
|
|
20
20
|
|
|
21
|
+
def __init__(self, output, rpa=False, suite_only=False):
|
|
22
|
+
super().__init__(output, rpa=rpa, generator='Rebot', suite_only=suite_only)
|
|
23
|
+
|
|
24
|
+
def start_message(self, msg):
|
|
25
|
+
self._write_message(msg)
|
|
26
|
+
|
|
27
|
+
def close(self):
|
|
28
|
+
self._writer.end('robot')
|
|
29
|
+
self._writer.close()
|
|
30
|
+
|
|
31
|
+
def end_result(self, result):
|
|
32
|
+
self.close()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class LegacyOutputWriter(LegacyXmlLogger):
|
|
36
|
+
|
|
21
37
|
def __init__(self, output, rpa=False):
|
|
22
|
-
|
|
38
|
+
super().__init__(output, rpa=rpa, generator='Rebot')
|
|
23
39
|
|
|
24
40
|
def start_message(self, msg):
|
|
25
41
|
self._write_message(msg)
|
|
@@ -54,7 +54,7 @@ class ResultWriter:
|
|
|
54
54
|
settings = settings or RebotSettings(options)
|
|
55
55
|
results = Results(settings, *self._sources)
|
|
56
56
|
if settings.output:
|
|
57
|
-
self._write_output(results.result, settings.output)
|
|
57
|
+
self._write_output(results.result, settings.output, settings.legacy_output)
|
|
58
58
|
if settings.xunit:
|
|
59
59
|
self._write_xunit(results.result, settings.xunit)
|
|
60
60
|
if settings.log:
|
|
@@ -67,8 +67,8 @@ class ResultWriter:
|
|
|
67
67
|
settings.report_config)
|
|
68
68
|
return results.return_code
|
|
69
69
|
|
|
70
|
-
def _write_output(self, result, path):
|
|
71
|
-
self._write('Output', result.save, path)
|
|
70
|
+
def _write_output(self, result, path, legacy_output=False):
|
|
71
|
+
self._write('Output', result.save, path, legacy_output)
|
|
72
72
|
|
|
73
73
|
def _write_xunit(self, result, path):
|
|
74
74
|
self._write('XUnit', XUnitWriter(result).write, path)
|
|
@@ -85,7 +85,7 @@ class ResultWriter:
|
|
|
85
85
|
except DataError as err:
|
|
86
86
|
LOGGER.error(err.message)
|
|
87
87
|
else:
|
|
88
|
-
LOGGER.
|
|
88
|
+
LOGGER.result_file(name, path)
|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
class Results:
|
|
@@ -21,16 +21,16 @@ class StringIndex(int):
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class StringCache:
|
|
24
|
+
empty = StringIndex(0)
|
|
24
25
|
_compress_threshold = 80
|
|
25
26
|
_use_compressed_threshold = 1.1
|
|
26
|
-
_zero_index = StringIndex(0)
|
|
27
27
|
|
|
28
28
|
def __init__(self):
|
|
29
|
-
self._cache = {('', False): self.
|
|
29
|
+
self._cache = {('', False): self.empty}
|
|
30
30
|
|
|
31
31
|
def add(self, text, html=False):
|
|
32
32
|
if not text:
|
|
33
|
-
return self.
|
|
33
|
+
return self.empty
|
|
34
34
|
key = (text, html)
|
|
35
35
|
if key not in self._cache:
|
|
36
36
|
self._cache[key] = StringIndex(len(self._cache))
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
-
from robot.result import ResultVisitor
|
|
16
|
+
from robot.result import ResultVisitor, TestCase, TestSuite
|
|
17
17
|
from robot.utils import XmlWriter
|
|
18
18
|
|
|
19
19
|
|
|
@@ -38,32 +38,34 @@ class XUnitFileWriter(ResultVisitor):
|
|
|
38
38
|
def __init__(self, xml_writer):
|
|
39
39
|
self._writer = xml_writer
|
|
40
40
|
|
|
41
|
-
def start_suite(self, suite):
|
|
41
|
+
def start_suite(self, suite: TestSuite):
|
|
42
42
|
stats = suite.statistics # Accessing property only once.
|
|
43
43
|
attrs = {'name': suite.name,
|
|
44
|
-
'tests':
|
|
44
|
+
'tests': str(stats.total),
|
|
45
45
|
'errors': '0',
|
|
46
|
-
'failures':
|
|
47
|
-
'skipped':
|
|
48
|
-
'time':
|
|
49
|
-
'timestamp'
|
|
46
|
+
'failures': str(stats.failed),
|
|
47
|
+
'skipped': str(stats.skipped),
|
|
48
|
+
'time': format(suite.elapsed_time.total_seconds(), '.3f'),
|
|
49
|
+
'timestamp': suite.start_time.isoformat() if suite.start_time else None}
|
|
50
50
|
self._writer.start('testsuite', attrs)
|
|
51
51
|
|
|
52
|
-
def end_suite(self, suite):
|
|
52
|
+
def end_suite(self, suite: TestSuite):
|
|
53
53
|
if suite.metadata or suite.doc:
|
|
54
54
|
self._writer.start('properties')
|
|
55
55
|
if suite.doc:
|
|
56
|
-
self._writer.element('property', attrs={'name': 'Documentation',
|
|
56
|
+
self._writer.element('property', attrs={'name': 'Documentation',
|
|
57
|
+
'value': suite.doc})
|
|
57
58
|
for meta_name, meta_value in suite.metadata.items():
|
|
58
|
-
self._writer.element('property', attrs={'name': meta_name,
|
|
59
|
+
self._writer.element('property', attrs={'name': meta_name,
|
|
60
|
+
'value': meta_value})
|
|
59
61
|
self._writer.end('properties')
|
|
60
62
|
self._writer.end('testsuite')
|
|
61
63
|
|
|
62
|
-
def visit_test(self, test):
|
|
64
|
+
def visit_test(self, test: TestCase):
|
|
63
65
|
self._writer.start('testcase',
|
|
64
|
-
{'classname': test.parent.
|
|
66
|
+
{'classname': test.parent.full_name,
|
|
65
67
|
'name': test.name,
|
|
66
|
-
'time':
|
|
68
|
+
'time': format(test.elapsed_time.total_seconds(), '.3f')})
|
|
67
69
|
if test.failed:
|
|
68
70
|
self._writer.element('failure', attrs={'message': test.message,
|
|
69
71
|
'type': 'AssertionError'})
|
|
@@ -72,9 +74,6 @@ class XUnitFileWriter(ResultVisitor):
|
|
|
72
74
|
'type': 'SkipExecution'})
|
|
73
75
|
self._writer.end('testcase')
|
|
74
76
|
|
|
75
|
-
def _time_as_seconds(self, millis):
|
|
76
|
-
return format(millis / 1000, '.3f')
|
|
77
|
-
|
|
78
77
|
def visit_keyword(self, kw):
|
|
79
78
|
pass
|
|
80
79
|
|
|
@@ -86,8 +85,3 @@ class XUnitFileWriter(ResultVisitor):
|
|
|
86
85
|
|
|
87
86
|
def end_result(self, result):
|
|
88
87
|
self._writer.close()
|
|
89
|
-
|
|
90
|
-
def _starttime_to_isoformat(self, stime):
|
|
91
|
-
if not stime:
|
|
92
|
-
return None
|
|
93
|
-
return f'{stime[:4]}-{stime[4:6]}-{stime[6:8]}T{stime[9:22]}000'
|
|
@@ -38,7 +38,8 @@ __ http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#
|
|
|
38
38
|
"""
|
|
39
39
|
|
|
40
40
|
from .executionresult import Result
|
|
41
|
-
from .model import (Break, Continue, Error, For, ForIteration, If, IfBranch, Keyword,
|
|
42
|
-
Return, TestCase, TestSuite, Try, TryBranch, While,
|
|
41
|
+
from .model import (Break, Continue, Error, For, ForIteration, If, IfBranch, Keyword,
|
|
42
|
+
Message, Return, TestCase, TestSuite, Try, TryBranch, Var, While,
|
|
43
|
+
WhileIteration)
|
|
43
44
|
from .resultbuilder import ExecutionResult, ExecutionResultBuilder
|
|
44
45
|
from .visitor import ResultVisitor
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
16
|
from robot import model
|
|
17
|
-
from robot.utils import is_string,
|
|
17
|
+
from robot.utils import is_string, parse_timestamp
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class SuiteConfigurer(model.SuiteConfigurer):
|
|
@@ -32,11 +32,11 @@ class SuiteConfigurer(model.SuiteConfigurer):
|
|
|
32
32
|
|
|
33
33
|
def __init__(self, remove_keywords=None, log_level=None, start_time=None,
|
|
34
34
|
end_time=None, **base_config):
|
|
35
|
-
|
|
35
|
+
super().__init__(**base_config)
|
|
36
36
|
self.remove_keywords = self._get_remove_keywords(remove_keywords)
|
|
37
37
|
self.log_level = log_level
|
|
38
|
-
self.start_time = self.
|
|
39
|
-
self.end_time = self.
|
|
38
|
+
self.start_time = self._to_datetime(start_time)
|
|
39
|
+
self.end_time = self._to_datetime(end_time)
|
|
40
40
|
|
|
41
41
|
def _get_remove_keywords(self, value):
|
|
42
42
|
if value is None:
|
|
@@ -45,14 +45,13 @@ class SuiteConfigurer(model.SuiteConfigurer):
|
|
|
45
45
|
return [value]
|
|
46
46
|
return value
|
|
47
47
|
|
|
48
|
-
def
|
|
48
|
+
def _to_datetime(self, timestamp):
|
|
49
49
|
if not timestamp:
|
|
50
50
|
return None
|
|
51
51
|
try:
|
|
52
|
-
|
|
52
|
+
return parse_timestamp(timestamp)
|
|
53
53
|
except ValueError:
|
|
54
54
|
return None
|
|
55
|
-
return secs_to_timestamp(secs, millis=True)
|
|
56
55
|
|
|
57
56
|
def visit_suite(self, suite):
|
|
58
57
|
model.SuiteConfigurer.visit_suite(self, suite)
|
|
@@ -66,6 +65,10 @@ class SuiteConfigurer(model.SuiteConfigurer):
|
|
|
66
65
|
|
|
67
66
|
def _set_times(self, suite):
|
|
68
67
|
if self.start_time:
|
|
69
|
-
suite.
|
|
68
|
+
suite.end_time = suite.end_time # Preserve original value.
|
|
69
|
+
suite.elapsed_time = None # Force re-calculation.
|
|
70
|
+
suite.start_time = self.start_time
|
|
70
71
|
if self.end_time:
|
|
71
|
-
suite.
|
|
72
|
+
suite.start_time = suite.start_time
|
|
73
|
+
suite.elapsed_time = None
|
|
74
|
+
suite.end_time = self.end_time
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
16
18
|
from robot.errors import DataError
|
|
17
19
|
from robot.model import Statistics
|
|
18
20
|
|
|
@@ -20,6 +22,28 @@ from .executionerrors import ExecutionErrors
|
|
|
20
22
|
from .model import TestSuite
|
|
21
23
|
|
|
22
24
|
|
|
25
|
+
def is_json_source(source):
|
|
26
|
+
if isinstance(source, bytes):
|
|
27
|
+
# Latin-1 is most likely not the right encoding, but decoding bytes with it
|
|
28
|
+
# always succeeds and characters we care about will be correct as well.
|
|
29
|
+
source = source.decode('Latin-1')
|
|
30
|
+
if isinstance(source, str):
|
|
31
|
+
source = source.strip()
|
|
32
|
+
first, last = (source[0], source[-1]) if source else ('', '')
|
|
33
|
+
if (first, last) == ('{', '}'):
|
|
34
|
+
return True
|
|
35
|
+
if (first, last) == ('<', '>'):
|
|
36
|
+
return False
|
|
37
|
+
path = Path(source)
|
|
38
|
+
elif isinstance(source, Path):
|
|
39
|
+
path = source
|
|
40
|
+
elif hasattr(source, 'name') and isinstance(source.name, str):
|
|
41
|
+
path = Path(source.name)
|
|
42
|
+
else:
|
|
43
|
+
return False
|
|
44
|
+
return bool(path and path.suffix.lower() == '.json')
|
|
45
|
+
|
|
46
|
+
|
|
23
47
|
class Result:
|
|
24
48
|
"""Test execution results.
|
|
25
49
|
|
|
@@ -96,14 +120,38 @@ class Result:
|
|
|
96
120
|
self._status_rc = status_rc
|
|
97
121
|
self._stat_config = stat_config or {}
|
|
98
122
|
|
|
99
|
-
def save(self,
|
|
100
|
-
"""Save results as
|
|
101
|
-
|
|
102
|
-
:param
|
|
103
|
-
|
|
123
|
+
def save(self, target=None, legacy_output=False):
|
|
124
|
+
"""Save results as XML or JSON file.
|
|
125
|
+
|
|
126
|
+
:param target: Target where to save results to. Can be a path
|
|
127
|
+
(``pathlib.Path`` or ``str``) or an open file object. If omitted,
|
|
128
|
+
uses the :attr:`source` which overwrites the original file.
|
|
129
|
+
:param legacy_output: Save result in Robot Framework 6.x compatible
|
|
130
|
+
format. New in Robot Framework 7.0.
|
|
131
|
+
|
|
132
|
+
File type is got based on the ``target``. The type is JSON if the ``target``
|
|
133
|
+
is a path that has a ``.json`` suffix or if it is an open file that has
|
|
134
|
+
a ``name`` attribute with a ``.json`` suffix. Otherwise, the type is XML.
|
|
135
|
+
|
|
136
|
+
Notice that saved JSON files only contain suite information, no statics
|
|
137
|
+
or errors like XML files. This is likely to change in the future so
|
|
138
|
+
that JSON files get a new root object with the current suite as a child
|
|
139
|
+
and statics and errors as additional children. Robot Framework's own
|
|
140
|
+
functions and methods accepting JSON results will continue to work
|
|
141
|
+
also with JSON files containing only a suite.
|
|
104
142
|
"""
|
|
105
|
-
from robot.reporting.outputwriter import OutputWriter
|
|
106
|
-
|
|
143
|
+
from robot.reporting.outputwriter import LegacyOutputWriter, OutputWriter
|
|
144
|
+
|
|
145
|
+
target = target or self.source
|
|
146
|
+
if not target:
|
|
147
|
+
raise ValueError('Path required.')
|
|
148
|
+
if is_json_source(target):
|
|
149
|
+
# This writes only suite information, not stats or errors. This
|
|
150
|
+
# should be changed when we add JSON support to execution.
|
|
151
|
+
self.suite.to_json(target)
|
|
152
|
+
else:
|
|
153
|
+
writer = OutputWriter if not legacy_output else LegacyOutputWriter
|
|
154
|
+
self.visit(writer(target, rpa=self.rpa))
|
|
107
155
|
|
|
108
156
|
def visit(self, visitor):
|
|
109
157
|
"""An entry point to visit the whole result object.
|
|
@@ -142,7 +190,7 @@ class CombinedResult(Result):
|
|
|
142
190
|
"""Combined results of multiple test executions."""
|
|
143
191
|
|
|
144
192
|
def __init__(self, results=None):
|
|
145
|
-
|
|
193
|
+
super().__init__()
|
|
146
194
|
for result in results or ():
|
|
147
195
|
self.add_result(result)
|
|
148
196
|
|