robotframework 6.1.1__zip → 7.0a1__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/src/robotframework.egg-info → robotframework-7.0a1}/PKG-INFO +3 -6
- {robotframework-6.1.1 → robotframework-7.0a1}/setup.py +2 -5
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/api/interfaces.py +35 -48
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/api/parsing.py +4 -2
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/conf/gatherfailed.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/conf/languages.py +0 -9
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/conf/settings.py +8 -5
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/log.css +4 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/log.html +9 -1
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/model.js +2 -4
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/testdata.js +10 -3
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/template.py +3 -3
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/builder.py +0 -8
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/datatypes.py +9 -10
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/htmlutils.py +4 -7
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/jsonbuilder.py +14 -10
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/model.py +13 -25
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/robotbuilder.py +13 -3
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/xmlbuilder.py +8 -8
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/xmlwriter.py +12 -38
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/BuiltIn.py +215 -189
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Collections.py +2 -9
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/DateTime.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/OperatingSystem.py +4 -3
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Process.py +26 -27
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Remote.py +40 -36
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/String.py +4 -4
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/XML.py +7 -8
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/__init__.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/__init__.py +4 -4
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/body.py +14 -6
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/configurer.py +15 -11
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/control.py +151 -81
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/filter.py +31 -25
- robotframework-7.0a1/src/robot/model/keyword.py +70 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/message.py +19 -10
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/namepatterns.py +3 -25
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/stats.py +9 -15
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/tags.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/testcase.py +12 -21
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/testsuite.py +16 -22
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/visitor.py +35 -8
- robotframework-7.0a1/src/robot/output/console/dotted.py +90 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/console/quiet.py +3 -2
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/console/verbose.py +60 -60
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/debugfile.py +36 -23
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/filelogger.py +16 -13
- robotframework-7.0a1/src/robot/output/listeners.py +586 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/logger.py +164 -77
- robotframework-7.0a1/src/robot/output/loggerapi.py +152 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/loggerhelper.py +23 -56
- robotframework-7.0a1/src/robot/output/output.py +158 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/stdoutlogsplitter.py +8 -5
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/xmllogger.py +163 -109
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/blocklexers.py +17 -13
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/context.py +12 -2
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/lexer.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/settings.py +6 -3
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/statementlexers.py +39 -10
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/tokens.py +27 -29
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/model/blocks.py +19 -6
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/model/statements.py +184 -84
- robotframework-7.0a1/src/robot/parsing/model/visitor.py +102 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/expandkeywordmatcher.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/jsbuildingcontext.py +8 -6
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/jsmodelbuilders.py +88 -61
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/stringcache.py +4 -3
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/xunitwriter.py +15 -21
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/__init__.py +3 -2
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/configurer.py +12 -9
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/flattenkeywordmatcher.py +8 -8
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/keywordremover.py +71 -54
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/merger.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/model.py +400 -316
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/modeldeprecation.py +9 -3
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/resultbuilder.py +21 -23
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/xmlelementhandlers.py +76 -40
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/__init__.py +1 -1
- robotframework-7.0a1/src/robot/running/arguments/argumentconverter.py +101 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/argumentmapper.py +16 -14
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/argumentresolver.py +41 -33
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/argumentspec.py +24 -90
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/argumentvalidator.py +34 -27
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/customconverters.py +14 -11
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/embedded.py +23 -26
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/typeconverters.py +175 -213
- robotframework-7.0a1/src/robot/running/arguments/typeinfo.py +367 -0
- robotframework-7.0a1/src/robot/running/arguments/typevalidator.py +62 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/bodyrunner.py +83 -68
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/builder/parsers.py +8 -10
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/builder/settings.py +9 -17
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/builder/transformers.py +166 -308
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/context.py +80 -25
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/handlers.py +11 -16
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/handlerstore.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/librarykeywordrunner.py +9 -17
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/model.py +109 -32
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/namespace.py +18 -19
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/statusreporter.py +13 -12
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/suiterunner.py +15 -17
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/testlibraries.py +33 -40
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/usererrorhandler.py +8 -8
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/userkeyword.py +13 -8
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/userkeywordrunner.py +18 -21
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/testdoc.py +18 -13
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/__init__.py +50 -35
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/connectioncache.py +64 -59
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/encodingsniffer.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/escaping.py +11 -9
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/markupwriters.py +20 -13
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/normalizing.py +9 -24
- robotframework-7.0a1/src/robot/utils/notset.py +33 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/platform.py +15 -5
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/robotpath.py +1 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/robottime.py +120 -88
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/robottypes.py +16 -31
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/setter.py +0 -5
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/text.py +7 -4
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/unic.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/__init__.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/assigner.py +17 -19
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/evaluation.py +20 -17
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/filesetter.py +80 -80
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/replacer.py +33 -36
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/scopes.py +3 -3
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/search.py +66 -41
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/store.py +14 -16
- robotframework-7.0a1/src/robot/variables/tablesetter.py +164 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/variables.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/version.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0a1/src/robotframework.egg-info}/PKG-INFO +3 -6
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robotframework.egg-info/SOURCES.txt +3 -4
- {robotframework-6.1.1 → robotframework-7.0a1}/tasks.py +6 -6
- 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/parsing/model/visitor.py +0 -67
- robotframework-6.1.1/src/robot/running/arguments/argumentconverter.py +0 -79
- robotframework-6.1.1/src/robot/running/arguments/typevalidator.py +0 -56
- robotframework-6.1.1/src/robot/running/modelcombiner.py +0 -32
- robotframework-6.1.1/src/robot/variables/tablesetter.py +0 -156
- {robotframework-6.1.1 → robotframework-7.0a1}/AUTHORS.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/BUILD.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/CONTRIBUTING.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/COPYRIGHT.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/INSTALL.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/LICENSE.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/MANIFEST.in +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/README.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/setup.cfg +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/__main__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/api/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/api/deco.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/api/exceptions.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/api/logger.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/conf/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/errors.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/common/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/common/js_disabled.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/common/storage.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/htmlfilewriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/jsonwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/lib/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/lib/jquery.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/libdoc/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/libdoc/doc_formatting.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/libdoc/libdoc.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/libdoc/libdoc.html +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/libdoc/print.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/libdoc/pygments.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/common.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/doc_formatting.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/fileloading.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/log.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/print.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/report.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/report.html +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/util.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/rebot/view.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/testdoc/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/testdoc/testdoc.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/htmldata/testdoc/testdoc.html +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdoc.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/consoleviewer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/htmlwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/jsonwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/output.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/standardtypes.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libdocpkg/writer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Dialogs.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Easter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Screenshot.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/Telnet.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/libraries/dialogs_py.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/fixture.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/itemlist.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/metadata.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/modelobject.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/modifier.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/statistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/suitestatistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/tagsetter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/tagstatistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/model/totalstatistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/console/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/console/highlighting.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/librarylogger.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/output/pyloggingconf.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/lexer/tokenizer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/model/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/parser/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/parser/blockparsers.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/parser/fileparser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/parser/parser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/parsing/suitestructure.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/pythonpathsetter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/rebot.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/jsexecutionresult.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/jswriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/logreportwriters.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/outputwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/reporting/resultwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/executionerrors.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/executionresult.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/messagefilter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/suiteteardownfailed.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/result/visitor.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/run.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/arguments/argumentparser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/builder/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/builder/builders.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/dynamicmethods.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/importer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/libraryscopes.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/outputcapture.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/randomizer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/runkwregister.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/signalhandler.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/status.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/timeouts/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/timeouts/posix.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/running/timeouts/windows.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/application.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/argumentparser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/asserts.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/charwidth.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/compress.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/dotdict.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/encoding.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/error.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/etreewrapper.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/filereader.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/frange.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/htmlformatters.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/importer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/markuputils.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/match.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/misc.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/recommendations.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/restreader.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/robotenv.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/robotinspect.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/robotio.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/sortable.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/utils/typehints.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/finders.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/notfound.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robot/variables/resolvable.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robotframework.egg-info/dependency_links.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robotframework.egg-info/entry_points.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0a1}/src/robotframework.egg-info/top_level.txt +0 -0
|
@@ -15,14 +15,16 @@
|
|
|
15
15
|
|
|
16
16
|
import ast
|
|
17
17
|
import re
|
|
18
|
+
import warnings
|
|
18
19
|
from abc import ABC, abstractmethod
|
|
19
20
|
from collections.abc import Iterator, Sequence
|
|
20
|
-
from typing import cast, ClassVar, overload, TYPE_CHECKING, Type, TypeVar
|
|
21
|
+
from typing import cast, ClassVar, Literal, overload, TYPE_CHECKING, Type, TypeVar
|
|
21
22
|
|
|
22
23
|
from robot.conf import Language
|
|
23
24
|
from robot.running.arguments import UserKeywordArgumentParser
|
|
24
25
|
from robot.utils import normalize_whitespace, seq2str, split_from_equals, test_or_task
|
|
25
|
-
from robot.variables import is_scalar_assign, is_dict_variable,
|
|
26
|
+
from robot.variables import (contains_variable, is_scalar_assign, is_dict_variable,
|
|
27
|
+
search_variable)
|
|
26
28
|
|
|
27
29
|
from ..lexer import Token
|
|
28
30
|
|
|
@@ -45,10 +47,13 @@ class Node(ast.AST, ABC):
|
|
|
45
47
|
|
|
46
48
|
|
|
47
49
|
class Statement(Node, ABC):
|
|
48
|
-
|
|
50
|
+
_attributes = ('type', 'tokens') + Node._attributes
|
|
49
51
|
type: str
|
|
50
52
|
handles_types: 'ClassVar[tuple[str, ...]]' = ()
|
|
51
53
|
statement_handlers: 'ClassVar[dict[str, Type[Statement]]]' = {}
|
|
54
|
+
# Accepted configuration options. If the value is a tuple, it lists accepted
|
|
55
|
+
# values. If the used value contains a variable, it cannot be validated.
|
|
56
|
+
options: 'dict[str, tuple|None]' = {}
|
|
52
57
|
|
|
53
58
|
def __init__(self, tokens: 'Sequence[Token]', errors: 'Sequence[str]' = ()):
|
|
54
59
|
self.tokens = tuple(tokens)
|
|
@@ -164,15 +169,10 @@ class Statement(Node, ABC):
|
|
|
164
169
|
|
|
165
170
|
New in Robot Framework 6.1.
|
|
166
171
|
"""
|
|
167
|
-
|
|
168
|
-
return ', '.join(options[name]) if name in options else default
|
|
172
|
+
return self._get_options().get(name, default)
|
|
169
173
|
|
|
170
|
-
def _get_options(self) -> 'dict[str,
|
|
171
|
-
|
|
172
|
-
for option in self.get_values(Token.OPTION):
|
|
173
|
-
name, value = option.split('=', 1)
|
|
174
|
-
options.setdefault(name, []).append(value)
|
|
175
|
-
return options
|
|
174
|
+
def _get_options(self) -> 'dict[str, str]':
|
|
175
|
+
return dict(opt.split('=', 1) for opt in self.get_values(Token.OPTION))
|
|
176
176
|
|
|
177
177
|
@property
|
|
178
178
|
def lines(self) -> 'Iterator[list[Token]]':
|
|
@@ -189,10 +189,13 @@ class Statement(Node, ABC):
|
|
|
189
189
|
pass
|
|
190
190
|
|
|
191
191
|
def _validate_options(self):
|
|
192
|
-
for name,
|
|
193
|
-
if
|
|
194
|
-
self.
|
|
195
|
-
|
|
192
|
+
for name, value in self._get_options().items():
|
|
193
|
+
if self.options[name] is not None:
|
|
194
|
+
expected = self.options[name]
|
|
195
|
+
if value.upper() not in expected and not contains_variable(value):
|
|
196
|
+
self.errors += (f"{self.type} option '{name}' does not accept "
|
|
197
|
+
f"value '{value}'. Valid values are "
|
|
198
|
+
f"{seq2str(expected)}.",)
|
|
196
199
|
|
|
197
200
|
def __iter__(self) -> 'Iterator[Token]':
|
|
198
201
|
return iter(self.tokens)
|
|
@@ -344,7 +347,7 @@ class LibraryImport(Statement):
|
|
|
344
347
|
Token(Token.ARGUMENT, arg)])
|
|
345
348
|
if alias is not None:
|
|
346
349
|
tokens.extend([Token(Token.SEPARATOR, separator),
|
|
347
|
-
Token(Token.
|
|
350
|
+
Token(Token.AS),
|
|
348
351
|
Token(Token.SEPARATOR, separator),
|
|
349
352
|
Token(Token.NAME, alias)])
|
|
350
353
|
tokens.append(Token(Token.EOL, eol))
|
|
@@ -360,7 +363,7 @@ class LibraryImport(Statement):
|
|
|
360
363
|
|
|
361
364
|
@property
|
|
362
365
|
def alias(self) -> 'str|None':
|
|
363
|
-
separator = self.get_token(Token.
|
|
366
|
+
separator = self.get_token(Token.AS)
|
|
364
367
|
return self.get_tokens(Token.NAME)[-1].value if separator else None
|
|
365
368
|
|
|
366
369
|
|
|
@@ -467,13 +470,13 @@ class Metadata(DocumentationOrMetadata):
|
|
|
467
470
|
|
|
468
471
|
|
|
469
472
|
@Statement.register
|
|
470
|
-
class
|
|
471
|
-
type = Token.
|
|
473
|
+
class TestTags(MultiValue):
|
|
474
|
+
type = Token.TEST_TAGS
|
|
472
475
|
|
|
473
476
|
@classmethod
|
|
474
477
|
def from_params(cls, values: 'Sequence[str]', separator: str = FOUR_SPACES,
|
|
475
|
-
eol: str = EOL) -> '
|
|
476
|
-
tokens = [Token(Token.
|
|
478
|
+
eol: str = EOL) -> 'TestTags':
|
|
479
|
+
tokens = [Token(Token.TEST_TAGS, 'Test Tags')]
|
|
477
480
|
for tag in values:
|
|
478
481
|
tokens.extend([Token(Token.SEPARATOR, separator),
|
|
479
482
|
Token(Token.ARGUMENT, tag)])
|
|
@@ -627,15 +630,24 @@ class TestTimeout(SingleValue):
|
|
|
627
630
|
@Statement.register
|
|
628
631
|
class Variable(Statement):
|
|
629
632
|
type = Token.VARIABLE
|
|
633
|
+
options = {
|
|
634
|
+
'separator': None
|
|
635
|
+
}
|
|
630
636
|
|
|
631
637
|
@classmethod
|
|
632
|
-
def from_params(cls, name: str,
|
|
633
|
-
|
|
638
|
+
def from_params(cls, name: str,
|
|
639
|
+
value: 'str|Sequence[str]',
|
|
640
|
+
value_separator: 'str|None' = None,
|
|
641
|
+
separator: str = FOUR_SPACES,
|
|
642
|
+
eol: str = EOL) -> 'Variable':
|
|
634
643
|
values = [value] if isinstance(value, str) else value
|
|
635
644
|
tokens = [Token(Token.VARIABLE, name)]
|
|
636
645
|
for value in values:
|
|
637
646
|
tokens.extend([Token(Token.SEPARATOR, separator),
|
|
638
647
|
Token(Token.ARGUMENT, value)])
|
|
648
|
+
if value_separator is not None:
|
|
649
|
+
tokens.extend([Token(Token.SEPARATOR, separator),
|
|
650
|
+
Token(Token.OPTION, f'separator={value_separator}')])
|
|
639
651
|
tokens.append(Token(Token.EOL, eol))
|
|
640
652
|
return cls(tokens)
|
|
641
653
|
|
|
@@ -650,26 +662,13 @@ class Variable(Statement):
|
|
|
650
662
|
def value(self) -> 'tuple[str, ...]':
|
|
651
663
|
return self.get_values(Token.ARGUMENT)
|
|
652
664
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
if not match.is_assign(allow_assign_mark=True, allow_nested=True):
|
|
657
|
-
self.errors += (f"Invalid variable name '{name}'.",)
|
|
658
|
-
if match.is_dict_assign(allow_assign_mark=True):
|
|
659
|
-
self._validate_dict_items()
|
|
660
|
-
|
|
661
|
-
def _validate_dict_items(self):
|
|
662
|
-
for item in self.get_values(Token.ARGUMENT):
|
|
663
|
-
if not self._is_valid_dict_item(item):
|
|
664
|
-
self.errors += (
|
|
665
|
-
f"Invalid dictionary variable item '{item}'. "
|
|
666
|
-
f"Items must use 'name=value' syntax or be dictionary "
|
|
667
|
-
f"variables themselves.",
|
|
668
|
-
)
|
|
665
|
+
@property
|
|
666
|
+
def separator(self) -> 'str|None':
|
|
667
|
+
return self.get_option('separator')
|
|
669
668
|
|
|
670
|
-
def
|
|
671
|
-
|
|
672
|
-
|
|
669
|
+
def validate(self, ctx: 'ValidationContext'):
|
|
670
|
+
VariableValidator().validate(self)
|
|
671
|
+
self._validate_options()
|
|
673
672
|
|
|
674
673
|
|
|
675
674
|
@Statement.register
|
|
@@ -819,22 +818,18 @@ class Arguments(MultiValue):
|
|
|
819
818
|
self.errors = tuple(errors)
|
|
820
819
|
|
|
821
820
|
|
|
822
|
-
# TODO: Change Return to mean ReturnStatement in RF
|
|
823
|
-
# - Rename
|
|
824
|
-
# - Rename current ReturnStatement to Return
|
|
821
|
+
# TODO: Change Return to mean ReturnStatement in RF 8.0.
|
|
822
|
+
# - Rename ReturnStatement to Return
|
|
825
823
|
# - Add backwards compatible ReturnStatement alias
|
|
824
|
+
# - Consider keeping ReturnSetting for backwards compatibility. It could just be `None`.
|
|
826
825
|
# - Change Token.RETURN to mean Token.RETURN_STATEMENT
|
|
827
826
|
# - Update also ModelVisitor
|
|
828
827
|
@Statement.register
|
|
829
828
|
class Return(MultiValue):
|
|
830
829
|
"""Represents the deprecated ``[Return]`` setting.
|
|
831
830
|
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
Robot Framework 6.1) should be used instead. :class:`ReturnStatement` will
|
|
835
|
-
be renamed to ``Return`` in Robot Framework 7.0.
|
|
836
|
-
|
|
837
|
-
Eventually ``[Return]`` and ``ReturnSetting`` will be removed altogether.
|
|
831
|
+
The ``[Return]`` setting is deprecated and will be removed in Robot Framework 8.0.
|
|
832
|
+
At the same time the :class:`ReturnStatement` class will be renamed to ``Return``.
|
|
838
833
|
"""
|
|
839
834
|
type = Token.RETURN
|
|
840
835
|
|
|
@@ -908,15 +903,23 @@ class TemplateArguments(Statement):
|
|
|
908
903
|
@Statement.register
|
|
909
904
|
class ForHeader(Statement):
|
|
910
905
|
type = Token.FOR
|
|
906
|
+
options = {
|
|
907
|
+
'start': None,
|
|
908
|
+
'mode': ('STRICT', 'SHORTEST', 'LONGEST'),
|
|
909
|
+
'fill': None
|
|
910
|
+
}
|
|
911
911
|
|
|
912
912
|
@classmethod
|
|
913
|
-
def from_params(cls,
|
|
914
|
-
|
|
915
|
-
|
|
913
|
+
def from_params(cls, assign: 'Sequence[str]',
|
|
914
|
+
values: 'Sequence[str]',
|
|
915
|
+
flavor: Literal['IN', 'IN RANGE', 'IN ENUMERATE', 'IN ZIP'] = 'IN',
|
|
916
|
+
indent: str = FOUR_SPACES,
|
|
917
|
+
separator: str = FOUR_SPACES,
|
|
918
|
+
eol: str = EOL) -> 'ForHeader':
|
|
916
919
|
tokens = [Token(Token.SEPARATOR, indent),
|
|
917
920
|
Token(Token.FOR),
|
|
918
921
|
Token(Token.SEPARATOR, separator)]
|
|
919
|
-
for variable in
|
|
922
|
+
for variable in assign:
|
|
920
923
|
tokens.extend([Token(Token.VARIABLE, variable),
|
|
921
924
|
Token(Token.SEPARATOR, separator)])
|
|
922
925
|
tokens.append(Token(Token.FOR_SEPARATOR, flavor))
|
|
@@ -927,9 +930,15 @@ class ForHeader(Statement):
|
|
|
927
930
|
return cls(tokens)
|
|
928
931
|
|
|
929
932
|
@property
|
|
930
|
-
def
|
|
933
|
+
def assign(self) -> 'tuple[str, ...]':
|
|
931
934
|
return self.get_values(Token.VARIABLE)
|
|
932
935
|
|
|
936
|
+
@property
|
|
937
|
+
def variables(self) -> 'tuple[str, ...]': # TODO: Remove in RF 8.0.
|
|
938
|
+
warnings.warn("'ForHeader.variables' is deprecated and will be removed in "
|
|
939
|
+
"Robot Framework 8.0. Use 'ForHeader.assign' instead.")
|
|
940
|
+
return self.assign
|
|
941
|
+
|
|
933
942
|
@property
|
|
934
943
|
def values(self) -> 'tuple[str, ...]':
|
|
935
944
|
return self.get_values(Token.ARGUMENT)
|
|
@@ -952,17 +961,17 @@ class ForHeader(Statement):
|
|
|
952
961
|
return self.get_option('fill') if self.flavor == 'IN ZIP' else None
|
|
953
962
|
|
|
954
963
|
def validate(self, ctx: 'ValidationContext'):
|
|
955
|
-
self.
|
|
956
|
-
if not self.variables:
|
|
964
|
+
if not self.assign:
|
|
957
965
|
self._add_error('no loop variables')
|
|
958
966
|
if not self.flavor:
|
|
959
967
|
self._add_error("no 'IN' or other valid separator")
|
|
960
968
|
else:
|
|
961
|
-
for var in self.
|
|
969
|
+
for var in self.assign:
|
|
962
970
|
if not is_scalar_assign(var):
|
|
963
971
|
self._add_error(f"invalid loop variable '{var}'")
|
|
964
972
|
if not self.values:
|
|
965
973
|
self._add_error('no loop values')
|
|
974
|
+
self._validate_options()
|
|
966
975
|
|
|
967
976
|
def _add_error(self, error: str):
|
|
968
977
|
self.errors += (f'FOR loop has {error}.',)
|
|
@@ -1084,10 +1093,13 @@ class TryHeader(NoArgumentHeader):
|
|
|
1084
1093
|
@Statement.register
|
|
1085
1094
|
class ExceptHeader(Statement):
|
|
1086
1095
|
type = Token.EXCEPT
|
|
1096
|
+
options = {
|
|
1097
|
+
'type': ('GLOB', 'REGEXP', 'START', 'LITERAL')
|
|
1098
|
+
}
|
|
1087
1099
|
|
|
1088
1100
|
@classmethod
|
|
1089
1101
|
def from_params(cls, patterns: 'Sequence[str]' = (), type: 'str|None' = None,
|
|
1090
|
-
|
|
1102
|
+
assign: 'str|None' = None, indent: str = FOUR_SPACES,
|
|
1091
1103
|
separator: str = FOUR_SPACES, eol: str = EOL) -> 'ExceptHeader':
|
|
1092
1104
|
tokens = [Token(Token.SEPARATOR, indent),
|
|
1093
1105
|
Token(Token.EXCEPT)]
|
|
@@ -1097,11 +1109,11 @@ class ExceptHeader(Statement):
|
|
|
1097
1109
|
if type:
|
|
1098
1110
|
tokens.extend([Token(Token.SEPARATOR, separator),
|
|
1099
1111
|
Token(Token.OPTION, f'type={type}')])
|
|
1100
|
-
if
|
|
1112
|
+
if assign:
|
|
1101
1113
|
tokens.extend([Token(Token.SEPARATOR, separator),
|
|
1102
1114
|
Token(Token.AS),
|
|
1103
1115
|
Token(Token.SEPARATOR, separator),
|
|
1104
|
-
Token(Token.VARIABLE,
|
|
1116
|
+
Token(Token.VARIABLE, assign)])
|
|
1105
1117
|
tokens.append(Token(Token.EOL, eol))
|
|
1106
1118
|
return cls(tokens)
|
|
1107
1119
|
|
|
@@ -1114,20 +1126,26 @@ class ExceptHeader(Statement):
|
|
|
1114
1126
|
return self.get_option('type')
|
|
1115
1127
|
|
|
1116
1128
|
@property
|
|
1117
|
-
def
|
|
1129
|
+
def assign(self) -> 'str|None':
|
|
1118
1130
|
return self.get_value(Token.VARIABLE)
|
|
1119
1131
|
|
|
1132
|
+
@property
|
|
1133
|
+
def variable(self) -> 'str|None': # TODO: Remove in RF 8.0.
|
|
1134
|
+
warnings.warn("'ExceptHeader.variable' is deprecated and will be removed in "
|
|
1135
|
+
"Robot Framework 8.0. Use 'ExceptHeader.assigns' instead.")
|
|
1136
|
+
return self.assign
|
|
1137
|
+
|
|
1120
1138
|
def validate(self, ctx: 'ValidationContext'):
|
|
1121
|
-
self._validate_options()
|
|
1122
1139
|
as_token = self.get_token(Token.AS)
|
|
1123
1140
|
if as_token:
|
|
1124
|
-
|
|
1125
|
-
if not
|
|
1126
|
-
self.errors += ("EXCEPT
|
|
1127
|
-
elif len(
|
|
1128
|
-
self.errors += ("EXCEPT
|
|
1129
|
-
elif not is_scalar_assign(
|
|
1130
|
-
self.errors += (f"EXCEPT
|
|
1141
|
+
assign = self.get_tokens(Token.VARIABLE)
|
|
1142
|
+
if not assign:
|
|
1143
|
+
self.errors += ("EXCEPT AS requires a value.",)
|
|
1144
|
+
elif len(assign) > 1:
|
|
1145
|
+
self.errors += ("EXCEPT AS accepts only one value.",)
|
|
1146
|
+
elif not is_scalar_assign(assign[0].value):
|
|
1147
|
+
self.errors += (f"EXCEPT AS variable '{assign[0].value}' is invalid.",)
|
|
1148
|
+
self._validate_options()
|
|
1131
1149
|
|
|
1132
1150
|
|
|
1133
1151
|
@Statement.register
|
|
@@ -1143,6 +1161,11 @@ class End(NoArgumentHeader):
|
|
|
1143
1161
|
@Statement.register
|
|
1144
1162
|
class WhileHeader(Statement):
|
|
1145
1163
|
type = Token.WHILE
|
|
1164
|
+
options = {
|
|
1165
|
+
'limit': None,
|
|
1166
|
+
'on_limit': ('PASS', 'FAIL'),
|
|
1167
|
+
'on_limit_message': None
|
|
1168
|
+
}
|
|
1146
1169
|
|
|
1147
1170
|
@classmethod
|
|
1148
1171
|
def from_params(cls, condition: str, limit: 'str|None' = None,
|
|
@@ -1154,13 +1177,13 @@ class WhileHeader(Statement):
|
|
|
1154
1177
|
Token(Token.SEPARATOR, separator),
|
|
1155
1178
|
Token(Token.ARGUMENT, condition)]
|
|
1156
1179
|
if limit:
|
|
1157
|
-
tokens.extend([Token(Token.SEPARATOR,
|
|
1180
|
+
tokens.extend([Token(Token.SEPARATOR, separator),
|
|
1158
1181
|
Token(Token.OPTION, f'limit={limit}')])
|
|
1159
1182
|
if on_limit:
|
|
1160
|
-
tokens.extend([Token(Token.SEPARATOR,
|
|
1183
|
+
tokens.extend([Token(Token.SEPARATOR, separator),
|
|
1161
1184
|
Token(Token.OPTION, f'on_limit={on_limit}')])
|
|
1162
1185
|
if on_limit_message:
|
|
1163
|
-
tokens.extend([Token(Token.SEPARATOR,
|
|
1186
|
+
tokens.extend([Token(Token.SEPARATOR, separator),
|
|
1164
1187
|
Token(Token.OPTION, f'on_limit_message={on_limit_message}')])
|
|
1165
1188
|
tokens.append(Token(Token.EOL, eol))
|
|
1166
1189
|
return cls(tokens)
|
|
@@ -1182,26 +1205,76 @@ class WhileHeader(Statement):
|
|
|
1182
1205
|
return self.get_option('on_limit_message')
|
|
1183
1206
|
|
|
1184
1207
|
def validate(self, ctx: 'ValidationContext'):
|
|
1185
|
-
conditions = self.
|
|
1208
|
+
conditions = self.get_values(Token.ARGUMENT)
|
|
1186
1209
|
if len(conditions) > 1:
|
|
1187
|
-
self.
|
|
1188
|
-
f
|
|
1210
|
+
self.errors += (f"WHILE accepts only one condition, got {len(conditions)} "
|
|
1211
|
+
f"conditions {seq2str(conditions)}.",)
|
|
1189
1212
|
if self.on_limit and not self.limit:
|
|
1190
|
-
self.
|
|
1213
|
+
self.errors += ("WHILE option 'on_limit' cannot be used without 'limit'.",)
|
|
1191
1214
|
self._validate_options()
|
|
1192
1215
|
|
|
1193
|
-
def _add_error(self, error: str):
|
|
1194
|
-
self.errors += (f'WHILE loop {error}.',)
|
|
1195
|
-
|
|
1196
1216
|
|
|
1197
1217
|
@Statement.register
|
|
1198
|
-
class
|
|
1199
|
-
type = Token.
|
|
1218
|
+
class Var(Statement):
|
|
1219
|
+
type = Token.VAR
|
|
1220
|
+
options = {
|
|
1221
|
+
'scope': ('GLOBAL', 'SUITE', 'TEST', 'TASK', 'LOCAL'),
|
|
1222
|
+
'separator': None
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
@classmethod
|
|
1226
|
+
def from_params(cls, name: str,
|
|
1227
|
+
value: 'str|Sequence[str]',
|
|
1228
|
+
scope: 'str|None' = None,
|
|
1229
|
+
value_separator: 'str|None' = None,
|
|
1230
|
+
indent: str = FOUR_SPACES,
|
|
1231
|
+
separator: str = FOUR_SPACES,
|
|
1232
|
+
eol: str = EOL) -> 'Var':
|
|
1233
|
+
tokens = [Token(Token.SEPARATOR, indent),
|
|
1234
|
+
Token(Token.VAR),
|
|
1235
|
+
Token(Token.SEPARATOR, separator),
|
|
1236
|
+
Token(Token.VARIABLE, name)]
|
|
1237
|
+
values = [value] if isinstance(value, str) else value
|
|
1238
|
+
for value in values:
|
|
1239
|
+
tokens.extend([Token(Token.SEPARATOR, separator),
|
|
1240
|
+
Token(Token.ARGUMENT, value)])
|
|
1241
|
+
if scope:
|
|
1242
|
+
tokens.extend([Token(Token.SEPARATOR, separator),
|
|
1243
|
+
Token(Token.OPTION, f'scope={scope}')])
|
|
1244
|
+
if value_separator:
|
|
1245
|
+
tokens.extend([Token(Token.SEPARATOR, separator),
|
|
1246
|
+
Token(Token.OPTION, f'separator={value_separator}')])
|
|
1247
|
+
tokens.append(Token(Token.EOL, eol))
|
|
1248
|
+
return cls(tokens)
|
|
1200
1249
|
|
|
1201
1250
|
@property
|
|
1202
|
-
def
|
|
1251
|
+
def name(self) -> str:
|
|
1252
|
+
name = self.get_value(Token.VARIABLE, '')
|
|
1253
|
+
if name.endswith('='):
|
|
1254
|
+
return name[:-1].rstrip()
|
|
1255
|
+
return name
|
|
1256
|
+
|
|
1257
|
+
@property
|
|
1258
|
+
def value(self) -> 'tuple[str, ...]':
|
|
1203
1259
|
return self.get_values(Token.ARGUMENT)
|
|
1204
1260
|
|
|
1261
|
+
@property
|
|
1262
|
+
def scope(self) -> 'str|None':
|
|
1263
|
+
return self.get_option('scope')
|
|
1264
|
+
|
|
1265
|
+
@property
|
|
1266
|
+
def separator(self) -> 'str|None':
|
|
1267
|
+
return self.get_option('separator')
|
|
1268
|
+
|
|
1269
|
+
def validate(self, ctx: 'ValidationContext'):
|
|
1270
|
+
VariableValidator().validate(self)
|
|
1271
|
+
self._validate_options()
|
|
1272
|
+
|
|
1273
|
+
|
|
1274
|
+
@Statement.register
|
|
1275
|
+
class ReturnStatement(Statement):
|
|
1276
|
+
type = Token.RETURN_STATEMENT
|
|
1277
|
+
|
|
1205
1278
|
@classmethod
|
|
1206
1279
|
def from_params(cls, values: 'Sequence[str]' = (), indent: str = FOUR_SPACES,
|
|
1207
1280
|
separator: str = FOUR_SPACES, eol: str = EOL) -> 'ReturnStatement':
|
|
@@ -1213,6 +1286,10 @@ class ReturnStatement(Statement):
|
|
|
1213
1286
|
tokens.append(Token(Token.EOL, eol))
|
|
1214
1287
|
return cls(tokens)
|
|
1215
1288
|
|
|
1289
|
+
@property
|
|
1290
|
+
def values(self) -> 'tuple[str, ...]':
|
|
1291
|
+
return self.get_values(Token.ARGUMENT)
|
|
1292
|
+
|
|
1216
1293
|
def validate(self, ctx: 'ValidationContext'):
|
|
1217
1294
|
if not ctx.in_keyword:
|
|
1218
1295
|
self.errors += ('RETURN can only be used inside a user keyword.',)
|
|
@@ -1310,3 +1387,26 @@ class EmptyLine(Statement):
|
|
|
1310
1387
|
@classmethod
|
|
1311
1388
|
def from_params(cls, eol: str = EOL):
|
|
1312
1389
|
return cls([Token(Token.EOL, eol)])
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
class VariableValidator:
|
|
1393
|
+
|
|
1394
|
+
def validate(self, statement: Statement):
|
|
1395
|
+
name = statement.get_value(Token.VARIABLE, '')
|
|
1396
|
+
match = search_variable(name, ignore_errors=True)
|
|
1397
|
+
if not match.is_assign(allow_assign_mark=True, allow_nested=True):
|
|
1398
|
+
statement.errors += (f"Invalid variable name '{name}'.",)
|
|
1399
|
+
if match.identifier == '&':
|
|
1400
|
+
self._validate_dict_items(statement)
|
|
1401
|
+
|
|
1402
|
+
def _validate_dict_items(self, statement: Statement):
|
|
1403
|
+
for item in statement.get_values(Token.ARGUMENT):
|
|
1404
|
+
if not self._is_valid_dict_item(item):
|
|
1405
|
+
statement.errors += (
|
|
1406
|
+
f"Invalid dictionary variable item '{item}'. Items must use "
|
|
1407
|
+
f"'name=value' syntax or be dictionary variables themselves.",
|
|
1408
|
+
)
|
|
1409
|
+
|
|
1410
|
+
def _is_valid_dict_item(self, item: str) -> bool:
|
|
1411
|
+
name, value = split_from_equals(item)
|
|
1412
|
+
return value is not None or is_dict_variable(item)
|
|
@@ -0,0 +1,102 @@
|
|
|
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 ast import NodeTransformer, NodeVisitor
|
|
17
|
+
from typing import Callable
|
|
18
|
+
|
|
19
|
+
from .statements import Node
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Unbound method and thus needs `NodeVisitor` as `self`.
|
|
23
|
+
VisitorMethod = Callable[[NodeVisitor, Node], 'None|Node|list[Node]']
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class VisitorFinder:
|
|
27
|
+
__visitor_cache: 'dict[type[Node], VisitorMethod]'
|
|
28
|
+
|
|
29
|
+
def __init_subclass__(cls, **kwargs):
|
|
30
|
+
super().__init_subclass__(**kwargs)
|
|
31
|
+
cls.__visitor_cache = {}
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def _find_visitor(cls, node_cls: 'type[Node]') -> VisitorMethod:
|
|
35
|
+
if node_cls not in cls.__visitor_cache:
|
|
36
|
+
visitor = cls._find_visitor_from_class(node_cls)
|
|
37
|
+
cls.__visitor_cache[node_cls] = visitor or cls.generic_visit
|
|
38
|
+
return cls.__visitor_cache[node_cls]
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def _find_visitor_from_class(cls, node_cls: 'type[Node]') -> 'VisitorMethod|None':
|
|
42
|
+
method_name = 'visit_' + node_cls.__name__
|
|
43
|
+
method = getattr(cls, method_name, None)
|
|
44
|
+
if callable(method):
|
|
45
|
+
return method
|
|
46
|
+
if method_name in ('visit_TestTags', 'visit_Return'):
|
|
47
|
+
method = cls._compatibility(method_name)
|
|
48
|
+
if callable(method):
|
|
49
|
+
return method
|
|
50
|
+
for base in node_cls.__bases__:
|
|
51
|
+
if issubclass(base, Node):
|
|
52
|
+
method = cls._find_visitor_from_class(base)
|
|
53
|
+
if method:
|
|
54
|
+
return method
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def _compatibility(cls, method_name):
|
|
59
|
+
# visit_ForceTags is supported for backwards compatibility.
|
|
60
|
+
# visit_ReturnSetting is supported for forward compatibility.
|
|
61
|
+
name = {'visit_TestTags': 'visit_ForceTags',
|
|
62
|
+
'visit_Return': 'visit_ReturnSetting'}[method_name]
|
|
63
|
+
return getattr(cls, name, None)
|
|
64
|
+
|
|
65
|
+
def generic_visit(self, node: Node) -> 'None|Node|list[Node]':
|
|
66
|
+
raise NotImplementedError
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ModelVisitor(NodeVisitor, VisitorFinder):
|
|
70
|
+
"""NodeVisitor that supports matching nodes based on their base classes.
|
|
71
|
+
|
|
72
|
+
The biggest difference compared to the standard `ast.NodeVisitor
|
|
73
|
+
<https://docs.python.org/library/ast.html#ast.NodeVisitor>`__,
|
|
74
|
+
is that this class allows creating ``visit_ClassName`` methods so that
|
|
75
|
+
the ``ClassName`` is one of the base classes of the node. For example,
|
|
76
|
+
the following visitor method matches all node classes that extend
|
|
77
|
+
``Statement``::
|
|
78
|
+
|
|
79
|
+
def visit_Statement(self, node):
|
|
80
|
+
...
|
|
81
|
+
|
|
82
|
+
Another difference is that visitor methods are cached for performance
|
|
83
|
+
reasons. This means that dynamically adding ``visit_Something`` methods
|
|
84
|
+
does not work.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
def visit(self, node: Node) -> None:
|
|
88
|
+
visitor_method = self._find_visitor(type(node))
|
|
89
|
+
visitor_method(self, node)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class ModelTransformer(NodeTransformer, VisitorFinder):
|
|
93
|
+
"""NodeTransformer that supports matching nodes based on their base classes.
|
|
94
|
+
|
|
95
|
+
See :class:`ModelVisitor` for explanation how this is different compared
|
|
96
|
+
to the standard `ast.NodeTransformer
|
|
97
|
+
<https://docs.python.org/library/ast.html#ast.NodeTransformer>`__.
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
def visit(self, node: Node) -> 'None|Node|list[Node]':
|
|
101
|
+
visitor_method = self._find_visitor(type(node))
|
|
102
|
+
return visitor_method(self, node)
|
|
@@ -33,6 +33,6 @@ class ExpandKeywordMatcher:
|
|
|
33
33
|
self._match_tags = MultiMatcher(tags).match_any
|
|
34
34
|
|
|
35
35
|
def match(self, kw: Keyword):
|
|
36
|
-
if (self._match_name(kw.
|
|
36
|
+
if (self._match_name(kw.full_name or '')
|
|
37
37
|
or self._match_tags(kw.tags)) and not kw.not_run:
|
|
38
38
|
self.matched_ids.append(kw.id)
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
+
from datetime import datetime
|
|
16
17
|
from contextlib import contextmanager
|
|
17
18
|
from pathlib import Path
|
|
18
19
|
|
|
19
20
|
from robot.output.loggerhelper import LEVELS
|
|
20
|
-
from robot.utils import
|
|
21
|
-
timestamp_to_secs)
|
|
21
|
+
from robot.utils import attribute_escape, get_link_path, html_escape, safe_str
|
|
22
22
|
|
|
23
23
|
from .expandkeywordmatcher import ExpandKeywordMatcher
|
|
24
24
|
from .stringcache import StringCache
|
|
@@ -48,7 +48,9 @@ class JsBuildingContext:
|
|
|
48
48
|
return None
|
|
49
49
|
|
|
50
50
|
def string(self, string, escape=True, attr=False):
|
|
51
|
-
if
|
|
51
|
+
if not string:
|
|
52
|
+
return self._strings.empty
|
|
53
|
+
if escape:
|
|
52
54
|
if not isinstance(string, str):
|
|
53
55
|
string = safe_str(string)
|
|
54
56
|
string = (html_escape if not attr else attribute_escape)(string)
|
|
@@ -64,10 +66,10 @@ class JsBuildingContext:
|
|
|
64
66
|
if self._log_dir and source and source.exists() else ''
|
|
65
67
|
return self.string(rel_source)
|
|
66
68
|
|
|
67
|
-
def timestamp(self,
|
|
68
|
-
if not
|
|
69
|
+
def timestamp(self, ts: datetime) -> 'int|None':
|
|
70
|
+
if not ts:
|
|
69
71
|
return None
|
|
70
|
-
millis =
|
|
72
|
+
millis = round(ts.timestamp() * 1000)
|
|
71
73
|
if self.basemillis is None:
|
|
72
74
|
self.basemillis = millis
|
|
73
75
|
return millis - self.basemillis
|