robotframework 6.1rc1__zip → 7.0__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {robotframework-6.1rc1 → robotframework-7.0}/INSTALL.rst +25 -25
- {robotframework-6.1rc1 → robotframework-7.0}/PKG-INFO +6 -8
- {robotframework-6.1rc1 → robotframework-7.0}/README.rst +3 -2
- {robotframework-6.1rc1 → robotframework-7.0}/setup.py +3 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/__init__.py +4 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/deco.py +60 -14
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/exceptions.py +6 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/interfaces.py +403 -68
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/logger.py +27 -20
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/api/parsing.py +4 -2
- robotframework-7.0/src/robot/api/py.typed +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/gatherfailed.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/languages.py +61 -25
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/settings.py +21 -14
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/common/storage.js +11 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/htmlfilewriter.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.css +10 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.html +10 -0
- robotframework-7.0/src/robot/htmldata/rebot/common.css +362 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/doc_formatting.css +13 -7
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/log.css +51 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/log.html +14 -23
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/model.js +2 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/report.css +83 -19
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/report.html +22 -7
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/testdata.js +10 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/view.js +84 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/template.py +3 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/builder.py +0 -8
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/datatypes.py +9 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/htmlutils.py +4 -7
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/jsonbuilder.py +38 -20
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/model.py +21 -28
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/robotbuilder.py +50 -31
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/standardtypes.py +9 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/xmlbuilder.py +35 -20
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/xmlwriter.py +18 -38
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/BuiltIn.py +255 -205
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Collections.py +384 -240
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/DateTime.py +73 -60
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/OperatingSystem.py +6 -5
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Process.py +26 -27
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Remote.py +40 -36
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/String.py +66 -76
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/XML.py +66 -59
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/__init__.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/dialogs_py.py +14 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/__init__.py +5 -5
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/body.py +44 -13
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/configurer.py +19 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/control.py +230 -88
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/filter.py +31 -25
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/itemlist.py +9 -8
- robotframework-7.0/src/robot/model/keyword.py +77 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/message.py +19 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/modelobject.py +27 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/modifier.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/namepatterns.py +3 -25
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/stats.py +9 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/tags.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/testcase.py +15 -27
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/testsuite.py +44 -28
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/visitor.py +35 -8
- robotframework-7.0/src/robot/output/console/dotted.py +90 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/quiet.py +3 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/verbose.py +61 -61
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/debugfile.py +39 -24
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/filelogger.py +18 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/librarylogger.py +3 -2
- robotframework-7.0/src/robot/output/listeners.py +753 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/logger.py +216 -80
- robotframework-7.0/src/robot/output/loggerapi.py +215 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/loggerhelper.py +23 -56
- robotframework-7.0/src/robot/output/output.py +185 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/stdoutlogsplitter.py +8 -5
- robotframework-7.0/src/robot/output/xmllogger.py +459 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/blocklexers.py +17 -13
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/context.py +12 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/lexer.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/settings.py +6 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/statementlexers.py +39 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/tokens.py +27 -29
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/model/blocks.py +19 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/model/statements.py +193 -94
- robotframework-7.0/src/robot/parsing/model/visitor.py +100 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/rebot.py +2 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/expandkeywordmatcher.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jsbuildingcontext.py +8 -6
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jsmodelbuilders.py +88 -61
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/logreportwriters.py +16 -10
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/outputwriter.py +18 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/resultwriter.py +4 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/stringcache.py +3 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/xunitwriter.py +15 -21
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/__init__.py +3 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/configurer.py +12 -9
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/executionresult.py +56 -8
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/flattenkeywordmatcher.py +48 -9
- robotframework-7.0/src/robot/result/keywordremover.py +207 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/merger.py +1 -1
- robotframework-7.0/src/robot/result/model.py +1185 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/modeldeprecation.py +9 -3
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/resultbuilder.py +46 -36
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/xmlelementhandlers.py +83 -43
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/run.py +3 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/__init__.py +14 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/__init__.py +2 -1
- robotframework-7.0/src/robot/running/arguments/argumentconverter.py +100 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentmapper.py +26 -24
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentparser.py +85 -61
- robotframework-7.0/src/robot/running/arguments/argumentresolver.py +158 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentspec.py +83 -116
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/argumentvalidator.py +33 -27
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/customconverters.py +15 -12
- robotframework-7.0/src/robot/running/arguments/embedded.py +145 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/arguments/typeconverters.py +268 -220
- robotframework-7.0/src/robot/running/arguments/typeinfo.py +317 -0
- robotframework-7.0/src/robot/running/arguments/typeinfoparser.py +219 -0
- robotframework-7.0/src/robot/running/arguments/typevalidator.py +60 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/bodyrunner.py +147 -129
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/builders.py +17 -26
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/parsers.py +17 -11
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/settings.py +9 -17
- robotframework-7.0/src/robot/running/builder/transformers.py +535 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/context.py +113 -31
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/dynamicmethods.py +62 -34
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/importer.py +27 -49
- robotframework-7.0/src/robot/running/invalidkeyword.py +67 -0
- robotframework-7.0/src/robot/running/keywordfinder.py +91 -0
- robotframework-7.0/src/robot/running/keywordimplementation.py +164 -0
- robotframework-7.0/src/robot/running/librarykeyword.py +392 -0
- robotframework-7.0/src/robot/running/librarykeywordrunner.py +250 -0
- robotframework-7.0/src/robot/running/libraryscopes.py +115 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/model.py +198 -337
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/namespace.py +124 -137
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/outputcapture.py +20 -12
- robotframework-7.0/src/robot/running/resourcemodel.py +448 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/statusreporter.py +16 -13
- robotframework-7.0/src/robot/running/suiterunner.py +265 -0
- robotframework-7.0/src/robot/running/testlibraries.py +500 -0
- robotframework-7.0/src/robot/running/userkeywordrunner.py +260 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/testdoc.py +18 -13
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/__init__.py +53 -35
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/connectioncache.py +64 -59
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/dotdict.py +3 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/encodingsniffer.py +9 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/escaping.py +19 -19
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/importer.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/markupwriters.py +23 -15
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/misc.py +1 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/normalizing.py +9 -24
- robotframework-7.0/src/robot/utils/notset.py +33 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/platform.py +15 -5
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotio.py +9 -9
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotpath.py +1 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robottime.py +122 -90
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robottypes.py +21 -31
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/setter.py +0 -5
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/text.py +7 -4
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/unic.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/__init__.py +2 -2
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/assigner.py +17 -19
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/evaluation.py +20 -17
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/filesetter.py +80 -80
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/replacer.py +33 -36
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/scopes.py +17 -12
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/search.py +66 -41
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/store.py +14 -16
- robotframework-7.0/src/robot/variables/tablesetter.py +164 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/variables.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/version.py +1 -1
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/PKG-INFO +6 -8
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/SOURCES.txt +10 -8
- {robotframework-6.1rc1 → robotframework-7.0}/tasks.py +6 -6
- robotframework-6.1rc1/src/robot/htmldata/rebot/common.css +0 -239
- robotframework-6.1rc1/src/robot/libraries/Reserved.py +0 -48
- robotframework-6.1rc1/src/robot/model/keyword.py +0 -173
- robotframework-6.1rc1/src/robot/output/console/dotted.py +0 -90
- robotframework-6.1rc1/src/robot/output/listenerarguments.py +0 -165
- robotframework-6.1rc1/src/robot/output/listenermethods.py +0 -113
- robotframework-6.1rc1/src/robot/output/listeners.py +0 -174
- robotframework-6.1rc1/src/robot/output/output.py +0 -95
- robotframework-6.1rc1/src/robot/output/xmllogger.py +0 -354
- robotframework-6.1rc1/src/robot/parsing/model/visitor.py +0 -67
- robotframework-6.1rc1/src/robot/result/keywordremover.py +0 -183
- robotframework-6.1rc1/src/robot/result/model.py +0 -957
- robotframework-6.1rc1/src/robot/running/arguments/argumentconverter.py +0 -79
- robotframework-6.1rc1/src/robot/running/arguments/argumentresolver.py +0 -131
- robotframework-6.1rc1/src/robot/running/arguments/embedded.py +0 -146
- robotframework-6.1rc1/src/robot/running/arguments/typevalidator.py +0 -56
- robotframework-6.1rc1/src/robot/running/builder/transformers.py +0 -642
- robotframework-6.1rc1/src/robot/running/handlers.py +0 -321
- robotframework-6.1rc1/src/robot/running/handlerstore.py +0 -66
- robotframework-6.1rc1/src/robot/running/librarykeywordrunner.py +0 -238
- robotframework-6.1rc1/src/robot/running/libraryscopes.py +0 -97
- robotframework-6.1rc1/src/robot/running/modelcombiner.py +0 -32
- robotframework-6.1rc1/src/robot/running/suiterunner.py +0 -249
- robotframework-6.1rc1/src/robot/running/testlibraries.py +0 -420
- robotframework-6.1rc1/src/robot/running/usererrorhandler.py +0 -75
- robotframework-6.1rc1/src/robot/running/userkeyword.py +0 -111
- robotframework-6.1rc1/src/robot/running/userkeywordrunner.py +0 -274
- robotframework-6.1rc1/src/robot/variables/tablesetter.py +0 -156
- {robotframework-6.1rc1 → robotframework-7.0}/AUTHORS.rst +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/BUILD.rst +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/CONTRIBUTING.rst +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/COPYRIGHT.txt +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/LICENSE.txt +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/MANIFEST.in +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/setup.cfg +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/__main__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/conf/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/errors.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/common/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/common/js_disabled.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/jsonwriter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/doc_formatting.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/print.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/libdoc/pygments.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/fileloading.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/log.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/print.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/rebot/util.js +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/testdoc/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.css +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.html +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdoc.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/consoleviewer.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/htmlwriter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/jsonwriter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/output.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libdocpkg/writer.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Dialogs.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Easter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Screenshot.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/libraries/Telnet.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/fixture.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/metadata.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/statistics.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/suitestatistics.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/tagsetter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/tagstatistics.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/model/totalstatistics.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/console/highlighting.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/output/pyloggingconf.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/lexer/tokenizer.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/model/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/blockparsers.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/fileparser.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/parser/parser.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/parsing/suitestructure.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/pythonpathsetter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jsexecutionresult.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/reporting/jswriter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/executionerrors.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/messagefilter.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/suiteteardownfailed.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/result/visitor.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/builder/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/randomizer.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/runkwregister.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/signalhandler.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/status.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/timeouts/__init__.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/timeouts/posix.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/running/timeouts/windows.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/application.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/argumentparser.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/asserts.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/charwidth.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/compress.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/encoding.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/error.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/etreewrapper.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/filereader.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/frange.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/htmlformatters.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/markuputils.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/match.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/recommendations.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/restreader.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotenv.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/robotinspect.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/sortable.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/utils/typehints.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/finders.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/notfound.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robot/variables/resolvable.py +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/dependency_links.txt +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/entry_points.txt +0 -0
- {robotframework-6.1rc1 → robotframework-7.0}/src/robotframework.egg-info/top_level.txt +0 -0
|
@@ -34,8 +34,7 @@ else:
|
|
|
34
34
|
from robot.api import logger
|
|
35
35
|
from robot.api.deco import keyword
|
|
36
36
|
from robot.libraries.BuiltIn import BuiltIn
|
|
37
|
-
from robot.utils import
|
|
38
|
-
is_truthy, plural_or_not as s)
|
|
37
|
+
from robot.utils import asserts, ET, ETSource, plural_or_not as s
|
|
39
38
|
from robot.version import get_version
|
|
40
39
|
|
|
41
40
|
|
|
@@ -53,7 +52,7 @@ class XML:
|
|
|
53
52
|
The library has the following main usages:
|
|
54
53
|
|
|
55
54
|
- Parsing an XML file, or a string containing XML, into an XML element
|
|
56
|
-
structure and finding certain elements from it for
|
|
55
|
+
structure and finding certain elements from it for further analysis
|
|
57
56
|
(e.g. `Parse XML` and `Get Element` keywords).
|
|
58
57
|
- Getting text or attributes of elements
|
|
59
58
|
(e.g. `Get Element Text` and `Get Element Attribute`).
|
|
@@ -75,10 +74,10 @@ class XML:
|
|
|
75
74
|
children and their children. Possible comments and processing instructions
|
|
76
75
|
in the source XML are removed.
|
|
77
76
|
|
|
78
|
-
XML is not validated during parsing even if has a schema defined. How
|
|
77
|
+
XML is not validated during parsing even if it has a schema defined. How
|
|
79
78
|
possible doctype elements are handled otherwise depends on the used XML
|
|
80
79
|
module and on the platform. The standard ElementTree strips doctypes
|
|
81
|
-
altogether but when `using lxml` they are preserved when XML is saved.
|
|
80
|
+
altogether, but when `using lxml` they are preserved when XML is saved.
|
|
82
81
|
|
|
83
82
|
The element structure returned by `Parse XML`, as well as elements
|
|
84
83
|
returned by keywords such as `Get Element`, can be used as the ``source``
|
|
@@ -95,8 +94,6 @@ class XML:
|
|
|
95
94
|
escaped by doubling it (``\\\\``). Using the built-in variable ``${/}``
|
|
96
95
|
naturally works too.
|
|
97
96
|
|
|
98
|
-
Note: Support for XML as bytes is new in Robot Framework 3.2.
|
|
99
|
-
|
|
100
97
|
= Using lxml =
|
|
101
98
|
|
|
102
99
|
By default, this library uses Python's standard
|
|
@@ -168,7 +165,7 @@ class XML:
|
|
|
168
165
|
|
|
169
166
|
If lxml support is enabled when `importing` the library, the whole
|
|
170
167
|
[http://www.w3.org/TR/xpath/|xpath 1.0 standard] is supported.
|
|
171
|
-
That includes everything listed below but also lot of other useful
|
|
168
|
+
That includes everything listed below but also a lot of other useful
|
|
172
169
|
constructs.
|
|
173
170
|
|
|
174
171
|
== Tag names ==
|
|
@@ -304,7 +301,7 @@ class XML:
|
|
|
304
301
|
= Handling XML namespaces =
|
|
305
302
|
|
|
306
303
|
ElementTree and lxml handle possible namespaces in XML documents by adding
|
|
307
|
-
the namespace URI to tag names in so
|
|
304
|
+
the namespace URI to tag names in so-called Clark Notation. That is
|
|
308
305
|
inconvenient especially with xpaths, and by default this library strips
|
|
309
306
|
those namespaces away and moves them to ``xmlns`` attribute instead. That
|
|
310
307
|
can be avoided by passing ``keep_clark_notation`` argument to `Parse XML`
|
|
@@ -433,8 +430,6 @@ class XML:
|
|
|
433
430
|
| `Parse XML` | ${XML} | keep_clark_notation=${EMPTY} | # Empty string is false. |
|
|
434
431
|
| `Parse XML` | ${XML} | keep_clark_notation=${FALSE} | # Python ``False`` is false. |
|
|
435
432
|
|
|
436
|
-
Considering ``OFF`` and ``0`` false is new in Robot Framework 3.1.
|
|
437
|
-
|
|
438
433
|
== Pattern matching ==
|
|
439
434
|
|
|
440
435
|
Some keywords, for example `Elements Should Match`, support so called
|
|
@@ -450,9 +445,6 @@ class XML:
|
|
|
450
445
|
Unlike with glob patterns normally, path separator characters ``/`` and
|
|
451
446
|
``\\`` and the newline character ``\\n`` are matches by the above
|
|
452
447
|
wildcards.
|
|
453
|
-
|
|
454
|
-
Support for brackets like ``[abc]`` and ``[!a-z]`` is new in
|
|
455
|
-
Robot Framework 3.1
|
|
456
448
|
"""
|
|
457
449
|
ROBOT_LIBRARY_SCOPE = 'GLOBAL'
|
|
458
450
|
ROBOT_LIBRARY_VERSION = get_version()
|
|
@@ -470,7 +462,6 @@ class XML:
|
|
|
470
462
|
If lxml mode is enabled but the module is not installed, this library
|
|
471
463
|
emits a warning and reverts back to using the standard ElementTree.
|
|
472
464
|
"""
|
|
473
|
-
use_lxml = is_truthy(use_lxml)
|
|
474
465
|
if use_lxml and lxml_etree:
|
|
475
466
|
self.etree = lxml_etree
|
|
476
467
|
self.modern_etree = True
|
|
@@ -523,8 +514,8 @@ class XML:
|
|
|
523
514
|
strip = (lxml_etree.Comment, lxml_etree.ProcessingInstruction)
|
|
524
515
|
lxml_etree.strip_elements(tree, *strip, **dict(with_tail=False))
|
|
525
516
|
root = tree.getroot()
|
|
526
|
-
if not
|
|
527
|
-
self._ns_stripper.strip(root, preserve=
|
|
517
|
+
if not keep_clark_notation:
|
|
518
|
+
self._ns_stripper.strip(root, preserve=not strip_namespaces)
|
|
528
519
|
return root
|
|
529
520
|
|
|
530
521
|
def get_element(self, source, xpath='.'):
|
|
@@ -565,10 +556,10 @@ class XML:
|
|
|
565
556
|
|
|
566
557
|
def _wrong_number_of_matches(self, count, xpath):
|
|
567
558
|
if not count:
|
|
568
|
-
return "No element matching '
|
|
559
|
+
return f"No element matching '{xpath}' found."
|
|
569
560
|
if count == 1:
|
|
570
|
-
return "One element matching '
|
|
571
|
-
return "Multiple elements (
|
|
561
|
+
return f"One element matching '{xpath}' found."
|
|
562
|
+
return f"Multiple elements ({count}) matching '{xpath}' found."
|
|
572
563
|
|
|
573
564
|
def get_elements(self, source, xpath):
|
|
574
565
|
"""Returns a list of elements in the ``source`` matching the ``xpath``.
|
|
@@ -619,7 +610,7 @@ class XML:
|
|
|
619
610
|
See also `Element Should Exist` and `Element Should Not Exist`.
|
|
620
611
|
"""
|
|
621
612
|
count = len(self.get_elements(source, xpath))
|
|
622
|
-
logger.info("
|
|
613
|
+
logger.info(f"{count} element{s(count)} matched '{xpath}'.")
|
|
623
614
|
return count
|
|
624
615
|
|
|
625
616
|
def element_should_exist(self, source, xpath='.', message=None):
|
|
@@ -685,7 +676,7 @@ class XML:
|
|
|
685
676
|
"""
|
|
686
677
|
element = self.get_element(source, xpath)
|
|
687
678
|
text = ''.join(self._yield_texts(element))
|
|
688
|
-
if
|
|
679
|
+
if normalize_whitespace:
|
|
689
680
|
text = self._normalize_whitespace(text)
|
|
690
681
|
return text
|
|
691
682
|
|
|
@@ -854,7 +845,7 @@ class XML:
|
|
|
854
845
|
"""
|
|
855
846
|
attr = self.get_element_attribute(source, name, xpath)
|
|
856
847
|
if attr is None:
|
|
857
|
-
raise AssertionError("Attribute '
|
|
848
|
+
raise AssertionError(f"Attribute '{name}' does not exist.")
|
|
858
849
|
should_match(attr, pattern, message, values=False)
|
|
859
850
|
|
|
860
851
|
def element_should_not_have_attribute(self, source, name, xpath='.', message=None):
|
|
@@ -876,11 +867,11 @@ class XML:
|
|
|
876
867
|
"""
|
|
877
868
|
attr = self.get_element_attribute(source, name, xpath)
|
|
878
869
|
if attr is not None:
|
|
879
|
-
raise AssertionError(message or
|
|
880
|
-
|
|
870
|
+
raise AssertionError(message or
|
|
871
|
+
f"Attribute '{name}' exists and has value '{attr}'.")
|
|
881
872
|
|
|
882
873
|
def elements_should_be_equal(self, source, expected, exclude_children=False,
|
|
883
|
-
normalize_whitespace=False):
|
|
874
|
+
normalize_whitespace=False, sort_children=False):
|
|
884
875
|
"""Verifies that the given ``source`` element is equal to ``expected``.
|
|
885
876
|
|
|
886
877
|
Both ``source`` and ``expected`` can be given as a path to an XML file,
|
|
@@ -890,12 +881,14 @@ class XML:
|
|
|
890
881
|
|
|
891
882
|
The keyword passes if the ``source`` element and ``expected`` element
|
|
892
883
|
are equal. This includes testing the tag names, texts, and attributes
|
|
893
|
-
of the elements. By default also child elements are verified the same
|
|
884
|
+
of the elements. By default, also child elements are verified the same
|
|
894
885
|
way, but this can be disabled by setting ``exclude_children`` to a
|
|
895
|
-
true value (see `Boolean arguments`).
|
|
886
|
+
true value (see `Boolean arguments`). Child elements are expected to
|
|
887
|
+
be in the same order, but that can be changed by giving ``sort_children``
|
|
888
|
+
a true value. Notice that elements are sorted solely based on tag names.
|
|
896
889
|
|
|
897
890
|
All texts inside the given elements are verified, but possible text
|
|
898
|
-
outside them is not. By default texts must match exactly, but setting
|
|
891
|
+
outside them is not. By default, texts must match exactly, but setting
|
|
899
892
|
``normalize_whitespace`` to a true value makes text verification
|
|
900
893
|
independent on newlines, tabs, and the amount of spaces. For more
|
|
901
894
|
details about handling text see `Get Element Text` keyword and
|
|
@@ -915,12 +908,14 @@ class XML:
|
|
|
915
908
|
the ``.`` at the end that is the `tail` text of the ``<i>`` element.
|
|
916
909
|
|
|
917
910
|
See also `Elements Should Match`.
|
|
911
|
+
|
|
912
|
+
``sort_children`` is new in Robot Framework 7.0.
|
|
918
913
|
"""
|
|
919
|
-
self._compare_elements(source, expected, should_be_equal,
|
|
920
|
-
|
|
914
|
+
self._compare_elements(source, expected, should_be_equal, exclude_children,
|
|
915
|
+
sort_children, normalize_whitespace)
|
|
921
916
|
|
|
922
917
|
def elements_should_match(self, source, expected, exclude_children=False,
|
|
923
|
-
normalize_whitespace=False):
|
|
918
|
+
normalize_whitespace=False, sort_children=False):
|
|
924
919
|
"""Verifies that the given ``source`` element matches ``expected``.
|
|
925
920
|
|
|
926
921
|
This keyword works exactly like `Elements Should Be Equal` except that
|
|
@@ -937,16 +932,22 @@ class XML:
|
|
|
937
932
|
|
|
938
933
|
See `Elements Should Be Equal` for more examples.
|
|
939
934
|
"""
|
|
940
|
-
self._compare_elements(source, expected, should_match,
|
|
941
|
-
|
|
935
|
+
self._compare_elements(source, expected, should_match, exclude_children,
|
|
936
|
+
sort_children, normalize_whitespace)
|
|
942
937
|
|
|
943
938
|
def _compare_elements(self, source, expected, comparator, exclude_children,
|
|
944
|
-
normalize_whitespace):
|
|
945
|
-
normalizer = self._normalize_whitespace
|
|
946
|
-
|
|
947
|
-
comparator = ElementComparator(comparator, normalizer, exclude_children)
|
|
939
|
+
sort_children, normalize_whitespace):
|
|
940
|
+
normalizer = self._normalize_whitespace if normalize_whitespace else None
|
|
941
|
+
sorter = self._sort_children if sort_children else None
|
|
942
|
+
comparator = ElementComparator(comparator, normalizer, sorter, exclude_children)
|
|
948
943
|
comparator.compare(self.get_element(source), self.get_element(expected))
|
|
949
944
|
|
|
945
|
+
def _sort_children(self, element):
|
|
946
|
+
tails = [child.tail for child in element]
|
|
947
|
+
element[:] = sorted(element, key=lambda child: child.tag)
|
|
948
|
+
for child, tail in zip(element, tails):
|
|
949
|
+
child.tail = tail
|
|
950
|
+
|
|
950
951
|
def set_element_tag(self, source, tag, xpath='.'):
|
|
951
952
|
"""Sets the tag of the specified element.
|
|
952
953
|
|
|
@@ -1219,7 +1220,7 @@ class XML:
|
|
|
1219
1220
|
|
|
1220
1221
|
def _remove_element(self, root, element, remove_tail=False):
|
|
1221
1222
|
parent = self._find_parent(root, element)
|
|
1222
|
-
if not
|
|
1223
|
+
if not remove_tail:
|
|
1223
1224
|
self._preserve_tail(element, parent)
|
|
1224
1225
|
parent.remove(element)
|
|
1225
1226
|
|
|
@@ -1269,7 +1270,7 @@ class XML:
|
|
|
1269
1270
|
element = self.get_element(source, xpath)
|
|
1270
1271
|
tail = element.tail
|
|
1271
1272
|
element.clear()
|
|
1272
|
-
if not
|
|
1273
|
+
if not clear_tail:
|
|
1273
1274
|
element.tail = tail
|
|
1274
1275
|
return source
|
|
1275
1276
|
|
|
@@ -1279,7 +1280,7 @@ class XML:
|
|
|
1279
1280
|
The element to copy is specified using ``source`` and ``xpath``. They
|
|
1280
1281
|
have exactly the same semantics as with `Get Element` keyword.
|
|
1281
1282
|
|
|
1282
|
-
If the copy or the original element is modified
|
|
1283
|
+
If the copy or the original element is modified afterward, the changes
|
|
1283
1284
|
have no effect on the other.
|
|
1284
1285
|
|
|
1285
1286
|
Examples using ``${XML}`` structure from `Example`:
|
|
@@ -1308,6 +1309,8 @@ class XML:
|
|
|
1308
1309
|
See also `Log Element` and `Save XML`.
|
|
1309
1310
|
"""
|
|
1310
1311
|
source = self.get_element(source, xpath)
|
|
1312
|
+
if self.lxml_etree:
|
|
1313
|
+
source = self._ns_stripper.unstrip(source)
|
|
1311
1314
|
string = self.etree.tostring(source, encoding='UTF-8').decode('UTF-8')
|
|
1312
1315
|
string = re.sub(r'^<\?xml .*\?>', '', string).strip()
|
|
1313
1316
|
if encoding:
|
|
@@ -1365,8 +1368,7 @@ class XML:
|
|
|
1365
1368
|
output.write(self.etree.tostring(tree, **config))
|
|
1366
1369
|
else:
|
|
1367
1370
|
tree.write(output, **config)
|
|
1368
|
-
logger.info('XML saved to <a href="file
|
|
1369
|
-
html=True)
|
|
1371
|
+
logger.info(f'XML saved to <a href="file://{path}">{path}</a>.', html=True)
|
|
1370
1372
|
|
|
1371
1373
|
def evaluate_xpath(self, source, expression, context='.'):
|
|
1372
1374
|
"""Evaluates the given xpath expression and returns results.
|
|
@@ -1420,7 +1422,7 @@ class NameSpaceStripper:
|
|
|
1420
1422
|
elem = copy.deepcopy(elem)
|
|
1421
1423
|
ns = elem.attrib.pop('xmlns', current_ns)
|
|
1422
1424
|
if ns:
|
|
1423
|
-
elem.tag = '{
|
|
1425
|
+
elem.tag = f'{{{ns}}}{elem.tag}'
|
|
1424
1426
|
for child in elem:
|
|
1425
1427
|
self.unstrip(child, ns, copied=True)
|
|
1426
1428
|
return elem
|
|
@@ -1460,10 +1462,12 @@ class ElementFinder:
|
|
|
1460
1462
|
|
|
1461
1463
|
class ElementComparator:
|
|
1462
1464
|
|
|
1463
|
-
def __init__(self, comparator, normalizer=None,
|
|
1464
|
-
|
|
1465
|
-
self.
|
|
1466
|
-
self.
|
|
1465
|
+
def __init__(self, comparator, normalizer=None, child_sorter=None,
|
|
1466
|
+
exclude_children=False):
|
|
1467
|
+
self.comparator = comparator
|
|
1468
|
+
self.normalizer = normalizer or (lambda text: text)
|
|
1469
|
+
self.child_sorter = child_sorter
|
|
1470
|
+
self.exclude_children = exclude_children
|
|
1467
1471
|
|
|
1468
1472
|
def compare(self, actual, expected, location=None):
|
|
1469
1473
|
if not location:
|
|
@@ -1473,7 +1477,7 @@ class ElementComparator:
|
|
|
1473
1477
|
self._compare_texts(actual, expected, location)
|
|
1474
1478
|
if location.is_not_root:
|
|
1475
1479
|
self._compare_tails(actual, expected, location)
|
|
1476
|
-
if not self.
|
|
1480
|
+
if not self.exclude_children:
|
|
1477
1481
|
self._compare_children(actual, expected, location)
|
|
1478
1482
|
|
|
1479
1483
|
def _compare_tags(self, actual, expected, location):
|
|
@@ -1482,9 +1486,9 @@ class ElementComparator:
|
|
|
1482
1486
|
|
|
1483
1487
|
def _compare(self, actual, expected, message, location, comparator=None):
|
|
1484
1488
|
if location.is_not_root:
|
|
1485
|
-
message = "
|
|
1489
|
+
message = f"{message} at '{location.path}'"
|
|
1486
1490
|
if not comparator:
|
|
1487
|
-
comparator = self.
|
|
1491
|
+
comparator = self.comparator
|
|
1488
1492
|
comparator(actual, expected, message)
|
|
1489
1493
|
|
|
1490
1494
|
def _compare_attributes(self, actual, expected, location):
|
|
@@ -1492,14 +1496,14 @@ class ElementComparator:
|
|
|
1492
1496
|
'Different attribute names', location, should_be_equal)
|
|
1493
1497
|
for key in actual.attrib:
|
|
1494
1498
|
self._compare(actual.attrib[key], expected.attrib[key],
|
|
1495
|
-
"Different value for attribute '
|
|
1499
|
+
f"Different value for attribute '{key}'", location)
|
|
1496
1500
|
|
|
1497
1501
|
def _compare_texts(self, actual, expected, location):
|
|
1498
1502
|
self._compare(self._text(actual.text), self._text(expected.text),
|
|
1499
1503
|
'Different text', location)
|
|
1500
1504
|
|
|
1501
1505
|
def _text(self, text):
|
|
1502
|
-
return self.
|
|
1506
|
+
return self.normalizer(text or '')
|
|
1503
1507
|
|
|
1504
1508
|
def _compare_tails(self, actual, expected, location):
|
|
1505
1509
|
self._compare(self._text(actual.tail), self._text(expected.tail),
|
|
@@ -1508,6 +1512,9 @@ class ElementComparator:
|
|
|
1508
1512
|
def _compare_children(self, actual, expected, location):
|
|
1509
1513
|
self._compare(len(actual), len(expected), 'Different number of child elements',
|
|
1510
1514
|
location, should_be_equal)
|
|
1515
|
+
if self.child_sorter:
|
|
1516
|
+
self.child_sorter(actual)
|
|
1517
|
+
self.child_sorter(expected)
|
|
1511
1518
|
for act, exp in zip(actual, expected):
|
|
1512
1519
|
self.compare(act, exp, location.child(act.tag))
|
|
1513
1520
|
|
|
@@ -1517,12 +1524,12 @@ class Location:
|
|
|
1517
1524
|
def __init__(self, path, is_root=True):
|
|
1518
1525
|
self.path = path
|
|
1519
1526
|
self.is_not_root = not is_root
|
|
1520
|
-
self.
|
|
1527
|
+
self.children = {}
|
|
1521
1528
|
|
|
1522
1529
|
def child(self, tag):
|
|
1523
|
-
if tag not in self.
|
|
1524
|
-
self.
|
|
1530
|
+
if tag not in self.children:
|
|
1531
|
+
self.children[tag] = 1
|
|
1525
1532
|
else:
|
|
1526
|
-
self.
|
|
1527
|
-
tag += '[
|
|
1528
|
-
return Location('
|
|
1533
|
+
self.children[tag] += 1
|
|
1534
|
+
tag += f'[{self.children[tag]}]'
|
|
1535
|
+
return Location(f'{self.path}/{tag}', is_root=False)
|
|
@@ -27,5 +27,5 @@ the http://robotframework.org web site.
|
|
|
27
27
|
"""
|
|
28
28
|
|
|
29
29
|
STDLIBS = frozenset(('BuiltIn', 'Collections', 'DateTime', 'Dialogs', 'Easter',
|
|
30
|
-
'OperatingSystem', 'Process', 'Remote', '
|
|
31
|
-
'
|
|
30
|
+
'OperatingSystem', 'Process', 'Remote', 'Screenshot',
|
|
31
|
+
'String', 'Telnet', 'XML'))
|
|
@@ -27,6 +27,7 @@ class TkDialog(Toplevel):
|
|
|
27
27
|
def __init__(self, message, value=None, **config):
|
|
28
28
|
self._prevent_execution_with_timeouts()
|
|
29
29
|
self.root = self._get_root()
|
|
30
|
+
self._button_bindings = {}
|
|
30
31
|
super().__init__(self.root)
|
|
31
32
|
self._initialize_dialog()
|
|
32
33
|
self.widget = self._create_body(message, value, **config)
|
|
@@ -92,8 +93,9 @@ class TkDialog(Toplevel):
|
|
|
92
93
|
if label:
|
|
93
94
|
button = Button(parent, text=label, width=10, command=callback, underline=0)
|
|
94
95
|
button.pack(side=LEFT, padx=5, pady=5)
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
for char in label[0].upper(), label[0].lower():
|
|
97
|
+
self.bind(char, callback)
|
|
98
|
+
self._button_bindings[char] = callback
|
|
97
99
|
|
|
98
100
|
def _left_button_clicked(self, event=None):
|
|
99
101
|
if self._validate_value():
|
|
@@ -135,8 +137,18 @@ class InputDialog(TkDialog):
|
|
|
135
137
|
widget = Entry(parent, show='*' if hidden else '')
|
|
136
138
|
widget.insert(0, default)
|
|
137
139
|
widget.select_range(0, END)
|
|
140
|
+
widget.bind('<FocusIn>', self._unbind_buttons)
|
|
141
|
+
widget.bind('<FocusOut>', self._rebind_buttons)
|
|
138
142
|
return widget
|
|
139
143
|
|
|
144
|
+
def _unbind_buttons(self, event):
|
|
145
|
+
for char in self._button_bindings:
|
|
146
|
+
self.unbind(char)
|
|
147
|
+
|
|
148
|
+
def _rebind_buttons(self, event):
|
|
149
|
+
for char, callback in self._button_bindings.items():
|
|
150
|
+
self.bind(char, callback)
|
|
151
|
+
|
|
140
152
|
def _get_value(self) -> str:
|
|
141
153
|
return self.widget.get()
|
|
142
154
|
|
|
@@ -25,16 +25,16 @@ elsewhere.
|
|
|
25
25
|
This package is considered stable.
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
-
from .body import BaseBody, Body, BodyItem, BaseBranches
|
|
28
|
+
from .body import BaseBody, Body, BodyItem, BaseBranches, BaseIterations
|
|
29
29
|
from .configurer import SuiteConfigurer
|
|
30
|
-
from .control import Break, Continue, Error, For, If, IfBranch,
|
|
30
|
+
from .control import (Break, Continue, Error, For, ForIteration, If, IfBranch,
|
|
31
|
+
Return, Try, TryBranch, Var, While, WhileIteration)
|
|
31
32
|
from .fixture import create_fixture
|
|
32
33
|
from .itemlist import ItemList
|
|
33
|
-
from .keyword import
|
|
34
|
-
from .message import Message, Messages
|
|
34
|
+
from .keyword import Arguments, Keyword
|
|
35
|
+
from .message import Message, MessageLevel, Messages
|
|
35
36
|
from .modelobject import DataDict, ModelObject
|
|
36
37
|
from .modifier import ModelModifier
|
|
37
|
-
from .namepatterns import SuiteNamePatterns, TestNamePatterns
|
|
38
38
|
from .statistics import Statistics
|
|
39
39
|
from .tags import Tags, TagPattern, TagPatterns
|
|
40
40
|
from .testcase import TestCase, TestCases
|
|
@@ -23,10 +23,9 @@ from .itemlist import ItemList
|
|
|
23
23
|
from .modelobject import DataDict, full_name, ModelObject
|
|
24
24
|
|
|
25
25
|
if TYPE_CHECKING:
|
|
26
|
-
from robot.
|
|
27
|
-
from
|
|
28
|
-
|
|
29
|
-
Try, TryBranch, While)
|
|
26
|
+
from robot.running.model import ResourceFile, UserKeyword
|
|
27
|
+
from .control import (Break, Continue, Error, For, ForIteration, If, IfBranch,
|
|
28
|
+
Return, Try, TryBranch, Var, While, WhileIteration)
|
|
30
29
|
from .keyword import Keyword
|
|
31
30
|
from .message import Message
|
|
32
31
|
from .testcase import TestCase
|
|
@@ -35,19 +34,21 @@ if TYPE_CHECKING:
|
|
|
35
34
|
|
|
36
35
|
BodyItemParent = Union['TestSuite', 'TestCase', 'UserKeyword', 'For', 'ForIteration',
|
|
37
36
|
'If', 'IfBranch', 'Try', 'TryBranch', 'While', 'WhileIteration',
|
|
38
|
-
'Keyword', 'Return', 'Continue', 'Break', 'Error', None]
|
|
37
|
+
'Keyword', 'Var', 'Return', 'Continue', 'Break', 'Error', None]
|
|
39
38
|
BI = TypeVar('BI', bound='BodyItem')
|
|
40
39
|
KW = TypeVar('KW', bound='Keyword')
|
|
41
40
|
F = TypeVar('F', bound='For')
|
|
42
41
|
W = TypeVar('W', bound='While')
|
|
43
42
|
I = TypeVar('I', bound='If')
|
|
44
43
|
T = TypeVar('T', bound='Try')
|
|
44
|
+
V = TypeVar('V', bound='Var')
|
|
45
45
|
R = TypeVar('R', bound='Return')
|
|
46
46
|
C = TypeVar('C', bound='Continue')
|
|
47
47
|
B = TypeVar('B', bound='Break')
|
|
48
48
|
M = TypeVar('M', bound='Message')
|
|
49
49
|
E = TypeVar('E', bound='Error')
|
|
50
50
|
IT = TypeVar('IT', bound='IfBranch|TryBranch')
|
|
51
|
+
FW = TypeVar('FW', bound='ForIteration|WhileIteration')
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
class BodyItem(ModelObject):
|
|
@@ -65,11 +66,13 @@ class BodyItem(ModelObject):
|
|
|
65
66
|
EXCEPT = 'EXCEPT'
|
|
66
67
|
FINALLY = 'FINALLY'
|
|
67
68
|
WHILE = 'WHILE'
|
|
69
|
+
VAR = 'VAR'
|
|
68
70
|
RETURN = 'RETURN'
|
|
69
71
|
CONTINUE = 'CONTINUE'
|
|
70
72
|
BREAK = 'BREAK'
|
|
71
73
|
ERROR = 'ERROR'
|
|
72
74
|
MESSAGE = 'MESSAGE'
|
|
75
|
+
KEYWORD_TYPES = (KEYWORD, SETUP, TEARDOWN)
|
|
73
76
|
type = None
|
|
74
77
|
__slots__ = ['parent']
|
|
75
78
|
|
|
@@ -111,7 +114,7 @@ class BodyItem(ModelObject):
|
|
|
111
114
|
raise NotImplementedError
|
|
112
115
|
|
|
113
116
|
|
|
114
|
-
class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, R, C, B, M, E]):
|
|
117
|
+
class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, V, R, C, B, M, E]):
|
|
115
118
|
"""Base class for Body and Branches objects."""
|
|
116
119
|
__slots__ = []
|
|
117
120
|
# Set using 'BaseBody.register' when these classes are created.
|
|
@@ -120,6 +123,7 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, R, C, B, M, E]):
|
|
|
120
123
|
while_class: Type[W] = KnownAtRuntime
|
|
121
124
|
if_class: Type[I] = KnownAtRuntime
|
|
122
125
|
try_class: Type[T] = KnownAtRuntime
|
|
126
|
+
var_class: Type[V] = KnownAtRuntime
|
|
123
127
|
return_class: Type[R] = KnownAtRuntime
|
|
124
128
|
continue_class: Type[C] = KnownAtRuntime
|
|
125
129
|
break_class: Type[B] = KnownAtRuntime
|
|
@@ -132,7 +136,7 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, R, C, B, M, E]):
|
|
|
132
136
|
|
|
133
137
|
def _item_from_dict(self, data: DataDict) -> BodyItem:
|
|
134
138
|
item_type = data.get('type', None)
|
|
135
|
-
if
|
|
139
|
+
if item_type is None:
|
|
136
140
|
item_class = self.keyword_class
|
|
137
141
|
elif item_type == BodyItem.IF_ELSE_ROOT:
|
|
138
142
|
item_class = self.if_class
|
|
@@ -159,7 +163,7 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, R, C, B, M, E]):
|
|
|
159
163
|
f"Use item specific methods like 'create_keyword' instead."
|
|
160
164
|
)
|
|
161
165
|
|
|
162
|
-
def _create(self, cls: 'Type[BI]', name: str, args: 'tuple[Any]',
|
|
166
|
+
def _create(self, cls: 'Type[BI]', name: str, args: 'tuple[Any, ...]',
|
|
163
167
|
kwargs: 'dict[str, Any]') -> BI:
|
|
164
168
|
if cls is KnownAtRuntime:
|
|
165
169
|
raise TypeError(f"'{full_name(self)}' object does not support '{name}'.")
|
|
@@ -185,6 +189,10 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, R, C, B, M, E]):
|
|
|
185
189
|
def create_while(self, *args, **kwargs) -> while_class:
|
|
186
190
|
return self._create(self.while_class, 'create_while', args, kwargs)
|
|
187
191
|
|
|
192
|
+
@copy_signature(var_class)
|
|
193
|
+
def create_var(self, *args, **kwargs) -> var_class:
|
|
194
|
+
return self._create(self.var_class, 'create_var', args, kwargs)
|
|
195
|
+
|
|
188
196
|
@copy_signature(return_class)
|
|
189
197
|
def create_return(self, *args, **kwargs) -> return_class:
|
|
190
198
|
return self._create(self.return_class, 'create_return', args, kwargs)
|
|
@@ -267,8 +275,8 @@ class BaseBody(ItemList[BodyItem], Generic[KW, F, W, I, T, R, C, B, M, E]):
|
|
|
267
275
|
return steps
|
|
268
276
|
|
|
269
277
|
|
|
270
|
-
class Body(BaseBody['Keyword', 'For', 'While', 'If', 'Try', '
|
|
271
|
-
'Break', 'Message', 'Error']):
|
|
278
|
+
class Body(BaseBody['Keyword', 'For', 'While', 'If', 'Try', 'Var', 'Return',
|
|
279
|
+
'Continue', 'Break', 'Message', 'Error']):
|
|
272
280
|
"""A list-like object representing a body of a test, keyword, etc.
|
|
273
281
|
|
|
274
282
|
Body contains the keywords and other structures such as FOR loops.
|
|
@@ -276,19 +284,19 @@ class Body(BaseBody['Keyword', 'For', 'While', 'If', 'Try', 'Return', 'Continue'
|
|
|
276
284
|
pass
|
|
277
285
|
|
|
278
286
|
|
|
287
|
+
# BaseBranches cannot extend Generic[IT] directly with BaseBody[...].
|
|
279
288
|
class BranchType(Generic[IT]):
|
|
280
|
-
"""Class that wrapps `Generic` as python doesn't allow multple generic inheritance"""
|
|
281
289
|
pass
|
|
282
290
|
|
|
283
291
|
|
|
284
|
-
class BaseBranches(BaseBody[KW, F, W, I, T, R, C, B, M, E], BranchType[IT]):
|
|
292
|
+
class BaseBranches(BaseBody[KW, F, W, I, T, V, R, C, B, M, E], BranchType[IT]):
|
|
285
293
|
"""A list-like object representing IF and TRY branches."""
|
|
286
294
|
__slots__ = ['branch_class']
|
|
287
295
|
branch_type: Type[IT] = KnownAtRuntime
|
|
288
296
|
|
|
289
297
|
def __init__(self, branch_class: Type[IT],
|
|
290
298
|
parent: BodyItemParent = None,
|
|
291
|
-
items: 'Iterable[
|
|
299
|
+
items: 'Iterable[IT|DataDict]' = ()):
|
|
292
300
|
self.branch_class = branch_class
|
|
293
301
|
super().__init__(parent, items)
|
|
294
302
|
|
|
@@ -298,3 +306,26 @@ class BaseBranches(BaseBody[KW, F, W, I, T, R, C, B, M, E], BranchType[IT]):
|
|
|
298
306
|
@copy_signature(branch_type)
|
|
299
307
|
def create_branch(self, *args, **kwargs) -> IT:
|
|
300
308
|
return self._create(self.branch_class, 'create_branch', args, kwargs)
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
# BaseIterations cannot extend Generic[IT] directly with BaseBody[...].
|
|
312
|
+
class IterationType(Generic[FW]):
|
|
313
|
+
pass
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
class BaseIterations(BaseBody[KW, F, W, I, T, V, R, C, B, M, E], IterationType[FW]):
|
|
317
|
+
__slots__ = ['iteration_class']
|
|
318
|
+
iteration_type: Type[FW] = KnownAtRuntime
|
|
319
|
+
|
|
320
|
+
def __init__(self, iteration_class: Type[FW],
|
|
321
|
+
parent: BodyItemParent = None,
|
|
322
|
+
items: 'Iterable[FW|DataDict]' = ()):
|
|
323
|
+
self.iteration_class = iteration_class
|
|
324
|
+
super().__init__(parent, items)
|
|
325
|
+
|
|
326
|
+
def _item_from_dict(self, data: DataDict) -> FW:
|
|
327
|
+
return self.iteration_class.from_dict(data)
|
|
328
|
+
|
|
329
|
+
@copy_signature(iteration_type)
|
|
330
|
+
def create_iteration(self, *args, **kwargs) -> FW:
|
|
331
|
+
return self._create(self.iteration_class, 'iteration_class', args, kwargs)
|
|
@@ -59,29 +59,33 @@ class SuiteConfigurer(SuiteVisitor):
|
|
|
59
59
|
name = suite.name
|
|
60
60
|
suite.filter(self.include_suites, self.include_tests,
|
|
61
61
|
self.include_tags, self.exclude_tags)
|
|
62
|
-
if not (suite.
|
|
63
|
-
self.
|
|
62
|
+
if not (suite.has_tests or self.empty_suite_ok):
|
|
63
|
+
self._raise_no_tests_or_tasks_error(name, suite.rpa)
|
|
64
64
|
|
|
65
|
-
def
|
|
66
|
-
parts = ['tests'
|
|
65
|
+
def _raise_no_tests_or_tasks_error(self, name, rpa):
|
|
66
|
+
parts = [{False: 'tests', True: 'tasks', None: 'tests or tasks'}[rpa],
|
|
67
67
|
self._get_test_selector_msgs(),
|
|
68
68
|
self._get_suite_selector_msg()]
|
|
69
|
-
raise DataError("Suite '
|
|
70
|
-
|
|
69
|
+
raise DataError(f"Suite '{name}' contains no "
|
|
70
|
+
f"{' '.join(p for p in parts if p)}.")
|
|
71
71
|
|
|
72
72
|
def _get_test_selector_msgs(self):
|
|
73
73
|
parts = []
|
|
74
|
-
for explanation,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
for separator, explanation, selectors in [
|
|
75
|
+
(None, 'matching name', self.include_tests),
|
|
76
|
+
('or', 'matching tags', self.include_tags),
|
|
77
|
+
('and', 'not matching tags', self.exclude_tags)
|
|
78
|
+
]:
|
|
79
|
+
if selectors:
|
|
80
|
+
if parts:
|
|
81
|
+
parts.append(separator)
|
|
82
|
+
parts.append(self._format_selector_msg(explanation, selectors))
|
|
83
|
+
return ' '.join(parts)
|
|
80
84
|
|
|
81
|
-
def _format_selector_msg(self, explanation,
|
|
82
|
-
if len(
|
|
85
|
+
def _format_selector_msg(self, explanation, selectors):
|
|
86
|
+
if len(selectors) == 1 and explanation[-1] == 's':
|
|
83
87
|
explanation = explanation[:-1]
|
|
84
|
-
return
|
|
88
|
+
return f"{explanation} {seq2str(selectors, lastsep=' or ')}"
|
|
85
89
|
|
|
86
90
|
def _get_suite_selector_msg(self):
|
|
87
91
|
if not self.include_suites:
|