robotframework 6.1.1__zip → 7.0__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {robotframework-6.1.1 → robotframework-7.0}/INSTALL.rst +25 -25
- {robotframework-6.1.1 → robotframework-7.0}/PKG-INFO +6 -8
- {robotframework-6.1.1 → robotframework-7.0}/README.rst +3 -2
- {robotframework-6.1.1 → robotframework-7.0}/setup.py +3 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/__init__.py +4 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/deco.py +60 -14
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/exceptions.py +6 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/interfaces.py +402 -67
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/logger.py +27 -20
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/api/parsing.py +4 -2
- robotframework-7.0/src/robot/api/py.typed +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/gatherfailed.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/languages.py +0 -9
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/settings.py +21 -14
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/common/storage.js +11 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/htmlfilewriter.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.css +10 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/libdoc.html +10 -0
- robotframework-7.0/src/robot/htmldata/rebot/common.css +362 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/doc_formatting.css +13 -7
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/log.css +51 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/log.html +14 -23
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/model.js +2 -4
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/report.css +83 -19
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/report.html +22 -7
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/testdata.js +10 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/view.js +84 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/template.py +3 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/builder.py +0 -8
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/datatypes.py +9 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/htmlutils.py +4 -7
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/jsonbuilder.py +38 -20
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/model.py +21 -28
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/robotbuilder.py +50 -31
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/standardtypes.py +9 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/xmlbuilder.py +35 -20
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/xmlwriter.py +18 -38
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/BuiltIn.py +255 -205
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Collections.py +384 -240
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/DateTime.py +73 -60
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/OperatingSystem.py +6 -5
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Process.py +26 -27
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Remote.py +40 -36
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/String.py +66 -76
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/XML.py +66 -59
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/__init__.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/__init__.py +5 -5
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/body.py +44 -13
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/configurer.py +15 -11
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/control.py +226 -84
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/filter.py +31 -25
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/itemlist.py +9 -8
- robotframework-7.0/src/robot/model/keyword.py +77 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/message.py +19 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/modelobject.py +25 -7
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/namepatterns.py +3 -25
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/stats.py +9 -15
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/tags.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/testcase.py +15 -27
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/testsuite.py +17 -26
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/visitor.py +35 -8
- robotframework-7.0/src/robot/output/console/dotted.py +90 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/quiet.py +3 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/verbose.py +61 -61
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/debugfile.py +39 -24
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/filelogger.py +18 -15
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/librarylogger.py +3 -2
- robotframework-7.0/src/robot/output/listeners.py +753 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/logger.py +216 -80
- robotframework-7.0/src/robot/output/loggerapi.py +215 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/loggerhelper.py +23 -56
- robotframework-7.0/src/robot/output/output.py +185 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/stdoutlogsplitter.py +8 -5
- robotframework-7.0/src/robot/output/xmllogger.py +459 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/blocklexers.py +17 -13
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/context.py +12 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/lexer.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/settings.py +6 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/statementlexers.py +39 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/tokens.py +27 -29
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/model/blocks.py +19 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/model/statements.py +193 -94
- robotframework-7.0/src/robot/parsing/model/visitor.py +100 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/rebot.py +2 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/expandkeywordmatcher.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jsbuildingcontext.py +8 -6
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jsmodelbuilders.py +88 -61
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/logreportwriters.py +16 -10
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/outputwriter.py +18 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/resultwriter.py +4 -4
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/stringcache.py +3 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/xunitwriter.py +15 -21
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/__init__.py +3 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/configurer.py +12 -9
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/executionresult.py +56 -8
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/flattenkeywordmatcher.py +48 -9
- robotframework-7.0/src/robot/result/keywordremover.py +207 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/merger.py +1 -1
- robotframework-7.0/src/robot/result/model.py +1185 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/modeldeprecation.py +9 -3
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/resultbuilder.py +46 -36
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/xmlelementhandlers.py +83 -43
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/run.py +2 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/__init__.py +14 -4
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/__init__.py +2 -1
- robotframework-7.0/src/robot/running/arguments/argumentconverter.py +100 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentmapper.py +26 -24
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentparser.py +82 -60
- robotframework-7.0/src/robot/running/arguments/argumentresolver.py +158 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentspec.py +83 -116
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/argumentvalidator.py +33 -27
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/customconverters.py +15 -12
- robotframework-7.0/src/robot/running/arguments/embedded.py +145 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/arguments/typeconverters.py +233 -213
- robotframework-7.0/src/robot/running/arguments/typeinfo.py +317 -0
- robotframework-7.0/src/robot/running/arguments/typeinfoparser.py +219 -0
- robotframework-7.0/src/robot/running/arguments/typevalidator.py +60 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/bodyrunner.py +147 -129
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/builders.py +2 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/parsers.py +10 -11
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/settings.py +9 -17
- robotframework-7.0/src/robot/running/builder/transformers.py +535 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/context.py +113 -31
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/dynamicmethods.py +62 -34
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/importer.py +27 -49
- robotframework-7.0/src/robot/running/invalidkeyword.py +67 -0
- robotframework-7.0/src/robot/running/keywordfinder.py +91 -0
- robotframework-7.0/src/robot/running/keywordimplementation.py +164 -0
- robotframework-7.0/src/robot/running/librarykeyword.py +392 -0
- robotframework-7.0/src/robot/running/librarykeywordrunner.py +250 -0
- robotframework-7.0/src/robot/running/libraryscopes.py +115 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/model.py +195 -377
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/namespace.py +124 -137
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/outputcapture.py +20 -12
- robotframework-7.0/src/robot/running/resourcemodel.py +448 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/statusreporter.py +16 -13
- robotframework-7.0/src/robot/running/suiterunner.py +265 -0
- robotframework-7.0/src/robot/running/testlibraries.py +500 -0
- robotframework-7.0/src/robot/running/userkeywordrunner.py +260 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/testdoc.py +18 -13
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/__init__.py +53 -35
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/connectioncache.py +64 -59
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/dotdict.py +3 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/encodingsniffer.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/escaping.py +19 -19
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/importer.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/markupwriters.py +23 -15
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/misc.py +1 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/normalizing.py +9 -24
- robotframework-7.0/src/robot/utils/notset.py +33 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/platform.py +15 -5
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotio.py +9 -9
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotpath.py +1 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robottime.py +122 -90
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robottypes.py +21 -31
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/setter.py +0 -5
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/text.py +7 -4
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/unic.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/__init__.py +2 -2
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/assigner.py +17 -19
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/evaluation.py +20 -17
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/filesetter.py +80 -80
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/replacer.py +33 -36
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/scopes.py +17 -12
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/search.py +66 -41
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/store.py +14 -16
- robotframework-7.0/src/robot/variables/tablesetter.py +164 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/variables.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/version.py +1 -1
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/PKG-INFO +6 -8
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/SOURCES.txt +10 -8
- {robotframework-6.1.1 → robotframework-7.0}/tasks.py +6 -6
- robotframework-6.1.1/src/robot/htmldata/rebot/common.css +0 -239
- robotframework-6.1.1/src/robot/libraries/Reserved.py +0 -48
- robotframework-6.1.1/src/robot/model/keyword.py +0 -173
- robotframework-6.1.1/src/robot/output/console/dotted.py +0 -90
- robotframework-6.1.1/src/robot/output/listenerarguments.py +0 -165
- robotframework-6.1.1/src/robot/output/listenermethods.py +0 -113
- robotframework-6.1.1/src/robot/output/listeners.py +0 -174
- robotframework-6.1.1/src/robot/output/output.py +0 -95
- robotframework-6.1.1/src/robot/output/xmllogger.py +0 -354
- robotframework-6.1.1/src/robot/parsing/model/visitor.py +0 -67
- robotframework-6.1.1/src/robot/result/keywordremover.py +0 -183
- robotframework-6.1.1/src/robot/result/model.py +0 -957
- robotframework-6.1.1/src/robot/running/arguments/argumentconverter.py +0 -79
- robotframework-6.1.1/src/robot/running/arguments/argumentresolver.py +0 -131
- robotframework-6.1.1/src/robot/running/arguments/embedded.py +0 -146
- robotframework-6.1.1/src/robot/running/arguments/typevalidator.py +0 -56
- robotframework-6.1.1/src/robot/running/builder/transformers.py +0 -642
- robotframework-6.1.1/src/robot/running/handlers.py +0 -321
- robotframework-6.1.1/src/robot/running/handlerstore.py +0 -66
- robotframework-6.1.1/src/robot/running/librarykeywordrunner.py +0 -238
- robotframework-6.1.1/src/robot/running/libraryscopes.py +0 -97
- robotframework-6.1.1/src/robot/running/modelcombiner.py +0 -32
- robotframework-6.1.1/src/robot/running/suiterunner.py +0 -248
- robotframework-6.1.1/src/robot/running/testlibraries.py +0 -423
- robotframework-6.1.1/src/robot/running/usererrorhandler.py +0 -75
- robotframework-6.1.1/src/robot/running/userkeyword.py +0 -111
- robotframework-6.1.1/src/robot/running/userkeywordrunner.py +0 -274
- robotframework-6.1.1/src/robot/variables/tablesetter.py +0 -156
- {robotframework-6.1.1 → robotframework-7.0}/AUTHORS.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/BUILD.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/CONTRIBUTING.rst +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/COPYRIGHT.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/LICENSE.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/MANIFEST.in +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/setup.cfg +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/__main__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/conf/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/errors.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/common/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/common/js_disabled.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/jsonwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.highlight.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tablesorter.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jquery.tmpl.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/lib/jsxcompressor.min.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/doc_formatting.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/print.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/libdoc/pygments.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/fileloading.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/log.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/print.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/rebot/util.js +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/testdoc/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.css +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/htmldata/testdoc/testdoc.html +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdoc.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/consoleviewer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/htmlwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/jsonwriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/output.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libdocpkg/writer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Dialogs.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Easter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Screenshot.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/Telnet.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/libraries/dialogs_py.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/fixture.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/metadata.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/modifier.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/statistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/suitestatistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/tagsetter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/tagstatistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/model/totalstatistics.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/console/highlighting.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/output/pyloggingconf.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/lexer/tokenizer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/model/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/blockparsers.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/fileparser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/parser/parser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/parsing/suitestructure.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/pythonpathsetter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jsexecutionresult.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/reporting/jswriter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/executionerrors.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/messagefilter.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/suiteteardownfailed.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/result/visitor.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/builder/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/randomizer.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/runkwregister.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/signalhandler.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/status.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/timeouts/__init__.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/timeouts/posix.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/running/timeouts/windows.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/application.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/argumentparser.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/asserts.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/charwidth.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/compress.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/encoding.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/error.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/etreewrapper.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/filereader.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/frange.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/htmlformatters.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/markuputils.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/match.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/recommendations.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/restreader.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotenv.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/robotinspect.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/sortable.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/utils/typehints.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/finders.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/notfound.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robot/variables/resolvable.py +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/dependency_links.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/entry_points.txt +0 -0
- {robotframework-6.1.1 → robotframework-7.0}/src/robotframework.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
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 typing import Generic, Literal, overload, TypeVar, TYPE_CHECKING
|
|
17
|
+
|
|
18
|
+
from robot.utils import NormalizedDict, plural_or_not as s, seq2str
|
|
19
|
+
|
|
20
|
+
from .keywordimplementation import KeywordImplementation
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from .testlibraries import TestLibrary
|
|
24
|
+
from .resourcemodel import ResourceFile
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
K = TypeVar('K', bound=KeywordImplementation)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class KeywordFinder(Generic[K]):
|
|
31
|
+
|
|
32
|
+
def __init__(self, owner: 'TestLibrary|ResourceFile'):
|
|
33
|
+
self.owner = owner
|
|
34
|
+
self.cache: KeywordCache|None = None
|
|
35
|
+
|
|
36
|
+
@overload
|
|
37
|
+
def find(self, name: str, count: Literal[1]) -> 'K':
|
|
38
|
+
...
|
|
39
|
+
|
|
40
|
+
@overload
|
|
41
|
+
def find(self, name: str, count: 'int|None' = None) -> 'list[K]':
|
|
42
|
+
...
|
|
43
|
+
|
|
44
|
+
def find(self, name: str, count: 'int|None' = None) -> 'list[K]|K':
|
|
45
|
+
"""Find keywords based on the given ``name``.
|
|
46
|
+
|
|
47
|
+
With normal keywords matching is a case, space and underscore insensitive
|
|
48
|
+
string comparison and there cannot be more than one match. With keywords
|
|
49
|
+
accepting embedded arguments, matching is done against the name and
|
|
50
|
+
there can be multiple matches.
|
|
51
|
+
|
|
52
|
+
Returns matching keywords as a list, possibly as an empty list, without
|
|
53
|
+
any validation by default. If the optional ``count`` is used, raises
|
|
54
|
+
a ``ValueError`` if the number of found keywords does not match. If
|
|
55
|
+
``count`` is ``1`` and exactly one keyword is found, returns that keyword
|
|
56
|
+
directly and not as a list.
|
|
57
|
+
"""
|
|
58
|
+
if self.cache is None:
|
|
59
|
+
self.cache = KeywordCache[K](self.owner.keywords)
|
|
60
|
+
return self.cache.find(name, count)
|
|
61
|
+
|
|
62
|
+
def invalidate_cache(self):
|
|
63
|
+
self.cache = None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class KeywordCache(Generic[K]):
|
|
67
|
+
|
|
68
|
+
def __init__(self, keywords: 'list[K]'):
|
|
69
|
+
self.normal = NormalizedDict[K](ignore='_')
|
|
70
|
+
self.embedded: list[K] = []
|
|
71
|
+
add_normal = self.normal.__setitem__
|
|
72
|
+
add_embedded = self.embedded.append
|
|
73
|
+
for kw in keywords:
|
|
74
|
+
if kw.embedded:
|
|
75
|
+
add_embedded(kw)
|
|
76
|
+
else:
|
|
77
|
+
add_normal(kw.name, kw)
|
|
78
|
+
|
|
79
|
+
def find(self, name: str, count: 'int|None' = None) -> 'list[K]|K':
|
|
80
|
+
try:
|
|
81
|
+
keywords = [self.normal[name]]
|
|
82
|
+
except KeyError:
|
|
83
|
+
keywords = [kw for kw in self.embedded if kw.matches(name)]
|
|
84
|
+
if count is not None:
|
|
85
|
+
if len(keywords) != count:
|
|
86
|
+
names = ': ' + seq2str([kw.name for kw in keywords]) if keywords else '.'
|
|
87
|
+
raise ValueError(f"Expected {count} keyword{s(count)} matching name "
|
|
88
|
+
f"'{name}', found {len(keywords)}{names}")
|
|
89
|
+
if count == 1:
|
|
90
|
+
return keywords[0]
|
|
91
|
+
return keywords
|
|
@@ -0,0 +1,164 @@
|
|
|
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 pathlib import Path
|
|
17
|
+
from typing import Any, Literal, Sequence, TYPE_CHECKING
|
|
18
|
+
|
|
19
|
+
from robot.model import ModelObject, Tags
|
|
20
|
+
from robot.utils import eq, getshortdoc, setter
|
|
21
|
+
|
|
22
|
+
from .arguments import ArgInfo, ArgumentSpec, EmbeddedArguments
|
|
23
|
+
from .model import BodyItemParent, Keyword
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from .librarykeywordrunner import LibraryKeywordRunner
|
|
27
|
+
from .resourcemodel import ResourceFile
|
|
28
|
+
from .testlibraries import TestLibrary
|
|
29
|
+
from .userkeywordrunner import UserKeywordRunner
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class KeywordImplementation(ModelObject):
|
|
33
|
+
"""Base class for different keyword implementations."""
|
|
34
|
+
USER_KEYWORD = 'USER KEYWORD'
|
|
35
|
+
LIBRARY_KEYWORD = 'LIBRARY KEYWORD'
|
|
36
|
+
INVALID_KEYWORD = 'INVALID KEYWORD'
|
|
37
|
+
repr_args = ('name', 'args')
|
|
38
|
+
__slots__ = ['embedded', '_name', '_doc', '_lineno', 'owner', 'parent', 'error']
|
|
39
|
+
type: Literal['USER KEYWORD', 'LIBRARY KEYWORD', 'INVALID KEYWORD']
|
|
40
|
+
|
|
41
|
+
def __init__(self, name: str = '',
|
|
42
|
+
args: 'ArgumentSpec|None' = None,
|
|
43
|
+
doc: str = '',
|
|
44
|
+
tags: 'Tags|Sequence[str]' = (),
|
|
45
|
+
lineno: 'int|None' = None,
|
|
46
|
+
owner: 'ResourceFile|TestLibrary|None' = None,
|
|
47
|
+
parent: 'BodyItemParent|None' = None,
|
|
48
|
+
error: 'str|None' = None):
|
|
49
|
+
self._name = name
|
|
50
|
+
self.embedded = self._get_embedded(name)
|
|
51
|
+
self.args = args
|
|
52
|
+
self._doc = doc
|
|
53
|
+
self.tags = tags
|
|
54
|
+
self._lineno = lineno
|
|
55
|
+
self.owner = owner
|
|
56
|
+
self.parent = parent
|
|
57
|
+
self.error = error
|
|
58
|
+
|
|
59
|
+
def _get_embedded(self, name) -> 'EmbeddedArguments|None':
|
|
60
|
+
return EmbeddedArguments.from_name(name)
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def name(self) -> str:
|
|
64
|
+
return self._name
|
|
65
|
+
|
|
66
|
+
@name.setter
|
|
67
|
+
def name(self, name: str):
|
|
68
|
+
self.embedded = self._get_embedded(name)
|
|
69
|
+
if self.owner and self._name:
|
|
70
|
+
self.owner.keyword_finder.invalidate_cache()
|
|
71
|
+
self._name = name
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def full_name(self) -> str:
|
|
75
|
+
if self.owner and self.owner.name:
|
|
76
|
+
return f'{self.owner.name}.{self.name}'
|
|
77
|
+
return self.name
|
|
78
|
+
|
|
79
|
+
@setter
|
|
80
|
+
def args(self, spec: 'ArgumentSpec|None') -> ArgumentSpec:
|
|
81
|
+
"""Information about accepted arguments.
|
|
82
|
+
|
|
83
|
+
It would be more correct to use term *parameter* instead of
|
|
84
|
+
*argument* in this context, and this attribute may be renamed
|
|
85
|
+
accordingly in the future. A forward compatible :attr:`params`
|
|
86
|
+
attribute exists already now.
|
|
87
|
+
"""
|
|
88
|
+
if spec is None:
|
|
89
|
+
spec = ArgumentSpec()
|
|
90
|
+
spec.name = lambda: self.full_name
|
|
91
|
+
return spec
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def params(self) -> ArgumentSpec:
|
|
95
|
+
"""Keyword parameter information.
|
|
96
|
+
|
|
97
|
+
This is a forward compatible alias for :attr:`args`.
|
|
98
|
+
"""
|
|
99
|
+
return self.args
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def doc(self) -> str:
|
|
103
|
+
return self._doc
|
|
104
|
+
|
|
105
|
+
@doc.setter
|
|
106
|
+
def doc(self, doc: str):
|
|
107
|
+
self._doc = doc
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def short_doc(self) -> str:
|
|
111
|
+
return getshortdoc(self.doc)
|
|
112
|
+
|
|
113
|
+
@setter
|
|
114
|
+
def tags(self, tags: 'Tags|Sequence[str]') -> Tags:
|
|
115
|
+
return Tags(tags)
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def lineno(self) -> 'int|None':
|
|
119
|
+
return self._lineno
|
|
120
|
+
|
|
121
|
+
@lineno.setter
|
|
122
|
+
def lineno(self, lineno: 'int|None'):
|
|
123
|
+
self._lineno = lineno
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def private(self) -> bool:
|
|
127
|
+
return bool(self.tags and self.tags.robot('private'))
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def source(self) -> 'Path|None':
|
|
131
|
+
return self.owner.source if self.owner is not None else None
|
|
132
|
+
|
|
133
|
+
def matches(self, name: str) -> bool:
|
|
134
|
+
"""Returns true if ``name`` matches the keyword name.
|
|
135
|
+
|
|
136
|
+
With normal keywords matching is a case, space and underscore insensitive
|
|
137
|
+
string comparison. With keywords accepting embedded arguments, matching
|
|
138
|
+
is done against the name.
|
|
139
|
+
"""
|
|
140
|
+
if self.embedded:
|
|
141
|
+
return self.embedded.match(name) is not None
|
|
142
|
+
return eq(self.name, name, ignore='_')
|
|
143
|
+
|
|
144
|
+
def resolve_arguments(self, args: Sequence[str], variables=None,
|
|
145
|
+
languages=None) -> 'tuple[list, list]':
|
|
146
|
+
return self.args.resolve(args, variables, languages=languages)
|
|
147
|
+
|
|
148
|
+
def create_runner(self, name: 'str|None', languages=None) \
|
|
149
|
+
-> 'LibraryKeywordRunner|UserKeywordRunner':
|
|
150
|
+
raise NotImplementedError
|
|
151
|
+
|
|
152
|
+
def bind(self, data: Keyword) -> 'KeywordImplementation':
|
|
153
|
+
raise NotImplementedError
|
|
154
|
+
|
|
155
|
+
def _include_in_repr(self, name: str, value: Any) -> bool:
|
|
156
|
+
return name == 'name' or value
|
|
157
|
+
|
|
158
|
+
def _repr_format(self, name: str, value: Any) -> str:
|
|
159
|
+
if name == 'args':
|
|
160
|
+
value = [self._decorate_arg(a) for a in self.args]
|
|
161
|
+
return super()._repr_format(name, value)
|
|
162
|
+
|
|
163
|
+
def _decorate_arg(self, arg: ArgInfo) -> str:
|
|
164
|
+
return str(arg)
|
|
@@ -0,0 +1,392 @@
|
|
|
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
|
+
import inspect
|
|
17
|
+
from os.path import normpath
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Any, Callable, Generic, Sequence, TypeVar, TYPE_CHECKING
|
|
20
|
+
|
|
21
|
+
from robot.model import Tags
|
|
22
|
+
from robot.errors import DataError
|
|
23
|
+
from robot.utils import (is_init, is_list_like, printable_name, split_tags_from_doc,
|
|
24
|
+
type_name)
|
|
25
|
+
|
|
26
|
+
from .arguments import ArgumentSpec, DynamicArgumentParser, PythonArgumentParser
|
|
27
|
+
from .dynamicmethods import (GetKeywordArguments, GetKeywordDocumentation,
|
|
28
|
+
GetKeywordTags, GetKeywordTypes, GetKeywordSource,
|
|
29
|
+
RunKeyword)
|
|
30
|
+
from .model import BodyItemParent, Keyword
|
|
31
|
+
from .keywordimplementation import KeywordImplementation
|
|
32
|
+
from .librarykeywordrunner import EmbeddedArgumentsRunner, LibraryKeywordRunner, RunKeywordRunner
|
|
33
|
+
from .runkwregister import RUN_KW_REGISTER
|
|
34
|
+
|
|
35
|
+
if TYPE_CHECKING:
|
|
36
|
+
from .testlibraries import DynamicLibrary, TestLibrary
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
Self = TypeVar('Self', bound='LibraryKeyword')
|
|
40
|
+
K = TypeVar('K', bound='LibraryKeyword')
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class LibraryKeyword(KeywordImplementation):
|
|
44
|
+
"""Base class for different library keywords."""
|
|
45
|
+
type = KeywordImplementation.LIBRARY_KEYWORD
|
|
46
|
+
owner: 'TestLibrary'
|
|
47
|
+
__slots__ = ['_resolve_args_until']
|
|
48
|
+
|
|
49
|
+
def __init__(self, owner: 'TestLibrary',
|
|
50
|
+
name: str = '',
|
|
51
|
+
args: 'ArgumentSpec|None' = None,
|
|
52
|
+
doc: str = '',
|
|
53
|
+
tags: 'Tags|Sequence[str]' = (),
|
|
54
|
+
resolve_args_until: 'int|None' = None,
|
|
55
|
+
parent: 'BodyItemParent|None' = None,
|
|
56
|
+
error: 'str|None' = None):
|
|
57
|
+
super().__init__(name, args, doc, tags, owner=owner, parent=parent, error=error)
|
|
58
|
+
self._resolve_args_until = resolve_args_until
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def method(self) -> Callable[..., Any]:
|
|
62
|
+
raise NotImplementedError
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def lineno(self) -> 'int|None':
|
|
66
|
+
method = self.method
|
|
67
|
+
try:
|
|
68
|
+
lines, start_lineno = inspect.getsourcelines(inspect.unwrap(method))
|
|
69
|
+
except (TypeError, OSError, IOError):
|
|
70
|
+
return None
|
|
71
|
+
for increment, line in enumerate(lines):
|
|
72
|
+
if line.strip().startswith('def '):
|
|
73
|
+
return start_lineno + increment
|
|
74
|
+
return start_lineno
|
|
75
|
+
|
|
76
|
+
def create_runner(self, name: 'str|None', languages=None) -> LibraryKeywordRunner:
|
|
77
|
+
if self.embedded:
|
|
78
|
+
return EmbeddedArgumentsRunner(self, name)
|
|
79
|
+
if self._resolve_args_until is not None:
|
|
80
|
+
dry_run = RUN_KW_REGISTER.get_dry_run(self.owner.real_name, self.name)
|
|
81
|
+
return RunKeywordRunner(self, execute_in_dry_run=dry_run)
|
|
82
|
+
return LibraryKeywordRunner(self, languages=languages)
|
|
83
|
+
|
|
84
|
+
def resolve_arguments(self, args: Sequence[str], variables=None,
|
|
85
|
+
languages=None) -> 'tuple[list, list]':
|
|
86
|
+
resolve_args_until = self._resolve_args_until
|
|
87
|
+
positional, named = self.args.resolve(args, variables, self.owner.converters,
|
|
88
|
+
resolve_named=resolve_args_until is None,
|
|
89
|
+
resolve_args_until=resolve_args_until,
|
|
90
|
+
languages=languages)
|
|
91
|
+
if self.embedded:
|
|
92
|
+
self.embedded.validate(positional)
|
|
93
|
+
return positional, named
|
|
94
|
+
|
|
95
|
+
def bind(self: Self, data: Keyword) -> Self:
|
|
96
|
+
return self.copy(parent=data.parent)
|
|
97
|
+
|
|
98
|
+
def copy(self: Self, **attributes) -> Self:
|
|
99
|
+
raise NotImplementedError
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class StaticKeyword(LibraryKeyword):
|
|
103
|
+
"""Represents a keyword in a static library."""
|
|
104
|
+
__slots__ = ['method_name']
|
|
105
|
+
|
|
106
|
+
def __init__(self, method_name: str,
|
|
107
|
+
owner: 'TestLibrary',
|
|
108
|
+
name: str = '',
|
|
109
|
+
args: 'ArgumentSpec|None' = None,
|
|
110
|
+
doc: str = '',
|
|
111
|
+
tags: 'Tags|Sequence[str]' = (),
|
|
112
|
+
resolve_args_until: 'int|None' = None,
|
|
113
|
+
parent: 'BodyItemParent|None' = None,
|
|
114
|
+
error: 'str|None' = None):
|
|
115
|
+
super().__init__(owner, name, args, doc, tags, resolve_args_until, parent, error)
|
|
116
|
+
self.method_name = method_name
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def method(self) -> Callable[..., Any]:
|
|
120
|
+
"""Keyword method."""
|
|
121
|
+
return getattr(self.owner.instance, self.method_name)
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def source(self) -> 'Path|None':
|
|
125
|
+
# `getsourcefile` can return None and raise TypeError.
|
|
126
|
+
try:
|
|
127
|
+
if self.method is None:
|
|
128
|
+
raise TypeError
|
|
129
|
+
source = inspect.getsourcefile(inspect.unwrap(self.method))
|
|
130
|
+
except TypeError:
|
|
131
|
+
source = None
|
|
132
|
+
return Path(normpath(source)) if source else super().source
|
|
133
|
+
|
|
134
|
+
@classmethod
|
|
135
|
+
def from_name(cls, name: str, owner: 'TestLibrary') -> 'StaticKeyword':
|
|
136
|
+
return StaticKeywordCreator(name, owner).create(method_name=name)
|
|
137
|
+
|
|
138
|
+
def copy(self, **attributes) -> 'StaticKeyword':
|
|
139
|
+
return StaticKeyword(self.method_name, self.owner, self.name, self.args,
|
|
140
|
+
self._doc, self.tags, self._resolve_args_until,
|
|
141
|
+
self.parent, self.error).config(**attributes)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class DynamicKeyword(LibraryKeyword):
|
|
145
|
+
"""Represents a keyword in a dynamic library."""
|
|
146
|
+
owner: 'DynamicLibrary'
|
|
147
|
+
__slots__ = ['run_keyword', '_orig_name', '__source_info']
|
|
148
|
+
|
|
149
|
+
def __init__(self, owner: 'DynamicLibrary',
|
|
150
|
+
name: str = '',
|
|
151
|
+
args: 'ArgumentSpec|None' = None,
|
|
152
|
+
doc: str = '',
|
|
153
|
+
tags: 'Tags|Sequence[str]' = (),
|
|
154
|
+
resolve_args_until: 'int|None' = None,
|
|
155
|
+
parent: 'BodyItemParent|None' = None,
|
|
156
|
+
error: 'str|None' = None):
|
|
157
|
+
# TODO: It would probably be better not to convert name we got from
|
|
158
|
+
# `get_keyword_names`. That would have some backwards incompatibility
|
|
159
|
+
# effects, but we can consider it in RF 8.0.
|
|
160
|
+
super().__init__(owner, printable_name(name, code_style=True), args, doc,
|
|
161
|
+
tags, resolve_args_until, parent, error)
|
|
162
|
+
self._orig_name = name
|
|
163
|
+
self.__source_info = None
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def method(self) -> Callable[..., Any]:
|
|
167
|
+
"""Dynamic ``run_keyword`` method."""
|
|
168
|
+
return RunKeyword(self.owner.instance, self._orig_name,
|
|
169
|
+
self.owner.supports_named_args)
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def source(self) -> 'Path|None':
|
|
173
|
+
return self._source_info[0] or super().source
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def lineno(self) -> 'int|None':
|
|
177
|
+
return self._source_info[1]
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def _source_info(self) -> 'tuple[Path|None, int]':
|
|
181
|
+
if not self.__source_info:
|
|
182
|
+
get_keyword_source = GetKeywordSource(self.owner.instance)
|
|
183
|
+
try:
|
|
184
|
+
source = get_keyword_source(self._orig_name)
|
|
185
|
+
except DataError as err:
|
|
186
|
+
source = None
|
|
187
|
+
self.owner.report_error(f"Getting source information for keyword "
|
|
188
|
+
f"'{self.name}' failed: {err}", err.details)
|
|
189
|
+
if source and ':' in source and source.rsplit(':', 1)[1].isdigit():
|
|
190
|
+
source, lineno = source.rsplit(':', 1)
|
|
191
|
+
lineno = int(lineno)
|
|
192
|
+
else:
|
|
193
|
+
lineno = None
|
|
194
|
+
self.__source_info = Path(normpath(source)) if source else None, lineno
|
|
195
|
+
return self.__source_info
|
|
196
|
+
|
|
197
|
+
@classmethod
|
|
198
|
+
def from_name(cls, name: str, owner: 'DynamicLibrary') -> 'DynamicKeyword':
|
|
199
|
+
return DynamicKeywordCreator(name, owner).create()
|
|
200
|
+
|
|
201
|
+
def resolve_arguments(self, arguments, variables=None,
|
|
202
|
+
languages=None) -> 'tuple[list, list]':
|
|
203
|
+
positional, named = super().resolve_arguments(arguments, variables, languages)
|
|
204
|
+
if not self.owner.supports_named_args:
|
|
205
|
+
positional, named = self.args.map(positional, named)
|
|
206
|
+
return positional, named
|
|
207
|
+
|
|
208
|
+
def copy(self, **attributes) -> 'DynamicKeyword':
|
|
209
|
+
return DynamicKeyword(self.owner, self._orig_name, self.args, self._doc,
|
|
210
|
+
self.tags, self._resolve_args_until, self.parent,
|
|
211
|
+
self.error).config(**attributes)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class LibraryInit(LibraryKeyword):
|
|
215
|
+
"""Represents a library initializer.
|
|
216
|
+
|
|
217
|
+
:attr:`positional` and :attr:`named` contain arguments used for initializing
|
|
218
|
+
the library.
|
|
219
|
+
"""
|
|
220
|
+
|
|
221
|
+
def __init__(self, owner: 'TestLibrary',
|
|
222
|
+
name: str = '',
|
|
223
|
+
args: 'ArgumentSpec|None' = None,
|
|
224
|
+
doc: str = '',
|
|
225
|
+
tags: 'Tags|Sequence[str]' = (),
|
|
226
|
+
positional: 'list|None' = None,
|
|
227
|
+
named: 'dict|None' = None):
|
|
228
|
+
super().__init__(owner, name, args, doc, tags)
|
|
229
|
+
self.positional = positional or []
|
|
230
|
+
self.named = named or {}
|
|
231
|
+
|
|
232
|
+
@property
|
|
233
|
+
def doc(self) -> str:
|
|
234
|
+
from .testlibraries import DynamicLibrary
|
|
235
|
+
if isinstance(self.owner, DynamicLibrary):
|
|
236
|
+
doc = GetKeywordDocumentation(self.owner.instance)('__init__')
|
|
237
|
+
if doc:
|
|
238
|
+
return doc
|
|
239
|
+
return self._doc
|
|
240
|
+
|
|
241
|
+
@doc.setter
|
|
242
|
+
def doc(self, doc: str):
|
|
243
|
+
self._doc = doc
|
|
244
|
+
|
|
245
|
+
@property
|
|
246
|
+
def method(self) -> 'Callable[..., None]|None':
|
|
247
|
+
"""Initializer method.
|
|
248
|
+
|
|
249
|
+
``None`` with module based libraries and when class based libraries
|
|
250
|
+
do not have ``__init__``.
|
|
251
|
+
"""
|
|
252
|
+
return getattr(self.owner.instance, '__init__', None)
|
|
253
|
+
|
|
254
|
+
@classmethod
|
|
255
|
+
def from_class(cls, klass) -> 'LibraryInit':
|
|
256
|
+
method = getattr(klass, '__init__', None)
|
|
257
|
+
return LibraryInitCreator(method).create()
|
|
258
|
+
|
|
259
|
+
@classmethod
|
|
260
|
+
def null(cls) -> 'LibraryInit':
|
|
261
|
+
return LibraryInitCreator(None).create()
|
|
262
|
+
|
|
263
|
+
def copy(self, **attributes) -> 'LibraryInit':
|
|
264
|
+
return LibraryInit(self.owner, self.name, self.args, self._doc, self.tags,
|
|
265
|
+
self.positional, self.named).config(**attributes)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class KeywordCreator(Generic[K]):
|
|
269
|
+
keyword_class: 'type[K]'
|
|
270
|
+
|
|
271
|
+
def __init__(self, name: str, library: 'TestLibrary|None' = None):
|
|
272
|
+
self.name = name
|
|
273
|
+
self.library = library
|
|
274
|
+
self.extra = {}
|
|
275
|
+
if library and RUN_KW_REGISTER.is_run_keyword(library.real_name, name):
|
|
276
|
+
resolve_until = RUN_KW_REGISTER.get_args_to_process(library.real_name, name)
|
|
277
|
+
self.extra['resolve_args_until'] = resolve_until
|
|
278
|
+
|
|
279
|
+
@property
|
|
280
|
+
def instance(self) -> Any:
|
|
281
|
+
return self.library.instance
|
|
282
|
+
|
|
283
|
+
def create(self, **extra) -> K:
|
|
284
|
+
tags = self.get_tags()
|
|
285
|
+
doc, doc_tags = split_tags_from_doc(self.get_doc())
|
|
286
|
+
kw = self.keyword_class(
|
|
287
|
+
owner=self.library,
|
|
288
|
+
name=self.get_name(),
|
|
289
|
+
args=self.get_args(),
|
|
290
|
+
doc=doc,
|
|
291
|
+
tags=tags + doc_tags,
|
|
292
|
+
**self.extra,
|
|
293
|
+
**extra
|
|
294
|
+
)
|
|
295
|
+
kw.args.name = lambda: kw.full_name
|
|
296
|
+
return kw
|
|
297
|
+
|
|
298
|
+
def get_name(self) -> str:
|
|
299
|
+
raise NotImplementedError
|
|
300
|
+
|
|
301
|
+
def get_args(self) -> ArgumentSpec:
|
|
302
|
+
raise NotImplementedError
|
|
303
|
+
|
|
304
|
+
def get_doc(self) -> str:
|
|
305
|
+
raise NotImplementedError
|
|
306
|
+
|
|
307
|
+
def get_tags(self) -> 'list[str]':
|
|
308
|
+
raise NotImplementedError
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
class StaticKeywordCreator(KeywordCreator[StaticKeyword]):
|
|
312
|
+
keyword_class = StaticKeyword
|
|
313
|
+
|
|
314
|
+
def __init__(self, name: str, library: 'TestLibrary'):
|
|
315
|
+
super().__init__(name, library)
|
|
316
|
+
self.method = getattr(library.instance, name)
|
|
317
|
+
|
|
318
|
+
def get_name(self) -> str:
|
|
319
|
+
robot_name = getattr(self.method, 'robot_name', None)
|
|
320
|
+
name = robot_name or printable_name(self.name, code_style=True)
|
|
321
|
+
if not name:
|
|
322
|
+
raise DataError('Keyword name cannot be empty.')
|
|
323
|
+
return name
|
|
324
|
+
|
|
325
|
+
def get_args(self) -> ArgumentSpec:
|
|
326
|
+
return PythonArgumentParser().parse(self.method)
|
|
327
|
+
|
|
328
|
+
def get_doc(self) -> str:
|
|
329
|
+
return inspect.getdoc(self.method) or ''
|
|
330
|
+
|
|
331
|
+
def get_tags(self) -> 'list[str]':
|
|
332
|
+
tags = getattr(self.method, 'robot_tags', ())
|
|
333
|
+
if not is_list_like(tags):
|
|
334
|
+
raise DataError(f"Expected tags to be list-like, got {type_name(tags)}.")
|
|
335
|
+
return list(tags)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
class DynamicKeywordCreator(KeywordCreator[DynamicKeyword]):
|
|
339
|
+
keyword_class = DynamicKeyword
|
|
340
|
+
library: 'DynamicLibrary'
|
|
341
|
+
|
|
342
|
+
def get_name(self) -> str:
|
|
343
|
+
return self.name
|
|
344
|
+
|
|
345
|
+
def get_args(self) -> ArgumentSpec:
|
|
346
|
+
supports_named_args = self.library.supports_named_args
|
|
347
|
+
get_keyword_arguments = GetKeywordArguments(self.instance, supports_named_args)
|
|
348
|
+
spec = DynamicArgumentParser().parse(get_keyword_arguments(self.name))
|
|
349
|
+
if not supports_named_args:
|
|
350
|
+
name = RunKeyword(self.instance).name
|
|
351
|
+
if spec.named_only:
|
|
352
|
+
raise DataError(f"Too few '{name}' method parameters to support "
|
|
353
|
+
f"named-only arguments.")
|
|
354
|
+
if spec.var_named:
|
|
355
|
+
raise DataError(f"Too few '{name}' method parameters to support "
|
|
356
|
+
f"free named arguments.")
|
|
357
|
+
types = GetKeywordTypes(self.instance)(self.name)
|
|
358
|
+
if isinstance(types, dict) and 'return' in types:
|
|
359
|
+
spec.return_type = types.pop('return')
|
|
360
|
+
spec.types = types
|
|
361
|
+
return spec
|
|
362
|
+
|
|
363
|
+
def get_doc(self) -> str:
|
|
364
|
+
return GetKeywordDocumentation(self.instance)(self.name)
|
|
365
|
+
|
|
366
|
+
def get_tags(self) -> 'list[str]':
|
|
367
|
+
return GetKeywordTags(self.instance)(self.name)
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
class LibraryInitCreator(KeywordCreator[LibraryInit]):
|
|
371
|
+
keyword_class = LibraryInit
|
|
372
|
+
|
|
373
|
+
def __init__(self, method: 'Callable[..., None]|None'):
|
|
374
|
+
super().__init__('__init__')
|
|
375
|
+
self.method = method if is_init(method) else lambda: None
|
|
376
|
+
|
|
377
|
+
def create(self, **extra) -> LibraryInit:
|
|
378
|
+
init = super().create(**extra)
|
|
379
|
+
init.args.name = lambda: init.owner.name
|
|
380
|
+
return init
|
|
381
|
+
|
|
382
|
+
def get_name(self) -> str:
|
|
383
|
+
return self.name
|
|
384
|
+
|
|
385
|
+
def get_args(self) -> ArgumentSpec:
|
|
386
|
+
return PythonArgumentParser('Library').parse(self.method)
|
|
387
|
+
|
|
388
|
+
def get_doc(self) -> str:
|
|
389
|
+
return inspect.getdoc(self.method) or ''
|
|
390
|
+
|
|
391
|
+
def get_tags(self) -> 'list[str]':
|
|
392
|
+
return []
|