Repository: psychopy/psychopy

Issue:
Exception during component registration seems to silently get swallowed
I just fetched `master` and started Builder, and the Pump Component seems to have disappeared from the Components panel. It ought to appear under `Custom`.


Discussion:
Ok so turns out I didn't have the dependency `pyqmix` installed into my virtual environment. The Pump Component imports `hardware.qmix`, which imports `pyqmix`. This must've raised an exception that was swallowed somewhere, leading to a silent failure when the components were compiled. So this is not a bug with the Pump Component _per se_, but rather it seems we need to look into exception handling during component registration…
I would still classify this as a bug though!
I don't recall exactly where this is being trapped during component registration and I agree that some level of message would be appropriate. 
**Simple solution is to output the message** using logging.warning() (or logging.info()? In a way the thing is that whether someone that doesn't have a pump and hasn't installed that lib (see recent discussion on pip minimal installations) do they wnat to have a warning about lots of Components not working, that they never wanted anyway

**Maybe better solution** would be that the component shows up with a strike-through icon and you can click on the icon to see a dialog box that explains what's wrong. That's obviously a lot more work
The swallowing is probably occurring as a result of 
https://github.com/psychopy/psychopy/blob/28c67754612386b9dbdb75e0e72b0c445affd203/psychopy/experiment/components/__init__.py#L149
That's actually there originally not so much to check for failing modules but for other objects (folders?) in the Components location that aren't components at all and shouldn't be treated as such. So to solve your issue we'd need to test "This does **look like** a module, but it fails to load"

Resolving patch:
diff --git a/psychopy/experiment/components/__init__.py b/psychopy/experiment/components/__init__.py
--- a/psychopy/experiment/components/__init__.py
+++ b/psychopy/experiment/components/__init__.py
@@ -22,6 +22,7 @@
 from ..params import Param
 from psychopy.localization import _translate
 from psychopy.experiment import py2js
+import psychopy.logging as logging
 
 excludeComponents = ['BaseComponent', 'BaseVisualComponent', 'BaseStandaloneRoutine'  # templates only
                      ]  # this one isn't ready yet
@@ -148,7 +149,6 @@ def getComponents(folder=None, fetchIcons=True):
         # module = imp.load_source(file[:-3], fullPath)
         # v1.83.00 used exec(implicit-relative), no go for python3:
         # exec('import %s as module' % file[:-3])
-
         # importlib.import_module eases 2.7 -> 3.x migration
         if cmpfile.endswith('.py'):
             explicit_rel_path = pkg + '.' + cmpfile[:-3]
@@ -157,7 +157,11 @@ def getComponents(folder=None, fetchIcons=True):
         try:
             module = import_module(explicit_rel_path, package=pkg)
         except ImportError:
+            logging.error(
+                'Failed to load component package `{}`. Does it have a '
+                '`__init__.py`?'.format(cmpfile))
             continue  # not a valid module (no __init__.py?)
+            
         # check for orphaned pyc files (__file__ is not a .py file)
         if hasattr(module, '__file__'):
             if not module.__file__:


Test patch: