create filtering that prevents overwriting the device name
This commit is contained in:
parent
4199a583f8
commit
f69d78926e
@ -1,18 +1,21 @@
|
||||
from owrx.config import Config
|
||||
from owrx.locator import Locator
|
||||
from owrx.property import PropertyFilter
|
||||
from owrx.property.filter import ByPropertyName
|
||||
|
||||
|
||||
class ReceiverDetails(PropertyFilter):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
Config.get(),
|
||||
"receiver_name",
|
||||
"receiver_location",
|
||||
"receiver_asl",
|
||||
"receiver_gps",
|
||||
"photo_title",
|
||||
"photo_desc",
|
||||
ByPropertyName(
|
||||
"receiver_name",
|
||||
"receiver_location",
|
||||
"receiver_asl",
|
||||
"receiver_gps",
|
||||
"photo_title",
|
||||
"photo_desc",
|
||||
)
|
||||
)
|
||||
|
||||
def __dict__(self):
|
||||
|
@ -1,5 +1,6 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from owrx.property.validators import Validator
|
||||
from owrx.property.filter import Filter, ByPropertyName
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -60,7 +61,7 @@ class PropertyManager(ABC):
|
||||
return self.__dict__().__len__()
|
||||
|
||||
def filter(self, *props):
|
||||
return PropertyFilter(self, *props)
|
||||
return PropertyFilter(self, ByPropertyName(*props))
|
||||
|
||||
def readonly(self):
|
||||
return PropertyReadOnly(self)
|
||||
@ -132,41 +133,41 @@ class PropertyLayer(PropertyManager):
|
||||
|
||||
|
||||
class PropertyFilter(PropertyManager):
|
||||
def __init__(self, pm: PropertyManager, *props: str):
|
||||
def __init__(self, pm: PropertyManager, filter: Filter):
|
||||
super().__init__()
|
||||
self.pm = pm
|
||||
self.props = props
|
||||
self._filter = filter
|
||||
self.pm.wire(self.receiveEvent)
|
||||
|
||||
def receiveEvent(self, changes):
|
||||
changesToForward = {name: value for name, value in changes.items() if name in self.props}
|
||||
changesToForward = {name: value for name, value in changes.items() if self._filter.apply(name)}
|
||||
self._fireCallbacks(changesToForward)
|
||||
|
||||
def __getitem__(self, item):
|
||||
if item not in self.props:
|
||||
if not self._filter.apply(item):
|
||||
raise KeyError(item)
|
||||
return self.pm.__getitem__(item)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key not in self.props:
|
||||
if not self._filter.apply(key):
|
||||
raise KeyError(key)
|
||||
return self.pm.__setitem__(key, value)
|
||||
|
||||
def __contains__(self, item):
|
||||
if item not in self.props:
|
||||
if not self._filter.apply(item):
|
||||
return False
|
||||
return self.pm.__contains__(item)
|
||||
|
||||
def __dict__(self):
|
||||
return {k: v for k, v in self.pm.__dict__().items() if k in self.props}
|
||||
return {k: v for k, v in self.pm.__dict__().items() if self._filter.apply(k)}
|
||||
|
||||
def __delitem__(self, key):
|
||||
if key not in self.props:
|
||||
if not self._filter.apply(key):
|
||||
raise KeyError(key)
|
||||
return self.pm.__delitem__(key)
|
||||
|
||||
def keys(self):
|
||||
return [k for k in self.pm.keys() if k in self.props]
|
||||
return [k for k in self.pm.keys() if self._filter.apply(k)]
|
||||
|
||||
|
||||
class PropertyDelegator(PropertyManager):
|
||||
|
23
owrx/property/filter.py
Normal file
23
owrx/property/filter.py
Normal file
@ -0,0 +1,23 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class Filter(ABC):
|
||||
@abstractmethod
|
||||
def apply(self, prop) -> bool:
|
||||
pass
|
||||
|
||||
|
||||
class ByPropertyName(Filter):
|
||||
def __init__(self, *props):
|
||||
self.props = props
|
||||
|
||||
def apply(self, prop) -> bool:
|
||||
return prop in self.props
|
||||
|
||||
|
||||
class ByLambda(Filter):
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
|
||||
def apply(self, prop) -> bool:
|
||||
return self.func(prop)
|
@ -9,7 +9,8 @@ import signal
|
||||
from abc import ABC, abstractmethod
|
||||
from owrx.command import CommandMapper
|
||||
from owrx.socket import getAvailablePort
|
||||
from owrx.property import PropertyStack, PropertyLayer
|
||||
from owrx.property import PropertyStack, PropertyLayer, PropertyFilter
|
||||
from owrx.property.filter import ByLambda
|
||||
from owrx.form import Input, TextInput, NumberInput, CheckboxInput, ModesInput
|
||||
from owrx.form.converter import OptionalConverter
|
||||
from owrx.form.device import GainInput
|
||||
@ -96,6 +97,9 @@ class SdrSource(ABC):
|
||||
if self.isAlwaysOn() and self.state is not SdrSourceState.DISABLED:
|
||||
self.start()
|
||||
|
||||
def _loadProfile(self, profile):
|
||||
self.props.replaceLayer(0, PropertyFilter(profile, ByLambda(lambda x: x != "name")))
|
||||
|
||||
def validateProfiles(self):
|
||||
props = PropertyStack()
|
||||
props.addLayer(1, self.props)
|
||||
@ -155,7 +159,7 @@ class SdrSource(ABC):
|
||||
profile = profiles[profile_id]
|
||||
self.profile_id = profile_id
|
||||
|
||||
self.props.replaceLayer(0, profile)
|
||||
self._loadProfile(profile)
|
||||
|
||||
def getId(self):
|
||||
return self.id
|
||||
|
0
test/property/filter/__init__.py
Normal file
0
test/property/filter/__init__.py
Normal file
17
test/property/filter/test_by_lambda.py
Normal file
17
test/property/filter/test_by_lambda.py
Normal file
@ -0,0 +1,17 @@
|
||||
from owrx.property.filter import ByLambda
|
||||
from unittest import TestCase
|
||||
from unittest.mock import Mock
|
||||
|
||||
|
||||
class TestByLambda(TestCase):
|
||||
def testPositive(self):
|
||||
mock = Mock(return_value=True)
|
||||
filter = ByLambda(mock)
|
||||
self.assertTrue(filter.apply("test_key"))
|
||||
mock.assert_called_with("test_key")
|
||||
|
||||
def testNegateive(self):
|
||||
mock = Mock(return_value=False)
|
||||
filter = ByLambda(mock)
|
||||
self.assertFalse(filter.apply("test_key"))
|
||||
mock.assert_called_with("test_key")
|
12
test/property/filter/test_by_property_name.py
Normal file
12
test/property/filter/test_by_property_name.py
Normal file
@ -0,0 +1,12 @@
|
||||
from owrx.property.filter import ByPropertyName
|
||||
from unittest import TestCase
|
||||
|
||||
|
||||
class ByPropertyNameTest(TestCase):
|
||||
def testNameIsInList(self):
|
||||
filter = ByPropertyName("test_key")
|
||||
self.assertTrue(filter.apply("test_key"))
|
||||
|
||||
def testNameNotInList(self):
|
||||
filter = ByPropertyName("test_key")
|
||||
self.assertFalse(filter.apply("other_key"))
|
@ -7,20 +7,26 @@ class PropertyFilterTest(TestCase):
|
||||
def testPassesProperty(self):
|
||||
pm = PropertyLayer()
|
||||
pm["testkey"] = "testvalue"
|
||||
pf = PropertyFilter(pm, "testkey")
|
||||
mock = Mock()
|
||||
mock.apply.return_value = True
|
||||
pf = PropertyFilter(pm, mock)
|
||||
self.assertEqual(pf["testkey"], "testvalue")
|
||||
|
||||
def testMissesProperty(self):
|
||||
pm = PropertyLayer()
|
||||
pm["testkey"] = "testvalue"
|
||||
pf = PropertyFilter(pm, "other_key")
|
||||
mock = Mock()
|
||||
mock.apply.return_value = False
|
||||
pf = PropertyFilter(pm, mock)
|
||||
self.assertFalse("testkey" in pf)
|
||||
with self.assertRaises(KeyError):
|
||||
x = pf["testkey"]
|
||||
|
||||
def testForwardsEvent(self):
|
||||
pm = PropertyLayer()
|
||||
pf = PropertyFilter(pm, "testkey")
|
||||
mock = Mock()
|
||||
mock.apply.return_value = True
|
||||
pf = PropertyFilter(pm, mock)
|
||||
mock = Mock()
|
||||
pf.wire(mock.method)
|
||||
pm["testkey"] = "testvalue"
|
||||
@ -28,7 +34,9 @@ class PropertyFilterTest(TestCase):
|
||||
|
||||
def testForwardsPropertyEvent(self):
|
||||
pm = PropertyLayer()
|
||||
pf = PropertyFilter(pm, "testkey")
|
||||
mock = Mock()
|
||||
mock.apply.return_value = True
|
||||
pf = PropertyFilter(pm, mock)
|
||||
mock = Mock()
|
||||
pf.wireProperty("testkey", mock.method)
|
||||
pm["testkey"] = "testvalue"
|
||||
@ -36,7 +44,9 @@ class PropertyFilterTest(TestCase):
|
||||
|
||||
def testForwardsWrite(self):
|
||||
pm = PropertyLayer()
|
||||
pf = PropertyFilter(pm, "testkey")
|
||||
mock = Mock()
|
||||
mock.apply.return_value = True
|
||||
pf = PropertyFilter(pm, mock)
|
||||
pf["testkey"] = "testvalue"
|
||||
self.assertTrue("testkey" in pm)
|
||||
self.assertEqual(pm["testkey"], "testvalue")
|
||||
@ -44,7 +54,9 @@ class PropertyFilterTest(TestCase):
|
||||
def testOverwrite(self):
|
||||
pm = PropertyLayer()
|
||||
pm["testkey"] = "old value"
|
||||
pf = PropertyFilter(pm, "testkey")
|
||||
mock = Mock()
|
||||
mock.apply.return_value = True
|
||||
pf = PropertyFilter(pm, mock)
|
||||
pf["testkey"] = "new value"
|
||||
self.assertEqual(pm["testkey"], "new value")
|
||||
self.assertEqual(pf["testkey"], "new value")
|
||||
@ -52,7 +64,9 @@ class PropertyFilterTest(TestCase):
|
||||
def testRejectsWrite(self):
|
||||
pm = PropertyLayer()
|
||||
pm["testkey"] = "old value"
|
||||
pf = PropertyFilter(pm, "otherkey")
|
||||
mock = Mock()
|
||||
mock.apply.return_value = False
|
||||
pf = PropertyFilter(pm, mock)
|
||||
with self.assertRaises(KeyError):
|
||||
pf["testkey"] = "new value"
|
||||
self.assertEqual(pm["testkey"], "old value")
|
||||
|
Loading…
Reference in New Issue
Block a user