diff --git a/src/hostinfo.py b/src/hostinfo.py
index 25121d39b19072c612e37b36856237430b9da3e7..e5516410ce63a499bbfbdc9b2e6fe157898b7e03 100755
--- a/src/hostinfo.py
+++ b/src/hostinfo.py
@@ -77,6 +77,9 @@ if not hasattr(__builtins__, "True"):
 
 attr_key_table = {
     ('host', 'name') : 1,
+    ('host', 'duid') : 2,
+    ('host', 'serial') : 3,
+    ('host', 'info') : 4,
     ('disk', 'host') : 1,
     ('disk', 'root') : 2,
     ('disk', 'id') : 3,
@@ -85,21 +88,20 @@ attr_key_table = {
     ('interface', 'ip') : 1,
     ('interface', 'ether') : 2,
     ('subnet', 'network') : 1,
-    ('subnet', 'prefix') : 1,
-    ('subnet', 'domain') : 2,
-    ('subnet', 'broadcast') : 3,
-    ('subnet', 'netmask') : 4,
-    ('subnet', 'gateway') : 5,
-    ('subnet', 'name_servers') : 6,
+    ('subnet', 'prefix') : 2,
+    ('subnet', 'domain') : 3,
+    ('subnet', 'broadcast') : 4,
+    ('subnet', 'netmask') : 5,
+    ('subnet', 'gateway') : 6,
+    ('subnet', 'name_servers') : 7,
     None : 99,
 }
 
-def attr_key(node, attr): # , b
-    return
+def attr_key(node, attr):
     try:
-        return attr_key_table[node._tag, attr]
+        return (attr_key_table[node._tag, attr], attr)
     except:
-        return attr_key_table[None]
+        return (attr_key_table[None], attr)
 
 def network_order(n):
     net = hostinfo.util.network(n)
@@ -153,6 +155,9 @@ node_key_table = {
     ('hostinfo', 'nameserver')  : (3, None),
     ('hostinfo', 'netgroup')    : (4, lambda n: n.name[0]),
     ('hostinfo', 'host')        : (5, host_order),
+    ('subnet', 'txt')           : (1, lambda t: t.value[0]),
+    ('subnet', 'cname')         : (2, lambda c: c.alias[0]),
+    ('subnet', 'srv')           : (3, lambda s: s.name[0]),
     ('host', 'role')            : (1, None),
     ('host', 'automount')       : (2, lambda a: a.host[0]),
     ('host', 'mio')             : (3, None),
@@ -278,7 +283,6 @@ if __name__ == '__main__':
             tree, options)
         pass
             
-    
     if options.ethers:
         file[options.ethers] = hostinfo.yp.ethers(tree)
 
@@ -298,7 +302,13 @@ if __name__ == '__main__':
         
     if options.mio:
         mio = hostinfo.mio.generate(tree)
-        print(mio.encode("utf-8"))
+        try:
+            print(mio)
+            pass
+        except UnicodeEncodeError:
+            # Python 2 hack
+            print(mio.encode('utf-8'))
+            pass
         
     if options.named:
         for (f, c) in hostinfo.named.generate(tree, options):
@@ -310,7 +320,13 @@ if __name__ == '__main__':
     if options.pretty:
         result = "<?xml version='1.0' encoding='utf-8'?>\n\n"
         result += tree._xml(attr_key=attr_key, node_key=node_key)
-        print(result.encode("utf-8"))
+        try:
+            print(result)
+            pass
+        except UnicodeEncodeError:
+            # Python 2 hack
+            print(result.encode('utf-8'))
+            pass
         sys.exit(0)
 
     if options.role:
@@ -337,7 +353,7 @@ if __name__ == '__main__':
             f = open(name)
             conf = f.read()
             f.close()
-            write = conf != file[name].encode("utf-8")
+            write = conf != file[name]
         except IOError as e:
             write = True
 
@@ -345,7 +361,7 @@ if __name__ == '__main__':
             print(name)
             result = 0
             f = open(name, "w")
-            f.write(file[name].encode("utf-8"))
+            f.write(file[name])
             f.close()
 
     for name in symlink.keys():
diff --git a/src/hostinfo/dhcpd.py b/src/hostinfo/dhcpd.py
index 04385fb9553a4caf7421a3795647ffb431162ee4..81478819ff5a448bd3bf677dc684d0305046232e 100755
--- a/src/hostinfo/dhcpd.py
+++ b/src/hostinfo/dhcpd.py
@@ -150,8 +150,9 @@ class "AppleNBI-ppc" {
     
 def generate(tree, options):
     result = util.StringArray()
-    dhcp = set(filter(lambda d: options.host in d.name[0::1],
-                     tree._host_._interface_._ip_._dhcpserver_))
+    dhcp = set([d for d
+                in tree._host_._interface_._ip_._dhcpserver_
+                if options.host in d.name[0::1]])
     assert dhcp, '%s is not a dhcp server' % options.host
     pxeboot = get_pxeboot(dhcp)
 
@@ -174,25 +175,23 @@ def generate(tree, options):
         pass
     #result += MacOS_NETBOOT(dhcpip)
 
-    interface = set(map(lambda d: d._parent._parent, dhcp))
+    interface = set([d._parent._parent for d in dhcp])
     for i in interface:
         result += emit_interface(tree, options, i)
         pass
-    served_networks = map(lambda d: util.network(get_subnet(tree, d._parent)), 
-                          dhcp)
+    served_networks = [util.network(get_subnet(tree, d._parent)) for d in dhcp]
     result += emit_hosts(tree, options, served_networks,
                          pxeboot=pxeboot)
     return str(result)
 
 def emit_interface(tree, options, interface):
     result = util.StringArray()
-    subnet = dict(map(lambda d: (get_subnet(tree, d._parent), 
-                                 map(None, d._parent._dhcpserver_)),
-                      interface._ip_._dhcpserver_))
+    subnet = dict([ (get_subnet(tree, d._parent), list(d._parent._dhcpserver_))
+                    for d in interface._ip_._dhcpserver_ ])
     for ethernet in util.ethernets(interface.ethernet[0]):
         result += 'shared-network "MAC(%s)" {' % ethernet
-        for sn,dhcp in map(lambda n: (n, subnet[n]),
-                           sorted(subnet, key=lambda s: s.network[0])): 
+        for sn,dhcp in [ (n, subnet[n]) for n
+                         in sorted(subnet, key=lambda s: s.network[0]) ]:
             result += emit_network(tree, options, sn, dhcp).indent()
             pass
         result += "}"
@@ -210,9 +209,9 @@ def emit_network(tree, options, subnet, dhcp):
       |  server-name "%(host)s";
       |  default-lease-time 14400; # 4 hours
       |  max-lease-time 86400; # 1 day
-      """ % dict(network=net.network,
+      """ % dict(network=net.network_address,
                  netmask=net.netmask,
-                 broadcast=net.broadcast,
+                 broadcast=net.broadcast_address,
                  host=options.host))
     for d in dhcp:
         if d.first[0] and d.last[0]:
@@ -259,7 +258,7 @@ def emit_subnet_info(subnet):
 def emit_hosts(tree, options, networks, pxeboot=False):
     result = util.StringArray()
     def match(a):
-        return filter(lambda n: a in n, networks)
+        return [ n for n in networks if a in n ]
     static = {}
     never = {}
     for ip in tree._host_._interface_._ip_:
@@ -287,7 +286,7 @@ def emit_hosts(tree, options, networks, pxeboot=False):
     def by_name(ether_ip_dict):
         result = {}
         for e in ether_ip_dict:
-            name = set(map(lambda n: n.name[0:], ether_ip_dict[e]))
+            name = set([n.name[0:] for n in ether_ip_dict[e]])
             if len(name) != 1:
                 raise util.HostinfoException('Multiple names %s' % name,
                                              where=ether_ip_dict[e])
@@ -317,9 +316,8 @@ def emit_hosts(tree, options, networks, pxeboot=False):
                                 dict(id='%s_%s' % (name, ether.replace(':','')),
                                      name=name,
                                      ethernet=ether,
-                                     address=', '.join(
-                                         map(str,
-                                             map(util.address, ip)))))
+                                     address=', '.join([ str(util.address(i))
+                                                         for i in ip ])))
             if pxeboot != 'no':
                 for i in ip:
                     for p in i._pxeboot_:
@@ -350,13 +348,13 @@ def get_subnet(tree, ip):
     def match(subnet):
         s = util.network(subnet)
         return s and a in s
-    subnet = filter(match, tree._subnet_)
+    subnet = [ s for s in tree._subnet_ if match(s) ]
     assert len(subnet) == 1, '%s matches multiple networks %s' % (a, subnet)
     return subnet[0]
 
 def get_pxeboot(dhcp):
     try:
-        p = set(map(lambda d: d.pxeboot[0] or 'no', dhcp))
+        p = set([ d.pxeboot[0] or 'no' for d in dhcp ])
         if len(p) != 1:
             raise util.HostinfoException("Mixed pxeboot not allowed (%s)" % 
                                          ','.join(p),
diff --git a/src/hostinfo/dhcpd_ipv6.py b/src/hostinfo/dhcpd_ipv6.py
index ad2a5ffb90243faa9c61e4abdab73bb7cd55d614..14a570575d09412e5a36396a2dd5509867f8790b 100755
--- a/src/hostinfo/dhcpd_ipv6.py
+++ b/src/hostinfo/dhcpd_ipv6.py
@@ -1,7 +1,7 @@
 import sys
 import os
 import re
-import ipaddr
+import ipaddress
 import hostinfo.util as util
 
 """
@@ -69,8 +69,9 @@ class "pxeclient" {
 
 def generate(tree, options):
     result = util.StringArray()
-    dhcp = set(filter(lambda d: options.host in d.name[0::1],
-                     tree._host_._interface_._ipv6_._dhcpserver_))
+    dhcp = set([d for d
+                in tree._host_._interface_._ipv6_._dhcpserver_
+                if options.host in d.name[0::1]])
     assert dhcp, '%s is not a dhcp6 server' % options.host
     pxeboot = get_pxeboot(dhcp)
 
@@ -90,12 +91,11 @@ def generate(tree, options):
     # else:
     #     result += PXE_DENY
     #     pass
-    interface = set(map(lambda d: d._parent._parent, dhcp))
+    interface = set([d._parent._parent for d in dhcp])
     for i in interface:
         result += emit_interface(tree, options, i)
         pass
-    served_networks = map(lambda d: util.network(get_subnet(tree, d._parent)), 
-                          dhcp)
+    served_networks = [util.network(get_subnet(tree, d._parent)) for d in dhcp]
     result += emit_hosts(tree, options, served_networks)
 #    if pxeboot == 'no':
 #        result += emit_hosts(tree, options, served_networks)
@@ -103,11 +103,11 @@ def generate(tree, options):
 
 def emit_interface(tree, options, interface):
     result = util.StringArray()
-    subnet = dict(map(lambda d: (get_subnet(tree, d._parent), d),
-                      interface._ipv6_._dhcpserver_))
+    subnet = dict([(get_subnet(tree, d._parent), d) for d
+                   in interface._ipv6_._dhcpserver_])
     for ethernet in util.ethernets(interface.ethernet[0]):
         result += 'shared-network "MAC(%s)" {' % ethernet
-        for sn,dhcp in map(lambda n: (n, subnet[n]), sorted(subnet)): 
+        for sn,dhcp in [(n, subnet[n]) for n in sorted(subnet)]:
             result += emit_network(tree, options, sn, dhcp).indent()
             pass
         result += "}"
@@ -124,8 +124,6 @@ def emit_network(tree, options, subnet, dhcp):
       |  default-lease-time 14400; # 4 hours
       |  max-lease-time 86400; # 1 day
       """ % dict(prefix=str(net),
-                 netmask=net.netmask,
-                 broadcast=net.broadcast,
                  host=options.host))
     if dhcp.first[0] and dhcp.last[0]:
         first = util.address(dhcp.first[0])
