pw_log_tokenized: Update Python Metadata fields - Update the field order in pw_log_tokenized.Metadata to match the order in C++ (level, line, flags, module). - Update the pw_log_tokenized.Metadata class and add tests. Change-Id: I6c7ecdad94bc7d55bde11731958cef76ff2e648c Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/48361 Reviewed-by: Keir Mierle <keir@google.com> Commit-Queue: Wyatt Hepler <hepler@google.com>
diff --git a/pw_log_tokenized/py/BUILD.gn b/pw_log_tokenized/py/BUILD.gn index 6c66e61..54ad83b 100644 --- a/pw_log_tokenized/py/BUILD.gn +++ b/pw_log_tokenized/py/BUILD.gn
@@ -19,6 +19,9 @@ pw_python_package("py") { setup = [ "setup.py" ] sources = [ "pw_log_tokenized/__init__.py" ] - tests = [ "format_string_test.py" ] + tests = [ + "format_string_test.py", + "metadata_test.py", + ] pylintrc = "$dir_pigweed/.pylintrc" }
diff --git a/pw_log_tokenized/py/format_string_test.py b/pw_log_tokenized/py/format_string_test.py index b20c6a0..af49bf2 100644 --- a/pw_log_tokenized/py/format_string_test.py +++ b/pw_log_tokenized/py/format_string_test.py
@@ -19,8 +19,8 @@ from pw_log_tokenized import FormatStringWithMetadata -class TestDecodeTokenized(unittest.TestCase): - """Tests decoding tokenized strings with various arguments.""" +class TestFormatStringWithMetadata(unittest.TestCase): + """Tests extracting metadata from a pw_log_tokenized-style format string.""" def test_all_fields(self): log = FormatStringWithMetadata( '■msg♦hello %d■file♦__FILE__■module♦log module name!')
diff --git a/pw_log_tokenized/py/metadata_test.py b/pw_log_tokenized/py/metadata_test.py new file mode 100644 index 0000000..1073a92 --- /dev/null +++ b/pw_log_tokenized/py/metadata_test.py
@@ -0,0 +1,54 @@ +# Copyright 2021 The Pigweed Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +"""Tests for the pw_log_tokenized packed metadata class.""" + +import unittest + +from pw_log_tokenized import Metadata + + +class TestMetadata(unittest.TestCase): + """Tests extracting fields from a pw_log_tokenized packed metadata value.""" + def test_zero(self): + metadata = Metadata(0) + self.assertEqual(metadata.log_level, 0) + self.assertEqual(metadata.line, 0) + self.assertEqual(metadata.flags, 0) + self.assertEqual(metadata.module_token, 0) + + def test_various(self): + metadata = Metadata(0xABCD << 16 | 1 << 14 | 1234 << 3 | 5, + log_bits=3, + line_bits=11, + flag_bits=2, + module_bits=16) + self.assertEqual(metadata.log_level, 5) + self.assertEqual(metadata.line, 1234) + self.assertEqual(metadata.flags, 1) + self.assertEqual(metadata.module_token, 0xABCD) + + def test_max(self): + metadata = Metadata(0xFFFFFFFF, + log_bits=3, + line_bits=11, + flag_bits=2, + module_bits=16) + self.assertEqual(metadata.log_level, 7) + self.assertEqual(metadata.line, 2047) + self.assertEqual(metadata.flags, 3) + self.assertEqual(metadata.module_token, 0xFFFF) + + +if __name__ == '__main__': + unittest.main()
diff --git a/pw_log_tokenized/py/pw_log_tokenized/__init__.py b/pw_log_tokenized/py/pw_log_tokenized/__init__.py index 3e1768b..d0cc1d1 100644 --- a/pw_log_tokenized/py/pw_log_tokenized/__init__.py +++ b/pw_log_tokenized/py/pw_log_tokenized/__init__.py
@@ -23,30 +23,29 @@ return (value & (mask << start)) >> start -@dataclass(frozen=True) class Metadata: """Parses the metadata payload used by pw_log_tokenized.""" - _value: int + def __init__(self, + value: int, + *, + log_bits: int = 3, + line_bits: int = 11, + flag_bits: int = 2, + module_bits: int = 16) -> None: + self.value = value - log_bits: int = 3 - module_bits: int = 16 - flag_bits: int = 2 - line_bits: int = 11 + self.log_level = _mask(value, 0, log_bits) + self.line = _mask(value, log_bits, line_bits) + self.flags = _mask(value, log_bits + line_bits, flag_bits) + self.module_token = _mask(value, log_bits + line_bits + flag_bits, + module_bits) - def log_level(self) -> int: - return _mask(self._value, 0, self.log_bits) - - def module_token(self) -> int: - return _mask(self._value, self.log_bits, self.module_bits) - - def flags(self) -> int: - return _mask(self._value, self.log_bits + self.module_bits, - self.flag_bits) - - def line(self) -> int: - return _mask(self._value, - self.log_bits + self.module_bits + self.flag_bits, - self.line_bits) + def __repr__(self) -> str: + return (f'{type(self).__name__}(' + f'log_level={self.log_level}, ' + f'line={self.line}, ' + f'flags={self.flags}, ' + f'module_token={self.module_token})') class FormatStringWithMetadata: