Repository: mne-tools/mne-python

Issue:
few errors while building 0.13 debian pkg
lazy me decided just to ask how to fix/address those two 

```
======================================================================
ERROR: Test CombineMarkersModel Traits Model
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/build/python-mne-0.13+dfsg/mne/utils.py", line 827, in dec
    return function(*args, **kwargs)
  File "/build/python-mne-0.13+dfsg/mne/gui/tests/test_marker_gui.py", line 33, in test_combine_markers_model
    assert_false(model.mrk3.can_save)
AttributeError: 'function' object has no attribute 'can_save'

======================================================================
FAIL: Test CombineMarkersModel Traits Model.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/build/python-mne-0.13+dfsg/mne/utils.py", line 827, in dec
    return function(*args, **kwargs)
  File "/build/python-mne-0.13+dfsg/mne/gui/tests/test_kit2fiff_gui.py", line 35, in test_kit2fiff_model
    assert_false(model.can_save)
AssertionError: <bound method Kit2FiffModel.<lambda> of <mne.gui._kit2fiff_gui.Kit2FiffModel object at 0x7ff3e84eea10>> is not false
    '<bound method Kit2FiffModel.<lambda> of <mne.gui._kit2fiff_gui.Kit2FiffModel object at 0x7ff3e84eea10>> is not false' = self._formatMessage('<bound method Kit2FiffModel.<lambda> of <mne.gui._kit2fiff_gui.Kit2FiffModel object at 0x7ff3e84eea10>> is not false', "%s is not false" % safe_repr(expr))
>>  raise self.failureException('<bound method Kit2FiffModel.<lambda> of <mne.gui._kit2fiff_gui.Kit2FiffModel object at 0x7ff3e84eea10>> is not false')
```



Discussion:
cc @christianbrodbeck 

Hmm, looks like a traits problem? `mrk3` should be an `Instance(MarkerPointDest)`, not a function. Haven't we had something like this before on a different platform? What platform is this on?

On Thu, 06 Oct 2016, Christian Brodbeck wrote:

>    Hmm, looks like a traits problem? mrk3 should be an
>    Instance(MarkerPointDest), not a function. Haven't we had something like
>    before on a different platform? What platform is this on?

Debian unstable (sid) amd64

Yeah I think it might have been Debian too last time.... I don't have access to Debian to even check whether the GUI works. Can we just disable the tests on Debian?

On Thu, 06 Oct 2016, Christian Brodbeck wrote:

>    Yeah I think it might have ben Debian too last time.... I don't have
>    access to Debian even check whether the GUI works. Can we just disable the
>    tests on Debian?

no cheating!   What OS you have?  I could provide a 'howto' (e.g. with
docker) to get a similar/identical environment.

I'm on OS X. Is there a demand at all for using the GUI on Debian? (This GUI is specific to KIT systems of which there are not many.) It also looks more likely than not that the problem is in the traits library, because if traits were working correctly `mrk3` would not be a function...

I believe this happens because mayavi is not available. I'm not sure how traits work (seems like black magic to me), but I noticed it before. Now I tried running the test on a platform with traits installed and no mayavi and get the same error. So maybe just add `@requires_mayavi` decorator to the test?

FWIW -- in the first test that lambda is generated by 

```
def trait_wraith(*args, **kwargs):
    # Stand in for traits to allow importing traits based modules when the
    # traits library is not installed
    return lambda x: x
```

FWIW:  I am also running under export ETS_TOOLKIT=qt4  ; well -- mayavi2 is available (theoretically ;)).  Adding `@requires_mayavi` to the first test "fixes" it and makes it skip... will do that I guess

Full cmdline to execute the test is smth like

``` shell
root@smaug:/tmp/buildd/python-mne-0.13+dfsg# ETS_TOOLKIT=qt4 MNE_DONTWRITE_HOME=true MNE_SKIP_SAMPLE_DATASET_TESTS=true MNE_FORCE_SERIAL=true MNE_SKIP_NETWORK_TESTS=1 xvfb-run --auto-servernum --server-num=20 -s "-screen 0 1024x768x24 -ac +extension GLX +render -noreset" nosetests -s -v  mne/gui/tests/test_marker_gui.py
Test CombineMarkersModel Traits Model ... /usr/lib/python2.7/dist-packages/tvtk/tools/ivtk.py:35: ImportWarning: Not importing directory '/usr/lib/python2.7/dist-packages/tvtk/pyface': missing __init__.py
  from tvtk.pyface.api import Scene, DecoratedScene
/usr/lib/python2.7/dist-packages/traits/etsconfig/etsconfig.py:373: UserWarning: Environment variable "HOME" not set, setting home directory to /tmp
  (environment_variable, parent_directory))
/usr/lib/python2.7/dist-packages/mayavi/core/base.py:19: ImportWarning: Not importing directory '/usr/lib/python2.7/dist-packages/tvtk/pyface': missing __init__.py
  from tvtk.pyface.tvtk_scene import TVTKScene
ERROR

======================================================================
ERROR: Test CombineMarkersModel Traits Model
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/build/python-mne-0.13+dfsg/mne/utils.py", line 827, in dec
    return function(*args, **kwargs)
  File "/build/python-mne-0.13+dfsg/mne/gui/tests/test_marker_gui.py", line 33, in test_combine_markers_model
    assert_false(model.mrk3.can_save)
AttributeError: 'function' object has no attribute 'can_save'
-------------------- >> begin captured logging << --------------------
traits.has_traits: WARNING: DEPRECATED: traits.has_traits.wrapped_class, 'the 'implements' class advisor has been deprecated. Use the 'provides' class decorator.
apptools.preferences.preferences: DEBUG: loading preferences from </tmp/.enthought_root/mayavi_e3/preferences.ini>
apptools.preferences.preferences: DEBUG: loading preferences from <<open file '/usr/lib/python2.7/dist-packages/mayavi/preferences/preferences.ini', mode 'rb' at 0x7fd8b7313540>>
apptools.preferences.preferences: DEBUG: loading preferences from <<open file '/usr/lib/python2.7/dist-packages/tvtk/plugins/scene/preferences.ini', mode 'rb' at 0x7fd8b7313db0>>
--------------------- >> end captured logging << ---------------------

----------------------------------------------------------------------
Ran 1 test in 1.522s

FAILED (errors=1)
```

```
```

> I'm on OS X. Is there a demand at all for using the GUI on Debian? (This
> GUI is specific to KIT systems of which there are not many.)

Given the relatively high frequency of traits-related problems relative to
this low demand, what do you think about splitting the GUI into a separate
package like mne_gui? We actually could do a `try import mne_gui as gui` in
`__init__.py`, or just ask people to import separately. The few users who
want it could easily just pip install from github. I suspect it might
simplify things a bit in the longer term given the scope of necessary
support. WDYT?

just for completness -- mayavi2 is present but "broken" -- misses pyface.tvtk_scene (some how recent upload in Debian broke it)

``` shell
root@smaug:/tmp/buildd/python-mne-0.13+dfsg# ETS_TOOLKIT=qt4 MNE_DONTWRITE_HOME=true MNE_SKIP_SAMPLE_DATASET_TESTS=true MNE_FORCE_SERIAL=true MNE_SKIP_NETWORK_TESTS=1 xvfb-run --auto-servernum --server-num=20 -s "-screen 0 1024x768x24 -ac +extension GLX +render -noreset" python -c 'import mayavi; from mayavi import mlab;'
/usr/lib/python2.7/dist-packages/traits/etsconfig/etsconfig.py:373: UserWarning: Environment variable "HOME" not set, setting home directory to /tmp
  (environment_variable, parent_directory))
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/mayavi/mlab.py", line 27, in <module>
    from mayavi.tools.camera import view, roll, yaw, pitch, move
  File "/usr/lib/python2.7/dist-packages/mayavi/tools/camera.py", line 25, in <module>
    from engine_manager import get_engine
  File "/usr/lib/python2.7/dist-packages/mayavi/tools/engine_manager.py", line 14, in <module>
    from mayavi.core.engine import Engine
  File "/usr/lib/python2.7/dist-packages/mayavi/core/engine.py", line 28, in <module>
    from mayavi.core.base import Base
  File "/usr/lib/python2.7/dist-packages/mayavi/core/base.py", line 19, in <module>
    from tvtk.pyface.tvtk_scene import TVTKScene
ImportError: No module named pyface.tvtk_scene
root@smaug:/tmp/buildd/python-mne-0.13+dfsg# apt-cache policy python-tvtk
N: Unable to locate package python-tvtk
root@smaug:/tmp/buildd/python-mne-0.13+dfsg# apt-cache search pyface
python-pyface - traits-capable windowing framework
root@smaug:/tmp/buildd/python-mne-0.13+dfsg# apt-get install python-pyface
Reading package lists... Done
Building dependency tree       
Reading state information... Done
python-pyface is already the newest version (4.5.2-1).
python-pyface set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

root@smaug:/tmp/buildd/python-mne-0.13+dfsg# dpkg -L mayavi2 | grep tvtk_scene
/usr/lib/python2.7/dist-packages/tvtk/tests/test_tvtk_scene.py

root@smaug:/tmp/buildd/python-mne-0.13+dfsg# apt-cache policy mayavi2
mayavi2:
  Installed: 4.4.3-2.2
  Candidate: 4.4.3-2.2
  Version table:
 *** 4.4.3-2.2 500
        500 http://127.0.0.1:3142/debian sid/main amd64 Packages
        100 /var/lib/dpkg/status
```

