From aa11afbed3b23343c3680ac24888c0aedec20810 2014-05-07 20:05:28
From: Thomas Kluyver <takowl@gmail.com>
Date: 2014-05-07 20:05:28
Subject: [PATCH] Backport PR #5486: disambiguate to location when no IPs can be determined

previously, fallback was to localhost, which could often be wrong.

closes #5477

---

diff --git a/IPython/parallel/util.py b/IPython/parallel/util.py
index 3d98fae..17ab32a 100644
--- a/IPython/parallel/util.py
+++ b/IPython/parallel/util.py
@@ -1,27 +1,15 @@
-"""Some generic utilities for dealing with classes, urls, and serialization.
+"""Some generic utilities for dealing with classes, urls, and serialization."""
 
-Authors:
+# Copyright (c) IPython Development Team.
+# Distributed under the terms of the Modified BSD License.
 
-* Min RK
-"""
-#-----------------------------------------------------------------------------
-#  Copyright (C) 2010-2011  The IPython Development Team
-#
-#  Distributed under the terms of the BSD License.  The full license is in
-#  the file COPYING, distributed as part of this software.
-#-----------------------------------------------------------------------------
-
-#-----------------------------------------------------------------------------
-# Imports
-#-----------------------------------------------------------------------------
-
-# Standard library imports.
 import logging
 import os
 import re
 import stat
 import socket
 import sys
+import warnings
 from signal import signal, SIGINT, SIGABRT, SIGTERM
 try:
     from signal import SIGKILL
@@ -36,13 +24,11 @@ except:
     cPickle = None
     import pickle
 
-# System library imports
 import zmq
 from zmq.log import handlers
 
 from IPython.external.decorator import decorator
 
-# IPython imports
 from IPython.config.application import Application
 from IPython.utils.localinterfaces import localhost, is_public_ip, public_ips
 from IPython.utils.py3compat import string_types, iteritems, itervalues
@@ -184,18 +170,42 @@ def split_url(url):
     assert len(lis) == 2, 'Invalid url: %r'%url
     addr,s_port = lis
     return proto,addr,s_port
-    
+
+
 def disambiguate_ip_address(ip, location=None):
-    """turn multi-ip interfaces '0.0.0.0' and '*' into connectable
-    ones, based on the location (default interpretation of location is localhost)."""
-    if ip in ('0.0.0.0', '*'):
-        if location is None or is_public_ip(location) or not public_ips():
-            # If location is unspecified or cannot be determined, assume local
+    """turn multi-ip interfaces '0.0.0.0' and '*' into a connectable address
+    
+    Explicit IP addresses are returned unmodified.
+    
+    Parameters
+    ----------
+    
+    ip : IP address
+        An IP address, or the special values 0.0.0.0, or *
+    location: IP address, optional
+        A public IP of the target machine.
+        If location is an IP of the current machine,
+        localhost will be returned,
+        otherwise location will be returned.
+    """
+    if ip in {'0.0.0.0', '*'}:
+        if not location:
+            # unspecified location, localhost is the only choice
+            ip = localhost()
+        elif is_public_ip(location):
+            # location is a public IP on this machine, use localhost
             ip = localhost()
-        elif location:
-            return location
+        elif not public_ips():
+            # this machine's public IPs cannot be determined,
+            # assume `location` is not this machine
+            warnings.warn("IPython could not determine public IPs", RuntimeWarning)
+            ip = location
+        else:
+            # location is not this machine, do not use loopback
+            ip = location
     return ip
 
+
 def disambiguate_url(url, location=None):
     """turn multi-ip interfaces '0.0.0.0' and '*' into connectable
     ones, based on the location (default interpretation is localhost).