Implementation:MarketSquare Robotframework browser PluginParser Parse Plugins
PluginParser.parse_plugins
Type
Wrapper Doc (wraps robotlibcore.PluginParser)
Source
Browser/browser.py, lines 894-900
External Dependency
from robotlibcore import DynamicCore, PluginParser # type: ignore
PluginParser is provided by the robotlibcore package, which is a dependency of the Browser library.
API Call in Context
The following code executes during Browser.__init__:
if plugins:
parser = PluginParser(LibraryComponent, [self])
parsed_plugins = parser.parse_plugins(plugins)
libraries.extend(parsed_plugins)
self._plugin_keywords = parser.get_plugin_keywords(parsed_plugins)
else:
self._plugin_keywords = []
PluginParser Constructor
PluginParser(base_class, call_args)
| Parameter | Value in Browser | Description |
|---|---|---|
base_class |
LibraryComponent |
The required base class for all plugins. PluginParser validates that each discovered plugin class is a subclass of this.
|
call_args |
[self] (the Browser instance) |
A list of arguments to pass to each plugin constructor. Since LibraryComponent.__init__ expects a single Browser argument, the list contains only the library instance itself.
|
parse_plugins Method
parser.parse_plugins(plugins) -> list[LibraryComponent]
| Parameter | Type | Description |
|---|---|---|
plugins |
list[str] | Plugin specification string. Supports multiple formats (see below). |
Returns: A list of instantiated plugin objects, each an instance of a class that inherits from LibraryComponent.
Plugin Specification Format
The plugins argument supports several specification formats:
Single Plugin by Module Path
mypackage.mymodule.MyPlugin
PluginParser imports mypackage.mymodule and instantiates MyPlugin.
Single Plugin by File Path
/path/to/MyPlugin.py
PluginParser loads the module from the file path. The class is expected to have the same name as the file (without extension) or be the first LibraryComponent subclass found.
Plugin with Extra Arguments
mypackage.MyPlugin;arg1;arg2
The semicolon ; separates the plugin path from additional constructor arguments. These are appended after the mandatory library argument:
# PluginParser effectively calls:
MyPlugin(browser_instance, "arg1", "arg2")
This requires the plugin constructor to accept additional parameters:
class MyPlugin(LibraryComponent):
def __init__(self, library: Browser, config_path: str, mode: str):
super().__init__(library)
self.config = load_config(config_path)
self.mode = mode
Multiple Plugins (Comma-Separated)
mypackage.PluginA,mypackage.PluginB;arg1,another.PluginC
Commas separate distinct plugin specifications. Each specification is processed independently.
get_plugin_keywords Method
parser.get_plugin_keywords(parsed_plugins) -> list[str]
| Parameter | Type | Description |
|---|---|---|
parsed_plugins |
list[LibraryComponent] |
The list of instantiated plugin objects returned by parse_plugins.
|
Returns: A list of keyword method names from the plugin instances. These are the names of methods that have been decorated with @keyword.
This list is stored as self._plugin_keywords on the Browser instance and used by get_keyword_tags() to auto-tag plugin keywords with "Plugin".
Integration with DynamicCore
After plugins are parsed and added to the libraries list, DynamicCore.__init__ is called:
# Browser.__init__ continues after plugin loading:
DynamicCore.__init__(self, libraries, translation_file)
DynamicCore iterates over all components in the libraries list, discovers @keyword-decorated methods, and builds the keyword-to-method mapping that Robot Framework uses at runtime.
Usage in Robot Framework Test Files
Single Plugin
*** Settings ***
Library Browser plugins=${CURDIR}/MyPlugin.py
Multiple Plugins
*** Settings ***
Library Browser plugins=${CURDIR}/PluginA.py,${CURDIR}/PluginB.py
Plugin with Arguments
*** Settings ***
Library Browser plugins=mypackage.MyPlugin;${CONFIG};debug
Plugin via Python
from Browser import Browser
browser = Browser(plugins="mypackage.MyPlugin;arg1")
Plugin Keyword Tagging (get_keyword_tags)
From Browser/browser.py lines 1301-1305:
def get_keyword_tags(self, name: str) -> list:
tags = list(DynamicCore.get_keyword_tags(self, name))
if name in self._plugin_keywords:
tags.append("Plugin")
return tags
This method is called by Robot Framework for each keyword. If the keyword name is in the _plugin_keywords list (populated by get_plugin_keywords), the "Plugin" tag is appended to whatever tags the keyword already has.
Sequence Diagram
Robot Framework Browser.__init__ PluginParser
| | |
| Library Browser plugins=X | |
|------------------------------>| |
| | PluginParser(LC, [self]) |
| |--------------------------->|
| | |
| | parse_plugins("X") |
| |--------------------------->|
| | | import module
| | | validate class
| | | instantiate(self)
| |<-- [plugin_instances] -----|
| | |
| | get_plugin_keywords(...) |
| |--------------------------->|
| |<-- [keyword_names] --------|
| | |
| | DynamicCore.__init__(libs) |
| | |
Related
- MarketSquare_Robotframework_browser_Plugin_Loading_Mechanism -- Principle: how dynamic plugin loading works
- MarketSquare_Robotframework_browser_LibraryComponent_Init -- The base class required for all plugins
- MarketSquare_Robotframework_browser_Keyword_Decorator_Pattern -- How plugin keyword methods are defined