@@ -168,7 +166,7 @@ def emit_subnet_info(subnet):
 def emit_hosts(tree, options, networks):
     result = util.StringArray()
     def match(a):
-        return filter(lambda n: a in n, networks)
+        return [n for n in networks if a in n]
     static = {}
     never = {}
     for ip in tree._host_._interface_._ipv6_:
@@ -194,7 +192,7 @@ def emit_hosts(tree, options, networks):
     def by_name(ether_ip_dict):
         result = {}
         for e in ether_ip_dict:
-            name = set(map(lambda n: n.name[0:], ether_ip_dict[e]))
+            name = set([n.name[0:] for n in ether_ip_dict[e]])
             if len(name) != 1:
                 raise util.HostinfoException('Multiple names %s' % name,
                                              where=ether_ip_dict[e])
@@ -223,8 +221,8 @@ def emit_hosts(tree, options, networks):
               |  }""" % dict(id='%s_%s' % (name, ether.replace(':','')),
                              name=name, 
                              ethernet=ether,
-                             address=', '.join(map(str, 
-                                                   map(util.address, ip)))))
+                             address=', '.join([ str(util.address(i))
+                                                 for  i in ip ])))
         result += "}"
         pass
     if never:
@@ -246,13 +244,13 @@ def get_subnet(tree, ip):
     def match(subnet):
         s = util.network(subnet)
         return s and a in s
-    subnet = filter(match, tree._subnet_)
+    subnet = [ s for s in tree._subnet_ if match(s) ]
     assert len(subnet) == 1, '%s matches multiple networks %s' % (a, subnet)
     return subnet[0]
 
 def get_pxeboot(dhcp):
     try:
-        p = set(map(lambda d: d.pxeboot[0] or 'no', dhcp))
+        p = set([d.pxeboot[0] or 'no' for d in dhcp])
         if len(p) != 1:
             raise util.HostinfoException("Mixed pxeboot not allowed (%s)" % 
                                          ','.join(p),
diff --git a/src/hostinfo/ifconfig.py b/src/hostinfo/ifconfig.py
index 993512ceedac09093cdd09fcc8defeaa7366b6cf..1b17804a54c1763deff602a4deb30571077741fe 100755
--- a/src/hostinfo/ifconfig.py
+++ b/src/hostinfo/ifconfig.py
@@ -1,7 +1,7 @@
 import hostinfo.util as util
 import subprocess
 import re
-import ipaddr
+import ipaddress
 import sys
 import uuid
 from functools import reduce
@@ -89,9 +89,9 @@ def generate_ifcfgv4(tree, interface, search, nameservers):
             n = util.network(s)
             if a in n:
                 netmask = n.netmask
-                network = n.network
+                network = n.network_address
                 prefixlen = n.prefixlen
-                broadcast = n.broadcast
+                broadcast = n.broadcast_address
                 gateway = s.gateway[0]
                 if interface_is_static(interface):
                     if s.name_servers[0]:
@@ -219,11 +219,10 @@ def generate_ifcfg(tree, interface):
                          nameservers, [])
     config.extend(indexed_assign('DNS', nameservers[0:10], 1))
     if search:
-        def reverse_order(a, b):
-            a_v = list(reversed(a.split('.')))
-            b_v = list(reversed(b.split('.')))
-            return cmp(a_v, b_v)
-        tmp = sorted(search, cmp=reverse_order)
+        def reverse_order(a):
+            v = list(reversed(a.split('.')))
+            return v
+        tmp = sorted(search, key=reverse_order)
         config.append('SEARCH="%s"' % (' '.join(tmp)))
         config.append('DOMAIN="%s"' % (' '.join(tmp)))
         pass
@@ -285,6 +284,7 @@ def device(ethernet):
     p = subprocess.Popen(['/sbin/ip', '-o', 'link', 'show'], 
                          stdout=subprocess.PIPE)
     for l in p.stdout:
+        l = l.decode('utf-8')
         m = re.match('^[0-9]+:\s+([^:]+):.*link/ether\s+([0-9a-f:]+)\s+.*', l)
         if m:
             if m.group(2) == ethernet:
diff --git a/src/hostinfo/macosx_auto.py b/src/hostinfo/macosx_auto.py
index 40919428b50468d590ede35f51db465c16cc9034..5704f2e803fb579f407194eb40b662c0a265685b 100755
--- a/src/hostinfo/macosx_auto.py
+++ b/src/hostinfo/macosx_auto.py
@@ -16,10 +16,8 @@ def auto_map(tree, map_name):
                 for e in a._entry_:
                     path = '/'.join([a.root[0], e.path[0]])
                     auto[e.key[0]] = "%s:%s" % (h.name[0],path)
-    ak = auto.keys()
-    ak.sort()
     result = ""
-    for k in ak:
+    for k in sorted(auto.keys()):
         result += "%-15s rw,resvport,nosuid %s\n" % (k, auto[k])
     return result
 
diff --git a/src/hostinfo/named.py b/src/hostinfo/named.py
index 428a5c4d5b3916ef15bb85627b67de8b49485617..f4aa4d667806575fce07e9785e4c5ad2d88becec 100755
--- a/src/hostinfo/named.py
+++ b/src/hostinfo/named.py
@@ -1,6 +1,6 @@
 import copy
 import hostinfo.parser
-import ipaddr
+import ipaddress
 import hostinfo.util as util
 import re
 import sys
@@ -46,15 +46,14 @@ def generate(tree, options):
 
     forward = generate_forward(tree, get_hosts(tree))
     reverse = generate_reverse(tree, get_hosts(tree, with_alias=False))
-
-    for f in filter(lambda f: forward[f], sorted(forward)):
+    for f in [ f for f in sorted(forward) if forward[f] ]:
         conf.append_lines("""
           |zone \"%(name)s\" {
           |  type master; file \"hosts-%(name)s\";
           |};""" % dict(name=f))
         result.append(("named/hosts-%s" % f, str(forward[f])))
         pass
-    for r in filter(lambda r: reverse[r], sorted(reverse)):
+    for r in [ r for r in sorted(reverse) if reverse[r] ]:
         conf.append_lines("""
           |zone \"%(name)s\" {
           |  type master; file \"%(name)s\";
@@ -72,9 +71,9 @@ def reverse_addr(addr):
     if addr.version == 4:
         def join(l):
             return '.'.join(reversed(l))+'.in-addr.arpa'
-        if isinstance(addr, ipaddr._BaseNet):
+        if isinstance(addr, ipaddress._BaseNetwork):
             assert addr.prefixlen % 8 == 0
-            n = addr.prefixlen / 8
+            n = int(addr.prefixlen / 8)
             return join(addr.exploded.split('.')[0:n])
         else:
             return join(addr.exploded.split('.'))
@@ -82,14 +81,14 @@ def reverse_addr(addr):
     elif addr.version == 6:
         def join(l):
             return '.'.join(reversed(l))+'.ip6.arpa'
-        if isinstance(addr, ipaddr._BaseNet):
+        if isinstance(addr, ipaddress._BaseNetwork):
             assert addr.prefixlen % 4 == 0
-            n = addr.prefixlen / 4
-            return join(map(None, addr.exploded.replace(':', ''))[0:n])
+            n = int(addr.prefixlen / 4)
+            return join(list(addr.exploded.replace(':', ''))[0:n])
         else:
-            return join(map(None, addr.exploded.replace(':', '')))
+            return join(list(addr.exploded.replace(':', '')))
     else:
-	raise Exception('Unknown address version %s' % addr)
+        raise Exception('Unknown address version %s' % addr)
 
 def header(tree, domain, origin=None):
     soa = None
@@ -105,8 +104,9 @@ def header(tree, domain, origin=None):
     if not soa:
         raise Exception("No SOA defined for %s" % domain)
 
-    if not filter(lambda ns: ns.domain[0] == domain and ns.primary[0] == 'yes',
-                  tree._host_._interface_._nameserver_):
+    if not [ns for ns
+            in tree._host_._interface_._nameserver_
+            if ns.domain[0] == domain and ns.primary[0] == 'yes']:
         raise NoNameserverException("No nameserver defined for %s" % domain)
     result = util.StringArray()
     if origin:
@@ -170,10 +170,10 @@ class DomainDict:
             self.host[name].add((kind, value, ttl))
             pass
 
-        def value(self, cmp=None):
+        def value(self, key=None):
             result = util.StringArray()
             result += self.header
-            for name in sorted(self.host, cmp):
+            for name in sorted(self.host, key=key):
                 for kind,value,ttl in sorted(self.host[name]):
                     result += ('%(name)-18s %(ttl)-8s IN %(kind)-7s %(value)s' % 
                                dict(name=name, ttl=ttl, kind=kind, value=value))
@@ -188,10 +188,10 @@ class DomainDict:
         self.domain = {}
         pass
 
-    def value(self, cmp=None):
+    def value(self, key=None):
         result = {}
         for d in self.domain:
-            result[d] = self.domain[d].value(cmp)
+            result[d] = self.domain[d].value(key)
             pass
         return result
 
