Skip to content

Commit da51c05

Browse files
deb
1 parent 4b58c18 commit da51c05

File tree

3 files changed

+28
-39
lines changed

3 files changed

+28
-39
lines changed

moler/io/io_connection.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,14 @@ def send(self, data: str) -> None:
9999
by moler_connection when it needs.
100100
"""
101101

102-
# def receive(self) -> bytes:
103-
# """
104-
# Pull data bytes from external-IO:
105-
# data = io_connection.receive()
106-
# and then forward it to Moler's connection:
107-
# self.moler_connection.data_received(data)
108-
# """
102+
def receive(self) -> bytes:
103+
"""
104+
Pull data bytes from external-IO:
105+
data = io_connection.receive()
106+
and then forward it to Moler's connection:
107+
self.moler_connection.data_received(data)
108+
"""
109+
return b""
109110

110111
def data_received(self, data: str, recv_time: datetime) -> None:
111112
"""

moler/io/raw/terminal_no_forkpty.py

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55

66
import codecs
77
import contextlib
8+
import fcntl
89
import os
910
import re
1011
import select
1112
import datetime
1213
import logging
14+
import pty
1315
import shlex
1416
import subprocess
1517
import threading
@@ -25,16 +27,17 @@
2527
from moler.connection import Connection
2628
from typing import Tuple, List, Optional
2729

30+
# Unix only. Does not work on Windows.
2831

2932
class PtyProcessUnicodeNotFork:
3033
"""PtyProcessUnicode without forking process."""
3134
def __init__(self, cmd: str = "/bin/bash", dimensions: Tuple[int, int] = (25, 120), buffer_size: int = 4096):
32-
self.cmd = cmd
33-
self.dimensions = dimensions
34-
self.buffer_size = buffer_size
35-
self.delayafterclose = 0.2
36-
encoding = "utf-8"
37-
self.decoder = codecs.getincrementaldecoder(encoding)(errors='strict')
35+
self.cmd: str = cmd
36+
self.dimensions: Tuple[int, int] = dimensions
37+
self.buffer_size: int = buffer_size
38+
self.delayafterclose: float = 0.2
39+
self.encoding = "utf-8"
40+
self.decoder = codecs.getincrementaldecoder(self.encoding)(errors='strict')
3841
self.fd: int = -1 # File descriptor for pty master
3942
self.pid: int = -1 # Process ID of the child process
4043
self.slave_fd: int = -1 # File descriptor for pty slave
@@ -43,27 +46,22 @@ def __init__(self, cmd: str = "/bin/bash", dimensions: Tuple[int, int] = (25, 12
4346

4447
def create_pty_process(self):
4548
"""Create PtyProcessUnicode without forking process."""
46-
import pty
47-
import fcntl
4849

4950
# Create a new pty pair
5051
master_fd, slave_fd = pty.openpty()
51-
print(f"Created pty master_fd={master_fd}, slave_fd={slave_fd}")
5252

5353
# Set master fd to non-blocking mode
5454
flags = fcntl.fcntl(master_fd, fcntl.F_GETFL)
5555
fcntl.fcntl(master_fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
5656

5757
# Start the subprocess with the slave fd
58-
process: subprocess.Popen = subprocess.Popen(
58+
process = subprocess.Popen(
5959
shlex.split(self.cmd),
6060
stdin=slave_fd,
6161
stdout=slave_fd,
6262
stderr=slave_fd,
6363
start_new_session=True
6464
)
65-
print(f"Started subprocess with cmd='{self.cmd}'")
66-
print(f"Subprocess PID: {process.pid}")
6765

6866
# Store the process information
6967
self.fd = master_fd
@@ -72,11 +70,6 @@ def create_pty_process(self):
7270
self.process = process
7371
self._closed = False
7472

75-
# Close slave fd in parent process (child process still has it)
76-
# We keep it open initially to prevent early closure
77-
# os.close(slave_fd) # Commented out to keep it open
78-
79-
# Give the shell time to initialize
8073
time.sleep(0.1)
8174

8275
def write(self, data: str):
@@ -87,7 +80,7 @@ def write(self, data: str):
8780
try:
8881
# Convert string to bytes if necessary
8982
if isinstance(data, str):
90-
data_bytes = data.encode('utf-8')
83+
data_bytes = data.encode(self.encoding)
9184
else:
9285
data_bytes = data
9386

@@ -129,10 +122,6 @@ def close(self, force: bool = False) -> None:
129122
"""Close pty process."""
130123
if self._closed:
131124
return
132-
133-
import signal
134-
import subprocess
135-
136125
self._closed = True
137126

138127
# Try to terminate the process gracefully first
@@ -225,7 +214,7 @@ def __init__(
225214
self.dimensions = dimensions
226215
self.first_prompt = first_prompt
227216
self.target_prompt = target_prompt
228-
self._cmd = [cmd]
217+
self._cmd = cmd
229218
self.set_prompt_cmd = set_prompt_cmd
230219
self._re_set_prompt_cmd = re.sub(
231220
"['\"].*['\"]", "", self.set_prompt_cmd.strip()
@@ -238,10 +227,8 @@ def open(self) -> contextlib.closing:
238227

239228
if not self._terminal:
240229
self.moler_connection.open()
241-
# self._terminal = PtyProcessUnicode.spawn(
242-
# self._cmd, dimensions=self.dimensions
243-
# )
244-
self._terminal = PtyProcessUnicodeNotFork()
230+
self._terminal = PtyProcessUnicodeNotFork(cmd=self._cmd, dimensions=self.dimensions,
231+
buffer_size=self._read_buffer_size)
245232
assert self._terminal is not None
246233
self._terminal.create_pty_process()
247234
self._terminal.delayafterclose = self._terminal_delayafterclose

test/crt/test_unix_no_forkpty.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
__copyright__ = 'Copyright (C) 2026, Nokia'
55
__email__ = 'marcin.usielski@nokia.com'
66

7+
import time
78
import pytest
89
import tempfile
910
import os
@@ -178,14 +179,16 @@ def test_cp_md5sum_cat_mv_rm_ls(unix_terminal):
178179
assert dst_file not in ret['files']
179180

180181

181-
def test_ls_from_two_terminals(unix_terminal, unix_terminal2):
182+
def test_ping_from_two_terminals(unix_terminal, unix_terminal2):
182183
unix1 = unix_terminal
183184
unix2 = unix_terminal2
184185

185-
cmd_ping_1 = unix1.get_cmd(cmd_name="ping", cmd_params={'options': f"-c 2", 'destination': '127.0.0.1'})
186-
cmd_ping_2 = unix2.get_cmd(cmd_name="ping", cmd_params={'options': f"-c 3", 'destination': 'localhost'})
186+
cmd_ping_1 = unix1.get_cmd(cmd_name="ping", cmd_params={'options': f"-c 2 -i 0.2", 'destination': '127.0.0.1'})
187+
cmd_ping_2 = unix2.get_cmd(cmd_name="ping", cmd_params={'options': f"-c 3 -i 0.1", 'destination': 'localhost'})
187188
cmd_ping_1.start()
188189
cmd_ping_2.start()
190+
assert cmd_ping_1.running()
191+
assert cmd_ping_2.running()
189192
ret1 = cmd_ping_1.await_done(timeout=10)
190193
ret2 =cmd_ping_2.await_done(timeout=10)
191194
assert 'packets_transmitted' in ret1
@@ -194,8 +197,6 @@ def test_ls_from_two_terminals(unix_terminal, unix_terminal2):
194197
assert ret2['packets_transmitted'] == 3
195198

196199

197-
198-
199200
@pytest.fixture
200201
def unix_terminal():
201202
unix = UnixLocal(io_type='terminal_no_forkpty', variant='threaded')

0 commit comments

Comments
 (0)