def __init__(self): ConfigurableNode.__init__(self) self._url = 'unknown' self._poll_event = None self._period = 0.2 # Pre-load attributes. self.off_text = "Off" self.on_text = "On" self.auto_text = "Auto" self.reverse_output = 0 self.output = REQUIRED self.input = REQUIRED self.period = self._period self.asyncOK = 1 self.state = 2 self.debug = 0 self.__running = False self._init_debug() self.OFF = EnumeratedValue(0, self.off_text) self.ON = EnumeratedValue(1, self.on_text) self.AUTO = EnumeratedValue(2, self.auto_text) self._NORMAL = 0 self._SAFETY = 1 self._output_state = self._NORMAL self._output_lock = Lock() self._changes_at = 0 self._waiting_value = None self._value = None self._lock = Lock() return
class SubscriptionExecutioner(object): PENDING = EnumeratedValue(0, 'Pending') PREPARING = EnumeratedValue(1, 'Preparing for export') GETTING = EnumeratedValue(2, 'Getting data') FORMATTING = EnumeratedValue(3, 'Formatting data') SENDING = EnumeratedValue(4, 'Starting transaction') SCHEDULING = EnumeratedValue(5, 'Scheduling next export') COMPLETED = EnumeratedValue(6, 'Completed') STAGES = [ PENDING, PREPARING, GETTING, FORMATTING, SENDING, SCHEDULING, COMPLETED ] def __init__(self, group, subscription): self.group = group self.subscription = subscription self.stagecallbacks = [(self.execute_prepare, ), (self.execute_get_data, ), (self.execute_format_data, ), (self.execute_start_transaction, ), (self.execute_schedule_export, )] self.stagearguments = () def get_stage(self): return self.STAGES[-len(self.stagecallbacks) - 1] def execute(self): stage = self.get_stage() stagemethods = self.stagecallbacks.pop(0) try: for stagemethod in stagemethods: stagearguments = self.stagearguments result = stagemethod(*stagearguments) self.stagearguments = (result, ) except Exception, error: self.subscription.handle_export_exception(error, stage) if not self.is_complete(): self.group.notify_stage_aborted(self, stage) else: self.group.notify_executioner_aborted(self) self.stagecallbacks, self.stagearguments = [], () else:
class Calculated(_Trigger, Calculator): implements(ITrigger) INITIALIZING = EnumeratedValue(0, 'init') INACTIVE = EnumeratedValue(1, 'inactive') ACTIVE = EnumeratedValue(2, 'active') ERROR = EnumeratedValue(3, 'error') DISABLED = EnumeratedValue(4, 'disabled') STATES = { INITIALIZING: { 'start': INACTIVE, 'stop': DISABLED }, INACTIVE: { 'clear': INACTIVE, 'trigger': ACTIVE, 'stop': DISABLED }, ACTIVE: { 'clear': INACTIVE, 'trigger': ACTIVE, 'stop': DISABLED }, ERROR: { 'clear': INACTIVE, 'trigger': ERROR, 'stop': DISABLED }, DISABLED: { 'stop': DISABLED, 'start': INACTIVE } } ACTIONS = ('clear', 'trigger') EVENTTYPES = { (ACTIVE, INACTIVE): TriggerCleared, (INACTIVE, ACTIVE): TriggerActivated } def __init__(self, *args): _Trigger.__init__(self, *args) Calculator.__init__(self) self.state = self.INITIALIZING self.scheduled = None self._running = Flag() self._start_failed = False def configure(self, config): Calculator.configure(self, config) _Trigger.configure(self, config) message = '' if 'poll_period' in config: try: policy = float(config['poll_period']) except ValueError: raise ValueError( 'Value of field \'Poll period\' is not numeric') if not (config.has_key('message') and config['message']): for var in self.variables: if message: message += ', ' message += '%s = ${%s}' % (var['vn'], var['vn']) set_attribute(self, 'message', message, {}) else: set_attribute(self, 'message', REQUIRED, config) set_attribute(self, 'poll_period', 2, config, float) set_attribute(self, 'critical_input', '', config) set_attribute(self, 'description', '', config) set_attribute(self, 'enabled', 1, config, as_boolean) self.manager = self.parent def configuration(self): config = Calculator.configuration(self) config.update(_Trigger.configuration(self)) get_attribute(self, 'message', config) get_attribute(self, 'poll_period', config, str) get_attribute(self, 'critical_input', config) get_attribute(self, 'description', config) get_attribute(self, 'enabled', config, str) return config def is_active(self): return self.get_state() is self.ACTIVE def is_running(self): return self._running.isSet() def get_state(self): return self.state def get(self, skipCache=0): return str(self.get_state()) def start(self): if not self._running.isSet(): _Trigger.start(self) variables = [] self._message = '' message = self.message while '$' in message: index = message.index('$') try: if message[index + 1] == '{': end = string.find(message, '}', index) if end > -1: var = message[index:end + 1] variable = var[2:-1] if '$' not in variable and '{' not in variable: message = string.replace(message, var, '%s') variables.append(variable) except IndexError: pass self._message += message[0:index + 1] message = message[index + 1:] self._message += message self._message_vars = tuple(variables) self.state = self.STATES[self.state]['start'] self._running.set() try: Calculator.start(self) except: message = "Failed to start Trigger %r. Will retry in 30 secs." msglog.error(message % self.name) if not self._start_failed: msglog.exception(prefix="handled") self._start_failed = True else: message = "Trigger %r started. Evaluation runs in 30 seconds." msglog.inform(message % self.name) self._start_failed = False finally: self.reschedule(30) def stop(self): self.synclock.acquire() try: self._running.clear() self.state = self.STATES[self.state]['stop'] finally: self.synclock.release() self.reschedule() Calculator.stop(self) _Trigger.stop(self) def __call__(self): if not self.started: self.start() else: try: self._run_evaluation() except: msglog.exception() msglog.inform('Trigger reschedule delayed 20 seconds.') delay = 20 else: delay = self.poll_period finally: self.reschedule(delay) def _run_evaluation(self): values = self._get_values(self.local_context) current_value = self.evaluate(values) self.synclock.acquire() try: # Check running state before performing evaluation. if not self._running.isSet(): return action = self.ACTIONS[current_value] previous = self.state self.state = current = self.STATES[self.state][action] finally: self.synclock.release() eventtype = self.EVENTTYPES.get((previous, current)) if not eventtype: return timestamp = time.time() if self.critical_input: value = values[self.critical_input] elif len(values.keys()) == 1: value = values.values()[0] else: value = None event = eventtype(self, timestamp, value, values) self._dispatch(event) def _dispatch(self, event): self.manager.dispatcher.dispatch(event) def reschedule(self, delay=None): scheduled, self.scheduled = self.scheduled, None if scheduled: scheduled.cancel() if self._running.isSet(): if delay is None: delay = self.poll_period self.scheduled = scheduler.after(delay, self.manager.queue_trigger, (self, )) return self.scheduled
def trim_ge(self, column, value): pass def reset(self): pass def destroy(self): pass ## # Type Conversion data and functions. # _types = { 'char': EnumeratedValue(0, 'c'), 'char': EnumeratedValue(1, 'b'), 'unsigned_char': EnumeratedValue(2, 'B'), 'short': EnumeratedValue(3, 'h'), 'unsgined_short': EnumeratedValue(4, 'H'), 'int': EnumeratedValue(5, 'i'), 'unsigned_int': EnumeratedValue(6, 'I'), 'long': EnumeratedValue(7, 'l'), 'unsigned_long': EnumeratedValue(8, 'L'), 'float': EnumeratedValue(9, 'f'), 'double': EnumeratedValue(10, 'd') } def _to_type_value(name): return _types[name]
def test_1(self): try: ed = EnumeratedDictionary() except: raise 'Failed to create empty dictionary' try: one = EnumeratedValue(1, 'one') two = EnumeratedValue(2, 'two') ed[1] = one ed['two'] = two except: raise 'Basic assignment failed' try: ed[3] = one except: pass else: raise 'Failed to detect mismatch between int key and value' try: ed['three'] = one except: pass else: raise 'Failed to detect mismatch between str key and value' try: s = str(ed) except: raise 'Failed to produce str from self' #exp_str = "{1: EnumeratedValue(1,'one'), 2: EnumeratedValue(2,'two')}" exp_str = "{1: {'__base__': 'EnumeratedValue', 'num': 1, '__class__': 'mpx.lib.EnumeratedValue', 'str': 'one'}, 2: {'__base__': 'EnumeratedValue', 'num': 2, '__class__': 'mpx.lib.EnumeratedValue', 'str': 'two'}}" if s != exp_str: raise 'str conversion failed (%s vs %s)' % (s, exp_str) try: r = repr(ed) except: raise 'Failed to produce repr string' #exp_repr = "EnumeratedDictionary({1: EnumeratedValue(1,'one'), 2: EnumeratedValue(2,'two')})" exp_repr = "EnumeratedDictionary({1: {'__base__': 'EnumeratedValue', 'num': 1, '__class__': 'mpx.lib.EnumeratedValue', 'str': 'one'}, 2: {'__base__': 'EnumeratedValue', 'num': 2, '__class__': 'mpx.lib.EnumeratedValue', 'str': 'two'}})" if r != exp_repr: raise 'repr string comparison failed (%s vs %s)' % (r, exp_repr) if ed[1] != one: raise 'Failed to get correct item for int key' if ed['two'] != two: raise 'Failed to get correct item for str key' try: ed['three'] except: pass else: raise 'Failed to raise key exception on bad key' if ed.items() != [(1, EnumeratedValue(1,'one')), (2, EnumeratedValue(2,'two'))]: raise 'Failed to produce items' try: ed[3]='three' ed['four']=4 except: raise 'Failed set for simple int and str items' if ed[3] != EnumeratedValue(3,'three'): raise 'Implicit creation of EnumeratedValue failed' if ed['three'] != EnumeratedValue(3,'three'): raise 'str dict did not get implicit assignment' ed2 = EnumeratedDictionary(ed) try: if ed == ed2: pass else: raise 'Equality test failed' except: raise 'Equality test crashed' ed2 = EnumeratedDictionary(ed) try: ed3 = EnumeratedDictionary(ed2) except: raise 'Failed to instanciate from another EnumeratedDictionary' if ed != ed3: raise 'Non-equality test failed' try: del ed2[1] except: raise 'del failed' if ed2.get(1) != None: raise 'Failed to del an item' if ed2.get('one') != None: raise 'Failed to del an item from str_dict' try: del ed2['two'] except: raise 'del failed' if ed2.get(2) != None: raise 'Failed to del an item' if ed2.get('two') != None: raise 'Failed to del an item from str_dict' s = str(ed) #exp_str = "{1: EnumeratedValue(1,'one'), 2: EnumeratedValue(2,'two'), 3: EnumeratedValue(3,'three'), 4: EnumeratedValue(4,'four')}" exp_str = "{1: {'__base__': 'EnumeratedValue', 'num': 1, '__class__': 'mpx.lib.EnumeratedValue', 'str': 'one'}, 2: {'__base__': 'EnumeratedValue', 'num': 2, '__class__': 'mpx.lib.EnumeratedValue', 'str': 'two'}, 3: {'__base__': 'EnumeratedValue', 'num': 3, '__class__': 'mpx.lib.EnumeratedValue', 'str': 'three'}, 4: {'__base__': 'EnumeratedValue', 'num': 4, '__class__': 'mpx.lib.EnumeratedValue', 'str': 'four'}}" if s != exp_str: raise 'Failed to survive all the stuff I tried to do to it.... (%s vs %s)' % (s, exp_str)
class CalculatedTrigger(Calculator, EventProducerMixin): INITIALIZING = EnumeratedValue(0, 'init') INACTIVE = EnumeratedValue(1, 'inactive') TRIGGERED = EnumeratedValue(2, 'triggered') SENDING = EnumeratedValue(3, 'sending') SENT = EnumeratedValue(4, 'sent') ACKNOWLEDGED = EnumeratedValue(5, 'acknowledged') ERROR = EnumeratedValue(6, 'error') DISABLED = EnumeratedValue(7, 'disabled') STATE = { INITIALIZING: { 'start': INACTIVE, 'stop': DISABLED }, INACTIVE: { 'start': INACTIVE, 'clear': INACTIVE, 'trigger': TRIGGERED, 'stop': DISABLED }, TRIGGERED: { 'start': ERROR, 'caught': SENDING, 'stop': DISABLED }, SENDING: { 'start': ERROR, 'succeed': SENT, 'fail': ERROR, 'stop': DISABLED }, SENT: { 'start': SENT, 'clear': INACTIVE, 'trigger': SENT, 'acknowledge': ACKNOWLEDGED, 'stop': DISABLED }, ACKNOWLEDGED: { 'start': ACKNOWLEDGED, 'clear': INACTIVE, 'trigger': ACKNOWLEDGED, 'acknowledge': ACKNOWLEDGED, 'stop': DISABLED }, ERROR: { 'start': ERROR, 'clear': INACTIVE, 'trigger': ERROR, 'stop': DISABLED }, DISABLED: { 'start': INACTIVE, 'stop': DISABLED } } def __init__(self): Calculator.__init__(self) EventProducerMixin.__init__(self) self._state = self.INITIALIZING self._current_id = None self._scheduled = None self._state_lock = Lock() self._schedule_lock = Lock() self.require_acknowledge = 0 return def get(self, skipCache=0): return int(self._state) def __str__(self): return '%s: %s' % (self.name, str(self._state)) def configure(self, config): Calculator.configure(self, config) message = '' if not (config.has_key('message') and config['message']): for var in self.variables: if message: message += ', ' message += '%s = ${%s}' % (var['vn'], var['vn']) set_attribute(self, 'message', message, {}) else: set_attribute(self, 'message', REQUIRED, config) set_attribute(self, 'poll_period', 0.1, config, float) set_attribute(self, 'critical_input', '', config) set_attribute(self, 'send_retries', 3, config, int) set_attribute(self, 'enabled', 1, config, as_boolean) set_attribute(self, 'require_acknowledge', 0, config, as_boolean) self._manager = self.parent.parent def configuration(self): config = Calculator.configuration(self) get_attribute(self, 'message', config) get_attribute(self, 'poll_period', config, str) get_attribute(self, 'critical_input', config) get_attribute(self, 'send_retries', config) get_attribute(self, 'enabled', config, str) return config def enable(self): self.enabled = 1 self.start() def disable(self): self.enabled = 0 self.stop() def is_enabled(self): return self.enabled def get_state_name(self): return str(self._state) def start(self): self.STATE = {} self.STATE.update(self.__class__.STATE) if self.require_acknowledge: self.STATE[self.__class__.SENT]['clear'] = self.__class__.SENT Calculator.start(self) variables = [] self._message = '' message = self.message while '$' in message: index = message.index('$') try: if message[index + 1] == '{': end = string.find(message, '}', index) if end > -1: var = message[index:end + 1] variable = var[2:-1] if '$' not in variable and '{' not in variable: message = string.replace(message, var, '%s') variables.append(variable) except IndexError: pass self._message += message[0:index + 1] message = message[index + 1:] self._message += message self._message_vars = tuple(variables) self._change_state('start') def stop(self): # this is where we need to cancel our schedule entry. self._change_state('stop') Calculator.stop(self) def caught(self, alarm): if alarm.__class__ == AlarmTriggerEvent: self._caught_trigger(alarm) elif alarm.__class__ == AlarmClearEvent: self._caught_clear(alarm) def success(self, alarm): self._change_state('succeed') def fail(self, alarm): msglog.log('broadway', msglog.types.WARN, 'Failed sending alarm -> %s' % alarm) self._change_state('fail') ## # @todo Consider creating and using an alarm ack event # similar to the way that trigger and clear are used. # This would allow the manager to keep a list of # 'active' 'unacknowledged' alarms so that something # like the alarm handler could generate a list. def acknowledge(self, alarm=None): self._change_state('acknowledge') def state(self, alarm): return self._state def check_condition(self): try: values = self._get_values(self.local_context) except: msglog.exception() self._reschedule() return value = None if self.critical_input: value = values[self.critical_input] elif len(values.keys()) == 1: value = values.values()[0] if self._evaluate(values): self._trigger(time.time(), value, values) else: self._clear(time.time(), value, values) def _reschedule(self): self._schedule_lock.acquire() try: if (self._scheduled is None or self._scheduled.executing() or self._scheduled.expired()): self._scheduled = scheduler.after( self.poll_period, self._manager.queue_alarm_check, (self, )) finally: self._schedule_lock.release() return def _have_trasition(self, action): self._state_lock.acquire() try: actions = self.STATE[self._state] return actions.has_key(action) finally: self._state_lock.release() raise EUnreachableCode() def _change_state(self, action): self._state_lock.acquire() try: actions = self.STATE[self._state] if not actions.has_key(action): raise EInvalidValue( 'action', action, 'Invalid action from state %s' % self._state) state = actions[action] if self.TRANSITION[state]: self.TRANSITION[state](self) self._state = state finally: self._state_lock.release() return ## # @todo May want to add another state that waits for the # AlarmClearEvent to be confirmed caught, but then # again, maybe not. def _clear(self, timestamp, value, values): try: self._change_state('clear') # If the alarm is currently 'active' if (self._state == self.ACKNOWLEDGED or (self._state == self.SENT and not self.require_acknowledge)): if self._current_id != None: clear = AlarmClearEvent(self, self._current_id, timestamp, value, values) self._current_id = None self.event_generate(clear) else: msglog.log('broadway', msglog.types.WARN, 'IGNORING CLEAR BECAUSE NO CURRENT ID') except EInvalidValue: pass def _trigger(self, timestamp, value, values): try: state = self._state self._change_state('trigger') if state == self.INACTIVE: self._current_id = self._manager.unique_id() message = self._message for var in self._message_vars: if values.has_key(var): message = string.replace(message, '%s', str(values[var]), 1) else: message = string.replace(message, '%s', '${%s}' % var, 1) trigger = AlarmTriggerEvent(self, self._current_id, timestamp, value, values, message) self.event_generate(trigger) except EInvalidValue: pass def _caught_trigger(self, alarm): self._change_state('caught') def _caught_clear(self, alarm): pass TRANSITION = { INACTIVE: _reschedule, TRIGGERED: None, SENDING: None, SENT: _reschedule, ACKNOWLEDGED: _reschedule, ERROR: _reschedule, DISABLED: None }
def test_dumps_enumerated_value(self): print "\n", 60 * "-" print dumps((EnumeratedValue(12, 'twelve'), )) print 60 * "-"
print dumps((StringClass("Text with ]]>"), )) print """ # # The StringMarshaller is more advanced then the built in string marshelling. # We could remove our escape hack and replace the string marshalling. # >>> Marshaller.dispatch[types.StringType] = \\ Marshaller.dispatch[types.InstanceType] """ Marshaller.dispatch[types.StringType] = Marshaller.dispatch[types.InstanceType] print """ # # We could do a cleaner reimplementation, but this just show that now the str # marshaller uses the InstanceType, which I've extended to support registerring # handlers, blah, blah, blah... # >>> print dumps(('this is a test.',)) # Look ma, CDATA goodies! """ print dumps(('this is a test.', )) from mpx.lib import EnumeratedValue print dumps((EnumeratedValue(2, "asdf"), )) from mpx.lib.magnitude import MagnitudeInterface print dumps((MagnitudeInterface(1), )) print dumps((MagnitudeInterface(2L), )) print dumps((MagnitudeInterface(3.0), ))