Add a cachedproperty descriptor
It is pretty common that we create a property method that checks if an instance variable is none, then creates it and then sets the instance property (and then never gets called to create it again, unless property is reset to none). Apply this new property descriptor to a few places that are redoing this same action over (don't repeat yourself principle in action). Change-Id: If6c20c5a2d145c51af3f3db56a4746eca8601253
This commit is contained in:
@@ -61,9 +61,6 @@ class ActionEngine(base.EngineBase):
|
||||
self._compiled = False
|
||||
self._lock = threading.RLock()
|
||||
self._state_lock = threading.RLock()
|
||||
self._task_executor = None
|
||||
self._task_action = None
|
||||
self._retry_action = None
|
||||
self._storage_ensured = False
|
||||
|
||||
def __str__(self):
|
||||
@@ -166,6 +163,19 @@ class ActionEngine(base.EngineBase):
|
||||
self._root.reset_all()
|
||||
self._change_state(states.PENDING)
|
||||
|
||||
@misc.cachedproperty
|
||||
def _retry_action(self):
|
||||
return self._retry_action_factory(self.storage, self.task_notifier)
|
||||
|
||||
@misc.cachedproperty
|
||||
def _task_executor(self):
|
||||
return self._task_executor_factory()
|
||||
|
||||
@misc.cachedproperty
|
||||
def _task_action(self):
|
||||
return self._task_action_factory(self.storage, self._task_executor,
|
||||
self.task_notifier)
|
||||
|
||||
@lock_utils.locked
|
||||
def compile(self):
|
||||
if self._compiled:
|
||||
@@ -175,15 +185,6 @@ class ActionEngine(base.EngineBase):
|
||||
raise exc.Empty("Flow %s is empty." % self._flow.name)
|
||||
self._analyzer = self._graph_analyzer_factory(execution_graph,
|
||||
self.storage)
|
||||
if self._task_executor is None:
|
||||
self._task_executor = self._task_executor_factory()
|
||||
if self._task_action is None:
|
||||
self._task_action = self._task_action_factory(self.storage,
|
||||
self._task_executor,
|
||||
self.task_notifier)
|
||||
if self._retry_action is None:
|
||||
self._retry_action = self._retry_action_factory(self.storage,
|
||||
self.task_notifier)
|
||||
self._root = self._graph_action_factory(self._analyzer,
|
||||
self.storage,
|
||||
self._task_action,
|
||||
|
||||
@@ -34,17 +34,13 @@ class EngineBase(object):
|
||||
self._conf = {}
|
||||
else:
|
||||
self._conf = dict(conf)
|
||||
self._storage = None
|
||||
self.notifier = misc.Notifier()
|
||||
self.task_notifier = misc.Notifier()
|
||||
|
||||
@property
|
||||
@misc.cachedproperty
|
||||
def storage(self):
|
||||
"""The storage unit for this flow."""
|
||||
if self._storage is None:
|
||||
self._storage = self._storage_factory(self._flow_detail,
|
||||
self._backend)
|
||||
return self._storage
|
||||
return self._storage_factory(self._flow_detail, self._backend)
|
||||
|
||||
@abc.abstractproperty
|
||||
def _storage_factory(self):
|
||||
|
||||
@@ -21,6 +21,7 @@ import copy
|
||||
import datetime
|
||||
import errno
|
||||
import functools
|
||||
import inspect
|
||||
import keyword
|
||||
import logging
|
||||
import os
|
||||
@@ -174,6 +175,37 @@ def decode_json(raw_data, root_types=(dict,)):
|
||||
return data
|
||||
|
||||
|
||||
class cachedproperty(object):
|
||||
"""Descriptor that can be placed on instance methods to translate
|
||||
those methods into properties that will be cached in the instance (avoiding
|
||||
repeated creation checking logic to do the equivalent).
|
||||
"""
|
||||
def __init__(self, wrapped):
|
||||
# If a name is provided (as an argument) then this will be the string
|
||||
# to place the cached attribute under if not then it will be the
|
||||
# function itself to be wrapped into a property.
|
||||
if inspect.isfunction(wrapped):
|
||||
self._wrapped = wrapped
|
||||
self._wrapped_attr = "_%s" % (wrapped.__name__)
|
||||
else:
|
||||
self._wrapped_attr = wrapped
|
||||
self._wrapped = None
|
||||
|
||||
def __call__(self, fget):
|
||||
# If __init__ received a string then this will be the function to be
|
||||
# wrapped as a property (if __init__ got a function then this will not
|
||||
# be called).
|
||||
self._wrapped = fget
|
||||
return self
|
||||
|
||||
def __get__(self, source, owner):
|
||||
try:
|
||||
return getattr(source, self._wrapped_attr)
|
||||
except AttributeError:
|
||||
setattr(source, self._wrapped_attr, self._wrapped(source))
|
||||
return getattr(source, self._wrapped_attr)
|
||||
|
||||
|
||||
def wallclock():
|
||||
# NOTE(harlowja): made into a function so that this can be easily mocked
|
||||
# out if we want to alter time related functionality (for testing
|
||||
|
||||
Reference in New Issue
Block a user