as to me -- splitting is more work later to package/maintain ;)

@Eric89GXL the coregistration GUI uses all the same basics and has a wider audience...

But I do remember that I wanted to replace the `trait_wraith` hack with raising import errors 


Resolving patch:
diff --git a/mne/utils.py b/mne/utils.py
--- a/mne/utils.py
+++ b/mne/utils.py
@@ -796,14 +796,11 @@ def requires_module(function, name, call=None):
 
     @wraps(function)
     def dec(*args, **kwargs):
-        skip = False
         try:
             exec(call) in globals(), locals()
-        except Exception:
-            skip = True
-        if skip is True:
-            raise SkipTest('Test %s skipped, requires %s'
-                           % (function.__name__, name))
+        except Exception as exc:
+            raise SkipTest('Test %s skipped, requires %s. Got exception (%s)'
+                           % (function.__name__, name, exc))
         return function(*args, **kwargs)
     return dec
 


Test patch:
diff --git a/mne/gui/tests/test_kit2fiff_gui.py b/mne/gui/tests/test_kit2fiff_gui.py
--- a/mne/gui/tests/test_kit2fiff_gui.py
+++ b/mne/gui/tests/test_kit2fiff_gui.py
@@ -13,6 +13,7 @@
 from mne.io.kit.tests import data_dir as kit_data_dir
 from mne.io import read_raw_fif
 from mne.utils import _TempDir, requires_traits, run_tests_if_main
+from mne.utils import requires_mayavi
 
 mrk_pre_path = os.path.join(kit_data_dir, 'test_mrk_pre.sqd')
 mrk_post_path = os.path.join(kit_data_dir, 'test_mrk_post.sqd')
@@ -25,6 +26,7 @@
 
 
 @requires_traits
+@requires_mayavi
 def test_kit2fiff_model():
     """Test CombineMarkersModel Traits Model."""
     from mne.gui._kit2fiff_gui import Kit2FiffModel, Kit2FiffPanel
diff --git a/mne/gui/tests/test_marker_gui.py b/mne/gui/tests/test_marker_gui.py
--- a/mne/gui/tests/test_marker_gui.py
+++ b/mne/gui/tests/test_marker_gui.py
@@ -12,6 +12,7 @@
 from mne.io.kit.tests import data_dir as kit_data_dir
 from mne.io.kit import read_mrk
 from mne.utils import _TempDir, requires_traits, run_tests_if_main
+from mne.utils import requires_mayavi
 
 mrk_pre_path = os.path.join(kit_data_dir, 'test_mrk_pre.sqd')
 mrk_post_path = os.path.join(kit_data_dir, 'test_mrk_post.sqd')
@@ -21,6 +22,7 @@
 
 
 @requires_traits
+@requires_mayavi
 def test_combine_markers_model():
     """Test CombineMarkersModel Traits Model"""
     from mne.gui._marker_gui import CombineMarkersModel, CombineMarkersPanel