Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/.gitignore b/.gitignore
- index e2a7f94..b576114 100644
- --- a/.gitignore
- +++ b/.gitignore
- @@ -1,3 +1,2 @@
- **/__pycache__/**
- __pycache__/**
- -*.pyc
- \ No newline at end of file
- diff --git a/.gitmodules b/.gitmodules
- deleted file mode 100644
- index 45125a4..0000000
- --- a/.gitmodules
- +++ /dev/null
- @@ -1,3 +0,0 @@
- -[submodule "colorama"]
- - path = colorama
- - url = https://github.com/tartley/colorama
- diff --git a/Makefile b/Makefile
- deleted file mode 100644
- index 8f04b8b..0000000
- --- a/Makefile
- +++ /dev/null
- @@ -1,7 +0,0 @@
- -test:
- - python3 test/tests.py
- -.PHONY: test
- -
- -clean:
- - rm -rf *.pyc */*.pyc __pycache__/* */__pycache__/*
- -.PHONY: clean
- diff --git a/README.md b/README.md
- index a9c2c64..17acf17 100644
- --- a/README.md
- +++ b/README.md
- @@ -1 +1,41 @@
- -# PMLR: poor man's (pure python) libreadline
- \ No newline at end of file
- +# input_constrain
- +
- +#### simple little module for getting very specific user inputs.
- +
- +---
- +
- +## module overview
- +
- +* `read_single_keypress() -> string` — cross-platform function that gets exactly one keypress
- +
- +* `thismany(count: int = -1) -> string` — get exactly `count` characters from stdin. if count is `-1`, then `sys.maxsize` chars will be read.
- +
- +* `until(chars: string || list, count: int = -1) -> string` — get characters from stdin until `char` is read, or until `count` chars have been read. if `count` is `-1`, `sys.maxsize` chars will be read.
- +
- +* `until_not(chars: string || list, count: int = -1) -> string` — get characters from stdin until any of `chars` is not read. if `count` is `-1`, then `sys.maxsize` chars will be read.
- +
- +* `pretty_press() -> string` — read a byte from stdin, and send it through the same processing as the other functions do — write it, if it's a backspace, then backspace, etc
- +
- +## other parts of the module
- +
- +* class `_Getch`: determines system platform and calls one of `_GetchUnix` or `_GetchWindows` appropriately
- +
- +* class `_GetchUnix`: get a raw character from stdin, on any *nx box
- +
- +* class `_GetchWindows`: get a raw character from stdin, on any Windows box
- +
- +* function `nbsp`: do stuff accordingly for certain chars of input; handles backspace, etc
- +
- +* function `parsenum`: return a number, or `sys.maxsize` if number is `-1`
- +
- +## examples overview
- +
- +* `_until_demo() -> None` — small demo of `until()`
- +
- +* `_thismany_demo() -> None` — small demo of `thismany()`
- +
- +* `_can_you_vote() -> None` — small demo of `until_not_multi()`
- +
- +* `_forth_syntax_test() -> None` — small practical demo of `until()`
- +
- +Thanks to [Dannno](http://codereview.stackexchange.com/users/47529/dannnno) and [his post](http://codereview.stackexchange.com/a/118726/87163) for making this module cool.
- \ No newline at end of file
- diff --git a/__init__.py b/__init__.py
- new file mode 100644
- index 0000000..e69de29
- diff --git a/colorama b/colorama
- deleted file mode 160000
- index 1244a00..0000000
- --- a/colorama
- +++ /dev/null
- @@ -1 +0,0 @@
- -Subproject commit 1244a00ae1accfeca3b4b1a85a3b718a920dd6bd
- diff --git a/examples.py b/examples.py
- new file mode 100755
- index 0000000..5ad3a0e
- --- /dev/null
- +++ b/examples.py
- @@ -0,0 +1,64 @@
- +#!/usr/bin/env python3
- +
- +import sys
- +import input_constrain
- +
- +def _until_demo() -> None:
- + """demonstrate the until function"""
- + print("get until what?")
- + char = input_constrain._read_keypress()
- + input_constrain._writer(char + "\n")
- + y = input_constrain.until(char)
- + print("\n" + y)
- +
- +
- +def _thismany_demo() -> None:
- + """demonstrate the thismany function"""
- + print("get how many chars?")
- + kps = input()
- + try:
- + kps = int(kps)
- + except ValueError:
- + print("not a number, sorry")
- + return
- + print("getting", str(kps))
- + y = input_constrain.thismany(kps)
- + print("\n" + y)
- +
- +
- +def _can_you_vote() -> None:
- + """a practical example:
- + test if a user can vote based purely on keypresses"""
- + input_constrain._writer("can you vote? age : ")
- + x = int("0" + until_not("0123456789"))
- + if not x:
- + print("\nsorry, age can only consist of digits.")
- + return
- + print(
- + "your age is", x, "\nYou can vote!"
- + if x >= 18
- + else "Sorry! you can't vote"
- + )
- +
- +
- +def _forth_syntax_test() -> None:
- + """
- + in the programming language Forth,
- + `function` definitons start at the beginning of a line with a `:` colon
- + and go until the next semicolon.
- +
- + this is an example of how this module can be used
- + in a Forth REPL to compile statements specially;
- + it's implemented in catb0t/microcat as well.
- + """
- + input_constrain._writer("demo FORTH repl \n> ")
- + firstchar = input_constrain._read_keypress()
- + input_constrain._writer(firstchar)
- + if firstchar != ":":
- + return print("first char wasn't ':'")
- + defn = firstchar + input_constrain.until(";") + ";"
- + input_constrain._writer("\nrepl got:\n" + defn + "\n")
- +
- +
- +if __name__ == "__main__":
- + _forth_syntax_test()
- diff --git a/examples/examples.py b/examples/examples.py
- deleted file mode 100755
- index c899f9e..0000000
- --- a/examples/examples.py
- +++ /dev/null
- @@ -1,81 +0,0 @@
- -#!/usr/bin/env python3
- -
- -import sys
- -import string
- -import pmlr
- -
- -
- -def _until_demo():
- - """
- - demonstrate the until function
- - """
- -
- - print("get until what?")
- - char = pmlr._read_keypress()
- - pmlr._writer(char + "\n")
- - y = pmlr.until(char)
- - print("\n" + y)
- -
- -
- -def _thismany_demo():
- - """
- - demonstrate the thismany function
- - """
- -
- - print("get how many chars?")
- - kps = input()
- - try:
- - kps = int(kps)
- - except ValueError:
- - print("not a number, sorry")
- - return
- - print("getting", str(kps))
- - y = pmlr.thismany(kps)
- - print("\n" + y)
- -
- -
- -def _can_you_vote():
- - """
- - a practical example:
- - test if a user can vote based purely on keypresses
- - """
- -
- - pmlr._writer("can you vote? age : ")
- - x = int("0" + pmlr.ignore_not("0123456789", "0123456789", end_cond=True, count=2))
- - if not x:
- - print("\nsorry, age can only consist of digits.")
- - return
- - print(
- - "\nyour age is", x, "\nYou can vote!"
- - if x >= 18
- - else "Sorry! you can't vote"
- - )
- -
- -
- -def _forth_syntax_test():
- - """
- - in the programming language Forth,
- - `function` definitons start at the beginning of a line with a `:` colon
- - and go until the next semicolon.
- -
- - this is an example of how this module can be used
- - in a Forth REPL to compile statements specially;
- - it's implemented in catb0t/microcat as well.
- - """
- -
- - pmlr._writer("demo FORTH repl \n> ")
- - firstchar = pmlr._read_keypress()
- - pmlr._writer(firstchar)
- - if firstchar != ":":
- - print("\nreturned because first char wasn't ':'")
- - return
- - defn = firstchar + pmlr.until(";") + ";"
- - pmlr._writer("\nrepl got:\n" + defn + "\n")
- -
- -
- -def _get_paragraphs():
- - from string import printable as ALLOWED_CHARS
- - print("\nPress CTRL-C or CTRL-D to stop reading.")
- - textwriterCommand = pmlr.until_not(ALLOWED_CHARS, count=500, raw=True)
- - pmlr._writer("\n\n")
- - return pmlr._writer("you typed:" + textwriterCommand)
- diff --git a/input_constrain.py b/input_constrain.py
- new file mode 100755
- index 0000000..7dcb18c
- --- /dev/null
- +++ b/input_constrain.py
- @@ -0,0 +1,113 @@
- +#!/usr/bin/env python3
- +
- +import sys
- +from platform import system
- +
- +if system == "Windows":
- + import msvcrt
- +
- + def _Getch():
- + return msvcrt.getch()
- +
- +else:
- + import tty, termios
- +
- + def _Getch():
- + fd = sys.stdin.fileno()
- + old_settings = termios.tcgetattr(fd)
- + try:
- + tty.setraw(sys.stdin.fileno())
- + ch = sys.stdin.read(1)
- + finally:
- + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
- + return ch
- +
- +
- +def parsenum(num):
- + return sys.maxsize if 0 > num else num
- +
- +CHAR_INT = chr(3)
- +CHAR_EOF = chr(4)
- +CHAR_BKS = chr(8)
- +CHAR_ESC = chr(27)
- +CHAR_SPC = chr(32)
- +CHAR_DEL = chr(127)
- +
- +
- +def _read_keypress():
- + """interface for _Getch that interprets backspace and DEL properly"""
- + c = _Getch()
- +
- + if c in (CHAR_BKS, CHAR_DEL, CHAR_ESC):
- + sys.stdout.write(CHAR_BKS)
- + sys.stdout.write(CHAR_SPC) # hacky? indeed. does it *work*? hell yeah!
- + sys.stdout.write(CHAR_BKS)
- +
- + elif c == CHAR_INT: raise KeyboardInterrupt
- + elif c == CHAR_EOF: raise EOFError
- +
- + return c
- +
- +
- +def _nbsp(x, y):
- + """append x to y as long as x is not DEL or backspace"""
- + if x in (CHAR_DEL, CHAR_BKS):
- + try:
- + y.pop()
- + except IndexError:
- + pass
- + return y
- + y.append(x)
- + return y
- +
- +
- +def _writer(i):
- + sys.stdout.write(i)
- + sys.stdout.flush()
- +
- +
- +def pretty_press() -> str:
- + """literally just read any fancy char from stdin let caller do whatever"""
- + i = _read_keypress()
- + _writer(i)
- + return _nbsp(i, y)
- +
- +
- +def thismany(count=-1) -> str:
- + """get exactly count chars of stdin"""
- + y = []
- + count = parsenum(count)
- + while len(y) <= count:
- + i = _read_keypress()
- + _writer(i)
- + y = _nbsp(i, y)
- + return "".join(y)
- +
- +
- +def _until_condition(chars, condition, count) -> str:
- + y = []
- + while len(y) <= count:
- + i = _read_keypress()
- + _writer(i)
- + if condition(i, chars):
- + break
- + y = _nbsp(i, y)
- + return "".join(y)
- +
- +
- +def until(chars, count=-1) -> str:
- + """get chars of stdin until any of chars is read,
- + or until count chars have been read, whichever comes first"""
- +
- + return _until_condition(
- + chars, lambda i, chars: i in chars, parsenum(count)
- + )
- +
- +
- +def until_not(chars, count=-1) -> str:
- + """read stdin until any of chars stop being read,
- + or until count chars have been read; whichever comes first"""
- +
- + return _until_condition(
- + chars, lambda i, chars: i not in chars, parsenum(count)
- + )
- diff --git a/pmlr/__init__.py b/pmlr/__init__.py
- deleted file mode 100755
- index 7ec47e6..0000000
- --- a/pmlr/__init__.py
- +++ /dev/null
- @@ -1,341 +0,0 @@
- -#!/usr/bin/env python3
- -
- -import sys
- -import struct
- -from platform import system
- -SYSTEM = system().lower()
- -DEBUG = True
- -
- -class CHAR:
- - """essentially an enum, to avoid clouding the ns"""
- - NUL = chr(0)
- - INT = chr(3)
- - EOF = chr(4)
- - BEL = chr(7)
- - BKS = chr(8)
- - LFD = chr(10)
- - CRR = chr(13)
- - ESC = chr(27)
- - SPC = chr(32)
- - DEL = chr(127)
- -
- - CONDS = [
- - (lambda i, chars: i in chars),
- - (lambda i, chars: i not in chars),
- - (lambda *args, **kwargs: False),
- - ]
- -
- -
- -def init(TERM_BUFSIZE=4096):
- - """module initialiser: calls constructors so you don't have to
- - you must call this before other functions!"""
- - global reader
- - reader = read_class(TERMCTL_SPECIAL_BUFSIZE=TERM_BUFSIZE)
- -
- -
- -def checkinit(func, *args, **kwargs):
- -
- - def isdefined(*args, **kwargs):
- -
- - if "reader" not in globals().keys():
- - print("\n\tfatal: init() not called\n")
- - msg = "must call init() first, or call init() again before {}()".format(func.__name__)
- - raise TypeError(msg)
- -
- - return func(*args, **kwargs)
- -
- - return isdefined
- -
- -
- -class _nt_reader():
- -
- - def __init__(self, *args, **kwargs):
- - """reader on nt"""
- -
- - self.NAME = "NT"
- -
- - if SYSTEM != "windows":
- - util.writer("\n\there be dragons; ye COWER in the SHADOW of", self.NAME, "\n\n")
- -
- - self.msvcrt = __import__("msvcrt")
- - self.ctypes = __import__("ctypes")
- - try:
- - self.colorama = __import__("colorama")
- - self.colorama.init()
- - except (AttributeError, ImportError):
- - print(
- - """
- - you must install colorama to use this module on windows
- - do this by:
- - $ cd colorama
- - $ python setup.py install
- - """
- - )
- - exit(2)
- -
- -
- - def getch(self):
- - """use msvcrt to get a char"""
- - return self.msvcrt.getch()
- -
- - def drain_buf(self):
- - """while buffer, pseudo-nonblocking read bytes from buffer using msvcrt"""
- - y = []
- - while self.msvcrt.kbhit():
- - y.append(self.msvcrt.getch())
- - return "".join(y)
- -
- -
- -class _posix_reader():
- -
- - def __init__(self, TERMCTL_SPECIAL_BUFSIZE=4096):
- - """reader on posix"""
- -
- - self.NAME = "POSIX"
- -
- - if SYSTEM == "windows":
- - util.writer("\n\there be dragons; ye COWER in the SHADOW of", self.NAME, "\n\n")
- -
- - self.tty = __import__("tty")
- - self.termios = __import__("termios")
- - self.fcntl = __import__("fcntl")
- -
- - self.O_NONBLOCK = __import__("os").O_NONBLOCK
- -
- - self.TERM_BUFSIZE = TERMCTL_SPECIAL_BUFSIZE
- -
- - def getch(self):
- - """use old fashioned termios to getch"""
- - if sys.stdin.isatty(): # fixes "Inappropriate ioctl for device"
- - fd = sys.stdin.fileno()
- - old_settings = self.termios.tcgetattr(fd)
- - try:
- - self.tty.setraw(sys.stdin.fileno())
- - ch = sys.stdin.read(1)
- - finally:
- - self.termios.tcsetattr(fd, self.termios.TCSADRAIN, old_settings)
- - return ch
- - else:
- - return sys.stdin.read(1)
- -
- - def drain_buf(self):
- - """read TERM_BUFSIZE of waiting keypresses"""
- - if sys.stdin.isatty():
- - fd = sys.stdin.fileno()
- - fl = self.fcntl.fcntl(fd, self.fcntl.F_GETFL)
- - self.fcntl.fcntl(fd, self.fcntl.F_SETFL, fl | self.O_NONBLOCK)
- - try:
- - # if nothing is waiting on sys.stdin, then TypeError
- - # because "can't concat NoneType and str"
- - chars = sys.stdin.read(self.TERM_BUFSIZE)
- - except TypeError:
- - chars = ""
- - finally:
- - self.fcntl.fcntl(fd, self.fcntl.F_SETFL, fl) # restore settings
- - return chars
- - else:
- - return sys.stdin.read(self.TERM_BUFSIZE) # ???
- -
- -read_class = {
- - "windows": _nt_reader,
- -}.get(
- - SYSTEM,
- - _posix_reader # default
- -)
- -
- -
- -class util():
- - """utilities"""
- - def parsenum(num):
- - """sys.maxsize if num is negative"""
- - num = int(num)
- - return sys.maxsize if num < 0 else num
- -
- - def writer(*args):
- - """write a string to stdout and flush.
- - should be used by all stdout-writing"""
- - if not args:
- - raise TypeError("writer requires at least one argument")
- - if len(args) > 1:
- - args = " ".join(str(i) for i in args).strip(" ")
- - else:
- - args = "".join(str(i) for i in args)
- - sys.stdout.write(args)
- - sys.stdout.flush()
- -
- - def esc_filter(x, y):
- - """append x to y as long as x is not DEL or backspace or esc"""
- - if x in (CHAR.DEL, CHAR.BKS):
- - try:
- - y.pop()
- - except IndexError:
- - pass
- - return y
- -
- - y.append(x)
- - return y
- -
- -
- -@checkinit
- -def readkey(raw=False):
- - """interface for getch + drain_buf
- - if raw, behave like getch but with flushing for multibyte inputs"""
- - ch = reader.getch()
- - more = reader.drain_buf()
- -
- - if raw:
- - return ch + more
- -
- - # cooked
- -
- - if ch == CHAR.INT: raise KeyboardInterrupt
- - if ch == CHAR.EOF: raise EOFError
- -
- - if ch in (CHAR.BKS, CHAR.DEL):
- - util.writer(CHAR.BKS + CHAR.SPC + CHAR.BKS)
- - return CHAR.BKS
- -
- - elif ch in (CHAR.CRR, CHAR.LFD):
- - util.writer(CHAR.CRR if SYSTEM == "Windows" else "")
- - return CHAR.LFD
- -
- - elif ch == CHAR.ESC:
- - if more:
- - if more[0] == "[":
- - sp = more[1:]
- - if sp in ("D", "C"):
- - return "\033[" + sp
- -
- - elif sp == "3~":
- - return CHAR.SPC
- -
- - else:
- - return CHAR.BEL
- - else:
- - return CHAR.ESC + more
- -
- - ch += more
- - return ch
- -
- -
- -@checkinit
- -def raw_readkey():
- - """alias for readkey(raw=True)"""
- - return readkey(raw=True)
- -
- -
- -@checkinit
- -def pretty_press(raw=False):
- - """literally just read any fancy char from stdin let caller do whatever"""
- - y = []
- - i = readkey(raw=raw)
- - if (not raw) and (i not in (CHAR.BKS, CHAR.DEL, CHAR.ESC)):
- - util.writer(i)
- - return util.esc_filter(i, y)
- -
- -
- -@checkinit
- -def _do_condition(
- - end_chars,
- - end_condition,
- - count,
- - ignore_chars=(),
- - ignore_condition=CHAR.CONDS[True + 1], # always false
- - raw=False
- - ):
- - """singular interface to reading strings from readkey, to minimise duplication"""
- - y = []
- - count = util.parsenum(count)
- - while len(y) <= count:
- - i = readkey(raw=raw)
- - if end_condition(i, end_chars):
- - break
- - if not ignore_condition(i, ignore_chars):
- - if (not raw) and (i not in (CHAR.BKS, CHAR.DEL)):
- - util.writer(i)
- - y = util.esc_filter(i, y)
- - return "".join(y)
- -
- -
- -@checkinit
- -def thismany(count, raw=False):
- - """read exactly count chars"""
- -
- - return _do_condition(
- - "",
- - CHAR.CONDS[True + 1], # more than true == never expires :D
- - count,
- - raw=raw
- - )
- -
- -
- -@checkinit
- -def until(chars, invert=False, count=-1, raw=False):
- - """get chars of stdin until any of chars is read,
- - or until count chars have been read, whichever comes first"""
- -
- - return _do_condition(
- - chars,
- - CHAR.CONDS[invert],
- - count,
- - raw=raw
- - )
- -
- -
- -@checkinit
- -def until_not(chars, count=-1, raw=False):
- - """read stdin until any of chars stop being read,
- - or until count chars have been read; whichever comes first"""
- -
- - return until(
- - chars,
- - invert=True,
- - count=count,
- - raw=raw
- - )
- -
- -
- -@checkinit
- -def ignore(
- - ignore_these,
- - end_on,
- - end_cond=True,
- - count=-1,
- - raw=False,
- - invert=False
- - ):
- - """ignore_these keypresses, and stop reading at end_on or count,
- - whichever comes first"""
- -
- - return _do_condition(
- - end_on,
- - CHAR.CONDS[not end_cond],
- - count,
- - ignore_chars=ignore_these,
- - ignore_condition=CHAR.CONDS[invert],
- - raw=raw
- - )
- -
- -
- -@checkinit
- -def ignore_not(
- - ignore_these,
- - end_on,
- - end_cond=True,
- - count=-1,
- - raw=False
- - ):
- - """ignore everything that isn't these keypresses
- - and stop reading at end_on or count, whichever comes first"""
- -
- - return ignore(
- - ignore_these,
- - end_on,
- - end_cond=end_cond,
- - count=count,
- - raw=raw,
- - invert=True
- - )
- -
- -if DEBUG:
- - init()
- \ No newline at end of file
- diff --git a/pmlr/__main__.py b/pmlr/__main__.py
- deleted file mode 100644
- index 777c7d6..0000000
- --- a/pmlr/__main__.py
- +++ /dev/null
- @@ -1 +0,0 @@
- -from .pmlr import *
- \ No newline at end of file
- diff --git a/test/_tests_helper.py b/test/_tests_helper.py
- deleted file mode 100755
- index 57be079..0000000
- --- a/test/_tests_helper.py
- +++ /dev/null
- @@ -1,42 +0,0 @@
- -#!/usr/bin/env python3
- -from sys import argv as _argv
- -
- -from tests import pmlr as _ic
- -
- -_p = _ic.util.writer
- -
- -
- -def getch(*a):
- - _ic.init()
- - _p(ord(_ic.reader.getch()))
- -
- -
- -def readkey(*a):
- - _ic.init()
- - _p(ord(_ic.readkey()))
- -
- -
- -def raw_readkey(*a):
- - _ic.init()
- - _p(ord(_ic.raw_readkey()))
- -
- -
- -def writer(*a):
- - if a:
- - _p(*a)
- -
- -if __name__ == "__main__":
- - try:
- - _arg = _argv[1]
- - _rest = tuple(_argv[2:])
- - except IndexError:
- - _g = globals().copy()
- - _funcs = [
- - i for i in _g
- - if not list(_g.keys())[list(_g.keys())
- - .index(i)]
- - .startswith("_")
- - ]
- - print("names:\t" + "\n\t".join(i for i in _funcs))
- - else:
- - globals()[_arg](*_rest)
- diff --git a/test/tests.py b/test/tests.py
- deleted file mode 100755
- index 7d7aea7..0000000
- --- a/test/tests.py
- +++ /dev/null
- @@ -1,135 +0,0 @@
- -#!/usr/bin/env python3
- -import unittest
- -import subprocess as sp
- -from sys import executable as py, maxsize as MAXSIZE, version_info as VERINFO
- -from os import getcwd, path
- -
- -TESTMOD_INFO = ("pmlr", path.join(getcwd(), "..", "pmlr", "pmlr", "__main__.py"))
- -
- -TEST_HELP = path.join(getcwd(), "..", "pmlr", "test", "_tests_helper.py")
- -
- -
- -if VERINFO.major == 2:
- - import imp
- - pmlr = imp.load_source(*TESTMOD_INFO)
- -
- -elif VERINFO.major == 3:
- - if VERINFO.minor < 5:
- - from importlib.machinery import SourceFileLoader
- - pmlr = SourceFileLoader(*TESTMOD_INFO).load_module()
- -
- - elif VERINFO.minor >= 5:
- - import importlib.util
- - spec = importlib.util.spec_from_file_location(*TESTMOD_INFO)
- - pmlr = importlib.util.module_from_spec(spec)
- - spec.loader.exec_module(pmlr)
- -else:
- - raise NotImplementedError("unsupported Python version: ", VERINFO.major)
- -
- -
- -class TestUtilsNoIO(unittest.TestCase):
- - """io-less util tests"""
- -
- - def test_parsenum(self):
- - """test parsenum"""
- - nums = (-MAXSIZE, -122, -1, 0, 8, 88, 888880, MAXSIZE)
- - for elem in nums:
- - result = pmlr.util.parsenum(elem)
- - expect = MAXSIZE if elem < 0 else elem
- - self.assertEqual(result, expect)
- -
- - def test_parsenum_complex(self):
- - """test parsenum failure"""
- - with self.assertRaises(TypeError):
- - pmlr.util.parsenum(8j)
- -
- -
- -class TestKPressIO(unittest.TestCase):
- -
- - def setUp(self):
- - pmlr.init()
- -
- - def test_getch(self):
- - """test getch (patience)"""
- - for ch in range(128):
- - p = sp.Popen(
- - [py, TEST_HELP, "getch"],
- - stdin=sp.PIPE,
- - stdout=sp.PIPE,
- - )
- - out, _ = p.communicate(input=bytes(chr(ch), "utf-8"))
- - self.assertEqual(
- - out, bytes('{}'.format(ch), "utf-8") # ewww
- - )
- -
- - def test_read_keypress(self):
- - """test readkey (patience)"""
- - specials = { # special cases
- - 3: "KeyboardInterrupt",
- - 4: "EOFError",
- - 8: b'\x08\x088',
- - 13: b'10',
- - 27: b'\x08\x0827',
- - 127: '',
- - }
- - for ch in range(128):
- - p = sp.Popen(
- - [py, TEST_HELP, "readkey"],
- - stdin=sp.PIPE,
- - stdout=sp.PIPE,
- - stderr=sp.PIPE
- - )
- - out, err = p.communicate(input=bytes(chr(ch), "utf-8"))
- - if ch in specials.keys():
- - res = ( # magic
- - err
- - .decode("utf-8")
- - .strip()
- - .split("\n")[-1]
- - if ch not in (8, 13, 27)
- - else out
- - )
- - self.assertEqual(
- - specials[ch], res
- - )
- - else:
- - self.assertEqual(
- - out, bytes('{}'.format(ch), "utf-8")
- - )
- -
- - def test_read_keypress_raw(self):
- - """read raw keypress (patience)"""
- - specials = { # special cases
- - 8: b'\x08\x088',
- - 13: b'10',
- - 27: b'\x08\x0827',
- - 127: b'\x08\x08127',
- - }
- - for ch in range(128):
- - p = sp.Popen(
- - [py, TEST_HELP, "raw_readkey"],
- - stdin=sp.PIPE,
- - stdout=sp.PIPE,
- - stderr=sp.PIPE
- - )
- - out, err = p.communicate(input=bytes(chr(ch), "utf-8"))
- - if ch in specials.keys():
- - self.assertEqual(
- - specials[ch], out
- - )
- - else:
- - self.assertEqual(
- - out, bytes('{}'.format(ch), "utf-8")
- - )
- -
- -
- -if __name__ == '__main__':
- - from os import stat
- - try:
- - stat(TEST_HELP)
- - except FileNotFoundError as e:
- - print(e)
- - print("stat: cannot stat '{}': no such file or directory".format(TEST_HELP))
- - exit(2)
- - else:
- - unittest.main(verbosity = 3)
- \ No newline at end of file
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement