Skip to content

Commit

Permalink
Merge pull request #77 from masenf/allow-invalid-tone
Browse files Browse the repository at this point in the history
Allow invalid tone
  • Loading branch information
masenf committed Aug 29, 2021
2 parents bdb3256 + f4a7534 commit 7807632
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 5 deletions.
5 changes: 5 additions & 0 deletions src/dzcb/k7abd.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
Talkgroup,
Zone,
)
import dzcb.tone


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -321,6 +322,10 @@ def Codeplug_from_k7abd(input_dir):
talkgroups = {}
all_talkgroups_by_name = {}
total_files = 0
if not dzcb.tone.REQUIRE_VALID_TONE:
logger.warning(
"REQUIRE_VALID_TONE=0: resulting codeplug files may contain invalid entries"
)
for p in sorted(d.glob("Analog__*.csv")):
update_zones_channels(
zones, Analog_from_csv(p.read_text().splitlines()), log_filename=p
Expand Down
16 changes: 14 additions & 2 deletions src/dzcb/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@ def flattened(self, allowed_powers):
"No known powers are allowed {!r} from {!r}".format(self, allowed_powers)
)

@classmethod
def from_any(cls, v):
"""Passable as an attr converter."""
if isinstance(v, str):
# use title case string
v = v.title()
return super(Power, cls).from_any(v)


class Bandwidth(ConvertibleEnum):
_125 = "12.5"
Expand Down Expand Up @@ -234,9 +242,13 @@ def transmit_frequency(self):

def _tone_validator(instance, attribute, value):
if value is not None and value not in dzcb.tone.VALID_TONES:
raise ValueError(
"field {!r} has unknown tone {!r}".format(attribute.name, value)
message = "field {!r} for {} has unknown tone {!r}".format(
attribute.name, instance.name, value
)
if dzcb.tone.REQUIRE_VALID_TONE:
raise ValueError(message)
else:
logger.warning(message)


def _tone_converter(value):
Expand Down
6 changes: 6 additions & 0 deletions src/dzcb/tone.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
"""All valid PL / DCS tones"""

from .util import getenv_bool

# set REQUIRE_VALID_TONE=0 in the environment to write non-valid tones
# into codeplug output files
REQUIRE_VALID_TONE = getenv_bool("REQUIRE_VALID_TONE", default=True)

VALID_TONES = [
"67.0",
"69.3",
Expand Down
28 changes: 28 additions & 0 deletions src/dzcb/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import os


STR_TO_BOOL = {
"false": False,
"no": False,
"off": False,
"0": False,
0: False,
"true": True,
"yes": True,
"on": True,
"1": True,
1: True,
}


def getenv_bool(var_name, default=False):
"""
Retrieve the given environment variable as a bool.
Will use the text translation table STR_TO_BOOL to facilitate the conversion
so that "yes"/"no" and "on"/"off" can also be used.
"""
val = os.environ.get(var_name, None)
if val is None:
return default
return STR_TO_BOOL[val.lower()]
28 changes: 25 additions & 3 deletions tests/test_k7abd.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,23 @@ def test_digital_channels_missing_talkgroup():
assert ch0tg.timeslot == Timeslot.ONE


def test_analog_weird_values():
@pytest.fixture(params=[True, False])
def require_valid_tone(request, monkeypatch):
import dzcb.tone

monkeypatch.setattr(dzcb.tone, "REQUIRE_VALID_TONE", request.param)
return request.param


def test_analog_weird_values(require_valid_tone):
"""
test validation of fields in the csv file
"""

cp = codeplug_from_relative_dir("analog-weird-values").filter()

assert len(cp.zones) == 6
assert len(cp.channels) == 6
assert len(cp.zones) == 6 if require_valid_tone else 9
assert len(cp.channels) == 6 if require_valid_tone else 9

for ch in cp.channels:
if ch.name in ("off", "blank"):
Expand All @@ -111,6 +119,20 @@ def test_analog_weird_values():
elif ch.name == "split-tone":
assert ch.tone_decode == "74.4"
assert ch.tone_encode == "254.1"
if require_valid_tone:
assert ch.name != "restricted-in"
assert ch.name != "restricted-out"
assert ch.name != "sixty-nine"
else:
if ch.name == "restricted-in":
assert ch.tone_decode == "restricted"
assert ch.tone_encode is None
elif ch.name == "restricted-out":
assert ch.tone_decode is None
assert ch.tone_encode == "restricted"
elif ch.name == "sixty-nine":
assert ch.tone_decode == "69.0"
assert ch.tone_encode == "69.0"


def test_digital_repeaters_private_contacts():
Expand Down
38 changes: 38 additions & 0 deletions tests/test_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import pytest

import dzcb.util


ENV_VAR_NAME = "TEST_UTIL_ENVVAR"


@pytest.fixture(
params=[
("yes", True),
("on", True),
(0, False),
("no", False),
("off", False),
(None, None), # should use default
("foo", KeyError), # should use default
]
)
def exp_env_bool(request, monkeypatch):
env_value, exp_bool_value = request.param
if env_value is not None:
monkeypatch.setenv(ENV_VAR_NAME, env_value)
return exp_bool_value


@pytest.mark.parametrize("default", [True, False])
def test_getenv_bool(exp_env_bool, default):
if isinstance(exp_env_bool, type) and issubclass(exp_env_bool, Exception):
with pytest.raises(exp_env_bool):
_ = dzcb.util.getenv_bool(ENV_VAR_NAME, default=default)
return

val = dzcb.util.getenv_bool(ENV_VAR_NAME, default=default)
if exp_env_bool is None:
assert val is default
else:
assert val is exp_env_bool

0 comments on commit 7807632

Please sign in to comment.