script_builder.py
ofrak.gui.script_builder
ActionType (IntEnum)
An enumeration.
ScriptAction
dataclass
Encapsulates the structure of a single action within the script, which consists of the string representation of the code for that action and the action's type.
ScriptBuilder
Builds and maintains runnable OFRAK scripts as sequences of actions, with each script tied to a session.
add_action(self, resource, action, action_type)
async
Adds an action to the script session queue to which the selected resource belongs. An action is a string representing the code that is being run on the resource based on an action that has occurred in the GUI.
Actions are queued so that invalid actions which result in runtime exceptions within OFRAK
do not make it into the final script. Once an action is queued and the corresponding OFRAK
calls have run, the caller must explicitly call clear_script_queue
or commit_to_script
depending on whether an exception was raised or not, respectively.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
resource |
Resource |
Resource upon which the action is being taken |
required |
action |
str |
A string describing the code being run based on a GUI action |
required |
action_type |
ActionType |
An instance of |
required |
Source code in ofrak/gui/script_builder.py
async def add_action(
self,
resource: Resource,
action: str,
action_type: ActionType,
) -> None:
"""
Adds an action to the script session queue to which the selected resource belongs. An action
is a string representing the code that is being run on the resource based on an action that
has occurred in the GUI.
Actions are queued so that invalid actions which result in runtime exceptions within OFRAK
do not make it into the final script. Once an action is queued and the corresponding OFRAK
calls have run, the caller must explicitly call `clear_script_queue` or `commit_to_script`
depending on whether an exception was raised or not, respectively.
:param resource: Resource upon which the action is being taken
:param action: A string describing the code being run based on a GUI action
:param action_type: An instance of `ActionType` categorizing the action
"""
var_name = await self._add_variable(resource)
qualified_action = action.format(resource=var_name)
await self._add_action_to_session_queue(resource, qualified_action, action_type)
get_script(self, resource)
async
Returns the most up-to-date version of the script for the session to which the resource belongs.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
resource |
Resource |
Resource belonging to the session for which the script is to be returned |
required |
Returns:
Type | Description |
---|---|
List[str] |
List of strings where each entry is a line in the script |
Source code in ofrak/gui/script_builder.py
async def get_script(self, resource: Resource) -> List[str]:
"""
Returns the most up-to-date version of the script for the session to which the resource
belongs.
:param resource: Resource belonging to the session for which the script is to be returned
:return: List of strings where each entry is a line in the script
"""
root_resource = await self._get_root_resource(resource)
return self._get_script(root_resource.get_id())
commit_to_script(self, resource)
async
Commits the staged actions and variable names in the queue to the script session following a one or more valid actions being run.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
resource |
Resource |
Resource belonging to the session whose queue will be committed |
required |
Source code in ofrak/gui/script_builder.py
async def commit_to_script(self, resource: Resource) -> None:
"""
Commits the staged actions and variable names in the queue to the script session following
a one or more valid actions being run.
:param resource: Resource belonging to the session whose queue will be committed
"""
root_resource = await self._get_root_resource(resource)
session = self._get_session(root_resource.get_id())
for id, name in session.resource_variable_names_queue.items():
session.resource_variable_names[id] = name
session.actions += session.actions_queue
session.actions_queue = []
session.resource_variable_names_queue = {}
clear_script_queue(self, resource)
async
Clears the script session queue of all staged actions and variable names following an invalid action being run.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
resource |
Resource |
Resource belonging to the session whose queue will be cleared |
required |
Source code in ofrak/gui/script_builder.py
async def clear_script_queue(self, resource: Resource) -> None:
"""
Clears the script session queue of all staged actions and variable names following an
invalid action being run.
:param resource: Resource belonging to the session whose queue will be cleared
"""
root_resource = await self._get_root_resource(resource)
session = self._get_session(root_resource.get_id())
session.actions_queue = []
session.resource_variable_names_queue = {}
_add_variable(self, resource)
async
private
Replaces references to a particular resource selected in the GUI with a generated variable name based on uniquely identifying characteristics of the resource. This overcomes the issue of referencing the same resource across OFRAK contexts due to the randomly generated resource IDs changing.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
resource |
Resource |
Resource that needs to be uniquely identified in the script |
required |
Returns:
Type | Description |
---|---|
str |
a unique variable name |
Source code in ofrak/gui/script_builder.py
async def _add_variable(self, resource: Resource) -> str:
"""
Replaces references to a particular resource selected in the GUI with a generated variable
name based on uniquely identifying characteristics of the resource. This overcomes the issue
of referencing the same resource across OFRAK contexts due to the randomly generated
resource IDs changing.
:param resource: Resource that needs to be uniquely identified in the script
:return: a unique variable name
"""
if await self._var_exists(resource):
return await self._get_variable_from_session(resource)
root_resource = await self._get_root_resource(resource)
if resource.get_id() == root_resource.get_id():
await self._add_variable_to_session_queue(resource, "root_resource")
return "root_resource"
parent = await resource.get_parent()
if not await self._var_exists(parent):
await self._add_variable(parent)
name = ""
# Cannot propagate exceptions to the server as this would interfere with user actions
# regardless of whether they're interested in the script. Currently only _get_selector()
# and _generate_name() can lead to exceptions raised within ScriptBuilder.
try:
selector = await self._get_selector(resource)
name = await self._generate_name(resource)
await self._add_action_to_session_queue(
resource,
rf"""
{name} = {selector}""",
ActionType.UNDEF,
)
await self._add_variable_to_session_queue(resource, name)
except SelectableAttributesError as e:
name = await self._generate_missing_name(resource, e)
LOGGER.exception("Could not find selectable attributes for resource")
return name
except:
LOGGER.exception("Exception raised in add_variable")
return name
_get_root_resource(self, resource)
async
private
Maps a given resource to its root for efficient retrieval of the root resource because
getting the root resource is likely the most performed operation in ScriptBuilder
.
Source code in ofrak/gui/script_builder.py
async def _get_root_resource(self, resource: Resource) -> Resource:
"""
Maps a given resource to its root for efficient retrieval of the root resource because
getting the root resource is likely the most performed operation in `ScriptBuilder`.
"""
resource_id = resource.get_id()
if resource_id in self.root_cache:
return self.root_cache[resource_id]
ancestors = list(await resource.get_ancestors())
root = ancestors[-1] if ancestors else resource
self.root_cache[resource_id] = root
return root
ScriptSession
dataclass
A script, consisting of an ordered sequence of script actions and a mapping between resources and their autogenerated variable names.
SelectableAttributesError (Exception)
Prompt the user for an attribute to select with