Hello community,

here is the log from the commit of package python-system_hotkey for 
openSUSE:Factory checked in at 2020-10-23 12:22:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-system_hotkey (Old)
 and      /work/SRC/openSUSE:Factory/.python-system_hotkey.new.3463 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-system_hotkey"

Fri Oct 23 12:22:25 2020 rev:2 rq:843483 version:1.0.3

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-system_hotkey/python-system_hotkey.changes    
    2020-05-26 17:21:57.700315511 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-system_hotkey.new.3463/python-system_hotkey.changes
      2020-10-23 12:23:55.940750595 +0200
@@ -1,0 +2,8 @@
+Thu Oct 22 16:48:44 UTC 2020 - andy great <andythe_gr...@pm.me>
+
+- Update to version 1.0.3.
+  * Fix a typo in Readme
+  * Documented the fact that xlib shouldn't really be used
+- Cleanup spec file.
+
+-------------------------------------------------------------------

Old:
----
  system_hotkey-1.0.2.tar.gz

New:
----
  system_hotkey-1.0.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-system_hotkey.spec ++++++
--- /var/tmp/diff_new_pack.3mL1cI/_old  2020-10-23 12:23:57.776755861 +0200
+++ /var/tmp/diff_new_pack.3mL1cI/_new  2020-10-23 12:23:57.780755872 +0200
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           python-system_hotkey
-Version:        1.0.2
+Version:        1.0.3
 Release:        0
 Summary:        System wide hotkeys
 License:        BSD-3-Clause
@@ -44,8 +44,6 @@
 
 %prep
 %setup -q -n system_hotkey-%{version}
-# version was not bumped
-sed -i -e 's:1\.0\.1:1.0.2:g' setup.py
 
 %build
 %python_build
@@ -61,10 +59,7 @@
 %files %{python_files}
 %license LICENSE
 %doc HISTORY.rst README.rst
