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
|
@@ -105,7 +105,7 @@ class VariableAssigner:
|
|
|
105
105
|
|
|
106
106
|
def assign(self, return_value):
|
|
107
107
|
context = self._context
|
|
108
|
-
context.output.trace(lambda: 'Return:
|
|
108
|
+
context.output.trace(lambda: f'Return: {prepr(return_value)}',
|
|
109
109
|
write_if_flat=False)
|
|
110
110
|
resolver = ReturnValueResolver(self._assignment)
|
|
111
111
|
for name, items, value in resolver.resolve(return_value):
|
|
@@ -120,7 +120,7 @@ class VariableAssigner:
|
|
|
120
120
|
return False
|
|
121
121
|
base, attr = [token.strip() for token in name[2:-1].rsplit('.', 1)]
|
|
122
122
|
try:
|
|
123
|
-
var = variables.replace_scalar('${
|
|
123
|
+
var = variables.replace_scalar(f'${{{base}}}')
|
|
124
124
|
except VariableError:
|
|
125
125
|
return False
|
|
126
126
|
if not (self._variable_supports_extended_assign(var) and
|
|
@@ -128,9 +128,9 @@ class VariableAssigner:
|
|
|
128
128
|
return False
|
|
129
129
|
try:
|
|
130
130
|
setattr(var, attr, value)
|
|
131
|
-
except:
|
|
132
|
-
raise VariableError("Setting attribute '
|
|
133
|
-
|
|
131
|
+
except Exception:
|
|
132
|
+
raise VariableError(f"Setting attribute '{attr}' to variable '${{{base}}}' "
|
|
133
|
+
f"failed: {get_error_message()}")
|
|
134
134
|
return True
|
|
135
135
|
|
|
136
136
|
def _variable_supports_extended_assign(self, var):
|
|
@@ -172,14 +172,12 @@ class VariableAssigner:
|
|
|
172
172
|
*nested, item = items
|
|
173
173
|
decorated_nested_items = ''.join(f'[{item}]' for item in nested)
|
|
174
174
|
var = variables.replace_scalar(f'${name[1:]}{decorated_nested_items}')
|
|
175
|
-
|
|
176
175
|
if not self._variable_type_supports_item_assign(var):
|
|
177
176
|
var_type = type_name(var)
|
|
178
177
|
raise VariableError(
|
|
179
178
|
f"Variable '{name}{decorated_nested_items}' is {var_type} "
|
|
180
179
|
f"and does not support item assignment."
|
|
181
180
|
)
|
|
182
|
-
|
|
183
181
|
selector = variables.replace_scalar(item)
|
|
184
182
|
if isinstance(var, MutableSequence):
|
|
185
183
|
try:
|
|
@@ -199,7 +197,10 @@ class VariableAssigner:
|
|
|
199
197
|
return value
|
|
200
198
|
|
|
201
199
|
def _normal_assign(self, name, value, variables):
|
|
202
|
-
|
|
200
|
+
try:
|
|
201
|
+
variables[name] = value
|
|
202
|
+
except DataError as err:
|
|
203
|
+
raise VariableError(f"Setting variable '{name}' failed: {err}")
|
|
203
204
|
# Always return the actually assigned value.
|
|
204
205
|
return value if name[0] == '$' else variables[name]
|
|
205
206
|
|
|
@@ -239,8 +240,8 @@ class _MultiReturnValueResolver:
|
|
|
239
240
|
def __init__(self, assignments):
|
|
240
241
|
self._names = []
|
|
241
242
|
self._items = []
|
|
242
|
-
for
|
|
243
|
-
match: VariableMatch = search_variable(
|
|
243
|
+
for assign in assignments:
|
|
244
|
+
match: VariableMatch = search_variable(assign)
|
|
244
245
|
self._names.append(match.name)
|
|
245
246
|
self._items.append(match.items)
|
|
246
247
|
self._min_count = len(assignments)
|
|
@@ -261,10 +262,10 @@ class _MultiReturnValueResolver:
|
|
|
261
262
|
self._raise_expected_list(return_value)
|
|
262
263
|
|
|
263
264
|
def _raise_expected_list(self, ret):
|
|
264
|
-
self._raise('Expected list-like value, got
|
|
265
|
+
self._raise(f'Expected list-like value, got {type_name(ret)}.')
|
|
265
266
|
|
|
266
267
|
def _raise(self, error):
|
|
267
|
-
raise VariableError('Cannot set variables:
|
|
268
|
+
raise VariableError(f'Cannot set variables: {error}')
|
|
268
269
|
|
|
269
270
|
def _validate(self, return_count):
|
|
270
271
|
raise NotImplementedError
|
|
@@ -277,8 +278,7 @@ class ScalarsOnlyReturnValueResolver(_MultiReturnValueResolver):
|
|
|
277
278
|
|
|
278
279
|
def _validate(self, return_count):
|
|
279
280
|
if return_count != self._min_count:
|
|
280
|
-
self._raise('Expected
|
|
281
|
-
% (self._min_count, return_count))
|
|
281
|
+
self._raise(f'Expected {self._min_count} return values, got {return_count}.')
|
|
282
282
|
|
|
283
283
|
def _resolve(self, return_value):
|
|
284
284
|
return list(zip(self._names, self._items, return_value))
|
|
@@ -287,18 +287,17 @@ class ScalarsOnlyReturnValueResolver(_MultiReturnValueResolver):
|
|
|
287
287
|
class ScalarsAndListReturnValueResolver(_MultiReturnValueResolver):
|
|
288
288
|
|
|
289
289
|
def __init__(self, assignments):
|
|
290
|
-
|
|
290
|
+
super().__init__(assignments)
|
|
291
291
|
self._min_count -= 1
|
|
292
292
|
|
|
293
293
|
def _validate(self, return_count):
|
|
294
294
|
if return_count < self._min_count:
|
|
295
|
-
self._raise('Expected
|
|
296
|
-
|
|
295
|
+
self._raise(f'Expected {self._min_count} or more return values, '
|
|
296
|
+
f'got {return_count}.')
|
|
297
297
|
|
|
298
298
|
def _resolve(self, return_value):
|
|
299
299
|
list_index = [a[0][0] for a in self._names].index('@')
|
|
300
300
|
list_len = len(return_value) - len(self._names) + 1
|
|
301
|
-
|
|
302
301
|
elements_before_list = list(zip(
|
|
303
302
|
self._names[:list_index],
|
|
304
303
|
self._items[:list_index],
|
|
@@ -314,5 +313,4 @@ class ScalarsAndListReturnValueResolver(_MultiReturnValueResolver):
|
|
|
314
313
|
self._items[list_index],
|
|
315
314
|
return_value[list_index:list_index+list_len],
|
|
316
315
|
)]
|
|
317
|
-
|
|
318
316
|
return elements_before_list + list_elements + elements_after_list
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
16
|
import builtins
|
|
17
|
+
import re
|
|
17
18
|
import token
|
|
18
19
|
from collections.abc import MutableMapping
|
|
19
20
|
from io import StringIO
|
|
@@ -22,7 +23,7 @@ from tokenize import generate_tokens, untokenize
|
|
|
22
23
|
from robot.errors import DataError
|
|
23
24
|
from robot.utils import get_error_message, type_name
|
|
24
25
|
|
|
25
|
-
from .search import
|
|
26
|
+
from .search import VariableMatches
|
|
26
27
|
from .notfound import variable_not_found
|
|
27
28
|
|
|
28
29
|
|
|
@@ -44,12 +45,18 @@ def evaluate_expression(expression, variables, modules=None, namespace=None,
|
|
|
44
45
|
return _evaluate(expression, variables.store, modules, namespace)
|
|
45
46
|
except DataError as err:
|
|
46
47
|
error = str(err)
|
|
47
|
-
|
|
48
|
-
except Exception:
|
|
48
|
+
variable_recommendation = ''
|
|
49
|
+
except Exception as err:
|
|
49
50
|
error = get_error_message()
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
variable_recommendation = ''
|
|
52
|
+
if isinstance(err, NameError) and 'RF_VAR_' in error:
|
|
53
|
+
name = re.search(r'RF_VAR_([\w_]*)', error).group(1)
|
|
54
|
+
error = (f"Robot Framework variable '${name}' is used in a scope "
|
|
55
|
+
f"where it cannot be seen.")
|
|
56
|
+
else:
|
|
57
|
+
variable_recommendation = _recommend_special_variables(original)
|
|
58
|
+
raise DataError(f'Evaluating expression {expression!r} failed: {error}\n\n'
|
|
59
|
+
f'{variable_recommendation}'.strip())
|
|
53
60
|
|
|
54
61
|
|
|
55
62
|
def _evaluate(expression, variable_store, modules=None, namespace=None):
|
|
@@ -106,19 +113,15 @@ def _import_modules(module_names):
|
|
|
106
113
|
|
|
107
114
|
|
|
108
115
|
def _recommend_special_variables(expression):
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
while True:
|
|
112
|
-
match = search_variable(remaining)
|
|
113
|
-
if not match:
|
|
114
|
-
break
|
|
115
|
-
example[-1:] = [match.before, match.identifier, match.base, match.after]
|
|
116
|
-
remaining = example[-1]
|
|
117
|
-
if not example:
|
|
116
|
+
matches = VariableMatches(expression)
|
|
117
|
+
if not matches:
|
|
118
118
|
return ''
|
|
119
|
+
example = []
|
|
120
|
+
for match in matches:
|
|
121
|
+
example[-1:] += [match.before, match.identifier, match.base, match.after]
|
|
119
122
|
example = ''.join(example)
|
|
120
|
-
return (f"Variables in the original expression
|
|
121
|
-
f"before the expression was evaluated. Try using
|
|
123
|
+
return (f"Variables in the original expression {expression!r} were resolved "
|
|
124
|
+
f"before the expression was evaluated. Try using {example!r} "
|
|
122
125
|
f"syntax to avoid that. See Evaluating Expressions appendix in "
|
|
123
126
|
f"Robot Framework User Guide for more details.")
|
|
124
127
|
|
|
@@ -23,14 +23,16 @@ except ImportError:
|
|
|
23
23
|
|
|
24
24
|
from robot.errors import DataError
|
|
25
25
|
from robot.output import LOGGER
|
|
26
|
-
from robot.utils import (get_error_message,
|
|
27
|
-
|
|
26
|
+
from robot.utils import (DotDict, get_error_message, Importer, is_dict_like,
|
|
27
|
+
is_list_like, type_name)
|
|
28
|
+
|
|
29
|
+
from .store import VariableStore
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
class VariableFileSetter:
|
|
31
33
|
|
|
32
|
-
def __init__(self, store):
|
|
33
|
-
self.
|
|
34
|
+
def __init__(self, store: VariableStore):
|
|
35
|
+
self.store = store
|
|
34
36
|
|
|
35
37
|
def set(self, path_or_variables, args=None, overwrite=False):
|
|
36
38
|
variables = self._import_if_needed(path_or_variables, args)
|
|
@@ -38,10 +40,9 @@ class VariableFileSetter:
|
|
|
38
40
|
return variables
|
|
39
41
|
|
|
40
42
|
def _import_if_needed(self, path_or_variables, args=None):
|
|
41
|
-
if not
|
|
43
|
+
if not isinstance(path_or_variables, str):
|
|
42
44
|
return path_or_variables
|
|
43
|
-
LOGGER.info("Importing variable file '
|
|
44
|
-
% (path_or_variables, args))
|
|
45
|
+
LOGGER.info(f"Importing variable file '{path_or_variables}' with args {args}.")
|
|
45
46
|
if path_or_variables.lower().endswith(('.yaml', '.yml')):
|
|
46
47
|
importer = YamlImporter()
|
|
47
48
|
elif path_or_variables.lower().endswith('.json'):
|
|
@@ -50,48 +51,14 @@ class VariableFileSetter:
|
|
|
50
51
|
importer = PythonImporter()
|
|
51
52
|
try:
|
|
52
53
|
return importer.import_variables(path_or_variables, args)
|
|
53
|
-
except:
|
|
54
|
-
args = 'with arguments
|
|
55
|
-
raise DataError("Processing variable file '
|
|
56
|
-
|
|
54
|
+
except Exception:
|
|
55
|
+
args = f'with arguments {args} ' if args else ''
|
|
56
|
+
raise DataError(f"Processing variable file '{path_or_variables}' "
|
|
57
|
+
f"{args}failed: {get_error_message()}")
|
|
57
58
|
|
|
58
59
|
def _set(self, variables, overwrite=False):
|
|
59
60
|
for name, value in variables:
|
|
60
|
-
self.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class YamlImporter:
|
|
64
|
-
|
|
65
|
-
def import_variables(self, path, args=None):
|
|
66
|
-
if args:
|
|
67
|
-
raise DataError('YAML variable files do not accept arguments.')
|
|
68
|
-
variables = self._import(path)
|
|
69
|
-
return [('${%s}' % name, self._dot_dict(value))
|
|
70
|
-
for name, value in variables]
|
|
71
|
-
|
|
72
|
-
def _import(self, path):
|
|
73
|
-
with io.open(path, encoding='UTF-8') as stream:
|
|
74
|
-
variables = self._load_yaml(stream)
|
|
75
|
-
if not is_dict_like(variables):
|
|
76
|
-
raise DataError('YAML variable file must be a mapping, got %s.'
|
|
77
|
-
% type_name(variables))
|
|
78
|
-
return variables.items()
|
|
79
|
-
|
|
80
|
-
def _load_yaml(self, stream):
|
|
81
|
-
if not yaml:
|
|
82
|
-
raise DataError('Using YAML variable files requires PyYAML module '
|
|
83
|
-
'to be installed. Typically you can install it '
|
|
84
|
-
'by running `pip install pyyaml`.')
|
|
85
|
-
if yaml.__version__.split('.')[0] == '3':
|
|
86
|
-
return yaml.load(stream)
|
|
87
|
-
return yaml.full_load(stream)
|
|
88
|
-
|
|
89
|
-
def _dot_dict(self, value):
|
|
90
|
-
if is_dict_like(value):
|
|
91
|
-
return DotDict((k, self._dot_dict(v)) for k, v in value.items())
|
|
92
|
-
if is_list_like(value):
|
|
93
|
-
return [self._dot_dict(v) for v in value]
|
|
94
|
-
return value
|
|
61
|
+
self.store.add(name, value, overwrite, decorated=False)
|
|
95
62
|
|
|
96
63
|
|
|
97
64
|
class PythonImporter:
|
|
@@ -102,24 +69,29 @@ class PythonImporter:
|
|
|
102
69
|
return self._get_variables(var_file, args)
|
|
103
70
|
|
|
104
71
|
def _get_variables(self, var_file, args):
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
72
|
+
get_variables = (getattr(var_file, 'get_variables', None) or
|
|
73
|
+
getattr(var_file, 'getVariables', None))
|
|
74
|
+
if get_variables:
|
|
75
|
+
variables = self._get_dynamic(get_variables, args)
|
|
76
|
+
elif not args:
|
|
108
77
|
variables = self._get_static(var_file)
|
|
78
|
+
else:
|
|
79
|
+
raise DataError('Static variable files do not accept arguments.')
|
|
109
80
|
return list(self._decorate_and_validate(variables))
|
|
110
81
|
|
|
111
|
-
def
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
def _get_dynamic(self, var_file, args):
|
|
116
|
-
get_variables = (getattr(var_file, 'get_variables', None) or
|
|
117
|
-
getattr(var_file, 'getVariables'))
|
|
118
|
-
variables = get_variables(*args)
|
|
82
|
+
def _get_dynamic(self, get_variables, args):
|
|
83
|
+
positional, named = self._resolve_arguments(get_variables, args)
|
|
84
|
+
variables = get_variables(*positional, **dict(named))
|
|
119
85
|
if is_dict_like(variables):
|
|
120
86
|
return variables.items()
|
|
121
|
-
raise DataError("Expected '
|
|
122
|
-
|
|
87
|
+
raise DataError(f"Expected '{get_variables.__name__}' to return "
|
|
88
|
+
f"a dictionary-like value, got {type_name(variables)}.")
|
|
89
|
+
|
|
90
|
+
def _resolve_arguments(self, get_variables, args):
|
|
91
|
+
# Avoid cyclic import. Yuck.
|
|
92
|
+
from robot.running.arguments import PythonArgumentParser
|
|
93
|
+
spec = PythonArgumentParser('variable file').parse(get_variables)
|
|
94
|
+
return spec.resolve(args)
|
|
123
95
|
|
|
124
96
|
def _get_static(self, var_file):
|
|
125
97
|
names = [attr for attr in dir(var_file) if not attr.startswith('_')]
|
|
@@ -132,40 +104,35 @@ class PythonImporter:
|
|
|
132
104
|
|
|
133
105
|
def _decorate_and_validate(self, variables):
|
|
134
106
|
for name, value in variables:
|
|
135
|
-
name
|
|
136
|
-
|
|
107
|
+
if name.startswith('LIST__'):
|
|
108
|
+
if not is_list_like(value):
|
|
109
|
+
raise DataError(f"Invalid variable '{name}': Expected a "
|
|
110
|
+
f"list-like value, got {type_name(value)}.")
|
|
111
|
+
name = name[6:]
|
|
112
|
+
value = list(value)
|
|
113
|
+
elif name.startswith('DICT__'):
|
|
114
|
+
if not is_dict_like(value):
|
|
115
|
+
raise DataError(f"Invalid variable '{name}': Expected a "
|
|
116
|
+
f"dictionary-like value, got {type_name(value)}.")
|
|
117
|
+
name = name[6:]
|
|
118
|
+
value = DotDict(value)
|
|
137
119
|
yield name, value
|
|
138
120
|
|
|
139
|
-
def _decorate(self, name):
|
|
140
|
-
if name.startswith('LIST__'):
|
|
141
|
-
return '@{%s}' % name[6:]
|
|
142
|
-
if name.startswith('DICT__'):
|
|
143
|
-
return '&{%s}' % name[6:]
|
|
144
|
-
return '${%s}' % name
|
|
145
|
-
|
|
146
|
-
def _validate(self, name, value):
|
|
147
|
-
if name[0] == '@' and not is_list_like(value):
|
|
148
|
-
raise DataError("Invalid variable '%s': Expected list-like value, "
|
|
149
|
-
"got %s." % (name, type_name(value)))
|
|
150
|
-
if name[0] == '&' and not is_dict_like(value):
|
|
151
|
-
raise DataError("Invalid variable '%s': Expected dict-like value, "
|
|
152
|
-
"got %s." % (name, type_name(value)))
|
|
153
|
-
|
|
154
121
|
|
|
155
122
|
class JsonImporter:
|
|
123
|
+
|
|
156
124
|
def import_variables(self, path, args=None):
|
|
157
125
|
if args:
|
|
158
126
|
raise DataError('JSON variable files do not accept arguments.')
|
|
159
127
|
variables = self._import(path)
|
|
160
|
-
return [(
|
|
161
|
-
for name, value in variables]
|
|
128
|
+
return [(name, self._dot_dict(value)) for name, value in variables]
|
|
162
129
|
|
|
163
130
|
def _import(self, path):
|
|
164
131
|
with io.open(path, encoding='UTF-8') as stream:
|
|
165
132
|
variables = json.load(stream)
|
|
166
133
|
if not is_dict_like(variables):
|
|
167
|
-
raise DataError('JSON variable file must be a mapping,
|
|
168
|
-
|
|
134
|
+
raise DataError(f'JSON variable file must be a mapping, '
|
|
135
|
+
f'got {type_name(variables)}.')
|
|
169
136
|
return variables.items()
|
|
170
137
|
|
|
171
138
|
def _dot_dict(self, value):
|
|
@@ -174,3 +141,36 @@ class JsonImporter:
|
|
|
174
141
|
if is_list_like(value):
|
|
175
142
|
return [self._dot_dict(v) for v in value]
|
|
176
143
|
return value
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class YamlImporter:
|
|
147
|
+
|
|
148
|
+
def import_variables(self, path, args=None):
|
|
149
|
+
if args:
|
|
150
|
+
raise DataError('YAML variable files do not accept arguments.')
|
|
151
|
+
variables = self._import(path)
|
|
152
|
+
return [(name, self._dot_dict(value)) for name, value in variables]
|
|
153
|
+
|
|
154
|
+
def _import(self, path):
|
|
155
|
+
with io.open(path, encoding='UTF-8') as stream:
|
|
156
|
+
variables = self._load_yaml(stream)
|
|
157
|
+
if not is_dict_like(variables):
|
|
158
|
+
raise DataError(f'YAML variable file must be a mapping, '
|
|
159
|
+
f'got {type_name(variables)}.')
|
|
160
|
+
return variables.items()
|
|
161
|
+
|
|
162
|
+
def _load_yaml(self, stream):
|
|
163
|
+
if not yaml:
|
|
164
|
+
raise DataError('Using YAML variable files requires PyYAML module '
|
|
165
|
+
'to be installed. Typically you can install it '
|
|
166
|
+
'by running `pip install pyyaml`.')
|
|
167
|
+
if yaml.__version__.split('.')[0] == '3':
|
|
168
|
+
return yaml.load(stream)
|
|
169
|
+
return yaml.full_load(stream)
|
|
170
|
+
|
|
171
|
+
def _dot_dict(self, value):
|
|
172
|
+
if is_dict_like(value):
|
|
173
|
+
return DotDict((k, self._dot_dict(v)) for k, v in value.items())
|
|
174
|
+
if is_list_like(value):
|
|
175
|
+
return [self._dot_dict(v) for v in value]
|
|
176
|
+
return value
|
|
@@ -42,33 +42,32 @@ class VariableReplacer:
|
|
|
42
42
|
items = list(items or [])
|
|
43
43
|
if replace_until is not None:
|
|
44
44
|
return self._replace_list_until(items, replace_until, ignore_errors)
|
|
45
|
-
return
|
|
45
|
+
return self._replace_list(items, ignore_errors)
|
|
46
46
|
|
|
47
|
-
def _replace_list_until(self, items,
|
|
47
|
+
def _replace_list_until(self, items, limit, ignore_errors):
|
|
48
48
|
# @{list} variables can contain more or less arguments than needed.
|
|
49
49
|
# Therefore, we need to go through items one by one, and escape
|
|
50
50
|
# possible extra items we got.
|
|
51
51
|
replaced = []
|
|
52
|
-
while len(replaced) <
|
|
52
|
+
while len(replaced) < limit and items:
|
|
53
53
|
replaced.extend(self._replace_list([items.pop(0)], ignore_errors))
|
|
54
|
-
if len(replaced) >
|
|
55
|
-
replaced[
|
|
56
|
-
for item in replaced[replace_until:]]
|
|
54
|
+
if len(replaced) > limit:
|
|
55
|
+
replaced[limit:] = [escape(item) for item in replaced[limit:]]
|
|
57
56
|
return replaced + items
|
|
58
57
|
|
|
59
58
|
def _replace_list(self, items, ignore_errors):
|
|
59
|
+
result = []
|
|
60
60
|
for item in items:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return [value]
|
|
61
|
+
match = search_variable(item, ignore_errors=ignore_errors)
|
|
62
|
+
if not match:
|
|
63
|
+
result.append(unescape(item))
|
|
64
|
+
else:
|
|
65
|
+
value = self._replace_scalar(match, ignore_errors)
|
|
66
|
+
if match.is_list_variable() and is_list_like(value):
|
|
67
|
+
result.extend(value)
|
|
68
|
+
else:
|
|
69
|
+
result.append(value)
|
|
70
|
+
return result
|
|
72
71
|
|
|
73
72
|
def replace_scalar(self, item, ignore_errors=False):
|
|
74
73
|
"""Replaces variables from a scalar item.
|
|
@@ -77,20 +76,18 @@ class VariableReplacer:
|
|
|
77
76
|
its value is returned. Otherwise, possible variables are replaced with
|
|
78
77
|
'replace_string'. Result may be any object.
|
|
79
78
|
"""
|
|
80
|
-
|
|
79
|
+
if isinstance(item, VariableMatch):
|
|
80
|
+
match = item
|
|
81
|
+
else:
|
|
82
|
+
match = search_variable(item, ignore_errors=ignore_errors)
|
|
81
83
|
if not match:
|
|
82
84
|
return unescape(match.string)
|
|
83
85
|
return self._replace_scalar(match, ignore_errors)
|
|
84
86
|
|
|
85
|
-
def _search_variable(self, item, ignore_errors):
|
|
86
|
-
if isinstance(item, VariableMatch):
|
|
87
|
-
return item
|
|
88
|
-
return search_variable(item, ignore_errors=ignore_errors)
|
|
89
|
-
|
|
90
87
|
def _replace_scalar(self, match, ignore_errors=False):
|
|
91
|
-
if
|
|
92
|
-
return self.
|
|
93
|
-
return self.
|
|
88
|
+
if match.is_variable():
|
|
89
|
+
return self._get_variable_value(match, ignore_errors)
|
|
90
|
+
return self._replace_string(match, unescape, ignore_errors)
|
|
94
91
|
|
|
95
92
|
def replace_string(self, item, custom_unescaper=None, ignore_errors=False):
|
|
96
93
|
"""Replaces variables from a string. Result is always a string.
|
|
@@ -98,7 +95,10 @@ class VariableReplacer:
|
|
|
98
95
|
Input can also be an already found VariableMatch.
|
|
99
96
|
"""
|
|
100
97
|
unescaper = custom_unescaper or unescape
|
|
101
|
-
|
|
98
|
+
if isinstance(item, VariableMatch):
|
|
99
|
+
match = item
|
|
100
|
+
else:
|
|
101
|
+
match = search_variable(item, ignore_errors=ignore_errors)
|
|
102
102
|
if not match:
|
|
103
103
|
return safe_str(unescaper(match.string))
|
|
104
104
|
return self._replace_string(match, unescaper, ignore_errors)
|
|
@@ -106,10 +106,8 @@ class VariableReplacer:
|
|
|
106
106
|
def _replace_string(self, match, unescaper, ignore_errors):
|
|
107
107
|
parts = []
|
|
108
108
|
while match:
|
|
109
|
-
parts.
|
|
110
|
-
|
|
111
|
-
safe_str(self._get_variable_value(match, ignore_errors))
|
|
112
|
-
])
|
|
109
|
+
parts.append(unescaper(match.before))
|
|
110
|
+
parts.append(safe_str(self._get_variable_value(match, ignore_errors)))
|
|
113
111
|
match = search_variable(match.after, ignore_errors=ignore_errors)
|
|
114
112
|
parts.append(unescaper(match.string))
|
|
115
113
|
return ''.join(parts)
|
|
@@ -126,17 +124,16 @@ class VariableReplacer:
|
|
|
126
124
|
if match.items:
|
|
127
125
|
value = self._get_variable_item(match, value)
|
|
128
126
|
try:
|
|
129
|
-
|
|
127
|
+
return self._validate_value(match, value)
|
|
130
128
|
except VariableError:
|
|
131
129
|
raise
|
|
132
130
|
except Exception:
|
|
133
131
|
error = get_error_message()
|
|
134
132
|
raise VariableError(f"Resolving variable '{match}' failed: {error}")
|
|
135
133
|
except DataError:
|
|
136
|
-
if
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
return value
|
|
134
|
+
if ignore_errors:
|
|
135
|
+
return unescape(match.match)
|
|
136
|
+
raise
|
|
140
137
|
|
|
141
138
|
def _get_variable_item(self, match, value):
|
|
142
139
|
name = match.name
|
|
@@ -113,9 +113,9 @@ class VariableScopes:
|
|
|
113
113
|
else:
|
|
114
114
|
scope.set_from_file(variables, overwrite=overwrite)
|
|
115
115
|
|
|
116
|
-
def
|
|
116
|
+
def set_from_variable_section(self, variables, overwrite=False):
|
|
117
117
|
for scope in self._scopes_until_suite:
|
|
118
|
-
scope.
|
|
118
|
+
scope.set_from_variable_section(variables, overwrite)
|
|
119
119
|
|
|
120
120
|
def resolve_delayed(self):
|
|
121
121
|
for scope in self._scopes_until_suite:
|
|
@@ -140,8 +140,7 @@ class VariableScopes:
|
|
|
140
140
|
return
|
|
141
141
|
for scope in self._scopes_until_suite:
|
|
142
142
|
name, value = self._set_global_suite_or_test(scope, name, value)
|
|
143
|
-
|
|
144
|
-
self._variables_set.set_suite(name, value)
|
|
143
|
+
self._variables_set.set_suite(name, value, children)
|
|
145
144
|
|
|
146
145
|
def set_test(self, name, value):
|
|
147
146
|
if self._test is None:
|
|
@@ -154,7 +153,7 @@ class VariableScopes:
|
|
|
154
153
|
self.current[name] = value
|
|
155
154
|
self._variables_set.set_keyword(name, value)
|
|
156
155
|
|
|
157
|
-
def
|
|
156
|
+
def set_local(self, name, value):
|
|
158
157
|
self.current[name] = value
|
|
159
158
|
|
|
160
159
|
def as_dict(self, decoration=True):
|
|
@@ -203,11 +202,11 @@ class GlobalVariables(Variables):
|
|
|
203
202
|
('${False}', False),
|
|
204
203
|
('${None}', None),
|
|
205
204
|
('${null}', None),
|
|
206
|
-
('${OUTPUT_DIR}', settings.output_directory),
|
|
207
|
-
('${OUTPUT_FILE}', settings.output or 'NONE'),
|
|
208
|
-
('${REPORT_FILE}', settings.report or 'NONE'),
|
|
209
|
-
('${LOG_FILE}', settings.log or 'NONE'),
|
|
210
|
-
('${DEBUG_FILE}', settings.debug_file or 'NONE'),
|
|
205
|
+
('${OUTPUT_DIR}', str(settings.output_directory)),
|
|
206
|
+
('${OUTPUT_FILE}', str(settings.output or 'NONE')),
|
|
207
|
+
('${REPORT_FILE}', str(settings.report or 'NONE')),
|
|
208
|
+
('${LOG_FILE}', str(settings.log or 'NONE')),
|
|
209
|
+
('${DEBUG_FILE}', str(settings.debug_file or 'NONE')),
|
|
211
210
|
('${LOG_LEVEL}', settings.log_level),
|
|
212
211
|
('${PREV_TEST_NAME}', ''),
|
|
213
212
|
('${PREV_TEST_STATUS}', ''),
|
|
@@ -252,8 +251,14 @@ class SetVariables:
|
|
|
252
251
|
if name in scope:
|
|
253
252
|
scope.pop(name)
|
|
254
253
|
|
|
255
|
-
def set_suite(self, name, value):
|
|
256
|
-
self.
|
|
254
|
+
def set_suite(self, name, value, children=False):
|
|
255
|
+
for scope in reversed(self._scopes):
|
|
256
|
+
if children:
|
|
257
|
+
scope[name] = value
|
|
258
|
+
elif name in scope:
|
|
259
|
+
scope.pop(name)
|
|
260
|
+
if scope is self._suite:
|
|
261
|
+
break
|
|
257
262
|
|
|
258
263
|
def set_test(self, name, value):
|
|
259
264
|
for scope in reversed(self._scopes):
|