Skip to content

Instantly share code, notes, and snippets.

@gorenje
Created April 23, 2019 14:10
Show Gist options
  • Save gorenje/57fbde5c9e76541228c064c6cb8730f4 to your computer and use it in GitHub Desktop.
Save gorenje/57fbde5c9e76541228c064c6cb8730f4 to your computer and use it in GitHub Desktop.
23.Apr.19 14:07:19 AttributeOne set to 1 for topic one because increment to limit
23.Apr.19 14:07:19 AttributeOne set to 2 for topic one because increment to limit
23.Apr.19 14:07:19 AttributeOne set to 1 for topic one because decrement to limit
23.Apr.19 14:07:19 AttributeOne set to 0 for topic one because decrement to limit
23.Apr.19 14:07:19 AttributeTwo set to 5 for topic one because limited to max 5
import types, math, sys, re, inspect, logging
from datetime import datetime
from collections import defaultdict
def tostderr(msg):
dstr = datetime.utcnow().strftime('%d.%b.%y %H:%M:%S')
for line in str(msg).splitlines():
sys.stderr.write("%s %s\n" % (dstr, line))
## Wrapper Class for handling method chaining and notify the wrapped
## object when it needs to modify its values.
class Scaler(object):
class Wrapper(object):
def __init__(self, name, parent):
self.name = name
self.parent = parent
def new_value(self, value, reason=None):
self.parent.set_cfg(self.name, value)
if reason != None:
tostderr("%s set to %s for %s because %s" % (
self.name, value, self.parent, reason
))
else:
tostderr("%s set to %s for %s" % (
self.name, value, self.parent
))
return value
@property
def current_value(self):
return int(self.parent.cfg[self.name])
def __init__(self, parent, direction):
self.parent = parent
self.direction = direction
self.cv = parent.current_value
self.amount = None
self.lmt = None
self.reason = None
@classmethod
def new(self, cfgname, direction, parent):
return Scaler(Scaler.Wrapper(cfgname, parent), direction)
def by(self, value):
self.amount = value
return self
def limit(self, value):
self.lmt = value
return self
def cause(self, reason):
self.reason = reason
return self
@property
def doit(self):
nv = None
if self.direction == "inc":
nv = self.cv + self.amount
nv = min([nv, self.lmt]) or nv
elif self.direction == "dec":
nv = max([self.cv - self.amount, self.lmt])
else:
return False
if self.cv == nv:
return False
return self.parent.new_value(nv, self.reason)
## Example of a class that represents configuration values.
class Topic(object):
def __init__(self, name):
self.cfg = defaultdict(lambda: 0, {})
self.name = name
def inc(self, cfgname):
return Scaler.new(cfgname, "inc", self)
def dec(self, cfgname):
return Scaler.new(cfgname, "dec", self)
def __str__(self):
return self.name
def set_cfg(self, attrname, value):
## This is called when the attrname is changed and can
## be used to persist the value, for example, to a database.
self.cfg[attrname] = value
def main():
# 'topic one' becomes the name of this object.
topic = Topic("topic one")
UpperLimit = 2
LowerLimit = 0
topic.inc("AttributeOne").by(1).limit(UpperLimit).cause(
"increment to limit").doit
topic.inc("AttributeOne").by(1).limit(UpperLimit).cause(
"increment to limit").doit
topic.inc("AttributeOne").by(1).limit(UpperLimit).cause(
"increment to limit").doit
topic.dec("AttributeOne").by(1).limit(LowerLimit).cause(
"decrement to limit").doit
topic.dec("AttributeOne").by(1).limit(LowerLimit).cause(
"decrement to limit").doit
topic.dec("AttributeOne").by(1).limit(LowerLimit).cause(
"decrement to limit").doit
topic.inc("AttributeTwo").by(10).limit(5).cause("limited to max 5").doit
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment