diff --git a/.github/keylabeler.yml b/.github/keylabeler.yml index 90bd07b..aab21eb 100644 --- a/.github/keylabeler.yml +++ b/.github/keylabeler.yml @@ -16,6 +16,7 @@ labelMappings: "part:collections": "part:collections" "part:datetime": "part:datetime" "part:docs": "part:docs" + "part:logging": "part:logging" "part:math": "part:math" "part:tests": "part:tests" "part:tooling": "part:tooling" diff --git a/.github/labeler.yml b/.github/labeler.yml index d40bfa1..f8c769c 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -63,6 +63,14 @@ - "examples/**" - LICENSE +"part:logging": + - changed-files: + - any-glob-to-any-file: + - "src/frequenz/core/logging.py" + - "src/frequenz/core/logging/**" + - "tests/test_logging.py" + - "tests/logging/**" + "part:math": - changed-files: - any-glob-to-any-file: diff --git a/src/frequenz/core/logging.py b/src/frequenz/core/logging.py new file mode 100644 index 0000000..4dba6ed --- /dev/null +++ b/src/frequenz/core/logging.py @@ -0,0 +1,38 @@ +# License: MIT +# Copyright © 2023 Frequenz Energy-as-a-Service GmbH + +"""Logging tools.""" + +import logging + + +def get_public_logger(module_name: str) -> logging.Logger: + """Get a logger for the public module containing the given module name. + + * Modules are considered private if they start with `_`. + * All modules inside a private module are also considered private, even if they + don't start with `_`. + * If there is no leading public part, the root logger is returned. + + Example: + Here are a few examples of how this function will resolve module names: + + * `some.pub` -> `some.pub` + * `some.pub._some._priv` -> `some.pub` + * `some.pub._some._priv.public` -> `some.pub` + * `some.pub._some._priv.public._private` -> `some.pub` + * `_priv` -> `root` + + Args: + module_name: The fully qualified name of the module to get the logger for + (normally the `__name__` built-in variable). + + Returns: + The logger for the public module containing the given module name. + """ + public_parts: list[str] = [] + for part in module_name.split("."): + if part.startswith("_"): + break + public_parts.append(part) + return logging.getLogger(".".join(public_parts)) diff --git a/tests/test_logging.py b/tests/test_logging.py new file mode 100644 index 0000000..f061142 --- /dev/null +++ b/tests/test_logging.py @@ -0,0 +1,29 @@ +# License: MIT +# Copyright © 2024 Frequenz Energy-as-a-Service GmbH + +"""Tests for the log module.""" + + +import pytest + +from frequenz.core.logging import get_public_logger + + +@pytest.mark.parametrize( + "module_name, expected_logger_name", + [ + ("some.pub", "some.pub"), + ("some.pub._some._priv", "some.pub"), + ("some.pub._some._priv.public", "some.pub"), + ("some.pub._some._priv.public._private", "some.pub"), + ("some._priv.pub", "some"), + ("_priv.some.pub", "root"), + ("some", "some"), + ("some._priv", "some"), + ("_priv", "root"), + ], +) +def test_get_public_logger(module_name: str, expected_logger_name: str) -> None: + """Test that the logger name is as expected.""" + logger = get_public_logger(module_name) + assert logger.name == expected_logger_name