Commits

Simon Cross committed e4b882f

(simon, fijal) Merge sensor-value-as-tuple branch.

  • Participants
  • Parent commits d644380

Comments (0)

Files changed (5)

File katcp/core.py

 import sys
 import re
 import time
+import warnings
 
 class Message(object):
     """Represents a KAT device control language message.
 
         self._sensor_type = sensor_type
         self._observers = set()
-        self._timestamp = time.time()
-        self._status = Sensor.UNKNOWN
 
-        typeclass, self._value = self.SENSOR_TYPES[sensor_type]
+        typeclass, default_value = self.SENSOR_TYPES[sensor_type]
 
         if self._sensor_type in [Sensor.INTEGER, Sensor.FLOAT]:
-            if not params[0] <= self._value <= params[1]:
-                self._value = params[0]
+            if not params[0] <= default_value <= params[1]:
+                default_value = params[0]
             self._kattype = typeclass(params[0], params[1])
         elif self._sensor_type == Sensor.DISCRETE:
-            self._value = params[0]
+            default_value = params[0]
             self._kattype = typeclass(params)
         else:
             self._kattype = typeclass()
 
+        if default is not None:
+            default_value = default
+
+        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+        # self._value_tuple should also be set and read in a single
+        # bytecode to avoid situations were an update in one thread
+        # causes another thread to read the timestamp from one update
+        # and the value and/or status from a different update.
+        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+        self._value_tuple = (time.time(), Sensor.UNKNOWN, default_value)
         self._formatter = self._kattype.pack
         self._parser = self._kattype.unpack
         self.stype = self._kattype.name
         self.params = params
         self.formatted_params = [self._formatter(p, True) for p in params]
 
-        if default is not None:
-            self._value = default
+    # support for legacy KATCP users that relied on being able to
+    # read _timestamp, _status and _value. Such usage will be
+    # deprecated in a future version of KATCP.
+
+    def _value_tuple_getter(i, name):
+        def getter(self):
+            warnings.warn("Use of katcp.Sensor.%s attribute is deprecated"
+                          % name, DeprecationWarning)
+            return self._value_tuple[i]
+        return getter
+
+    _timestamp = property(_value_tuple_getter(0, "_timestamp"))
+    _status = property(_value_tuple_getter(1, "_status"))
+    _value = property(_value_tuple_getter(2, "_value"))
+
+    del _value_tuple_getter
 
     def __repr__(self):
         cls = self.__class__
             The value of the sensor (the type should be appropriate to the
             sensor's type).
         """
-        self._timestamp, self._status, self._value = timestamp, status, value
+        self._value_tuple = (timestamp, status, value)
         self.notify()
 
     def set_formatted(self, raw_timestamp, raw_status, raw_value):
             The value of the sensor (the type will be appropriate to the
             sensor's type).
         """
-        return (self._timestamp, self._status, self._value)
+        return self._value_tuple
 
     def set_value(self, value, status=NOMINAL, timestamp=None):
         """Check and then set the value of the sensor.

File katcp/sampling.py

         if self._nextTime is not None and (self._nextTime > now):
             return
 
-        if sensor._status != self._lastStatus or sensor._value != self._lastValue:
-            self._lastStatus = sensor._status
-            self._lastValue = sensor._value
+        _timestamp, status, value = sensor.read()
+        if status != self._lastStatus or value != self._lastValue:
+            self._lastStatus = status
+            self._lastValue = value
             if self._minTimeSep:
                 self._nextTime = now + self._minTimeSep
             self.inform()
         self._lastValue = None
 
     def update(self, sensor):
-        if sensor._status != self._lastStatus or abs(sensor._value - self._lastValue) > self._threshold:
-            self._lastStatus = sensor._status
-            self._lastValue = sensor._value
+        _timestamp, status, value = sensor.read()
+        if status != self._lastStatus or abs(value - self._lastValue) > self._threshold:
+            self._lastStatus = status
+            self._lastValue = value
             self.inform()
 
     def get_sampling(self):
         if period_ms <= 0:
             raise ValueError("The period must be a positive integer in ms.")
         self._period = period_ms / SamplePeriod.MILLISECOND
-        self._status = sensor._status
-        self._value = sensor._value
 
     def periodic(self, timestamp):
         self.inform()

File katcp/tx/sampling.py

 class EventStrategy(ObserverStrategy):
     def __init__(self, protocol, sensor):
         ObserverStrategy.__init__(self, protocol, sensor)
-        self.value = sensor.value()
-        self.status = sensor._status
+        _timestamp, self.status, self.value = sensor.read()
 
     def update(self, sensor):
-        newval = sensor.value()
-        newstatus = sensor._status
+        _timestamp, newval, newstatus = sensor.read()
         if self.status != newstatus or self.value != newval:
             self.status = newstatus
             self.value = newval
 class DifferentialStrategy(ObserverStrategy):
     def __init__(self, protocol, sensor):
         ObserverStrategy.__init__(self, protocol, sensor)
-        self.value = sensor.value()
-        self.status = sensor._status
+        _timestamp, self.status, self.value = sensor.read()
 
     def run(self, threshold):
         self.threshold = float(threshold)
         ObserverStrategy.run(self)
 
     def update(self, sensor):
-        newval = sensor.value()
-        newstatus = sensor._status
+        _timestamp, newstatus, newval = sensor.read()
         if (self.status != newstatus or
             abs(self.value - newval) > self.threshold):
             self.protocol.send_sensor_status(sensor)

File katcp/tx/test/test_core.py

     def setup_sensors(self):
         sensor = Sensor(int, 'int_sensor', 'descr', 'unit',
                         params=[-10, 10])
-        sensor._timestamp = 0
+        sensor.set_value(sensor.value(), status=Sensor.UNKNOWN, timestamp=0)
         self.add_sensor(sensor)
         sensor = Sensor(float, 'float_sensor', 'descr', 'unit',
                         params=[-3.5, 3.5])
-        sensor._timestamp = 1
+        sensor.set_value(sensor.value(), status=Sensor.UNKNOWN, timestamp=1)
         self.add_sensor(sensor)
 
 class TestClientKatCP(ClientKatCPProtocol):
             self.assertEquals(informs, [Message.inform('sensor-value', '0',
                                                        '1', 'int_sensor',
                                                        'nominal', '3')])
-            self.factory.sensors['int_sensor'].set_value(5)
-            self.factory.sensors['int_sensor']._timestamp = 0
+            self.factory.sensors['int_sensor'].set(0, Sensor.NOMINAL, 5)
             protocol.send_request('sensor-value',
                                   'int_sensor').addCallback(even_more, protocol)
 
                                                    'int_sensor', 'auto'))
             self.assertEquals(len(self.client.status_updates), 0)
 
