From b951907912df463bf727de826dc87365c96cfe6d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 21 Mar 2013 17:24:09 +0100 Subject: [PATCH] Autodetect network interfaces to monitor --- powerline/lib/threaded.py | 7 ++++-- powerline/segments/common.py | 45 ++++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/powerline/lib/threaded.py b/powerline/lib/threaded.py index b9841cec..8d8ff5d4 100644 --- a/powerline/lib/threaded.py +++ b/powerline/lib/threaded.py @@ -67,11 +67,14 @@ class ThreadedSegment(Thread): self.update() def startup(self, **kwargs): + # Normally .update() succeeds to run before value is requested, meaning + # that user is getting values he needs directly at vim startup. Without + # .startup() we will not have to wait long until receiving bug “I opened + # vim, but branch information is only shown after I move cursor”. self.run_once = False - self.set_state(**kwargs) - if not self.is_alive(): + self.set_state(**kwargs) self.start() diff --git a/powerline/segments/common.py b/powerline/segments/common.py index dfa1a3ae..551a1dd4 100644 --- a/powerline/segments/common.py +++ b/powerline/segments/common.py @@ -452,6 +452,12 @@ try: return None return if_io.bytes_recv, if_io.bytes_sent + def _get_interfaces(): + io_counters = psutil.network_io_counters(pernic=True) + for interface, data in io_counters.items(): + if data: + yield interface, data.bytes_recv, data.bytes_sent + def _get_user(): return psutil.Process(os.getpid()).username @@ -476,6 +482,12 @@ except ImportError: except IOError: return None + def _get_interfaces(): + for interface in os.listdir('/sys/class/net'): + x = _get_bytes(interface) + if x is not None: + yield interface, x[0], x[1] + def _get_user(): # NOQA return os.environ.get('USER', None) @@ -552,13 +564,42 @@ def uptime(format='{days}d {hours:02d}h {minutes:02d}m'): class NetworkLoadSegment(KwThreadedSegment): + import re interfaces = {} + replace_num_pat = re.compile(r'[a-zA-Z]+') @staticmethod - def key(interface='eth0', **kwargs): + def key(interface='detect', **kwargs): return interface def compute_state(self, interface): + if interface == 'detect': + proc_exists = getattr(self, 'proc_exists', None) + if proc_exists is None: + proc_exists = self.proc_exists = os.path.exists('/proc/net/route') + if proc_exists: + # Look for default interface in routing table + with open('/proc/net/route', 'rb') as f: + for line in f.readlines(): + parts = line.split() + if len(parts) > 1: + iface, destination = parts[:2] + if not destination.replace(b'0', b''): + interface = iface.decode('utf-8') + break + if interface == 'detect': + # Choose interface with most total activity, excluding some + # well known interface names + interface, total = 'eth0', -1 + for name, rx, tx in _get_interfaces(): + base = self.replace_num_pat.match(name) + if None in (base, rx, tx) or base.group() in ('lo', 'vmnet', 'sit'): + continue + activity = rx + tx + if activity > total: + total = activity + interface = name + if interface in self.interfaces: idata = self.interfaces[interface] try: @@ -603,7 +644,7 @@ falls back to reading :file:`/sys/class/net/{interface}/statistics/{rx,tx}_bytes`. :param str interface: - network interface to measure + network interface to measure (use the special value "detect" to have powerline try to auto-detect the network interface) :param str suffix: string appended to each load string :param bool si_prefix: