Пример #1
0
    def __init__(self):
        # The configuration object is needed to retrieve some settings below.
        configuration = Configuration()

        addresses = []

        # Loop through all available network interfaces.
        for interface in netifaces.interfaces():
            # Fetch associated addresses elements.
            interface_addrs = netifaces.ifaddresses(interface)

            # For each IPv4 or IPv6 address...
            for addr_type in [netifaces.AF_INET, netifaces.AF_INET6]:
                if addr_type in interface_addrs:
                    for interface_addr in interface_addrs[addr_type]:
                        # Filter out loopback addresses.
                        if (addr_type != netifaces.AF_INET or \
                                not interface_addr['addr'].startswith('127.')) and \
                                interface_addr['addr'] != '::1':
                            addresses.append(
                                interface_addr['addr'].split('%')[0])

        lan_ip_max_count = configuration.get('ip_settings')['lan_ip_max_count']
        if lan_ip_max_count is not False:
            addresses = addresses[:lan_ip_max_count]

        self.value = ', '.join(addresses) or configuration.get(
            'default_strings')['no_address']
Пример #2
0
    def entry_mock(entry, configuration=None):
        """
        Creates a placeholder "instance" of the entry class passed, with a clean default
        `_configuration` which is optionally updated by `configuration`.

        It can be used to very cleanly unit-test instance methods of a class,
        by passing it in (after setting appropriate attributes).

        The attributes defined are not instance attributes, however since this isn't
        technically an instance, they are used in place of the respective instance attributes.
        """
        # We spec to the entry so non-existent methods can't be called...
        # ...and wrap it, to inherit its methods.
        instance_mock = MagicMock(spec=entry, wraps=entry)
        # These instance-attributes are quite important, so let's mimic them.
        instance_mock.name = str(entry.__name__)
        instance_mock.value = None  # (entry default)

        # Let's initially give the entry configuration the defaults.
        # We deep-copy `DEFAULT_CONFIG` to prevent its mutation.
        entry_configuration = deepcopy(DEFAULT_CONFIG)
        # Then, let's merge in `configuration` recursively.
        Configuration.update_recursive(entry_configuration, (configuration or {}))
        # Finally, replaces the internal (and private!) `_configuration` attribute by...
        # ... the corresponding configuration object.
        setattr(instance_mock, '_configuration', entry_configuration)

        return instance_mock
Пример #3
0
    def __init__(self):
        # The configuration object is needed to retrieve some settings below.
        configuration = Configuration()

        # This dictionary will store values obtained from sub-processes calls.
        self._usage = {'used': 0.0, 'total': 0.0}

        self._run_df_usage()
        self._run_btrfs_usage()

        # Check whether at least one media could be found.
        if not self._usage['total']:
            self.value = configuration.get('default_strings')['not_detected']
            return

        # Fetch the user-defined disk limits from configuration.
        disk_limits = configuration.get('limits')['disk']

        # Based on the disk percentage usage, select the corresponding level color.
        level_color = Colors.get_level_color(
            (self._usage['used'] / (self._usage['total'] or 1)) * 100,
            disk_limits['warning'], disk_limits['danger'])

        self.value = '{0}{1} GiB{2} / {3} GiB'.format(
            level_color, round(self._usage['used'], 1), Colors.CLEAR,
            round(self._usage['total'], 1))
Пример #4
0
    def __init__(self):
        # The configuration object is needed to retrieve some settings below.
        configuration = Configuration()

        addr_types = [netifaces.AF_INET]
        if configuration.get('ip_settings')['lan_ip_v6_support']:
            addr_types.append(netifaces.AF_INET6)

        ip_addrs = []

        # Loop through all available network interfaces.
        for if_name in netifaces.interfaces():
            # Fetch associated addresses elements.
            if_addrs = netifaces.ifaddresses(if_name)

            # For each IPv4 (or IPv6 address)...
            for addr_type in addr_types:
                if addr_type not in if_addrs:
                    continue

                for if_addr in if_addrs[addr_type]:
                    # Filter out loopback addresses.
                    if (addr_type == netifaces.AF_INET and if_addr['addr'].startswith('127.')) \
                        or if_addr['addr'] == '::1':
                        continue

                    ip_addrs.append(if_addr['addr'].split('%')[0])

        lan_ip_max_count = configuration.get('ip_settings')['lan_ip_max_count']
        if lan_ip_max_count is not False:
            ip_addrs = ip_addrs[:lan_ip_max_count]

        self.value = ', '.join(ip_addrs) or configuration.get(
            'default_strings')['no_address']
Пример #5
0
    def patch_clean_configuration(method_definition=None, *, configuration=None):
        """
        Decorator for an entry test definition, which sets the entry's `_configuration` attribute to
        the Archey defaults, optionally updated with `configuration`.
        """
        # Let's initially give the entry configuration the defaults.
        # We deep-copy `DEFAULT_CONFIG` to prevent its mutation.
        entry_configuration = deepcopy(DEFAULT_CONFIG)
        # Then, let's merge in `configuration` recursively.
        Configuration.update_recursive(entry_configuration, (configuration or {}))

        def decorator_patch_clean_configuration(method):
            @wraps(method)
            def wrapper_patch_clean_configuration(*args, **kwargs):
                with patch('archey.entry.Configuration', autospec=True) as config_instance_mock:
                    # Mock "publicly" used methods.
                    config_instance_mock().get = entry_configuration.get
                    config_instance_mock().__iter__ = lambda _: iter(entry_configuration.items())
                    return method(*args, **kwargs)

            return wrapper_patch_clean_configuration

        if method_definition is None:
            return decorator_patch_clean_configuration

        return decorator_patch_clean_configuration(method_definition)
Пример #6
0
    def __init__(self):
        try:
            with open('/sys/devices/virtual/dmi/id/product_name') as file:
                model = file.read().rstrip()

        except FileNotFoundError:
            # The file above does not exist, is this device a Raspberry Pi ?
            # Let's retrieve the Hardware and Revision IDs with `/proc/cpuinfo`
            with open('/proc/cpuinfo') as file:
                output = file.read()

            hardware = re.search('(?<=Hardware\t: ).*', output)
            revision = re.search('(?<=Revision\t: ).*', output)

            # If the output contains 'Hardware' and 'Revision'...
            if hardware and revision:
                # ... let's set a pretty info string with these data
                model = 'Raspberry Pi {0} (Rev. {1})'.format(
                    hardware.group(0),
                    revision.group(0)
                )

            else:
                # The configuration object is needed to retrieve some settings below.
                configuration = Configuration()

                # A tricky way to retrieve some details about hypervisor...
                # ... within virtual contexts.
                # `archey` needs to be run as root although.
                try:
                    virt_what = ', '.join(
                        check_output(
                            ['virt-what'],
                            stderr=DEVNULL, universal_newlines=True
                        ).splitlines()
                    )

                    if virt_what:
                        try:
                            # Sometimes we may gather info added by...
                            # ... hosting service provider this way
                            model = check_output(
                                ['dmidecode', '-s', 'system-product-name'],
                                stderr=DEVNULL, universal_newlines=True
                            ).rstrip()

                        except (FileNotFoundError, CalledProcessError):
                            model = configuration.get('default_strings')['virtual_environment']

                        model += ' ({0})'.format(virt_what)

                    else:
                        model = configuration.get('default_strings')['bare_metal_environment']

                except (FileNotFoundError, CalledProcessError):
                    model = configuration.get('default_strings')['not_detected']

        self.value = model
Пример #7
0
    def __init__(self, name=None, value=None):
        # Each entry will have always have the following attributes...
        # `name` (key);
        # `value` (value of entry as an appropriate object)
        # ... which are `None` by default.
        self.name = name
        self.value = value

        # Propagates a reference to `Configuration` singleton to each inheriting class.
        self._configuration = Configuration()
