mirror of
https://github.com/clearml/wexpect-venv
synced 2025-06-26 18:15:52 +00:00
[MRG] #10 merged to test
This commit is contained in:
commit
3484a98cdc
13
README.md
13
README.md
@ -41,6 +41,19 @@ child.sendline('exit')
|
|||||||
|
|
||||||
For more information see [examples](./examples) folder.
|
For more information see [examples](./examples) folder.
|
||||||
|
|
||||||
|
## Code Clean up!
|
||||||
|
|
||||||
|
Wexpect works only on Windows platforms. There are handy tools for other platforms. Therefore I will
|
||||||
|
remove any non-windows code. If you see following warning in your console please contact me to
|
||||||
|
prevent the removal of that function.
|
||||||
|
|
||||||
|
```
|
||||||
|
################################## WARNING ##################################
|
||||||
|
<some func> is deprecated, and will be removed soon.
|
||||||
|
Please contact me and report it at github.com/raczben/wexpect if you use it.
|
||||||
|
################################## WARNING ##################################
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
## What is it?
|
## What is it?
|
||||||
|
|
||||||
|
20
appveyor.yml
20
appveyor.yml
@ -11,7 +11,6 @@ environment:
|
|||||||
testpypipw:
|
testpypipw:
|
||||||
secure: CcyBI8e/2LdIT2aYIytTAgR4795DNBDM/ztsz1kqZYYOeNc3zlJWLdYWrnjCHn5W6/ZcAHrsxCdCMHvtr6PIVgBRpl2RR3fk2jKTzKqJJsLW871q30BsE0kws32f1IiqfjVtLn8BUC91IJ2xBBXtOYktf1tCMi3zJMSF9+MIOQKIu298bIRnD1Lc+4lzcSZJOn4I7dOMdzlcCMRqhtO58TGwR/hD+22FHjyWVB8nLL18AO+XXS9lHSOUrH6rD5NYvVFZD68oV/RrCGAjRmfMnw==
|
secure: CcyBI8e/2LdIT2aYIytTAgR4795DNBDM/ztsz1kqZYYOeNc3zlJWLdYWrnjCHn5W6/ZcAHrsxCdCMHvtr6PIVgBRpl2RR3fk2jKTzKqJJsLW871q30BsE0kws32f1IiqfjVtLn8BUC91IJ2xBBXtOYktf1tCMi3zJMSF9+MIOQKIu298bIRnD1Lc+4lzcSZJOn4I7dOMdzlcCMRqhtO58TGwR/hD+22FHjyWVB8nLL18AO+XXS9lHSOUrH6rD5NYvVFZD68oV/RrCGAjRmfMnw==
|
||||||
|
|
||||||
|
|
||||||
build: off
|
build: off
|
||||||
|
|
||||||
install:
|
install:
|
||||||
@ -39,9 +38,18 @@ after_test:
|
|||||||
# Create source distribution.
|
# Create source distribution.
|
||||||
- python -m setup sdist
|
- python -m setup sdist
|
||||||
|
|
||||||
# Upload to test pypi
|
# Upload to pypi.
|
||||||
- twine upload -r testpypi dist\\wexpect*.tar.gz
|
# More precisely. The master and release builds will be uploaded to pypi. Test branch will be
|
||||||
|
# uploaded to test-pypi the test builds.
|
||||||
|
# See more at https://stackoverflow.com/a/39155147/2506522
|
||||||
|
|
||||||
# Upload to offitial pypi
|
- IF %APPVEYOR_REPO_BRANCH%==master (
|
||||||
- twine upload -r pypi dist\\wexpect*.tar.gz
|
twine upload -r pypi dist\\wexpect*.tar.gz
|
||||||
|
)
|
||||||
|
- IF %APPVEYOR_REPO_TAG%==true (
|
||||||
|
twine upload -r pypi dist\\wexpect*.tar.gz
|
||||||
|
)
|
||||||
|
- IF %APPVEYOR_REPO_BRANCH%==test (
|
||||||
|
twine upload -r testpypi dist\\wexpect*.tar.gz
|
||||||
|
)
|
||||||
|
|
4
codecov.yml
Normal file
4
codecov.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# Settings for https://codecov.io/gh/raczben/wexpect/
|
||||||
|
|
||||||
|
ignore:
|
||||||
|
- tests/* # ignore folders and all its contents
|
@ -1,36 +0,0 @@
|
|||||||
# A simple example code for wexpect
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
here = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
wexpectPath = os.path.dirname(here)
|
|
||||||
#sys.path.insert(0, wexpectPath)
|
|
||||||
|
|
||||||
import wexpect
|
|
||||||
|
|
||||||
# Path of cmd executable:
|
|
||||||
cmdPathes = ['C:\Windows\System32\cmd.exe', 'cmd.exe', 'cmd']
|
|
||||||
cmdPrompt = '>'
|
|
||||||
|
|
||||||
for cmdPath in cmdPathes:
|
|
||||||
# Start the child process
|
|
||||||
p = wexpect.spawn(cmdPath)
|
|
||||||
|
|
||||||
# Wait for prompt
|
|
||||||
p.expect(cmdPrompt)
|
|
||||||
|
|
||||||
# print the texts
|
|
||||||
print(p.before, end='')
|
|
||||||
print(p.match.group(0), end='')
|
|
||||||
|
|
||||||
# Send a command
|
|
||||||
p.sendline('ls')
|
|
||||||
p.expect(cmdPrompt)
|
|
||||||
|
|
||||||
# print the texts
|
|
||||||
print(p.before, end='')
|
|
||||||
print(p.match.group(0), end='')
|
|
||||||
|
|
15
tests/lines_printer.py
Normal file
15
tests/lines_printer.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
'''
|
||||||
|
This is is a very basic stdio handler script. This is used by python.py example.
|
||||||
|
'''
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
# Read an integer from the user:
|
||||||
|
print('Give a small integer: ', end='')
|
||||||
|
num = input()
|
||||||
|
|
||||||
|
# Wait the given time
|
||||||
|
for i in range(int(num)):
|
||||||
|
print('waiter ' + str(i))
|
||||||
|
time.sleep(0.2)
|
||||||
|
print('Bye!')
|
@ -33,6 +33,10 @@ class TestCaseConstructor(PexpectTestCase.PexpectTestCase):
|
|||||||
p2 = wexpect.spawn('uname', ['-m', '-n', '-p', '-r', '-s', '-v'])
|
p2 = wexpect.spawn('uname', ['-m', '-n', '-p', '-r', '-s', '-v'])
|
||||||
p2.expect(wexpect.EOF)
|
p2.expect(wexpect.EOF)
|
||||||
self.assertEqual(p1.before, p2.before)
|
self.assertEqual(p1.before, p2.before)
|
||||||
|
self.assertEqual(str(p1).splitlines()[1:9], str(p2).splitlines()[1:9])
|
||||||
|
|
||||||
|
run_result = wexpect.run('uname -m -n -p -r -s -v')
|
||||||
|
self.assertEqual(run_result, p2.before)
|
||||||
|
|
||||||
def test_named_parameters (self):
|
def test_named_parameters (self):
|
||||||
'''This tests that named parameters work.
|
'''This tests that named parameters work.
|
||||||
|
83
tests/test_readline.py
Normal file
83
tests/test_readline.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
'''
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2008 Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett, Robert Stone,
|
||||||
|
Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids vander Molen, George Todd,
|
||||||
|
Noel Taylor, Nicolas D. Cesar, Alexander Gattin, Geoffrey Marshall, Francisco Lourenco, Glen Mabey,
|
||||||
|
Karthik Gurusamy, Fernando Perez, Corey Minyard, Jon Cohen, Guillaume Chazarain, Andrew Ryan,
|
||||||
|
Nick Craig-Wood, Andrew Stone, Jorgen Grahn, Benedek Racz
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
'''
|
||||||
|
import wexpect
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
from . import PexpectTestCase
|
||||||
|
|
||||||
|
here = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
sys.path.insert(0, here)
|
||||||
|
|
||||||
|
print(wexpect.__version__)
|
||||||
|
|
||||||
|
# With quotes (C:\Program Files\Python37\python.exe needs quotes)
|
||||||
|
python_executable = '"' + sys.executable + '" '
|
||||||
|
child_script = here + '\\lines_printer.py'
|
||||||
|
|
||||||
|
class ReadLineTestCase(PexpectTestCase.PexpectTestCase):
|
||||||
|
def testReadline(self):
|
||||||
|
fooPath = python_executable + ' ' + child_script
|
||||||
|
prompt = ': '
|
||||||
|
num = 5
|
||||||
|
|
||||||
|
# Start the child process
|
||||||
|
p = wexpect.spawn(fooPath)
|
||||||
|
# Wait for prompt
|
||||||
|
p.expect(prompt)
|
||||||
|
p.sendline(str(num))
|
||||||
|
p.expect('Bye!\r\n')
|
||||||
|
expected_lines = p.before.splitlines(True) # Keep the line end
|
||||||
|
expected_lines += [p.match.group()]
|
||||||
|
|
||||||
|
# Start the child process
|
||||||
|
p = wexpect.spawn(fooPath)
|
||||||
|
# Wait for prompt
|
||||||
|
p.expect(prompt)
|
||||||
|
|
||||||
|
p.sendline(str(num))
|
||||||
|
for i in range(num +2): # +1 the line of sendline +1: Bye
|
||||||
|
line = p.readline()
|
||||||
|
self.assertEqual(expected_lines[i], line)
|
||||||
|
|
||||||
|
# Start the child process
|
||||||
|
p = wexpect.spawn(fooPath)
|
||||||
|
# Wait for prompt
|
||||||
|
p.expect(prompt)
|
||||||
|
|
||||||
|
p.sendline(str(num))
|
||||||
|
readlines_lines = p.readlines()
|
||||||
|
self.assertEqual(expected_lines, readlines_lines)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|
||||||
|
suite = unittest.makeSuite(ReadLineTestCase,'test')
|
78
wexpect.py
78
wexpect.py
@ -75,6 +75,7 @@ Pexpect is intended for UNIX-like operating systems.""")
|
|||||||
#
|
#
|
||||||
# Import built in modules
|
# Import built in modules
|
||||||
#
|
#
|
||||||
|
import warnings
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
@ -110,6 +111,13 @@ except ImportError as e:
|
|||||||
screenbufferfillchar = '\4'
|
screenbufferfillchar = '\4'
|
||||||
maxconsoleY = 8000
|
maxconsoleY = 8000
|
||||||
|
|
||||||
|
warnings.simplefilter("always", category=DeprecationWarning)
|
||||||
|
no_unix_deprecation_warning = '''
|
||||||
|
################################## WARNING ##################################
|
||||||
|
{} is deprecated, and will be removed soon.
|
||||||
|
Please contact me and report it at github.com/raczben/wexpect if you use it.
|
||||||
|
################################## WARNING ##################################
|
||||||
|
'''
|
||||||
|
|
||||||
# The version is handled by the package: pbr, which derives the version from the git tags.
|
# The version is handled by the package: pbr, which derives the version from the git tags.
|
||||||
try:
|
try:
|
||||||
@ -534,8 +542,10 @@ class spawn_unix (object):
|
|||||||
s.append('delayafterterminate: ' + str(self.delayafterterminate))
|
s.append('delayafterterminate: ' + str(self.delayafterterminate))
|
||||||
return '\n'.join(s)
|
return '\n'.join(s)
|
||||||
|
|
||||||
def _spawn(self,command,args=[]):
|
|
||||||
|
|
||||||
|
def _spawn(self,command,args=[]): # pragma: no cover
|
||||||
|
warnings.warn(no_unix_deprecation_warning.format("spawn_unix::_spawn"), DeprecationWarning)
|
||||||
|
|
||||||
"""This starts the given command in a child process. This does all the
|
"""This starts the given command in a child process. This does all the
|
||||||
fork/exec type of stuff for a pty. This is called by __init__. If args
|
fork/exec type of stuff for a pty. This is called by __init__. If args
|
||||||
is empty then command will be parsed (split on spaces) and args will be
|
is empty then command will be parsed (split on spaces) and args will be
|
||||||
@ -622,7 +632,9 @@ class spawn_unix (object):
|
|||||||
self.terminated = False
|
self.terminated = False
|
||||||
self.closed = False
|
self.closed = False
|
||||||
|
|
||||||
def __fork_pty(self):
|
def __fork_pty(self): # pragma: no cover
|
||||||
|
warnings.warn(no_unix_deprecation_warning.format("spawn_unix::__fork_pty"), DeprecationWarning)
|
||||||
|
|
||||||
|
|
||||||
"""This implements a substitute for the forkpty system call. This
|
"""This implements a substitute for the forkpty system call. This
|
||||||
should be more portable than the pty.fork() function. Specifically,
|
should be more portable than the pty.fork() function. Specifically,
|
||||||
@ -661,7 +673,8 @@ class spawn_unix (object):
|
|||||||
|
|
||||||
return pid, parent_fd
|
return pid, parent_fd
|
||||||
|
|
||||||
def __pty_make_controlling_tty(self, tty_fd):
|
def __pty_make_controlling_tty(self, tty_fd): # pragma: no cover
|
||||||
|
warnings.warn(no_unix_deprecation_warning.format("spawn_unix::__pty_make_controlling_tty"), DeprecationWarning)
|
||||||
|
|
||||||
"""This makes the pseudo-terminal the controlling tty. This should be
|
"""This makes the pseudo-terminal the controlling tty. This should be
|
||||||
more portable than the pty.fork() function. Specifically, this should
|
more portable than the pty.fork() function. Specifically, this should
|
||||||
@ -726,8 +739,9 @@ class spawn_unix (object):
|
|||||||
self.closed = True
|
self.closed = True
|
||||||
#self.pid = None
|
#self.pid = None
|
||||||
|
|
||||||
def flush (self): # File-like object.
|
def flush (self): # pragma: no cover # File-like object.
|
||||||
|
|
||||||
|
warnings.warn(no_unix_deprecation_warning.format("spawn_unix::flush"), DeprecationWarning)
|
||||||
"""This does nothing. It is here to support the interface for a
|
"""This does nothing. It is here to support the interface for a
|
||||||
File-like object. """
|
File-like object. """
|
||||||
|
|
||||||
@ -824,7 +838,8 @@ class spawn_unix (object):
|
|||||||
# and blocked on some platforms. TCSADRAIN is probably ideal if it worked.
|
# and blocked on some platforms. TCSADRAIN is probably ideal if it worked.
|
||||||
termios.tcsetattr(self.child_fd, termios.TCSANOW, attr)
|
termios.tcsetattr(self.child_fd, termios.TCSANOW, attr)
|
||||||
|
|
||||||
def read_nonblocking (self, size = 1, timeout = -1):
|
def read_nonblocking (self, size = 1, timeout = -1): # pragma: no cover
|
||||||
|
warnings.warn(no_unix_deprecation_warning.format("spawn_unix::read_nonblocking"), DeprecationWarning)
|
||||||
|
|
||||||
"""This reads at most size characters from the child application. It
|
"""This reads at most size characters from the child application. It
|
||||||
includes a timeout. If the read does not complete within the timeout
|
includes a timeout. If the read does not complete within the timeout
|
||||||
@ -995,7 +1010,9 @@ class spawn_unix (object):
|
|||||||
for s in sequence:
|
for s in sequence:
|
||||||
self.write (s)
|
self.write (s)
|
||||||
|
|
||||||
def send(self, s):
|
def send(self, s): # pragma: no cover
|
||||||
|
warnings.warn(no_unix_deprecation_warning.format("spawn_unix::send"), DeprecationWarning)
|
||||||
|
|
||||||
|
|
||||||
"""This sends a string to the child process. This returns the number of
|
"""This sends a string to the child process. This returns the number of
|
||||||
bytes written. If a log file was set then the data is also written to
|
bytes written. If a log file was set then the data is also written to
|
||||||
@ -1167,7 +1184,8 @@ class spawn_unix (object):
|
|||||||
raise ExceptionPexpect ('Wait was called for a child process that is stopped. This is not supported. Is some other process attempting job control with our child pid?')
|
raise ExceptionPexpect ('Wait was called for a child process that is stopped. This is not supported. Is some other process attempting job control with our child pid?')
|
||||||
return self.exitstatus
|
return self.exitstatus
|
||||||
|
|
||||||
def isalive(self):
|
def isalive(self): # pragma: no cover
|
||||||
|
warnings.warn(no_unix_deprecation_warning.format("spawn_unix::isalive"), DeprecationWarning)
|
||||||
|
|
||||||
"""This tests if the child process is running or not. This is
|
"""This tests if the child process is running or not. This is
|
||||||
non-blocking. If the child was terminated then this will read the
|
non-blocking. If the child was terminated then this will read the
|
||||||
@ -1505,7 +1523,8 @@ class spawn_unix (object):
|
|||||||
s = struct.pack('HHHH', r, c, 0, 0)
|
s = struct.pack('HHHH', r, c, 0, 0)
|
||||||
fcntl.ioctl(self.fileno(), TIOCSWINSZ, s)
|
fcntl.ioctl(self.fileno(), TIOCSWINSZ, s)
|
||||||
|
|
||||||
def interact(self, escape_character = chr(29), input_filter = None, output_filter = None):
|
def interact(self, escape_character = chr(29), input_filter = None, output_filter = None): # pragma: no cover
|
||||||
|
warnings.warn(no_unix_deprecation_warning.format("spawn_unix::interact"), DeprecationWarning)
|
||||||
|
|
||||||
"""This gives control of the child process to the interactive user (the
|
"""This gives control of the child process to the interactive user (the
|
||||||
human at the keyboard). Keystrokes are sent to the child process, and
|
human at the keyboard). Keystrokes are sent to the child process, and
|
||||||
@ -2045,22 +2064,22 @@ class Wtty:
|
|||||||
win32console.AttachConsole(self.conpid)
|
win32console.AttachConsole(self.conpid)
|
||||||
self.__consin = win32console.GetStdHandle(win32console.STD_INPUT_HANDLE)
|
self.__consin = win32console.GetStdHandle(win32console.STD_INPUT_HANDLE)
|
||||||
self.__consout = self.getConsoleOut()
|
self.__consout = self.getConsoleOut()
|
||||||
except Exception as e:
|
|
||||||
#e = traceback.format_exc()
|
except pywintypes.error as e:
|
||||||
try:
|
# pywintypes.error: (5, 'AttachConsole', 'Access is denied.')
|
||||||
win32console.AttachConsole(self.__parentPid)
|
# When child has finished...
|
||||||
except Exception as ex:
|
logging.info(e)
|
||||||
pass
|
# In case of any error: We "switch back" (attach) our original console, then raise the
|
||||||
#log(e)
|
# error.
|
||||||
#log(ex)
|
self.switchBack()
|
||||||
return
|
raise EOF('End Of File (EOF) in switchTo().')
|
||||||
#self.__consin = None
|
except:
|
||||||
#self.__consout = None
|
# In case of any error: We "switch back" (attach) our original console, then raise the
|
||||||
#raise e
|
# error.
|
||||||
|
self.switchBack()
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def switchBack(self):
|
def switchBack(self):
|
||||||
"""Releases from the current console and attaches
|
"""Releases from the current console and attaches
|
||||||
to the parents."""
|
to the parents."""
|
||||||
@ -2157,7 +2176,6 @@ class Wtty:
|
|||||||
def readConsole(self, startCo, endCo):
|
def readConsole(self, startCo, endCo):
|
||||||
"""Reads the console area from startCo to endCo and returns it
|
"""Reads the console area from startCo to endCo and returns it
|
||||||
as a string."""
|
as a string."""
|
||||||
logger.info("STARTED")
|
|
||||||
|
|
||||||
buff = []
|
buff = []
|
||||||
self.lastRead = 0
|
self.lastRead = 0
|
||||||
@ -2170,20 +2188,15 @@ class Wtty:
|
|||||||
if readlen <= 0:
|
if readlen <= 0:
|
||||||
break
|
break
|
||||||
|
|
||||||
logger.info("startOff: %d endOff: %d readlen: %d", startOff, endOff, readlen)
|
|
||||||
|
|
||||||
if readlen > 4000:
|
if readlen > 4000:
|
||||||
readlen = 4000
|
readlen = 4000
|
||||||
endPoint = self.getCoord(startOff + readlen)
|
endPoint = self.getCoord(startOff + readlen)
|
||||||
logger.info("endPoint {}".format(endPoint))
|
|
||||||
|
|
||||||
s = self.__consout.ReadConsoleOutputCharacter(readlen, startCo)
|
s = self.__consout.ReadConsoleOutputCharacter(readlen, startCo)
|
||||||
logger.info("len {}".format(len(s)))
|
|
||||||
self.lastRead += len(s)
|
self.lastRead += len(s)
|
||||||
self.totalRead += len(s)
|
self.totalRead += len(s)
|
||||||
buff.append(s)
|
buff.append(s)
|
||||||
logger.info(s.replace(screenbufferfillchar, '*'))
|
|
||||||
|
|
||||||
startCo = endPoint
|
startCo = endPoint
|
||||||
|
|
||||||
return ''.join(buff)
|
return ''.join(buff)
|
||||||
@ -2210,7 +2223,6 @@ class Wtty:
|
|||||||
position and inserts the string into self.__buffer."""
|
position and inserts the string into self.__buffer."""
|
||||||
|
|
||||||
if not self.__consout:
|
if not self.__consout:
|
||||||
logger.info('self.__consout is False')
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
consinfo = self.__consout.GetConsoleScreenBufferInfo()
|
consinfo = self.__consout.GetConsoleScreenBufferInfo()
|
||||||
@ -2241,7 +2253,7 @@ class Wtty:
|
|||||||
raw = raw[self.__consSize[0]:]
|
raw = raw[self.__consSize[0]:]
|
||||||
raw = ''.join(rawlist)
|
raw = ''.join(rawlist)
|
||||||
s = self.parseData(raw)
|
s = self.parseData(raw)
|
||||||
logger.info(s)
|
logger.debug(s)
|
||||||
for i, line in enumerate(reversed(rawlist)):
|
for i, line in enumerate(reversed(rawlist)):
|
||||||
if line.endswith(screenbufferfillchar):
|
if line.endswith(screenbufferfillchar):
|
||||||
# Record the Y offset where the most recent line break was detected
|
# Record the Y offset where the most recent line break was detected
|
||||||
|
Loading…
Reference in New Issue
Block a user