Skip to content

Commit

Permalink
Ethernet functionality on the Wlan widget (#4569)
Browse files Browse the repository at this point in the history
Included functionality to display a message when Ethernet is connected and WiFi disconnected.
  • Loading branch information
Sprinter05 committed Mar 11, 2024
1 parent 13e9ac8 commit 04354d5
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 6 deletions.
35 changes: 30 additions & 5 deletions libqtile/widget/wlan.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,19 @@ class Wlan(base.InLoopPollText):
orientations = base.ORIENTATION_HORIZONTAL
defaults = [
("interface", "wlan0", "The interface to monitor"),
(
"ethernet_interface",
"eth0",
"The ethernet interface to monitor, NOTE: If you do not have a wlan device in your system, ethernet functionality will not work, use the Net widget instead",
),
("update_interval", 1, "The update interval."),
("disconnected_message", "Disconnected", "String to show when the wlan is diconnected."),
("ethernet_message", "eth", "String to show when ethernet is being used"),
(
"use_ethernet",
False,
"Activate or deactivate checking for ethernet when no wlan connection is detected",
),
(
"format",
"{essid} {quality}/70",
Expand All @@ -65,18 +76,32 @@ class Wlan(base.InLoopPollText):
def __init__(self, **config):
base.InLoopPollText.__init__(self, **config)
self.add_defaults(Wlan.defaults)
self.ethernetInterfaceNotFound = False

def poll(self):
try:
essid, quality = get_status(self.interface)
disconnected = essid is None
if disconnected:
return self.disconnected_message

if self.use_ethernet:
try:
with open(
f"/sys/class/net/{self.ethernet_interface}/operstate", "r"
) as statfile:
if statfile.read().strip() == "up":
return self.ethernet_message
else:
return self.disconnected_message
except FileNotFoundError:
if not self.ethernetInterfaceNotFound:
logger.error("Ethernet interface has not been found!")
self.ethernetInterfaceNotFound = True
return self.disconnected_message
else:
return self.disconnected_message
return self.format.format(essid=essid, quality=quality, percent=(quality / 70))
except EnvironmentError:
logger.error(
"%s: Probably your wlan device is switched off or "
" otherwise not present in your system.",
self.__class__.__name__,
"Probably your wlan device is switched off or "
" otherwise not present in your system."
)
43 changes: 42 additions & 1 deletion test/widgets/test_wlan.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

# Widget specific tests

import builtins
import sys
from importlib import reload
from types import ModuleType
Expand All @@ -34,6 +35,23 @@ def no_op(*args, **kwargs):
pass


def mock_open(output):
class MockOpen:
def __init__(self, *args):
self.output = output

def __enter__(self):
return self

def __exit__(*exc):
return None

def read(self):
return self.output

return MockOpen


class MockIwlib(ModuleType):
DATA = {
"wlan0": {
Expand All @@ -44,7 +62,10 @@ class MockIwlib(ModuleType):
"ESSID": b"QtileNet",
"Mode": b"Managed",
"stats": {"quality": 49, "level": 190, "noise": 0, "updated": 75},
}
},
"wlan1": {
"ESSID": None,
},
}

@classmethod
Expand Down Expand Up @@ -80,3 +101,23 @@ def test_wlan_display(minimal_conf_noscreen, manager_nospawn, patched_wlan, kwar

text = manager_nospawn.c.bar["top"].info()["widgets"][0]["text"]
assert text == expected


@pytest.mark.parametrize(
"kwargs,state,expected",
[
({"interface": "wlan1", "use_ethernet": True}, "up", "eth"),
({"interface": "wlan1", "use_ethernet": True}, "down", "Disconnected"),
(
{"interface": "wlan1", "use_ethernet": True, "ethernet_message": "Wired"},
"up",
"Wired",
),
],
)
def test_ethernet(
minimal_conf_noscreen, manager_nospawn, patched_wlan, kwargs, state, expected, monkeypatch
):
monkeypatch.setattr(builtins, "open", mock_open(state))
widget = patched_wlan.Wlan(**kwargs)
assert widget.poll() == expected

0 comments on commit 04354d5

Please sign in to comment.