Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Output/Entry] Changes entries output method to pretty_value property #147

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion archey/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class Colors8Bit(Style):
"""

def __init__(self, bright: int, value: int):
if bright not in (0, 1) or value not in range(0, 255):
if bright not in (0, 1) or not 0 <= value <= 255:
raise ValueError("Supplied color is outside the allowed range.")
# `ESC[38;5` selects 8-bit foreground colour
self.value = (bright, 38, 5, value)
30 changes: 8 additions & 22 deletions archey/entries/cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,25 +186,11 @@ def _parse_sysctl_cpu_model() -> List[Dict[str, int]]:
model_name, nb_cores = sysctl_output.splitlines()
return [{model_name: int(nb_cores)}]

def output(self, output) -> None:
"""Writes CPUs to `output` based on preferences"""
# No CPU could be detected.
if not self.value:
output.append(self.name, self._default_strings.get("not_detected"))
return

entries = []
for cpus in self.value:
for model_name, cpu_count in cpus.items():
if cpu_count > 1 and self.options.get("show_cores", True):
entries.append(f"{cpu_count} x {model_name}")
else:
entries.append(model_name)

if self.options.get("one_line"):
# One-line output is enabled : Join the results !
output.append(self.name, ", ".join(entries))
else:
# One-line output has been disabled, add one entry per item.
for entry in entries:
output.append(self.name, entry)
def __next__(self) -> Entry.ValueType:
"""Yield nicely-formatted CPU values"""
cpu = next(self._iter_value)

model_name, cpu_count = next(iter(cpu.items())) # This dict only ever has one entry
if cpu_count > 1 and self.options.get("show_cores", True):
return (self.name, f"{cpu_count} x {model_name}")
return (self.name, model_name)
14 changes: 3 additions & 11 deletions archey/entries/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,6 @@ def __init__(self, *args, **kwargs):
if log_stderr and proc.stderr:
self._logger.warning("%s", proc.stderr.rstrip())

def output(self, output) -> None:
if not self.value:
output.append(self.name, self._default_strings.get("not_detected"))
return

# Join the results only if `one_line` option is enabled.
if self.options.get("one_line", True):
output.append(self.name, ", ".join(self.value))
else:
for element in self.value:
output.append(self.name, element)
def __next__(self) -> Entry.ValueType:
"""Yield nicely-formatted entry values"""
return (self.name, str(next(self._iter_value)))
120 changes: 60 additions & 60 deletions archey/entries/disk.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
import plistlib
import re
from subprocess import DEVNULL, PIPE, check_output, run
from typing import Dict, Iterable, List
from typing import Dict, Iterable, List, TypeVar

from archey.colors import Colors
from archey.entry import Entry

Self = TypeVar("Self", bound="Disk")


class Disk(Entry):
"""Uses `df` to compute disk usage across devices"""
Expand Down Expand Up @@ -228,70 +230,68 @@ def _blocks_to_human_readable(blocks: float, suffix: str = "B") -> str:

return f"{blocks:02.1f} {unit}{suffix}"

def output(self, output) -> None:
"""
Adds the entry to `output` after formatting with color and units.
Follows the user configuration supplied for formatting.
"""
# Fetch our `filesystems` object locally so we can modify it safely.
filesystems = self.value

if not filesystems:
# We didn't find any disk, fall back to the default entry behavior.
super().output(output)
return
def __str__(self):
return "placeholder"

def __iter__(self: Self) -> Self:
"""Sets up iterable for entry."""
# Combine all entries into one grand-total if configured to do so
# (and we have a "truthy" value).
if self.options.get("combine_total", True) and self.value:
# Tuple inside list in order to get a proper iter
self._iter_value = iter(
{
None: {
"device_path": None,
"used_blocks": sum(
fs_data["used_blocks"] for fs_data in self.value.values()
),
"total_blocks": sum(
fs_data["total_blocks"] for fs_data in self.value.values()
),
},
}.items()
)
else:
self._iter_value = iter(self.value.items())
return self

def __next__(self) -> Entry.ValueType:
"""Yield nicely-formatted disk entry values"""
# DRY configuration object for the output.
disk_labels = self.options.get("disk_labels")
hide_entry_name = self.options.get("hide_entry_name")

# Combine all entries into one grand-total if configured to do so.
if self.options.get("combine_total", True):
name = self.name

# Rewrite our `filesystems` object as one combining all of them.
filesystems = {
None: {
"device_path": None,
"used_blocks": sum(
filesystem_data["used_blocks"] for filesystem_data in filesystems.values()
),
"total_blocks": sum(
filesystem_data["total_blocks"] for filesystem_data in filesystems.values()
),
}
}
filesystem = next(self._iter_value)

# Work out name
fs_name = ""
if not (hide_entry_name and disk_labels):
# Only allow entry name to be hidden if labels are defined
fs_name += self.name
if disk_labels:
if not hide_entry_name:
fs_name += " "
fs_name += "({disk_label})"

# Select the corresponding level color based on disk percentage usage.
level_color = Colors.get_level_color(
(filesystem[1]["used_blocks"] / filesystem[1]["total_blocks"]) * 100,
self.options.get("warning_use_percent", 50),
self.options.get("danger_use_percent", 75),
)

# Set the correct disk label
if disk_labels == "mount_points":
disk_label = filesystem[0]
elif disk_labels == "device_paths":
disk_label = filesystem[1]["device_path"]
else:
# We will only use disk labels and entry name hiding if we aren't combining entries.
name = ""
# Hide `Disk` from entry name only if the user specified it... as long as a label.
if not hide_entry_name or not disk_labels:
name += self.name
if disk_labels:
if not hide_entry_name:
name += " "
name += "({disk_label})"

# We will only run this loop a single time for combined entries.
for mount_point, filesystem_data in filesystems.items():
# Select the corresponding level color based on disk percentage usage.
level_color = Colors.get_level_color(
(filesystem_data["used_blocks"] / filesystem_data["total_blocks"]) * 100,
self.options.get("warning_use_percent", 50),
self.options.get("danger_use_percent", 75),
)
disk_label = None

# Set the correct disk label
if disk_labels == "mount_points":
disk_label = mount_point
elif disk_labels == "device_paths":
disk_label = filesystem_data["device_path"]
else:
disk_label = None

pretty_filesystem_value = f"{level_color}{{}}{Colors.CLEAR} / {{}}".format(
self._blocks_to_human_readable(filesystem_data["used_blocks"]),
self._blocks_to_human_readable(filesystem_data["total_blocks"]),
)
pretty_filesystem_value = f"{level_color}{{}}{Colors.CLEAR} / {{}}".format(
self._blocks_to_human_readable(filesystem[1]["used_blocks"]),
self._blocks_to_human_readable(filesystem[1]["total_blocks"]),
)

output.append(name.format(disk_label=disk_label), pretty_filesystem_value)
return (fs_name.format(disk_label=disk_label), pretty_filesystem_value)
9 changes: 3 additions & 6 deletions archey/entries/distro.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@ def _fetch_darwin_release() -> Optional[str]:

return f"Darwin {platform.release()}"

def output(self, output) -> None:
output.append(
self.name,
f"{{}} {self.value['arch']}".format(
self.value["name"] or self._default_strings.get("not_detected")
),
def __str__(self) -> str:
return f"{{}} {self.value['arch']}".format(
self.value["name"] or self._default_strings.get("not_detected")
)
16 changes: 3 additions & 13 deletions archey/entries/gpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,6 @@ def _parse_pciconf_output() -> List[str]:

return gpus_list

def output(self, output) -> None:
"""Writes GPUs to `output` based on preferences"""
# No GPU could be detected.
if not self.value:
output.append(self.name, self._default_strings.get("not_detected"))
return

# Join the results only if `one_line` option is enabled.
if self.options.get("one_line"):
output.append(self.name, ", ".join(self.value))
else:
for gpu_device in self.value:
output.append(self.name, gpu_device)
def __next__(self) -> Entry.ValueType:
"""Yield nicely-formatted GPU entry values"""
return (self.name, str(next(self._iter_value)))
4 changes: 2 additions & 2 deletions archey/entries/kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def _fetch_latest_linux_release() -> Optional[str]:

return kernel_releases.get("latest_stable", {}).get("version")

def output(self, output) -> None:
def __str__(self) -> "str":
"""Display running kernel and latest kernel if possible"""
text_output = " ".join((self.value["name"], self.value["release"]))

Expand All @@ -68,4 +68,4 @@ def output(self, output) -> None:
else:
text_output += f" ({self._default_strings.get('latest')})"

output.append(self.name, text_output)
return text_output
34 changes: 15 additions & 19 deletions archey/entries/lan_ip.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import ipaddress
from itertools import islice
from typing import Iterator
from typing import Iterator, TypeVar

try:
import netifaces
Expand All @@ -11,6 +11,8 @@

from archey.entry import Entry

Self = TypeVar("Self", bound="LanIP")


class LanIP(Entry):
"""Relies on the `netifaces` module to detect LAN IP addresses"""
Expand Down Expand Up @@ -75,23 +77,17 @@ def _lan_ip_addresses_generator(
# Finally, yield the address compressed representation.
yield ip_addr.compressed

def output(self, output) -> None:
"""Adds the entry to `output` after pretty-formatting the IP address list."""
# If we found IP addresses, join them together nicely.
# If not, fall back on default strings according to `netifaces` availability.
if self.value:
if not self.options.get("one_line", True):
# One-line output has been disabled, add one IP address per item.
for ip_address in self.value:
output.append(self.name, ip_address)

return

text_output = ", ".join(self.value)

elif netifaces:
text_output = self._default_strings.get("no_address")
def __iter__(self: Self) -> Self:
"""Sets up iterable over IP addresses"""
if not self.value and netifaces:
# If no IP addresses found, fall-back on the "No address" string.
self._iter_value = iter([self._default_strings.get("no_address")])
elif not self.value:
self._iter_value = iter([])
else:
text_output = self._default_strings.get("not_detected")
self._iter_value = iter(self.value)
return self

output.append(self.name, text_output)
def __next__(self) -> Entry.ValueType:
"""Yield IP addresses."""
return (self.name, str(next(self._iter_value)))
24 changes: 8 additions & 16 deletions archey/entries/load_average.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,17 @@ def __init__(self, *args, **kwargs):
with suppress(AttributeError):
self.value = os.getloadavg()

def output(self, output) -> None:
if not self.value:
# Fall back on the default behavior if load average values could not be detected.
super().output(output)
return

def __str__(self) -> str:
# DRY constant thresholds.
decimal_places = self.options.get("decimal_places", 2)
warning_threshold = self.options.get("warning_threshold", 1.0)
danger_threshold = self.options.get("danger_threshold", 2.0)

output.append(
self.name,
" ".join(
[
str(Colors.get_level_color(load_avg, warning_threshold, danger_threshold))
+ str(round(load_avg, decimal_places))
+ str(Colors.CLEAR)
for load_avg in self.value
]
),
return " ".join(
[
str(Colors.get_level_color(load_avg, warning_threshold, danger_threshold))
+ str(round(load_avg, decimal_places))
+ str(Colors.CLEAR)
for load_avg in self.value
]
)
14 changes: 2 additions & 12 deletions archey/entries/ram.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,7 @@ def _run_sysctl_mem() -> Tuple[float, float]:

return (mem_used / 1024), (mem_total / 1024)

def output(self, output) -> None:
"""
Adds the entry to `output` after pretty-formatting the RAM usage with color and units.
"""
if not self.value:
# Fall back on the default behavior if no RAM usage could be detected.
super().output(output)
return

def __str__(self) -> str:
# DRY some constants
used = self.value["used"]
total = self.value["total"]
Expand All @@ -175,6 +167,4 @@ def output(self, output) -> None:
self.options.get("danger_use_percent", 66.7),
)

output.append(
self.name, f"{level_color}{int(used)} {unit}{Colors.CLEAR} / {int(total)} {unit}"
)
return f"{level_color}{int(used)} {unit}{Colors.CLEAR} / {int(total)} {unit}"
10 changes: 2 additions & 8 deletions archey/entries/temperature.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,7 @@ def _convert_to_fahrenheit(temp: float) -> float:
"""Simple Celsius to Fahrenheit conversion method"""
return temp * (9 / 5) + 32

def output(self, output) -> None:
"""Adds the entry to `output` after pretty-formatting with units."""
if not self.value:
# Fall back on the default behavior if no temperatures were detected.
super().output(output)
return

def __str__(self) -> str:
# DRY some constants
char_before_unit = self.value["char_before_unit"]
unit = self.value["unit"]
Expand All @@ -242,4 +236,4 @@ def output(self, output) -> None:
if len(self._temps) > 1:
entry_text += f" (Max. {self.value['max_temperature']}{char_before_unit}{unit})"

output.append(self.name, entry_text)
return entry_text
6 changes: 2 additions & 4 deletions archey/entries/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,8 @@ def _detect_terminal_emulator() -> Optional[str]:
# Note : It _might_ be `None` in very specific environments.
return env_term

def output(self, output) -> None:
"""Adds the entry to `output` after pretty-formatting with colors palette"""
def __str__(self) -> str:
text_output = self.value or self._default_strings.get("not_detected")
if Style.should_color_output():
text_output += " " + self._get_colors_palette()

output.append(self.name, text_output)
return text_output
Loading
Loading