diff --git a/CHANGES b/CHANGES.rst
similarity index 94%
rename from CHANGES
rename to CHANGES.rst
index 9dbf373..8a907d2 100644
--- a/CHANGES
+++ b/CHANGES.rst
@@ -8,6 +8,18 @@ For the full changelog refer to the
`Git version history `_.
+HATop 0.8
+=========
+
+HATop is now compatible with Python 3.
+
+
+HATop 0.8.0
+-----------
+
+*Not released yet.*
+
+
HATop 0.7
=========
diff --git a/INSTALL b/INSTALL.rst
similarity index 100%
rename from INSTALL
rename to INSTALL.rst
diff --git a/README b/README.rst
similarity index 100%
rename from README
rename to README.rst
diff --git a/bin/hatop b/bin/hatop
index d50c766..afa5ac4 100755
--- a/bin/hatop
+++ b/bin/hatop
@@ -153,7 +153,7 @@ L7STS layer 7 response error, for example HTTP 5xx
__author__ = 'John Feuerstein '
__copyright__ = 'Copyright (C) 2011 %s' % __author__
__license__ = 'GNU GPLv3'
-__version__ = '0.7.7'
+__version__ = '0.8.0'
import fcntl
import os
@@ -376,7 +376,7 @@ class Socket:
data = self._socket.recv(HAPROXY_CLI_BUFSIZE)
if not data:
raise SocketError('error while waiting for prompt')
- return data
+ return data.decode()
def connect(self):
# Initialize socket connection
@@ -390,16 +390,16 @@ class Socket:
# Enter the interactive socket mode. This requires HAProxy 1.4+ and
# allows us to error out early if connected to an older version.
try:
- self.send('prompt')
+ self.send(b'prompt')
self.wait()
- self.send('set timeout cli %d' % HAPROXY_CLI_TIMEOUT)
+ self.send(b'set timeout cli %d' % HAPROXY_CLI_TIMEOUT)
self.wait()
except SocketError:
raise SocketError('error while initializing interactive mode')
def close(self):
try:
- self.send('quit')
+ self.send(b'quit')
except:
pass
try:
@@ -408,7 +408,7 @@ class Socket:
pass
def send(self, cmdline):
- self._socket.sendall('%s\n' % cmdline)
+ self._socket.sendall(b'%s\n' % cmdline)
def wait(self):
# Wait for the prompt and discard data.
@@ -471,7 +471,7 @@ class SocketData:
raise ValueError('invalid proxy filter: %s' % filter)
# Convert proxy filters into more efficient stat filters
- self.socket.send('show stat')
+ self.socket.send(b'show stat')
pxstat, pxcount, svcount = parse_stat(self.socket.recv())
proxy_iid_map = {} # {pxname: iid, ...}
@@ -490,11 +490,11 @@ class SocketData:
raise RuntimeError('proxy not found: %s' % pxname)
# Register filters
- for iid in proxy_iid_map.itervalues():
+ for iid in proxy_iid_map.values():
self._filters.add((iid, -1, -1))
def update_info(self):
- self.socket.send('show info')
+ self.socket.send(b'show info')
iterable = self.socket.recv()
self.info = parse_info(iterable)
@@ -511,7 +511,7 @@ class SocketData:
if self._filters:
for filter in self._filters:
- self.socket.send('show stat %d %d %d' % filter)
+ self.socket.send(b'show stat %d %d %d' % filter)
filter_stat, filter_pxcount, filter_svcount = \
parse_stat(self.socket.recv())
@@ -522,7 +522,7 @@ class SocketData:
self.svcount += filter_svcount
self.stat.update(filter_stat)
else:
- self.socket.send('show stat')
+ self.socket.send(b'show stat')
self.stat, self.pxcount, self.svcount = \
parse_stat(self.socket.recv())
@@ -692,7 +692,7 @@ class ScreenCLI:
self.ibuf = list(self.ihist[-1])
self.mvend()
- def next(self):
+ def __next__(self):
if len(self.ihist) == 0:
return
self.ihist.rotate(-1)
@@ -830,7 +830,7 @@ class ScreenCLI:
def execute_cmdline(self, cmdline):
self.obuf.append('* %s' % time.ctime())
self.obuf.append('> %s' % cmdline)
- self.screen.data.socket.send(cmdline)
+ self.screen.data.socket.send(cmdline.encode())
self.obuf.extend(self.screen.data.socket.recv())
self.update_screenlines()
@@ -1063,7 +1063,7 @@ class Screen:
self.data.update_info()
try:
self.data.update_stat()
- except RuntimeWarning, x:
+ except RuntimeWarning as x:
self.exceptions.append(x)
def update_bars(self):
@@ -1414,19 +1414,19 @@ class StatusBar:
# ------------------------------------------------------------------------- #
def human_seconds(numeric):
- for minval, prefix in sorted(PREFIX_TIME.items(), reverse=True):
+ for minval, prefix in sorted(list(PREFIX_TIME.items()), reverse=True):
if (numeric/minval):
return '%d%s' % (numeric/minval, prefix)
return '%ds' % numeric
def human_metric(numeric):
- for minval, prefix in sorted(PREFIX_METRIC.items(), reverse=True):
+ for minval, prefix in sorted(list(PREFIX_METRIC.items()), reverse=True):
if (numeric/minval):
return '%d%s' % (numeric/minval, prefix)
return str(numeric)
def human_binary(numeric):
- for minval, prefix in sorted(PREFIX_BINARY.items(), reverse=True):
+ for minval, prefix in sorted(list(PREFIX_BINARY.items()), reverse=True):
if (numeric/minval):
return '%.2f%s' % (float(numeric)/float(minval), prefix)
return '%dB' % numeric
@@ -1659,20 +1659,20 @@ def parse_info(iterable):
line = line.strip()
if not line:
continue
- for key, regexp in HAPROXY_INFO_RE.iteritems():
+ for key, regexp in HAPROXY_INFO_RE.items():
match = regexp.match(line)
if match:
info[key] = match.group('value')
break
- for key in HAPROXY_INFO_RE.iterkeys():
+ for key in HAPROXY_INFO_RE.keys():
if not key in info:
raise RuntimeError('missing "%s" in info data' % key)
return info
def get_idx(field):
- return filter(lambda x: x[1][1] == field, HAPROXY_STAT_CSV)[0][0]
+ return [x for x in HAPROXY_STAT_CSV if x[1][1] == field][0][0]
def get_width(width, xmax, ncols, idx):
# distribute excess space evenly from left to right
@@ -1684,7 +1684,7 @@ def get_width(width, xmax, ncols, idx):
else:
if idx < (xdiff - (xdiff / ncols) * ncols):
width += 1 # compensate rounding
- width = width + xdiff / ncols
+ width = width + xdiff // ncols
return width
def get_cell(width, align, value):
@@ -1708,7 +1708,7 @@ def get_head(mode):
def get_screenlines(stat):
screenlines = []
- for iid, svstats in stat.iteritems():
+ for iid, svstats in stat.items():
lines = []
try:
@@ -1750,11 +1750,11 @@ def get_screenline(mode, stat):
value = stat[column.name]
for filter in column.filters['always']:
- value = filter(value)
+ value = list(filter(value))
if len(str(value)) > column.width:
for filter in column.filters['ondemand']:
- value = filter(value)
+ value = list(filter(value))
value = str(value)
value = trim(value, column.width)
@@ -2075,7 +2075,7 @@ def mainloop(screen, interval):
elif c == curses.KEY_UP:
screen.cli.prev()
elif c == curses.KEY_DOWN:
- screen.cli.next()
+ next(screen.cli)
# output history
elif c == curses.KEY_PPAGE:
@@ -2188,21 +2188,21 @@ if __name__ == '__main__':
break
except KeyboardInterrupt:
break
- except CursesError, e:
+ except CursesError as e:
screen.reset()
log('curses error: %s, restarting...' % e)
time.sleep(1)
screen.recover()
- except ValueError, e:
+ except ValueError as e:
screen.reset()
log('value error: %s' % e)
sys.exit(1)
- except RuntimeError, e:
+ except RuntimeError as e:
screen.reset()
log('runtime error: %s' % e)
sys.exit(1)
- except SocketError, e:
+ except SocketError as e:
screen.reset()
log('socket error: %s' % e)
sys.exit(2)
diff --git a/doc/changes.rst b/doc/changes.rst
index 55c8837..a26d8aa 100644
--- a/doc/changes.rst
+++ b/doc/changes.rst
@@ -1,4 +1,4 @@
.. _changes:
-.. include:: ../CHANGES
+.. include:: ../CHANGES.rst
diff --git a/doc/install.rst b/doc/install.rst
index a343f45..6d8fbec 100644
--- a/doc/install.rst
+++ b/doc/install.rst
@@ -1,4 +1,4 @@
.. _install:
-.. include:: ../INSTALL
+.. include:: ../INSTALL.rst
diff --git a/doc/readme.rst b/doc/readme.rst
index e4ab278..7800c98 100644
--- a/doc/readme.rst
+++ b/doc/readme.rst
@@ -1,4 +1,4 @@
.. _readme:
-.. include:: ../README
+.. include:: ../README.rst