PKGhpynput/__init__.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . from . import keyboard from . import mouse PK%2H'sCCpynput/_info.py# coding: utf8 __author__ = u'Moses Palmér' __version__ = (0, 5) PKGC*pynput/keyboard/__init__.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import os import sys if os.environ.get('__PYNPUT_GENERATE_DOCUMENTATION') == 'yes': from ._base import KeyCode, Key, Controller else: KeyCode = None Key = None Controller = None Listener = None if sys.platform == 'darwin': if KeyCode is None and Key is None and Controller is None: from ._darwin import KeyCode, Key, Controller elif sys.platform == 'win32': if KeyCode is None and Key is None and Controller is None: from ._win32 import KeyCode, Key, Controller else: if KeyCode is None and Key is None and Controller is None: try: from ._xorg import KeyCode, Key, Controller except: pass if not KeyCode or not Key or not Controller: raise ImportError('this platform is not supported') PK2Hn nnpynput/keyboard/_darwin.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import enum import Quartz from pynput._util.darwin import * from . import _base class KeyCode(_base.KeyCode): def event(self, modifiers, mapping, is_pressed): vk = self.vk or mapping.get(self.char, 0) result = Quartz.CGEventCreateKeyboardEvent(None, vk, is_pressed) Quartz.CGEventSetFlags( result, (Quartz.kCGEventFlagMaskAlternate if Key.alt in modifiers else 0) | (Quartz.kCGEventFlagMaskCommand if Key.cmd in modifiers else 0) | (Quartz.kCGEventFlagMaskControl if Key.ctrl in modifiers else 0) | (Quartz.kCGEventFlagMaskShift if Key.shift in modifiers else 0)) if not vk and self.char is not None: Quartz.CGEventKeyboardSetUnicodeString( result, len(self.char), self.char) return result class Key(enum.Enum): # Default keys alt = KeyCode.from_vk(0x3A) alt_l = KeyCode.from_vk(0x3A) alt_r = KeyCode.from_vk(0x3D) alt_gr = KeyCode.from_vk(0x3D) backspace = KeyCode.from_vk(0x33) caps_lock = KeyCode.from_vk(0x39) cmd = KeyCode.from_vk(0x37) cmd_l = KeyCode.from_vk(0x37) cmd_r = KeyCode.from_vk(0x37) ctrl = KeyCode.from_vk(0x3B) ctrl_l = KeyCode.from_vk(0x3B) ctrl_r = KeyCode.from_vk(0x3E) delete = KeyCode.from_vk(0x35) down = KeyCode.from_vk(0x7D) end = KeyCode.from_vk(0x77) enter = KeyCode.from_vk(0x24) esc = KeyCode.from_vk(0x35) f1 = KeyCode.from_vk(0x7A) f2 = KeyCode.from_vk(0x78) f3 = KeyCode.from_vk(0x63) f4 = KeyCode.from_vk(0x76) f5 = KeyCode.from_vk(0x60) f6 = KeyCode.from_vk(0x61) f7 = KeyCode.from_vk(0x62) f8 = KeyCode.from_vk(0x64) f9 = KeyCode.from_vk(0x65) f10 = KeyCode.from_vk(0x6D) f11 = KeyCode.from_vk(0x67) f12 = KeyCode.from_vk(0x6F) f13 = KeyCode.from_vk(0x69) f14 = KeyCode.from_vk(0x6B) f15 = KeyCode.from_vk(0x71) f16 = KeyCode.from_vk(0x6A) f17 = KeyCode.from_vk(0x40) f18 = KeyCode.from_vk(0x4F) f19 = KeyCode.from_vk(0x50) f20 = KeyCode.from_vk(0x5A) home = KeyCode.from_vk(0x73) left = KeyCode.from_vk(0x7B) page_down = KeyCode.from_vk(0x79) page_up = KeyCode.from_vk(0x74) right = KeyCode.from_vk(0x7C) shift = KeyCode.from_vk(0x38) shift_l = KeyCode.from_vk(0x38) shift_r = KeyCode.from_vk(0x3C) space = KeyCode(vk=0x31, char=' ') tab = KeyCode.from_vk(0x31) up = KeyCode.from_vk(0x7E) class Controller(_base.Controller): _KeyCode = KeyCode _Key = Key def __init__(self): super(Controller, self).__init__() self._mapping = get_unicode_to_keycode_map() def _handle(self, key, is_press): with self.modifiers as modifiers: Quartz.CGEventPost( Quartz.kCGHIDEventTap, (key if key not in Key else key.value).event( modifiers, self._mapping, is_press)) PK2Hsl((pynput/keyboard/_win32.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import enum from pynput._util.win32 import * from . import _base class KeyCode(_base.KeyCode): def parameters(self, is_press): """The parameters to pass to ``SendInput`` to generate this key. """ if self.vk: vk = self.vk scan = 0 flags = 0 else: r = VkKeyScan(ord(self.char)) if (r >> 8) & 0xFF == 0: vk = r & 0xFF scan = 0 flags = 0 else: vk = 0 scan = ord(self.char) flags = KEYBDINPUT.UNICODE return dict( dwFlags=flags | (KEYBDINPUT.KEYUP if not is_press else 0), wVk=vk, wScan=scan) class Key(enum.Enum): alt = KeyCode.from_vk(0x12) alt_l = KeyCode.from_vk(0xA4) alt_r = KeyCode.from_vk(0xA5) alt_gr = KeyCode.from_vk(0xA5) backspace = KeyCode.from_vk(0x08) caps_lock = KeyCode.from_vk(0x14) cmd = KeyCode.from_vk(0x5B) cmd_l = KeyCode.from_vk(0x5B) cmd_r = KeyCode.from_vk(0xA4) ctrl = KeyCode.from_vk(0x11) ctrl_l = KeyCode.from_vk(0xA2) ctrl_r = KeyCode.from_vk(0xA3) delete = KeyCode.from_vk(0x2E) down = KeyCode.from_vk(0x28) end = KeyCode.from_vk(0x23) enter = KeyCode.from_vk(0x0D) esc = KeyCode.from_vk(0x1B) f1 = KeyCode.from_vk(0x70) f2 = KeyCode.from_vk(0x71) f3 = KeyCode.from_vk(0x72) f4 = KeyCode.from_vk(0x73) f5 = KeyCode.from_vk(0x74) f6 = KeyCode.from_vk(0x75) f7 = KeyCode.from_vk(0x76) f8 = KeyCode.from_vk(0x77) f9 = KeyCode.from_vk(0x78) f10 = KeyCode.from_vk(0x79) f11 = KeyCode.from_vk(0x7A) f12 = KeyCode.from_vk(0x7B) f13 = KeyCode.from_vk(0x7C) f14 = KeyCode.from_vk(0x7D) f15 = KeyCode.from_vk(0x7E) f16 = KeyCode.from_vk(0x7F) f17 = KeyCode.from_vk(0x80) f18 = KeyCode.from_vk(0x81) f19 = KeyCode.from_vk(0x82) f20 = KeyCode.from_vk(0x83) home = KeyCode.from_vk(0x24) left = KeyCode.from_vk(0x25) page_down = KeyCode.from_vk(0x22) page_up = KeyCode.from_vk(0x21) right = KeyCode.from_vk(0x27) shift = KeyCode.from_vk(0xA0) shift_l = KeyCode.from_vk(0xA0) shift_r = KeyCode.from_vk(0xA1) space = KeyCode(vk=0x20, char=' ') tab = KeyCode.from_vk(0x09) up = KeyCode.from_vk(0x26) insert = KeyCode.from_vk(0x2D) menu = KeyCode.from_vk(0x5D) num_lock = KeyCode.from_vk(0x90) pause = KeyCode.from_vk(0x13) print_screen = KeyCode.from_vk(0x2C) scroll_lock = KeyCode.from_vk(0x91) class Controller(_base.Controller): _KeyCode = KeyCode _Key = Key def _handle(self, key, is_press): SendInput( 1, ctypes.byref(INPUT( type=INPUT.KEYBOARD, value=INPUT_union( ki=KEYBDINPUT(**key.parameters(is_press))))), ctypes.sizeof(INPUT)) PK2HJm//pynput/keyboard/_xorg.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import enum import threading import Xlib.display import Xlib.ext import Xlib.ext.xtest import Xlib.X import Xlib.XK import Xlib.protocol from pynput._util.xorg import * from . import _base class KeyCode(_base.KeyCode): @classmethod def from_symbol(self, symbol): """Creates a key from a symbol. :param str symbol: The symbol name. :return: a key code """ # First try simple translation keysym = Xlib.XK.string_to_keysym(symbol) if keysym: return self.from_vk(keysym) # If that fails, try checking a module attribute of Xlib.keysymdef.xkb if not keysym: try: return self.from_vk( getattr(Xlib.keysymdef.xkb, 'XK_' + symbol, 0)) except: return self.from_vk( SYMBOLS.get(symbol, (0,))[0]) class Key(enum.Enum): # Default keys alt = KeyCode.from_symbol('Alt_L') alt_l = KeyCode.from_symbol('Alt_L') alt_r = KeyCode.from_symbol('Alt_R') alt_gr = KeyCode.from_symbol('Mode_switch') backspace = KeyCode.from_symbol('BackSpace') caps_lock = KeyCode.from_symbol('Caps_Lock') cmd = KeyCode.from_symbol('Super_L') cmd_l = KeyCode.from_symbol('Super_L') cmd_r = KeyCode.from_symbol('Super_R') ctrl = KeyCode.from_symbol('Control_L') ctrl_l = KeyCode.from_symbol('Control_L') ctrl_r = KeyCode.from_symbol('Control_R') delete = KeyCode.from_symbol('Delete') down = KeyCode.from_symbol('Down') end = KeyCode.from_symbol('End') enter = KeyCode.from_symbol('Return') esc = KeyCode.from_symbol('Escape') f1 = KeyCode.from_symbol('F1') f2 = KeyCode.from_symbol('F2') f3 = KeyCode.from_symbol('F3') f4 = KeyCode.from_symbol('F4') f5 = KeyCode.from_symbol('F5') f6 = KeyCode.from_symbol('F6') f7 = KeyCode.from_symbol('F7') f8 = KeyCode.from_symbol('F8') f9 = KeyCode.from_symbol('F9') f10 = KeyCode.from_symbol('F10') f11 = KeyCode.from_symbol('F11') f12 = KeyCode.from_symbol('F12') f13 = KeyCode.from_symbol('F13') f14 = KeyCode.from_symbol('F14') f15 = KeyCode.from_symbol('F15') f16 = KeyCode.from_symbol('F16') f17 = KeyCode.from_symbol('F17') f18 = KeyCode.from_symbol('F18') f19 = KeyCode.from_symbol('F19') f20 = KeyCode.from_symbol('F20') home = KeyCode.from_symbol('Home') left = KeyCode.from_symbol('Left') page_down = KeyCode.from_symbol('Page_Down') page_up = KeyCode.from_symbol('Page_Up') right = KeyCode.from_symbol('Right') shift = KeyCode.from_symbol('Shift_L') shift_l = KeyCode.from_symbol('Shift_L') shift_r = KeyCode.from_symbol('Shift_R') space = KeyCode(vk=Xlib.XK.string_to_keysym('space'), char=' ') tab = KeyCode.from_symbol('Tab') up = KeyCode.from_symbol('Up') insert = KeyCode.from_symbol('Insert') menu = KeyCode.from_symbol('Menu') num_lock = KeyCode.from_symbol('Num_Lock') pause = KeyCode.from_symbol('Pause') print_screen = KeyCode.from_symbol('Print') scroll_lock = KeyCode.from_symbol('Scroll_Lock') class Controller(_base.Controller): _KeyCode = KeyCode _Key = Key #: The shift mask for :attr:`Key.ctrl` CTRL_MASK = Xlib.X.ControlMask #: The shift mask for :attr:`Key.shift` SHIFT_MASK = Xlib.X.ShiftMask def __init__(self): super(Controller, self).__init__() self._display = Xlib.display.Display() self._keyboard_mapping = None self._borrows = {} self._borrow_lock = threading.RLock() self.ALT_MASK = alt_mask(self._display) self.ALT_GR_MASK = alt_gr_mask(self._display) def __del__(self): if self._display: self._display.close() @property def keyboard_mapping(self): """A mapping from *keysyms* to *key codes*. Each value is the tuple ``(key_code, shift_state)``. By sending an event with the specified *key code* and shift state, the specified *keysym* will be touched. """ if not self._keyboard_mapping: self._update_keyboard_mapping() return self._keyboard_mapping def _handle(self, key, is_press): """Resolves a key identifier and sends a keyboard event. :param event: The *X* keyboard event. :param int keysym: The keysym to handle. """ event = Xlib.display.event.KeyPress if is_press \ else Xlib.display.event.KeyRelease keysym = self._keysym(key) try: keycode, shift_state = self.keyboard_mapping[keysym] self._send_key(event, keycode, shift_state) except KeyError: with self._borrow_lock: keycode, index, count = self._borrows[keysym] self._send_key( event, keycode, index_to_shift(self._display, index)) count += 1 if is_press else -1 self._borrows[keysym] = (keycode, index, count) def _keysym(self, key): """Converts a key to a *keysym*. :param KeyCode key: The key code to convert. """ return self._resolve_dead(key) if key.is_dead else None \ or self._resolve_special(key) \ or self._resolve_normal(key) \ or self._resolve_borrowed(key) \ or self._resolve_borrowing(key) def _send_key(self, event, keycode, shift_state): """Sends a single keyboard event. :param event: The *X* keyboard event. :param int keycode: The keycode. :param int shift_state: The shift state. The actual value used is :attr:`shift_state` or'd with this value. """ with display_manager(self._display) as d, self.modifiers as modifiers: window = d.get_input_focus().focus window.send_event(event( detail=keycode, state=shift_state | self._shift_mask(modifiers), time=0, root=d.screen().root, window=window, same_screen=0, child=Xlib.X.NONE, root_x=0, root_y=0, event_x=0, event_y=0)) def _resolve_dead(self, key): """Tries to resolve a dead key. :param str identifier: The identifier to resolve. """ try: keysym, _ = SYMBOLS[CHARS[key.combining]] except: return None if keysym not in self.keyboard_mapping: return None return keysym def _resolve_special(self, key): """Tries to resolve a special key. A special key has the :attr:`~KeyCode.vk` attribute set. :param KeyCode key: The key to resolve. """ if not key.vk: return None return key.vk def _resolve_normal(self, key): """Tries to resolve a normal key. A normal key exists on the keyboard, and is typed by pressing and releasing a simple key, possibly in combination with a modifier. :param KeyCode key: The key to resolve. """ keysym = self._key_to_keysym(key) if keysym is None: return None if keysym not in self.keyboard_mapping: return None return keysym def _resolve_borrowed(self, key): """Tries to resolve a key by looking up the already borrowed *keysyms*. A borrowed *keysym* does not exist on the keyboard, but has been temporarily added to the layout. :param KeyCode key: The key to resolve. """ keysym = self._key_to_keysym(key) if keysym is None: return None with self._borrow_lock: if keysym not in self._borrows: return None return keysym def _resolve_borrowing(self, key): """Tries to resolve a key by modifying the layout temporarily. A borrowed *keysym* does not exist on the keyboard, but is temporarily added to the layout. :param KeyCode key: The key to resolve. """ keysym = self._key_to_keysym(key) if keysym is None: return None keyboard_mapping = self._display.get_keyboard_mapping(8, 255 - 8) def i2kc(index): return index + 8 def kc2i(keycode): return keycode - 8 #: Finds a keycode and index by looking at already used keycodes def reuse(): for keysym, (keycode, _, _) in self._borrows.items(): keycodes = keyboard_mapping[kc2i(keycode)] # Only the first four items are addressable by X for index in range(4): if not keycodes[index]: return keycode, index #: Finds a keycode and index by using a new keycode def borrow(): for i, keycodes in enumerate(keyboard_mapping): if not any(keycodes): return i2kc(i), 0 #: Finds a keycode and index by reusing an old, unused one def overwrite(): for keysym, (keycode, index, count) in self._borrows.items(): if count < 1: del self._borrows[keysym] return keycode, index #: Registers a keycode for a specific key and modifier state def register(keycode, index): i = kc2i(keycode) keyboard_mapping[i][index] = keysym d.change_keyboard_mapping( keycode, keyboard_mapping[i:i + 1]) self._borrows[keysym] = (keycode, index, 0) try: with display_manager(self._display) as d, self._borrow_lock: # First try an already used keycode, then try a new one, and # fall back on reusing one that is not currently pressed register(*( reuse() or borrow() or overwrite())) return keysym except TypeError: return None def _key_to_keysym(self, key): """Converts a character key code to a *keysym*. :param KeyCode key: The key code. :return: a keysym if found :rtype: int or None """ symbol = CHARS.get(key.char, None) if symbol is None: return None try: return symbol_to_keysym(symbol) except: try: return SYMBOLS[symbol][0] except: return None def _shift_mask(self, modifiers): """The *X* modifier mask to apply for a set of modifiers. :param set modifiers: A set of active modifiers for which to get the shift mask. """ return ( (self.ALT_MASK if Key.alt in modifiers else 0) | (self.ALT_GR_MASK if Key.alt_gr in modifiers else 0) | (self.CTRL_MASK if Key.ctrl in modifiers else 0) | (self.SHIFT_MASK if Key.shift in modifiers else 0)) def _update_keyboard_mapping(self): """Updates the keyboard mapping. """ with display_manager(self._display) as d: self._keyboard_mapping = keyboard_mapping(d) PK2H 77pynput/keyboard/_base.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import contextlib import enum import six import threading import unicodedata class KeyCode(object): def __init__(self, vk=0, char=None, is_dead=False): self.vk = vk self.char = six.text_type(char) if char is not None else None self.is_dead = is_dead if self.is_dead: self.combining = unicodedata.lookup( 'COMBINING ' + unicodedata.name(self.char)) if not self.combining: raise KeyError(char) else: self.combining = None def __repr__(self): if self.is_dead: return '[%s]' % repr(self.char) if self.char is not None: return repr(self.char) else: return '<%d>' % self.vk def __str__(self): return repr(self) def join(self, key): """Applies this dead key to another key and returns a sequence of key codes. :param KeyCode dead: The dead key to join with another key. :param KeyCode key: The key to join with the dead key. :return: a key code :raises ValueError: if the keys cannot be joined """ # Joining two of the same keycodes, or joining with space, yields the # non-dead version of the key if key.char == ' ' or (key.is_dead and key.char == self.char): return self.from_char(self.char) # Otherwise we combine the characters if key.char is not None: combined = unicodedata.normalize( 'NFC', key.char + self.combining) if combined: return self.from_char(combined) raise ValueError(key) @classmethod def from_vk(self, vk): """Creates a key from a virtual key code. :param vk: The virtual key code. :return: a key code """ return self(vk=vk) @classmethod def from_char(self, char): """Creates a key from a character. :param str char: The character. :return: a key code """ return self(char=char) @classmethod def from_dead(self, char): """Creates a dead key. :param char: The dead key. This should be the unicode character representing the stand alone character, such as ``'~'`` for *COMBINING TILDE*. :return: a key code """ return self(char=char, is_dead=True) class Key(enum.Enum): """A class representing various buttons that may not correspond to letters. This includes modifier keys and function keys. The actual values for these items differ between platforms. Some platforms may have additional buttons, but these are guaranteed to be present everywhere. """ #: A generic Alt key. This is a modifier. alt = 0 #: The left Alt key. This is a modifier. alt_l = 0 #: The right Alt key. This is a modifier. alt_r = 0 #: The AltGr key. This is a modifier. alt_gr = 0 #: The Backspace key. backspace = 0 #: The CapsLock key. caps_lock = 0 #: A generic command button. On *PC* platforms, this corresponds to the #: Super key or Windows key, and on *Mac* it corresponds to the Command #: key. This may be a modifier. cmd = 0 #: The left command button. On *PC* platforms, this corresponds to the #: Super key or Windows key, and on *Mac* it corresponds to the Command #: key. This may be a modifier. cmd_l = 0 #: The right command button. On *PC* platforms, this corresponds to the #: Super key or Windows key, and on *Mac* it corresponds to the Command #: key. This may be a modifier. cmd_r = 0 #: A generic Ctrl key. This is a modifier. ctrl = 0 #: The left Ctrl key. This is a modifier. ctrl_l = 0 #: The right Ctrl key. This is a modifier. ctrl_r = 0 #: The Delete key. delete = 0 #: A down array key. down = 0 #: The End key. end = 0 #: The Enter or Return key. enter = 0 #: The Esc key. esc = 0 #: The function keys. F1 to F20 are defined. f1 = 0 f2 = 0 f3 = 0 f4 = 0 f5 = 0 f6 = 0 f7 = 0 f8 = 0 f9 = 0 f10 = 0 f11 = 0 f12 = 0 f13 = 0 f14 = 0 f15 = 0 f16 = 0 f17 = 0 f18 = 0 f19 = 0 f20 = 0 #: The Home key. home = 0 #: A left arrow key. left = 0 #: Trhe PageDown key. page_down = 0 #: The Pageup key. page_up = 0 #: A right arrow key. right = 0 #: A generic Shift key. This is a modifier. shift = 0 #: The left Shift key. This is a modifier. shift_l = 0 #: The right Shift key. This is a modifier. shift_r = 0 #: The Space key. space = 0 #: The Tab key. tab = 0 #: An up arrow key. up = 0 #: The Insert key. This may be undefined for some platforms. insert = 0 #: The Menu key. This may be udefined for some platforms. menu = 0 #: The NumLock key. This may be undefined for some platforms. num_lock = 0 #: The Pause/Break key. This may be undefined for some platforms. pause = 0 #: The PrintScreen key. This may be undefined for some platforms. print_screen = 0 #: The ScrollLock key. This may be undefined for some platforms. scroll_lock = 0 class Controller(object): """A controller for sending virtual keyboard events to the system. """ #: The virtual key codes _KeyCode = KeyCode #: The various keys. _Key = Key class InvalidKeyException(Exception): """The exception raised when and invalid ``key`` parameter is passed to either :meth:`Controller.press` or :meth:`Controller.release`. Its first argument is the ``key`` parameter. """ pass class InvalidCharacterException(Exception): """The exception raised when and invalid character is encountered in the string passed to :meth:`Controller.type`. Its first argument is the index of the character in the string, and the second the character. """ pass def __init__(self): self._modifiers_lock = threading.RLock() self._modifiers = set() self._caps_lock = False self._dead_key = None K = self._Key #: The keys used as modifiers; the first value in each tuple is the #: base modifier to use for subsequent modifiers. self._MODIFIER_KEYS = ( (K.alt_gr, (K.alt_gr.value,)), (K.alt, (K.alt.value, K.alt_l.value, K.alt_r.value)), (K.cmd, (K.cmd.value, K.cmd_l.value, K.cmd_r.value)), (K.ctrl, (K.ctrl.value, K.ctrl_l.value, K.ctrl_r.value)), (K.shift, (K.shift.value, K.shift_l.value, K.shift_r.value))) def press(self, key): """Presses a key. A key may be either a string of length 1, one of the :class:`Key` members or a :class:`KeyCode`. Strings will be transformed to :class:`KeyCode` using :meth:`KeyCode.char`. Members of :class:`Key` will be translated to their :meth:`~Key.value`. :param key: The key to press. :raises InvalidKeyException: if the key is invalid :raises ValueError: if ``key`` is a string, but its length is not ``1`` """ self._dispatch(key, True) def release(self, key): """Releases a key. A key may be either a string of length 1, one of the :class:`Key` members or a :class:`KeyCode`. Strings will be transformed to :class:`KeyCode` using :meth:`KeyCode.char`. Members of :class:`Key` will be translated to their :meth:`~Key.value`. :param key: The key to release. If this is a string, it is passed to :meth:`touches` and the returned releases are used. :raises InvalidKeyException: if the key is invalid :raises ValueError: if ``key`` is a string, but its length is not ``1`` """ self._dispatch(key, False) def touch(self, key, is_press): """Calls either :meth:`press` or :meth:`release` depending on the value of ``is_press``. :param key: The key to press or release. :param bool is_press: Whether to press the key. """ if is_press: self.press(key) else: self.release(key) @contextlib.contextmanager def pressed(self, *args): """Executes a block with some keys pressed. :param keys: The keys to keep pressed. """ for key in args: self.press(key) try: yield finally: for key in reversed(args): self.press(key) def type(self, string): """Types a string. This method will send all key presses and releases necessary to type all characters in the string. :param str string: The string to type. :raises InvalidCharacterException: if an untypable character is encountered """ for i, character in enumerate(string): try: self.press(character) self.release(character) except ValueError: raise self.InvalidCharacterException(i, character) @property @contextlib.contextmanager def modifiers(self): """The currently pressed modifier keys. """ with self._modifiers_lock: yield self._modifiers @property def alt_pressed(self): """Whether any *alt* key is pressed. """ with self.modifiers as modifiers: return self._Key.alt in modifiers @property def alt_gr_pressed(self): """Whether *altgr* is pressed. """ with self.modifiers as modifiers: return self._Key.alt_gr in modifiers @property def ctrl_pressed(self): """Whether any *ctrl* key is pressed. """ with self.modifiers as modifiers: return self._Key.ctrl in modifiers @property def shift_pressed(self): """Whether any *shift* key is pressed, or *caps lock* is toggled. """ if self._caps_lock: return True with self.modifiers as modifiers: return self._Key.shift in modifiers def _dispatch(self, key, is_press): """Dispatches a press or release. This method selects the correct platform implementation and translates the ``key`` argument as described in :meth:`press` and :meth:`release`. It also handles any platform indepentent key actions. :param key: The key. :param bool is_press: Whether this is a press event. :raises ValueError: if ``key`` is a string, but its length is not ``1`` """ # Use the value for the key constants if key in self._Key: return self._dispatch(key.value, is_press) # Convert strings to key codes if isinstance(key, six.string_types): if len(key) != 1: raise ValueError(key) return self._dispatch(self._KeyCode.from_char(key), is_press) # Check whether the key is a modifier modifier = self._as_modifier(key) if modifier: with self.modifiers as modifiers: if is_press: modifiers.add(modifier) else: try: modifiers.remove(modifier) except KeyError: pass # Apply shift if any shift keys are active if key.char is not None and self.shift_pressed: key = self._KeyCode.from_char(key.char.upper()) # Otherwise, let the platform implementation handle it if is_press: # Update caps lock state if is_press and key == self._Key.caps_lock.value: self._caps_lock = not self._caps_lock # If we currently have a dead key pressed, join it with this key if self._dead_key: try: key = self._dead_key.join(key) except ValueError: self._handle(self._dead_key, True) self._handle(self._dead_key, False) self._dead_key = None # If the key is a dead key, keep it for later if key.is_dead: self._dead_key = key return else: # Ignore released dead keys if key.is_dead: return self._handle(key, is_press) def _as_modifier(self, key): """Returns a key as the modifier used internally is defined. This method will convert values like :attr:`Key.alt_r.value` and :attr:`Key.shift_l.value` to :attr:`Key.alt` and :attr:`Key.shift`. :param key: The possible modifier key. :return: the base modifier key, or ``None`` if ``key`` is not a modifier """ for base, modifiers in self._MODIFIER_KEYS: if key in modifiers: return base def _handle(self, key, is_press): """The platform implementation of the actual emitting of keyboard events. This is a platform dependent implementation. :param Key key: The key to handle. :param bool is_press: Whether this is a key press event. """ raise NotImplementedError() PKYGYpynput/_util/__init__.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . PK2H"HHpynput/_util/darwin.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import contextlib import ctypes import ctypes.util import six import objc import CoreFoundation #: The objc module as a library handle _objc = ctypes.PyDLL(objc._objc.__file__) _objc.PyObjCObject_New.restype = ctypes.py_object _objc.PyObjCObject_New.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] def _wrap_value(value): """Converts a pointer to a *Python objc* value. :param value: The pointer to convert. :return: a wrapped value """ return _objc.PyObjCObject_New(value, 0, 1) @contextlib.contextmanager def _wrapped(value): """A context manager that converts a raw pointer to a *Python objc* value. When the block is exited, the value is released. :param value: The raw value to wrap. """ wrapped_value = _wrap_value(value) try: yield value finally: CoreFoundation.CFRelease(wrapped_value) class CarbonExtra(object): """A class exposing some missing functionality from *Carbon* as class attributes. """ _Carbon = ctypes.cdll.LoadLibrary(ctypes.util.find_library('Carbon')) _Carbon.TISCopyCurrentKeyboardInputSource.argtypes = [] _Carbon.TISCopyCurrentKeyboardInputSource.restype = ctypes.c_void_p _Carbon.TISGetInputSourceProperty.argtypes = [ ctypes.c_void_p, ctypes.c_void_p] _Carbon.TISGetInputSourceProperty.restype = ctypes.c_void_p _Carbon.LMGetKbdType.argtypes = [] _Carbon.LMGetKbdType.restype = ctypes.c_uint32 _Carbon.UCKeyTranslate.argtypes = [ ctypes.c_void_p, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint32, ctypes.c_uint32, ctypes.c_uint32, ctypes.POINTER(ctypes.c_uint32), ctypes.c_uint8, ctypes.POINTER(ctypes.c_uint8), ctypes.c_uint16 * 4] _Carbon.UCKeyTranslate.restype = ctypes.c_uint32 TISCopyCurrentKeyboardInputSource = \ _Carbon.TISCopyCurrentKeyboardInputSource kTISPropertyUnicodeKeyLayoutData = ctypes.c_void_p.in_dll( _Carbon, 'kTISPropertyUnicodeKeyLayoutData') TISGetInputSourceProperty = \ _Carbon.TISGetInputSourceProperty LMGetKbdType = \ _Carbon.LMGetKbdType kUCKeyActionDisplay = 3 kUCKeyTranslateNoDeadKeysBit = 0 UCKeyTranslate = \ _Carbon.UCKeyTranslate def get_unicode_to_keycode_map(): LENGTH = 4 with _wrapped(CarbonExtra.TISCopyCurrentKeyboardInputSource()) as keyboard: keyboard_type = CarbonExtra.LMGetKbdType() layout = _wrap_value(CarbonExtra.TISGetInputSourceProperty( keyboard, CarbonExtra.kTISPropertyUnicodeKeyLayoutData)) data = layout.bytes().tobytes() def keycode_to_string(keycode): dead_key_state = ctypes.c_uint32() length = ctypes.c_uint8() unicode_string = (ctypes.c_uint16 * LENGTH)() CarbonExtra.UCKeyTranslate( data, keycode, CarbonExtra.kUCKeyActionDisplay, 0, keyboard_type, CarbonExtra.kUCKeyTranslateNoDeadKeysBit, ctypes.byref(dead_key_state), LENGTH, ctypes.byref(length), unicode_string) return u''.join( six.unichr(unicode_string[i]) for i in range(length.value)) return { keycode_to_string(keycode): keycode for keycode in range(128)} PK2Hݣ6 pynput/_util/xorg.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import itertools import Xlib.display import Xlib.XK from .xorg_keysyms import * # Create a display to verify that we have an X connection display = Xlib.display.Display() display.close() del display class X11Error(Exception): """An error that is thrown at the end of a code block managed by a :func:`display_manager` if an *X11* error occurred. """ pass def display_manager(display): """Traps *X* errors and raises an :class:``X11Error`` at the end if any error occurred. This handler also ensures that the :class:`Xlib.display.Display` being managed is sync'd. :param Xlib.display.Display display: The *X* display. :return: the display :rtype: Xlib.display.Display """ from contextlib import contextmanager @contextmanager def manager(): errors = [] def handler(*args): errors.append(args) old_handler = display.set_error_handler(handler) yield display display.sync() display.set_error_handler(old_handler) if errors: raise X11Error(errors) return manager() def _find_mask(display, symbol): """Returns the mode flags to use for a modiofier symbol. """ # Get the key code for the symbol modifier_keycode = display.keysym_to_keycode( Xlib.XK.string_to_keysym(symbol)) for index, keycodes in enumerate(display.get_modifier_mapping()): for keycode in keycodes: if keycode == modifier_keycode: return 1 << index return 0 def alt_mask(display): """Returns the *alt* mask flags. """ return _find_mask(display, 'Alt_L') def alt_gr_mask(display): """Returns the *alt* mask flags. """ return _find_mask(display, 'Mode_switch') def keysym_is_latin_upper(keysym): """Determines whether a *keysym* is an upper case *latin* character. """ return Xlib.XK.XK_A <= keysym <= Xlib.XK.XK_Z def keysym_is_latin_lower(keysym): """Determines whether a *keysym* is a lower case *latin* character. """ return Xlib.XK.XK_a <= keysym <= Xlib.XK.XK_z def keysym_group(a, b): """Generates a group from two *keysyms*. The implementation of this function comes from: Within each group, if the second element of the group is ``NoSymbol``, then the group should be treated as if the second element were the same as the first element, except when the first element is an alphabetic *KeySym* ``K`` for which both lowercase and uppercase forms are defined. In that case, the group should be treated as if the first element were the lowercase form of ``K`` and the second element were the uppercase form of ``K``. This function assumes that *alphabetic* means *latin*; this assumption appears to be consistent with observations of the return values from ``XGetKeyboardMapping``. :param a: The first *keysym*. :param b: The second *keysym*. :return: a tuple conforming to the description above """ if b == Xlib.XK.NoSymbol: if keysym_is_latin_upper(a): return (Xlib.XK.XK_a + a - Xlib.XK.XK_A, a) elif keysym_is_latin_lower(a): return (a, Xlib.XK.XK_A + a - Xlib.XK.XK_a) else: return (a, a) else: return (a, b) def keysym_normalize(keysym): """Normalises a list of *keysyms*. The implementation of this function comes from: If the list (ignoring trailing ``NoSymbol`` entries) is a single *KeySym* ``K``, then the list is treated as if it were the list ``K NoSymbol K NoSymbol``. If the list (ignoring trailing ``NoSymbol`` entries) is a pair of *KeySyms* ``K1 K2``, then the list is treated as if it were the list ``K1 K2 K1 K2``. If the list (ignoring trailing ``NoSymbol`` entries) is a triple of *KeySyms* ``K1 K2 K3``, then the list is treated as if it were the list ``K1 K2 K3 NoSymbol``. This function will also group the *keysyms* using :func:`keysym_group`. :param keysyms: A list of keysyms. :return: the tuple ``(group_1, group_2)`` or ``None`` """ # Remove trailing NoSymbol stripped = list(reversed(list( itertools.dropwhile( lambda n: n == Xlib.XK.NoSymbol, reversed(keysym))))) if not stripped: return elif len(stripped) == 1: return ( keysym_group(stripped[0], Xlib.XK.NoSymbol), keysym_group(stripped[0], Xlib.XK.NoSymbol)) elif len(stripped) == 2: return ( keysym_group(stripped[0], stripped[1]), keysym_group(stripped[0], stripped[1])) elif len(stripped) == 3: return ( keysym_group(stripped[0], stripped[1]), keysym_group(stripped[2], Xlib.XK.NoSymbol)) elif len(stripped) >= 6: # TODO: Find out why this is necessary; using only the documented # behaviour may lead to only a US layout being used? return ( keysym_group(stripped[0], stripped[1]), keysym_group(stripped[4], stripped[5])) else: return ( keysym_group(stripped[0], stripped[1]), keysym_group(stripped[2], stripped[3])) def index_to_shift(display, index): """Converts an index in a *key code* list to the corresponding shift state. :param Xlib.display.Display display: The display for which to retrieve the shift mask. :param int index: The keyboard mapping *key code* index. :retur: a shift mask """ return 0 \ | 1 << 0 if index & 1 else 0 \ | alt_gr_mask(display) if index & 2 else 0 def keyboard_mapping(display): """Generates a mapping from *keysyms* to *key codes* and required modifier shift states. :param Xlib.display.Display display: The display for which to retrieve the keyboard mapping. :return: the keyboard mapping """ mapping = {} shift_mask = 1 << 0 group_mask = alt_gr_mask(display) # Iterate over all keysym lists in the keyboard mapping min_keycode = display.display.info.min_keycode keycode_count = display.display.info.max_keycode - min_keycode + 1 for index, keysyms in enumerate(display.get_keyboard_mapping( min_keycode, keycode_count)): key_code = index + display.display.info.min_keycode # Normalise the keysym list to yield a tuple containing the two groups normalized = keysym_normalize(keysyms) if not normalized: continue # Iterate over the groups to extract the shift and modifier state for groups, group in zip(normalized, (False, True)): for keysym, shift in zip(groups, (False, True)): if not keysym: continue shift_state = 0 \ | (shift_mask if shift else 0) \ | (group_mask if group else 0) if keysym in mapping and mapping[keysym][1] < shift_state: continue mapping[keysym] = (key_code, shift_state) return mapping def symbol_to_keysym(symbol): """Converts a symbol name to a *keysym*. :param str symbol: The name of the symbol. :return: the corresponding *keysym*, or ``0`` if it cannot be found """ # First try simple translation keysym = Xlib.XK.string_to_keysym(symbol) if keysym: return keysym # If that fails, try checking a module attribute of Xlib.keysymdef.xkb if not keysym: try: return getattr(Xlib.keysymdef.xkb, 'XK_' + symbol, 0) except: return SYMBOLS.get(symbol, (0,))[0] PKG7 '..pynput/_util/xorg_keysyms.py# coding: utf-8 # Copyright 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . SYMBOLS = { 'dead_grave': (0xfe50, u'\u0300'), 'dead_acute': (0xfe51, u'\u0301'), 'dead_circumflex': (0xfe52, u'\u0302'), 'dead_tilde': (0xfe53, u'\u0303'), 'dead_macron': (0xfe54, u'\u0304'), 'dead_breve': (0xfe55, u'\u0306'), 'dead_abovedot': (0xfe56, u'\u0307'), 'dead_diaeresis': (0xfe57, u'\u0308'), 'dead_abovering': (0xfe58, u'\u030A'), 'dead_doubleacute': (0xfe59, u'\u030B'), 'dead_caron': (0xfe5a, u'\u030C'), 'dead_cedilla': (0xfe5b, u'\u0327'), 'dead_ogonek': (0xfe5c, u'\u0328'), 'dead_iota': (0xfe5d, u'\u0345'), 'dead_voiced_sound': (0xfe5e, None), 'dead_semivoiced_sound': (0xfe5f, None), 'dead_belowdot': (0xfe60, u'\u0323'), 'dead_hook': (0xfe61, u'\u0309'), 'dead_horn': (0xfe62, u'\u031B'), 'dead_stroke': (0xfe63, u'\u0335'), 'dead_abovecomma': (0xfe64, u'\u0315'), 'dead_abovereversedcomma': (0xfe65, u'\u0312'), 'dead_doublegrave': (0xfe66, u'\u030F'), 'dead_belowring': (0xfe67, u'\u0325'), 'dead_belowmacron': (0xfe68, u'\u0331'), 'dead_belowcircumflex': (0xfe69, u'\u032D'), 'dead_belowtilde': (0xfe6a, u'\u0330'), 'dead_belowbreve': (0xfe6b, u'\u032E'), 'dead_belowdiaeresis': (0xfe6c, u'\u0324'), 'dead_invertedbreve': (0xfe6d, u'\u032F'), 'dead_belowcomma': (0xfe6e, u'\u0326'), 'dead_currency': (0xfe6f, None), 'dead_lowline': (0xfe90, u'\u0332'), 'dead_aboveverticalline': (0xfe91, u'\u030D'), 'dead_belowverticalline': (0xfe92, u'\u0329'), 'dead_longsolidusoverlay': (0xfe93, u'\u0338'), 'dead_a': (0xfe80, None), 'dead_A': (0xfe81, None), 'dead_e': (0xfe82, None), 'dead_E': (0xfe83, None), 'dead_i': (0xfe84, None), 'dead_I': (0xfe85, None), 'dead_o': (0xfe86, None), 'dead_O': (0xfe87, None), 'dead_u': (0xfe88, None), 'dead_U': (0xfe89, None), 'dead_small_schwa': (0xfe8a, None), 'dead_capital_schwa': (0xfe8b, None), 'dead_greek': (0xfe8c, None), 'space': (0x0020, u'\u0020'), 'exclam': (0x0021, u'\u0021'), 'quotedbl': (0x0022, u'\u0022'), 'numbersign': (0x0023, u'\u0023'), 'dollar': (0x0024, u'\u0024'), 'percent': (0x0025, u'\u0025'), 'ampersand': (0x0026, u'\u0026'), 'apostrophe': (0x0027, u'\u0027'), 'parenleft': (0x0028, u'\u0028'), 'parenright': (0x0029, u'\u0029'), 'asterisk': (0x002a, u'\u002A'), 'plus': (0x002b, u'\u002B'), 'comma': (0x002c, u'\u002C'), 'minus': (0x002d, u'\u002D'), 'period': (0x002e, u'\u002E'), 'slash': (0x002f, u'\u002F'), '0': (0x0030, u'\u0030'), '1': (0x0031, u'\u0031'), '2': (0x0032, u'\u0032'), '3': (0x0033, u'\u0033'), '4': (0x0034, u'\u0034'), '5': (0x0035, u'\u0035'), '6': (0x0036, u'\u0036'), '7': (0x0037, u'\u0037'), '8': (0x0038, u'\u0038'), '9': (0x0039, u'\u0039'), 'colon': (0x003a, u'\u003A'), 'semicolon': (0x003b, u'\u003B'), 'less': (0x003c, u'\u003C'), 'equal': (0x003d, u'\u003D'), 'greater': (0x003e, u'\u003E'), 'question': (0x003f, u'\u003F'), 'at': (0x0040, u'\u0040'), 'A': (0x0041, u'\u0041'), 'B': (0x0042, u'\u0042'), 'C': (0x0043, u'\u0043'), 'D': (0x0044, u'\u0044'), 'E': (0x0045, u'\u0045'), 'F': (0x0046, u'\u0046'), 'G': (0x0047, u'\u0047'), 'H': (0x0048, u'\u0048'), 'I': (0x0049, u'\u0049'), 'J': (0x004a, u'\u004A'), 'K': (0x004b, u'\u004B'), 'L': (0x004c, u'\u004C'), 'M': (0x004d, u'\u004D'), 'N': (0x004e, u'\u004E'), 'O': (0x004f, u'\u004F'), 'P': (0x0050, u'\u0050'), 'Q': (0x0051, u'\u0051'), 'R': (0x0052, u'\u0052'), 'S': (0x0053, u'\u0053'), 'T': (0x0054, u'\u0054'), 'U': (0x0055, u'\u0055'), 'V': (0x0056, u'\u0056'), 'W': (0x0057, u'\u0057'), 'X': (0x0058, u'\u0058'), 'Y': (0x0059, u'\u0059'), 'Z': (0x005a, u'\u005A'), 'bracketleft': (0x005b, u'\u005B'), 'backslash': (0x005c, u'\u005C'), 'bracketright': (0x005d, u'\u005D'), 'asciicircum': (0x005e, u'\u005E'), 'underscore': (0x005f, u'\u005F'), 'grave': (0x0060, u'\u0060'), 'a': (0x0061, u'\u0061'), 'b': (0x0062, u'\u0062'), 'c': (0x0063, u'\u0063'), 'd': (0x0064, u'\u0064'), 'e': (0x0065, u'\u0065'), 'f': (0x0066, u'\u0066'), 'g': (0x0067, u'\u0067'), 'h': (0x0068, u'\u0068'), 'i': (0x0069, u'\u0069'), 'j': (0x006a, u'\u006A'), 'k': (0x006b, u'\u006B'), 'l': (0x006c, u'\u006C'), 'm': (0x006d, u'\u006D'), 'n': (0x006e, u'\u006E'), 'o': (0x006f, u'\u006F'), 'p': (0x0070, u'\u0070'), 'q': (0x0071, u'\u0071'), 'r': (0x0072, u'\u0072'), 's': (0x0073, u'\u0073'), 't': (0x0074, u'\u0074'), 'u': (0x0075, u'\u0075'), 'v': (0x0076, u'\u0076'), 'w': (0x0077, u'\u0077'), 'x': (0x0078, u'\u0078'), 'y': (0x0079, u'\u0079'), 'z': (0x007a, u'\u007A'), 'braceleft': (0x007b, u'\u007B'), 'bar': (0x007c, u'\u007C'), 'braceright': (0x007d, u'\u007D'), 'asciitilde': (0x007e, u'\u007E'), 'nobreakspace': (0x00a0, u'\u00A0'), 'exclamdown': (0x00a1, u'\u00A1'), 'cent': (0x00a2, u'\u00A2'), 'sterling': (0x00a3, u'\u00A3'), 'currency': (0x00a4, u'\u00A4'), 'yen': (0x00a5, u'\u00A5'), 'brokenbar': (0x00a6, u'\u00A6'), 'section': (0x00a7, u'\u00A7'), 'diaeresis': (0x00a8, u'\u00A8'), 'copyright': (0x00a9, u'\u00A9'), 'ordfeminine': (0x00aa, u'\u00AA'), 'guillemotleft': (0x00ab, u'\u00AB'), 'notsign': (0x00ac, u'\u00AC'), 'hyphen': (0x00ad, u'\u00AD'), 'registered': (0x00ae, u'\u00AE'), 'macron': (0x00af, u'\u00AF'), 'degree': (0x00b0, u'\u00B0'), 'plusminus': (0x00b1, u'\u00B1'), 'twosuperior': (0x00b2, u'\u00B2'), 'threesuperior': (0x00b3, u'\u00B3'), 'acute': (0x00b4, u'\u00B4'), 'mu': (0x00b5, u'\u00B5'), 'paragraph': (0x00b6, u'\u00B6'), 'periodcentered': (0x00b7, u'\u00B7'), 'cedilla': (0x00b8, u'\u00B8'), 'onesuperior': (0x00b9, u'\u00B9'), 'masculine': (0x00ba, u'\u00BA'), 'guillemotright': (0x00bb, u'\u00BB'), 'onequarter': (0x00bc, u'\u00BC'), 'onehalf': (0x00bd, u'\u00BD'), 'threequarters': (0x00be, u'\u00BE'), 'questiondown': (0x00bf, u'\u00BF'), 'Agrave': (0x00c0, u'\u00C0'), 'Aacute': (0x00c1, u'\u00C1'), 'Acircumflex': (0x00c2, u'\u00C2'), 'Atilde': (0x00c3, u'\u00C3'), 'Adiaeresis': (0x00c4, u'\u00C4'), 'Aring': (0x00c5, u'\u00C5'), 'AE': (0x00c6, u'\u00C6'), 'Ccedilla': (0x00c7, u'\u00C7'), 'Egrave': (0x00c8, u'\u00C8'), 'Eacute': (0x00c9, u'\u00C9'), 'Ecircumflex': (0x00ca, u'\u00CA'), 'Ediaeresis': (0x00cb, u'\u00CB'), 'Igrave': (0x00cc, u'\u00CC'), 'Iacute': (0x00cd, u'\u00CD'), 'Icircumflex': (0x00ce, u'\u00CE'), 'Idiaeresis': (0x00cf, u'\u00CF'), 'ETH': (0x00d0, u'\u00D0'), 'Ntilde': (0x00d1, u'\u00D1'), 'Ograve': (0x00d2, u'\u00D2'), 'Oacute': (0x00d3, u'\u00D3'), 'Ocircumflex': (0x00d4, u'\u00D4'), 'Otilde': (0x00d5, u'\u00D5'), 'Odiaeresis': (0x00d6, u'\u00D6'), 'multiply': (0x00d7, u'\u00D7'), 'Oslash': (0x00d8, u'\u00D8'), 'Ooblique': (0x00d8, u'\u00D8'), 'Ugrave': (0x00d9, u'\u00D9'), 'Uacute': (0x00da, u'\u00DA'), 'Ucircumflex': (0x00db, u'\u00DB'), 'Udiaeresis': (0x00dc, u'\u00DC'), 'Yacute': (0x00dd, u'\u00DD'), 'THORN': (0x00de, u'\u00DE'), 'ssharp': (0x00df, u'\u00DF'), 'agrave': (0x00e0, u'\u00E0'), 'aacute': (0x00e1, u'\u00E1'), 'acircumflex': (0x00e2, u'\u00E2'), 'atilde': (0x00e3, u'\u00E3'), 'adiaeresis': (0x00e4, u'\u00E4'), 'aring': (0x00e5, u'\u00E5'), 'ae': (0x00e6, u'\u00E6'), 'ccedilla': (0x00e7, u'\u00E7'), 'egrave': (0x00e8, u'\u00E8'), 'eacute': (0x00e9, u'\u00E9'), 'ecircumflex': (0x00ea, u'\u00EA'), 'ediaeresis': (0x00eb, u'\u00EB'), 'igrave': (0x00ec, u'\u00EC'), 'iacute': (0x00ed, u'\u00ED'), 'icircumflex': (0x00ee, u'\u00EE'), 'idiaeresis': (0x00ef, u'\u00EF'), 'eth': (0x00f0, u'\u00F0'), 'ntilde': (0x00f1, u'\u00F1'), 'ograve': (0x00f2, u'\u00F2'), 'oacute': (0x00f3, u'\u00F3'), 'ocircumflex': (0x00f4, u'\u00F4'), 'otilde': (0x00f5, u'\u00F5'), 'odiaeresis': (0x00f6, u'\u00F6'), 'division': (0x00f7, u'\u00F7'), 'oslash': (0x00f8, u'\u00F8'), 'ooblique': (0x00f8, u'\u00F8'), 'ugrave': (0x00f9, u'\u00F9'), 'uacute': (0x00fa, u'\u00FA'), 'ucircumflex': (0x00fb, u'\u00FB'), 'udiaeresis': (0x00fc, u'\u00FC'), 'yacute': (0x00fd, u'\u00FD'), 'thorn': (0x00fe, u'\u00FE'), 'ydiaeresis': (0x00ff, u'\u00FF'), 'Aogonek': (0x01a1, u'\u0104'), 'breve': (0x01a2, u'\u02D8'), 'Lstroke': (0x01a3, u'\u0141'), 'Lcaron': (0x01a5, u'\u013D'), 'Sacute': (0x01a6, u'\u015A'), 'Scaron': (0x01a9, u'\u0160'), 'Scedilla': (0x01aa, u'\u015E'), 'Tcaron': (0x01ab, u'\u0164'), 'Zacute': (0x01ac, u'\u0179'), 'Zcaron': (0x01ae, u'\u017D'), 'Zabovedot': (0x01af, u'\u017B'), 'aogonek': (0x01b1, u'\u0105'), 'ogonek': (0x01b2, u'\u02DB'), 'lstroke': (0x01b3, u'\u0142'), 'lcaron': (0x01b5, u'\u013E'), 'sacute': (0x01b6, u'\u015B'), 'caron': (0x01b7, u'\u02C7'), 'scaron': (0x01b9, u'\u0161'), 'scedilla': (0x01ba, u'\u015F'), 'tcaron': (0x01bb, u'\u0165'), 'zacute': (0x01bc, u'\u017A'), 'doubleacute': (0x01bd, u'\u02DD'), 'zcaron': (0x01be, u'\u017E'), 'zabovedot': (0x01bf, u'\u017C'), 'Racute': (0x01c0, u'\u0154'), 'Abreve': (0x01c3, u'\u0102'), 'Lacute': (0x01c5, u'\u0139'), 'Cacute': (0x01c6, u'\u0106'), 'Ccaron': (0x01c8, u'\u010C'), 'Eogonek': (0x01ca, u'\u0118'), 'Ecaron': (0x01cc, u'\u011A'), 'Dcaron': (0x01cf, u'\u010E'), 'Dstroke': (0x01d0, u'\u0110'), 'Nacute': (0x01d1, u'\u0143'), 'Ncaron': (0x01d2, u'\u0147'), 'Odoubleacute': (0x01d5, u'\u0150'), 'Rcaron': (0x01d8, u'\u0158'), 'Uring': (0x01d9, u'\u016E'), 'Udoubleacute': (0x01db, u'\u0170'), 'Tcedilla': (0x01de, u'\u0162'), 'racute': (0x01e0, u'\u0155'), 'abreve': (0x01e3, u'\u0103'), 'lacute': (0x01e5, u'\u013A'), 'cacute': (0x01e6, u'\u0107'), 'ccaron': (0x01e8, u'\u010D'), 'eogonek': (0x01ea, u'\u0119'), 'ecaron': (0x01ec, u'\u011B'), 'dcaron': (0x01ef, u'\u010F'), 'dstroke': (0x01f0, u'\u0111'), 'nacute': (0x01f1, u'\u0144'), 'ncaron': (0x01f2, u'\u0148'), 'odoubleacute': (0x01f5, u'\u0151'), 'rcaron': (0x01f8, u'\u0159'), 'uring': (0x01f9, u'\u016F'), 'udoubleacute': (0x01fb, u'\u0171'), 'tcedilla': (0x01fe, u'\u0163'), 'abovedot': (0x01ff, u'\u02D9'), 'Hstroke': (0x02a1, u'\u0126'), 'Hcircumflex': (0x02a6, u'\u0124'), 'Iabovedot': (0x02a9, u'\u0130'), 'Gbreve': (0x02ab, u'\u011E'), 'Jcircumflex': (0x02ac, u'\u0134'), 'hstroke': (0x02b1, u'\u0127'), 'hcircumflex': (0x02b6, u'\u0125'), 'idotless': (0x02b9, u'\u0131'), 'gbreve': (0x02bb, u'\u011F'), 'jcircumflex': (0x02bc, u'\u0135'), 'Cabovedot': (0x02c5, u'\u010A'), 'Ccircumflex': (0x02c6, u'\u0108'), 'Gabovedot': (0x02d5, u'\u0120'), 'Gcircumflex': (0x02d8, u'\u011C'), 'Ubreve': (0x02dd, u'\u016C'), 'Scircumflex': (0x02de, u'\u015C'), 'cabovedot': (0x02e5, u'\u010B'), 'ccircumflex': (0x02e6, u'\u0109'), 'gabovedot': (0x02f5, u'\u0121'), 'gcircumflex': (0x02f8, u'\u011D'), 'ubreve': (0x02fd, u'\u016D'), 'scircumflex': (0x02fe, u'\u015D'), 'kra': (0x03a2, u'\u0138'), 'Rcedilla': (0x03a3, u'\u0156'), 'Itilde': (0x03a5, u'\u0128'), 'Lcedilla': (0x03a6, u'\u013B'), 'Emacron': (0x03aa, u'\u0112'), 'Gcedilla': (0x03ab, u'\u0122'), 'Tslash': (0x03ac, u'\u0166'), 'rcedilla': (0x03b3, u'\u0157'), 'itilde': (0x03b5, u'\u0129'), 'lcedilla': (0x03b6, u'\u013C'), 'emacron': (0x03ba, u'\u0113'), 'gcedilla': (0x03bb, u'\u0123'), 'tslash': (0x03bc, u'\u0167'), 'ENG': (0x03bd, u'\u014A'), 'eng': (0x03bf, u'\u014B'), 'Amacron': (0x03c0, u'\u0100'), 'Iogonek': (0x03c7, u'\u012E'), 'Eabovedot': (0x03cc, u'\u0116'), 'Imacron': (0x03cf, u'\u012A'), 'Ncedilla': (0x03d1, u'\u0145'), 'Omacron': (0x03d2, u'\u014C'), 'Kcedilla': (0x03d3, u'\u0136'), 'Uogonek': (0x03d9, u'\u0172'), 'Utilde': (0x03dd, u'\u0168'), 'Umacron': (0x03de, u'\u016A'), 'amacron': (0x03e0, u'\u0101'), 'iogonek': (0x03e7, u'\u012F'), 'eabovedot': (0x03ec, u'\u0117'), 'imacron': (0x03ef, u'\u012B'), 'ncedilla': (0x03f1, u'\u0146'), 'omacron': (0x03f2, u'\u014D'), 'kcedilla': (0x03f3, u'\u0137'), 'uogonek': (0x03f9, u'\u0173'), 'utilde': (0x03fd, u'\u0169'), 'umacron': (0x03fe, u'\u016B'), 'Wcircumflex': (0x1000174, u'\u0174'), 'wcircumflex': (0x1000175, u'\u0175'), 'Ycircumflex': (0x1000176, u'\u0176'), 'ycircumflex': (0x1000177, u'\u0177'), 'Babovedot': (0x1001e02, u'\u1E02'), 'babovedot': (0x1001e03, u'\u1E03'), 'Dabovedot': (0x1001e0a, u'\u1E0A'), 'dabovedot': (0x1001e0b, u'\u1E0B'), 'Fabovedot': (0x1001e1e, u'\u1E1E'), 'fabovedot': (0x1001e1f, u'\u1E1F'), 'Mabovedot': (0x1001e40, u'\u1E40'), 'mabovedot': (0x1001e41, u'\u1E41'), 'Pabovedot': (0x1001e56, u'\u1E56'), 'pabovedot': (0x1001e57, u'\u1E57'), 'Sabovedot': (0x1001e60, u'\u1E60'), 'sabovedot': (0x1001e61, u'\u1E61'), 'Tabovedot': (0x1001e6a, u'\u1E6A'), 'tabovedot': (0x1001e6b, u'\u1E6B'), 'Wgrave': (0x1001e80, u'\u1E80'), 'wgrave': (0x1001e81, u'\u1E81'), 'Wacute': (0x1001e82, u'\u1E82'), 'wacute': (0x1001e83, u'\u1E83'), 'Wdiaeresis': (0x1001e84, u'\u1E84'), 'wdiaeresis': (0x1001e85, u'\u1E85'), 'Ygrave': (0x1001ef2, u'\u1EF2'), 'ygrave': (0x1001ef3, u'\u1EF3'), 'OE': (0x13bc, u'\u0152'), 'oe': (0x13bd, u'\u0153'), 'Ydiaeresis': (0x13be, u'\u0178'), 'overline': (0x047e, u'\u203E'), 'kana_fullstop': (0x04a1, u'\u3002'), 'kana_openingbracket': (0x04a2, u'\u300C'), 'kana_closingbracket': (0x04a3, u'\u300D'), 'kana_comma': (0x04a4, u'\u3001'), 'kana_conjunctive': (0x04a5, u'\u30FB'), 'kana_WO': (0x04a6, u'\u30F2'), 'kana_a': (0x04a7, u'\u30A1'), 'kana_i': (0x04a8, u'\u30A3'), 'kana_u': (0x04a9, u'\u30A5'), 'kana_e': (0x04aa, u'\u30A7'), 'kana_o': (0x04ab, u'\u30A9'), 'kana_ya': (0x04ac, u'\u30E3'), 'kana_yu': (0x04ad, u'\u30E5'), 'kana_yo': (0x04ae, u'\u30E7'), 'kana_tsu': (0x04af, u'\u30C3'), 'prolongedsound': (0x04b0, u'\u30FC'), 'kana_A': (0x04b1, u'\u30A2'), 'kana_I': (0x04b2, u'\u30A4'), 'kana_U': (0x04b3, u'\u30A6'), 'kana_E': (0x04b4, u'\u30A8'), 'kana_O': (0x04b5, u'\u30AA'), 'kana_KA': (0x04b6, u'\u30AB'), 'kana_KI': (0x04b7, u'\u30AD'), 'kana_KU': (0x04b8, u'\u30AF'), 'kana_KE': (0x04b9, u'\u30B1'), 'kana_KO': (0x04ba, u'\u30B3'), 'kana_SA': (0x04bb, u'\u30B5'), 'kana_SHI': (0x04bc, u'\u30B7'), 'kana_SU': (0x04bd, u'\u30B9'), 'kana_SE': (0x04be, u'\u30BB'), 'kana_SO': (0x04bf, u'\u30BD'), 'kana_TA': (0x04c0, u'\u30BF'), 'kana_CHI': (0x04c1, u'\u30C1'), 'kana_TSU': (0x04c2, u'\u30C4'), 'kana_TE': (0x04c3, u'\u30C6'), 'kana_TO': (0x04c4, u'\u30C8'), 'kana_NA': (0x04c5, u'\u30CA'), 'kana_NI': (0x04c6, u'\u30CB'), 'kana_NU': (0x04c7, u'\u30CC'), 'kana_NE': (0x04c8, u'\u30CD'), 'kana_NO': (0x04c9, u'\u30CE'), 'kana_HA': (0x04ca, u'\u30CF'), 'kana_HI': (0x04cb, u'\u30D2'), 'kana_FU': (0x04cc, u'\u30D5'), 'kana_HE': (0x04cd, u'\u30D8'), 'kana_HO': (0x04ce, u'\u30DB'), 'kana_MA': (0x04cf, u'\u30DE'), 'kana_MI': (0x04d0, u'\u30DF'), 'kana_MU': (0x04d1, u'\u30E0'), 'kana_ME': (0x04d2, u'\u30E1'), 'kana_MO': (0x04d3, u'\u30E2'), 'kana_YA': (0x04d4, u'\u30E4'), 'kana_YU': (0x04d5, u'\u30E6'), 'kana_YO': (0x04d6, u'\u30E8'), 'kana_RA': (0x04d7, u'\u30E9'), 'kana_RI': (0x04d8, u'\u30EA'), 'kana_RU': (0x04d9, u'\u30EB'), 'kana_RE': (0x04da, u'\u30EC'), 'kana_RO': (0x04db, u'\u30ED'), 'kana_WA': (0x04dc, u'\u30EF'), 'kana_N': (0x04dd, u'\u30F3'), 'voicedsound': (0x04de, u'\u309B'), 'semivoicedsound': (0x04df, u'\u309C'), 'Farsi_0': (0x10006f0, u'\u06F0'), 'Farsi_1': (0x10006f1, u'\u06F1'), 'Farsi_2': (0x10006f2, u'\u06F2'), 'Farsi_3': (0x10006f3, u'\u06F3'), 'Farsi_4': (0x10006f4, u'\u06F4'), 'Farsi_5': (0x10006f5, u'\u06F5'), 'Farsi_6': (0x10006f6, u'\u06F6'), 'Farsi_7': (0x10006f7, u'\u06F7'), 'Farsi_8': (0x10006f8, u'\u06F8'), 'Farsi_9': (0x10006f9, u'\u06F9'), 'Arabic_percent': (0x100066a, u'\u066A'), 'Arabic_superscript_alef': (0x1000670, u'\u0670'), 'Arabic_tteh': (0x1000679, u'\u0679'), 'Arabic_peh': (0x100067e, u'\u067E'), 'Arabic_tcheh': (0x1000686, u'\u0686'), 'Arabic_ddal': (0x1000688, u'\u0688'), 'Arabic_rreh': (0x1000691, u'\u0691'), 'Arabic_comma': (0x05ac, u'\u060C'), 'Arabic_fullstop': (0x10006d4, u'\u06D4'), 'Arabic_0': (0x1000660, u'\u0660'), 'Arabic_1': (0x1000661, u'\u0661'), 'Arabic_2': (0x1000662, u'\u0662'), 'Arabic_3': (0x1000663, u'\u0663'), 'Arabic_4': (0x1000664, u'\u0664'), 'Arabic_5': (0x1000665, u'\u0665'), 'Arabic_6': (0x1000666, u'\u0666'), 'Arabic_7': (0x1000667, u'\u0667'), 'Arabic_8': (0x1000668, u'\u0668'), 'Arabic_9': (0x1000669, u'\u0669'), 'Arabic_semicolon': (0x05bb, u'\u061B'), 'Arabic_question_mark': (0x05bf, u'\u061F'), 'Arabic_hamza': (0x05c1, u'\u0621'), 'Arabic_maddaonalef': (0x05c2, u'\u0622'), 'Arabic_hamzaonalef': (0x05c3, u'\u0623'), 'Arabic_hamzaonwaw': (0x05c4, u'\u0624'), 'Arabic_hamzaunderalef': (0x05c5, u'\u0625'), 'Arabic_hamzaonyeh': (0x05c6, u'\u0626'), 'Arabic_alef': (0x05c7, u'\u0627'), 'Arabic_beh': (0x05c8, u'\u0628'), 'Arabic_tehmarbuta': (0x05c9, u'\u0629'), 'Arabic_teh': (0x05ca, u'\u062A'), 'Arabic_theh': (0x05cb, u'\u062B'), 'Arabic_jeem': (0x05cc, u'\u062C'), 'Arabic_hah': (0x05cd, u'\u062D'), 'Arabic_khah': (0x05ce, u'\u062E'), 'Arabic_dal': (0x05cf, u'\u062F'), 'Arabic_thal': (0x05d0, u'\u0630'), 'Arabic_ra': (0x05d1, u'\u0631'), 'Arabic_zain': (0x05d2, u'\u0632'), 'Arabic_seen': (0x05d3, u'\u0633'), 'Arabic_sheen': (0x05d4, u'\u0634'), 'Arabic_sad': (0x05d5, u'\u0635'), 'Arabic_dad': (0x05d6, u'\u0636'), 'Arabic_tah': (0x05d7, u'\u0637'), 'Arabic_zah': (0x05d8, u'\u0638'), 'Arabic_ain': (0x05d9, u'\u0639'), 'Arabic_ghain': (0x05da, u'\u063A'), 'Arabic_tatweel': (0x05e0, u'\u0640'), 'Arabic_feh': (0x05e1, u'\u0641'), 'Arabic_qaf': (0x05e2, u'\u0642'), 'Arabic_kaf': (0x05e3, u'\u0643'), 'Arabic_lam': (0x05e4, u'\u0644'), 'Arabic_meem': (0x05e5, u'\u0645'), 'Arabic_noon': (0x05e6, u'\u0646'), 'Arabic_ha': (0x05e7, u'\u0647'), 'Arabic_waw': (0x05e8, u'\u0648'), 'Arabic_alefmaksura': (0x05e9, u'\u0649'), 'Arabic_yeh': (0x05ea, u'\u064A'), 'Arabic_fathatan': (0x05eb, u'\u064B'), 'Arabic_dammatan': (0x05ec, u'\u064C'), 'Arabic_kasratan': (0x05ed, u'\u064D'), 'Arabic_fatha': (0x05ee, u'\u064E'), 'Arabic_damma': (0x05ef, u'\u064F'), 'Arabic_kasra': (0x05f0, u'\u0650'), 'Arabic_shadda': (0x05f1, u'\u0651'), 'Arabic_sukun': (0x05f2, u'\u0652'), 'Arabic_madda_above': (0x1000653, u'\u0653'), 'Arabic_hamza_above': (0x1000654, u'\u0654'), 'Arabic_hamza_below': (0x1000655, u'\u0655'), 'Arabic_jeh': (0x1000698, u'\u0698'), 'Arabic_veh': (0x10006a4, u'\u06A4'), 'Arabic_keheh': (0x10006a9, u'\u06A9'), 'Arabic_gaf': (0x10006af, u'\u06AF'), 'Arabic_noon_ghunna': (0x10006ba, u'\u06BA'), 'Arabic_heh_doachashmee': (0x10006be, u'\u06BE'), 'Farsi_yeh': (0x10006cc, u'\u06CC'), 'Arabic_farsi_yeh': (0x10006cc, u'\u06CC'), 'Arabic_yeh_baree': (0x10006d2, u'\u06D2'), 'Arabic_heh_goal': (0x10006c1, u'\u06C1'), 'Cyrillic_GHE_bar': (0x1000492, u'\u0492'), 'Cyrillic_ghe_bar': (0x1000493, u'\u0493'), 'Cyrillic_ZHE_descender': (0x1000496, u'\u0496'), 'Cyrillic_zhe_descender': (0x1000497, u'\u0497'), 'Cyrillic_KA_descender': (0x100049a, u'\u049A'), 'Cyrillic_ka_descender': (0x100049b, u'\u049B'), 'Cyrillic_KA_vertstroke': (0x100049c, u'\u049C'), 'Cyrillic_ka_vertstroke': (0x100049d, u'\u049D'), 'Cyrillic_EN_descender': (0x10004a2, u'\u04A2'), 'Cyrillic_en_descender': (0x10004a3, u'\u04A3'), 'Cyrillic_U_straight': (0x10004ae, u'\u04AE'), 'Cyrillic_u_straight': (0x10004af, u'\u04AF'), 'Cyrillic_U_straight_bar': (0x10004b0, u'\u04B0'), 'Cyrillic_u_straight_bar': (0x10004b1, u'\u04B1'), 'Cyrillic_HA_descender': (0x10004b2, u'\u04B2'), 'Cyrillic_ha_descender': (0x10004b3, u'\u04B3'), 'Cyrillic_CHE_descender': (0x10004b6, u'\u04B6'), 'Cyrillic_che_descender': (0x10004b7, u'\u04B7'), 'Cyrillic_CHE_vertstroke': (0x10004b8, u'\u04B8'), 'Cyrillic_che_vertstroke': (0x10004b9, u'\u04B9'), 'Cyrillic_SHHA': (0x10004ba, u'\u04BA'), 'Cyrillic_shha': (0x10004bb, u'\u04BB'), 'Cyrillic_SCHWA': (0x10004d8, u'\u04D8'), 'Cyrillic_schwa': (0x10004d9, u'\u04D9'), 'Cyrillic_I_macron': (0x10004e2, u'\u04E2'), 'Cyrillic_i_macron': (0x10004e3, u'\u04E3'), 'Cyrillic_O_bar': (0x10004e8, u'\u04E8'), 'Cyrillic_o_bar': (0x10004e9, u'\u04E9'), 'Cyrillic_U_macron': (0x10004ee, u'\u04EE'), 'Cyrillic_u_macron': (0x10004ef, u'\u04EF'), 'Serbian_dje': (0x06a1, u'\u0452'), 'Macedonia_gje': (0x06a2, u'\u0453'), 'Cyrillic_io': (0x06a3, u'\u0451'), 'Ukrainian_ie': (0x06a4, u'\u0454'), 'Macedonia_dse': (0x06a5, u'\u0455'), 'Ukrainian_i': (0x06a6, u'\u0456'), 'Ukrainian_yi': (0x06a7, u'\u0457'), 'Cyrillic_je': (0x06a8, u'\u0458'), 'Cyrillic_lje': (0x06a9, u'\u0459'), 'Cyrillic_nje': (0x06aa, u'\u045A'), 'Serbian_tshe': (0x06ab, u'\u045B'), 'Macedonia_kje': (0x06ac, u'\u045C'), 'Ukrainian_ghe_with_upturn': (0x06ad, u'\u0491'), 'Byelorussian_shortu': (0x06ae, u'\u045E'), 'Cyrillic_dzhe': (0x06af, u'\u045F'), 'numerosign': (0x06b0, u'\u2116'), 'Serbian_DJE': (0x06b1, u'\u0402'), 'Macedonia_GJE': (0x06b2, u'\u0403'), 'Cyrillic_IO': (0x06b3, u'\u0401'), 'Ukrainian_IE': (0x06b4, u'\u0404'), 'Macedonia_DSE': (0x06b5, u'\u0405'), 'Ukrainian_I': (0x06b6, u'\u0406'), 'Ukrainian_YI': (0x06b7, u'\u0407'), 'Cyrillic_JE': (0x06b8, u'\u0408'), 'Cyrillic_LJE': (0x06b9, u'\u0409'), 'Cyrillic_NJE': (0x06ba, u'\u040A'), 'Serbian_TSHE': (0x06bb, u'\u040B'), 'Macedonia_KJE': (0x06bc, u'\u040C'), 'Ukrainian_GHE_WITH_UPTURN': (0x06bd, u'\u0490'), 'Byelorussian_SHORTU': (0x06be, u'\u040E'), 'Cyrillic_DZHE': (0x06bf, u'\u040F'), 'Cyrillic_yu': (0x06c0, u'\u044E'), 'Cyrillic_a': (0x06c1, u'\u0430'), 'Cyrillic_be': (0x06c2, u'\u0431'), 'Cyrillic_tse': (0x06c3, u'\u0446'), 'Cyrillic_de': (0x06c4, u'\u0434'), 'Cyrillic_ie': (0x06c5, u'\u0435'), 'Cyrillic_ef': (0x06c6, u'\u0444'), 'Cyrillic_ghe': (0x06c7, u'\u0433'), 'Cyrillic_ha': (0x06c8, u'\u0445'), 'Cyrillic_i': (0x06c9, u'\u0438'), 'Cyrillic_shorti': (0x06ca, u'\u0439'), 'Cyrillic_ka': (0x06cb, u'\u043A'), 'Cyrillic_el': (0x06cc, u'\u043B'), 'Cyrillic_em': (0x06cd, u'\u043C'), 'Cyrillic_en': (0x06ce, u'\u043D'), 'Cyrillic_o': (0x06cf, u'\u043E'), 'Cyrillic_pe': (0x06d0, u'\u043F'), 'Cyrillic_ya': (0x06d1, u'\u044F'), 'Cyrillic_er': (0x06d2, u'\u0440'), 'Cyrillic_es': (0x06d3, u'\u0441'), 'Cyrillic_te': (0x06d4, u'\u0442'), 'Cyrillic_u': (0x06d5, u'\u0443'), 'Cyrillic_zhe': (0x06d6, u'\u0436'), 'Cyrillic_ve': (0x06d7, u'\u0432'), 'Cyrillic_softsign': (0x06d8, u'\u044C'), 'Cyrillic_yeru': (0x06d9, u'\u044B'), 'Cyrillic_ze': (0x06da, u'\u0437'), 'Cyrillic_sha': (0x06db, u'\u0448'), 'Cyrillic_e': (0x06dc, u'\u044D'), 'Cyrillic_shcha': (0x06dd, u'\u0449'), 'Cyrillic_che': (0x06de, u'\u0447'), 'Cyrillic_hardsign': (0x06df, u'\u044A'), 'Cyrillic_YU': (0x06e0, u'\u042E'), 'Cyrillic_A': (0x06e1, u'\u0410'), 'Cyrillic_BE': (0x06e2, u'\u0411'), 'Cyrillic_TSE': (0x06e3, u'\u0426'), 'Cyrillic_DE': (0x06e4, u'\u0414'), 'Cyrillic_IE': (0x06e5, u'\u0415'), 'Cyrillic_EF': (0x06e6, u'\u0424'), 'Cyrillic_GHE': (0x06e7, u'\u0413'), 'Cyrillic_HA': (0x06e8, u'\u0425'), 'Cyrillic_I': (0x06e9, u'\u0418'), 'Cyrillic_SHORTI': (0x06ea, u'\u0419'), 'Cyrillic_KA': (0x06eb, u'\u041A'), 'Cyrillic_EL': (0x06ec, u'\u041B'), 'Cyrillic_EM': (0x06ed, u'\u041C'), 'Cyrillic_EN': (0x06ee, u'\u041D'), 'Cyrillic_O': (0x06ef, u'\u041E'), 'Cyrillic_PE': (0x06f0, u'\u041F'), 'Cyrillic_YA': (0x06f1, u'\u042F'), 'Cyrillic_ER': (0x06f2, u'\u0420'), 'Cyrillic_ES': (0x06f3, u'\u0421'), 'Cyrillic_TE': (0x06f4, u'\u0422'), 'Cyrillic_U': (0x06f5, u'\u0423'), 'Cyrillic_ZHE': (0x06f6, u'\u0416'), 'Cyrillic_VE': (0x06f7, u'\u0412'), 'Cyrillic_SOFTSIGN': (0x06f8, u'\u042C'), 'Cyrillic_YERU': (0x06f9, u'\u042B'), 'Cyrillic_ZE': (0x06fa, u'\u0417'), 'Cyrillic_SHA': (0x06fb, u'\u0428'), 'Cyrillic_E': (0x06fc, u'\u042D'), 'Cyrillic_SHCHA': (0x06fd, u'\u0429'), 'Cyrillic_CHE': (0x06fe, u'\u0427'), 'Cyrillic_HARDSIGN': (0x06ff, u'\u042A'), 'Greek_ALPHAaccent': (0x07a1, u'\u0386'), 'Greek_EPSILONaccent': (0x07a2, u'\u0388'), 'Greek_ETAaccent': (0x07a3, u'\u0389'), 'Greek_IOTAaccent': (0x07a4, u'\u038A'), 'Greek_IOTAdieresis': (0x07a5, u'\u03AA'), 'Greek_OMICRONaccent': (0x07a7, u'\u038C'), 'Greek_UPSILONaccent': (0x07a8, u'\u038E'), 'Greek_UPSILONdieresis': (0x07a9, u'\u03AB'), 'Greek_OMEGAaccent': (0x07ab, u'\u038F'), 'Greek_accentdieresis': (0x07ae, u'\u0385'), 'Greek_horizbar': (0x07af, u'\u2015'), 'Greek_alphaaccent': (0x07b1, u'\u03AC'), 'Greek_epsilonaccent': (0x07b2, u'\u03AD'), 'Greek_etaaccent': (0x07b3, u'\u03AE'), 'Greek_iotaaccent': (0x07b4, u'\u03AF'), 'Greek_iotadieresis': (0x07b5, u'\u03CA'), 'Greek_iotaaccentdieresis': (0x07b6, u'\u0390'), 'Greek_omicronaccent': (0x07b7, u'\u03CC'), 'Greek_upsilonaccent': (0x07b8, u'\u03CD'), 'Greek_upsilondieresis': (0x07b9, u'\u03CB'), 'Greek_upsilonaccentdieresis': (0x07ba, u'\u03B0'), 'Greek_omegaaccent': (0x07bb, u'\u03CE'), 'Greek_ALPHA': (0x07c1, u'\u0391'), 'Greek_BETA': (0x07c2, u'\u0392'), 'Greek_GAMMA': (0x07c3, u'\u0393'), 'Greek_DELTA': (0x07c4, u'\u0394'), 'Greek_EPSILON': (0x07c5, u'\u0395'), 'Greek_ZETA': (0x07c6, u'\u0396'), 'Greek_ETA': (0x07c7, u'\u0397'), 'Greek_THETA': (0x07c8, u'\u0398'), 'Greek_IOTA': (0x07c9, u'\u0399'), 'Greek_KAPPA': (0x07ca, u'\u039A'), 'Greek_LAMDA': (0x07cb, u'\u039B'), 'Greek_LAMBDA': (0x07cb, u'\u039B'), 'Greek_MU': (0x07cc, u'\u039C'), 'Greek_NU': (0x07cd, u'\u039D'), 'Greek_XI': (0x07ce, u'\u039E'), 'Greek_OMICRON': (0x07cf, u'\u039F'), 'Greek_PI': (0x07d0, u'\u03A0'), 'Greek_RHO': (0x07d1, u'\u03A1'), 'Greek_SIGMA': (0x07d2, u'\u03A3'), 'Greek_TAU': (0x07d4, u'\u03A4'), 'Greek_UPSILON': (0x07d5, u'\u03A5'), 'Greek_PHI': (0x07d6, u'\u03A6'), 'Greek_CHI': (0x07d7, u'\u03A7'), 'Greek_PSI': (0x07d8, u'\u03A8'), 'Greek_OMEGA': (0x07d9, u'\u03A9'), 'Greek_alpha': (0x07e1, u'\u03B1'), 'Greek_beta': (0x07e2, u'\u03B2'), 'Greek_gamma': (0x07e3, u'\u03B3'), 'Greek_delta': (0x07e4, u'\u03B4'), 'Greek_epsilon': (0x07e5, u'\u03B5'), 'Greek_zeta': (0x07e6, u'\u03B6'), 'Greek_eta': (0x07e7, u'\u03B7'), 'Greek_theta': (0x07e8, u'\u03B8'), 'Greek_iota': (0x07e9, u'\u03B9'), 'Greek_kappa': (0x07ea, u'\u03BA'), 'Greek_lamda': (0x07eb, u'\u03BB'), 'Greek_lambda': (0x07eb, u'\u03BB'), 'Greek_mu': (0x07ec, u'\u03BC'), 'Greek_nu': (0x07ed, u'\u03BD'), 'Greek_xi': (0x07ee, u'\u03BE'), 'Greek_omicron': (0x07ef, u'\u03BF'), 'Greek_pi': (0x07f0, u'\u03C0'), 'Greek_rho': (0x07f1, u'\u03C1'), 'Greek_sigma': (0x07f2, u'\u03C3'), 'Greek_finalsmallsigma': (0x07f3, u'\u03C2'), 'Greek_tau': (0x07f4, u'\u03C4'), 'Greek_upsilon': (0x07f5, u'\u03C5'), 'Greek_phi': (0x07f6, u'\u03C6'), 'Greek_chi': (0x07f7, u'\u03C7'), 'Greek_psi': (0x07f8, u'\u03C8'), 'Greek_omega': (0x07f9, u'\u03C9'), 'leftradical': (0x08a1, u'\u23B7'), 'topintegral': (0x08a4, u'\u2320'), 'botintegral': (0x08a5, u'\u2321'), 'topleftsqbracket': (0x08a7, u'\u23A1'), 'botleftsqbracket': (0x08a8, u'\u23A3'), 'toprightsqbracket': (0x08a9, u'\u23A4'), 'botrightsqbracket': (0x08aa, u'\u23A6'), 'topleftparens': (0x08ab, u'\u239B'), 'botleftparens': (0x08ac, u'\u239D'), 'toprightparens': (0x08ad, u'\u239E'), 'botrightparens': (0x08ae, u'\u23A0'), 'leftmiddlecurlybrace': (0x08af, u'\u23A8'), 'rightmiddlecurlybrace': (0x08b0, u'\u23AC'), 'lessthanequal': (0x08bc, u'\u2264'), 'notequal': (0x08bd, u'\u2260'), 'greaterthanequal': (0x08be, u'\u2265'), 'integral': (0x08bf, u'\u222B'), 'therefore': (0x08c0, u'\u2234'), 'variation': (0x08c1, u'\u221D'), 'infinity': (0x08c2, u'\u221E'), 'nabla': (0x08c5, u'\u2207'), 'approximate': (0x08c8, u'\u223C'), 'similarequal': (0x08c9, u'\u2243'), 'ifonlyif': (0x08cd, u'\u21D4'), 'implies': (0x08ce, u'\u21D2'), 'identical': (0x08cf, u'\u2261'), 'radical': (0x08d6, u'\u221A'), 'includedin': (0x08da, u'\u2282'), 'includes': (0x08db, u'\u2283'), 'intersection': (0x08dc, u'\u2229'), 'union': (0x08dd, u'\u222A'), 'logicaland': (0x08de, u'\u2227'), 'logicalor': (0x08df, u'\u2228'), 'partialderivative': (0x08ef, u'\u2202'), 'function': (0x08f6, u'\u0192'), 'leftarrow': (0x08fb, u'\u2190'), 'uparrow': (0x08fc, u'\u2191'), 'rightarrow': (0x08fd, u'\u2192'), 'downarrow': (0x08fe, u'\u2193'), 'soliddiamond': (0x09e0, u'\u25C6'), 'checkerboard': (0x09e1, u'\u2592'), 'ht': (0x09e2, u'\u2409'), 'ff': (0x09e3, u'\u240C'), 'cr': (0x09e4, u'\u240D'), 'lf': (0x09e5, u'\u240A'), 'nl': (0x09e8, u'\u2424'), 'vt': (0x09e9, u'\u240B'), 'lowrightcorner': (0x09ea, u'\u2518'), 'uprightcorner': (0x09eb, u'\u2510'), 'upleftcorner': (0x09ec, u'\u250C'), 'lowleftcorner': (0x09ed, u'\u2514'), 'crossinglines': (0x09ee, u'\u253C'), 'horizlinescan1': (0x09ef, u'\u23BA'), 'horizlinescan3': (0x09f0, u'\u23BB'), 'horizlinescan5': (0x09f1, u'\u2500'), 'horizlinescan7': (0x09f2, u'\u23BC'), 'horizlinescan9': (0x09f3, u'\u23BD'), 'leftt': (0x09f4, u'\u251C'), 'rightt': (0x09f5, u'\u2524'), 'bott': (0x09f6, u'\u2534'), 'topt': (0x09f7, u'\u252C'), 'vertbar': (0x09f8, u'\u2502'), 'emspace': (0x0aa1, u'\u2003'), 'enspace': (0x0aa2, u'\u2002'), 'em3space': (0x0aa3, u'\u2004'), 'em4space': (0x0aa4, u'\u2005'), 'digitspace': (0x0aa5, u'\u2007'), 'punctspace': (0x0aa6, u'\u2008'), 'thinspace': (0x0aa7, u'\u2009'), 'hairspace': (0x0aa8, u'\u200A'), 'emdash': (0x0aa9, u'\u2014'), 'endash': (0x0aaa, u'\u2013'), 'ellipsis': (0x0aae, u'\u2026'), 'doubbaselinedot': (0x0aaf, u'\u2025'), 'onethird': (0x0ab0, u'\u2153'), 'twothirds': (0x0ab1, u'\u2154'), 'onefifth': (0x0ab2, u'\u2155'), 'twofifths': (0x0ab3, u'\u2156'), 'threefifths': (0x0ab4, u'\u2157'), 'fourfifths': (0x0ab5, u'\u2158'), 'onesixth': (0x0ab6, u'\u2159'), 'fivesixths': (0x0ab7, u'\u215A'), 'careof': (0x0ab8, u'\u2105'), 'figdash': (0x0abb, u'\u2012'), 'oneeighth': (0x0ac3, u'\u215B'), 'threeeighths': (0x0ac4, u'\u215C'), 'fiveeighths': (0x0ac5, u'\u215D'), 'seveneighths': (0x0ac6, u'\u215E'), 'trademark': (0x0ac9, u'\u2122'), 'leftsinglequotemark': (0x0ad0, u'\u2018'), 'rightsinglequotemark': (0x0ad1, u'\u2019'), 'leftdoublequotemark': (0x0ad2, u'\u201C'), 'rightdoublequotemark': (0x0ad3, u'\u201D'), 'prescription': (0x0ad4, u'\u211E'), 'permille': (0x0ad5, u'\u2030'), 'minutes': (0x0ad6, u'\u2032'), 'seconds': (0x0ad7, u'\u2033'), 'latincross': (0x0ad9, u'\u271D'), 'club': (0x0aec, u'\u2663'), 'diamond': (0x0aed, u'\u2666'), 'heart': (0x0aee, u'\u2665'), 'maltesecross': (0x0af0, u'\u2720'), 'dagger': (0x0af1, u'\u2020'), 'doubledagger': (0x0af2, u'\u2021'), 'checkmark': (0x0af3, u'\u2713'), 'ballotcross': (0x0af4, u'\u2717'), 'musicalsharp': (0x0af5, u'\u266F'), 'musicalflat': (0x0af6, u'\u266D'), 'malesymbol': (0x0af7, u'\u2642'), 'femalesymbol': (0x0af8, u'\u2640'), 'telephone': (0x0af9, u'\u260E'), 'telephonerecorder': (0x0afa, u'\u2315'), 'phonographcopyright': (0x0afb, u'\u2117'), 'caret': (0x0afc, u'\u2038'), 'singlelowquotemark': (0x0afd, u'\u201A'), 'doublelowquotemark': (0x0afe, u'\u201E'), 'downtack': (0x0bc2, u'\u22A4'), 'downstile': (0x0bc4, u'\u230A'), 'jot': (0x0bca, u'\u2218'), 'quad': (0x0bcc, u'\u2395'), 'uptack': (0x0bce, u'\u22A5'), 'circle': (0x0bcf, u'\u25CB'), 'upstile': (0x0bd3, u'\u2308'), 'lefttack': (0x0bdc, u'\u22A3'), 'righttack': (0x0bfc, u'\u22A2'), 'hebrew_doublelowline': (0x0cdf, u'\u2017'), 'hebrew_aleph': (0x0ce0, u'\u05D0'), 'hebrew_bet': (0x0ce1, u'\u05D1'), 'hebrew_gimel': (0x0ce2, u'\u05D2'), 'hebrew_dalet': (0x0ce3, u'\u05D3'), 'hebrew_he': (0x0ce4, u'\u05D4'), 'hebrew_waw': (0x0ce5, u'\u05D5'), 'hebrew_zain': (0x0ce6, u'\u05D6'), 'hebrew_chet': (0x0ce7, u'\u05D7'), 'hebrew_tet': (0x0ce8, u'\u05D8'), 'hebrew_yod': (0x0ce9, u'\u05D9'), 'hebrew_finalkaph': (0x0cea, u'\u05DA'), 'hebrew_kaph': (0x0ceb, u'\u05DB'), 'hebrew_lamed': (0x0cec, u'\u05DC'), 'hebrew_finalmem': (0x0ced, u'\u05DD'), 'hebrew_mem': (0x0cee, u'\u05DE'), 'hebrew_finalnun': (0x0cef, u'\u05DF'), 'hebrew_nun': (0x0cf0, u'\u05E0'), 'hebrew_samech': (0x0cf1, u'\u05E1'), 'hebrew_ayin': (0x0cf2, u'\u05E2'), 'hebrew_finalpe': (0x0cf3, u'\u05E3'), 'hebrew_pe': (0x0cf4, u'\u05E4'), 'hebrew_finalzade': (0x0cf5, u'\u05E5'), 'hebrew_zade': (0x0cf6, u'\u05E6'), 'hebrew_qoph': (0x0cf7, u'\u05E7'), 'hebrew_resh': (0x0cf8, u'\u05E8'), 'hebrew_shin': (0x0cf9, u'\u05E9'), 'hebrew_taw': (0x0cfa, u'\u05EA'), 'Thai_kokai': (0x0da1, u'\u0E01'), 'Thai_khokhai': (0x0da2, u'\u0E02'), 'Thai_khokhuat': (0x0da3, u'\u0E03'), 'Thai_khokhwai': (0x0da4, u'\u0E04'), 'Thai_khokhon': (0x0da5, u'\u0E05'), 'Thai_khorakhang': (0x0da6, u'\u0E06'), 'Thai_ngongu': (0x0da7, u'\u0E07'), 'Thai_chochan': (0x0da8, u'\u0E08'), 'Thai_choching': (0x0da9, u'\u0E09'), 'Thai_chochang': (0x0daa, u'\u0E0A'), 'Thai_soso': (0x0dab, u'\u0E0B'), 'Thai_chochoe': (0x0dac, u'\u0E0C'), 'Thai_yoying': (0x0dad, u'\u0E0D'), 'Thai_dochada': (0x0dae, u'\u0E0E'), 'Thai_topatak': (0x0daf, u'\u0E0F'), 'Thai_thothan': (0x0db0, u'\u0E10'), 'Thai_thonangmontho': (0x0db1, u'\u0E11'), 'Thai_thophuthao': (0x0db2, u'\u0E12'), 'Thai_nonen': (0x0db3, u'\u0E13'), 'Thai_dodek': (0x0db4, u'\u0E14'), 'Thai_totao': (0x0db5, u'\u0E15'), 'Thai_thothung': (0x0db6, u'\u0E16'), 'Thai_thothahan': (0x0db7, u'\u0E17'), 'Thai_thothong': (0x0db8, u'\u0E18'), 'Thai_nonu': (0x0db9, u'\u0E19'), 'Thai_bobaimai': (0x0dba, u'\u0E1A'), 'Thai_popla': (0x0dbb, u'\u0E1B'), 'Thai_phophung': (0x0dbc, u'\u0E1C'), 'Thai_fofa': (0x0dbd, u'\u0E1D'), 'Thai_phophan': (0x0dbe, u'\u0E1E'), 'Thai_fofan': (0x0dbf, u'\u0E1F'), 'Thai_phosamphao': (0x0dc0, u'\u0E20'), 'Thai_moma': (0x0dc1, u'\u0E21'), 'Thai_yoyak': (0x0dc2, u'\u0E22'), 'Thai_rorua': (0x0dc3, u'\u0E23'), 'Thai_ru': (0x0dc4, u'\u0E24'), 'Thai_loling': (0x0dc5, u'\u0E25'), 'Thai_lu': (0x0dc6, u'\u0E26'), 'Thai_wowaen': (0x0dc7, u'\u0E27'), 'Thai_sosala': (0x0dc8, u'\u0E28'), 'Thai_sorusi': (0x0dc9, u'\u0E29'), 'Thai_sosua': (0x0dca, u'\u0E2A'), 'Thai_hohip': (0x0dcb, u'\u0E2B'), 'Thai_lochula': (0x0dcc, u'\u0E2C'), 'Thai_oang': (0x0dcd, u'\u0E2D'), 'Thai_honokhuk': (0x0dce, u'\u0E2E'), 'Thai_paiyannoi': (0x0dcf, u'\u0E2F'), 'Thai_saraa': (0x0dd0, u'\u0E30'), 'Thai_maihanakat': (0x0dd1, u'\u0E31'), 'Thai_saraaa': (0x0dd2, u'\u0E32'), 'Thai_saraam': (0x0dd3, u'\u0E33'), 'Thai_sarai': (0x0dd4, u'\u0E34'), 'Thai_saraii': (0x0dd5, u'\u0E35'), 'Thai_saraue': (0x0dd6, u'\u0E36'), 'Thai_sarauee': (0x0dd7, u'\u0E37'), 'Thai_sarau': (0x0dd8, u'\u0E38'), 'Thai_sarauu': (0x0dd9, u'\u0E39'), 'Thai_phinthu': (0x0dda, u'\u0E3A'), 'Thai_baht': (0x0ddf, u'\u0E3F'), 'Thai_sarae': (0x0de0, u'\u0E40'), 'Thai_saraae': (0x0de1, u'\u0E41'), 'Thai_sarao': (0x0de2, u'\u0E42'), 'Thai_saraaimaimuan': (0x0de3, u'\u0E43'), 'Thai_saraaimaimalai': (0x0de4, u'\u0E44'), 'Thai_lakkhangyao': (0x0de5, u'\u0E45'), 'Thai_maiyamok': (0x0de6, u'\u0E46'), 'Thai_maitaikhu': (0x0de7, u'\u0E47'), 'Thai_maiek': (0x0de8, u'\u0E48'), 'Thai_maitho': (0x0de9, u'\u0E49'), 'Thai_maitri': (0x0dea, u'\u0E4A'), 'Thai_maichattawa': (0x0deb, u'\u0E4B'), 'Thai_thanthakhat': (0x0dec, u'\u0E4C'), 'Thai_nikhahit': (0x0ded, u'\u0E4D'), 'Thai_leksun': (0x0df0, u'\u0E50'), 'Thai_leknung': (0x0df1, u'\u0E51'), 'Thai_leksong': (0x0df2, u'\u0E52'), 'Thai_leksam': (0x0df3, u'\u0E53'), 'Thai_leksi': (0x0df4, u'\u0E54'), 'Thai_lekha': (0x0df5, u'\u0E55'), 'Thai_lekhok': (0x0df6, u'\u0E56'), 'Thai_lekchet': (0x0df7, u'\u0E57'), 'Thai_lekpaet': (0x0df8, u'\u0E58'), 'Thai_lekkao': (0x0df9, u'\u0E59'), 'Armenian_ligature_ew': (0x1000587, u'\u0587'), 'Armenian_full_stop': (0x1000589, u'\u0589'), 'Armenian_verjaket': (0x1000589, u'\u0589'), 'Armenian_separation_mark': (0x100055d, u'\u055D'), 'Armenian_but': (0x100055d, u'\u055D'), 'Armenian_hyphen': (0x100058a, u'\u058A'), 'Armenian_yentamna': (0x100058a, u'\u058A'), 'Armenian_exclam': (0x100055c, u'\u055C'), 'Armenian_amanak': (0x100055c, u'\u055C'), 'Armenian_accent': (0x100055b, u'\u055B'), 'Armenian_shesht': (0x100055b, u'\u055B'), 'Armenian_question': (0x100055e, u'\u055E'), 'Armenian_paruyk': (0x100055e, u'\u055E'), 'Armenian_AYB': (0x1000531, u'\u0531'), 'Armenian_ayb': (0x1000561, u'\u0561'), 'Armenian_BEN': (0x1000532, u'\u0532'), 'Armenian_ben': (0x1000562, u'\u0562'), 'Armenian_GIM': (0x1000533, u'\u0533'), 'Armenian_gim': (0x1000563, u'\u0563'), 'Armenian_DA': (0x1000534, u'\u0534'), 'Armenian_da': (0x1000564, u'\u0564'), 'Armenian_YECH': (0x1000535, u'\u0535'), 'Armenian_yech': (0x1000565, u'\u0565'), 'Armenian_ZA': (0x1000536, u'\u0536'), 'Armenian_za': (0x1000566, u'\u0566'), 'Armenian_E': (0x1000537, u'\u0537'), 'Armenian_e': (0x1000567, u'\u0567'), 'Armenian_AT': (0x1000538, u'\u0538'), 'Armenian_at': (0x1000568, u'\u0568'), 'Armenian_TO': (0x1000539, u'\u0539'), 'Armenian_to': (0x1000569, u'\u0569'), 'Armenian_ZHE': (0x100053a, u'\u053A'), 'Armenian_zhe': (0x100056a, u'\u056A'), 'Armenian_INI': (0x100053b, u'\u053B'), 'Armenian_ini': (0x100056b, u'\u056B'), 'Armenian_LYUN': (0x100053c, u'\u053C'), 'Armenian_lyun': (0x100056c, u'\u056C'), 'Armenian_KHE': (0x100053d, u'\u053D'), 'Armenian_khe': (0x100056d, u'\u056D'), 'Armenian_TSA': (0x100053e, u'\u053E'), 'Armenian_tsa': (0x100056e, u'\u056E'), 'Armenian_KEN': (0x100053f, u'\u053F'), 'Armenian_ken': (0x100056f, u'\u056F'), 'Armenian_HO': (0x1000540, u'\u0540'), 'Armenian_ho': (0x1000570, u'\u0570'), 'Armenian_DZA': (0x1000541, u'\u0541'), 'Armenian_dza': (0x1000571, u'\u0571'), 'Armenian_GHAT': (0x1000542, u'\u0542'), 'Armenian_ghat': (0x1000572, u'\u0572'), 'Armenian_TCHE': (0x1000543, u'\u0543'), 'Armenian_tche': (0x1000573, u'\u0573'), 'Armenian_MEN': (0x1000544, u'\u0544'), 'Armenian_men': (0x1000574, u'\u0574'), 'Armenian_HI': (0x1000545, u'\u0545'), 'Armenian_hi': (0x1000575, u'\u0575'), 'Armenian_NU': (0x1000546, u'\u0546'), 'Armenian_nu': (0x1000576, u'\u0576'), 'Armenian_SHA': (0x1000547, u'\u0547'), 'Armenian_sha': (0x1000577, u'\u0577'), 'Armenian_VO': (0x1000548, u'\u0548'), 'Armenian_vo': (0x1000578, u'\u0578'), 'Armenian_CHA': (0x1000549, u'\u0549'), 'Armenian_cha': (0x1000579, u'\u0579'), 'Armenian_PE': (0x100054a, u'\u054A'), 'Armenian_pe': (0x100057a, u'\u057A'), 'Armenian_JE': (0x100054b, u'\u054B'), 'Armenian_je': (0x100057b, u'\u057B'), 'Armenian_RA': (0x100054c, u'\u054C'), 'Armenian_ra': (0x100057c, u'\u057C'), 'Armenian_SE': (0x100054d, u'\u054D'), 'Armenian_se': (0x100057d, u'\u057D'), 'Armenian_VEV': (0x100054e, u'\u054E'), 'Armenian_vev': (0x100057e, u'\u057E'), 'Armenian_TYUN': (0x100054f, u'\u054F'), 'Armenian_tyun': (0x100057f, u'\u057F'), 'Armenian_RE': (0x1000550, u'\u0550'), 'Armenian_re': (0x1000580, u'\u0580'), 'Armenian_TSO': (0x1000551, u'\u0551'), 'Armenian_tso': (0x1000581, u'\u0581'), 'Armenian_VYUN': (0x1000552, u'\u0552'), 'Armenian_vyun': (0x1000582, u'\u0582'), 'Armenian_PYUR': (0x1000553, u'\u0553'), 'Armenian_pyur': (0x1000583, u'\u0583'), 'Armenian_KE': (0x1000554, u'\u0554'), 'Armenian_ke': (0x1000584, u'\u0584'), 'Armenian_O': (0x1000555, u'\u0555'), 'Armenian_o': (0x1000585, u'\u0585'), 'Armenian_FE': (0x1000556, u'\u0556'), 'Armenian_fe': (0x1000586, u'\u0586'), 'Armenian_apostrophe': (0x100055a, u'\u055A'), 'Georgian_an': (0x10010d0, u'\u10D0'), 'Georgian_ban': (0x10010d1, u'\u10D1'), 'Georgian_gan': (0x10010d2, u'\u10D2'), 'Georgian_don': (0x10010d3, u'\u10D3'), 'Georgian_en': (0x10010d4, u'\u10D4'), 'Georgian_vin': (0x10010d5, u'\u10D5'), 'Georgian_zen': (0x10010d6, u'\u10D6'), 'Georgian_tan': (0x10010d7, u'\u10D7'), 'Georgian_in': (0x10010d8, u'\u10D8'), 'Georgian_kan': (0x10010d9, u'\u10D9'), 'Georgian_las': (0x10010da, u'\u10DA'), 'Georgian_man': (0x10010db, u'\u10DB'), 'Georgian_nar': (0x10010dc, u'\u10DC'), 'Georgian_on': (0x10010dd, u'\u10DD'), 'Georgian_par': (0x10010de, u'\u10DE'), 'Georgian_zhar': (0x10010df, u'\u10DF'), 'Georgian_rae': (0x10010e0, u'\u10E0'), 'Georgian_san': (0x10010e1, u'\u10E1'), 'Georgian_tar': (0x10010e2, u'\u10E2'), 'Georgian_un': (0x10010e3, u'\u10E3'), 'Georgian_phar': (0x10010e4, u'\u10E4'), 'Georgian_khar': (0x10010e5, u'\u10E5'), 'Georgian_ghan': (0x10010e6, u'\u10E6'), 'Georgian_qar': (0x10010e7, u'\u10E7'), 'Georgian_shin': (0x10010e8, u'\u10E8'), 'Georgian_chin': (0x10010e9, u'\u10E9'), 'Georgian_can': (0x10010ea, u'\u10EA'), 'Georgian_jil': (0x10010eb, u'\u10EB'), 'Georgian_cil': (0x10010ec, u'\u10EC'), 'Georgian_char': (0x10010ed, u'\u10ED'), 'Georgian_xan': (0x10010ee, u'\u10EE'), 'Georgian_jhan': (0x10010ef, u'\u10EF'), 'Georgian_hae': (0x10010f0, u'\u10F0'), 'Georgian_he': (0x10010f1, u'\u10F1'), 'Georgian_hie': (0x10010f2, u'\u10F2'), 'Georgian_we': (0x10010f3, u'\u10F3'), 'Georgian_har': (0x10010f4, u'\u10F4'), 'Georgian_hoe': (0x10010f5, u'\u10F5'), 'Georgian_fi': (0x10010f6, u'\u10F6'), 'Xabovedot': (0x1001e8a, u'\u1E8A'), 'Ibreve': (0x100012c, u'\u012C'), 'Zstroke': (0x10001b5, u'\u01B5'), 'Gcaron': (0x10001e6, u'\u01E6'), 'Ocaron': (0x10001d1, u'\u01D2'), 'Obarred': (0x100019f, u'\u019F'), 'xabovedot': (0x1001e8b, u'\u1E8B'), 'ibreve': (0x100012d, u'\u012D'), 'zstroke': (0x10001b6, u'\u01B6'), 'gcaron': (0x10001e7, u'\u01E7'), 'ocaron': (0x10001d2, u'\u01D2'), 'obarred': (0x1000275, u'\u0275'), 'SCHWA': (0x100018f, u'\u018F'), 'schwa': (0x1000259, u'\u0259'), 'EZH': (0x10001b7, u'\u01B7'), 'ezh': (0x1000292, u'\u0292'), 'Lbelowdot': (0x1001e36, u'\u1E36'), 'lbelowdot': (0x1001e37, u'\u1E37'), 'Abelowdot': (0x1001ea0, u'\u1EA0'), 'abelowdot': (0x1001ea1, u'\u1EA1'), 'Ahook': (0x1001ea2, u'\u1EA2'), 'ahook': (0x1001ea3, u'\u1EA3'), 'Acircumflexacute': (0x1001ea4, u'\u1EA4'), 'acircumflexacute': (0x1001ea5, u'\u1EA5'), 'Acircumflexgrave': (0x1001ea6, u'\u1EA6'), 'acircumflexgrave': (0x1001ea7, u'\u1EA7'), 'Acircumflexhook': (0x1001ea8, u'\u1EA8'), 'acircumflexhook': (0x1001ea9, u'\u1EA9'), 'Acircumflextilde': (0x1001eaa, u'\u1EAA'), 'acircumflextilde': (0x1001eab, u'\u1EAB'), 'Acircumflexbelowdot': (0x1001eac, u'\u1EAC'), 'acircumflexbelowdot': (0x1001ead, u'\u1EAD'), 'Abreveacute': (0x1001eae, u'\u1EAE'), 'abreveacute': (0x1001eaf, u'\u1EAF'), 'Abrevegrave': (0x1001eb0, u'\u1EB0'), 'abrevegrave': (0x1001eb1, u'\u1EB1'), 'Abrevehook': (0x1001eb2, u'\u1EB2'), 'abrevehook': (0x1001eb3, u'\u1EB3'), 'Abrevetilde': (0x1001eb4, u'\u1EB4'), 'abrevetilde': (0x1001eb5, u'\u1EB5'), 'Abrevebelowdot': (0x1001eb6, u'\u1EB6'), 'abrevebelowdot': (0x1001eb7, u'\u1EB7'), 'Ebelowdot': (0x1001eb8, u'\u1EB8'), 'ebelowdot': (0x1001eb9, u'\u1EB9'), 'Ehook': (0x1001eba, u'\u1EBA'), 'ehook': (0x1001ebb, u'\u1EBB'), 'Etilde': (0x1001ebc, u'\u1EBC'), 'etilde': (0x1001ebd, u'\u1EBD'), 'Ecircumflexacute': (0x1001ebe, u'\u1EBE'), 'ecircumflexacute': (0x1001ebf, u'\u1EBF'), 'Ecircumflexgrave': (0x1001ec0, u'\u1EC0'), 'ecircumflexgrave': (0x1001ec1, u'\u1EC1'), 'Ecircumflexhook': (0x1001ec2, u'\u1EC2'), 'ecircumflexhook': (0x1001ec3, u'\u1EC3'), 'Ecircumflextilde': (0x1001ec4, u'\u1EC4'), 'ecircumflextilde': (0x1001ec5, u'\u1EC5'), 'Ecircumflexbelowdot': (0x1001ec6, u'\u1EC6'), 'ecircumflexbelowdot': (0x1001ec7, u'\u1EC7'), 'Ihook': (0x1001ec8, u'\u1EC8'), 'ihook': (0x1001ec9, u'\u1EC9'), 'Ibelowdot': (0x1001eca, u'\u1ECA'), 'ibelowdot': (0x1001ecb, u'\u1ECB'), 'Obelowdot': (0x1001ecc, u'\u1ECC'), 'obelowdot': (0x1001ecd, u'\u1ECD'), 'Ohook': (0x1001ece, u'\u1ECE'), 'ohook': (0x1001ecf, u'\u1ECF'), 'Ocircumflexacute': (0x1001ed0, u'\u1ED0'), 'ocircumflexacute': (0x1001ed1, u'\u1ED1'), 'Ocircumflexgrave': (0x1001ed2, u'\u1ED2'), 'ocircumflexgrave': (0x1001ed3, u'\u1ED3'), 'Ocircumflexhook': (0x1001ed4, u'\u1ED4'), 'ocircumflexhook': (0x1001ed5, u'\u1ED5'), 'Ocircumflextilde': (0x1001ed6, u'\u1ED6'), 'ocircumflextilde': (0x1001ed7, u'\u1ED7'), 'Ocircumflexbelowdot': (0x1001ed8, u'\u1ED8'), 'ocircumflexbelowdot': (0x1001ed9, u'\u1ED9'), 'Ohornacute': (0x1001eda, u'\u1EDA'), 'ohornacute': (0x1001edb, u'\u1EDB'), 'Ohorngrave': (0x1001edc, u'\u1EDC'), 'ohorngrave': (0x1001edd, u'\u1EDD'), 'Ohornhook': (0x1001ede, u'\u1EDE'), 'ohornhook': (0x1001edf, u'\u1EDF'), 'Ohorntilde': (0x1001ee0, u'\u1EE0'), 'ohorntilde': (0x1001ee1, u'\u1EE1'), 'Ohornbelowdot': (0x1001ee2, u'\u1EE2'), 'ohornbelowdot': (0x1001ee3, u'\u1EE3'), 'Ubelowdot': (0x1001ee4, u'\u1EE4'), 'ubelowdot': (0x1001ee5, u'\u1EE5'), 'Uhook': (0x1001ee6, u'\u1EE6'), 'uhook': (0x1001ee7, u'\u1EE7'), 'Uhornacute': (0x1001ee8, u'\u1EE8'), 'uhornacute': (0x1001ee9, u'\u1EE9'), 'Uhorngrave': (0x1001eea, u'\u1EEA'), 'uhorngrave': (0x1001eeb, u'\u1EEB'), 'Uhornhook': (0x1001eec, u'\u1EEC'), 'uhornhook': (0x1001eed, u'\u1EED'), 'Uhorntilde': (0x1001eee, u'\u1EEE'), 'uhorntilde': (0x1001eef, u'\u1EEF'), 'Uhornbelowdot': (0x1001ef0, u'\u1EF0'), 'uhornbelowdot': (0x1001ef1, u'\u1EF1'), 'Ybelowdot': (0x1001ef4, u'\u1EF4'), 'ybelowdot': (0x1001ef5, u'\u1EF5'), 'Yhook': (0x1001ef6, u'\u1EF6'), 'yhook': (0x1001ef7, u'\u1EF7'), 'Ytilde': (0x1001ef8, u'\u1EF8'), 'ytilde': (0x1001ef9, u'\u1EF9'), 'Ohorn': (0x10001a0, u'\u01A0'), 'ohorn': (0x10001a1, u'\u01A1'), 'Uhorn': (0x10001af, u'\u01AF'), 'uhorn': (0x10001b0, u'\u01B0'), 'EcuSign': (0x10020a0, u'\u20A0'), 'ColonSign': (0x10020a1, u'\u20A1'), 'CruzeiroSign': (0x10020a2, u'\u20A2'), 'FFrancSign': (0x10020a3, u'\u20A3'), 'LiraSign': (0x10020a4, u'\u20A4'), 'MillSign': (0x10020a5, u'\u20A5'), 'NairaSign': (0x10020a6, u'\u20A6'), 'PesetaSign': (0x10020a7, u'\u20A7'), 'RupeeSign': (0x10020a8, u'\u20A8'), 'WonSign': (0x10020a9, u'\u20A9'), 'NewSheqelSign': (0x10020aa, u'\u20AA'), 'DongSign': (0x10020ab, u'\u20AB'), 'EuroSign': (0x20ac, u'\u20AC'), 'zerosuperior': (0x1002070, u'\u2070'), 'foursuperior': (0x1002074, u'\u2074'), 'fivesuperior': (0x1002075, u'\u2075'), 'sixsuperior': (0x1002076, u'\u2076'), 'sevensuperior': (0x1002077, u'\u2077'), 'eightsuperior': (0x1002078, u'\u2078'), 'ninesuperior': (0x1002079, u'\u2079'), 'zerosubscript': (0x1002080, u'\u2080'), 'onesubscript': (0x1002081, u'\u2081'), 'twosubscript': (0x1002082, u'\u2082'), 'threesubscript': (0x1002083, u'\u2083'), 'foursubscript': (0x1002084, u'\u2084'), 'fivesubscript': (0x1002085, u'\u2085'), 'sixsubscript': (0x1002086, u'\u2086'), 'sevensubscript': (0x1002087, u'\u2087'), 'eightsubscript': (0x1002088, u'\u2088'), 'ninesubscript': (0x1002089, u'\u2089'), 'partdifferential': (0x1002202, u'\u2202'), 'emptyset': (0x1002205, u'\u2205'), 'elementof': (0x1002208, u'\u2208'), 'notelementof': (0x1002209, u'\u2209'), 'containsas': (0x100220B, u'\u220B'), 'squareroot': (0x100221A, u'\u221A'), 'cuberoot': (0x100221B, u'\u221B'), 'fourthroot': (0x100221C, u'\u221C'), 'dintegral': (0x100222C, u'\u222C'), 'tintegral': (0x100222D, u'\u222D'), 'because': (0x1002235, u'\u2235'), 'approxeq': (0x1002248, u'\u2245'), 'notapproxeq': (0x1002247, u'\u2247'), 'notidentical': (0x1002262, u'\u2262'), 'stricteq': (0x1002263, u'\u2263'), 'braille_blank': (0x1002800, u'\u2800'), 'braille_dots_1': (0x1002801, u'\u2801'), 'braille_dots_2': (0x1002802, u'\u2802'), 'braille_dots_12': (0x1002803, u'\u2803'), 'braille_dots_3': (0x1002804, u'\u2804'), 'braille_dots_13': (0x1002805, u'\u2805'), 'braille_dots_23': (0x1002806, u'\u2806'), 'braille_dots_123': (0x1002807, u'\u2807'), 'braille_dots_4': (0x1002808, u'\u2808'), 'braille_dots_14': (0x1002809, u'\u2809'), 'braille_dots_24': (0x100280a, u'\u280a'), 'braille_dots_124': (0x100280b, u'\u280b'), 'braille_dots_34': (0x100280c, u'\u280c'), 'braille_dots_134': (0x100280d, u'\u280d'), 'braille_dots_234': (0x100280e, u'\u280e'), 'braille_dots_1234': (0x100280f, u'\u280f'), 'braille_dots_5': (0x1002810, u'\u2810'), 'braille_dots_15': (0x1002811, u'\u2811'), 'braille_dots_25': (0x1002812, u'\u2812'), 'braille_dots_125': (0x1002813, u'\u2813'), 'braille_dots_35': (0x1002814, u'\u2814'), 'braille_dots_135': (0x1002815, u'\u2815'), 'braille_dots_235': (0x1002816, u'\u2816'), 'braille_dots_1235': (0x1002817, u'\u2817'), 'braille_dots_45': (0x1002818, u'\u2818'), 'braille_dots_145': (0x1002819, u'\u2819'), 'braille_dots_245': (0x100281a, u'\u281a'), 'braille_dots_1245': (0x100281b, u'\u281b'), 'braille_dots_345': (0x100281c, u'\u281c'), 'braille_dots_1345': (0x100281d, u'\u281d'), 'braille_dots_2345': (0x100281e, u'\u281e'), 'braille_dots_12345': (0x100281f, u'\u281f'), 'braille_dots_6': (0x1002820, u'\u2820'), 'braille_dots_16': (0x1002821, u'\u2821'), 'braille_dots_26': (0x1002822, u'\u2822'), 'braille_dots_126': (0x1002823, u'\u2823'), 'braille_dots_36': (0x1002824, u'\u2824'), 'braille_dots_136': (0x1002825, u'\u2825'), 'braille_dots_236': (0x1002826, u'\u2826'), 'braille_dots_1236': (0x1002827, u'\u2827'), 'braille_dots_46': (0x1002828, u'\u2828'), 'braille_dots_146': (0x1002829, u'\u2829'), 'braille_dots_246': (0x100282a, u'\u282a'), 'braille_dots_1246': (0x100282b, u'\u282b'), 'braille_dots_346': (0x100282c, u'\u282c'), 'braille_dots_1346': (0x100282d, u'\u282d'), 'braille_dots_2346': (0x100282e, u'\u282e'), 'braille_dots_12346': (0x100282f, u'\u282f'), 'braille_dots_56': (0x1002830, u'\u2830'), 'braille_dots_156': (0x1002831, u'\u2831'), 'braille_dots_256': (0x1002832, u'\u2832'), 'braille_dots_1256': (0x1002833, u'\u2833'), 'braille_dots_356': (0x1002834, u'\u2834'), 'braille_dots_1356': (0x1002835, u'\u2835'), 'braille_dots_2356': (0x1002836, u'\u2836'), 'braille_dots_12356': (0x1002837, u'\u2837'), 'braille_dots_456': (0x1002838, u'\u2838'), 'braille_dots_1456': (0x1002839, u'\u2839'), 'braille_dots_2456': (0x100283a, u'\u283a'), 'braille_dots_12456': (0x100283b, u'\u283b'), 'braille_dots_3456': (0x100283c, u'\u283c'), 'braille_dots_13456': (0x100283d, u'\u283d'), 'braille_dots_23456': (0x100283e, u'\u283e'), 'braille_dots_123456': (0x100283f, u'\u283f'), 'braille_dots_7': (0x1002840, u'\u2840'), 'braille_dots_17': (0x1002841, u'\u2841'), 'braille_dots_27': (0x1002842, u'\u2842'), 'braille_dots_127': (0x1002843, u'\u2843'), 'braille_dots_37': (0x1002844, u'\u2844'), 'braille_dots_137': (0x1002845, u'\u2845'), 'braille_dots_237': (0x1002846, u'\u2846'), 'braille_dots_1237': (0x1002847, u'\u2847'), 'braille_dots_47': (0x1002848, u'\u2848'), 'braille_dots_147': (0x1002849, u'\u2849'), 'braille_dots_247': (0x100284a, u'\u284a'), 'braille_dots_1247': (0x100284b, u'\u284b'), 'braille_dots_347': (0x100284c, u'\u284c'), 'braille_dots_1347': (0x100284d, u'\u284d'), 'braille_dots_2347': (0x100284e, u'\u284e'), 'braille_dots_12347': (0x100284f, u'\u284f'), 'braille_dots_57': (0x1002850, u'\u2850'), 'braille_dots_157': (0x1002851, u'\u2851'), 'braille_dots_257': (0x1002852, u'\u2852'), 'braille_dots_1257': (0x1002853, u'\u2853'), 'braille_dots_357': (0x1002854, u'\u2854'), 'braille_dots_1357': (0x1002855, u'\u2855'), 'braille_dots_2357': (0x1002856, u'\u2856'), 'braille_dots_12357': (0x1002857, u'\u2857'), 'braille_dots_457': (0x1002858, u'\u2858'), 'braille_dots_1457': (0x1002859, u'\u2859'), 'braille_dots_2457': (0x100285a, u'\u285a'), 'braille_dots_12457': (0x100285b, u'\u285b'), 'braille_dots_3457': (0x100285c, u'\u285c'), 'braille_dots_13457': (0x100285d, u'\u285d'), 'braille_dots_23457': (0x100285e, u'\u285e'), 'braille_dots_123457': (0x100285f, u'\u285f'), 'braille_dots_67': (0x1002860, u'\u2860'), 'braille_dots_167': (0x1002861, u'\u2861'), 'braille_dots_267': (0x1002862, u'\u2862'), 'braille_dots_1267': (0x1002863, u'\u2863'), 'braille_dots_367': (0x1002864, u'\u2864'), 'braille_dots_1367': (0x1002865, u'\u2865'), 'braille_dots_2367': (0x1002866, u'\u2866'), 'braille_dots_12367': (0x1002867, u'\u2867'), 'braille_dots_467': (0x1002868, u'\u2868'), 'braille_dots_1467': (0x1002869, u'\u2869'), 'braille_dots_2467': (0x100286a, u'\u286a'), 'braille_dots_12467': (0x100286b, u'\u286b'), 'braille_dots_3467': (0x100286c, u'\u286c'), 'braille_dots_13467': (0x100286d, u'\u286d'), 'braille_dots_23467': (0x100286e, u'\u286e'), 'braille_dots_123467': (0x100286f, u'\u286f'), 'braille_dots_567': (0x1002870, u'\u2870'), 'braille_dots_1567': (0x1002871, u'\u2871'), 'braille_dots_2567': (0x1002872, u'\u2872'), 'braille_dots_12567': (0x1002873, u'\u2873'), 'braille_dots_3567': (0x1002874, u'\u2874'), 'braille_dots_13567': (0x1002875, u'\u2875'), 'braille_dots_23567': (0x1002876, u'\u2876'), 'braille_dots_123567': (0x1002877, u'\u2877'), 'braille_dots_4567': (0x1002878, u'\u2878'), 'braille_dots_14567': (0x1002879, u'\u2879'), 'braille_dots_24567': (0x100287a, u'\u287a'), 'braille_dots_124567': (0x100287b, u'\u287b'), 'braille_dots_34567': (0x100287c, u'\u287c'), 'braille_dots_134567': (0x100287d, u'\u287d'), 'braille_dots_234567': (0x100287e, u'\u287e'), 'braille_dots_1234567': (0x100287f, u'\u287f'), 'braille_dots_8': (0x1002880, u'\u2880'), 'braille_dots_18': (0x1002881, u'\u2881'), 'braille_dots_28': (0x1002882, u'\u2882'), 'braille_dots_128': (0x1002883, u'\u2883'), 'braille_dots_38': (0x1002884, u'\u2884'), 'braille_dots_138': (0x1002885, u'\u2885'), 'braille_dots_238': (0x1002886, u'\u2886'), 'braille_dots_1238': (0x1002887, u'\u2887'), 'braille_dots_48': (0x1002888, u'\u2888'), 'braille_dots_148': (0x1002889, u'\u2889'), 'braille_dots_248': (0x100288a, u'\u288a'), 'braille_dots_1248': (0x100288b, u'\u288b'), 'braille_dots_348': (0x100288c, u'\u288c'), 'braille_dots_1348': (0x100288d, u'\u288d'), 'braille_dots_2348': (0x100288e, u'\u288e'), 'braille_dots_12348': (0x100288f, u'\u288f'), 'braille_dots_58': (0x1002890, u'\u2890'), 'braille_dots_158': (0x1002891, u'\u2891'), 'braille_dots_258': (0x1002892, u'\u2892'), 'braille_dots_1258': (0x1002893, u'\u2893'), 'braille_dots_358': (0x1002894, u'\u2894'), 'braille_dots_1358': (0x1002895, u'\u2895'), 'braille_dots_2358': (0x1002896, u'\u2896'), 'braille_dots_12358': (0x1002897, u'\u2897'), 'braille_dots_458': (0x1002898, u'\u2898'), 'braille_dots_1458': (0x1002899, u'\u2899'), 'braille_dots_2458': (0x100289a, u'\u289a'), 'braille_dots_12458': (0x100289b, u'\u289b'), 'braille_dots_3458': (0x100289c, u'\u289c'), 'braille_dots_13458': (0x100289d, u'\u289d'), 'braille_dots_23458': (0x100289e, u'\u289e'), 'braille_dots_123458': (0x100289f, u'\u289f'), 'braille_dots_68': (0x10028a0, u'\u28a0'), 'braille_dots_168': (0x10028a1, u'\u28a1'), 'braille_dots_268': (0x10028a2, u'\u28a2'), 'braille_dots_1268': (0x10028a3, u'\u28a3'), 'braille_dots_368': (0x10028a4, u'\u28a4'), 'braille_dots_1368': (0x10028a5, u'\u28a5'), 'braille_dots_2368': (0x10028a6, u'\u28a6'), 'braille_dots_12368': (0x10028a7, u'\u28a7'), 'braille_dots_468': (0x10028a8, u'\u28a8'), 'braille_dots_1468': (0x10028a9, u'\u28a9'), 'braille_dots_2468': (0x10028aa, u'\u28aa'), 'braille_dots_12468': (0x10028ab, u'\u28ab'), 'braille_dots_3468': (0x10028ac, u'\u28ac'), 'braille_dots_13468': (0x10028ad, u'\u28ad'), 'braille_dots_23468': (0x10028ae, u'\u28ae'), 'braille_dots_123468': (0x10028af, u'\u28af'), 'braille_dots_568': (0x10028b0, u'\u28b0'), 'braille_dots_1568': (0x10028b1, u'\u28b1'), 'braille_dots_2568': (0x10028b2, u'\u28b2'), 'braille_dots_12568': (0x10028b3, u'\u28b3'), 'braille_dots_3568': (0x10028b4, u'\u28b4'), 'braille_dots_13568': (0x10028b5, u'\u28b5'), 'braille_dots_23568': (0x10028b6, u'\u28b6'), 'braille_dots_123568': (0x10028b7, u'\u28b7'), 'braille_dots_4568': (0x10028b8, u'\u28b8'), 'braille_dots_14568': (0x10028b9, u'\u28b9'), 'braille_dots_24568': (0x10028ba, u'\u28ba'), 'braille_dots_124568': (0x10028bb, u'\u28bb'), 'braille_dots_34568': (0x10028bc, u'\u28bc'), 'braille_dots_134568': (0x10028bd, u'\u28bd'), 'braille_dots_234568': (0x10028be, u'\u28be'), 'braille_dots_1234568': (0x10028bf, u'\u28bf'), 'braille_dots_78': (0x10028c0, u'\u28c0'), 'braille_dots_178': (0x10028c1, u'\u28c1'), 'braille_dots_278': (0x10028c2, u'\u28c2'), 'braille_dots_1278': (0x10028c3, u'\u28c3'), 'braille_dots_378': (0x10028c4, u'\u28c4'), 'braille_dots_1378': (0x10028c5, u'\u28c5'), 'braille_dots_2378': (0x10028c6, u'\u28c6'), 'braille_dots_12378': (0x10028c7, u'\u28c7'), 'braille_dots_478': (0x10028c8, u'\u28c8'), 'braille_dots_1478': (0x10028c9, u'\u28c9'), 'braille_dots_2478': (0x10028ca, u'\u28ca'), 'braille_dots_12478': (0x10028cb, u'\u28cb'), 'braille_dots_3478': (0x10028cc, u'\u28cc'), 'braille_dots_13478': (0x10028cd, u'\u28cd'), 'braille_dots_23478': (0x10028ce, u'\u28ce'), 'braille_dots_123478': (0x10028cf, u'\u28cf'), 'braille_dots_578': (0x10028d0, u'\u28d0'), 'braille_dots_1578': (0x10028d1, u'\u28d1'), 'braille_dots_2578': (0x10028d2, u'\u28d2'), 'braille_dots_12578': (0x10028d3, u'\u28d3'), 'braille_dots_3578': (0x10028d4, u'\u28d4'), 'braille_dots_13578': (0x10028d5, u'\u28d5'), 'braille_dots_23578': (0x10028d6, u'\u28d6'), 'braille_dots_123578': (0x10028d7, u'\u28d7'), 'braille_dots_4578': (0x10028d8, u'\u28d8'), 'braille_dots_14578': (0x10028d9, u'\u28d9'), 'braille_dots_24578': (0x10028da, u'\u28da'), 'braille_dots_124578': (0x10028db, u'\u28db'), 'braille_dots_34578': (0x10028dc, u'\u28dc'), 'braille_dots_134578': (0x10028dd, u'\u28dd'), 'braille_dots_234578': (0x10028de, u'\u28de'), 'braille_dots_1234578': (0x10028df, u'\u28df'), 'braille_dots_678': (0x10028e0, u'\u28e0'), 'braille_dots_1678': (0x10028e1, u'\u28e1'), 'braille_dots_2678': (0x10028e2, u'\u28e2'), 'braille_dots_12678': (0x10028e3, u'\u28e3'), 'braille_dots_3678': (0x10028e4, u'\u28e4'), 'braille_dots_13678': (0x10028e5, u'\u28e5'), 'braille_dots_23678': (0x10028e6, u'\u28e6'), 'braille_dots_123678': (0x10028e7, u'\u28e7'), 'braille_dots_4678': (0x10028e8, u'\u28e8'), 'braille_dots_14678': (0x10028e9, u'\u28e9'), 'braille_dots_24678': (0x10028ea, u'\u28ea'), 'braille_dots_124678': (0x10028eb, u'\u28eb'), 'braille_dots_34678': (0x10028ec, u'\u28ec'), 'braille_dots_134678': (0x10028ed, u'\u28ed'), 'braille_dots_234678': (0x10028ee, u'\u28ee'), 'braille_dots_1234678': (0x10028ef, u'\u28ef'), 'braille_dots_5678': (0x10028f0, u'\u28f0'), 'braille_dots_15678': (0x10028f1, u'\u28f1'), 'braille_dots_25678': (0x10028f2, u'\u28f2'), 'braille_dots_125678': (0x10028f3, u'\u28f3'), 'braille_dots_35678': (0x10028f4, u'\u28f4'), 'braille_dots_135678': (0x10028f5, u'\u28f5'), 'braille_dots_235678': (0x10028f6, u'\u28f6'), 'braille_dots_1235678': (0x10028f7, u'\u28f7'), 'braille_dots_45678': (0x10028f8, u'\u28f8'), 'braille_dots_145678': (0x10028f9, u'\u28f9'), 'braille_dots_245678': (0x10028fa, u'\u28fa'), 'braille_dots_1245678': (0x10028fb, u'\u28fb'), 'braille_dots_345678': (0x10028fc, u'\u28fc'), 'braille_dots_1345678': (0x10028fd, u'\u28fd'), 'braille_dots_2345678': (0x10028fe, u'\u28fe'), 'braille_dots_12345678': (0x10028ff, u'\u28ff'), 'Sinh_ng': (0x1000d82, u'\u0D82'), 'Sinh_h2': (0x1000d83, u'\u0D83'), 'Sinh_a': (0x1000d85, u'\u0D85'), 'Sinh_aa': (0x1000d86, u'\u0D86'), 'Sinh_ae': (0x1000d87, u'\u0D87'), 'Sinh_aee': (0x1000d88, u'\u0D88'), 'Sinh_i': (0x1000d89, u'\u0D89'), 'Sinh_ii': (0x1000d8a, u'\u0D8A'), 'Sinh_u': (0x1000d8b, u'\u0D8B'), 'Sinh_uu': (0x1000d8c, u'\u0D8C'), 'Sinh_ri': (0x1000d8d, u'\u0D8D'), 'Sinh_rii': (0x1000d8e, u'\u0D8E'), 'Sinh_lu': (0x1000d8f, u'\u0D8F'), 'Sinh_luu': (0x1000d90, u'\u0D90'), 'Sinh_e': (0x1000d91, u'\u0D91'), 'Sinh_ee': (0x1000d92, u'\u0D92'), 'Sinh_ai': (0x1000d93, u'\u0D93'), 'Sinh_o': (0x1000d94, u'\u0D94'), 'Sinh_oo': (0x1000d95, u'\u0D95'), 'Sinh_au': (0x1000d96, u'\u0D96'), 'Sinh_ka': (0x1000d9a, u'\u0D9A'), 'Sinh_kha': (0x1000d9b, u'\u0D9B'), 'Sinh_ga': (0x1000d9c, u'\u0D9C'), 'Sinh_gha': (0x1000d9d, u'\u0D9D'), 'Sinh_ng2': (0x1000d9e, u'\u0D9E'), 'Sinh_nga': (0x1000d9f, u'\u0D9F'), 'Sinh_ca': (0x1000da0, u'\u0DA0'), 'Sinh_cha': (0x1000da1, u'\u0DA1'), 'Sinh_ja': (0x1000da2, u'\u0DA2'), 'Sinh_jha': (0x1000da3, u'\u0DA3'), 'Sinh_nya': (0x1000da4, u'\u0DA4'), 'Sinh_jnya': (0x1000da5, u'\u0DA5'), 'Sinh_nja': (0x1000da6, u'\u0DA6'), 'Sinh_tta': (0x1000da7, u'\u0DA7'), 'Sinh_ttha': (0x1000da8, u'\u0DA8'), 'Sinh_dda': (0x1000da9, u'\u0DA9'), 'Sinh_ddha': (0x1000daa, u'\u0DAA'), 'Sinh_nna': (0x1000dab, u'\u0DAB'), 'Sinh_ndda': (0x1000dac, u'\u0DAC'), 'Sinh_tha': (0x1000dad, u'\u0DAD'), 'Sinh_thha': (0x1000dae, u'\u0DAE'), 'Sinh_dha': (0x1000daf, u'\u0DAF'), 'Sinh_dhha': (0x1000db0, u'\u0DB0'), 'Sinh_na': (0x1000db1, u'\u0DB1'), 'Sinh_ndha': (0x1000db3, u'\u0DB3'), 'Sinh_pa': (0x1000db4, u'\u0DB4'), 'Sinh_pha': (0x1000db5, u'\u0DB5'), 'Sinh_ba': (0x1000db6, u'\u0DB6'), 'Sinh_bha': (0x1000db7, u'\u0DB7'), 'Sinh_ma': (0x1000db8, u'\u0DB8'), 'Sinh_mba': (0x1000db9, u'\u0DB9'), 'Sinh_ya': (0x1000dba, u'\u0DBA'), 'Sinh_ra': (0x1000dbb, u'\u0DBB'), 'Sinh_la': (0x1000dbd, u'\u0DBD'), 'Sinh_va': (0x1000dc0, u'\u0DC0'), 'Sinh_sha': (0x1000dc1, u'\u0DC1'), 'Sinh_ssha': (0x1000dc2, u'\u0DC2'), 'Sinh_sa': (0x1000dc3, u'\u0DC3'), 'Sinh_ha': (0x1000dc4, u'\u0DC4'), 'Sinh_lla': (0x1000dc5, u'\u0DC5'), 'Sinh_fa': (0x1000dc6, u'\u0DC6'), 'Sinh_al': (0x1000dca, u'\u0DCA'), 'Sinh_aa2': (0x1000dcf, u'\u0DCF'), 'Sinh_ae2': (0x1000dd0, u'\u0DD0'), 'Sinh_aee2': (0x1000dd1, u'\u0DD1'), 'Sinh_i2': (0x1000dd2, u'\u0DD2'), 'Sinh_ii2': (0x1000dd3, u'\u0DD3'), 'Sinh_u2': (0x1000dd4, u'\u0DD4'), 'Sinh_uu2': (0x1000dd6, u'\u0DD6'), 'Sinh_ru2': (0x1000dd8, u'\u0DD8'), 'Sinh_e2': (0x1000dd9, u'\u0DD9'), 'Sinh_ee2': (0x1000dda, u'\u0DDA'), 'Sinh_ai2': (0x1000ddb, u'\u0DDB'), 'Sinh_o2': (0x1000ddc, u'\u0DDC'), 'Sinh_oo2': (0x1000ddd, u'\u0DDD'), 'Sinh_au2': (0x1000dde, u'\u0DDE'), 'Sinh_lu2': (0x1000ddf, u'\u0DDF'), 'Sinh_ruu2': (0x1000df2, u'\u0DF2'), 'Sinh_luu2': (0x1000df3, u'\u0DF3'), 'Sinh_kunddaliya': (0x1000df4, u'\u0DF4')} CHARS = { codepoint: name for name, (keysym, codepoint) in SYMBOLS.items() if codepoint} KEYSYMS = { keysym: name for name, (keysym, codepoint) in SYMBOLS.items() if codepoint} PK2H1pynput/_util/win32.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import ctypes import threading from ctypes import windll, wintypes class MessageLoop(object): """A class representing a message loop. """ #: The message that signals this loop to terminate WM_STOP = 0x0401 _GetMessage = windll.user32.GetMessageW _PeekMessage = windll.user32.PeekMessageW _PostThreadMessage = windll.user32.PostThreadMessageW PM_NOREMOVE = 0 def __init__( self, initialize=lambda message_loop: None, finalize=lambda message_loop: None): self._threadid = None self._initialize = initialize self._finalize = finalize self._event = threading.Event() self.thread = None def __iter__(self): """Initialises the message loop and yields all messages until :meth:`stop` is called. :raises AssertionError: if :meth:`start` has not been called """ assert self._threadid is not None try: # Pump messages until WM_STOP while True: msg = wintypes.MSG() lpmsg = ctypes.byref(msg) r = self._GetMessage(lpmsg, None, 0, 0) if r <= 0 or msg.message == self.WM_STOP: break else: yield msg finally: self._finalize(self) self._threadid = None self.thread = None def start(self): """Starts the message loop. This method must be called before iterating over messages, and it must be called from the same thread. """ self._threadid = GetCurrentThreadId() self.thread = threading.current_thread() # Create the message loop msg = wintypes.MSG() lpmsg = ctypes.byref(msg) self._PeekMessage(lpmsg, None, 0x0400, 0x0400, self.PM_NOREMOVE) # Let the called perform initialisation self._initialize(self) # Set the event to signal to other threads that the loop is created self._event.set() def stop(self): """Stops the message loop. """ self._event.wait() self._PostThreadMessage(self._threadid, self.WM_STOP, 0, 0) if self.thread != threading.current_thread(): self.thread.join() class SystemHook(object): """A class to handle Windows hooks. """ _SetWindowsHookEx = windll.user32.SetWindowsHookExW _UnhookWindowsHookEx = windll.user32.UnhookWindowsHookEx _CallNextHookEx = windll.user32.CallNextHookEx _HOOKPROC = wintypes.WINFUNCTYPE( wintypes.LPARAM, ctypes.c_int32, wintypes.WPARAM, wintypes.LPARAM) #: The registered hook procedures _HOOKS = {} def __init__(self, hook_id, on_hook=lambda code, msg, lpdata: None): self.hook_id = hook_id self.on_hook = on_hook self._hook = None def __enter__(self): key = threading.current_thread() assert key not in self._HOOKS # Add ourself to lookup table and install the hook self._HOOKS[key] = self self._hook = self._SetWindowsHookEx( self.hook_id, self._handler, None, 0) return self def __exit__(self, type, value, traceback): key = threading.current_thread() assert key in self._HOOKS if self._hook is not None: # Uninstall the hook and remove ourself from lookup table self._UnhookWindowsHookEx(self._hook) del self._HOOKS[key] @staticmethod @_HOOKPROC def _handler(code, msg, lpdata): key = threading.current_thread() self = SystemHook._HOOKS.get(key, None) if self: self.on_hook(code, msg, lpdata) # Always call the next hook return SystemHook._CallNextHookEx(0, code, msg, lpdata) GetCurrentThreadId = windll.kernel32.GetCurrentThreadId SendInput = windll.user32.SendInput VkKeyScan = windll.user32.VkKeyScanW class MOUSEINPUT(ctypes.Structure): """Contains information about a simulated mouse event. """ MOVE = 0x0001 LEFTDOWN = 0x0002 LEFTUP = 0x0004 RIGHTDOWN = 0x0008 RIGHTUP = 0x0010 MIDDLEDOWN = 0x0020 MIDDLEUP = 0x0040 XDOWN = 0x0080 XUP = 0x0100 WHEEL = 0x0800 HWHEEL = 0x1000 ABSOLUTE = 0x8000 XBUTTON1 = 0x0001 XBUTTON2 = 0x0002 _fields_ = [ ('dx', wintypes.LONG), ('dy', wintypes.LONG), ('mouseData', wintypes.DWORD), ('dwFlags', wintypes.DWORD), ('time', wintypes.DWORD), ('dwExtraInfo', ctypes.c_void_p)] class KEYBDINPUT(ctypes.Structure): """Contains information about a simulated keyboard event. """ EXTENDEDKEY = 0x0001 KEYUP = 0x0002 SCANCODE = 0x0008 UNICODE = 0x0004 _fields_ = [ ('wVk', wintypes.WORD), ('wScan', wintypes.WORD), ('dwFlags', wintypes.DWORD), ('time', wintypes.DWORD), ('dwExtraInfo', ctypes.c_void_p)] class HARDWAREINPUT(ctypes.Structure): """Contains information about a simulated message generated by an input device other than a keyboard or mouse. """ _fields_ = [ ('uMsg', wintypes.DWORD), ('wParamL', wintypes.WORD), ('wParamH', wintypes.WORD)] class INPUT_union(ctypes.Union): """Represents the union of input types in :class:`INPUT`. """ _fields_ = [ ('mi', MOUSEINPUT), ('ki', KEYBDINPUT), ('hi', HARDWAREINPUT)] class INPUT(ctypes.Structure): """Used by :attr:`SendInput` to store information for synthesizing input events such as keystrokes, mouse movement, and mouse clicks. """ MOUSE = 0 KEYBOARD = 1 HARDWARE = 2 _fields_ = [ ('type', wintypes.DWORD), ('value', INPUT_union)] PKG0Ppynput/mouse/__init__.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import os import sys if os.environ.get('__PYNPUT_GENERATE_DOCUMENTATION') == 'yes': from ._base import Button, Controller, Listener else: Button = None Controller = None Listener = None if sys.platform == 'darwin': if Controller is None and Listener is None: from ._darwin import Button, Controller, Listener elif sys.platform == 'win32': if Controller is None and Listener is None: from ._win32 import Button, Controller, Listener else: if Controller is None and Listener is None: try: from ._xorg import Button, Controller, Listener except: pass if not Button or not Controller or not Listener: raise ImportError('this platform is not supported') PKG _pynput/mouse/_darwin.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import enum import Quartz from AppKit import NSEvent from . import _base def _button_value(base_name, mouse_button): """Generates the value tuple for a :class:`Button` value. :param str base_name: The base name for the button. This shuld be a string like ``'kCGEventLeftMouse'``. :param int mouse_button: The mouse button ID. :return: a value tuple """ return ( tuple( getattr(Quartz, '%sMouse%s' % (base_name, name)) for name in ('Down', 'Up', 'Dragged')), mouse_button) class Button(enum.Enum): """The various buttons. """ left = _button_value('kCGEventLeft', 0) middle = _button_value('kCGEventOther', 2) right = _button_value('kCGEventRight', 1) class Controller(_base.Controller): def __init__(self, *args, **kwargs): super(Controller, self).__init__(*args, **kwargs) self._click = None self._drag_button = None def _position_get(self): pos = NSEvent.mouseLocation() return pos.x, Quartz.CGDisplayPixelsHigh(0) - pos.y def _position_set(self, pos): try: (_, _, mouse_type), mouse_button = self._drag_button except TypeError: mouse_type = Quartz.kCGEventMouseMoved mouse_button = 0 Quartz.CGEventPost( Quartz.kCGHIDEventTap, Quartz.CGEventCreateMouseEvent( None, mouse_type, pos, mouse_button)) def _scroll(self, dx, dy): while dx != 0 or dy != 0: xval = 1 if dx > 0 else -1 if dx < 0 else 0 dx -= xval yval = 1 if dy > 0 else -1 if dy < 0 else 0 dy -= yval Quartz.CGEventPost( Quartz.kCGHIDEventTap, Quartz.CGEventCreateScrollWheelEvent( None, Quartz.kCGScrollEventUnitPixel, 2, yval * 1, xval * 1)) def _press(self, button): (press, release, drag), mouse_button = button.value event = Quartz.CGEventCreateMouseEvent( None, press, self.position, mouse_button) # If we are performing a click, we need to set this state flag if self._click is not None: self._click += 1 Quartz.CGEventSetIntegerValueField( event, Quartz.kCGMouseEventClickState, self._click) Quartz.CGEventPost(Quartz.kCGHIDEventTap, event) # Store the button to enable dragging self._drag_button = button def _release(self, button): (press, release, drag), mouse_button = button.value event = Quartz.CGEventCreateMouseEvent( None, release, self.position, mouse_button) # If we are performing a click, we need to set this state flag if self._click is not None: Quartz.CGEventSetIntegerValueField( event, Quartz.kCGMouseEventClickState, self._click) Quartz.CGEventPost(Quartz.kCGHIDEventTap, event) if button == self._drag_button: self._drag_button = None def __enter__(self): self._click = 0 return self def __exit__(self, type, value, traceback): self._click = None class Listener(_base.Listener): #: The events that we listen to _TAP_EVENTS = ( Quartz.CGEventMaskBit(Quartz.kCGEventMouseMoved) | Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseDown) | Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseUp) | Quartz.CGEventMaskBit(Quartz.kCGEventRightMouseDown) | Quartz.CGEventMaskBit(Quartz.kCGEventRightMouseUp) | Quartz.CGEventMaskBit(Quartz.kCGEventOtherMouseDown) | Quartz.CGEventMaskBit(Quartz.kCGEventOtherMouseUp) | Quartz.CGEventMaskBit(Quartz.kCGEventScrollWheel)) def __init__(self, *args, **kwargs): super(Listener, self).__init__(*args, **kwargs) self._loop = None def _run(self): try: tap = Quartz.CGEventTapCreate( Quartz.kCGSessionEventTap, Quartz.kCGHeadInsertEventTap, Quartz.kCGEventTapOptionDefault, self._TAP_EVENTS, self._handler, None) loop_source = Quartz.CFMachPortCreateRunLoopSource( None, tap, 0) self._loop = Quartz.CFRunLoopGetCurrent() Quartz.CFRunLoopAddSource( self._loop, loop_source, Quartz.kCFRunLoopDefaultMode) Quartz.CGEventTapEnable(tap, True) while True: result = Quartz.CFRunLoopRunInMode( Quartz.kCFRunLoopDefaultMode, 1, False) if result != Quartz.kCFRunLoopRunTimedOut: break finally: self._loop = None def _stop(self): # The base class sets the running flag to False; this will cause the # loop around run loop invocations to terminate and set this event Quartz.CFRunLoopStop(self._loop) @_base.Listener._emitter def _handler(self, proxy, event_type, event, refcon): """The callback registered with *Mac OSX* for mouse events. This method will call the callbacks registered on initialisation. """ (x, y) = Quartz.CGEventGetLocation(event) try: # Quickly detect the most common event type if event_type == Quartz.kCGEventMouseMoved: self.on_move(x, y) elif event_type == Quartz.kCGEventScrollWheel: dx = Quartz.CGEventGetIntegerValueField( event, Quartz.kCGScrollWheelEventDeltaAxis2) dy = Quartz.CGEventGetIntegerValueField( event, Quartz.kCGScrollWheelEventDeltaAxis1) self.on_scroll(x, y, dx, dy) else: for button in Button: (press, release, drag), mouse_button = button.value # Press and release generate click events, and drag # generates move events if event_type in (press, release): self.on_click(x, y, button, event_type == press) elif event_type == drag: self.on_move(x, y) except self.StopException: self.stop() return event PKG,ݙ^^pynput/mouse/_win32.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import enum from pynput._util.win32 import * from . import _base class Button(enum.Enum): """The various buttons. """ left = (MOUSEINPUT.LEFTUP, MOUSEINPUT.LEFTDOWN) middle = (MOUSEINPUT.MIDDLEUP, MOUSEINPUT.MIDDLEDOWN) right = (MOUSEINPUT.RIGHTUP, MOUSEINPUT.RIGHTDOWN) class Controller(_base.Controller): __GetCursorPos = windll.user32.GetCursorPos __SetCursorPos = windll.user32.SetCursorPos def _position_get(self): point = wintypes.POINT() if self.__GetCursorPos(ctypes.byref(point)): return (point.x, point.y) else: return None def _position_set(self, pos): self.__SetCursorPos(*pos) self._notify('on_move', *pos) def _scroll(self, dx, dy): if dy: SendInput( 1, ctypes.byref(INPUT( type=INPUT.MOUSE, value=INPUT_union( mouse=MOUSEINPUT( dwFlags=MOUSEINPUT.WHEEL, mouseData=dy)))), ctypes.sizeof(INPUT)) if dx: SendInput( 1, ctypes.byref(INPUT( type=INPUT.MOUSE, value=INPUT_union( mouse=MOUSEINPUT( dwFlags=MOUSEINPUT.HWHEEL, mouseData=dy)))), ctypes.sizeof(INPUT)) if dx or dy: x, y = self._position_get() self._notify('on_scroll', x, y, dx, dy) def _press(self, button): SendInput( 1, ctypes.byref(INPUT( type=INPUT.MOUSE, value=INPUT_union( mouse=MOUSEINPUT( dwFlags=button.value[0])))), ctypes.sizeof(INPUT)) x, y = self.position self._notify('on_click', x, y, button, True) def _release(self, button): SendInput( 1, ctypes.byref(INPUT( type=INPUT.MOUSE, value=INPUT_union( mouse=MOUSEINPUT( dwFlags=button.value[1])))), ctypes.sizeof(INPUT)) x, y = self.position self._notify('on_click', x, y, button, False) def _notify(self, action, *args): """Sends a notification to all currently running instances of :class:`Listener`. This method will ensure that listeners that raise :class:`StopException` are stopped. :param str action: The name of the notification. :param args: The arguments to pass. """ stopped = [] for listener in Listener.listeners(): try: getattr(listener, action)(*args) except Listener.StopException: stopped.append(listener) for listener in stopped: listener.stop() class Listener(_base.Listener): #: The Windows hook ID for low level mouse events WH_MOUSE_LL = 14 HC_ACTION = 0 WM_LBUTTONDOWN = 0x0201 WM_LBUTTONUP = 0x0202 WM_MOUSEMOVE = 0x0200 WM_MOUSEWHEEL = 0x020A WM_MOUSEHWHEEL = 0x020E WM_RBUTTONDOWN = 0x0204 WM_RBUTTONUP = 0x0205 WHEEL_DELTA = 120 #: A mapping from messages to button events CLICK_BUTTONS = { WM_LBUTTONDOWN: (Button.left, True), WM_LBUTTONUP: (Button.left, False), WM_RBUTTONDOWN: (Button.right, True), WM_RBUTTONUP: (Button.right, False)} #: A mapping from messages to scroll vectors SCROLL_BUTTONS = { WM_MOUSEWHEEL: (0, 1), WM_MOUSEHWHEEL: (1, 0)} #: The currently running listeners __listeners = set() #: The lock protecting access to the :attr:`_listeners` __listener_lock = threading.Lock() class MSLLHOOKSTRUCT(ctypes.Structure): """Contains information about a mouse event passed to a ``WH_MOUSE_LL`` hook procedure, ``MouseProc``. """ _fields_ = [ ('pt', wintypes.POINT), ('mouseData', wintypes.DWORD), ('flags', wintypes.DWORD), ('time', wintypes.DWORD), ('dwExtraInfo', ctypes.c_void_p)] #: A pointer to a :class:`MSLLHOOKSTRUCT` LPMSLLHOOKSTRUCT = ctypes.POINTER(MSLLHOOKSTRUCT) def __init__(self, *args, **kwargs): super(Listener, self).__init__(*args, **kwargs) self._message_loop = MessageLoop() def _run(self): self.__add_listener(self) try: self._message_loop.start() with SystemHook(self.WH_MOUSE_LL, self._handler): # Just pump messages for msg in self._message_loop: if not self.running: break finally: self.__remove_listener(self) def _stop(self): self._message_loop.stop() @_base.Listener._emitter def _handler(self, code, msg, lpdata): """The callback registered with *Windows* for mouse events. This method will call the callbacks registered on initialisation. """ if code != self.HC_ACTION: return data = ctypes.cast(lpdata, self.LPMSLLHOOKSTRUCT).contents if msg == self.WM_MOUSEMOVE: self.on_move(data.pt.x, data.pt.y) elif msg in self.CLICK_BUTTONS: button, pressed = self.CLICK_BUTTONS[msg] self.on_click(data.pt.x, data.pt.y, button, pressed) elif msg in self.SCROLL_BUTTONS: mx, my = self.SCROLL_BUTTONS[msg] d = wintypes.SHORT(data.mouseData >> 16).value // self.WHEEL_DELTA self.on_scroll(data.pt.x, data.pt.y, d * mx, d * my) @classmethod def __add_listener(self, listener): """Adds a listener to the set of running listeners. :param Listener listener: The listener to add. """ with self.__listener_lock: self.__listeners.add(listener) @classmethod def __remove_listener(self, listener): """Removes a listener from the set of running listeners. :param Listener listener: The listener to remove. """ with self.__listener_lock: self.__listeners.remove(listener) @classmethod def listeners(self): """Iterates over the set of running listeners. This method will quit without acquiring the lock if the set is empty, so there is potential for race conditions. This is an optimisation, since :class:`Controller` will need to call this method for every control event. """ if not self.__listeners: return with self.__listener_lock: for listener in self.__listeners: yield listener PKGrƌpynput/mouse/_xorg.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import enum import Xlib.display import Xlib.ext import Xlib.ext.xtest import Xlib.X import Xlib.protocol from pynput._util.xorg import * from . import _base class Button(enum.Enum): """The various buttons. """ left = 1 middle = 2 right = 3 scroll_up = 4 scroll_down = 5 scroll_left = 6 scroll_right = 7 class Controller(_base.Controller): def __init__(self): self._display = Xlib.display.Display() def __del__(self): if hasattr(self, '_display'): self._display.close() def _position_get(self): with display_manager(self._display) as d: data = d.screen().root.query_pointer()._data return (data["root_x"], data["root_y"]) def _position_set(self, pos): x, y = pos with display_manager(self._display) as d: Xlib.ext.xtest.fake_input(d, Xlib.X.MotionNotify, x=x, y=y) def _scroll(self, dx, dy): if dy: self.click( button=Button.scroll_up if dy > 0 else Button.scroll_down, count=abs(dy)) if dx: self.click( button=Button.scroll_right if dx > 0 else Button.scroll_left, count=abs(dx)) def _press(self, button): with display_manager(self._display) as d: Xlib.ext.xtest.fake_input(d, Xlib.X.ButtonPress, button.value) def _release(self, button): with display_manager(self._display) as d: Xlib.ext.xtest.fake_input(d, Xlib.X.ButtonRelease, button.value) class Listener(_base.Listener): #: A mapping from button values to scroll directions SCROLL_BUTTONS = { Button.scroll_up.value: (0, 1), Button.scroll_down.value: (0, -1), Button.scroll_right.value: (1, 0), Button.scroll_left.value: (-1, 0)} def __init__(self, *args, **kwargs): super(Listener, self).__init__(*args, **kwargs) self._display_stop = Xlib.display.Display() self._display_record = Xlib.display.Display() with display_manager(self._display_record) as d: self._context = d.record_create_context( 0, [Xlib.ext.record.AllClients], [{ 'core_requests': (0, 0), 'core_replies': (0, 0), 'ext_requests': (0, 0, 0, 0), 'ext_replies': (0, 0, 0, 0), 'delivered_events': (0, 0), 'device_events': ( Xlib.X.ButtonPressMask, Xlib.X.ButtonReleaseMask), 'errors': (0, 0), 'client_started': False, 'client_died': False}]) def __del__(self): if hasattr(self, '_display_stop'): self._display_stop.close() if hasattr(self, '_display_record'): self._display_record.close() def _run(self): with display_manager(self._display_record) as d: d.record_enable_context( self._context, self._handler) d.record_free_context(self._context) def _stop(self): self._display_stop.sync() with display_manager(self._display_stop) as d: d.record_disable_context(self._context) @_base.Listener._emitter def _handler(self, events): """The callback registered with *X* for mouse events. This method will parse the response and call the callbacks registered on initialisation. """ # We use this instance for parsing the binary data e = Xlib.protocol.rq.EventField(None) data = events.data while len(data): event, data = e.parse_binary_value( data, self._display_record.display, None, None) x = event.root_x y = event.root_y if event.type == Xlib.X.ButtonPress: # Scroll events are sent as button presses with the scroll # button codes scroll = self.SCROLL_BUTTONS.get(event.detail, None) if scroll: self.on_scroll(x, y, *scroll) else: self.on_click(x, y, Button(event.detail), True) elif event.type == Xlib.X.ButtonRelease: # Send an event only if this was not a scroll event if event.detail not in self.SCROLL_BUTTONS: self.on_click(x, y, Button(event.detail), False) else: self.on_move(x, y) PKGo2pynput/mouse/_base.py# coding=utf-8 # pynput # Copyright (C) 2015 Moses Palmér # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . import enum import functools import threading class Button(enum.Enum): """The various buttons. The actual values for these items differ between platforms. Some platforms may have additional buttons, but these are guaranteed to be present everywhere. """ #: The left button left = 1 #: The middle button middle = 2 #: The right button right = 3 class Controller(object): """A controller for sending virtual mouse events to the system. """ @property def position(self): """The current position of the mouse pointer. This is the tuple ``(x, y)``. """ return self._position_get() @position.setter def position(self, pos): self._position_set(pos) def scroll(self, dx, dy): """Sends scroll events. :param int dx: The horizontal scroll. The units of scrolling is undefined. :param int dy: The vertical scroll. The units of scrolling is undefined. """ self._scroll(dx, dy) def press(self, button): """Emits a button press event at the current position. :param Button button: The button to press. """ self._press(button) def release(self, button): """Emits a button release event at the current position. :param Button button: The button to release. """ self._release(button) def move(self, dx, dy): """Moves the mouse pointer a number of pixels from its current position. :param int x: The horizontal offset. :param int dy: The vertical offset. """ self.position = tuple(sum(i) for i in zip(self.position, (dx, dy))) def click(self, button, count=1): """Emits a button click event at the current position. The default implementation sends a series a press and release events. :param Button button: The button to click. :param int count: The number of clicks to send. """ with self as controller: for _ in range(count): controller.press(button) controller.release(button) def __enter__(self): """Begins a series of clicks. In the default :meth:`click` implementation, the return value of this method is used for the calls to :meth:`press` and :meth:`release` instead of ``self``. The default implementation is a no-op. """ return self def __exit__(self, type, value, traceback): """Ends a series of clicks. """ pass def _position_get(self): """The implementation of the getter for :attr:`position`. This is a platform dependent implementation. """ raise NotImplementedError() def _position_set(self, pos): """The implementation of the setter for :attr:`position`. This is a platform dependent implementation. """ raise NotImplementedError() def _scroll(self, dx, dy): """The implementation of the :meth:`scroll` method. This is a platform dependent implementation. """ raise NotImplementedError() def _press(self, button): """The implementation of the :meth:`press` method. This is a platform dependent implementation. """ raise NotImplementedError() def _release(self, button): """The implementation of the :meth:`release` method. This is a platform dependent implementation. """ raise NotImplementedError() class Listener(threading.Thread): """A listener for mouse events. Instances of this class can be used as context managers. This is equivalent to the following code:: listener.start() try: with_statements() finally: listener.stop() :param callable on_move: The callback to call when mouse move events occur. It will be called with the arguments ``(x, y)``, which is the new pointer position. If this callback raises :class:`StopException` or returns ``False``, the listener is stopped. :param callable on_click: The callback to call when a mouse button is clicked. It will be called with the arguments ``(x, y, button, pressed)``, where ``(x, y)`` is the new pointer position, ``button`` is one of the :class:`Button` values and ``pressed`` is whether the button was pressed. If this callback raises :class:`StopException` or returns ``False``, the listener is stopped. :param callable on_scroll: The callback to call when mouse scroll events occur. It will be called with the arguments ``(x, y, dx, dy)``, where ``(x, y)`` is the new pointer position, and ``(dx, dy)`` is the scroll vector. If this callback raises :class:`StopException` or returns ``False``, the listener is stopped. """ class StopException(Exception): """If an event listener callback raises this exception, the current listener is stopped. Its first argument must be set to the :class:`Listener` to stop. """ pass def __init__(self, on_move=None, on_click=None, on_scroll=None): super(Listener, self).__init__() def wrapper(f): def inner(*args): if f(*args) is False: raise self.StopException(self) return inner self._running = False self._thread = threading.current_thread() self.on_move = wrapper(on_move or (lambda *a: None)) self.on_click = wrapper(on_click or (lambda *a: None)) self.on_scroll = wrapper(on_scroll or (lambda *a: None)) @property def running(self): """Whether the listener is currently running. """ return self._running def stop(self): """Stops listening for mouse events. When this method returns, the listening thread will have stopped. """ if self._running: self._running = False self._stop() if threading.current_thread() != self._thread: self.join() def __enter__(self): self.start() return self def __exit__(self, type, value, traceback): self.stop() def run(self): """The thread runner method. """ self._running = True self._thread = threading.current_thread() self._run() @classmethod def _emitter(self, f): """A decorator to mark a method as the one emitting the callbacks. This decorator will wrap the method and catch :class:`StopException`. If this exception is caught, the listener will be stopped. """ @functools.wraps(f) def inner(*args, **kwargs): try: f(*args, **kwargs) except self.StopException as e: e.args[0].stop() return inner def _run(self): """The implementation of the :meth:`start` method. This is a platform dependent implementation. """ raise NotImplementedError() def _stop(self): """The implementation of the :meth:`stop` method. This is a platform dependent implementation. """ raise NotImplementedError() PK;2Hѱ7  $pynput-0.5.dist-info/DESCRIPTION.rstpynput ====== This library allows you to control and monitor input devices. Currently, mouse input and monitoring, and keyboard input are supported. Controlling the mouse --------------------- Use ``pynput.mouse.Controller`` like this:: from pynput.mouse import Button, Controller, Listener d = Controller() # Read pointer position print('The current pointer position is {0}'.format( d.position)) # Set pointer position d.position = (10, 20) print('Now we have moved it to {0}'.format( d.position)) # Move pointer relative to current position d.move(5, -5) # Press and release d.press(Button.left) d.release(Button.left) # Double click; this is different from pressing and releasing twice on Mac # OSX d.click(Button.left, 2) # Scroll two steps down d.scroll(0, 2) Monitoring the mouse -------------------- Use ``pynput.mouse.Listener`` like this:: def on_move(x, y): print('Pointer moved to {0}'.format( (x, y))) def on_click(x, y, button, pressed): print('{0} at {1}'.format( 'Pressed' if pressed else 'Released', (x, y))) if not pressed: # Stop listener return False def on_scroll(dx, dy): print('Scrolled {0}'.format( (x, y))) # Collect events until released with Listener( on_move=on_move, on_click=on_click, on_scroll=on_scroll) as l: l.join() A mouse listener is a ``threading.Thread``, and all callbacks will be invoked from the thread. Call ``pynput.mouse.Listener.stop`` from anywhere, or raise ``pynput.mouse.Listener.StopException`` or return ``False`` from a callback to stop the listener. Release Notes ============= v0.5 - Keyboard Modifiers ------------------------- * Added support for modifiers. v0.4 - Keyboard Controller -------------------------- * Added keyboard controller. v0.3 - Cleanup ------------------------------------------------------------ * Moved ``pynput.mouse.Controller.Button`` to top-level. v0.2 - Initial Release ---------------------- * Support for controlling the mouse on *Linux*, *Mac OSX* and *Windows*. * Support for monitoring the mouse on *Linux*, *Mac OSX* and *Windows*. PK;2H/2"pynput-0.5.dist-info/metadata.json{"classifiers": ["Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows :: Windows NT/2000", "Operating System :: POSIX", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.4", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: System :: Monitoring"], "extensions": {"python.details": {"contacts": [{"email": "moses.palmer@gmail.com", "name": "Moses Palm\u00c3\u00a9r", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/moses-palmer/pynput"}}}, "extras": [], "generator": "bdist_wheel (0.26.0)", "keywords": ["control", "mouse", "mouse", "input"], "license": "GPLv3", "metadata_version": "2.0", "name": "pynput", "run_requires": [{"requires": ["enum34", "six"]}], "summary": "Monitor and control user input devices", "version": "0.5"}PK;2H2~..pynput-0.5.dist-info/pbr.json{"is_release": true, "git_version": "6ed7fa5"}PK;2HŨ"pynput-0.5.dist-info/top_level.txtpynput PKdOG2pynput-0.5.dist-info/zip-safe PK;2H''\\pynput-0.5.dist-info/WHEELWheel-Version: 1.0 Generator: bdist_wheel (0.26.0) Root-Is-Purelib: true Tag: py2-none-any PK;2HaW pynput-0.5.dist-info/METADATAMetadata-Version: 2.0 Name: pynput Version: 0.5 Summary: Monitor and control user input devices Home-page: https://github.com/moses-palmer/pynput Author: Moses Palmér Author-email: moses.palmer@gmail.com License: GPLv3 Keywords: control mouse,mouse input Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3) Classifier: Operating System :: MacOS :: MacOS X Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000 Classifier: Operating System :: POSIX Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.4 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: System :: Monitoring Requires-Dist: enum34 Requires-Dist: six pynput ====== This library allows you to control and monitor input devices. Currently, mouse input and monitoring, and keyboard input are supported. Controlling the mouse --------------------- Use ``pynput.mouse.Controller`` like this:: from pynput.mouse import Button, Controller, Listener d = Controller() # Read pointer position print('The current pointer position is {0}'.format( d.position)) # Set pointer position d.position = (10, 20) print('Now we have moved it to {0}'.format( d.position)) # Move pointer relative to current position d.move(5, -5) # Press and release d.press(Button.left) d.release(Button.left) # Double click; this is different from pressing and releasing twice on Mac # OSX d.click(Button.left, 2) # Scroll two steps down d.scroll(0, 2) Monitoring the mouse -------------------- Use ``pynput.mouse.Listener`` like this:: def on_move(x, y): print('Pointer moved to {0}'.format( (x, y))) def on_click(x, y, button, pressed): print('{0} at {1}'.format( 'Pressed' if pressed else 'Released', (x, y))) if not pressed: # Stop listener return False def on_scroll(dx, dy): print('Scrolled {0}'.format( (x, y))) # Collect events until released with Listener( on_move=on_move, on_click=on_click, on_scroll=on_scroll) as l: l.join() A mouse listener is a ``threading.Thread``, and all callbacks will be invoked from the thread. Call ``pynput.mouse.Listener.stop`` from anywhere, or raise ``pynput.mouse.Listener.StopException`` or return ``False`` from a callback to stop the listener. Release Notes ============= v0.5 - Keyboard Modifiers ------------------------- * Added support for modifiers. v0.4 - Keyboard Controller -------------------------- * Added keyboard controller. v0.3 - Cleanup ------------------------------------------------------------ * Moved ``pynput.mouse.Controller.Button`` to top-level. v0.2 - Initial Release ---------------------- * Support for controlling the mouse on *Linux*, *Mac OSX* and *Windows*. * Support for monitoring the mouse on *Linux*, *Mac OSX* and *Windows*. PK;2H5bpynput-0.5.dist-info/RECORDpynput/__init__.py,sha256=dhtaThkF9ZJkhNasDepxPzn1-ocg5D6nMrx-sfWk1To,737 pynput/_info.py,sha256=7VBQGFECyJdDVIM-9gU2jAXa2LU-_UhJpK5ohuOBsBA,67 pynput/_util/__init__.py,sha256=mRlq3NQSSG2IaeLmK0UE1ILK2afNIkrfwfFrK_DTvuc,693 pynput/_util/darwin.py,sha256=jITwSF_uczJ2kl-7aKV4NFOPnM9fviWGt8oedZfsq10,4168 pynput/_util/win32.py,sha256=Gr3oDm4t6vhhWW-_BhCGS_HpW6QVR3O5Nj08BQVJdQs,6537 pynput/_util/xorg.py,sha256=FER0Gpuza0eEPDjCa2s-NrtlOzAHEwWytJXV9ctOxUA,8434 pynput/_util/xorg_keysyms.py,sha256=ID9eqKMLou6iJXo5h7kdv9zPqBR6QwKBpPC7wIp4Xt4,66862 pynput/keyboard/__init__.py,sha256=Zi_jJPWbmiNga2eXrs1DamNtTLWoZ5gltOpUqtaDydA,1479 pynput/keyboard/_base.py,sha256=hp0uDIsVNc3kbbPp-KMlq3uBQx8kxzQSPOvgh7ICAZ4,14245 pynput/keyboard/_darwin.py,sha256=d5zeXhPoV4lzs_9iUhJ35A7bzIbILFAchS57FTgRf2k,3694 pynput/keyboard/_win32.py,sha256=49NXCLTJgbNO6rcdkHR0lSuywbUz6KHOFm0YdOSwFj0,3624 pynput/keyboard/_xorg.py,sha256=o-qJIF70jbO8ig8_ajWR8_sWZ-N0XxiHo3eCNACgmuk,12040 pynput/mouse/__init__.py,sha256=DdehXOCv8aXmSpv9SCEJe9F5hNh1V6UbCNy7XzNB5l8,1438 pynput/mouse/_base.py,sha256=kzc8HZ9oZmby-SShDbRg1pju_Cn3oV529mCdbRLhqOs,8109 pynput/mouse/_darwin.py,sha256=BfSpUxJlBNtE47YIhsKtWTJtB4EAfX-Y4SSJ_gmUDcg,7321 pynput/mouse/_win32.py,sha256=zbnC-ziXLAtB3WSA593G09eWXJnN21qGlwzWm3MNHls,7518 pynput/mouse/_xorg.py,sha256=2u2BSelSFwTKATBJcM28HDCLyIJMhL5nHd1hGAsMuJc,5296 pynput-0.5.dist-info/DESCRIPTION.rst,sha256=H0yC0gmjG77FYGYW1LnI9-j4kQ--DZvHqhycgYoj9mU,2312 pynput-0.5.dist-info/METADATA,sha256=ZfwkOpQptmjtKn-UzeAYfFPd9wdiRuE6tS35Qg9TH8Y,3212 pynput-0.5.dist-info/RECORD,, pynput-0.5.dist-info/WHEEL,sha256=JTb7YztR8fkPg6aSjc571Q4eiVHCwmUDlX8PhuuqIIE,92 pynput-0.5.dist-info/metadata.json,sha256=fFjOKgllKgXMWjH1lZa9NqBYS4Quse1merNevzKjqQc,1052 pynput-0.5.dist-info/pbr.json,sha256=i7XPBDqPYu0NlXMldg-zZPukeBT7Rhys7DKq3BD2fLo,46 pynput-0.5.dist-info/top_level.txt,sha256=DpJjYf-VkYaa_COk_yUczD0pHqsLndB9SjmwcQGkXJQ,7 pynput-0.5.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 PKGhpynput/__init__.pyPK%2H'sCCpynput/_info.pyPKGC*pynput/keyboard/__init__.pyPK2Hn nn pynput/keyboard/_darwin.pyPK2Hsl(('pynput/keyboard/_win32.pyPK2HJm//&pynput/keyboard/_xorg.pyPK2H 77Upynput/keyboard/_base.pyPKYGYpynput/_util/__init__.pyPK2H"HHpynput/_util/darwin.pyPK2Hݣ6 pynput/_util/xorg.pyPKG7 '..*pynput/_util/xorg_keysyms.pyPK2H1pynput/_util/win32.pyPKG0PNpynput/mouse/__init__.pyPKG _"pynput/mouse/_darwin.pyPKG,ݙ^^pynput/mouse/_win32.pyPKGrƌ!pynput/mouse/_xorg.pyPKGo2e6pynput/mouse/_base.pyPK;2Hѱ7  $EVpynput-0.5.dist-info/DESCRIPTION.rstPK;2H/2"_pynput-0.5.dist-info/metadata.jsonPK;2H2~..cpynput-0.5.dist-info/pbr.jsonPK;2HŨ"Tdpynput-0.5.dist-info/top_level.txtPKdOG2dpynput-0.5.dist-info/zip-safePK;2H''\\dpynput-0.5.dist-info/WHEELPK;2HaW kepynput-0.5.dist-info/METADATAPK;2H5b2rpynput-0.5.dist-info/RECORDPKIz