@@ -314,11 +314,9 @@ def generate_reverse(tree, hosts):
                 pass
             pass
         pass
-    def by_reverse(a, b):
-        a_v = map(lambda i: int(i,16), reversed(a.split('.')))
-        b_v = map(lambda i: int(i,16), reversed(b.split('.')))
-        return cmp(a_v, b_v)
-    return result.value(cmp=by_reverse)
+    def reverse_key(a):
+        return [ int(i,16) for i in reversed(a.split('.')) ]
+    return result.value(key=reverse_key)
 
 def get_hosts(tree, with_alias=True):
     result = []
@@ -345,8 +343,9 @@ def get_hosts(tree, with_alias=True):
             pass
         pass
     # IPv4 dynamic addresses
-    for d in filter(lambda d: d.first[0] and d.last[0], 
-                    tree._host_._interface_._ip_._dhcpserver_):
+    for d in [ d for d
+               in tree._host_._interface_._ip_._dhcpserver_
+               if d.first[0] and d.last[0] ]:
         last = util.address(d.last[0])
         a = util.address(d.first[0])
         while a <= last:
@@ -366,8 +365,9 @@ def get_hosts(tree, with_alias=True):
             pass
         pass
     # IPv6 dynamic addresses
-    for d in filter(lambda d: d.first[0] and d.last[0], 
-                    tree._host_._interface_._ipv6_._dhcpserver_):
+    for d in [ d for d
+               in tree._host_._interface_._ipv6_._dhcpserver_
+               if d.first[0] and d.last[0] ]:
         last = util.address(d.last[0])
         a = util.address(d.first[0])
         while a <= last:
diff --git a/src/hostinfo/parser.py b/src/hostinfo/parser.py
index 20eb8d999508b5aaf892c8f66e2a07238f71dfbc..daeb5dbd89f5341d9dcdfe63fe79c479dc5cda4b 100755
--- a/src/hostinfo/parser.py
+++ b/src/hostinfo/parser.py
@@ -397,6 +397,9 @@ class Comment:
         self._tag = ''
         self._attribute = { '': content}
 
+    def __lt__(self, other):
+        return self._tag < other._tag
+
     def __copy__(self):
         """Copy self"""
         result = Comment(self._content, self._line)
diff --git a/src/hostinfo/role.py b/src/hostinfo/role.py
index f0e7f0099d1926b88cfa5b85d31366f0a934455b..61bb5d7fcb7c02579715e05c85a9fa2105ca5d15 100755
--- a/src/hostinfo/role.py
+++ b/src/hostinfo/role.py
@@ -6,8 +6,7 @@ def generate(tree, host, roles):
         if not r in by_role:
             raise Exception("Role '%s' not found in %s" %
                             (r, by_role.keys()))
-    return filter(lambda k_v: k_v[0] in roles and k_v[1] == host, 
-                  by_role.iteritems())
+    return [ (k,v) for (k,v) in by_role.items() if k in roles and v == host ]
 
 def holder(tree, role):
     return get_all(tree)[role]
@@ -21,4 +20,4 @@ def get_all(tree):
                                          where=[result[name], r])
         result[name] = r
         pass
-    return dict([ (k,v.name[1]) for k,v in result.iteritems() ])
+    return dict([ (k,v.name[1]) for k,v in result.items() ])
diff --git a/src/hostinfo/util.py b/src/hostinfo/util.py
index 4e3d82e2119866cc6bd66c49af7b9787b37c3699..1b0ab09533cdb3aff324c5f950f7b63bd76f3adb 100755
--- a/src/hostinfo/util.py
+++ b/src/hostinfo/util.py
@@ -1,22 +1,35 @@
-import ipaddr
+import ipaddress
 import itertools
 import types
 import hostinfo.parser
 import re
 
+try:
+    # Python 2
+    from __builtin__ import unicode
+except ModuleNotFoundError:
+    # Python 3
+    from builtins import str as unicode
+
+try:
+    long
+except NameError:
+    # Python 3
+    from builtins import int as long
+
 def network(s):
     if s.network[0] and s.netmask[0]:
-        return ipaddr.IPNetwork('%s/%s' % (s.network[0], s.netmask[0]))
+        return ipaddress.ip_network('%s/%s' % (s.network[0], s.netmask[0]))
     elif s.prefix[0]:
