diff --git a/openlp/core/api/tab.py b/openlp/core/api/tab.py index d57b88a65..840fb0d0b 100644 --- a/openlp/core/api/tab.py +++ b/openlp/core/api/tab.py @@ -24,7 +24,7 @@ The :mod:`~openlp.core.api.tab` module contains the settings tab for the API """ from PyQt5 import QtCore, QtGui, QtNetwork, QtWidgets -from openlp.core.common import MY_IP4 +from openlp.core.common import get_local_ip4 from openlp.core.common.i18n import UiStrings, translate from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings @@ -221,8 +221,9 @@ class ApiTab(SettingsTab): """ if ip_address == ZERO_URL: # In case we have more than one interface - for key in iter(MY_IP4): - ip_address = MY_IP4.get(key)['ip'] + ifaces = get_local_ip4() + for key in iter(ifaces): + ip_address = ifaces.get(key)['ip'] # We only want the first interface returned break return ip_address diff --git a/openlp/core/common/__init__.py b/openlp/core/common/__init__.py index 6222ea3aa..d1f62fb8b 100644 --- a/openlp/core/common/__init__.py +++ b/openlp/core/common/__init__.py @@ -52,26 +52,43 @@ REPLACMENT_CHARS_MAP = str.maketrans({'\u2018': '\'', '\u2019': '\'', '\u201c': NEW_LINE_REGEX = re.compile(r' ?(\r\n?|\n) ?') WHITESPACE_REGEX = re.compile(r'[ \t]+') -# Get the local IPv4 active address(es) that are NOT localhost (lo or '127.0.0.1') -log.debug('Getting local IPv4 interface(es) information') -MY_IP4 = {} -for iface in QNetworkInterface.allInterfaces(): - if not iface.isValid() or not (iface.flags() & (QNetworkInterface.IsUp | QNetworkInterface.IsRunning)): - continue - for address in iface.addressEntries(): - ip = address.ip() - if (ip.protocol() == QAbstractSocket.IPv4Protocol) and (ip != QHostAddress.LocalHost): - MY_IP4[iface.name()] = {'ip': ip.toString(), - 'broadcast': address.broadcast().toString(), - 'netmask': address.netmask().toString(), - 'prefix': address.prefixLength(), - 'localnet': QHostAddress(address.netmask().toIPv4Address() & - ip.toIPv4Address()).toString() - } - log.debug('Adding {iface} to active list'.format(iface=iface.name())) -if not MY_IP4: - log.warning('No active IPv4 interfaces found') +def get_local_ip4(): + """ + Creates a dictionary of local IPv4 interfaces on local machine. + If no active interfaces available, returns a dict of localhost IPv4 information + + :returns: Dict of interfaces + """ + # Get the local IPv4 active address(es) that are NOT localhost (lo or '127.0.0.1') + log.debug('Getting local IPv4 interface(es) information') + MY_IP4 = {} + for iface in QNetworkInterface.allInterfaces(): + if not iface.isValid() or not (iface.flags() & (QNetworkInterface.IsUp | QNetworkInterface.IsRunning)): + continue + for address in iface.addressEntries(): + ip = address.ip() + # NOTE: Next line will skip if interface is localhost - keep for now until we decide about it later + # if (ip.protocol() == QAbstractSocket.IPv4Protocol) and (ip != QHostAddress.LocalHost): + if (ip.protocol() == QAbstractSocket.IPv4Protocol): + MY_IP4[iface.name()] = {'ip': ip.toString(), + 'broadcast': address.broadcast().toString(), + 'netmask': address.netmask().toString(), + 'prefix': address.prefixLength(), + 'localnet': QHostAddress(address.netmask().toIPv4Address() & + ip.toIPv4Address()).toString() + } + log.debug('Adding {iface} to active list'.format(iface=iface.name())) + if len(MY_IP4) == 1: + if 'lo' in MY_IP4: + # No active interfaces - so leave localhost in there + log.warning('No active IPv4 interfaces found except localhost') + else: + # Since we have a valid IP4 interface, remove localhost + log.debug('Found at least one IPv4 interface, removing localhost') + MY_IP4.pop('lo') + + return MY_IP4 def trace_error_handler(logger): diff --git a/tests/functional/openlp_core/api/test_tab.py b/tests/functional/openlp_core/api/test_tab.py index 7c57c8001..cf8b4d0b0 100644 --- a/tests/functional/openlp_core/api/test_tab.py +++ b/tests/functional/openlp_core/api/test_tab.py @@ -29,7 +29,7 @@ from unittest.mock import patch from PyQt5 import QtWidgets from openlp.core.api.tab import ApiTab -from openlp.core.common import MY_IP4 +from openlp.core.common import get_local_ip4 from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from tests.helpers.testmixin import TestMixin @@ -64,6 +64,7 @@ class TestApiTab(TestCase, TestMixin): Registry().create() Registry().set_flag('website_version', '00-00-0000') self.form = ApiTab(self.parent) + self.my_ip4_list = get_local_ip4() def tearDown(self): """ @@ -73,18 +74,22 @@ class TestApiTab(TestCase, TestMixin): del self.form self.destroy_settings() - @patch.dict(MY_IP4, {'test': {'ip': '127.0.0.1'}}, clear=True) def test_get_ip_address_default(self): """ Test the get_ip_address function with ZERO_URL """ + # GIVEN: list of local IP addresses for this machine + ip4_list = [] + for ip4 in iter(self.my_ip4_list): + ip4_list.append(self.my_ip4_list.get(ip4)['ip']) + # WHEN: the default ip address is given ip_address = self.form.get_ip_address(ZERO_URL) # THEN: the default ip address will be returned assert re.match('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', ip_address), \ 'The return value should be a valid ip address' - assert ip_address == '127.0.0.1', 'The return address should match the test address' + assert ip_address in ip4_list, 'The return address should be in the list of local IP addresses' def test_get_ip_address_with_ip(self): """