jquast / telnetlib3

Python Telnet server and client Protocol library using asyncio

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Am I doing something wrong? (Can't use in GUI application)

ethindp opened this issue · comments

I've got the following Python code but for some reason telnetlib3 is causing asyncio errors (that is, saying that no asyncio runtime is available when there is one). I'm using Toga, which is inherently compatible with asyncio, yet I receive this error:

Exception in callback TelnetClient.connection_made(<_ProactorSoc...sport fd=1900>)
handle: <Handle TelnetClient.connection_made(<_ProactorSoc...sport fd=1900>)>
Traceback (most recent call last):
  File "C:\Users\ethin\AppData\Local\Programs\Python\Python312\Lib\asyncio\events.py", line 84, in _run
    self._context.run(self._callback, *self._args)
  File "C:\Users\ethin\source\venvs\mudclient\Lib\site-packages\telnetlib3\client.py", line 74, in connection_made
    super().connection_made(transport)
  File "C:\Users\ethin\source\venvs\mudclient\Lib\site-packages\telnetlib3\client_base.py", line 137, in connection_made
    self.reader = reader_factory(**reader_kwds)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\ethin\source\venvs\mudclient\Lib\site-packages\telnetlib3\stream_reader.py", line 497, in __init__
    super().__init__(limit=limit)
  File "C:\Users\ethin\source\venvs\mudclient\Lib\site-packages\telnetlib3\stream_reader.py", line 39, in __init__
    self._loop = asyncio.get_event_loop_policy().get_event_loop()
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\ethin\AppData\Local\Programs\Python\Python312\Lib\asyncio\events.py", line 698, in get_event_loop
    raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Dummy-1'.
  File "C:\Users\ethin\source\venvs\mudclient\Lib\site-packages\telnetlib3\client_base.py", line 185, in data_received
    recv_inband = self.writer.feed_byte(bytes([byte]))
                  ^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'feed_byte'
  File "C:\Users\ethin\source\venvs\mudclient\Lib\site-packages\telnetlib3\client_base.py", line 185, in data_received
    recv_inband = self.writer.feed_byte(bytes([byte]))
                  ^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'feed_byte'
# Infinite more AttributeError exceptions

I'm unsure what I'm doing wrong. I set the shell to None, specifically because I handle the shell differently, but other than that I'm unsure what the problem is. The full code follows:

import asyncio
from toga.style import Pack
from toga.style.pack import COLUMN, ROW
import toga
import telnetlib3
from cytolk import tolk

class TelnetApp(toga.App):
    def startup(self):
        self.writer = None
        self.main_window = toga.MainWindow(title=self.formal_name)
        self.command_input = toga.TextInput(placeholder='Enter command here...', on_confirm =self.on_confirm)
        self.session_output = toga.MultilineTextInput(readonly=True, style=Pack(flex=1))
        self.close_button = toga.Button('Close', on_press=self.close_app, style=Pack(padding=5))
        self.command_box = toga.Box(style=Pack(direction=ROW, padding=5), children=[self.command_input])
        self.output_box = toga.Box(style=Pack(direction=COLUMN, padding=5), children=[self.session_output])
        self.button_box = toga.Box(style=Pack(direction=ROW, padding=5), children=[self.close_button])
        self.main_container = toga.Box(
            style=Pack(direction=COLUMN, padding=10),
            children=[self.command_box, self.output_box, self.button_box]
        )
        self.main_window.content = self.main_container
        self.main_window.show()
        self.loop.create_task(self.start_telnet())

    async def start_telnet(self):
        if self.writer is None:
            reader, self.writer = await telnetlib3.open_connection("localhost", 4000, shell=None)
            while True:
                data = await reader.read(1024)
                if not data:
                    break
                if data:
                    self.session_output.value += data
                    tolk.speak(data)

    async def on_confirm(self, event, **kwargs):
        if self.command_input.value:
            command = self.command_input.value.strip()
            await writer.write(command.encode('UTF-8', errors='replace') + b"\r\n")
            self.command_input.value = ""

    def close_app(self, widget, **kwargs):
        tolk.unload()
        self.exit()

def main():
    tolk.load()
    return TelnetApp('Mud Client', 'mudclient')

if __name__ == '__main__':
    main().main_loop()

Do I need to explicitly set the shell to a callback?