-        return ipaddr.IPNetwork(s.prefix[0])
+        return ipaddress.ip_network(s.prefix[0])
     else:
         return None
 
 def address(ip):
-    if isinstance(ip, (str,)):
-        return ipaddr.IPAddress(ip)
+    if isinstance(ip, (str, unicode)):
+        return ipaddress.ip_address(ip)
     elif ip.address[0]:
-        return ipaddr.IPAddress(ip.address[0])
+        return ipaddress.ip_address(ip.address[0])
     else:
         return None
 
@@ -24,7 +37,7 @@ def subnet(tree, addr):
     def match(subnet):
         net = network(subnet)
         return net and addr in net
-    result = filter(match, tree._subnet_)
+    result = [ s for s in tree._subnet_ if match(s) ]
     if len(result) > 1:
         raise HostinfoException('%s matches multiple networks' % (addr),
                                 where=result)
@@ -75,30 +88,13 @@ def fqn(tree, host):
                         (host.name[0:], host))
     pass
 
-def by_ip(a, b):
-    aa = a.split('.')
-    ba = b.split('.')
-    for i in range(0, len(aa)):
-        if int(aa[i]) < int(ba[i]):
-            return -1
-        elif int(aa[i]) > int(ba[i]):
-            return 1
-    return 0
-
-def by_mac(a, b):
-    aa = a.split(':')
-    ba = b.split(':')
-    for i in range(0, len(aa)):
-        if int(aa[i],16) < int(ba[i],16):
-            return -1
-        elif int(aa[i],16) > int(ba[i],16):
-            return 1
-    return 0
+def mac_key(m):
+    return tuple([ int(e, 16) for e in m.split(':') ])
 
 class StringArray(list, object):
 
     def append_lines(self, lines, sep='|'):
-        for l in map(lambda s: s.strip(), lines.split('\n')):
+        for l in [s.strip() for s in lines.split('\n')]:
             if not l:
                 continue
             if not l.startswith(sep):
diff --git a/src/hostinfo/yp.py b/src/hostinfo/yp.py
index cac7724f1c4c0ca609f242b4383d379e77f94345..932a241225a4c4be60da27d58e767d78ad374a99 100755
--- a/src/hostinfo/yp.py
+++ b/src/hostinfo/yp.py
@@ -1,4 +1,3 @@
-#from hostinfo.util import fqn, aton, ntoa, by_ip, by_mac
 import hostinfo.util as util
 from hostinfo.automount import auto_map
 
@@ -31,7 +30,7 @@ def hosts(tree):
 def ethers(tree):
     result = ""
     host = {}
-    for i in filter(lambda i: i.ethernet[0], tree._host_._interface_):
+    for i in  [ i for i in tree._host_._interface_ if i.ethernet[0] ]:
         for ethernet in util.ethernets(i.ethernet[0]):
             host[ethernet] = set([ i.name[0:] ])
             pass
@@ -52,7 +51,7 @@ def ethers(tree):
                 pass
             pass
         pass
-    for k in sorted(host, cmp=util.by_mac):
+    for k in sorted(host, key=util.mac_key):
         for h in sorted(host[k]):
             result += "%-15s %s\n" % (k, h)
     return result
@@ -68,8 +67,8 @@ def adjust_netgroup(netgroup):
             result[g] = entries
         else:
             # group is bigger than max YP length, split it
-            n = min(length / limit + 1, limit / (len(g) + 5))
-            m = len(entries) / n + 1
+            n = int(min(length / limit + 1, limit / (len(g) + 5)))
+            m = int(len(entries) / n + 1)
             tmp = {}
             tmp[g] = []
             for i in range(n):
@@ -78,7 +77,7 @@ def adjust_netgroup(netgroup):
                 if value:
                     tmp[g].append(key)
                     tmp[key] = value
-            for (k, v) in adjust_netgroup(tmp).iteritems():
+            for (k, v) in adjust_netgroup(tmp).items():
                 result[k] = v
     return result
 
@@ -125,10 +124,7 @@ def netgroup(tree):
         pass
     netgroup = adjust_netgroup(netgroup)
     result = ""
-    keys = netgroup.keys()
-    keys.sort()
-
-    for g in keys:
+    for g in sorted(netgroup.keys()):
         result += "%s" % g
         entries = netgroup[g]
         entries.sort()