Пример #8
0
    def __init__(self, name: str = None, value=None, options: dict = None):
        # Each entry will have always have the following attributes...
        # `name`: key (defaults to the instantiated entry class name);
        # `value`: value of entry as an appropriate object;
        # `options`: configuration options *specific* to an entry instance;
        self.name = name or self.__class__.__name__
        self.value = value
        self.options = options or {}

        # Propagates a reference to default strings specified in `Configuration`.
        self._default_strings = Configuration().get('default_strings')
Пример #9
0
    def __init__(self):
        # The configuration object is needed to retrieve some settings below.
        configuration = Configuration()
        use_fahrenheit = configuration.get('temperature')['use_fahrenheit']
        char_before_unit = configuration.get('temperature')['char_before_unit']

        temps = []

        try:
            # Let's try to retrieve a value from the Broadcom chip on Raspberry
            temp = float(
                re.search(
                    r'\d+\.\d+',
                    check_output(['/opt/vc/bin/vcgencmd', 'measure_temp'],
                                 stderr=DEVNULL,
                                 universal_newlines=True)).group(0))

            temps.append(
                self._convert_to_fahrenheit(temp) if use_fahrenheit else temp)

        except (FileNotFoundError, CalledProcessError):
            pass

        # Now we just check for values within files present in the path below
        for thermal_file in glob('/sys/class/thermal/thermal_zone*/temp'):
            with open(thermal_file) as file:
                try:
                    temp = float(file.read().strip()) / 1000

                except OSError:
                    continue

                if temp != 0.0:
                    temps.append(
                        self._convert_to_fahrenheit(temp)
                        if use_fahrenheit else temp)

        if temps:
            self.value = '{0}{1}{2}'.format(
                str(round(sum(temps) / len(temps), 1)), char_before_unit,
                'F' if use_fahrenheit else 'C')

            if len(temps) > 1:
                self.value += ' (Max. {0}{1}{2})'.format(
                    str(round(max(temps), 1)), char_before_unit,
                    'F' if use_fahrenheit else 'C')

        else:
            self.value = configuration.get('default_strings')['not_detected']
Пример #10
0
    def __init__(self):
        # The configuration object is needed to retrieve some settings below.
        configuration = Configuration()

        # IPv6 address retrieval (unless the user doesn't want it).
        if configuration.get('ip_settings')['wan_ip_v6_support']:
            try:
                ipv6_addr = check_output(
                    [
                        'dig', '+short', '-6', 'AAAA', 'myip.opendns.com',
                        '@resolver1.ipv6-sandbox.opendns.com'
                    ],
                    timeout=configuration.get('timeout')['ipv6_detection'],
                    stderr=DEVNULL,
                    universal_newlines=True).rstrip()

            except (FileNotFoundError, TimeoutExpired, CalledProcessError):
                try:
                    ipv6_addr = urlopen(
                        'https://v6.ident.me/',
                        timeout=configuration.get('timeout')['ipv6_detection'])
                    if ipv6_addr and ipv6_addr.getcode() == 200:
                        ipv6_addr = ipv6_addr.read().decode().strip()

                except (URLError, SocketTimeoutError):
                    # It looks like this user doesn't have any IPv6 address...
                    # ... or is not connected to Internet.
                    ipv6_addr = None

        else:
            ipv6_addr = None

        # IPv4 addresses retrieval (anyway).
        try:
            ipv4_addr = check_output(
                [
                    'dig', '+short', '-4', 'A', 'myip.opendns.com',
                    '@resolver1.opendns.com'
                ],
                timeout=configuration.get('timeout')['ipv4_detection'],
                stderr=DEVNULL,
                universal_newlines=True).rstrip()

        except (FileNotFoundError, TimeoutExpired, CalledProcessError):
            try:
                ipv4_addr = urlopen(
                    'https://v4.ident.me/',
                    timeout=configuration.get('timeout')['ipv4_detection'])
                if ipv4_addr and ipv4_addr.getcode() == 200:
                    ipv4_addr = ipv4_addr.read().decode().strip()

            except (URLError, SocketTimeoutError):
                # The user does not look connected to Internet...
                ipv4_addr = None

        self.value = ', '.join(filter(
            None,
            (ipv4_addr,
             ipv6_addr))) or configuration.get('default_strings')['no_address']
