Browse Source

term: new set(), register_cleanup() methods

The MMGen Project 2 years ago
parent
commit
c73409ac27
4 changed files with 104 additions and 12 deletions
  1. 32 6
      mmgen/term.py
  2. 1 5
      test/misc/term.py
  3. 34 0
      test/misc/term_ni.py
  4. 37 1
      test/test_py_d/ts_misc.py

+ 32 - 6
mmgen/term.py

@@ -41,10 +41,25 @@ _term_dimensions = namedtuple('terminal_dimensions',['width','height'])
 
 class MMGenTerm(object):
 
+	@classmethod
+	def register_cleanup(cls):
+		if g.platform == 'linux' and not hasattr(cls,'cleanup_registered'):
+			import atexit
+			atexit.register(
+				lambda: termios.tcsetattr(
+					cls.stdin_fd,
+					termios.TCSADRAIN,
+					cls.orig_term) )
+			cls.cleanup_registered = True
+
 	@classmethod
 	def init(cls,noecho=False):
 		pass
 
+	@classmethod
+	def set(cls,*args,**kwargs):
+		pass
+
 	@classmethod
 	def reset(cls):
 		pass
@@ -60,16 +75,23 @@ class MMGenTermLinux(MMGenTerm):
 		termios.tcsetattr( cls.stdin_fd, termios.TCSANOW, cls.orig_term )
 		cls.cur_term = cls.orig_term
 
+	@classmethod
+	def set(cls,setting):
+		d = {
+			'echo':   lambda t: t[:3] + [t[3] |  (termios.ECHO | termios.ECHONL)] + t[4:], # echo input chars
+			'noecho': lambda t: t[:3] + [t[3] & ~(termios.ECHO | termios.ECHONL)] + t[4:], # don’t echo input chars
+		}
+		termios.tcsetattr( cls.stdin_fd, termios.TCSANOW, d[setting](cls.cur_term) )
+		cls.cur_term = termios.tcgetattr(cls.stdin_fd)
+
 	@classmethod
 	def init(cls,noecho=False):
 		cls.stdin_fd = sys.stdin.fileno()
-		if not hasattr(cls,'orig_term'):
-			cls.orig_term = termios.tcgetattr(cls.stdin_fd)
-		if noecho: # don’t echo input characters
-			t = termios.tcgetattr(cls.stdin_fd)
-			t[3] &= ~(termios.ECHO | termios.ECHONL)
-			termios.tcsetattr( cls.stdin_fd, termios.TCSANOW, t )
 		cls.cur_term = termios.tcgetattr(cls.stdin_fd)
+		if not hasattr(cls,'orig_term'):
+			cls.orig_term = cls.cur_term
+		if noecho:
+			cls.set('noecho')
 
 	@classmethod
 	def get_terminal_size(cls):
@@ -137,6 +159,10 @@ class MMGenTermLinuxStub(MMGenTermLinux):
 	def init(cls,noecho=False):
 		cls.stdin_fd = sys.stdin.fileno()
 
+	@classmethod
+	def set(cls,*args,**kwargs):
+		pass
+
 	@classmethod
 	def reset(cls):
 		pass

+ 1 - 5
test/misc/term.py

@@ -137,11 +137,7 @@ def tt_txview():
 		if not keypress_confirm('Continue testing transaction view?',default_yes=True):
 			break
 
-if g.platform == 'linux':
-	import termios,atexit
-	fd = sys.stdin.fileno()
-	old = termios.tcgetattr(fd)
-	atexit.register(lambda: termios.tcsetattr(fd,termios.TCSADRAIN,old))
+term_mod.register_cleanup()
 
 tt_start()
 

+ 34 - 0
test/misc/term_ni.py

@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+
+import sys,os
+os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(os.path.dirname(sys.argv[0])))))
+sys.path[0] = os.curdir
+
+from mmgen.common import *
+
+cmd_args = opts.init()
+
+from mmgen.term import get_term,get_char_raw
+term = get_term()
+
+if cmd_args[0] == 'echo':
+
+	from mmgen.ui import line_input
+
+	term.init(noecho=True)
+	line_input('noecho> ')
+	get_char_raw()
+
+	term.set('echo')
+	line_input('echo> ')
+
+	term.set('noecho')
+	line_input('noecho> ')
+	get_char_raw()
+
+elif cmd_args[0] == 'cleanup':
+
+	term.register_cleanup()
+
+	import tty
+	tty.setcbreak(term.stdin_fd)

+ 37 - 1
test/test_py_d/ts_misc.py

@@ -27,13 +27,15 @@ from .ts_base import *
 from .ts_main import TestSuiteMain
 
 class TestSuiteMisc(TestSuiteBase):
-	'miscellaneous tests (RPC backends)'
+	'miscellaneous tests (RPC backends, xmrwallet_txview, term)'
 	networks = ('btc',)
 	tmpdir_nums = [99]
 	passthru_opts = ('daemon_data_dir','rpc_port')
 	cmd_group = (
 		('rpc_backends',     'RPC backends'),
 		('xmrwallet_txview', "'mmgen-xmrwallet' txview"),
+		('term_echo',        "term.set('echo')"),
+		('term_cleanup',     'term.register_cleanup()'),
 	)
 	need_daemon = True
 	color = True
@@ -54,6 +56,40 @@ class TestSuiteMisc(TestSuiteBase):
 			assert s in res, s
 		return t
 
+	def term_echo(self):
+
+		def test_echo():
+			t.expect('echo> ','foo\n')
+			t.expect('foo')
+
+		def test_noecho():
+			t.expect('noecho> ','foo\n')
+			import pexpect
+			try:
+				t.expect('foo')
+			except pexpect.TIMEOUT:
+				imsg('[input not echoed - OK]')
+			t.send('x')
+
+		if self.skip_for_win():
+			return 'skip'
+
+		t = self.spawn('test/misc/term_ni.py',['echo'],cmd_dir='.',pexpect_spawn=True,timeout=1)
+		t.p.logfile = None
+		t.p.logfile_read = sys.stdout if opt.verbose or opt.exact_output else None
+		t.p.logfile_send = None
+
+		test_noecho()
+		test_echo()
+		test_noecho()
+
+		return t
+
+	def term_cleanup(self):
+		if self.skip_for_win():
+			return 'skip'
+		return self.spawn('test/misc/term_ni.py',['cleanup'],cmd_dir='.',pexpect_spawn=True)
+
 class TestSuiteHelp(TestSuiteBase):
 	'help, info and usage screens'
 	networks = ('btc','ltc','bch','eth','xmr')