Ejemplo n.º 1
0
 def test_get_distro_name(self, _):
     """Very basic test cases for `get_distro_name` static method"""
     self.assertEqual(
         Distributions.get_distro_name(),
         'Debian GNU/Linux 10 (buster)'
     )
     self.assertIsNone(Distributions.get_distro_name())
Ejemplo n.º 2
0
    def test_darwin_detection(self, _, __, ___, ____):
        """Test OS detection for Darwin"""
        # Detection based on `distro`.
        self.assertEqual(Distributions.get_local(), Distributions.DARWIN)

        # Detection based on `platform`.
        self.assertEqual(Distributions.get_local(), Distributions.DARWIN)
Ejemplo n.º 3
0
 def test_get_ansi_color(self, _):
     """Very basic test cases for `get_ansi_color` static method"""
     self.assertEqual(
         Distributions.get_ansi_color(),
         '33;1',
     )
     self.assertIsNone(Distributions.get_ansi_color())
Ejemplo n.º 4
0
    def __init__(self):
        # First we check whether the Kernel has been compiled as a WSL.
        if 'microsoft' in check_output(['uname', '-r'],
                                       universal_newlines=True).lower():
            self._distribution = Distributions.WINDOWS
        else:
            try:
                self._distribution = Distributions(distro.id())
            except ValueError:
                # See <https://www.freedesktop.org/software/systemd/man/os-release.html#ID_LIKE=>.
                for distro_like in distro.like().split(' '):
                    try:
                        self._distribution = Distributions(distro_like)
                    except ValueError:
                        continue
                    break
                else:
                    # Well, we didn't match anything so let's fall-back to default `Linux`.
                    self._distribution = Distributions.LINUX

        # Fetch the colors palette related to this distribution.
        self._colors_palette = COLOR_DICT[self._distribution]

        # If `os-release`'s `ANSI_COLOR` option is set, honor it.
        # See <https://www.freedesktop.org/software/systemd/man/os-release.html#ANSI_COLOR=>.
        ansi_color = distro.os_release_attr('ansi_color')
        if ansi_color and Configuration().get(
                'colors_palette')['honor_ansi_color']:
            # Replace each Archey integrated colors by `ANSI_COLOR`.
            self._colors_palette = len(self._colors_palette) * \
                [Colors.escape_code_from_attrs(ansi_color)]

        # Each class output will be added in the list below afterwards
        self._results = []
Ejemplo n.º 5
0
    def __init__(self, **kwargs):
        # Fetches passed arguments.
        self._format_to_json = kwargs.get('format_to_json')  # type: int

        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.run_detection()

        # Retrieve distribution's logo module before copying and DRY-ing its attributes.
        logo_module = lazy_load_logo_module(self._distribution.value)
        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()
        if ansi_color and Configuration().get('honor_ansi_color'):
            # Replace each Archey integrated colors by `ANSI_COLOR`.
            self._colors = len(self._colors) * [Colors.escape_code_from_attrs(ansi_color)]

        # Each entry will be added to this list
        self._entries = []
        # Each class output will be added in the list below afterwards
        self._results = []
Ejemplo n.º 6
0
    def __init__(self, **kwargs):
        # Fetches passed arguments.
        self._format_to_json = kwargs.get('format_to_json')

        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.run_detection()

        # Fetch the colors palette related to this distribution.
        self._colors_palette = COLORS_DICT[self._distribution]

        # If `os-release`'s `ANSI_COLOR` option is set, honor it.
        ansi_color = Distributions.get_ansi_color()
        if ansi_color and Configuration().get(
                'colors_palette')['honor_ansi_color']:
            # Replace each Archey integrated colors by `ANSI_COLOR`.
            self._colors_palette = len(self._colors_palette) * \
                [Colors.escape_code_from_attrs(ansi_color)]

        # Each entry will be added to this list
        self._entries = []
        # Each class output will be added in the list below afterwards
        self._results = []
Ejemplo n.º 7
0
    def test_constant_values(self):
        """Test enumeration member instantiation from value"""
        self.assertEqual(Distributions('debian'), Distributions.DEBIAN)
        self.assertRaises(ValueError, Distributions, 'unknown')

        # Check `get_distribution_identifiers` consistency.
        distribution_identifiers = Distributions.get_distribution_identifiers()
        self.assertTrue(isinstance(distribution_identifiers, list))
        self.assertTrue(all(isinstance(i, str) for i in distribution_identifiers))
