1.1 --- a/imipweb/data.py Sat Oct 07 00:37:47 2017 +0200
1.2 +++ b/imipweb/data.py Sat Oct 07 22:08:13 2017 +0200
1.3 @@ -25,6 +25,57 @@
1.4 to_date
1.5 from imiptools.period import RecurringPeriod
1.6
1.7 +# General editing abstractions.
1.8 +
1.9 +class State:
1.10 +
1.11 + "Manage computed state."
1.12 +
1.13 + def __init__(self, callables):
1.14 +
1.15 + """
1.16 + Define state variable initialisation using the given 'callables', which
1.17 + is a mapping that defines a callable for each variable name that is
1.18 + invoked when the variable is first requested.
1.19 + """
1.20 +
1.21 + self.state = {}
1.22 + self.callables = callables
1.23 +
1.24 + def get_callable(self, key):
1.25 + return self.callables.get(key, lambda: None)
1.26 +
1.27 + def get(self, key, reset=False):
1.28 +
1.29 + """
1.30 + Return state for the given 'key', using the configured callable to
1.31 + compute and set the state if no state is already defined.
1.32 +
1.33 + If 'reset' is set to a true value, compute and return the state using
1.34 + the configured callable regardless of any existing state.
1.35 + """
1.36 +
1.37 + if reset or not self.state.has_key(key):
1.38 + self.state[key] = self.get_callable(key)()
1.39 +
1.40 + return self.state[key]
1.41 +
1.42 + def set(self, key, value):
1.43 + self.state[key] = value
1.44 +
1.45 + def __getitem__(self, key):
1.46 + return self.get(key)
1.47 +
1.48 + def __setitem__(self, key, value):
1.49 + self.set(key, value)
1.50 +
1.51 + def has_changed(self, key):
1.52 + return self.get_callable(key)() != self.get(key)
1.53 +
1.54 +
1.55 +
1.56 +# Period-related abstractions.
1.57 +
1.58 class PeriodError(Exception):
1.59 pass
1.60