Пример #11
0
def main():
    """Simple entry point"""

    # `Processes` is a singleton, let's populate the internal list here.
    Processes()

    # `Configuration` is a singleton, let's populate the internal object here.
    configuration = Configuration()

    output = Output()
    for entry in Entries:
        if configuration.get('entries', {}).get(entry.name, True):
            output.append(entry.name, entry.value().value)

    output.output()
Пример #12
0
class Entry(AbstractBaseClass):
    """Module base class"""
    @abstractmethod
    def __init__(self, name=None, value=None):
        # Each entry will have always have the following attributes...
        # `name` (key);
        # `value` (value of entry as an appropriate object)
        # ... which are `None` by default.
        self.name = name
        self.value = value

        # Propagates a reference to `Configuration` singleton to each inheriting class.
        self._configuration = Configuration()


    def output(self, output):
        """Output the results to output. Can be overridden by subclasses."""
        if self.value:
            # Let's assume we can just use `__str__` on the object in value,
            # and create a single-line output with it.
            output.append(self.name, str(self.value))
        else:
            # If the value is "falsy" leave a generic "Not detected" message for this entry.
            output.append(
                self.name,
                self._configuration.get('default_strings')['not_detected']
            )
Пример #13
0
class Entry(AbstractBaseClass):
    """Module base class"""
    @abstractmethod
    def __init__(self, name: str = None, value=None, options: dict = None):
        # Each entry will have always have the following attributes...
        # `name`: key (defaults to the instantiated entry class name);
        # `value`: value of entry as an appropriate object;
        # `options`: configuration options *specific* to an entry instance;
        self.name = name or self.__class__.__name__
        self.value = value
        self.options = options or {}

        # Propagates a reference to default strings specified in `Configuration`.
        self._default_strings = Configuration().get('default_strings')

    def __bool__(self):
        """Makes an `Entry` evaluates to _falsy_ if `disabled` config field is _truthy_"""
        return not bool(self.options.get('disabled'))

    def output(self, output):
        """Output the results to output. Can be overridden by subclasses."""
        if self.value:
            # Let's assume we can just use `__str__` on the object in value,
            # and create a single-line output with it.
            output.append(self.name, str(self.value))
        else:
            # If the value is "falsy" leave a generic "Not detected" message for this entry.
            output.append(self.name, self._default_strings.get('not_detected'))
Пример #14
0
    def __init__(self):
        for packages_tool in PACKAGES_TOOLS:
            try:
                results = check_output(packages_tool['cmd'],
                                       stderr=DEVNULL,
                                       env={'LANG': 'C'},
                                       universal_newlines=True)
            except (FileNotFoundError, CalledProcessError):
                continue

            packages = results.count('\n')

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

            # For DPKG only, remove any not purged package.
            if packages_tool['cmd'][0] == 'dpkg':
                packages -= results.count('deinstall')

            # At this step, we may break the loop.
            break

        else:
            packages = Configuration().get('default_strings')['not_detected']

        self.value = packages
Пример #15
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 = []
Пример #16
0
 def test__iter__(self):
     """Very simple method checking our `__iter__` implementation"""
     configuration = Configuration()
     self.assertEqual(
         configuration._config,  # pylint: disable=protected-access
         dict(configuration)
     )
