diff --git a/boltons/iterutils.py b/boltons/iterutils.py index 4e7a37fc..2243950f 100644 --- a/boltons/iterutils.py +++ b/boltons/iterutils.py @@ -1475,8 +1475,13 @@ def __init__(self, size=24): def reseed(self): import socket self.pid = os.getpid() + hostname = socket.gethostname() + # gethostname() may return bytes on some platforms/configs; decode so + # the str.join() below does not raise a TypeError on a mixed sequence. + if isinstance(hostname, bytes): + hostname = hostname.decode('utf8', 'replace') self.salt = '-'.join([str(self.pid), - socket.gethostname() or '', + hostname or '', str(time.time()), os.urandom(6).hex()]) return diff --git a/tests/test_iterutils.py b/tests/test_iterutils.py index e62e36c3..d3d4e2e6 100644 --- a/tests/test_iterutils.py +++ b/tests/test_iterutils.py @@ -535,6 +535,21 @@ def test_guiderator(): assert len(next(guid_iter)) == 26 +def test_guiderator_bytes_hostname(monkeypatch): + # socket.gethostname() may return bytes on some platforms; reseed() must + # not raise a TypeError when building the salt (issue #295). + import socket + import string + from boltons.iterutils import GUIDerator + + monkeypatch.setattr(socket, 'gethostname', lambda: b'myhost') + + guid_iter = GUIDerator() + guid = next(guid_iter) + assert guid + assert all([c in string.hexdigits for c in guid]) + + def test_seqguiderator(): import string from boltons.iterutils import SequentialGUIDerator as GUIDerator