Ejemplo n.º 8
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        for packages_tool in PACKAGES_TOOLS:
            if 'only_on' in packages_tool \
                and Distributions.get_local() not in packages_tool['only_on']:
                continue

            try:
                results = check_output(
                    packages_tool['cmd'],
                    stderr=DEVNULL,
                    env={
                        'LANG': 'C',
                        # Alpine Linux: We have to manually propagate `PATH`.
                        #               `apk` wouldn't be found otherwise.
                        'PATH': os.getenv('PATH')
                    },
                    universal_newlines=True)
            except (OSError, CalledProcessError):
                continue

            # Here we *may* use `\n` as `universal_newlines` has been set.
            if self.value:
                self.value += results.count('\n')
            else:
                self.value = results.count('\n')

            # If any, deduct output skew present due to the packages tool itself.
            if 'skew' in packages_tool:
                self.value -= packages_tool['skew']

            # For DPKG only, remove any not purged package.
            if packages_tool['cmd'][0] == 'dpkg':
                self.value -= results.count('deinstall')
Ejemplo n.º 9
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        distro_name = Distributions.get_distro_name()
        if not distro_name:
            distro_name = self._fetch_android_release()

        self.value = {'name': distro_name, 'arch': platform.machine()}
Ejemplo n.º 10
0
    def __init__(self, **kwargs):
        # Fetches passed arguments.
        self._format_to_json = kwargs.get('format_to_json')
        preferred_logo_style = (kwargs.get('preferred_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()
        else:
            self._logo, self._colors = logo_module.LOGO.copy(
            ), logo_module.COLORS.copy()

        configuration = Configuration()

        # If `os-release`'s `ANSI_COLOR` option is set, honor it.
        ansi_color = Distributions.get_ansi_color()
        if ansi_color and configuration.get("honor_ansi_color"):
            # Replace each Archey integrated colors by `ANSI_COLOR`.
            self._colors = len(
                self._colors) * [Colors.escape_code_from_attrs(ansi_color)]

        entries_color = configuration.get("entries_color")
        self._entries_color = (Colors.escape_code_from_attrs(entries_color)
                               if entries_color else self._colors[0])

        # Each entry will be added to this list
        self._entries = []
        # Each class output will be added in the list below afterwards
        self._results = []
Ejemplo n.º 11
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if platform.system() == 'Darwin':
            distro_name = self._fetch_darwin_release()
        else:
            distro_name = Distributions.get_distro_name() or \
                self._fetch_android_release()

        self.value = {'name': distro_name, 'arch': platform.machine()}
Ejemplo n.º 12
0
def args_parsing() -> argparse.Namespace:
    """Simple wrapper to `argparse`"""
    parser = argparse.ArgumentParser(prog='archey')
    parser.add_argument(
        '-c',
        '--config-path',
        metavar='PATH',
        help=
        'path to a configuration file, or a directory containing a `config.json`'
    )
    parser.add_argument(
        '-d',
        '--distribution',
        metavar='IDENTIFIER',
        choices=Distributions.get_identifiers(),
        help=
        'supported distribution identifier to show the logo of, pass `unknown` to list them'
    )
    parser.add_argument(
        '-j',
        '--json',
        action='count',
        help=
        'output entries data to JSON format, use multiple times to increase indentation'
    )
    parser.add_argument(
        '-l',
        '--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"
    )
    parser.add_argument(
        '-s',
        '--screenshot',
        metavar='PATH',
        nargs='?',
        const=False,
        help=
        'take a screenshot once execution is done, optionally specify a target path'
    )
    parser.add_argument('-v',
                        '--version',
                        action='version',
                        version=__version__)
    return parser.parse_args()
Ejemplo n.º 13
0
    def json_serialization(self, indent: int = 0) -> str:
        """
        JSON serialization of entries.
        Set `indent` to the number of wanted output indentation tabs (2-space long).
        """
        document = {
            'data': {entry.name: entry.value
                     for entry in self.entries},
            'meta': {
                'version': Utility.version_to_semver_segments(__version__),
                'date': datetime.now().isoformat(),
                'count': len(self.entries),
                'distro': Distributions.get_local().value,
            }
        }

        return json.dumps(document, indent=((indent * 2) or None))
Ejemplo n.º 14
0
def args_parsing():
    """Simple wrapper to `argparse`"""
    parser = argparse.ArgumentParser(prog='archey')
    parser.add_argument(
        '-c',
        '--config-path',
        metavar='PATH',
        help=
        'path to a configuration file, or a directory containing a `config.json`'
    )
    parser.add_argument(
        '-d',
        '--distribution',
        metavar='IDENTIFIER',
        choices=Distributions.get_distribution_identifiers(),
        help=
        'supported distribution identifier to show the logo of, pass `unknown` to list them'
    )
    parser.add_argument(
        '-j',
        '--json',
        action='count',
        help=
        'output entries data to JSON format, use multiple times to increase indentation'
    )
    parser.add_argument(
        '-s',
        '--screenshot',
        metavar='PATH',
        nargs='?',
        const=False,
        help=
        'take a screenshot once execution is done, optionally specify a target path'
    )
    parser.add_argument('-v',
                        '--version',
                        action='version',
                        version=__version__)
    return parser.parse_args()
Ejemplo n.º 15
0
    def test_distribution_logos_consistency(self):
        """
        Verify each distribution identifier got a logo module.
        Verify each distribution logo module contain `LOGO` & `COLORS` ("truthy") attributes.
        Also check they got _consistent_ widths across their respective lines.
        Additionally verify they don't contain any (useless) empty line.

        This test also indirectly checks `lazy_load_logo_module` behavior!
        """
        distributions_identifiers = Distributions.get_identifiers()

        for i, logo_module_info in enumerate(pkgutil.iter_modules(
                logos.__path__),
                                             start=1):

            # Check each logo module name corresponds to a distribution identifier.
            self.assertIn(
                logo_module_info.name,
                distributions_identifiers,
                msg=f'No distribution identifier for [{logo_module_info.name}]'
            )

            logo_module = lazy_load_logo_module(logo_module_info.name)

            # Attributes checks.
            self.assertTrue(
                getattr(logo_module, 'LOGO', []),
                msg=
                f'[{logo_module_info.name}] logo module missing `LOGO` attribute'
            )
            self.assertTrue(
                getattr(logo_module, 'COLORS', []),
                msg=
                f'[{logo_module_info.name}] logo module missing `COLORS` attribute'
            )

            # Compute once and for all the number of defined colors for this logo.
            nb_colors = len(logo_module.COLORS)

            # Make Archey compute the logo (effective) width.
            logo_width = get_logo_width(logo_module.LOGO, nb_colors)

            # Then, check that each logo line got the same effective width.
            for j, line in enumerate(logo_module.LOGO[1:], start=1):
                # Here we gotta trick the `get_logo_width` call.
                # We actually pass each logo line as if it was a "complete" logo.
                line_width = get_logo_width([line], nb_colors)

                # Width check.
                self.assertEqual(
                    line_width,
                    logo_width,
                    msg=
                    '[{}] line index {}, got an unexpected width {} (expected {})'
                    .format(logo_module_info.name, j, line_width, logo_width))

                # Non-empty line check.
                self.assertTrue(
                    Colors.remove_colors(line.format(c=[''] *
                                                     nb_colors)).strip(),
                    msg=
                    f'[{logo_module_info.name}] line index {j}, got an useless empty line'
                )

        # Finally, check each distributions identifier got a logo!
        # pylint: disable=undefined-loop-variable
        self.assertEqual(i,
                         len(distributions_identifiers),
                         msg='[{}] Expected {} logo modules, got {}'.format(
                             logo_module_info.name,
                             len(distributions_identifiers), i))
Ejemplo n.º 16
0
    def test_distribution_logos_consistency(self):
        """
        Verify each distribution identifier got a logo module.
        Verify each distribution logo module contain `LOGO` & `COLORS` ("truthy") attributes.
        Also check they got _consistent_ widths across their respective lines.
        Additionally verify they don't contain any (useless) empty line.

        This test also indirectly checks `lazy_load_logo_module` behavior!
        """
        distributions_identifiers = Distributions.get_distribution_identifiers(
        )

        for i, logo_module_info in enumerate(pkgutil.iter_modules(
                logos.__path__),
                                             start=1):
            # `iter_modules` yields `pkgutil.ModuleInfo` named tuple starting with Python 3.6.
            # So we manually extract the module name from `(module_finder, name, ispkg)` tuple.
            logo_module_name = logo_module_info[1]

            # Check each logo module name corresponds to a distribution identifier.
            self.assertIn(logo_module_name,
                          distributions_identifiers,
                          msg='No distribution identifier for [{0}]'.format(
                              logo_module_name))

            logo_module = lazy_load_logo_module(logo_module_name)

            # Attributes checks.
            self.assertTrue(
                getattr(logo_module, 'LOGO', []),
                msg='[{0}] logo module missing `LOGO` attribute'.format(
                    logo_module_name))
            self.assertTrue(
                getattr(logo_module, 'COLORS', []),
                msg='[{0}] logo module missing `COLORS` attribute'.format(
                    logo_module_name))

            # Make Archey compute the logo width.
            logo_width = get_logo_width(logo_module.LOGO)

            # Then, check that each logo line got the same effective width.
            for j, line in enumerate(logo_module.LOGO[1:], start=1):
                # Here we gotta trick the `get_logo_width` call.
                # We actually pass each logo line as if it was a "complete" logo.
                line_width = get_logo_width([line])

                # Width check.
                self.assertEqual(
                    line_width,
                    logo_width,
                    msg=
                    '[{0}] line index {1}, got an unexpected width {2} (expected {3})'
                    .format(logo_module_name, j, line_width, logo_width))

                # Non-empty line check.
                self.assertTrue(
                    Colors.remove_colors(line).strip(),
                    msg='[{0}] line index {1}, got an useless empty line'.
                    format(logo_module_name, j))

        # Finally, check each distributions identifier got a logo!
        # pylint: disable=undefined-loop-variable
        self.assertEqual(i,
                         len(distributions_identifiers),
                         msg='[{0}] Expected {1} logo modules, got {2}'.format(
                             logo_module_name, len(distributions_identifiers),
                             i))
 def test_run_detection_distro_like_second(self, _, __, ___):
     """Test distribution matching from the `os-release`'s `ID_LIKE` option (second candidate)"""
     self.assertEqual(Distributions.run_detection(), Distributions.ARCH)
 def test_run_detection_known_distro_like(self, _, __, ___):
     """Test distribution matching from the `os-release`'s `ID_LIKE` option"""
     self.assertEqual(Distributions.run_detection(), Distributions.UBUNTU)
 def test_run_detection_unknown_distro_id(self, _, __, ___, ____):
     """Test unknown distribution output"""
     self.assertEqual(Distributions.run_detection(), Distributions.LINUX)
 def test_run_detection_windows_subsystem(self, _):
     """Test output for Windows Subsystem Linux"""
     self.assertEqual(Distributions.run_detection(), Distributions.WINDOWS)
 def test_run_detection_windows(self):
     """Test output for Windows"""
     self.assertEqual(Distributions.run_detection(), Distributions.WINDOWS)
 def test_run_detection_specific_android(self, _, __):
     """Test Android specific detection"""
     self.assertEqual(Distributions.run_detection(), Distributions.ANDROID)
 def test_run_detection_specific_crunchbang(self, _, __, ___):
     """Test CrunchBang specific detection"""
     self.assertEqual(Distributions.run_detection(),
                      Distributions.CRUNCHBANG)
 def test_run_detection_both_distro_calls_fail(self, _, __, ___, ____):
     """Test distribution fall-back when `distro` soft-fail two times"""
     self.assertEqual(Distributions.run_detection(), Distributions.LINUX)
Ejemplo n.º 25
0
 def test_get_local_windows(self, _):
     """Test output for Windows"""
     self.assertEqual(Distributions.get_local(), Distributions.WINDOWS)
Ejemplo n.º 26
0
 def test_get_local_windows_subsystem(self, _, __):
     """Test output for Windows Subsystem Linux"""
     self.assertEqual(Distributions.get_local(), Distributions.WINDOWS)
Ejemplo n.º 27
0
 def test_get_local_unknown_distro_id(self, _, __, ___, ____, _____):
     """Test unknown distribution output"""
     self.assertEqual(Distributions.get_local(), Distributions.LINUX)