Пример #17
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 = []
Пример #18
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 = []
Пример #19
0
def main():
    """Simple entry point"""
    args = args_parsing()

    # `Processes` is a singleton, let's populate the internal list here.
    Processes()

    # `Configuration` is a singleton, let's populate the internal object here.
    configuration = Configuration(config_path=args.config_path)

    # From configuration, gather the entries user-enabled.
    enabled_entries = [
        (entry.value, entry.name) for entry in Entries
        if configuration.get('entries', {}).get(entry.name, True)
    ]

    output = Output(preferred_distribution=args.distribution,
                    format_to_json=args.json)

    # We will map this function onto our enabled entries to instantiate them.
    def _entry_instantiator(entry_tuple):
        return entry_tuple[0](name=entry_tuple[1])

    # Let's use a context manager stack to manage conditional use of `TheadPoolExecutor`.
    with ExitStack() as cm_stack:
        if not configuration.get('parallel_loading'):
            mapper = map
        else:
            # Instantiate a threads pool to load our enabled entries in parallel.
            # We use threads (and not processes) since most work done by our entries is IO-bound.
            # `max_workers` is manually computed to mimic Python 3.8+ behaviour, but for our needs.
            #   See <https://github.com/python/cpython/pull/13618>.
            executor = cm_stack.enter_context(
                ThreadPoolExecutor(max_workers=min(
                    len(enabled_entries) or 1, (os.cpu_count() or 1) + 4)))
            mapper = executor.map

        for entry_instance in mapper(_entry_instantiator, enabled_entries):
            output.add_entry(entry_instance)

    output.output()

    # Has the screenshot flag been specified ?
    if args.screenshot is not None:
        # If so, but still _falsy_, pass `None` as no output file has been specified by the user.
        take_screenshot((args.screenshot or None))
Пример #20
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 = []
Пример #21
0
    def test_instantiation_config_path(self):
        """Test for configuration loading from specific user-defined path"""
        with tempfile.TemporaryDirectory() as temp_dir:
            # We create a fake temporary configuration file.
            config_file = os.path.join(temp_dir,
                                       'user.cfg')  # A pure arbitrary name.
            with open(config_file, 'w') as f_config:
                f_config.write("""\
{
    "allow_overriding": false,
    "suppress_warnings": true,
    "colors_palette": {
        "use_unicode": false
    },
    "ip_settings": {
        "lan_ip_max_count": 4
    },
    "temperature": {
        "use_fahrenheit": true
    }
}
""")

            configuration = Configuration(config_path=config_file)

            # We can't use `assertDictEqual` here as the resulting `_config` internal object
            #  directly depends on the default one (which constantly evolves).
            # We safely check that above entries have correctly been overridden.
            self.assertFalse(configuration.get('allow_overriding'))
            self.assertTrue(configuration.get('suppress_warnings'))
            self.assertFalse(
                configuration.get('colors_palette')['use_unicode'])
            self.assertEqual(
                configuration.get('ip_settings')['lan_ip_max_count'], 4)
            self.assertTrue(configuration.get('temperature')['use_fahrenheit'])
Пример #22
0
    def __init__(self):
        # The configuration object is needed to retrieve some settings below.
        configuration = Configuration()

        terminal = os.getenv(
            'TERM',
            configuration.get('default_strings')['not_detected'])

        # On systems with non-Unicode locales, we imitate '\u2588' character
        # ... with '#' to display the terminal colors palette.
        # This is the default option for backward compatibility.
        use_unicode = configuration.get('colors_palette')['use_unicode']
        colors = ' '.join([
            '\x1b[0;3{0}m{1}\x1b[1;3{0}m{1}{2}'.format(
                i, '\u2588' if use_unicode else '#', COLOR_DICT['clear'])
            for i in range(7, 0, -1)
        ])

        self.value = '{0} {1}'.format(terminal, colors)
Пример #23
0
    def __init__(self):
        distro_name = distro.name(pretty=True)
        if not distro_name:
            distro_name = Configuration().get('default_strings')['not_detected']

        architecture = check_output(
            ['uname', '-m'],
            universal_newlines=True
        ).rstrip()

        self.value = '{0} [{1}]'.format(distro_name, architecture)
Пример #24
0
    def __init__(self):
        user = os.getenv('USER')
        if not user:
            try:
                user = check_output(['id', '-u', '-n'],
                                    universal_newlines=True).rstrip()
            except CalledProcessError:
                # Should not occur, but who knows ?
                user = Configuration().get('default_strings')['not_detected']

        self.value = user
