Merge pull request #13 from maxking/py3-qt6

Port to using Python3 and Pyside6
This commit is contained in:
Sébastien Helleu 2021-11-13 16:09:33 +01:00 committed by GitHub
commit e139bca02f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 190 additions and 232 deletions

View file

@ -1,7 +1,9 @@
language: python
python:
- "2.7"
- "3.7"
- "3.8"
- "3.9"
install:
- pip install flake8

View file

@ -25,13 +25,13 @@ Following packages are *required*:
* WeeChat (version >= 0.3.7) on local or remote machine, with relay plugin
enabled and listening on a port with protocol "weechat"
* Python 2.x >= 2.6
* PySide (recommended, packages: python.pyside.*) or PyQt4 (python-qt4)
* Python 3.7+
* PySide6
=== Install via source distribution
----
$ python setup.py install
$ pip install .
----
== WeeChat setup

View file

@ -20,10 +20,8 @@
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
#
import qt_compat
QtCore = qt_compat.import_module('QtCore')
QtGui = qt_compat.import_module('QtGui')
from PySide6 import QtCore
from PySide6 import QtWidgets as QtGui
class AboutDialog(QtGui.QDialog):
@ -44,7 +42,7 @@ class AboutDialog(QtGui.QDialog):
vbox = QtGui.QVBoxLayout()
for msg in messages:
label = QtGui.QLabel(msg.decode('utf-8'))
label = QtGui.QLabel(msg)
label.setAlignment(QtCore.Qt.AlignHCenter)
vbox.addWidget(label)
vbox.addLayout(hbox)

View file

