robotframework 6.1rc1__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.1rc1 → robotframework-7.0}/INSTALL.rst +25 -25
- {robotframework-6.1rc1 → robotframework-7.0}/PKG-INFO +6 -8
- {robotframework-6.1rc1 → robotframework-7.0}/README.rst +3 -2
- {robotframework-6.1rc1 → robotframework-7.0}/setup.py +3 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/__init__.py +4 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/deco.py +60 -14
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/exceptions.py +6 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/interfaces.py +403 -68
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/logger.py +27 -20
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/parsing.py +4 -2
- robotframework-7.0/src/robot/api/py.typed +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/gatherfailed.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/languages.py +61 -25
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/settings.py +21 -14
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/common/storage.js +11 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/htmlfilewriter.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.css +10 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.html +10 -0
- robotframework-7.0/src/robot/htmldata/rebot/common.css +362 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/doc_formatting.css +13 -7
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/log.css +51 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/log.html +14 -23
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/model.js +2 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/report.css +83 -19
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/report.html +22 -7
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/testdata.js +10 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/view.js +84 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/template.py +3 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/builder.py +0 -8
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/datatypes.py +9 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/htmlutils.py +4 -7
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/jsonbuilder.py +38 -20
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/model.py +21 -28
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/robotbuilder.py +50 -31
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/standardtypes.py +9 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/xmlbuilder.py +35 -20
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/xmlwriter.py +18 -38
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/BuiltIn.py +255 -205
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Collections.py +384 -240
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/DateTime.py +73 -60
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/OperatingSystem.py +6 -5
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Process.py +26 -27
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Remote.py +40 -36
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/String.py +66 -76
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/XML.py +66 -59
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/__init__.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/dialogs_py.py +14 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/__init__.py +5 -5
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/body.py +44 -13
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/configurer.py +19 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/control.py +230 -88
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/filter.py +31 -25
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/itemlist.py +9 -8
- robotframework-7.0/src/robot/model/keyword.py +77 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/message.py +19 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/modelobject.py +27 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/modifier.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/namepatterns.py +3 -25
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/stats.py +9 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/tags.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/testcase.py +15 -27
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/testsuite.py +44 -28
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/visitor.py +35 -8
- robotframework-7.0/src/robot/output/console/dotted.py +90 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/quiet.py +3 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/verbose.py +61 -61
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/debugfile.py +39 -24
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/filelogger.py +18 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/librarylogger.py +3 -2
- robotframework-7.0/src/robot/output/listeners.py +753 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/logger.py +216 -80
- robotframework-7.0/src/robot/output/loggerapi.py +215 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/loggerhelper.py +23 -56
- robotframework-7.0/src/robot/output/output.py +185 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/stdoutlogsplitter.py +8 -5
- robotframework-7.0/src/robot/output/xmllogger.py +459 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/blocklexers.py +17 -13
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/context.py +12 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/lexer.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/settings.py +6 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/statementlexers.py +39 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/tokens.py +27 -29
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/model/blocks.py +19 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/model/statements.py +193 -94
- robotframework-7.0/src/robot/parsing/model/visitor.py +100 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/rebot.py +2 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/expandkeywordmatcher.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jsbuildingcontext.py +8 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jsmodelbuilders.py +88 -61
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/logreportwriters.py +16 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/outputwriter.py +18 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/resultwriter.py +4 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/stringcache.py +3 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/xunitwriter.py +15 -21
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/__init__.py +3 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/configurer.py +12 -9
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/executionresult.py +56 -8
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/flattenkeywordmatcher.py +48 -9
- robotframework-7.0/src/robot/result/keywordremover.py +207 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/merger.py +1 -1
- robotframework-7.0/src/robot/result/model.py +1185 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/modeldeprecation.py +9 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/resultbuilder.py +46 -36
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/xmlelementhandlers.py +83 -43
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/run.py +3 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/__init__.py +14 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/__init__.py +2 -1
- robotframework-7.0/src/robot/running/arguments/argumentconverter.py +100 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentmapper.py +26 -24
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentparser.py +85 -61
- robotframework-7.0/src/robot/running/arguments/argumentresolver.py +158 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentspec.py +83 -116
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentvalidator.py +33 -27
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/customconverters.py +15 -12
- robotframework-7.0/src/robot/running/arguments/embedded.py +145 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/typeconverters.py +268 -220
- 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.1rc1 → robotframework-7.0}/src/robot/running/bodyrunner.py +147 -129
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/builders.py +17 -26
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/parsers.py +17 -11
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/settings.py +9 -17
- robotframework-7.0/src/robot/running/builder/transformers.py +535 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/context.py +113 -31
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/dynamicmethods.py +62 -34
- {robotframework-6.1rc1 → 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.1rc1 → robotframework-7.0}/src/robot/running/model.py +198 -337
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/namespace.py +124 -137
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/outputcapture.py +20 -12
- robotframework-7.0/src/robot/running/resourcemodel.py +448 -0
- {robotframework-6.1rc1 → 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.1rc1 → robotframework-7.0}/src/robot/testdoc.py +18 -13
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/__init__.py +53 -35
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/connectioncache.py +64 -59
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/dotdict.py +3 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/encodingsniffer.py +9 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/escaping.py +19 -19
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/importer.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/markupwriters.py +23 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/misc.py +1 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/normalizing.py +9 -24
- robotframework-7.0/src/robot/utils/notset.py +33 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/platform.py +15 -5
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotio.py +9 -9
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotpath.py +1 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robottime.py +122 -90
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robottypes.py +21 -31
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/setter.py +0 -5
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/text.py +7 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/unic.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/__init__.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/assigner.py +17 -19
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/evaluation.py +20 -17
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/filesetter.py +80 -80
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/replacer.py +33 -36
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/scopes.py +17 -12
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/search.py +66 -41
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/store.py +14 -16
- robotframework-7.0/src/robot/variables/tablesetter.py +164 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/variables.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/version.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/PKG-INFO +6 -8
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/SOURCES.txt +10 -8
- {robotframework-6.1rc1 → robotframework-7.0}/tasks.py +6 -6
- robotframework-6.1rc1/src/robot/htmldata/rebot/common.css +0 -239
- robotframework-6.1rc1/src/robot/libraries/Reserved.py +0 -48
- robotframework-6.1rc1/src/robot/model/keyword.py +0 -173
- robotframework-6.1rc1/src/robot/output/console/dotted.py +0 -90
- robotframework-6.1rc1/src/robot/output/listenerarguments.py +0 -165
- robotframework-6.1rc1/src/robot/output/listenermethods.py +0 -113
- robotframework-6.1rc1/src/robot/output/listeners.py +0 -174
- robotframework-6.1rc1/src/robot/output/output.py +0 -95
- robotframework-6.1rc1/src/robot/output/xmllogger.py +0 -354
- robotframework-6.1rc1/src/robot/parsing/model/visitor.py +0 -67
- robotframework-6.1rc1/src/robot/result/keywordremover.py +0 -183
- robotframework-6.1rc1/src/robot/result/model.py +0 -957
- robotframework-6.1rc1/src/robot/running/arguments/argumentconverter.py +0 -79
- robotframework-6.1rc1/src/robot/running/arguments/argumentresolver.py +0 -131
- robotframework-6.1rc1/src/robot/running/arguments/embedded.py +0 -146
- robotframework-6.1rc1/src/robot/running/arguments/typevalidator.py +0 -56
- robotframework-6.1rc1/src/robot/running/builder/transformers.py +0 -642
- robotframework-6.1rc1/src/robot/running/handlers.py +0 -321
- robotframework-6.1rc1/src/robot/running/handlerstore.py +0 -66
- robotframework-6.1rc1/src/robot/running/librarykeywordrunner.py +0 -238
- robotframework-6.1rc1/src/robot/running/libraryscopes.py +0 -97
- robotframework-6.1rc1/src/robot/running/modelcombiner.py +0 -32
- robotframework-6.1rc1/src/robot/running/suiterunner.py +0 -249
- robotframework-6.1rc1/src/robot/running/testlibraries.py +0 -420
- robotframework-6.1rc1/src/robot/running/usererrorhandler.py +0 -75
- robotframework-6.1rc1/src/robot/running/userkeyword.py +0 -111
- robotframework-6.1rc1/src/robot/running/userkeywordrunner.py +0 -274
- robotframework-6.1rc1/src/robot/variables/tablesetter.py +0 -156
- {robotframework-6.1rc1 → robotframework-7.0}/AUTHORS.rst +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/BUILD.rst +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/CONTRIBUTING.rst +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/COPYRIGHT.txt +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/LICENSE.txt +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/MANIFEST.in +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/setup.cfg +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/__main__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/errors.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/common/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/common/js_disabled.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/jsonwriter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/doc_formatting.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/print.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/pygments.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/fileloading.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/log.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/print.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/util.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/testdoc/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.html +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdoc.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/consoleviewer.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/htmlwriter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/jsonwriter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/output.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/writer.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Dialogs.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Easter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Screenshot.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Telnet.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/fixture.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/metadata.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/statistics.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/suitestatistics.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/tagsetter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/tagstatistics.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/totalstatistics.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/highlighting.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/pyloggingconf.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/tokenizer.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/model/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/blockparsers.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/fileparser.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/parser.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/suitestructure.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/pythonpathsetter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jsexecutionresult.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jswriter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/executionerrors.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/messagefilter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/suiteteardownfailed.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/visitor.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/randomizer.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/runkwregister.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/signalhandler.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/status.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/timeouts/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/timeouts/posix.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/timeouts/windows.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/application.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/argumentparser.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/asserts.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/charwidth.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/compress.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/encoding.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/error.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/etreewrapper.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/filereader.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/frange.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/htmlformatters.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/markuputils.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/match.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/recommendations.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/restreader.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotenv.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotinspect.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/sortable.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/typehints.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/finders.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/notfound.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/resolvable.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/dependency_links.txt +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/entry_points.txt +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/top_level.txt +0 -0
|
@@ -22,9 +22,10 @@ from robot.errors import DataError
|
|
|
22
22
|
from robot.parsing import File, get_init_model, get_model, get_resource_model
|
|
23
23
|
from robot.utils import FileReader, get_error_message, read_rest_data, type_name
|
|
24
24
|
|
|
25
|
+
from ..model import TestSuite
|
|
26
|
+
from ..resourcemodel import ResourceFile
|
|
25
27
|
from .settings import FileSettings, InitFileSettings, TestDefaults
|
|
26
28
|
from .transformers import ResourceBuilder, SuiteBuilder
|
|
27
|
-
from ..model import ResourceFile, TestSuite
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
class Parser(ABC):
|
|
@@ -53,22 +54,21 @@ class RobotParser(Parser):
|
|
|
53
54
|
def parse_suite_file(self, source: Path, defaults: TestDefaults) -> TestSuite:
|
|
54
55
|
model = get_model(self._get_source(source), data_only=True,
|
|
55
56
|
curdir=self._get_curdir(source), lang=self.lang)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
SuiteBuilder(suite, FileSettings(defaults)).build(model)
|
|
59
|
-
return suite
|
|
57
|
+
model.source = source
|
|
58
|
+
return self.parse_model(model, defaults)
|
|
60
59
|
|
|
61
60
|
def parse_init_file(self, source: Path, defaults: TestDefaults) -> TestSuite:
|
|
62
61
|
model = get_init_model(self._get_source(source), data_only=True,
|
|
63
62
|
curdir=self._get_curdir(source), lang=self.lang)
|
|
64
|
-
|
|
65
|
-
suite = TestSuite(name=TestSuite.name_from_source(
|
|
63
|
+
model.source = source
|
|
64
|
+
suite = TestSuite(name=TestSuite.name_from_source(source.parent),
|
|
65
|
+
source=source.parent, rpa=None)
|
|
66
66
|
SuiteBuilder(suite, InitFileSettings(defaults)).build(model)
|
|
67
67
|
return suite
|
|
68
68
|
|
|
69
69
|
def parse_model(self, model: File, defaults: 'TestDefaults|None' = None) -> TestSuite:
|
|
70
|
-
|
|
71
|
-
suite = TestSuite(name=
|
|
70
|
+
name = TestSuite.name_from_source(model.source, self.extensions)
|
|
71
|
+
suite = TestSuite(name=name, source=model.source)
|
|
72
72
|
SuiteBuilder(suite, FileSettings(defaults)).build(model)
|
|
73
73
|
return suite
|
|
74
74
|
|
|
@@ -81,7 +81,12 @@ class RobotParser(Parser):
|
|
|
81
81
|
def parse_resource_file(self, source: Path) -> ResourceFile:
|
|
82
82
|
model = get_resource_model(self._get_source(source), data_only=True,
|
|
83
83
|
curdir=self._get_curdir(source), lang=self.lang)
|
|
84
|
-
|
|
84
|
+
model.source = source
|
|
85
|
+
resource = self.parse_resource_model(model)
|
|
86
|
+
return resource
|
|
87
|
+
|
|
88
|
+
def parse_resource_model(self, model: File) -> ResourceFile:
|
|
89
|
+
resource = ResourceFile(source=model.source)
|
|
85
90
|
ResourceBuilder(resource).build(model)
|
|
86
91
|
return resource
|
|
87
92
|
|
|
@@ -112,7 +117,8 @@ class JsonParser(Parser):
|
|
|
112
117
|
class NoInitFileDirectoryParser(Parser):
|
|
113
118
|
|
|
114
119
|
def parse_init_file(self, source: Path, defaults: TestDefaults) -> TestSuite:
|
|
115
|
-
return TestSuite(name=TestSuite.name_from_source(source),
|
|
120
|
+
return TestSuite(name=TestSuite.name_from_source(source),
|
|
121
|
+
source=source, rpa=None)
|
|
116
122
|
|
|
117
123
|
|
|
118
124
|
class CustomParser(Parser):
|
|
@@ -13,31 +13,23 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
-
import sys
|
|
17
16
|
from collections.abc import Sequence
|
|
17
|
+
from typing import TypedDict
|
|
18
18
|
|
|
19
19
|
from ..model import TestCase
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
class OptionalItems(TypedDict, total=False):
|
|
23
|
+
args: 'Sequence[str]'
|
|
24
|
+
lineno: int
|
|
24
25
|
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
lineno: int
|
|
27
|
+
class FixtureDict(OptionalItems):
|
|
28
|
+
"""Dictionary containing setup or teardown info.
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
:attr:`args` and :attr:`lineno` are optional.
|
|
35
|
-
"""
|
|
36
|
-
name: str
|
|
37
|
-
|
|
38
|
-
else:
|
|
39
|
-
class FixtureDict(dict):
|
|
40
|
-
pass
|
|
30
|
+
:attr:`args` and :attr:`lineno` are optional.
|
|
31
|
+
"""
|
|
32
|
+
name: str
|
|
41
33
|
|
|
42
34
|
|
|
43
35
|
class TestDefaults:
|
|
@@ -0,0 +1,535 @@
|
|
|
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
|
+
from robot.errors import DataError
|
|
17
|
+
from robot.output import LOGGER
|
|
18
|
+
from robot.parsing import File, ModelVisitor, Token
|
|
19
|
+
from robot.utils import NormalizedDict
|
|
20
|
+
from robot.variables import VariableMatches
|
|
21
|
+
|
|
22
|
+
from ..model import For, If, IfBranch, TestSuite, TestCase, Try, TryBranch, While
|
|
23
|
+
from ..resourcemodel import ResourceFile, UserKeyword
|
|
24
|
+
from .settings import FileSettings
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class SettingsBuilder(ModelVisitor):
|
|
28
|
+
|
|
29
|
+
def __init__(self, suite: TestSuite, settings: FileSettings):
|
|
30
|
+
self.suite = suite
|
|
31
|
+
self.settings = settings
|
|
32
|
+
|
|
33
|
+
def visit_Documentation(self, node):
|
|
34
|
+
self.suite.doc = node.value
|
|
35
|
+
|
|
36
|
+
def visit_Metadata(self, node):
|
|
37
|
+
self.suite.metadata[node.name] = node.value
|
|
38
|
+
|
|
39
|
+
def visit_SuiteName(self, node):
|
|
40
|
+
self.suite.name = node.value
|
|
41
|
+
|
|
42
|
+
def visit_SuiteSetup(self, node):
|
|
43
|
+
self.suite.setup.config(name=node.name, args=node.args,
|
|
44
|
+
lineno=node.lineno)
|
|
45
|
+
|
|
46
|
+
def visit_SuiteTeardown(self, node):
|
|
47
|
+
self.suite.teardown.config(name=node.name, args=node.args,
|
|
48
|
+
lineno=node.lineno)
|
|
49
|
+
|
|
50
|
+
def visit_TestSetup(self, node):
|
|
51
|
+
self.settings.test_setup = {'name': node.name, 'args': node.args,
|
|
52
|
+
'lineno': node.lineno}
|
|
53
|
+
|
|
54
|
+
def visit_TestTeardown(self, node):
|
|
55
|
+
self.settings.test_teardown = {'name': node.name, 'args': node.args,
|
|
56
|
+
'lineno': node.lineno}
|
|
57
|
+
|
|
58
|
+
def visit_TestTimeout(self, node):
|
|
59
|
+
self.settings.test_timeout = node.value
|
|
60
|
+
|
|
61
|
+
def visit_DefaultTags(self, node):
|
|
62
|
+
self.settings.default_tags = node.values
|
|
63
|
+
|
|
64
|
+
def visit_TestTags(self, node):
|
|
65
|
+
self.settings.test_tags = node.values
|
|
66
|
+
|
|
67
|
+
def visit_KeywordTags(self, node):
|
|
68
|
+
self.settings.keyword_tags = node.values
|
|
69
|
+
|
|
70
|
+
def visit_TestTemplate(self, node):
|
|
71
|
+
self.settings.test_template = node.value
|
|
72
|
+
|
|
73
|
+
def visit_LibraryImport(self, node):
|
|
74
|
+
self.suite.resource.imports.library(node.name, node.args, node.alias, node.lineno)
|
|
75
|
+
|
|
76
|
+
def visit_ResourceImport(self, node):
|
|
77
|
+
self.suite.resource.imports.resource(node.name, node.lineno)
|
|
78
|
+
|
|
79
|
+
def visit_VariablesImport(self, node):
|
|
80
|
+
self.suite.resource.imports.variables(node.name, node.args, node.lineno)
|
|
81
|
+
|
|
82
|
+
def visit_VariableSection(self, node):
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
def visit_TestCaseSection(self, node):
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
def visit_KeywordSection(self, node):
|
|
89
|
+
pass
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class SuiteBuilder(ModelVisitor):
|
|
93
|
+
|
|
94
|
+
def __init__(self, suite: TestSuite, settings: FileSettings):
|
|
95
|
+
self.suite = suite
|
|
96
|
+
self.settings = settings
|
|
97
|
+
self.seen_keywords = NormalizedDict(ignore='_')
|
|
98
|
+
self.rpa = None
|
|
99
|
+
|
|
100
|
+
def build(self, model: File):
|
|
101
|
+
ErrorReporter(model.source).visit(model)
|
|
102
|
+
SettingsBuilder(self.suite, self.settings).visit(model)
|
|
103
|
+
self.visit(model)
|
|
104
|
+
if self.rpa is not None:
|
|
105
|
+
self.suite.rpa = self.rpa
|
|
106
|
+
|
|
107
|
+
def visit_SettingSection(self, node):
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
def visit_Variable(self, node):
|
|
111
|
+
self.suite.resource.variables.create(name=node.name,
|
|
112
|
+
value=node.value,
|
|
113
|
+
separator=node.separator,
|
|
114
|
+
lineno=node.lineno,
|
|
115
|
+
error=format_error(node.errors))
|
|
116
|
+
|
|
117
|
+
def visit_TestCaseSection(self, node):
|
|
118
|
+
if self.rpa is None:
|
|
119
|
+
self.rpa = node.tasks
|
|
120
|
+
elif self.rpa != node.tasks:
|
|
121
|
+
raise DataError('One file cannot have both tests and tasks.')
|
|
122
|
+
self.generic_visit(node)
|
|
123
|
+
|
|
124
|
+
def visit_TestCase(self, node):
|
|
125
|
+
TestCaseBuilder(self.suite, self.settings).build(node)
|
|
126
|
+
|
|
127
|
+
def visit_Keyword(self, node):
|
|
128
|
+
KeywordBuilder(self.suite.resource, self.settings, self.seen_keywords).build(node)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class ResourceBuilder(ModelVisitor):
|
|
132
|
+
|
|
133
|
+
def __init__(self, resource: ResourceFile):
|
|
134
|
+
self.resource = resource
|
|
135
|
+
self.settings = FileSettings()
|
|
136
|
+
self.seen_keywords = NormalizedDict(ignore='_')
|
|
137
|
+
|
|
138
|
+
def build(self, model: File):
|
|
139
|
+
ErrorReporter(model.source, raise_on_invalid_header=True).visit(model)
|
|
140
|
+
self.visit(model)
|
|
141
|
+
|
|
142
|
+
def visit_Documentation(self, node):
|
|
143
|
+
self.resource.doc = node.value
|
|
144
|
+
|
|
145
|
+
def visit_KeywordTags(self, node):
|
|
146
|
+
self.settings.keyword_tags = node.values
|
|
147
|
+
|
|
148
|
+
def visit_LibraryImport(self, node):
|
|
149
|
+
self.resource.imports.library(node.name, node.args, node.alias, node.lineno)
|
|
150
|
+
|
|
151
|
+
def visit_ResourceImport(self, node):
|
|
152
|
+
self.resource.imports.resource(node.name, node.lineno)
|
|
153
|
+
|
|
154
|
+
def visit_VariablesImport(self, node):
|
|
155
|
+
self.resource.imports.variables(node.name, node.args, node.lineno)
|
|
156
|
+
|
|
157
|
+
def visit_Variable(self, node):
|
|
158
|
+
self.resource.variables.create(name=node.name,
|
|
159
|
+
value=node.value,
|
|
160
|
+
separator=node.separator,
|
|
161
|
+
lineno=node.lineno,
|
|
162
|
+
error=format_error(node.errors))
|
|
163
|
+
|
|
164
|
+
def visit_Keyword(self, node):
|
|
165
|
+
KeywordBuilder(self.resource, self.settings, self.seen_keywords).build(node)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class BodyBuilder(ModelVisitor):
|
|
169
|
+
|
|
170
|
+
def __init__(self, model: 'TestCase|UserKeyword|For|If|Try|While|None' = None):
|
|
171
|
+
self.model = model
|
|
172
|
+
|
|
173
|
+
def visit_For(self, node):
|
|
174
|
+
ForBuilder(self.model).build(node)
|
|
175
|
+
|
|
176
|
+
def visit_While(self, node):
|
|
177
|
+
WhileBuilder(self.model).build(node)
|
|
178
|
+
|
|
179
|
+
def visit_If(self, node):
|
|
180
|
+
IfBuilder(self.model).build(node)
|
|
181
|
+
|
|
182
|
+
def visit_Try(self, node):
|
|
183
|
+
TryBuilder(self.model).build(node)
|
|
184
|
+
|
|
185
|
+
def visit_KeywordCall(self, node):
|
|
186
|
+
self.model.body.create_keyword(name=node.keyword, args=node.args,
|
|
187
|
+
assign=node.assign, lineno=node.lineno)
|
|
188
|
+
|
|
189
|
+
def visit_TemplateArguments(self, node):
|
|
190
|
+
self.model.body.create_keyword(args=node.args, lineno=node.lineno)
|
|
191
|
+
|
|
192
|
+
def visit_Var(self, node):
|
|
193
|
+
self.model.body.create_var(node.name, node.value, node.scope, node.separator,
|
|
194
|
+
lineno=node.lineno, error=format_error(node.errors))
|
|
195
|
+
|
|
196
|
+
def visit_Return(self, node):
|
|
197
|
+
self.model.body.create_return(node.values, lineno=node.lineno,
|
|
198
|
+
error=format_error(node.errors))
|
|
199
|
+
|
|
200
|
+
def visit_Continue(self, node):
|
|
201
|
+
self.model.body.create_continue(lineno=node.lineno,
|
|
202
|
+
error=format_error(node.errors))
|
|
203
|
+
|
|
204
|
+
def visit_Break(self, node):
|
|
205
|
+
self.model.body.create_break(lineno=node.lineno,
|
|
206
|
+
error=format_error(node.errors))
|
|
207
|
+
|
|
208
|
+
def visit_Error(self, node):
|
|
209
|
+
self.model.body.create_error(node.values, lineno=node.lineno,
|
|
210
|
+
error=format_error(node.errors))
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class TestCaseBuilder(BodyBuilder):
|
|
214
|
+
model: TestCase
|
|
215
|
+
|
|
216
|
+
def __init__(self, suite: TestSuite, settings: FileSettings):
|
|
217
|
+
super().__init__(suite.tests.create())
|
|
218
|
+
self.settings = settings
|
|
219
|
+
self._test_has_tags = False
|
|
220
|
+
|
|
221
|
+
def build(self, node):
|
|
222
|
+
settings = self.settings
|
|
223
|
+
# Possible parsing errors aren't reported further with tests because:
|
|
224
|
+
# - We only validate that test body or name isn't empty.
|
|
225
|
+
# - That is validated again during execution.
|
|
226
|
+
# - This way e.g. model modifiers can add content to body.
|
|
227
|
+
self.model.config(name=node.name, tags=settings.test_tags,
|
|
228
|
+
timeout=settings.test_timeout,
|
|
229
|
+
template=settings.test_template,
|
|
230
|
+
lineno=node.lineno)
|
|
231
|
+
if settings.test_setup:
|
|
232
|
+
self.model.setup.config(**settings.test_setup)
|
|
233
|
+
if settings.test_teardown:
|
|
234
|
+
self.model.teardown.config(**settings.test_teardown)
|
|
235
|
+
self.generic_visit(node)
|
|
236
|
+
if not self._test_has_tags:
|
|
237
|
+
self.model.tags.add(settings.default_tags)
|
|
238
|
+
if self.model.template:
|
|
239
|
+
self._set_template(self.model, self.model.template)
|
|
240
|
+
|
|
241
|
+
def _set_template(self, parent, template):
|
|
242
|
+
for item in parent.body:
|
|
243
|
+
if item.type == item.FOR:
|
|
244
|
+
self._set_template(item, template)
|
|
245
|
+
elif item.type == item.IF_ELSE_ROOT:
|
|
246
|
+
for branch in item.body:
|
|
247
|
+
self._set_template(branch, template)
|
|
248
|
+
elif item.type == item.KEYWORD:
|
|
249
|
+
name, args = self._format_template(template, item.args)
|
|
250
|
+
item.name = name
|
|
251
|
+
item.args = args
|
|
252
|
+
|
|
253
|
+
def _format_template(self, template, arguments):
|
|
254
|
+
matches = VariableMatches(template, identifiers='$')
|
|
255
|
+
count = len(matches)
|
|
256
|
+
if count == 0 or count != len(arguments):
|
|
257
|
+
return template, arguments
|
|
258
|
+
temp = []
|
|
259
|
+
for match, arg in zip(matches, arguments):
|
|
260
|
+
temp[-1:] = [match.before, arg, match.after]
|
|
261
|
+
return ''.join(temp), ()
|
|
262
|
+
|
|
263
|
+
def visit_Documentation(self, node):
|
|
264
|
+
self.model.doc = node.value
|
|
265
|
+
|
|
266
|
+
def visit_Setup(self, node):
|
|
267
|
+
self.model.setup.config(name=node.name, args=node.args, lineno=node.lineno)
|
|
268
|
+
|
|
269
|
+
def visit_Teardown(self, node):
|
|
270
|
+
self.model.teardown.config(name=node.name, args=node.args, lineno=node.lineno)
|
|
271
|
+
|
|
272
|
+
def visit_Timeout(self, node):
|
|
273
|
+
self.model.timeout = node.value
|
|
274
|
+
|
|
275
|
+
def visit_Tags(self, node):
|
|
276
|
+
for tag in node.values:
|
|
277
|
+
if tag.startswith('-'):
|
|
278
|
+
self.model.tags.remove(tag[1:])
|
|
279
|
+
else:
|
|
280
|
+
self.model.tags.add(tag)
|
|
281
|
+
self._test_has_tags = True
|
|
282
|
+
|
|
283
|
+
def visit_Template(self, node):
|
|
284
|
+
self.model.template = node.value
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
class KeywordBuilder(BodyBuilder):
|
|
288
|
+
model: UserKeyword
|
|
289
|
+
|
|
290
|
+
def __init__(self, resource: ResourceFile, settings: FileSettings,
|
|
291
|
+
seen_keywords: NormalizedDict):
|
|
292
|
+
super().__init__(resource.keywords.create(tags=settings.keyword_tags))
|
|
293
|
+
self.resource = resource
|
|
294
|
+
self.seen_keywords = seen_keywords
|
|
295
|
+
self.return_setting = None
|
|
296
|
+
|
|
297
|
+
def build(self, node):
|
|
298
|
+
kw = self.model
|
|
299
|
+
try:
|
|
300
|
+
# Validate only name here. Reporting all parsing errors would report also
|
|
301
|
+
# body being empty, but we want to validate it only at parsing time.
|
|
302
|
+
if not node.name:
|
|
303
|
+
raise DataError('User keyword name cannot be empty.')
|
|
304
|
+
kw.config(name=node.name, lineno=node.lineno)
|
|
305
|
+
except DataError as err:
|
|
306
|
+
# Errors other than name being empty mean that name contains invalid
|
|
307
|
+
# embedded arguments. Need to set `_name` to bypass `@property`.
|
|
308
|
+
kw.config(_name=node.name, lineno=node.lineno, error=str(err))
|
|
309
|
+
self._report_error(node, err)
|
|
310
|
+
self.generic_visit(node)
|
|
311
|
+
if self.return_setting:
|
|
312
|
+
kw.body.create_return(self.return_setting)
|
|
313
|
+
if not kw.embedded:
|
|
314
|
+
self._handle_duplicates(kw, self.seen_keywords, node)
|
|
315
|
+
|
|
316
|
+
def _report_error(self, node, error):
|
|
317
|
+
error = f"Creating keyword '{self.model.name}' failed: {error}"
|
|
318
|
+
ErrorReporter(self.model.source).report_error(node, error)
|
|
319
|
+
|
|
320
|
+
def _handle_duplicates(self, kw, seen, node):
|
|
321
|
+
if kw.name in seen:
|
|
322
|
+
error = 'Keyword with same name defined multiple times.'
|
|
323
|
+
seen[kw.name].error = error
|
|
324
|
+
self.resource.keywords.pop()
|
|
325
|
+
self._report_error(node, error)
|
|
326
|
+
else:
|
|
327
|
+
seen[kw.name] = kw
|
|
328
|
+
|
|
329
|
+
def visit_Documentation(self, node):
|
|
330
|
+
self.model.doc = node.value
|
|
331
|
+
|
|
332
|
+
def visit_Arguments(self, node):
|
|
333
|
+
if node.errors:
|
|
334
|
+
error = 'Invalid argument specification: ' + format_error(node.errors)
|
|
335
|
+
self.model.error = error
|
|
336
|
+
self._report_error(node, error)
|
|
337
|
+
else:
|
|
338
|
+
self.model.args = node.values
|
|
339
|
+
|
|
340
|
+
def visit_Tags(self, node):
|
|
341
|
+
for tag in node.values:
|
|
342
|
+
if tag.startswith('-'):
|
|
343
|
+
self.model.tags.remove(tag[1:])
|
|
344
|
+
else:
|
|
345
|
+
self.model.tags.add(tag)
|
|
346
|
+
|
|
347
|
+
def visit_ReturnSetting(self, node):
|
|
348
|
+
ErrorReporter(self.model.source).visit(node)
|
|
349
|
+
self.return_setting = node.values
|
|
350
|
+
|
|
351
|
+
def visit_Timeout(self, node):
|
|
352
|
+
self.model.timeout = node.value
|
|
353
|
+
|
|
354
|
+
def visit_Setup(self, node):
|
|
355
|
+
self.model.setup.config(name=node.name, args=node.args, lineno=node.lineno)
|
|
356
|
+
|
|
357
|
+
def visit_Teardown(self, node):
|
|
358
|
+
self.model.teardown.config(name=node.name, args=node.args, lineno=node.lineno)
|
|
359
|
+
|
|
360
|
+
def visit_KeywordCall(self, node):
|
|
361
|
+
self.model.body.create_keyword(name=node.keyword, args=node.args,
|
|
362
|
+
assign=node.assign, lineno=node.lineno)
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
class ForBuilder(BodyBuilder):
|
|
366
|
+
model: For
|
|
367
|
+
|
|
368
|
+
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While'):
|
|
369
|
+
super().__init__(parent.body.create_for())
|
|
370
|
+
|
|
371
|
+
def build(self, node):
|
|
372
|
+
error = format_error(self._get_errors(node))
|
|
373
|
+
self.model.config(assign=node.assign, flavor=node.flavor, values=node.values,
|
|
374
|
+
start=node.start, mode=node.mode, fill=node.fill,
|
|
375
|
+
lineno=node.lineno, error=error)
|
|
376
|
+
for step in node.body:
|
|
377
|
+
self.visit(step)
|
|
378
|
+
return self.model
|
|
379
|
+
|
|
380
|
+
def _get_errors(self, node):
|
|
381
|
+
errors = node.header.errors + node.errors
|
|
382
|
+
if node.end:
|
|
383
|
+
errors += node.end.errors
|
|
384
|
+
return errors
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
class IfBuilder(BodyBuilder):
|
|
388
|
+
model: 'IfBranch|None'
|
|
389
|
+
|
|
390
|
+
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While'):
|
|
391
|
+
super().__init__()
|
|
392
|
+
self.root = parent.body.create_if()
|
|
393
|
+
|
|
394
|
+
def build(self, node):
|
|
395
|
+
self.root.config(lineno=node.lineno, error=format_error(self._get_errors(node)))
|
|
396
|
+
assign = node.assign
|
|
397
|
+
node_type = None
|
|
398
|
+
while node:
|
|
399
|
+
node_type = node.type if node.type != 'INLINE IF' else 'IF'
|
|
400
|
+
self.model = self.root.body.create_branch(node_type, node.condition,
|
|
401
|
+
lineno=node.lineno)
|
|
402
|
+
for step in node.body:
|
|
403
|
+
self.visit(step)
|
|
404
|
+
if assign:
|
|
405
|
+
for item in self.model.body:
|
|
406
|
+
# Having assign when model item doesn't support assign is an error,
|
|
407
|
+
# but it has been handled already when model was validated.
|
|
408
|
+
if hasattr(item, 'assign'):
|
|
409
|
+
item.assign = assign
|
|
410
|
+
node = node.orelse
|
|
411
|
+
# Smallish hack to make sure assignment is always run.
|
|
412
|
+
if assign and node_type != 'ELSE':
|
|
413
|
+
self.root.body.create_branch('ELSE').body.create_keyword(
|
|
414
|
+
assign=assign, name='BuiltIn.Set Variable', args=['${NONE}']
|
|
415
|
+
)
|
|
416
|
+
return self.root
|
|
417
|
+
|
|
418
|
+
def _get_errors(self, node):
|
|
419
|
+
errors = node.header.errors + node.errors
|
|
420
|
+
if node.orelse:
|
|
421
|
+
errors += self._get_errors(node.orelse)
|
|
422
|
+
if node.end:
|
|
423
|
+
errors += node.end.errors
|
|
424
|
+
return errors
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
class TryBuilder(BodyBuilder):
|
|
428
|
+
model: 'TryBranch|None'
|
|
429
|
+
|
|
430
|
+
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While'):
|
|
431
|
+
super().__init__()
|
|
432
|
+
self.root = parent.body.create_try()
|
|
433
|
+
self.template_error = None
|
|
434
|
+
|
|
435
|
+
def build(self, node):
|
|
436
|
+
self.root.config(lineno=node.lineno)
|
|
437
|
+
errors = self._get_errors(node)
|
|
438
|
+
while node:
|
|
439
|
+
self.model = self.root.body.create_branch(node.type, node.patterns,
|
|
440
|
+
node.pattern_type, node.assign,
|
|
441
|
+
lineno=node.lineno)
|
|
442
|
+
for step in node.body:
|
|
443
|
+
self.visit(step)
|
|
444
|
+
node = node.next
|
|
445
|
+
if self.template_error:
|
|
446
|
+
errors += (self.template_error,)
|
|
447
|
+
if errors:
|
|
448
|
+
self.root.error = format_error(errors)
|
|
449
|
+
return self.root
|
|
450
|
+
|
|
451
|
+
def _get_errors(self, node):
|
|
452
|
+
errors = node.header.errors + node.errors
|
|
453
|
+
if node.next:
|
|
454
|
+
errors += self._get_errors(node.next)
|
|
455
|
+
if node.end:
|
|
456
|
+
errors += node.end.errors
|
|
457
|
+
return errors
|
|
458
|
+
|
|
459
|
+
def visit_TemplateArguments(self, node):
|
|
460
|
+
self.template_error = 'Templates cannot be used with TRY.'
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
class WhileBuilder(BodyBuilder):
|
|
464
|
+
model: While
|
|
465
|
+
|
|
466
|
+
def __init__(self, parent: 'TestCase|UserKeyword|For|If|Try|While'):
|
|
467
|
+
super().__init__(parent.body.create_while())
|
|
468
|
+
|
|
469
|
+
def build(self, node):
|
|
470
|
+
error = format_error(self._get_errors(node))
|
|
471
|
+
self.model.config(condition=node.condition, limit=node.limit,
|
|
472
|
+
on_limit=node.on_limit, on_limit_message=node.on_limit_message,
|
|
473
|
+
lineno=node.lineno, error=error)
|
|
474
|
+
for step in node.body:
|
|
475
|
+
self.visit(step)
|
|
476
|
+
return self.model
|
|
477
|
+
|
|
478
|
+
def _get_errors(self, node):
|
|
479
|
+
errors = node.header.errors + node.errors
|
|
480
|
+
if node.end:
|
|
481
|
+
errors += node.end.errors
|
|
482
|
+
return errors
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def format_error(errors):
|
|
486
|
+
if not errors:
|
|
487
|
+
return None
|
|
488
|
+
if len(errors) == 1:
|
|
489
|
+
return errors[0]
|
|
490
|
+
return '\n- '.join(('Multiple errors:',) + errors)
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
class ErrorReporter(ModelVisitor):
|
|
494
|
+
|
|
495
|
+
def __init__(self, source, raise_on_invalid_header=False):
|
|
496
|
+
self.source = source
|
|
497
|
+
self.raise_on_invalid_header = raise_on_invalid_header
|
|
498
|
+
|
|
499
|
+
def visit_TestCase(self, node):
|
|
500
|
+
pass
|
|
501
|
+
|
|
502
|
+
def visit_Keyword(self, node):
|
|
503
|
+
pass
|
|
504
|
+
|
|
505
|
+
def visit_ReturnSetting(self, node):
|
|
506
|
+
# Empty 'visit_Keyword' above prevents calling this when visiting the whole
|
|
507
|
+
# model, but 'KeywordBuilder.visit_ReturnSetting' visits the node it gets.
|
|
508
|
+
self.report_error(node.get_token(Token.RETURN_SETTING), warn=True)
|
|
509
|
+
|
|
510
|
+
def visit_SectionHeader(self, node):
|
|
511
|
+
token = node.get_token(*Token.HEADER_TOKENS)
|
|
512
|
+
if not token.error:
|
|
513
|
+
return
|
|
514
|
+
if token.type == Token.INVALID_HEADER:
|
|
515
|
+
self.report_error(token, throw=self.raise_on_invalid_header)
|
|
516
|
+
else:
|
|
517
|
+
# Errors, other than totally invalid headers, can occur only with
|
|
518
|
+
# deprecated singular headers, and we want to report them as warnings.
|
|
519
|
+
# A more generic solution for separating errors and warnings would be good.
|
|
520
|
+
self.report_error(token, warn=True)
|
|
521
|
+
|
|
522
|
+
def visit_Error(self, node):
|
|
523
|
+
for token in node.get_tokens(Token.ERROR):
|
|
524
|
+
self.report_error(token)
|
|
525
|
+
|
|
526
|
+
def report_error(self, source, error=None, warn=False, throw=False):
|
|
527
|
+
if not error:
|
|
528
|
+
if isinstance(source, Token):
|
|
529
|
+
error = source.error
|
|
530
|
+
else:
|
|
531
|
+
error = format_error(source.errors)
|
|
532
|
+
message = f"Error in file '{self.source}' on line {source.lineno}: {error}"
|
|
533
|
+
if throw:
|
|
534
|
+
raise DataError(message)
|
|
535
|
+
LOGGER.write(message, level='WARN' if warn else 'ERROR')
|