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.config import Config
|
||||||
from owrx.locator import Locator
|
from owrx.locator import Locator
|
||||||
from owrx.property import PropertyFilter
|
from owrx.property import PropertyFilter
|
||||||
|
from owrx.property.filter import ByPropertyName
|
||||||
|
|
||||||
|
|
||||||
class ReceiverDetails(PropertyFilter):
|
class ReceiverDetails(PropertyFilter):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
Config.get(),
|
Config.get(),
|
||||||
"receiver_name",
|
ByPropertyName(
|
||||||
"receiver_location",
|
"receiver_name",
|
||||||
"receiver_asl",
|
"receiver_location",
|
||||||
"receiver_gps",
|
"receiver_asl",
|
||||||
"photo_title",
|
"receiver_gps",
|
||||||
"photo_desc",
|
"photo_title",
|
||||||
|
"photo_desc",
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def __dict__(self):
|
def __dict__(self):
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from owrx.property.validators import Validator
|
from owrx.property.validators import Validator
|
||||||
|
from owrx.property.filter import Filter, ByPropertyName
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -60,7 +61,7 @@ class PropertyManager(ABC):
|
|||||||
return self.__dict__().__len__()
|
return self.__dict__().__len__()
|
||||||
|
|
||||||
def filter(self, *props):
|
def filter(self, *props):
|
||||||
return PropertyFilter(self, *props)
|
return PropertyFilter(self, ByPropertyName(*props))
|
||||||
|
|
||||||
def readonly(self):
|
def readonly(self):
|
||||||
return PropertyReadOnly(self)
|
return PropertyReadOnly(self)
|
||||||
@ -132,41 +133,41 @@ class PropertyLayer(PropertyManager):
|
|||||||
|
|
||||||
|
|
||||||
class PropertyFilter(PropertyManager):
|
class PropertyFilter(PropertyManager):
|
||||||
def __init__(self, pm: PropertyManager, *props: str):
|
def __init__(self, pm: PropertyManager, filter: Filter):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.pm = pm
|
self.pm = pm
|
||||||
self.props = props
|
self._filter = filter
|
||||||
self.pm.wire(self.receiveEvent)
|
self.pm.wire(self.receiveEvent)
|
||||||
|
|
||||||
def receiveEvent(self, changes):
|
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)
|
self._fireCallbacks(changesToForward)
|
||||||
|
|
||||||
def __getitem__(self, item):
|
def __getitem__(self, item):
|
||||||
if item not in self.props:
|
if not self._filter.apply(item):
|
||||||
raise KeyError(item)
|
raise KeyError(item)
|
||||||
return self.pm.__getitem__(item)
|
return self.pm.__getitem__(item)
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
if key not in self.props:
|
if not self._filter.apply(key):
|
||||||
raise KeyError(key)
|
raise KeyError(key)
|
||||||
return self.pm.__setitem__(key, value)
|
return self.pm.__setitem__(key, value)
|
||||||
|
|
||||||
def __contains__(self, item):
|
def __contains__(self, item):
|
||||||
if item not in self.props:
|
if not self._filter.apply(item):
|
||||||
return False
|
return False
|
||||||
return self.pm.__contains__(item)
|
return self.pm.__contains__(item)
|
||||||
|
|
||||||
def __dict__(self):
|
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):
|
def __delitem__(self, key):
|
||||||
if key not in self.props:
|
if not self._filter.apply(key):
|
||||||
raise KeyError(key)
|
raise KeyError(key)
|
||||||
return self.pm.__delitem__(key)
|
return self.pm.__delitem__(key)
|
||||||
|
|
||||||
def keys(self):
|
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):
|
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 abc import ABC, abstractmethod
|
||||||
from owrx.command import CommandMapper
|
from owrx.command import CommandMapper
|
||||||
from owrx.socket import getAvailablePort
|
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 import Input, TextInput, NumberInput, CheckboxInput, ModesInput
|
||||||
from owrx.form.converter import OptionalConverter
|
from owrx.form.converter import OptionalConverter
|
||||||
from owrx.form.device import GainInput
|
from owrx.form.device import GainInput
|
||||||
@ -96,6 +97,9 @@ class SdrSource(ABC):
|
|||||||
if self.isAlwaysOn() and self.state is not SdrSourceState.DISABLED:
|
if self.isAlwaysOn() and self.state is not SdrSourceState.DISABLED:
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
|
def _loadProfile(self, profile):
|
||||||
|
self.props.replaceLayer(0, PropertyFilter(profile, ByLambda(lambda x: x != "name")))
|
||||||
|
|
||||||
def validateProfiles(self):
|
def validateProfiles(self):
|
||||||
props = PropertyStack()
|
props = PropertyStack()
|
||||||
props.addLayer(1, self.props)
|
props.addLayer(1, self.props)
|
||||||
@ -155,7 +159,7 @@ class SdrSource(ABC):
|
|||||||
profile = profiles[profile_id]
|
profile = profiles[profile_id]
|
||||||
self.profile_id = profile_id
|
self.profile_id = profile_id
|
||||||
|
|
||||||
self.props.replaceLayer(0, profile)
|
self._loadProfile(profile)
|
||||||
|
|
||||||
def getId(self):
|
def getId(self):
|
||||||
return self.id
|
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):
|
def testPassesProperty(self):
|
||||||
pm = PropertyLayer()
|
pm = PropertyLayer()
|
||||||
pm["testkey"] = "testvalue"
|
pm["testkey"] = "testvalue"
|
||||||
pf = PropertyFilter(pm, "testkey")
|
mock = Mock()
|
||||||
|
mock.apply.return_value = True
|
||||||
|
pf = PropertyFilter(pm, mock)
|
||||||
self.assertEqual(pf["testkey"], "testvalue")
|
self.assertEqual(pf["testkey"], "testvalue")
|
||||||
|
|
||||||
def testMissesProperty(self):
|
def testMissesProperty(self):
|
||||||
pm = PropertyLayer()
|
pm = PropertyLayer()
|
||||||
pm["testkey"] = "testvalue"
|
pm["testkey"] = "testvalue"
|
||||||
pf = PropertyFilter(pm, "other_key")
|
mock = Mock()
|
||||||
|
mock.apply.return_value = False
|
||||||
|
pf = PropertyFilter(pm, mock)
|
||||||
self.assertFalse("testkey" in pf)
|
self.assertFalse("testkey" in pf)
|
||||||
with self.assertRaises(KeyError):
|
with self.assertRaises(KeyError):
|
||||||
x = pf["testkey"]
|
x = pf["testkey"]
|
||||||
|
|
||||||
def testForwardsEvent(self):
|
def testForwardsEvent(self):
|
||||||
pm = PropertyLayer()
|
pm = PropertyLayer()
|
||||||
pf = PropertyFilter(pm, "testkey")
|
mock = Mock()
|
||||||
|
mock.apply.return_value = True
|
||||||
|
pf = PropertyFilter(pm, mock)
|
||||||
mock = Mock()
|
mock = Mock()
|
||||||
pf.wire(mock.method)
|
pf.wire(mock.method)
|
||||||
pm["testkey"] = "testvalue"
|
pm["testkey"] = "testvalue"
|
||||||
@ -28,7 +34,9 @@ class PropertyFilterTest(TestCase):
|
|||||||
|
|
||||||
def testForwardsPropertyEvent(self):
|
def testForwardsPropertyEvent(self):
|
||||||
pm = PropertyLayer()
|
pm = PropertyLayer()
|
||||||
pf = PropertyFilter(pm, "testkey")
|
mock = Mock()
|
||||||
|
mock.apply.return_value = True
|
||||||
|
pf = PropertyFilter(pm, mock)
|
||||||
mock = Mock()
|
mock = Mock()
|
||||||
pf.wireProperty("testkey", mock.method)
|
pf.wireProperty("testkey", mock.method)
|
||||||
pm["testkey"] = "testvalue"
|
pm["testkey"] = "testvalue"
|
||||||
@ -36,7 +44,9 @@ class PropertyFilterTest(TestCase):
|
|||||||
|
|
||||||
def testForwardsWrite(self):
|
def testForwardsWrite(self):
|
||||||
pm = PropertyLayer()
|
pm = PropertyLayer()
|
||||||
pf = PropertyFilter(pm, "testkey")
|
mock = Mock()
|
||||||
|
mock.apply.return_value = True
|
||||||
|
pf = PropertyFilter(pm, mock)
|
||||||
pf["testkey"] = "testvalue"
|
pf["testkey"] = "testvalue"
|
||||||
self.assertTrue("testkey" in pm)
|
self.assertTrue("testkey" in pm)
|
||||||
self.assertEqual(pm["testkey"], "testvalue")
|
self.assertEqual(pm["testkey"], "testvalue")
|
||||||
@ -44,7 +54,9 @@ class PropertyFilterTest(TestCase):
|
|||||||
def testOverwrite(self):
|
def testOverwrite(self):
|
||||||
pm = PropertyLayer()
|
pm = PropertyLayer()
|
||||||
pm["testkey"] = "old value"
|
pm["testkey"] = "old value"
|
||||||
pf = PropertyFilter(pm, "testkey")
|
mock = Mock()
|
||||||
|
mock.apply.return_value = True
|
||||||
|
pf = PropertyFilter(pm, mock)
|
||||||
pf["testkey"] = "new value"
|
pf["testkey"] = "new value"
|
||||||
self.assertEqual(pm["testkey"], "new value")
|
self.assertEqual(pm["testkey"], "new value")
|
||||||
self.assertEqual(pf["testkey"], "new value")
|
self.assertEqual(pf["testkey"], "new value")
|
||||||
@ -52,7 +64,9 @@ class PropertyFilterTest(TestCase):
|
|||||||
def testRejectsWrite(self):
|
def testRejectsWrite(self):
|
||||||
pm = PropertyLayer()
|
pm = PropertyLayer()
|
||||||
pm["testkey"] = "old value"
|
pm["testkey"] = "old value"
|
||||||
pf = PropertyFilter(pm, "otherkey")
|
mock = Mock()
|
||||||
|
mock.apply.return_value = False
|
||||||
|
pf = PropertyFilter(pm, mock)
|
||||||
with self.assertRaises(KeyError):
|
with self.assertRaises(KeyError):
|
||||||
pf["testkey"] = "new value"
|
pf["testkey"] = "new value"
|
||||||
self.assertEqual(pm["testkey"], "old value")
|
self.assertEqual(pm["testkey"], "old value")
|
||||||
|
Loading…
Reference in New Issue
Block a user