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
def __init__(self, value, text, data_type='UCHAR', default=0, max_insts=1, \ prop_types=None, num_insts_obj_type_name=None): EnumeratedValue.__init__(self, value, text) self.max_num_instances = max_insts self.num_insts_obj_type_name = num_insts_obj_type_name if prop_types is None: prop_types = [0] self.prop_types = prop_types self.default = default self.data_type = data_type return
def __init__(self, value, text, data_type='UCHAR', default=0, max_insts=1, \ prop_types=None, num_insts_obj_type_name=None): EnumeratedValue.__init__(self,value,text) self.max_num_instances = max_insts self.num_insts_obj_type_name = num_insts_obj_type_name if prop_types is None: prop_types = [0] self.prop_types = prop_types self.default = default self.data_type = data_type return
def __new__(klass, value, text, data_type='NONE', default=0, max_insts=1, prop_types=None): return EnumeratedValue.__new__(klass, value, text)
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
class PeriodicRelayDriver(ConfigurableNode): 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 def _begin_critical_section(self): self._lock.acquire() return def _end_critical_section(self): self._lock.release() return def _init_debug(self): self.DEBUG1 = self._debug_stub self.DEBUG2 = self._debug_stub self.DEBUG3 = self._debug_stub self.DEBUG_EXC = self._debug_stub if self.debug > 0: self.DEBUG_EXC = self._debug_exc self.DEBUG1 = self._debug_print if self.debug > 1: self.DEBUG2 = self._debug_print if self.debug > 2: self.DEBUG3 = self._debug_print return def _schedule(self): self.DEBUG3("_schedule():\n") self._cancel_polling() if self.__running: self._poll_event = scheduler.after( self._period, self._lock_and_poll_input) self.DEBUG3("_schedule: return\n") return def _drive_output(self, value, force=0): self._output_lock.acquire() try: if force: # Immediatly change the value. self._value = value self.output.set(value) else: # May be delayed by minimum on/off times. self._output(value) finally: self._output_lock.release() return def _output(self, value): value = value ^ self.reverse_output if self.enabled and (value is not self._value): self.DEBUG3("_drive_output: self.output=%s\n", self.output) if self._output_state == self._SAFETY: self._waiting_value = value else: self.output.set(value) self._waiting_value = None self._value = value if (value == 1) and self.min_on_time > 0: self._output_state = self._SAFETY scheduler.after(self.min_on_time, self._clear_safety,()) self._changes_at = time.time() + self.min_on_time elif (value == 0) and self.min_off_time > 0: self._output_state = self._SAFETY scheduler.after(self.min_off_time, self._clear_safety,()) self._changes_at = time.time() + self.min_off_time self.DEBUG2("_drive_output: set:%r, got:%r\n", value, self.output.get) else: self.DEBUG3("_drive_output: No change\n") self.DEBUG3("_drive_output: return\n") return def time_remaining(self): self._output_lock.acquire() try: if self._output_state == self._NORMAL: return 0 return self._changes_at - time.time() finally: self._output_lock.release() return def _clear_safety(self): self._output_lock.acquire() try: self._output_state = self._NORMAL if self._waiting_value != None: self._output(self._waiting_value) finally: self._output_lock.release() return def _cancel_polling(self): self.DEBUG3("_cancel_polling():\n") if self._poll_event is not None: e = self._poll_event self._poll_event = None if not e.expired(): e.cancel() self.DEBUG2("_cancel_polling: canceled %s\n", e) self.DEBUG3("_cancel_polling: return\n") return def _poll_input(self): self._poll_event = None self.DEBUG3("_poll_input():\n") # @fixme: Create n "priority" threads for schedulies to use. # ReadyTask(threads_queue, function), .__call_ -> add queue. if self.state is self.AUTO: try: self._drive_output(int(self.input.get())) except: # Start falling back... self.DEBUG_EXC("AUTO drive of output failed.") self._period = self._period * 2 self.DEBUG1("Adjusting period to every %s seconds.", self._period) else: if self.debug and self._period > self.period: self.DEBUG1("Restoring period to every %s seconds.", self.period) self._period = self.period self._schedule() else: value = int(self.state) self.DEBUG3("_poll_input: return\n") return def _lock_and_poll_input(self): self.DEBUG3("_lock_and_poll_input()\n") self._begin_critical_section() try: self._poll_input() finally: self._end_critical_section() self.DEBUG3("_lock_and_poll_input: return\n") return def _set_state(self, value): self.DEBUG3("_set_state(%r):\n", value) self.ENUM_LIST = [self.OFF, self.ON, self.AUTO] self.STR_LIST = [str(self.OFF), str(self.ON), str(self.AUTO)] if value not in self.ENUM_LIST: if value in self.STR_LIST: value = self.ENUM_LIST[self.STR_LIST.index(value)] else: exception = EInvalidValue('state', value) self.DEBUG3("_set_state: raise %r\n", exception) raise exception else: value = self.ENUM_LIST[self.ENUM_LIST.index(value)] self.state = value self.DEBUG3("_set_state: %r\n", self.state) return self.state def _debug_exc(self, fmt='', *args): _sys.stderr.write("EXCEPTION: %r\n" % (fmt % args)) _tb.print_exc(None,_sys.stderr) _sys.stderr.flush() return def _debug_print(self, fmt, *args): try: converted_args = [] for arg in args: if callable(arg): arg = arg() converted_args.append(arg) converted_args = tuple(converted_args) _sys.stderr.write("DEBUG(%r): %s" % (self._url, (fmt % converted_args))) _sys.stderr.flush() except: _sys.stderr.write("DEBUG FAILED: self.DEBUG(%r, %r)\n" % (fmt, args)) self._debug_exc() _sys.stderr.write("\tself._url: %r\n" % self._url) _sys.stderr.write("\tfmt: %r\n" % fmt) _sys.stderr.write("\tconverted_args: %r\n" % converted_args) _sys.stderr.flush() return def _debug_stub(self, fmt, *args): return ## # @see ConfigurableNode#configure # def configure(self, config): set_attribute(self, 'debug', self.debug, config, int) self._init_debug() self.DEBUG3("configure(%r):\n", config) # @fixme Add the option to output on change (default), output every # time, or the check the outputs state. ConfigurableNode.configure(self, config) self._url = as_node_url(self) if self.output is REQUIRED: self.output = self.parent set_attribute(self, 'off_text', self.off_text, config, str) set_attribute(self, 'on_text', self.on_text, config, str) set_attribute(self, 'auto_text', self.auto_text, config, str) set_attribute(self, 'reverse_output', self.reverse_output, config, int) set_attribute(self, 'output', self.parent, config, self.as_deferred_node) set_attribute(self, 'input', REQUIRED, config, self.as_deferred_node) set_attribute(self, 'period', self.period, config, float) set_attribute(self, 'asyncOK', self.asyncOK, config, int) set_attribute(self, 'state', self.state, config, self._set_state) set_attribute(self, 'enabled', 1, config, as_boolean) set_attribute(self, 'min_on_time', 0, config, float) set_attribute(self, 'min_off_time', 0, config, float) return ## # Get this objects configuration. # # @return Dictionary containg configuration. # @see ConfigurableNode#configuration # def configuration(self): config = ConfigurableNode.configuration(self) get_attribute(self, 'off_text', config, str) get_attribute(self, 'on_text', config, str) get_attribute(self, 'auto_text', config, str) get_attribute(self, 'reverse_output', config, str) get_attribute(self, 'output', config, self.as_deferred_node) get_attribute(self, 'input', config, as_node_url) get_attribute(self, 'period', config, str) get_attribute(self, 'asyncOK', config, str) get_attribute(self, 'state', config, str) get_attribute(self, 'debug', config, str) get_attribute(self, 'enabled', config, str) get_attribute(self, 'min_on_time', config, str) get_attribute(self, 'min_off_time', config, str) return config def start(self): self.DEBUG3("start():\n") self.OFF.text(self.off_text) self.ON.text(self.on_text) self.AUTO.text(self.auto_text) ConfigurableNode.start(self) self.__running = True self._begin_critical_section() try: self._poll_input() finally: self._end_critical_section() self.DEBUG3("start: return\n") return def stop(self): self.DEBUG3("stop():\n") ConfigurableNode.stop(self) self.__running = False self._begin_critical_section() try: self._cancel_polling() finally: self._end_critical_section() self.DEBUG3("stop: return\n") return def get_result(self, skipCache=0, **keywords): self.DEBUG3("get_result(skipCache=%r)\n", skipCache) result = Result() self._begin_critical_section() try: result.value = self.state finally: self._end_critical_section() result.timestamp = time.time() result.cached = not self.asyncOK self.DEBUG3("get_result: return %r\n", result) return result def disable(self): self._output_lock.acquire() try: self.enabled = 0 finally: self._output_lock.release() return def is_disabled(self): self._output_lock.acquire() try: return not self.enabled finally: self._output_lock.release() return def enable(self): self._output_lock.acquire() try: self.enabled = 1 finally: self._output_lock.release() return def is_enabled(self): self._output_lock.acquire() try: return self.enabled finally: self._output_lock.release() def set_min_on_time(self, min): self._output_lock.acquire() try: self.min_on_time = min finally: self._output_lock.release() return def get_min_on_time(self): return self.min_on_time def set_min_off_time(self, min): self._output_lock.acquire() try: self.min_off_time = min finally: self._output_lock.release() return def get_min_off_time(self): return self.min_off_time def get(self, skipCache=0): self._begin_critical_section() try: result = self.state finally: self._end_critical_section() self.DEBUG3("get(skipCache=%r): return %r\n", skipCache, result) return result def states(self): self.DEBUG3("states():\n") list = [] list.extend(self.ENUM_LIST) self.DEBUG3("states: return %r\n", list) return list def set(self, value, asyncOK=1): self.DEBUG3("set(%r, asyncOK=%r):\n", value, asyncOK) self._begin_critical_section() try: self._set_state(value) self.asyncOK = asyncOK self._cancel_polling() if self.state == self.AUTO: self._poll_input() else: # Explicitly set ON/OFF states bypass the minimum on/off times. self._drive_output(int(self.state), 1) self.DEBUG3("set: return\n") finally: self._end_critical_section() return def as_deferred_node(self, node_ref): #set_attribute does not pass THIS node in for relative URLs return as_deferred_node(node_ref, self)
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 __new__(klass, value, text, obj_types): return EnumeratedValue.__new__(klass, value, text)
def __init__(self, value, text, data_type='UCHAR'): EnumeratedValue.__init__(self,value,text) self.data_type = _data_types[data_type] # use ref to EnumValue return
def __new__(klass, value, text, data_type='UCHAR', default=0, max_insts=1, \ prop_types=None, num_insts_obj_type_name=None): return EnumeratedValue.__new__(klass, value, text)
def test_dumps_enumerated_value(self): print "\n", 60 * "-" print dumps((EnumeratedValue(12, 'twelve'), )) print 60 * "-"
def __init__(self, value, text, obj_types): EnumeratedValue.__init__(self, value, text) self.obj_types = obj_types return
class PeriodicRelayDriver(ConfigurableNode): 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 def _begin_critical_section(self): self._lock.acquire() return def _end_critical_section(self): self._lock.release() return def _init_debug(self): self.DEBUG1 = self._debug_stub self.DEBUG2 = self._debug_stub self.DEBUG3 = self._debug_stub self.DEBUG_EXC = self._debug_stub if self.debug > 0: self.DEBUG_EXC = self._debug_exc self.DEBUG1 = self._debug_print if self.debug > 1: self.DEBUG2 = self._debug_print if self.debug > 2: self.DEBUG3 = self._debug_print return def _schedule(self): self.DEBUG3("_schedule():\n") self._cancel_polling() if self.__running: self._poll_event = scheduler.after(self._period, self._lock_and_poll_input) self.DEBUG3("_schedule: return\n") return def _drive_output(self, value, force=0): self._output_lock.acquire() try: if force: # Immediatly change the value. self._value = value self.output.set(value) else: # May be delayed by minimum on/off times. self._output(value) finally: self._output_lock.release() return def _output(self, value): value = value ^ self.reverse_output if self.enabled and (value is not self._value): self.DEBUG3("_drive_output: self.output=%s\n", self.output) if self._output_state == self._SAFETY: self._waiting_value = value else: self.output.set(value) self._waiting_value = None self._value = value if (value == 1) and self.min_on_time > 0: self._output_state = self._SAFETY scheduler.after(self.min_on_time, self._clear_safety, ()) self._changes_at = time.time() + self.min_on_time elif (value == 0) and self.min_off_time > 0: self._output_state = self._SAFETY scheduler.after(self.min_off_time, self._clear_safety, ()) self._changes_at = time.time() + self.min_off_time self.DEBUG2("_drive_output: set:%r, got:%r\n", value, self.output.get) else: self.DEBUG3("_drive_output: No change\n") self.DEBUG3("_drive_output: return\n") return def time_remaining(self): self._output_lock.acquire() try: if self._output_state == self._NORMAL: return 0 return self._changes_at - time.time() finally: self._output_lock.release() return def _clear_safety(self): self._output_lock.acquire() try: self._output_state = self._NORMAL if self._waiting_value != None: self._output(self._waiting_value) finally: self._output_lock.release() return def _cancel_polling(self): self.DEBUG3("_cancel_polling():\n") if self._poll_event is not None: e = self._poll_event self._poll_event = None if not e.expired(): e.cancel() self.DEBUG2("_cancel_polling: canceled %s\n", e) self.DEBUG3("_cancel_polling: return\n") return def _poll_input(self): self._poll_event = None self.DEBUG3("_poll_input():\n") # @fixme: Create n "priority" threads for schedulies to use. # ReadyTask(threads_queue, function), .__call_ -> add queue. if self.state is self.AUTO: try: self._drive_output(int(self.input.get())) except: # Start falling back... self.DEBUG_EXC("AUTO drive of output failed.") self._period = self._period * 2 self.DEBUG1("Adjusting period to every %s seconds.", self._period) else: if self.debug and self._period > self.period: self.DEBUG1("Restoring period to every %s seconds.", self.period) self._period = self.period self._schedule() else: value = int(self.state) self.DEBUG3("_poll_input: return\n") return def _lock_and_poll_input(self): self.DEBUG3("_lock_and_poll_input()\n") self._begin_critical_section() try: self._poll_input() finally: self._end_critical_section() self.DEBUG3("_lock_and_poll_input: return\n") return def _set_state(self, value): self.DEBUG3("_set_state(%r):\n", value) self.ENUM_LIST = [self.OFF, self.ON, self.AUTO] self.STR_LIST = [str(self.OFF), str(self.ON), str(self.AUTO)] if value not in self.ENUM_LIST: if value in self.STR_LIST: value = self.ENUM_LIST[self.STR_LIST.index(value)] else: exception = EInvalidValue('state', value) self.DEBUG3("_set_state: raise %r\n", exception) raise exception else: value = self.ENUM_LIST[self.ENUM_LIST.index(value)] self.state = value self.DEBUG3("_set_state: %r\n", self.state) return self.state def _debug_exc(self, fmt='', *args): _sys.stderr.write("EXCEPTION: %r\n" % (fmt % args)) _tb.print_exc(None, _sys.stderr) _sys.stderr.flush() return def _debug_print(self, fmt, *args): try: converted_args = [] for arg in args: if callable(arg): arg = arg() converted_args.append(arg) converted_args = tuple(converted_args) _sys.stderr.write("DEBUG(%r): %s" % (self._url, (fmt % converted_args))) _sys.stderr.flush() except: _sys.stderr.write("DEBUG FAILED: self.DEBUG(%r, %r)\n" % (fmt, args)) self._debug_exc() _sys.stderr.write("\tself._url: %r\n" % self._url) _sys.stderr.write("\tfmt: %r\n" % fmt) _sys.stderr.write("\tconverted_args: %r\n" % converted_args) _sys.stderr.flush() return def _debug_stub(self, fmt, *args): return ## # @see ConfigurableNode#configure # def configure(self, config): set_attribute(self, 'debug', self.debug, config, int) self._init_debug() self.DEBUG3("configure(%r):\n", config) # @fixme Add the option to output on change (default), output every # time, or the check the outputs state. ConfigurableNode.configure(self, config) self._url = as_node_url(self) if self.output is REQUIRED: self.output = self.parent set_attribute(self, 'off_text', self.off_text, config, str) set_attribute(self, 'on_text', self.on_text, config, str) set_attribute(self, 'auto_text', self.auto_text, config, str) set_attribute(self, 'reverse_output', self.reverse_output, config, int) set_attribute(self, 'output', self.parent, config, self.as_deferred_node) set_attribute(self, 'input', REQUIRED, config, self.as_deferred_node) set_attribute(self, 'period', self.period, config, float) set_attribute(self, 'asyncOK', self.asyncOK, config, int) set_attribute(self, 'state', self.state, config, self._set_state) set_attribute(self, 'enabled', 1, config, as_boolean) set_attribute(self, 'min_on_time', 0, config, float) set_attribute(self, 'min_off_time', 0, config, float) return ## # Get this objects configuration. # # @return Dictionary containg configuration. # @see ConfigurableNode#configuration # def configuration(self): config = ConfigurableNode.configuration(self) get_attribute(self, 'off_text', config, str) get_attribute(self, 'on_text', config, str) get_attribute(self, 'auto_text', config, str) get_attribute(self, 'reverse_output', config, str) get_attribute(self, 'output', config, self.as_deferred_node) get_attribute(self, 'input', config, as_node_url) get_attribute(self, 'period', config, str) get_attribute(self, 'asyncOK', config, str) get_attribute(self, 'state', config, str) get_attribute(self, 'debug', config, str) get_attribute(self, 'enabled', config, str) get_attribute(self, 'min_on_time', config, str) get_attribute(self, 'min_off_time', config, str) return config def start(self): self.DEBUG3("start():\n") self.OFF.text(self.off_text) self.ON.text(self.on_text) self.AUTO.text(self.auto_text) ConfigurableNode.start(self) self.__running = True self._begin_critical_section() try: self._poll_input() finally: self._end_critical_section() self.DEBUG3("start: return\n") return def stop(self): self.DEBUG3("stop():\n") ConfigurableNode.stop(self) self.__running = False self._begin_critical_section() try: self._cancel_polling() finally: self._end_critical_section() self.DEBUG3("stop: return\n") return def get_result(self, skipCache=0, **keywords): self.DEBUG3("get_result(skipCache=%r)\n", skipCache) result = Result() self._begin_critical_section() try: result.value = self.state finally: self._end_critical_section() result.timestamp = time.time() result.cached = not self.asyncOK self.DEBUG3("get_result: return %r\n", result) return result def disable(self): self._output_lock.acquire() try: self.enabled = 0 finally: self._output_lock.release() return def is_disabled(self): self._output_lock.acquire() try: return not self.enabled finally: self._output_lock.release() return def enable(self): self._output_lock.acquire() try: self.enabled = 1 finally: self._output_lock.release() return def is_enabled(self): self._output_lock.acquire() try: return self.enabled finally: self._output_lock.release() def set_min_on_time(self, min): self._output_lock.acquire() try: self.min_on_time = min finally: self._output_lock.release() return def get_min_on_time(self): return self.min_on_time def set_min_off_time(self, min): self._output_lock.acquire() try: self.min_off_time = min finally: self._output_lock.release() return def get_min_off_time(self): return self.min_off_time def get(self, skipCache=0): self._begin_critical_section() try: result = self.state finally: self._end_critical_section() self.DEBUG3("get(skipCache=%r): return %r\n", skipCache, result) return result def states(self): self.DEBUG3("states():\n") list = [] list.extend(self.ENUM_LIST) self.DEBUG3("states: return %r\n", list) return list def set(self, value, asyncOK=1): self.DEBUG3("set(%r, asyncOK=%r):\n", value, asyncOK) self._begin_critical_section() try: self._set_state(value) self.asyncOK = asyncOK self._cancel_polling() if self.state == self.AUTO: self._poll_input() else: # Explicitly set ON/OFF states bypass the minimum on/off times. self._drive_output(int(self.state), 1) self.DEBUG3("set: return\n") finally: self._end_critical_section() return def as_deferred_node(self, node_ref): #set_attribute does not pass THIS node in for relative URLs return as_deferred_node(node_ref, self)
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 }
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), ))
def __init__(self, value, text, data_type='UCHAR'): EnumeratedValue.__init__(self, value, text) self.data_type = _data_types[data_type] # use ref to EnumValue return