@ -19,22 +19,20 @@
# You should have received a copy of the GNU General Public License
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
#
from pkg_resources import resource_filename
import qt_compat
from chat import ChatTextEdit
from input import InputLineEdit
import weechat.color as color
QtCore = qt_compat.import_module('QtCore')
QtGui = qt_compat.import_module('QtGui')
from qweechat.chat import ChatTextEdit
from qweechat.input import InputLineEdit
from qweechat.weechat import color
from PySide6 import QtCore, QtGui, QtWidgets
class GenericListWidget(QtGui.QListWidget):
class GenericListWidget(QtWidgets.QListWidget):
"""Generic QListWidget with dynamic size."""
def __init__(self, *args):
QtGui.QListWidget.__init__(*(self,) + args)
super().__init__(*args)
self.setMaximumWidth(100)
self.setTextElideMode(QtCore.Qt.ElideNone)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
@ -52,17 +50,17 @@ class GenericListWidget(QtGui.QListWidget):
def clear(self, *args):
"""Re-implement clear to set dynamic size after clear."""
QtGui.QListWidget.clear(*(self,) + args)
QtWidgets.QListWidget.clear(*(self,) + args)
self.auto_resize()
def addItem(self, *args):
"""Re-implement addItem to set dynamic size after add."""
QtGui.QListWidget.addItem(*(self,) + args)
QtWidgets.QListWidget.addItem(*(self,) + args)
self.auto_resize()
def insertItem(self, *args):
"""Re-implement insertItem to set dynamic size after insert."""
QtGui.QListWidget.insertItem(*(self,) + args)
QtWidgets.QListWidget.insertItem(*(self,) + args)
self.auto_resize()
@ -70,7 +68,7 @@ class BufferListWidget(GenericListWidget):
"""Widget with list of buffers."""
def __init__(self, *args):
GenericListWidget.__init__(*(self,) + args)
super().__init__(*args)
def switch_prev_buffer(self):
if self.currentRow() > 0:
@ -85,23 +83,23 @@ class BufferListWidget(GenericListWidget):
self.setCurrentRow(0)
class BufferWidget(QtGui.QWidget):
class BufferWidget(QtWidgets.QWidget):
"""
Widget with (from top to bottom):
title, chat + nicklist (optional) + prompt/input.
"""
def __init__(self, display_nicklist=False):
QtGui.QWidget.__init__(self)
super().__init__()
# title
self.title = QtGui.QLineEdit()
self.title = QtWidgets.QLineEdit()
self.title.setFocusPolicy(QtCore.Qt.NoFocus)
# splitter with chat + nicklist
self.chat_nicklist = QtGui.QSplitter()
self.chat_nicklist.setSizePolicy(QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
self.chat_nicklist = QtWidgets.QSplitter()
self.chat_nicklist.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Expanding)
self.chat = ChatTextEdit(debug=False)
self.chat_nicklist.addWidget(self.chat)
self.nicklist = GenericListWidget()
@ -110,16 +108,16 @@ class BufferWidget(QtGui.QWidget):
self.chat_nicklist.addWidget(self.nicklist)
# prompt + input
self.hbox_edit = QtGui.QHBoxLayout()
self.hbox_edit = QtWidgets.QHBoxLayout()
self.hbox_edit.setContentsMargins(0, 0, 0, 0)
self.hbox_edit.setSpacing(0)
self.input = InputLineEdit(self.chat)
self.hbox_edit.addWidget(self.input)
prompt_input = QtGui.QWidget()
prompt_input = QtWidgets.QWidget()
prompt_input.setLayout(self.hbox_edit)
# vbox with title + chat/nicklist + prompt/input
vbox = QtGui.QVBoxLayout()
vbox = QtWidgets.QVBoxLayout()
vbox.setContentsMargins(0, 0, 0, 0)
vbox.setSpacing(0)
vbox.addWidget(self.title)
@ -139,7 +137,7 @@ class BufferWidget(QtGui.QWidget):
if self.hbox_edit.count() > 1:
self.hbox_edit.takeAt(0)
if prompt is not None:
label = QtGui.QLabel(prompt)
label = QtWidgets.QLabel(prompt)
label.setContentsMargins(0, 0, 5, 0)
self.hbox_edit.insertWidget(0, label)
@ -147,7 +145,7 @@ class BufferWidget(QtGui.QWidget):
class Buffer(QtCore.QObject):
"""A WeeChat buffer."""
bufferInput = qt_compat.Signal(str, str)
bufferInput = QtCore.Signal(str, str)
def __init__(self, data={}):
QtCore.QObject.__init__(self)
@ -167,15 +165,17 @@ class Buffer(QtCore.QObject):
"""Update title."""
try:
self.widget.set_title(
color.remove(self.data['title'].decode('utf-8')))
except: # noqa: E722
color.remove(self.data['title']))
except Exception: # noqa: E722
# TODO: Debug print the exception to be fixed.
# traceback.print_exc()
self.widget.set_title(None)
def update_prompt(self):
"""Update prompt."""
try:
self.widget.set_prompt(self.data['local_variables']['nick'])
except: # noqa: E722
except Exception: # noqa: E722
self.widget.set_prompt(None)
def input_text_sent(self, text):
@ -243,6 +243,6 @@ class Buffer(QtCore.QObject):
pixmap = QtGui.QPixmap(8, 8)
pixmap.fill()
icon = QtGui.QIcon(pixmap)
item = QtGui.QListWidgetItem(icon, nick['name'])
item = QtWidgets.QListWidgetItem(icon, nick['name'])
self.widget.nicklist.addItem(item)
self.widget.nicklist.setVisible(True)

View file

@ -21,19 +21,18 @@
#
import datetime
import qt_compat
import config
import weechat.color as color
from qweechat import config
from qweechat.weechat import color
QtCore = qt_compat.import_module('QtCore')
QtGui = qt_compat.import_module('QtGui')
from PySide6 import QtCore
from PySide6 import QtWidgets, QtGui
class ChatTextEdit(QtGui.QTextEdit):
class ChatTextEdit(QtWidgets.QTextEdit):
"""Chat area."""
def __init__(self, debug, *args):
QtGui.QTextEdit.__init__(*(self,) + args)
QtWidgets.QTextEdit.__init__(*(self,) + args)
self.debug = debug
self.readOnly = True
self.setFocusPolicy(QtCore.Qt.NoFocus)
@ -77,9 +76,9 @@ class ChatTextEdit(QtGui.QTextEdit):
prefix = '\x01(F%s)%s' % (forcecolor, prefix)
text = '\x01(F%s)%s' % (forcecolor, text)
if prefix:
self._display_with_colors(str(prefix).decode('utf-8') + ' ')
self._display_with_colors(prefix + ' ')
if text:
self._display_with_colors(str(text).decode('utf-8'))
self._display_with_colors(text)
if text[-1:] != '\n':
self.insertPlainText('\n')
else:

