Repository: kivy/kivy

Issue:
Python 3.4 packager KeyError: 'rthooks'
As described here:
http://stackoverflow.com/questions/31083061/kivy-1-9-0-windows-package-keyerror-rthooks/32366409#32366409

I've partially troubleshooted this:

---

The [kivy docs](http://kivy.org/docs/guide/packaging-windows.html) you reference mention adding the following three lines to the top of the `.spec` file:

```
from kivy.tools.packaging.pyinstaller_hooks import install_hooks
import os
install_hooks(globals())
```

The error is happening in `install_hooks(globals())`, which is defined at `\Lib\site-packages\kivy\tools\packaging\pyinstaller_hooks\__init__.py`:

```
from os.path import dirname, join
from functools import partial

curdir = dirname(__file__)

def install_hooks(sym, hookspath=None):

    _hookspath = [curdir]
    if hookspath is not None:
        _hookspath += hookspath

    sym['rthooks']['kivy'] = [join(curdir, 'rt-hook-kivy.py')]
    sym['Analysis'] = partial(sym['Analysis'], hookspath=_hookspath)
```

But the second last line is causing the message: `WARNING: stderr: KeyError: 'rthooks'`.

So it looks like it's expecting a variable `rthooks` to be in the global namespace, but it's not.

I'm not sure what to do next.



Discussion:
I'm experiencing the same issue. I understand that support for python3.x packaging is experimental, but it would be great to have a fix on this.

Same here, no kivy with python34 to me... I will try with python 2.7

There have been some changes to pyinstaller which broke some of our misuse of their api, specifically rthooks. Luckily, I found a fix. However, I ran into another py3 issue which needs to be fixed or resolved first: https://github.com/pyinstaller/pyinstaller/issues/1513.


Resolving patch:
diff --git a/kivy/tools/packaging/pyinstaller_hooks/__init__.py b/kivy/tools/packaging/pyinstaller_hooks/__init__.py
--- a/kivy/tools/packaging/pyinstaller_hooks/__init__.py
+++ b/kivy/tools/packaging/pyinstaller_hooks/__init__.py
@@ -1,14 +1,15 @@
 from os.path import dirname, join
-from functools import partial
 
 curdir = dirname(__file__)
 
 
-def install_hooks(sym, hookspath=None):
+def runtime_hooks():
+    return [join(curdir, 'rt-hook-kivy.py')]
 
-    _hookspath = [curdir]
-    if hookspath is not None:
-        _hookspath += hookspath
 
-    sym['rthooks']['kivy'] = [join(curdir, 'rt-hook-kivy.py')]
-    sym['Analysis'] = partial(sym['Analysis'], hookspath=_hookspath)
+def hookspath():
+    return [curdir]
+
+
+def get_hooks():
+    return {'hookspath': hookspath(), 'runtime_hooks': runtime_hooks()}
diff --git a/kivy/tools/packaging/pyinstaller_hooks/hook-kivy.py b/kivy/tools/packaging/pyinstaller_hooks/hook-kivy.py
--- a/kivy/tools/packaging/pyinstaller_hooks/hook-kivy.py
+++ b/kivy/tools/packaging/pyinstaller_hooks/hook-kivy.py
@@ -11,19 +11,37 @@
 Check kivy documentation about how to use these hook for packaging application.
 '''
 
+from os.path import join, basename
+from distutils.version import LooseVersion
+import PyInstaller
+
 import kivy
 from kivy.factory import Factory
 
+try:
+    pyinst_ver = PyInstaller.get_version()  # pyinstaller < 3.0x
+except AttributeError:
+    pyinst_ver = PyInstaller.__version__
+
 
 def get_modules():
     return [x.get('module', None) for x in Factory.classes.values()]
 
 
-datas = [
-    (kivy.kivy_data_dir, 'kivy_install'),
-    (kivy.kivy_modules_dir, 'kivy_install'),
-    (kivy.kivy_exts_dir, 'kivy_install'),
-]
+if LooseVersion(pyinst_ver) >= LooseVersion('3.0'):
+    # in pyinstaller 3, the directory contents rather than the directory itself
+    # is copied. See https://github.com/pyinstaller/pyinstaller/issues/1513.
+    datas = [
+        (kivy.kivy_data_dir,
+         join('kivy_install', basename(kivy.kivy_data_dir))),
+        (kivy.kivy_modules_dir,
+         join('kivy_install', basename(kivy.kivy_modules_dir))),
+    ]
+else:
+    datas = [
+        (kivy.kivy_data_dir, 'kivy_install'),
+        (kivy.kivy_modules_dir, 'kivy_install'),
+    ]
 
 # extensions
 _kivy_modules = [


Test patch: