diff options
Diffstat (limited to 'pydora/utils.py')
-rw-r--r-- | pydora/utils.py | 104 |
1 files changed, 90 insertions, 14 deletions
diff --git a/pydora/utils.py b/pydora/utils.py index faa18e5..6c608a7 100644 --- a/pydora/utils.py +++ b/pydora/utils.py | |||
@@ -6,13 +6,14 @@ import getpass | |||
6 | import subprocess | 6 | import subprocess |
7 | from pandora.py2compat import input | 7 | from pandora.py2compat import input |
8 | 8 | ||
9 | try: | ||
10 | import termios | ||
11 | except ImportError: | ||
12 | # Windows does not have a termios module | ||
13 | termios = None | ||
14 | 9 | ||
10 | class TerminalPlatformUnsupported(Exception): | ||
11 | """Platform-specific functionality is not supported | ||
15 | 12 | ||
13 | Raised by code that can not be used to interact with the terminal on this | ||
14 | platform. | ||
15 | """ | ||
16 | pass | ||
16 | 17 | ||
17 | 18 | ||
18 | class Colors(object): | 19 | class Colors(object): |
@@ -35,25 +36,100 @@ class Colors(object): | |||
35 | white = __wrap_with("37") | 36 | white = __wrap_with("37") |
36 | 37 | ||
37 | 38 | ||
38 | class Screen(object): | 39 | class PosixEchoControl(object): |
40 | """Posix Console Echo Control Driver | ||
39 | 41 | ||
40 | @staticmethod | 42 | Uses termios on POSIX compliant platforms to control console echo. Is not |
41 | def set_echo(enabled): | 43 | supported on Windows as termios is not available and will throw a |
42 | if not termios: | 44 | TerminalPlatformUnsupported exception if contructed on Windows. |
43 | return | 45 | """ |
46 | |||
47 | def __init__(self): | ||
48 | try: | ||
49 | import termios | ||
50 | self.termios = termios | ||
51 | except ImportError: | ||
52 | raise TerminalPlatformUnsupported("POSIX not supported") | ||
44 | 53 | ||
54 | def set_echo(self, enabled): | ||
45 | handle = sys.stdin.fileno() | 55 | handle = sys.stdin.fileno() |
46 | if not os.isatty(handle): | 56 | if not os.isatty(handle): |
47 | return | 57 | return |
48 | 58 | ||
49 | attrs = termios.tcgetattr(handle) | 59 | attrs = self.termios.tcgetattr(handle) |
60 | |||
61 | if enabled: | ||
62 | attrs[3] |= self.termios.ECHO | ||
63 | else: | ||
64 | attrs[3] &= ~self.termios.ECHO | ||
65 | |||
66 | self.termios.tcsetattr(handle, self.termios.TCSANOW, attrs) | ||
67 | |||
68 | |||
69 | class Win32EchoControl(object): | ||
70 | """Windows Console Echo Control Driver | ||
71 | |||
72 | This uses the console API from WinCon.h and ctypes to control console echo | ||
73 | on Windows clients. It is not possible to construct this class on | ||
74 | non-Windows systems, on those systems it will throw a | ||
75 | TerminalPlatformUnsupported exception. | ||
76 | """ | ||
77 | |||
78 | STD_INPUT_HANDLE = -10 | ||
79 | ENABLE_ECHO_INPUT = 0x4 | ||
80 | DISABLE_ECHO_INPUT = ~ENABLE_ECHO_INPUT | ||
81 | |||
82 | def __init__(self): | ||
83 | import ctypes | ||
84 | |||
85 | if not hasattr(ctypes, "windll"): | ||
86 | raise TerminalPlatformUnsupported("Windows not supported") | ||
87 | |||
88 | from ctypes import wintypes | ||
89 | |||
90 | self.ctypes = ctypes | ||
91 | self.wintypes = wintypes | ||
92 | self.kernel32 = ctypes.windll.kernel32 | ||
93 | |||
94 | def _GetStdHandle(self, handle): | ||
95 | return self.kernel32.GetStdHandle(handle) | ||
96 | |||
97 | def _GetConsoleMode(self, handle): | ||
98 | mode = self.wintypes.DWORD() | ||
99 | self.kernel32.GetConsoleMode(handle, self.ctypes.byref(mode)) | ||
100 | return mode.value | ||
101 | |||
102 | def _SetConsoleMode(self, handle, value): | ||
103 | self.kernel32.SetConsoleMode(handle, value) | ||
104 | |||
105 | def set_echo(self, enabled): | ||
106 | stdin = self._GetStdHandle(self.STD_INPUT_HANDLE) | ||
107 | mode = self._GetConsoleMode(stdin) | ||
50 | 108 | ||
51 | if enabled: | 109 | if enabled: |
52 | attrs[3] |= termios.ECHO | 110 | self._SetConsoleMode(stdin, mode | self.ENABLE_ECHO_INPUT) |
53 | else: | 111 | else: |
54 | attrs[3] &= ~termios.ECHO | 112 | self._SetConsoleMode(stdin, mode & self.DISABLE_ECHO_INPUT) |
113 | |||
114 | |||
115 | class Screen(object): | ||
116 | |||
117 | def __init__(self): | ||
118 | try: | ||
119 | self._echo_driver = PosixEchoControl() | ||
120 | except TerminalPlatformUnsupported: | ||
121 | pass | ||
122 | |||
123 | try: | ||
124 | self._echo_driver = Win32EchoControl() | ||
125 | except TerminalPlatformUnsupported: | ||
126 | pass | ||
127 | |||
128 | if not self._echo_driver: | ||
129 | raise TerminalPlatformUnsupported("No supported terminal driver") | ||
55 | 130 | ||
56 | termios.tcsetattr(handle, termios.TCSANOW, attrs) | 131 | def set_echo(self, enabled): |
132 | self._echo_driver.set_echo(enabled) | ||
57 | 133 | ||
58 | @staticmethod | 134 | @staticmethod |
59 | def clear(): | 135 | def clear(): |