Reputation: 44325
As telnetlib
seems to get deprecated in future python version I am trying to use telnetlib3
instead (using python 3.10.11, windows 10). I want this to use as a fixture for user-friendly py.test
tests. So for that I define a class for the telnet3
as follows:
import telnetlib3
import asyncio
class Telnet3:
def __init__(self, host, port):
self.host = host
self.port = port
# await telnet3.connect() # ???
# asyncio.run(await self.connect()) # ???
async def connect(self):
self.reader, self.writer = await telnetlib3.open_connection(self.host, self.port)
async def write_read(self, command):
self.writer.write(command)
data = await asyncio.wait_for(self.reader.read(4096), timeout=2)
return data
And I create a fixture in conftest.py
as follows:
from xxx import Telnet3
@pytest.fixture
def telnet3_session(config):
telnet3 = Telnet3(config["HOST"], config["PORT"])
# await telnet3.connect() # ???
return telnet3
And then use it in a test case
def test_telnet(telnet3_session):
telnet3_session.write_read("$SYS,INFO")
here I get the error
RuntimeWarning: coroutine 'Telnet3.write_read' was never awaited
and with
def test_telnet(telnet3_session):
await telnet3_session.write_read("$SYS,INFO")
I get the error
SyntaxError: 'await' outside async function
I run the test case as
python -m pytest -s path/to/case.py
So how to handle this case in a way that a non-expert in asyncio
(like me) can easily understand and maintain the test case? Maybe there is an alternative to telnetlib3
?
Upvotes: 0
Views: 194
Reputation: 44325
In order to use telnetlib3
as part of py.test
fixtures you first need to install pytest-asyncio
:
python -m pip install pytest-asyncio
Then your Telnet module looks like
import telnetlib3
import asyncio
class Telnet3:
def __init__(self, host, port):
"""Initialize the class with the host and port."""
self.host = host
self.port = port
async def connect(self):
"""Defines the connect coroutine and returns the telnet welcome message."""
self.reader, self.writer = await telnetlib3.open_connection(self.host, self.port)
return await asyncio.wait_for(self.reader.read(4096), timeout=2)
def write(self, command):
"""Writes a command to the telnet connection."""
self.writer.write(command + "\r\n")
async def read(self, expected="prompt >>"):
"""Read telnet data until expected command prompt appears."""
reply = ""
while True:
data = await self.reader.read(4096)
if data:
reply += data
if expected in reply:
break
return reply
async def write_read(self, command, timeout=2):
"""Write to telnet and wait for a response"""
self.write(command)
try:
return await asyncio.wait_for(self.read(), timeout=timeout)
except asyncio.exceptions.TimeoutError as e:
print("TimeoutError while reading from telnet!")
return None
Then in conftest.py
you create the fixture e.g. as follows:
import pytest_asyncio
@pytest_asyncio.fixture()
async def telnet3_session(config):
telnet3 = Telnet3(config["HOST"], config["PORT"])
reply = await telnet3.connect()
yield telnet3
And then finally in the test you can use it as follows
@pytest.mark.asyncio
async def test_telnet(telnet3_session):
reply = await telnet3_session.write_read("YOUR_COMMAND")
print(reply)
and then it might work! Not sure if this is the most efficient/simple way to implement it, but it seems to work.
Upvotes: 0