View file

@ -20,7 +20,7 @@
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
#
import ConfigParser
import configparser
import os
CONFIG_DIR = '%s/.qweechat' % os.getenv('HOME')
@ -91,7 +91,7 @@ config_color_options = []
def read():
"""Read config file."""
global config_color_options
config = ConfigParser.RawConfigParser()
config = configparser.RawConfigParser()
if os.path.isfile(CONFIG_FILENAME):
config.read(CONFIG_FILENAME)
@ -123,7 +123,7 @@ def write(config):
"""Write config file."""
if not os.path.exists(CONFIG_DIR):
os.mkdir(CONFIG_DIR, 0o0755)
with open(CONFIG_FILENAME, 'wb') as cfg:
with open(CONFIG_FILENAME, 'w') as cfg:
config.write(cfg)

View file

@ -20,29 +20,27 @@
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
#
import qt_compat
QtGui = qt_compat.import_module('QtGui')
from PySide6 import QtGui, QtWidgets
class ConnectionDialog(QtGui.QDialog):
class ConnectionDialog(QtWidgets.QDialog):
"""Connection window."""
def __init__(self, values, *args):
QtGui.QDialog.__init__(*(self,) + args)
super().__init__(*args)
self.values = values
self.setModal(True)
grid = QtGui.QGridLayout()
grid = QtWidgets.QGridLayout()
grid.setSpacing(10)
self.fields = {}
for line, field in enumerate(('server', 'port', 'password', 'lines')):
grid.addWidget(QtGui.QLabel(field.capitalize()), line, 0)
line_edit = QtGui.QLineEdit()
grid.addWidget(QtWidgets.QLabel(field.capitalize()), line, 0)
line_edit = QtWidgets.QLineEdit()
line_edit.setFixedWidth(200)
if field == 'password':
line_edit.setEchoMode(QtGui.QLineEdit.Password)
line_edit.setEchoMode(QtWidgets.QLineEdit.Password)
if field == 'lines':
validator = QtGui.QIntValidator(0, 2147483647, self)
line_edit.setValidator(validator)
@ -51,14 +49,14 @@ class ConnectionDialog(QtGui.QDialog):
grid.addWidget(line_edit, line, 1)
self.fields[field] = line_edit
if field == 'port':
ssl = QtGui.QCheckBox('SSL')
ssl = QtWidgets.QCheckBox('SSL')
ssl.setChecked(self.values['ssl'] == 'on')
grid.addWidget(ssl, line, 2)
self.fields['ssl'] = ssl
self.dialog_buttons = QtGui.QDialogButtonBox()
self.dialog_buttons = QtWidgets.QDialogButtonBox()
self.dialog_buttons.setStandardButtons(
QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
self.dialog_buttons.rejected.connect(self.close)
grid.addWidget(self.dialog_buttons, 4, 0, 1, 2)

View file

@ -20,25 +20,24 @@
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
#
import qt_compat
from chat import ChatTextEdit
from input import InputLineEdit
from qweechat.chat import ChatTextEdit
from qweechat.input import InputLineEdit
QtGui = qt_compat.import_module('QtGui')
from PySide6 import QtWidgets
class DebugDialog(QtGui.QDialog):
class DebugDialog(QtWidgets.QDialog):
"""Debug dialog."""
def __init__(self, *args):
QtGui.QDialog.__init__(*(self,) + args)
QtWidgets.QDialog.__init__(*(self,) + args)
self.resize(640, 480)
self.setWindowTitle('Debug console')
self.chat = ChatTextEdit(debug=True)
self.input = InputLineEdit(self.chat)
vbox = QtGui.QVBoxLayout()
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(self.chat)
vbox.addWidget(self.input)

View file

@ -20,21 +20,19 @@
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
#
import qt_compat
QtCore = qt_compat.import_module('QtCore')
QtGui = qt_compat.import_module('QtGui')
from PySide6 import QtCore
from PySide6 import QtWidgets
class InputLineEdit(QtGui.QLineEdit):
class InputLineEdit(QtWidgets.QLineEdit):
"""Input line."""
bufferSwitchPrev = qt_compat.Signal()
bufferSwitchNext = qt_compat.Signal()
textSent = qt_compat.Signal(str)
bufferSwitchPrev = QtCore.Signal()
bufferSwitchNext = QtCore.Signal()
textSent = QtCore.Signal(str)
def __init__(self, scroll_widget):
QtGui.QLineEdit.__init__(self)
super().__init__()
self.scroll_widget = scroll_widget
self._history = []
self._history_index = -1
@ -50,7 +48,7 @@ class InputLineEdit(QtGui.QLineEdit):
elif key == QtCore.Qt.Key_PageDown:
self.bufferSwitchNext.emit()
else:
QtGui.QLineEdit.keyPressEvent(self, event)
QtWidgets.QLineEdit.keyPressEvent(self, event)
elif modifiers == QtCore.Qt.AltModifier:
if key in (QtCore.Qt.Key_Left, QtCore.Qt.Key_Up):
self.bufferSwitchPrev.emit()
@ -65,7 +63,7 @@ class InputLineEdit(QtGui.QLineEdit):
elif key == QtCore.Qt.Key_End:
bar.setValue(bar.maximum())
else:
QtGui.QLineEdit.keyPressEvent(self, event)
QtWidgets.QLineEdit.keyPressEvent(self, event)
elif key == QtCore.Qt.Key_PageUp:
bar.setValue(bar.value() - bar.pageStep())
elif key == QtCore.Qt.Key_PageDown:
@ -75,10 +73,10 @@ class InputLineEdit(QtGui.QLineEdit):
elif key == QtCore.Qt.Key_Down:
self._history_navigate(1)
else:
QtGui.QLineEdit.keyPressEvent(self, event)
QtWidgets.QLineEdit.keyPressEvent(self, event)
def _input_return_pressed(self):
self._history.append(self.text().encode('utf-8'))
self._history.append(self.text())
self._history_index = len(self._history)
self.textSent.emit(self.text())
self.clear()

View file

@ -21,11 +21,11 @@
#
import struct
import qt_compat
import config
QtCore = qt_compat.import_module('QtCore')
QtNetwork = qt_compat.import_module('QtNetwork')
from PySide6 import QtCore, QtNetwork
from qweechat import config
_PROTO_INIT_CMD = ['init password=%(password)s']
@ -47,11 +47,11 @@ _PROTO_SYNC_CMDS = [
class Network(QtCore.QObject):
"""I/O with WeeChat/relay."""
statusChanged = qt_compat.Signal(str, str)
messageFromWeechat = qt_compat.Signal(QtCore.QByteArray)
statusChanged = QtCore.Signal(str, str)
messageFromWeechat = QtCore.Signal(QtCore.QByteArray)
def __init__(self, *args):
QtCore.QObject.__init__(*(self,) + args)
super().__init__(*args)
self.status_disconnected = 'disconnected'
self.status_connecting = 'connecting...'
self.status_connected = 'connected'
@ -63,7 +63,7 @@ class Network(QtCore.QObject):
self._buffer = QtCore.QByteArray()
self._socket = QtNetwork.QSslSocket()
self._socket.connected.connect(self._socket_connected)
self._socket.error.connect(self._socket_error)
# self._socket.error.connect(self._socket_error)
self._socket.readyRead.connect(self._socket_read)
self._socket.disconnected.connect(self._socket_disconnected)
@ -87,7 +87,7 @@ class Network(QtCore.QObject):
self._buffer.append(data)
while len(self._buffer) >= 4:
remainder = None
length = struct.unpack('>i', self._buffer[0:4])[0]
length = struct.unpack('>i', self._buffer[0:4].data())[0]
if len(self._buffer) < length:
# partial message, just wait for end of message
break
@ -108,7 +108,7 @@ class Network(QtCore.QObject):
self._server = None
self._port = None
self._ssl = None
self._password = None
self._password = ""
self.statusChanged.emit(self.status_disconnected, None)
def is_connected(self):
@ -136,11 +136,12 @@ class Network(QtCore.QObject):
return
if self._socket.state() != QtNetwork.QAbstractSocket.UnconnectedState:
self._socket.abort()
self._socket.connectToHost(self._server, self._port)
if self._ssl:
self._socket.ignoreSslErrors()
self._socket.startClientEncryption()
self.statusChanged.emit(self.status_connecting, None)
self._socket.connectToHostEncrypted(self._server, self._port)
else:
self._socket.connectToHost(self._server, self._port)
self.statusChanged.emit(self.status_connecting, "")
def disconnect_weechat(self):
"""Disconnect from WeeChat."""

View file

@ -1,55 +0,0 @@
# -*- coding: utf-8 -*-
#
# File downloaded from:
# https://github.com/epage/PythonUtils/blob/master/util/qt_compat.py
# Author: epage
# License: LGPL 2.1
#
from __future__ import with_statement
from __future__ import division
_TRY_PYSIDE = True
uses_pyside = False
try:
if not _TRY_PYSIDE:
raise ImportError()
import PySide.QtCore as _QtCore
QtCore = _QtCore
uses_pyside = True
except ImportError:
import sip
sip.setapi('QString', 2)
sip.setapi('QVariant', 2)
import PyQt4.QtCore as _QtCore
QtCore = _QtCore
uses_pyside = False
def _pyside_import_module(moduleName):
pyside = __import__('PySide', globals(), locals(), [moduleName], -1)
return getattr(pyside, moduleName)
def _pyqt4_import_module(moduleName):
pyside = __import__('PyQt4', globals(), locals(), [moduleName], -1)
return getattr(pyside, moduleName)
if uses_pyside:
import_module = _pyside_import_module
Signal = QtCore.Signal
Slot = QtCore.Slot
Property = QtCore.Property
else:
import_module = _pyqt4_import_module
Signal = QtCore.pyqtSignal
Slot = QtCore.pyqtSlot
Property = QtCore.pyqtProperty
if __name__ == "__main__":
pass

View file

@ -36,18 +36,18 @@ It requires requires WeeChat 0.3.7 or newer, running on local or remote host.
import sys
import traceback
from pkg_resources import resource_filename
import qt_compat
import config
import weechat.protocol as protocol
from network import Network
from connection import ConnectionDialog
from buffer import BufferListWidget, Buffer
from debug import DebugDialog
from about import AboutDialog
from version import qweechat_version
QtCore = qt_compat.import_module('QtCore')
QtGui = qt_compat.import_module('QtGui')
from PySide6 import QtGui, QtWidgets, QtCore
from qweechat import config
from qweechat.weechat import protocol
from qweechat.network import Network
from qweechat.connection import ConnectionDialog
from qweechat.buffer import BufferListWidget, Buffer
from qweechat.debug import DebugDialog
from qweechat.about import AboutDialog
from qweechat.version import qweechat_version
NAME = 'QWeeChat'
AUTHOR = 'Sébastien Helleu'
@ -58,11 +58,11 @@ WEECHAT_SITE = 'https://weechat.org/'
DEBUG_NUM_LINES = 50
class MainWindow(QtGui.QMainWindow):
class MainWindow(QtWidgets.QMainWindow):
"""Main window."""
def __init__(self, *args):
QtGui.QMainWindow.__init__(*(self,) + args)
super().__init__()
self.config = config.read()
@ -87,11 +87,11 @@ class MainWindow(QtGui.QMainWindow):
# default buffer
self.buffers = [Buffer()]
self.stacked_buffers = QtGui.QStackedWidget()
self.stacked_buffers = QtWidgets.QStackedWidget()
self.stacked_buffers.addWidget(self.buffers[0].widget)
# splitter with buffers + chat/input
splitter = QtGui.QSplitter()
splitter = QtWidgets.QSplitter()
splitter.addWidget(self.list_buffers)
splitter.addWidget(self.stacked_buffers)
@ -146,7 +146,7 @@ class MainWindow(QtGui.QMainWindow):
menu_window.addAction(self.actions['debug'])
menu_help = self.menu.addMenu('&Help')
menu_help.addAction(self.actions['about'])
self.network_status = QtGui.QLabel()
self.network_status = QtWidgets.QLabel()
self.network_status.setFixedHeight(20)
self.network_status.setFixedWidth(200)
self.network_status.setContentsMargins(0, 0, 10, 0)
@ -249,8 +249,7 @@ class MainWindow(QtGui.QMainWindow):
'&copy; 2011-2020 %s &lt;<a href="mailto:%s">%s</a>&gt;'
% (AUTHOR, AUTHOR_MAIL, AUTHOR_MAIL),
'',
'Running with %s' % ('PySide' if qt_compat.uses_pyside
else 'PyQt4'),
'Running with PySide6',
'',
'WeeChat site: <a href="%s">%s</a>'
% (WEECHAT_SITE, WEECHAT_SITE),
@ -315,11 +314,11 @@ class MainWindow(QtGui.QMainWindow):
self.debug_display(0, '==>',
'message (%d bytes):\n%s'
% (len(message),
protocol.hex_and_ascii(message, 20)),
protocol.hex_and_ascii(message.data(), 20)),
forcecolor='#008800')
try:
proto = protocol.Protocol()
message = proto.decode(str(message))
message = proto.decode(message.data())
if message.uncompressed:
self.debug_display(
0, '==>',
@ -329,7 +328,7 @@ class MainWindow(QtGui.QMainWindow):
forcecolor='#008800')
self.debug_display(0, '', 'Message: %s' % message)
self.parse_message(message)
except: # noqa: E722
except Exception: # noqa: E722
print('Error while decoding message from WeeChat:\n%s'
% traceback.format_exc())
self.network.disconnect_weechat()
@ -495,6 +494,8 @@ class MainWindow(QtGui.QMainWindow):
self.network.desync_weechat()
elif message.msgid == '_upgrade_ended':
self.network.sync_weechat()
else:
print(f"Unknown message with id {message.msgid}")
def create_buffer(self, item):
"""Create a new buffer."""
@ -509,9 +510,8 @@ class MainWindow(QtGui.QMainWindow):
def insert_buffer(self, index, buf):
"""Insert a buffer in list."""
self.buffers.insert(index, buf)
self.list_buffers.insertItem(index, '%d. %s'
% (buf.data['number'],
buf.data['full_name'].decode('utf-8')))
self.list_buffers.insertItem(index, '%s'
% (buf.data['local_variables']['name']))
self.stacked_buffers.insertWidget(index, buf.widget)
def remove_buffer(self, index):
@ -544,12 +544,18 @@ class MainWindow(QtGui.QMainWindow):
if self.debug_dialog:
self.debug_dialog.close()
config.write(self.config)
QtGui.QMainWindow.closeEvent(self, event)
QtWidgets.QMainWindow.closeEvent(self, event)
app = QtGui.QApplication(sys.argv)
app.setStyle(QtGui.QStyleFactory.create('Cleanlooks'))
app.setWindowIcon(QtGui.QIcon(
def main():
app = QtWidgets.QApplication(sys.argv)
app.setStyle(QtWidgets.QStyleFactory.create('Cleanlooks'))
app.setWindowIcon(QtGui.QIcon(
resource_filename(__name__, 'data/icons/weechat.png')))
main = MainWindow()
sys.exit(app.exec_())
main = MainWindow()
main.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

View file

@ -21,6 +21,7 @@
#
import re
import logging
RE_COLOR_ATTRS = r'[*!/_|]*'
RE_COLOR_STD = r'(?:%s\d{2})' % RE_COLOR_ATTRS
@ -75,6 +76,9 @@ WEECHAT_BASIC_COLORS = (
('white', 0))
log = logging.getLogger(__name__)
class Color():
def __init__(self, color_options, debug=False):
self.color_options = color_options
@ -92,7 +96,7 @@ class Color():
index = int(color)
return '\x01(Fr%s)' % self.color_options[index]
except: # noqa: E722
print('Error decoding WeeChat color "%s"' % color)
log.debug('Error decoding WeeChat color "%s"' % color)
return ''
def _convert_terminal_color(self, fg_bg, attrs, color):
@ -100,7 +104,7 @@ class Color():
index = int(color)
return '\x01(%s%s#%s)' % (fg_bg, attrs, self._rgb_color(index))
except: # noqa: E722
print('Error decoding terminal color "%s"' % color)
log.debug('Error decoding terminal color "%s"' % color)
return ''
def _convert_color_attr(self, fg_bg, color):
@ -123,7 +127,7 @@ class Color():
return self._convert_terminal_color(fg_bg, attrs,
WEECHAT_BASIC_COLORS[index][1])
except: # noqa: E722
print('Error decoding color "%s"' % color)
log.debug('Error decoding color "%s"' % color)
return ''
def _attrcode_to_char(self, code):

View file

@ -34,15 +34,11 @@ import collections
import struct
import zlib
if hasattr(collections, 'OrderedDict'):
# python >= 2.7
class WeechatDict(collections.OrderedDict):
class WeechatDict(collections.OrderedDict):
def __str__(self):
return '{%s}' % ', '.join(
['%s: %s' % (repr(key), repr(self[key])) for key in self])
else:
# python <= 2.6
WeechatDict = dict
class WeechatObject:
@ -151,7 +147,7 @@ class Protocol:
if len(self.data) < 3:
self.data = ''
return ''
objtype = str(self.data[0:3])
objtype = self.data[0:3].decode()
self.data = self.data[3:]
return objtype
@ -196,14 +192,14 @@ class Protocol:
value = self._obj_len_data(1)
if value is None:
return None
return int(str(value))
return int(value)
def _obj_str(self):
"""Read a string in data (length on 4 bytes + content)."""
value = self._obj_len_data(4)
if value is None:
return None
return str(value)
if value in ("", None):
return ""
return value.decode()
def _obj_buffer(self):
"""Read a buffer in data (length on 4 bytes + data)."""
@ -214,14 +210,14 @@ class Protocol:
value = self._obj_len_data(1)
if value is None:
return None
return '0x%s' % str(value)
return '0x%s' % value
def _obj_time(self):
"""Read a time in data (length on 1 byte + value as string)."""
value = self._obj_len_data(1)
if value is None:
return None
return int(str(value))
return int(value)
def _obj_hashtable(self):
"""
@ -314,7 +310,7 @@ class Protocol:
if compression:
uncompressed = zlib.decompress(self.data[5:])
size_uncompressed = len(uncompressed) + 5
uncompressed = '%s%s%s' % (struct.pack('>i', size_uncompressed),
uncompressed = b'%s%s%s' % (struct.pack('>i', size_uncompressed),
struct.pack('b', 0), uncompressed)
self.data = uncompressed
else:
@ -344,13 +340,20 @@ def hex_and_ascii(data, bytes_per_line=10):
for i in range(num_lines):
str_hex = []
str_ascii = []
for char in data[i*bytes_per_line:(i*bytes_per_line)+bytes_per_line]:
for j in range(bytes_per_line):
# We can't easily iterate over individual bytes, so we are going to
# do it this way.
index = (i*bytes_per_line) + j
char = data[index:index+1]
if not char:
char = b'x'
byte = struct.unpack('B', char)[0]
str_hex.append('%02X' % int(byte))
str_hex.append(b'%02X' % int(byte))
if byte >= 32 and byte <= 127:
str_ascii.append(char)
else:
str_ascii.append('.')
fmt = '%%-%ds %%s' % ((bytes_per_line * 3) - 1)
lines.append(fmt % (' '.join(str_hex), ''.join(str_ascii)))
return '\n'.join(lines)
str_ascii.append(b'.')
fmt = b'%%-%ds %%s' % ((bytes_per_line * 3) - 1)
lines.append(fmt % (b' '.join(str_hex),
b''.join(str_ascii)))
return b'\n'.join(lines)

View file

@ -24,8 +24,6 @@
Command-line program for testing WeeChat/relay protocol.
"""
from __future__ import print_function
import argparse
import os
import select
@ -36,8 +34,9 @@ import sys
import time
import traceback
import protocol # WeeChat/relay protocol
from .. version import qweechat_version
from qweechat.weechat import protocol
qweechat_version = '0.1'
NAME = 'qweechat-testproto'
@ -61,12 +60,13 @@ class TestProto(object):
try:
self.sock = socket.socket(inet, socket.SOCK_STREAM)
self.sock.connect((self.args.hostname, self.args.port))
except: # noqa: E722
except Exception:
if self.sock:
self.sock.close()
print('Failed to connect to', self.address)
return False
print('Connected to', self.address)
print(f'Connected to {self.address} socket {self.sock}')
return True
def send(self, messages):
@ -75,11 +75,12 @@ class TestProto(object):
Return True if OK, False if error.
"""
try:
for msg in messages.split('\n'):
if msg == 'quit':
for msg in messages.split(b'\n'):
if msg == b'quit':
self.has_quit = True
self.sock.sendall(msg + '\n')
print('\x1b[33m<-- ' + msg + '\x1b[0m')
self.sock.sendall(msg + b'\n')
sys.stdout.write(
(b'\x1b[33m<-- ' + msg + b'\x1b[0m\n').decode())
except: # noqa: E722
traceback.print_exc()
print('Failed to send message')
@ -94,7 +95,7 @@ class TestProto(object):
try:
proto = protocol.Protocol()
msgd = proto.decode(message,
separator='\n' if self.args.debug > 0
separator=b'\n' if self.args.debug > 0
else ', ')
print('')
if self.args.debug >= 2 and msgd.uncompressed:
@ -122,7 +123,7 @@ class TestProto(object):
data = os.read(sys.stdin.fileno(), 4096)
if data:
if not self.send(data.strip()):
# self.sock.close()
self.sock.close()
return False
# open stdin to read user commands
sys.stdin = open('/dev/tty')
@ -136,10 +137,10 @@ class TestProto(object):
"""
if self.has_quit:
return 0
message = ''
recvbuf = ''
prompt = '\x1b[36mrelay> \x1b[0m'
sys.stdout.write(prompt)
message = b''
recvbuf = b''
prompt = b'\x1b[36mrelay> \x1b[0m'
sys.stdout.write(prompt.decode())
sys.stdout.flush()
try:
while not self.has_quit:
@ -149,13 +150,14 @@ class TestProto(object):
buf = os.read(_file.fileno(), 4096)
if buf:
message += buf
if '\n' in message:
messages = message.split('\n')
msgsent = '\n'.join(messages[:-1])
if b'\n' in message:
messages = message.split(b'\n')
msgsent = b'\n'.join(messages[:-1])
if msgsent and not self.send(msgsent):
return 4
message = messages[-1]
sys.stdout.write(prompt + message)
sys.stdout.write((prompt + message).decode())
# sys.stdout.write(prompt + message)
sys.stdout.flush()
else:
buf = _file.recv(4096)
@ -178,12 +180,12 @@ class TestProto(object):
if remainder:
recvbuf = remainder
else:
recvbuf = ''
sys.stdout.write(prompt + message)
recvbuf = b''
sys.stdout.write((prompt + message).decode())
sys.stdout.flush()
except: # noqa: E722
traceback.print_exc()
self.send('quit')
self.send(b'quit')
return 0
def __del__(self):
@ -220,7 +222,7 @@ The script returns:
help='debug mode: long objects view '
'(-dd: display raw messages)')
parser.add_argument('-v', '--version', action='version',
version=qweechat_version())
version=qweechat_version)
parser.add_argument('hostname',
help='hostname (or IP address) of machine running '
'WeeChat/relay')

View file

@ -54,5 +54,8 @@ setup(
'console_scripts': [
'qweechat-testproto = qweechat.weechat.testproto:main',
]
}
},
install_requires = [
'PySide6',
]
)