-%dir %{python_sitelib}/system_hotkey/
-%dir %{python_sitelib}/system_hotkey/__pycache__/
-%{python_sitelib}/system_hotkey-%{version}-py%{python_version}.egg-info/
-%{python_sitelib}/system_hotkey/*.py
-%pycache_only %{python_sitelib}/system_hotkey/__pycache__/*.pyc
+%{python_sitelib}/system_hotkey
+%{python_sitelib}/*egg-info
 
 %changelog

++++++ system_hotkey-1.0.2.tar.gz -> system_hotkey-1.0.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/system_hotkey-1.0.2/.gitignore 
new/system_hotkey-1.0.3/.gitignore
--- old/system_hotkey-1.0.2/.gitignore  2016-07-28 22:29:56.000000000 +0200
+++ new/system_hotkey-1.0.3/.gitignore  2019-05-15 14:53:03.000000000 +0200
@@ -6,5 +6,5 @@
 *egg-info/
 *.bat
 .cache/
-
+tags
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/system_hotkey-1.0.2/HISTORY.rst 
new/system_hotkey-1.0.3/HISTORY.rst
--- old/system_hotkey-1.0.2/HISTORY.rst 2016-07-28 22:29:56.000000000 +0200
+++ new/system_hotkey-1.0.3/HISTORY.rst 2019-05-15 14:53:03.000000000 +0200
@@ -4,11 +4,22 @@
 
 Mac support
 
-eta > 9 months
+eta > 8 months
 
 
 Version Release Notes
 =====================
+1.0.4
+-----
+* Exceptions are now run in main
+
+1.0.3
+-----
+* Documented the fact that xlib shouldn't really be used
+
+1.0.2
+-----
+* Fixed a linux bug where spurious events got passed through
 
 1.0.0
 -----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/system_hotkey-1.0.2/README.rst 
new/system_hotkey-1.0.3/README.rst
--- old/system_hotkey-1.0.2/README.rst  2016-07-28 22:29:56.000000000 +0200
+++ new/system_hotkey-1.0.3/README.rst  2019-05-15 14:53:03.000000000 +0200
@@ -5,8 +5,6 @@
 
 Currently no mac or  python2 support :(
 
-Mac support is coming in a few years i would say!
-
 
 Installation
 ------------
@@ -15,7 +13,7 @@
 
 .. code-block:: bash
 
-    pip3 install system_hotkey
+  pip3 install system_hotkey
 
 should do the trick
 
@@ -25,9 +23,9 @@
 
 Linux
 ^^^^^
-For x11 you will can either use `xcffib <https://github.com/tych0/xcffib>`_  
(bsd license),
-or you may use the python xlib bindings (gpl license)
+For x11 you should use `xcffib <https://github.com/tych0/xcffib>`_  (bsd 
license),
 
+If for some reason you have to use the python xlib bindings (gpl license), a 
few fixes need be added first. See `here 
<https://github.com/timeyyy/system_hotkey/issues/6#issuecomment-265410255>`_
 
 
 Usage
@@ -46,16 +44,16 @@
 
 - control
 - shift
-- super (win key)
+- super (windows key)
 - alt
 
-A InvalidKeyError will be raised if a key was not understood
+InvalidKeyError will be raised if a key was not understood
 
 .. code-block:: python
 
     from system_hotkey import SystemHotkey
-    hk = SystemHotkeys()
-    hk.register(('control', 'shift', 'h'), callback=lambda:print("Easy!"))
+    hk = SystemHotkey()
+    hk.register(('control', 'shift', 'h'), callback=lambda x: print("Easy!"))
 
 A SystemRegisterError will be raised if a hotkey is already in use.
 
@@ -76,7 +74,7 @@
     def some_func(self, event, hotkey, args):
         pass
 
-    hk = SystemHotkeys(consumer=some_func)
+    hk = SystemHotkey(consumer=some_func)
     hk.register(hotkey, arg1, arg2, arg3)
 
 So you have a master function that receives all hotkey presses and can 
delegate as desired.
@@ -93,3 +91,5 @@
 - I have only mapped most common keys, i have not experimented with 
Unicode/Japanese characters etc. It's only a matter of mapping a name to the 
keysym on Linux and virtual key code on windows.
 
 - binding to kp_left (key pad left) will also bind to kp_4, there is a flag 
(unite_kp) to toggle this behaviour but it is experimental
+
+- Requires an xserver (x11)...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/system_hotkey-1.0.2/setup.py 
new/system_hotkey-1.0.3/setup.py
--- old/system_hotkey-1.0.2/setup.py    2016-07-28 22:29:56.000000000 +0200
+++ new/system_hotkey-1.0.3/setup.py    2019-05-15 14:53:03.000000000 +0200
@@ -1,5 +1,5 @@
 from setuptools import setup, find_packages
-from codecs import open                                        
+from codecs import open
 import os
 here = os.path.abspath(os.path.dirname(__file__))
 
@@ -8,88 +8,32 @@
     with open(os.path.join(*paths), 'r') as f:
         return f.read()
 
-#if os.name == 'nt':
-#      REQUIRED = ['pywin32']
-#else:
-REQUIRED = []
-
 setup(
        name = 'system_hotkey',
-
-       version='1.0.1',
-       
+       version='1.0.3',
        description = 'System wide hotkeys',
        long_description = (read('README.rst') + '\n\n' +
                       read('HISTORY.rst') + '\n\n' +
                       read('AUTHORS.rst')),
-       
        url = 'https://github.com/timeyyy/system_hotkey',
-       
        author='timothy eichler',
        author_email='tim_eich...@hotmail.com',
-       
        license='BSD3',
-       
        # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
        classifiers=[
                # How mature is this project? Common values are
                #~ 3 - Alpha
                # 4 - Beta
                # 5 - Production/Stable
-               'Development Status :: 3 - Alpha',
+               'Development Status :: 4 - Beta',
                'Intended Audience :: Developers',
                'Operating System :: OS Independent',
                'License :: OSI Approved :: BSD License',
-               # Specify the Python versions you support here. In particular, 
ensure
-               # that you indicate whether you support Python 2, Python 3 or 
both.
                #~ 'Programming Language :: Python :: 2',
-               #~ 'Programming Language :: Python :: 2.6',
-               #~ 'Programming Language :: Python :: 2.7',
                'Programming Language :: Python :: 3',
-               'Programming Language :: Python :: 3.2',
-               'Programming Language :: Python :: 3.3',
-               'Programming Language :: Python :: 3.4',
-               'Programming Language :: Python :: 3.5',
        ],
 
        # What does your project relate to?
        keywords = 'hotkeys python3 shortcutkeys shortuct x11 windows',
-
-       # You can just specify the packages manually here if your project is
-       # simple. Or you can use find_packages().
        packages=find_packages(exclude=['contrib', 'docs', 'tests*']),
-       
-       # List run-time dependencies here. These will be installed by pip when 
your
-       # project is installed. For an analysis of "install_requires" vs pip's
-       # requirements files see:
-       # https://packaging.python.org/en/latest/requirements.html
-       install_requires = REQUIRED,
-       
-       # List additional groups of dependencies here (e.g. development 
dependencies).
-       # You can install these using the following syntax, for example:
-       # $ pip install -e .[dev,test]
-       #~ extras_require = {
-       #~ 'dev': ['check-manifest'],
-       #~ 'test': ['coverage'],
-       #~ },
-       
-       # If there are data files included in your packages that need to be
-       # installed, specify them here. If using Python 2.6 or less, then these
-       # have to be included in MANIFEST.in as well.
-       #~ package_data={
-       #~ 'sample': ['package_data.dat'],
-       #~ },
-       
-       # Although 'package_data' is the preferred approach, in some case you 
may
-       # need to place data files outside of your packages.
-       # see 
http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files
-       # In this case, 'data_file' will be installed into 
'<sys.prefix>/my_data'
-       #~ data_files=[('my_data', ['data/data_file'])],
-       
-       # To provide executable scripts, use entry points in preference to the
-       # "scripts" keyword. Entry points provide cross-platform support and 
allow
-       # pip to create the appropriate form of executable for the target 
platform.
-       #~ entry_points = {
-                       #~ 'console_scripts': [
-                               #~ 'sample=sample:main',],},
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/system_hotkey-1.0.2/system_hotkey/system_hotkey.py 
new/system_hotkey-1.0.3/system_hotkey/system_hotkey.py
--- old/system_hotkey-1.0.2/system_hotkey/system_hotkey.py      2016-07-28 
22:29:56.000000000 +0200
+++ new/system_hotkey-1.0.3/system_hotkey/system_hotkey.py      2019-05-15 
14:53:03.000000000 +0200
@@ -137,16 +137,18 @@
         # win32con.NUMLOCK_ON,
         # win32con.NUMLOCK_ON | win32con.CAPSLOCK_ON
         )
+# Linux
 else:
     try:
         from . import xpybutil_keybind as keybind
     except SystemError:
         import xpybutil_keybind as keybind
 
+    # Xcb
     try:
-        import xcffib           # the xproto con will not work unlesss you 
inport this first
+        # Xproto con will not work unlesss you inport this first
+        import xcffib
         from xcffib import xproto
-        from xpybutil import keybind
 
         xcb_modifiers  = {
             'control' : xproto.ModMask.Control,
@@ -161,105 +163,69 @@
             xproto.ModMask.Lock | xproto.ModMask._2)
     except ImportError:
         pass
-    try:
-        from Xlib import X
-        from Xlib import XK
-        from Xlib.display import Display
-        special_X_keysyms = {           # these couldn't be gotten from the 
xlib keycode function
-            ' ' : "space",
-            '\t' : "Tab",
-            '\n' : "Return",
-            '\r' : "Return",
-            '\e' : "Escape",
-            '!' : "exclam",
-            '#' : "numbersign",
-            '%' : "percent",
-            '$' : "dollar",
-            '&' : "ampersand",
-            '"' : "quotedbl",
-            '\'' : "apostrophe",
-            '(' : "parenleft",
-            ')' : "parenright",
-            '*' : "asterisk",
-            '=' : "equal",
-            '+' : "plus",
-            ',' : "comma",
-            '-' : "minus",
-            '.' : "period",
-            '/' : "slash",
-            ':' : "colon",
-            ';' : "semicolon",
-            '<' : "less",
-            '>' : "greater",
-            '?' : "question",
-            '@' : "at",
-            '[' : "bracketleft",
-            ']' : "bracketright",
-            '\\' : "backslash",
-            '^' : "asciicircum",
-            '_' : "underscore",
-            '`' : "grave",
-            '{' : "braceleft",
-            '|' : "bar",
-            '}' : "braceright",
-            '~' : "asciitilde"
-            }
-
-        xlib_modifiers = {
-            'control' : X.ControlMask,
-            'shift' :  X.ShiftMask,
-            'alt' : X.Mod1Mask,
-            'super' : X.Mod4Mask
-            }
-
-        xlib_trivial_mods = (   # only working for scrollock
-            0,
-            X.LockMask,
-            X.Mod2Mask,
-            X.LockMask | X.Mod2Mask)
-    except ImportError:
-        pass
+    # Xlib
+    else:
+        try:
+            from Xlib import X
+            from Xlib import XK
+            from Xlib.display import Display
+           # These couldn't be gotten from the xlib keycode function
+            special_X_keysyms = {
+                ' ' : "space",
+                '\t' : "tab",
+                '\n' : "return",
+                '\r' : "return",
+                '\e' : "escape",
+                '!' : "exclam",
+                '#' : "numbersign",
+                '%' : "percent",
+                '$' : "dollar",
+                '&' : "ampersand",
+                '"' : "quotedbl",
+                '\'' : "apostrophe",
+                '(' : "parenleft",
+                ')' : "parenright",
+                '*' : "asterisk",
+                '=' : "equal",
+                '+' : "plus",
+                ',' : "comma",
+                '-' : "minus",
+                '.' : "period",
+                '/' : "slash",
+                ':' : "colon",
+                ';' : "semicolon",
+                '<' : "less",
+                '>' : "greater",
+                '?' : "question",
+                '@' : "at",
+                '[' : "bracketleft",
+                ']' : "bracketright",
+                '\\' : "backslash",
+                '^' : "asciicircum",
+                '_' : "underscore",
+                '`' : "grave",
+                '{' : "braceleft",
+                '|' : "bar",
+                '}' : "braceright",
+                '~' : "asciitilde"
+                }
+
+            xlib_modifiers = {
+                'control' : X.ControlMask,
+                'shift' :  X.ShiftMask,
+                'alt' : X.Mod1Mask,
+                'super' : X.Mod4Mask
+                }
+
+            xlib_trivial_mods = (   # only working for scrollock
+                0,
+                X.LockMask,
+                X.Mod2Mask,
+                X.LockMask | X.Mod2Mask)
+        except ImportError:
+            pass
 
 
-special_X_keysyms = {
-    ' ' : "space",
-    '\t' : "Tab",
-    '\n' : "Return",
-    '\r' : "Return",
-    '\e' : "Escape",
-    '!' : "exclam",
-    '#' : "numbersign",
-    '%' : "percent",
-    '$' : "dollar",
-    '&' : "ampersand",
-    '"' : "quotedbl",
-    '\'' : "apostrophe",
-    '(' : "parenleft",
-    ')' : "parenright",
-    '*' : "asterisk",
-    '=' : "equal",
-    '+' : "plus",
-    ',' : "comma",
-    '-' : "minus",
-    '.' : "period",
-    '/' : "slash",
-    ':' : "colon",
-    ';' : "semicolon",
-    '<' : "less",
-    '>' : "greater",
-    '?' : "question",
-    '@' : "at",
-    '[' : "bracketleft",
-    ']' : "bracketright",
-    '\\' : "backslash",
-    '^' : "asciicircum",
-    '_' : "underscore",
-    '`' : "grave",
-    '{' : "braceleft",
-    '|' : "bar",
-    '}' : "braceright",
-    '~' : "asciitilde"
-    }
 
 class Aliases():
     '''
@@ -291,7 +257,7 @@
 thread_safe = util.CallSerializer()
 
 class MixIn():
-    @thread_safe.serialize_call
+    @thread_safe.serialize_call(0.5)
     def register(self, hotkey, *args, callback=None, overwrite=False):
         '''
         Add a system wide hotkey,
@@ -328,7 +294,6 @@
             else:
                 msg = 'existing bind detected... unregister or set overwrite 
to True'
                 raise SystemRegisterError(msg, *hotkey)
-                return
 
         if os.name == 'nt':
             def nt_register():
@@ -367,11 +332,14 @@
             #~ copy[-1] = 'keyrelease'
             #~ self.keybinds[tuple(copy)].append(callback)
 
-    @thread_safe.serialize_call
+    @thread_safe.serialize_call(0.5)
     def unregister(self, hotkey):
         '''
         Remove the System wide hotkey,
         the order of the modifier keys is irrelevant
+
+        InvalidKeyError raised if key not understood
+        UnregisterError raiesd if key doesn't exist
         '''
         keycode, masks = self.parse_hotkeylist(hotkey)
         if os.name == 'nt':
@@ -392,9 +360,12 @@
                 try:
                     for mod in self.trivial_mods:
                         self.conn.core.UngrabKeyChecked(keycode, self.root, 
masks | mod).check()
-                except xproto.BadAccess:
-                    raise UnregisterError("Failed unregs")
-        del self.keybinds[tuple(self.order_hotkey(hotkey))]
+                except xproto.BadAccess as e:
+                    raise UnregisterError("Failed to unregister") from e
+        try:
+            del self.keybinds[tuple(self.order_hotkey(hotkey))]
+        except KeyError as err:
+            raise UnregisterError from err
 
     def order_hotkey(self, hotkey):
         # Order doesn't matter for modifiers, so we force an order here
@@ -437,7 +408,7 @@
                 try:
                     masks.append(self.modders[item])
                 except KeyError:
-                    raise SystemRegisterError('Modifier: %s not supported' % 
item)    #TBD rmeove how the keyerror gets displayed as well
+                    raise SystemRegisterError('Modifier: %s not supported' % 
item) from None
             masks = self.or_modifiers_together(masks)
         else:
             masks = 0
@@ -463,7 +434,7 @@
             if self.verbose:
                 print('MFERROR', hotkey)
             # Possible numpad key? The keysym can change if shift is pressed 
(only tested on linux)
-            # Todo test numpad bindings on a non english system
+            # TODO test numpad bindings on a non english system
             aliases = NUMPAD_ALIASES.get(hotkey[-1])
             if aliases:
                 for key in aliases:
@@ -532,7 +503,7 @@
         '''
         given a keycode returns a keysym
         '''
-        # Todo
+        # TODO
         # --quirks--
         # linux:
         #     numpad keys with multiple keysyms are currently undistinguishable
@@ -550,7 +521,7 @@
     hk_ref = {}
     keybinds = {}
 
-    def __init__(self, consumer='callback', check_queue_interval=0.01, 
use_xlib=False, conn=None, verbose=False, unite_kp=True):
+    def __init__(self, consumer='callback', check_queue_interval=0.0001, 
use_xlib=False, conn=None, verbose=False, unite_kp=True):
         '''
         if the consumer param = 'callback', -> All hotkeys will require
         a callback function
@@ -672,7 +643,7 @@
                             if event.event_type == 'keypress':
                                 if self.verbose:
                                     print('calling ', repr(cb))
-                                cb(event)   # TBD either throw these up in a 
thread, or pass in a queue to be put onto
+                                cb(event)   # TODO either throw these up in a 
thread, or pass in a queue to be put onto
             thread.start_new_thread(thread_me,(),)
 
         elif callable(consumer):
@@ -773,7 +744,7 @@
         return keybind.keysym_strings.get(keysym, [None])[0]
 
     def _xlib_the_grab(self, keycode, masks):
-        # Todo error handlig  
http://tronche.com/gui/x/xlib/event-handling/protocol-errors/default-handlers.html
+        # TODO error handlig  
http://tronche.com/gui/x/xlib/event-handling/protocol-errors/default-handlers.html
         # try:
         for triv_mod in self.trivial_mods:
             self.xRoot.grab_key(keycode, triv_mod | masks, 1, X.GrabModeAsync, 
X.GrabModeAsync)
@@ -788,13 +759,13 @@
                         True,
                         self.root, triv_mod | masks, keycode,
                         xproto.GrabMode.Async, xproto.GrabMode.Async).check()
-                except struct.error: 
+                except struct.error as e:
                     msg = 'Unable to Register, Key not understood by 
systemhotkey'
-                    raise InvalidKeyError(msg)
-        except xproto.AccessError:
+                    raise InvalidKeyError(msg) from e 
+        except xproto.AccessError as e:
             keysym = self._xcb_get_keysym(keycode)
             msg = 'The bind could be in use elsewhere: ' + keysym
-            raise SystemRegisterError(msg)
+            raise SystemRegisterError(msg) from e
 
     def _xcb_get_keycode(self, key):
         return keybind.lookup_string(key)
@@ -806,7 +777,7 @@
 if __name__ == '__main__':
     # hk = SystemHotkey(use_xlib=True, verbose=1, unite_kp=1)
     # hk = SystemHotkey(use_xlib=False, verbose=0)    # xcb
-    #hk.register(('a',), callback=lambda e: print('hi'))
+    # hk.register(('a',), callback=lambda e: print('hi'))
     # hk.register(('kp_3',), callback=lambda e: print('hi'))
 
     #hk.register(('left',), callback=lambda e: print('hi'))
@@ -825,20 +796,21 @@
     # hk.register(('control','shift', 'k'), callback=lambda e: print('i am con 
shift k2'))
     def consumer(event, hotkey, args):
         if hotkey != ["f4"]:
-            import pdb;pdb.set_trace()
+            print(1)
+            # import pdb;pdb.set_trace()
         else:
             print(1)
 
-    hk = SystemHotkey(use_xlib=False, consumer=consumer, verbose=1,
+    hk = SystemHotkey(use_xlib=False, consumer=consumer, verbose=0,
             check_queue_interval=0.001)
-    hk.register(('f4',), callback=lambda e: print('hi'))
+    hk.register(('escape',), callback=lambda e: print('hi'))
     while 1:
         pass
 
 # Refernces #
 #https://wiki.python.org/moin/AppsWithPythonScripting
-#~ http://msdn.microsoft.com/en-us/library/ms927178.aspx
-#http://www.kbdedit.com/manual/low_level_vk_list.html
-#http://stackoverflow.com/questions/14076207/simulating-a-key-press-event-in-python-2-7
 #TBD WINDOWS KEY UP /DOWN ?
+#vk codes http://msdn.microsoft.com/en-us/library/ms927178.aspx
+#vk codes http://www.kbdedit.com/manual/low_level_vk_list.html
+#http://stackoverflow.com/questions/14076207/simulating-a-key-press-event-in-python-2-7
 #TODO WINDOWS KEY UP /DOWN ?
 #https://github.com/Tzbob/python-windows-tiler/blob/master/pwt/hotkey.py
-# Tbd how to keep the lisetning alive if a n error is encounterd? how to 
recover?
+#TODO how to keep the lisetning alive if an error is encounterd? how to 
recover?
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/system_hotkey-1.0.2/system_hotkey/tests/test_system_hotkey.py 
new/system_hotkey-1.0.3/system_hotkey/tests/test_system_hotkey.py
--- old/system_hotkey-1.0.2/system_hotkey/tests/test_system_hotkey.py   
1970-01-01 01:00:00.000000000 +0100
+++ new/system_hotkey-1.0.3/system_hotkey/tests/test_system_hotkey.py   
2019-05-15 14:53:03.000000000 +0200
@@ -0,0 +1,44 @@
+from system_hotkey import SystemHotkey, \
+                          SystemRegisterError, \
+                          UnregisterError, \
+                          InvalidKeyError
+
+def test_errors_raised_in_main():
+    hk = SystemHotkey()
+    key = ('5',)
+    cb = lambda e: print('hi')
+
+    hk.register(key, callback=cb)
+    try:
+        hk.register(key, callback=cb)
+    except SystemRegisterError:
+        pass
+    else:
+        raise Exception('fail')
+
+    hk.unregister(key)
+    try:
+        hk.unregister(key)
+    except UnregisterError:
+        pass
+    else:
+        raise Exception('fail')
+
+    bad_key = ('badkey ..',)
+    try:
+        hk.register(bad_key, callback=cb)
+    except InvalidKeyError:
+        pass
+    else:
+        raise Exception('fail')
+
+    try:
+        hk.unregister(bad_key)
+    except:
+        pass
+    else:
+        raise Exception('fail')
+
+    # input() # Hold program open until you press enter
+
+test_errors_raised_in_main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/system_hotkey-1.0.2/system_hotkey/util.py 
new/system_hotkey-1.0.3/system_hotkey/util.py
--- old/system_hotkey-1.0.2/system_hotkey/util.py       2016-07-28 
22:29:56.000000000 +0200
+++ new/system_hotkey-1.0.3/system_hotkey/util.py       2019-05-15 
14:53:03.000000000 +0200
@@ -4,8 +4,11 @@
     general utilites..
 '''
 import _thread as thread
+import threading
 from queue import Queue
+import queue
 from functools import wraps
+import time
 
 
 def unique_int(values):
@@ -26,22 +29,93 @@
     return last
 
 
+class ExceptionSerializer():
+    def __init__(self):
+        self.queue = queue.Queue()
+
+    def catch_and_raise(self, func, timeout=0.5):
+        '''
+        wait for a function to finish and raise any errors'''
+        self.wait_event(func, timeout)
+        self._check_for_errors(func)
+
+    def mark_done(self, function):
+        '''Wrap functions so that we can monitor when they are done'''
+        self.init_wrap(function)
+        @wraps(function)
+        def decorator(*args, **kwargs):
+            # Function has started running
+            self.clear_event(function)
+            try:
+                results = function(*args, **kwargs)
+            except Exception as err:
+                self.queue.put(err)
+            else:
+                return results
+            finally:
+                # Function has finished running
+                self.set_event(function)
+
+        return decorator
+
+    def put(self, x):
+        self.queue.put(x)
+
+    def init_wrap(self, func):
+        name = self._make_event_name(func)
+        event = threading.Event()
+        setattr(self, name, event)
+
+    def _check_for_errors(self, func):
+        try:
+            error = self.queue.get(block=False)
+        except queue.Empty:
+            pass
+        else:
+            raise error
+
+    def _make_event_name(self, func):
+        return '_event_' + func.__name__
+
+    def get_event(self, func):
+        return getattr(self, self._make_event_name(func))
+
+    def set_event(self, func):
+        self.get_event(func).set()
+
+    def clear_event(self, func):
+        self.get_event(func).clear()
+
+    def wait_event(self, func, *args):
+        self.get_event(func).wait(*args)
+
+
 class CallSerializer():
     def __init__(self):
         self.queue = Queue()
         thread.start_new_thread(self.call_functions, (),)
+        self.bug_catcher = ExceptionSerializer()
 
     def call_functions(self):
         while 1:
             func, args, kwargs = self.queue.get(block=True)
             func(*args, **kwargs)
 
-    def serialize_call(self, function):
+    def serialize_call(self, timeout=0.5):
         '''
         a call to a function decorated will not have
         overlapping calls, i.e thread safe
         '''
-        @wraps(function)
-        def decorator(*args, **kwargs):
-            self.queue.put((function, args, kwargs))
-        return decorator
+        def state(function):
+            @wraps(function)
+            def decorator(*args, **kwargs):
+                # Function will let us know when it is done running
+                # This is done so we can catch exceptions raised
+                # in functions that are run within threads
+                mark_func = self.bug_catcher.mark_done(function)
+                self.queue.put((mark_func, args, kwargs))
+                # wait for the function to finish and raise errors
+                self.bug_catcher.catch_and_raise(function, timeout)
+            return decorator
+        return state
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/system_hotkey-1.0.2/tests/test_hotkeys.py 
new/system_hotkey-1.0.3/tests/test_hotkeys.py
--- old/system_hotkey-1.0.2/tests/test_hotkeys.py       2016-07-28 
22:29:56.000000000 +0200
+++ new/system_hotkey-1.0.3/tests/test_hotkeys.py       1970-01-01 
01:00:00.000000000 +0100
@@ -1,55 +0,0 @@
-import os
-import time
-
-import system_hotkey
-hk = system_hotkey.SystemHotkey()
-
-CALLBACK_RESULT = []
-
-def append_callback(key):
-       print('APPENDING ',key)
-       CALLBACK_RESULT.append(key)
-       
-if os.name == 'nt':
-       from win32api import keybd_event
-       def send_event(key):    # note if we change the time on checking our 
queue this sleep time will have to be changed
-               time.sleep(0.03)                                        
-               keybd_event(int(hk.get_keycode(key)) , 0, 1, 0)
-               time.sleep(0.03)
-
-
-keys_to_test = [('k',),
-                               ('control','k'),
-                               ('control','shift','k'),
-                               ('control','shift','alt','k'),
-                               ('control','shift','alt','super', 'k')]
-
-def test_register_args():
-       '''If in callback mode the register function requires a callback for 
all hotkeys regiersted,
-       an error needs to be raised'''
-       _hk = system_hotkey.SystemHotkey()
-       try:
-               _hk.register((keys_to_test[0]),)
-       except TypeError:
-               pass
-       else:
-               assert("hk register with no callback worked when it shouldn't 
have")
-               
-def test_register_1():
-       '''
-       Registers a hotkey without any modifiers, tests that the callback
-       was run
-       '''
-       hk.register(keys_to_test[0], callback=lambda e: 
append_callback(keys_to_test[0]))       # THIS IS THREADED SO TBD DOCUMENT just 
need to wait a bit before sending the first key or after pressing a key getting 
the result
-       send_event(keys_to_test[0][0])
-       assert CALLBACK_RESULT[0] == keys_to_test[0]
-
-
-def register_2():
-       '''testing with one modifier'''
-       hk.register(keys_to_test[1], lambda msg: 
CALLBACK_RESULT[0].append(keys_to_test[0]))
-       send_event(keys_to_test[1])
-
-#~ test_register_1()
-#~ register_2()
-


Reply via email to