From 173c4d6e76637c5ac1579d8d70ac60c3e50f79d8 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 24 Aug 2014 01:20:25 +0400 Subject: [PATCH] Add internal_ip segment Closes #857 --- .../config_files/colorschemes/default.json | 1 + powerline/segments/common.py | 68 +++++++++++++++++++ tests/install.sh | 2 +- tests/lib/__init__.py | 3 +- tests/test_segments.py | 48 ++++++++++++- 5 files changed, 119 insertions(+), 3 deletions(-) diff --git a/powerline/config_files/colorschemes/default.json b/powerline/config_files/colorschemes/default.json index a015fe6b..8aed60a3 100644 --- a/powerline/config_files/colorschemes/default.json +++ b/powerline/config_files/colorschemes/default.json @@ -16,6 +16,7 @@ "weather_condition_rainy": { "fg": "skyblue1", "bg": "gray0", "attr": [] }, "uptime": { "fg": "gray8", "bg": "gray0", "attr": [] }, "external_ip": { "fg": "gray8", "bg": "gray0", "attr": [] }, + "internal_ip": { "fg": "gray8", "bg": "gray0", "attr": [] }, "network_load": { "fg": "gray8", "bg": "gray0", "attr": [] }, "network_load_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0", "attr": [] }, "system_load": { "fg": "gray8", "bg": "gray0", "attr": [] }, diff --git a/powerline/segments/common.py b/powerline/segments/common.py index da07c7a0..ecb77700 100644 --- a/powerline/segments/common.py +++ b/powerline/segments/common.py @@ -263,6 +263,74 @@ Divider highlight group used: ``background:divider``. ''') +try: + import netifaces +except ImportError: + def internal_ip(pl, interface='detect', ipv=4): + return None +else: + _interface_starts = { + 'eth': 10, # Regular ethernet adapters : eth1 + 'enp': 10, # Regular ethernet adapters, Gentoo : enp2s0 + 'ath': 9, # Atheros WiFi adapters : ath0 + 'wlan': 9, # Other WiFi adapters : wlan1 + 'wlp': 9, # Other WiFi adapters, Gentoo : wlp5s0 + 'teredo': 1, # miredo interface : teredo + 'lo': -10, # Loopback interface : lo + } + + _interface_start_re = re.compile(r'^([a-z]+?)(\d|$)') + + def _interface_key(interface): + match = _interface_start_re.match(interface) + if match: + try: + base = _interface_starts[match.group(1)] * 100 + except KeyError: + base = 500 + if match.group(2): + return base - int(match.group(2)) + else: + return base + else: + return 0 + + def internal_ip(pl, interface='detect', ipv=4): + if interface == 'detect': + try: + interface = next(iter(sorted(netifaces.interfaces(), key=_interface_key, reverse=True))) + except StopIteration: + pl.info('No network interfaces found') + return None + addrs = netifaces.ifaddresses(interface) + try: + return addrs[netifaces.AF_INET6 if ipv == 6 else netifaces.AF_INET][0]['addr'] + except (KeyError, IndexError): + return None + + +internal_ip = with_docstring(internal_ip, +'''Return internal IP address + +Requires ``netifaces`` package to work properly. + +:param str interface: + Interface on which IP will be checked. Use ``detect`` to automatically + detect interface. In this case interfaces with lower numbers will be + preferred over interfaces with similar names. Order of preference based on + names: + + #. ``eth`` and ``enp`` followed by number or the end of string. + #. ``ath``, ``wlan`` and ``wlp`` followed by number or the end of string. + #. ``teredo`` followed by number or the end of string. + #. Any other interface that is not ``lo*``. + #. ``lo`` followed by number or the end of string. +:param int ipv: + 4 or 6 for ipv4 and ipv6 respectively, depending on which IP address you + need exactly. +''') + + # Weather condition code descriptions available at # http://developer.yahoo.com/weather/#codes weather_conditions_codes = ( diff --git a/tests/install.sh b/tests/install.sh index e9e243b3..42ef7650 100755 --- a/tests/install.sh +++ b/tests/install.sh @@ -1,6 +1,6 @@ #!/bin/sh pip install . -pip install psutil +pip install psutil netifaces if python -c 'import sys; sys.exit(1 * (sys.version_info[0] != 2))' ; then # Python 2 if python -c 'import platform, sys; sys.exit(1 - (platform.python_implementation() == "CPython"))' ; then diff --git a/tests/lib/__init__.py b/tests/lib/__init__.py index ff340982..641642c2 100644 --- a/tests/lib/__init__.py +++ b/tests/lib/__init__.py @@ -9,10 +9,11 @@ class Pl(object): self.errors = [] self.warns = [] self.debugs = [] + self.infos = [] self.prefix = None self.use_daemon_threads = True - for meth in ('error', 'warn', 'debug', 'exception'): + for meth in ('error', 'warn', 'debug', 'exception', 'info'): exec (( 'def {0}(self, msg, *args, **kwargs):\n' ' self.{0}s.append((kwargs.get("prefix") or self.prefix, msg, args, kwargs))\n' diff --git a/tests/test_segments.py b/tests/test_segments.py index 2acccb46..9666ca0b 100644 --- a/tests/test_segments.py +++ b/tests/test_segments.py @@ -9,7 +9,7 @@ import sys import os from functools import partial from tests.lib import Args, urllib_read, replace_attr, new_module, replace_module_module, replace_env, Pl -from tests import TestCase +from tests import TestCase, SkipTest vim = None @@ -587,6 +587,52 @@ class TestCommon(TestCase): } ]) + def test_internal_ip(self): + try: + import netifaces + except ImportError: + raise SkipTest() + pl = Pl() + addr = { + 'enp2s0': { + netifaces.AF_INET: [{'addr': '192.168.100.200'}], + netifaces.AF_INET6: [{'addr': 'feff::5446:5eff:fe5a:7777%enp2s0'}] + }, + 'lo': { + netifaces.AF_INET: [{'addr': '127.0.0.1'}], + netifaces.AF_INET6: [{'addr': '::1'}] + }, + 'teredo': { + netifaces.AF_INET6: [{'addr': 'feff::5446:5eff:fe5a:7777'}] + }, + } + interfaces = ['lo', 'enp2s0', 'teredo'] + with replace_module_module( + common, 'netifaces', + interfaces=(lambda: interfaces), + ifaddresses=(lambda interface: addr[interface]), + AF_INET=netifaces.AF_INET, + AF_INET6=netifaces.AF_INET6, + ): + self.assertEqual(common.internal_ip(pl=pl), '192.168.100.200') + self.assertEqual(common.internal_ip(pl=pl, interface='detect'), '192.168.100.200') + self.assertEqual(common.internal_ip(pl=pl, interface='lo'), '127.0.0.1') + self.assertEqual(common.internal_ip(pl=pl, interface='teredo'), None) + self.assertEqual(common.internal_ip(pl=pl, ipv=4), '192.168.100.200') + self.assertEqual(common.internal_ip(pl=pl, interface='detect', ipv=4), '192.168.100.200') + self.assertEqual(common.internal_ip(pl=pl, interface='lo', ipv=4), '127.0.0.1') + self.assertEqual(common.internal_ip(pl=pl, interface='teredo', ipv=4), None) + self.assertEqual(common.internal_ip(pl=pl, ipv=6), 'feff::5446:5eff:fe5a:7777%enp2s0') + self.assertEqual(common.internal_ip(pl=pl, interface='detect', ipv=6), 'feff::5446:5eff:fe5a:7777%enp2s0') + self.assertEqual(common.internal_ip(pl=pl, interface='lo', ipv=6), '::1') + self.assertEqual(common.internal_ip(pl=pl, interface='teredo', ipv=6), 'feff::5446:5eff:fe5a:7777') + interfaces[1:2] = () + self.assertEqual(common.internal_ip(pl=pl, ipv=6), 'feff::5446:5eff:fe5a:7777') + interfaces[1:2] = () + self.assertEqual(common.internal_ip(pl=pl, ipv=6), '::1') + interfaces[:] = () + self.assertEqual(common.internal_ip(pl=pl, ipv=6), None) + class TestVim(TestCase): def test_mode(self):