1
0
mirror of https://github.com/ARM-software/workload-automation.git synced 2025-01-19 12:24:32 +00:00
workload-automation/wlauto/utils/exec_control.py
Marc Bonnici 214d04eb8d Decorators: Added initial version of decorators and execution control
Added 3 decorators to enabled methods to be executed conditionally:
- Once for each method instance.
- Once for each class.
- Only once per environment including any derived classes.
Added execution control allowing for different environments to
be used in order to determine how often decorated commands should be ran.
Added relevant unittests for the above decorators.
2016-11-30 10:42:14 +00:00

118 lines
3.2 KiB
Python

from inspect import getmro
# "environment" management:
__environments = {}
__active_environment = None
def activate_environment(name):
"""
Sets the current tracking environment to ``name``. If an
environment with that name does not already exist, it will be
created.
"""
#pylint: disable=W0603
global __active_environment
if name not in __environments.keys():
init_environment(name)
__active_environment = name
def init_environment(name):
"""
Create a new environment called ``name``, but do not set it as the
current environment.
:raises: ``ValueError`` if an environment with name ``name``
already exists.
"""
if name in __environments.keys():
msg = "Environment {} already exists".format(name)
raise ValueError(msg)
__environments[name] = []
def reset_environment(name=None):
"""
Reset method call tracking for environment ``name``. If ``name`` is
not specified or is ``None``, reset the current active environment.
:raises: ``ValueError`` if an environment with name ``name``
does not exist.
"""
if name is not None:
if name not in __environments.keys():
msg = "Environment {} does not exist".format(name)
raise ValueError(msg)
__environments[name] = []
else:
if __active_environment is None:
raise ValueError("No Environment Active")
__environments[__active_environment] = []
# The decorators:
def once_per_instance(method):
"""
The specified method will be invoked only once for every bound
instance within the environment.
"""
def wrapper(*args, **kwargs):
if __active_environment is None:
raise ValueError("No Environment Active")
func_id = repr(args[0])
if func_id in __environments[__active_environment]:
return
else:
__environments[__active_environment].append(func_id)
return method(*args, **kwargs)
return wrapper
def once_per_class(method):
"""
The specified method will be invoked only once for all instances
of a class within the environment.
"""
def wrapper(*args, **kwargs):
if __active_environment is None:
raise ValueError("No Environment Active")
func_id = repr(method.func_name) + repr(args[0].__class__)
if func_id in __environments[__active_environment]:
return
else:
__environments[__active_environment].append(func_id)
return method(*args, **kwargs)
return wrapper
def once(method):
"""
The specified method will be invoked only once within the
environment.
"""
def wrapper(*args, **kwargs):
if __active_environment is None:
raise ValueError("No Environment Active")
func_id = repr(method.func_name)
# Store the least derived class, which isn't object, to account
# for subclasses.
func_id += repr(getmro(args[0].__class__)[-2])
if func_id in __environments[__active_environment]:
return
else:
__environments[__active_environment].append(func_id)
return method(*args, **kwargs)
return wrapper