-            self.factory.sensors['int_sensor'].set_value(3)
-            self.factory.sensors['int_sensor']._timestamp = 0
+            self.factory.sensors['int_sensor'].set(0, Sensor.NOMINAL, 3)
             protocol.send_request('sensor-value',
                                   'int_sensor').addCallback(more, protocol)
             return True
             self.assertEquals(informs, [Message.inform('sensor-value', '0',
                                                        '1', 'int_sensor',
                                                        'nominal', '3')])
-            self.factory.sensors['int_sensor'].set_value(3)
-            self.factory.sensors['int_sensor']._timestamp = 0
+            self.factory.sensors['int_sensor'].set_value(3, timestamp=0)
             protocol.send_request('sensor-value',
                                   'int_sensor').addCallback(even_more, protocol)
 
                                                    'int_sensor', 'event'))
             self.assertEquals(len(self.client.status_updates), 0)
 
-            self.factory.sensors['int_sensor'].set_value(3)
-            self.factory.sensors['int_sensor']._timestamp = 0
+            self.factory.sensors['int_sensor'].set_value(3, timestamp=0)
             protocol.send_request('sensor-value',
                                   'int_sensor').addCallback(more, protocol)
             return True
             self.assertEquals(informs, [Message.inform('sensor-value', '0',
                                                        '1', 'int_sensor',
                                                        'nominal', '2')])
-            self.factory.sensors['int_sensor'].set_value(5)
-            self.factory.sensors['int_sensor']._timestamp = 0
+            self.factory.sensors['int_sensor'].set_value(5, timestamp=0)
             protocol.send_request('sensor-value',
                                   'int_sensor').addCallback(second, protocol)
 
             self.assertEquals(informs, [Message.inform('sensor-value', '0',
                                                        '1', 'int_sensor',
                                                        'nominal', '5')])
-            self.factory.sensors['int_sensor'].set_value(10)
-            self.factory.sensors['int_sensor']._timestamp = 0
+            self.factory.sensors['int_sensor'].set_value(10, timestamp=0)
             protocol.send_request('sensor-value',
                                   'int_sensor').addCallback(third, protocol)
 
                                                    'differential', '3'))
             self.assertEquals(len(self.client.status_updates), 0)
 
-            self.factory.sensors['int_sensor'].set_value(2)
-            self.factory.sensors['int_sensor']._timestamp = 0
+            self.factory.sensors['int_sensor'].set_value(2, timestamp=0)
             protocol.send_request('sensor-value',
                                   'int_sensor').addCallback(first, protocol)
             return True

File katcp/tx/test/test_proxy.py

     def setup_sensors(self):
         sensor = Sensor(int, "sensor1", "Test sensor 1", "count",
                         [0,10])
-        sensor._timestamp = 1
+        sensor.set_value(sensor.value(), status=Sensor.UNKNOWN, timestamp=1)
         self.add_sensor(sensor)
         sensor2 = Sensor(int, "sensor2", "Test sensor 2", "count",
                          [0, 10])
-        sensor2._timestamp = 0
+        sensor2.set_value(sensor.value(), status=Sensor.UNKNOWN, timestamp=0)
         self.add_sensor(sensor2)
 
 class MyDeviceHandler(DeviceHandler):