1# -*- coding: utf-8 -*-
2"""
3Utilities for lazy resolution of configurations.
4
5Provides a bunch of tools to perform actions that need
6the configuration to be in place when performed
7
8"""
9
10from logging import getLogger
11log = getLogger(__name__)
12
13
14class _ConfigMilestoneTracker(object):
15    """Tracks actions that need to be performed
16    when a specific configuration point is reached
17    and required options are correctly initialized
18
19    """
20    def __init__(self, name):
21        self.name = name
22        self._actions = dict()
23        self._reached = False
24        self._keep_on_reset = []
25
26    @property
27    def reached(self):
28        return self._reached
29
30    def register(self, action, persist_on_reset=False):
31        """Registers an action to be called on milestone completion.
32
33        If milestone is already passed action is immediately called
34
35        """
36        if persist_on_reset:
37            self._keep_on_reset.append(action)
38
39        if self._reached:
40            log.debug('%s milestone passed, calling %s directly', self.name, action)
41            action()
42        else:
43            log.debug('Register %s to be called when %s reached', action, self.name)
44            self._actions[id(action)] = action
45
46    def reach(self):
47        """Marks the milestone as reached.
48
49        Runs the registered actions. Calling this
50        method multiple times should lead to nothing.
51
52        """
53        log.debug('%s milestone reached', self.name)
54
55        try:
56            while True:
57                try:
58                    __, action = self._actions.popitem()
59                    action()
60                except KeyError:
61                    break
62        finally:
63            self._reached = True
64
65    def _reset(self):
66        """This is just for testing purposes"""
67        self._reached = False
68        self._actions = dict()
69        for action in self._keep_on_reset:
70            self.register(action)
71
72
73config_ready = _ConfigMilestoneTracker('config_ready')
74renderers_ready = _ConfigMilestoneTracker('renderers_ready')
75environment_loaded = _ConfigMilestoneTracker('environment_loaded')
76
77
78def _reset_all():
79    """Utility method for the test suite to reset milestones"""
80    config_ready._reset()
81    renderers_ready._reset()
82    environment_loaded._reset()
83
84
85def _reach_all():
86    """Utility method for the test suite to reach all milestones"""
87    config_ready.reach()
88    renderers_ready.reach()
89    environment_loaded.reach()
90