Пример #25
0
def main():
    """Simple entry point"""
    parser = argparse.ArgumentParser(prog='archey')
    parser.add_argument('-v',
                        '--version',
                        action='version',
                        version=__version__)
    parser.parse_args()

    # `Processes` is a singleton, let's populate the internal list here.
    Processes()

    # `Configuration` is a singleton, let's populate the internal object here.
    configuration = Configuration()

    output = Output()
    for entry in Entries:
        if configuration.get('entries', {}).get(entry.name, True):
            output.append(entry.name, entry.value().value)

    output.output()
Пример #26
0
    def __init__(self):
        # The configuration object is needed to retrieve some settings below.
        configuration = Configuration()

        terminal = os.getenv(
            'TERM',
            configuration.get('default_strings')['not_detected'])

        # On systems with non-Unicode locales, we imitate '\u2588' character
        # ... with '#' to display the terminal colors palette.
        # This is the default option for backward compatibility.
        use_unicode = configuration.get('colors_palette')['use_unicode']
        colors = ' '.join([
            '{normal}{character}{bright}{character}{clear}'.format(
                normal=Colors((0, i)),
                bright=Colors((1, i)),
                character=('\u2588' if use_unicode else '#'),
                clear=Colors.CLEAR) for i in range(37, 30, -1)
        ])

        self.value = '{0} {1}'.format(terminal, colors)
Пример #27
0
    def __init__(self):
        # The configuration object is needed to retrieve some settings below.
        configuration = Configuration()

        self.temps = []

        # Tries `sensors` at first.
        self._run_sensors()

        # On error (list still empty), checks for system thermal zones files.
        if not self.temps:
            self._poll_thermal_zones()

        # Tries `vcgencmd` for Raspberry devices.
        self._run_vcgencmd()

        # No value could be fetched...
        if not self.temps:
            self.value = configuration.get('default_strings')['not_detected']
            return

        # Let's DRY some constants once.
        use_fahrenheit = configuration.get('temperature')['use_fahrenheit']
        char_before_unit = configuration.get('temperature')['char_before_unit']

        # Conversion to Fahrenheit if needed.
        if use_fahrenheit:
            for i in range(len(self.temps)):
                self.temps[i] = self._convert_to_fahrenheit(self.temps[i])

        # Final average computation.
        self.value = '{0}{1}{2}'.format(
            str(round(sum(self.temps) / len(self.temps), 1)), char_before_unit,
            'F' if use_fahrenheit else 'C')

        # Multiple values ? Show the hottest.
        if len(self.temps) > 1:
            self.value += ' (Max. {0}{1}{2})'.format(
                str(round(max(self.temps), 1)), char_before_unit,
                'F' if use_fahrenheit else 'C')
    def test_get(self):
        """Test the `get` binder method to configuration elements"""
        # pylint: disable=protected-access
        configuration = Configuration()
        configuration._config = {
            'ip_settings': {
                'lan_ip_max_count': 2,
            },
            'temperature': {
                'use_fahrenheit': False
            }
        }

        self.assertEqual(
            configuration._config.get('ip_settings')['lan_ip_max_count'],
            2
        )
        self.assertFalse(
            configuration._config.get('temperature')['use_fahrenheit']
        )
        self.assertTrue(configuration._config.get('does_not_exist', True))
        self.assertIsNone(configuration._config.get('does_not_exist_either'))
Пример #29
0
    def __init__(self):
        shell = os.getenv('SHELL')
        if not shell:
            try:
                shell = check_output(
                    ['getent', 'passwd', str(os.getuid())],
                    universal_newlines=True
                ).rstrip().split(':')[-1]
            except CalledProcessError:
                # Where does this user come from ?
                shell = Configuration().get('default_strings')['not_detected']

        self.value = shell
Пример #30
0
    def __init__(self):
        processes = Processes().get()
        for key, value in DE_DICT.items():
            if key in processes:
                desktop_environment = value
                break

        else:
            # Let's rely on an environment var if the loop above didn't `break`
            desktop_environment = os.getenv(
                'XDG_CURRENT_DESKTOP',
                Configuration().get('default_strings')['not_detected']
            )

        self.value = desktop_environment