Esempio n. 1
0
 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
Esempio n. 2
0
 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
Esempio n. 3
0
 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
Esempio n. 4
0
 def __new__(klass,
             value,
             text,
             data_type='NONE',
             default=0,
             max_insts=1,
             prop_types=None):
     return EnumeratedValue.__new__(klass, value, text)
Esempio n. 5
0
 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
Esempio n. 6
0
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:
Esempio n. 7
0
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
Esempio n. 8
0
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)
Esempio n. 9
0
 def __new__(klass, value, text, data_type='NONE', default=0, max_insts=1, prop_types=None):
    return EnumeratedValue.__new__(klass, value, text)
Esempio n. 10
0
    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]
Esempio n. 11
0
 def __new__(klass, value, text, obj_types):
    return EnumeratedValue.__new__(klass, value, text)
Esempio n. 12
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
Esempio n. 13
0
 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)
Esempio n. 14
0
 def test_dumps_enumerated_value(self):
     print "\n", 60 * "-"
     print dumps((EnumeratedValue(12, 'twelve'), ))
     print 60 * "-"
Esempio n. 15
0
 def __new__(klass, value, text, obj_types):
     return EnumeratedValue.__new__(klass, value, text)
Esempio n. 16
0
 def __init__(self, value, text, obj_types):
     EnumeratedValue.__init__(self, value, text)
     self.obj_types = obj_types
     return
Esempio n. 17
0
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)
Esempio n. 18
0
 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)
Esempio n. 19
0
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
    }
Esempio n. 20
0
 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)
Esempio n. 21
0
 def __init__(self, value, text, obj_types):
    EnumeratedValue.__init__(self, value, text)
    self.obj_types = obj_types
    return
Esempio n. 22
0
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), ))
Esempio n. 23
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