diff --git a/CHANGELOG.md b/CHANGELOG.md index f77c878..7af6611 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,15 @@ and this project (partially) adheres to [Semantic Versioning](https://semver.org ## [Unreleased] ### Added - `Model` support for Raspberry Pi 5+ +- `none` logo style to completely hide distribution logo - AppArmor confinement profile (included in Debian and AUR packages) ### Changed - `Model` honor `/proc/device-tree/model` when it exists +### Removed +- `_distribution` protected attribute from `Output` class + ## [v4.14.3.0] - 2024-04-06 ### Added - Official Armbian distribution support diff --git a/README.md b/README.md index c9a1b04..fcf93d4 100644 --- a/README.md +++ b/README.md @@ -267,7 +267,8 @@ Below stand further descriptions for each available (default) option : // `true` by default to honor os-release(5) `ANSI_COLOR` option. "honor_ansi_color": true, // Set this option to an alternative logo style identifier instead of the default one for your distro. - // For example, "retro" would show the retro styled Apple logo on Darwin platforms. + // For example, "retro" would show the retro styled Apple's logo on Darwin platforms. + // You can set it to "none" to completely hide distribution logo. // Note that the `--logo-style` argument overrides this setting. "logo_style": "", // Enable icons for entries. diff --git a/archey.1 b/archey.1 index 7343ce2..8daf2e3 100644 --- a/archey.1 +++ b/archey.1 @@ -43,7 +43,8 @@ indentation .IP "-l, --logo-style IDENTIFIER" alternative logo style identifier to show instead of the distribution default one. -For instance, you can try 'retro' to prefer old Apple's logo on Darwin platforms +For instance, you can try '\fBretro\fR' to prefer old Apple's logo on Darwin +platforms. Pass '\fBnone\fR' to completely hide distribution logo. .IP "-s, --screenshot [FILENAME]" take a screenshot once execution is done, optionally specify a target diff --git a/archey/__main__.py b/archey/__main__.py index 4c99a9d..fed4bf2 100644 --- a/archey/__main__.py +++ b/archey/__main__.py @@ -104,7 +104,8 @@ def args_parsing() -> argparse.Namespace: "--logo-style", metavar="IDENTIFIER", help="alternative logo style identifier to show instead of the distribution default one. " - "For instance, you can try 'retro' to prefer old Apple's logo on Darwin platforms. " + "For instance, you can try 'retro' to prefer old Apple's logo on Darwin platforms. Pass " + "'none' to completely hide distribution logo. " "Full list of styles : https://github.com/HorlogeSkynet/archey4/wiki/List-of-logos", ) parser.add_argument( diff --git a/archey/logos/__init__.py b/archey/logos/__init__.py index 20b90d6..12e5d73 100644 --- a/archey/logos/__init__.py +++ b/archey/logos/__init__.py @@ -25,5 +25,8 @@ def get_logo_width(logo: List[str], nb_colors: int = 8) -> int: `logo` is supposed to be one of the constants declared above. `nb_colors` must be greater than or equal to the number of colors used by the logo. """ + if not logo: + return 0 + # We replace each placeholder by a 0-character string. return len(logo[0].format(c=[""] * nb_colors)) diff --git a/archey/output.py b/archey/output.py index 056a3b4..934ed8a 100644 --- a/archey/output.py +++ b/archey/output.py @@ -24,7 +24,7 @@ class Output: It also handles the logo choice based on some system detections. """ - __LOGO_RIGHT_PADDING = " " + __logo_right_padding = " " def __init__(self, **kwargs): configuration = Configuration() @@ -35,22 +35,27 @@ def __init__(self, **kwargs): kwargs.get("preferred_logo_style") or configuration.get("logo_style") or "" ).upper() - try: - # If set, force the distribution to `preferred_distribution` argument. - self._distribution = Distributions(kwargs.get("preferred_distribution")) - except ValueError: - # If not (or unknown), run distribution detection. - self._distribution = Distributions.get_local() - - # Retrieve distribution's logo module before copying and DRY-ing its attributes. - logo_module = lazy_load_logo_module(self._distribution.value) - - # If set and available, fetch an alternative logo style from module. - if preferred_logo_style and hasattr(logo_module, f"LOGO_{preferred_logo_style}"): - self._logo = getattr(logo_module, f"LOGO_{preferred_logo_style}").copy() - self._colors = getattr(logo_module, f"COLORS_{preferred_logo_style}").copy() + # If logo shouldn't be displayed, don't load any module and reset right padding + if preferred_logo_style == "NONE": + self._logo, self._colors = [], [] + self.__logo_right_padding = "" else: - self._logo, self._colors = logo_module.LOGO.copy(), logo_module.COLORS.copy() + try: + # If set, force the distribution to `preferred_distribution` argument. + distribution = Distributions(kwargs.get("preferred_distribution")) + except ValueError: + # If not (or unknown), run distribution detection. + distribution = Distributions.get_local() + + # Retrieve distribution's logo module before copying and DRY-ing its attributes. + logo_module = lazy_load_logo_module(distribution.value) + + # If set and available, fetch an alternative logo style from module. + if preferred_logo_style and hasattr(logo_module, f"LOGO_{preferred_logo_style}"): + self._logo = getattr(logo_module, f"LOGO_{preferred_logo_style}").copy() + self._colors = getattr(logo_module, f"COLORS_{preferred_logo_style}").copy() + else: + self._logo, self._colors = logo_module.LOGO.copy(), logo_module.COLORS.copy() # If `os-release`'s `ANSI_COLOR` option is set, honor it. ansi_color = Distributions.get_ansi_color() @@ -59,9 +64,12 @@ def __init__(self, **kwargs): self._colors = len(self._colors) * [Style.escape_code_from_attrs(ansi_color)] entries_color = configuration.get("entries_color") - self._entries_color = ( - Style.escape_code_from_attrs(entries_color) if entries_color else self._colors[0] - ) + if entries_color: + self._entries_color = Style.escape_code_from_attrs(entries_color) + elif self._colors: + self._entries_color = str(self._colors[0]) + else: + self._entries_color = "" # Each entry will be added to this list self._entries = [] @@ -111,7 +119,7 @@ def _output_text(self) -> None: self._results[0:0] = [""] * (height_diff // 2) self._results.extend([""] * (len(self._logo) - len(self._results))) else: - colored_empty_line = [str(self._colors[0]) + " " * logo_width] + colored_empty_line = [(str(self._colors[0]) if self._colors else "") + " " * logo_width] self._logo[0:0] = colored_empty_line * (-height_diff // 2) self._logo.extend(colored_empty_line * (len(self._results) - len(self._logo))) @@ -119,7 +127,7 @@ def _output_text(self) -> None: if not sys.stdout.isatty(): text_width = cast(int, float("inf")) else: - text_width = get_terminal_size().columns - logo_width - len(self.__LOGO_RIGHT_PADDING) + text_width = get_terminal_size().columns - logo_width - len(self.__logo_right_padding) text_wrapper = TextWrapper( width=text_width, @@ -166,7 +174,7 @@ def _output_text(self) -> None: # Merge entry results to the distribution logo. logo_with_entries = os.linesep.join( [ - f"{logo_part}{self.__LOGO_RIGHT_PADDING}{entry_part}" + f"{logo_part}{self.__logo_right_padding}{entry_part}" for logo_part, entry_part in zip(self._logo, self._results) ] ) diff --git a/archey/test/test_archey_logos.py b/archey/test/test_archey_logos.py index 80fabe0..e510875 100644 --- a/archey/test/test_archey_logos.py +++ b/archey/test/test_archey_logos.py @@ -94,6 +94,7 @@ def test_distribution_logos_consistency(self): def test_get_logo_width(self): """Test `logos.get_logo_width` behavior""" + self.assertEqual(get_logo_width([]), 0) self.assertEqual(get_logo_width(["{c[0]} {c[1]}"], 2), 3) self.assertEqual(get_logo_width(["{c[0]} {{ {c[1]}"]), 3) self.assertEqual( diff --git a/archey/test/test_archey_output.py b/archey/test/test_archey_output.py index a2009f7..5dc0019 100644 --- a/archey/test/test_archey_output.py +++ b/archey/test/test_archey_output.py @@ -451,14 +451,14 @@ def test_line_wrapping(self, print_mock, termsize_mock, _, __, ___, ____): self.assertTrue(print_mock.assert_called_once) @patch("archey.output.Distributions.get_local") + @patch("archey.output.lazy_load_logo_module") @patch("archey.output.Distributions.get_ansi_color", return_value=None) - def test_preferred_distribution(self, _, get_local_mock): + def test_preferred_distribution(self, _, lazy_load_logo_module_mock, get_local_mock): """Simple test checking behavior when `preferred_distribution` is passed at instantiation""" - output = Output(preferred_distribution="rhel") + Output(preferred_distribution="rhel") - self.assertEqual( - output._distribution, Distributions.RHEL # pylint: disable=protected-access - ) + # Check `lazy_load_logo_module` has been called with RHEL distribution. + lazy_load_logo_module_mock.assert_called_with(Distributions.RHEL.value) # Check `Distributions.get_local` method has not been called at all. self.assertFalse(get_local_mock.called) @@ -488,6 +488,35 @@ def test_preferred_style(self, _): lazy_load_logo_module(Distributions.DARWIN.value).LOGO_RETRO, ) + @patch("archey.output.Distributions.get_ansi_color", return_value=None) + @patch("archey.output.sys.stdout.isatty", return_value=True) + @patch("archey.output.get_terminal_size") + @patch("archey.output.print", return_value=None) # Let's nastily mute class' outputs. + def test_no_logo(self, print_mock, termsize_mock, _, __): + """Test `Output` 'none' logo style (logo hiding)""" + output = Output(preferred_logo_style="none") + + # We only need a column value for the terminal size + termsize_tuple = namedtuple("termsize_tuple", "columns") + termsize_mock.return_value = termsize_tuple(80) + + output._results = [ # pylint: disable=protected-access + "entry_1", + "entry_2", + "entry_3", + ] + output.output() + + print_mock.assert_called_with( + """\ +entry_1 +entry_2 +entry_3\x1b[0m\ +""" + ) + # Check that `print` has been called only once. + self.assertTrue(print_mock.assert_called_once) + @patch( "archey.output.Distributions.get_local", return_value=Distributions.DEBIAN, # Make Debian being selected.