Skip to content

Commit dc758e6

Browse files
ENH: message: show reason for InvalidKey exception
if the user wants to add a field with an invalid key, the reason was not clear now the error message says that either the key is not allowed in the harmonization configuration or the key does not match the regular expression (for extra keys), e.g. is not lower case etc.
1 parent 8bb7035 commit dc758e6

File tree

5 files changed

+30
-16
lines changed

5 files changed

+30
-16
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ CHANGELOG
1212
### Configuration
1313

1414
### Core
15+
- `intelmq.lib.message`: For invalid message keys, add a hint on the failure to the exception: not allowed by configuration or not matching regular expression (PR#2398 by Sebastian Wagner).
16+
- `intelmq.lib.exceptions.InvalidKey`: Add optional parameter `additional_text` (PR#2398 by Sebastian Wagner).
1517

1618
### Development
1719

intelmq/lib/exceptions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ def __init__(self, key: str, value: str, reason: Any = None, object: bytes = Non
8888

8989
class InvalidKey(IntelMQHarmonizationException, KeyError):
9090

91-
def __init__(self, key: str):
92-
message = "invalid key %s" % repr(key)
91+
def __init__(self, key: str, additional_text: Optional[str] = None):
92+
message = f"invalid key {key!r} {additional_text or ''}".strip() # remove trailing whitespace if additional_text is not given
9393
super().__init__(message)
9494

9595

intelmq/lib/message.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import re
1414
import warnings
1515
from collections import defaultdict
16-
from typing import Any, Dict, Iterable, Optional, Sequence, Union
16+
from typing import Any, Dict, Iterable, Optional, Sequence, Union, Tuple
1717
from pkg_resources import resource_filename
1818

1919
import intelmq.lib.exceptions as exceptions
@@ -186,8 +186,9 @@ def is_valid(self, key: str, value: str, sanitize: bool = True) -> bool:
186186
intelmq.lib.exceptions.InvalidKey: if given key is invalid.
187187
188188
"""
189-
if not self.__is_valid_key(key):
190-
raise exceptions.InvalidKey(key)
189+
key_validation = self.__is_valid_key(key)
190+
if not key_validation[0]:
191+
raise exceptions.InvalidKey(key, additional_text=key_validation[1])
191192

192193
if value is None or value in ["", "-", "N/A"]:
193194
return False
@@ -243,8 +244,9 @@ def add(self, key: str, value: str, sanitize: bool = True,
243244
del self[key]
244245
return
245246

246-
if not self.__is_valid_key(key):
247-
raise exceptions.InvalidKey(key)
247+
key_validation = self.__is_valid_key(key)
248+
if not key_validation[0]:
249+
raise exceptions.InvalidKey(key, additional_text=key_validation[1])
248250

249251
try:
250252
if value in ignore:
@@ -330,16 +332,16 @@ def unserialize(message_string: str):
330332
message = json.loads(message_string)
331333
return message
332334

333-
def __is_valid_key(self, key: str):
335+
def __is_valid_key(self, key: str) -> Tuple[bool, str]:
334336
try:
335337
class_name, subitem = self.__get_type_config(key)
336338
except KeyError:
337-
return False
339+
return False, 'This key is not allowed by the harmonization configuration'
338340
if key in self.harmonization_config or key == '__type':
339-
return True
341+
return True, None
340342
if subitem:
341-
return HARMONIZATION_KEY_FORMAT.match(key)
342-
return False
343+
return HARMONIZATION_KEY_FORMAT.match(key), f'Does not match regular expression {HARMONIZATION_KEY_FORMAT.pattern}'
344+
return False, 'This key is not allowed by the harmonization configuration'
343345

344346
def __is_valid_value(self, key: str, value: str):
345347
if key == '__type':
@@ -569,7 +571,7 @@ def __init__(self, message: Union[dict, tuple] = (), auto: bool = False,
569571
if isinstance(message, Event):
570572
super().__init__({}, auto, harmonization)
571573
for key, value in message.items():
572-
if self._Message__is_valid_key(key):
574+
if self._Message__is_valid_key(key)[0]:
573575
self.add(key, value, sanitize=False)
574576
else:
575577
super().__init__(message, auto, harmonization)

intelmq/tests/lib/test_exceptions.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ def test_MissingDependencyError(self):
6464
self.assertIn(repr(depname), exc)
6565
self.assertTrue(exc.endswith(" %s" % additional))
6666

67+
def test_invalid_key(self):
68+
"""
69+
Check intelmq.lib.exceptions.InvalidKey
70+
"""
71+
exc = excs.InvalidKey('test_key', additional_text='TEST').args[0]
72+
self.assertTrue(exc.endswith(' TEST'))
73+
6774

6875
if __name__ == '__main__': # pragma: no cover
6976
unittest.main()

intelmq/tests/lib/test_message.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,10 @@ def test_invalid_type2(self):
168168
def test_report_invalid_key(self):
169169
""" Test if report raises InvalidKey for invalid key in add(). """
170170
report = self.new_report()
171-
with self.assertRaises(exceptions.InvalidKey):
171+
with self.assertRaises(exceptions.InvalidKey) as cm:
172172
report.add('invalid', 0)
173+
self.assertIn('not allowed', cm.exception.args[0])
174+
173175

174176
def test_report_add_raw(self):
175177
""" Test if report can add raw value. """
@@ -764,10 +766,11 @@ def test_invalid_harm_key(self):
764766
message.Event(harmonization={'event': {'foo.bar.': {}}})
765767

766768
def test_invalid_extra_key_name(self):
767-
""" Test if error is raised if an extra field name is invalid. """
769+
""" Test if error is raised when an extra field name is invalid and error message is included in exception. """
768770
event = message.Event(harmonization=HARM)
769-
with self.assertRaises(exceptions.InvalidKey):
771+
with self.assertRaises(exceptions.InvalidKey) as cm:
770772
event.add('extra.foo-', 'bar')
773+
self.assertIn('Does not match regular expression', cm.exception.args[0])
771774

772775

773776
class TestReport(unittest.TestCase):

0 commit comments

Comments
 (0)