Index: src/martian/core.py
===================================================================
--- src/martian/core.py	(revision 90776)
+++ src/martian/core.py	(working copy)
@@ -196,8 +196,10 @@
         self.register(InstanceMetaGrokker(self))
         self.register(GlobalMetaGrokker(self))
 
-def grok_dotted_name(dotted_name, grokker, exclude_filter=None, **kw):
-    module_info = scan.module_info_from_dotted_name(dotted_name, exclude_filter)
+def grok_dotted_name(dotted_name, grokker, exclude_filter=None,
+                     ignore_nonsource=True, **kw):
+    module_info = scan.module_info_from_dotted_name(dotted_name, exclude_filter,
+                                                    ignore_nonsource)
     grok_package(module_info, grokker, **kw)
 
 def grok_package(module_info, grokker, **kw):
Index: src/martian/scan.py
===================================================================
--- src/martian/scan.py	(revision 90776)
+++ src/martian/scan.py	(working copy)
@@ -32,14 +32,17 @@
 class ModuleInfo(object):
     implements(IModuleInfo)
 
-    def __init__(self, path, dotted_name, exclude_filter=None):
+    def __init__(self, path, dotted_name, exclude_filter=None,
+                 ignore_nonsource=True):
         # Normalize .pyc files to .py
         if path.endswith('c'):
             path = path[:-1]
         self.path = path
         self.dotted_name = dotted_name
+        self.ignore_nonsource = ignore_nonsource
 
         if exclude_filter is None:
+            # this exclude filter receives extensionless filenames
             self.exclude_filter = lambda x: False
         else:
             self.exclude_filter = exclude_filter
@@ -77,6 +80,9 @@
             dotted_name = self.dotted_name + '.' + name
             if self.exclude_filter(name):
                 continue
+            if self.ignore_nonsource:
+                if ext in ['.pyo', '.pyc']:
+                    continue
             # Case one: modules
             if (os.path.isfile(entry_path) and ext in ['.py', '.pyc']):
                 if name == '__init__':
@@ -85,24 +91,31 @@
                 if name in seen:
                     continue
                 seen.append(name)
-                module_infos.append(ModuleInfo(entry_path, dotted_name))
+                module_infos.append(
+                    ModuleInfo(entry_path,
+                               dotted_name,
+                               ignore_nonsource=self.ignore_nonsource)
+                    )
             # Case two: packages
             elif is_package(entry_path):
                 # We can blindly use __init__.py even if only
                 # __init__.pyc exists because we never actually use
                 # that filename.
                 module_infos.append(ModuleInfo(
-                    os.path.join(entry_path, '__init__.py'), dotted_name))
+                    os.path.join(entry_path, '__init__.py'), dotted_name,
+                    ignore_nonsource=self.ignore_nonsource))
         return module_infos
 
     def getSubModuleInfo(self, name):
         path = os.path.join(os.path.dirname(self.path), name)
         if is_package(path):
             return ModuleInfo(os.path.join(path, '__init__.py'),
-                              '%s.%s' % (self.package_dotted_name, name))
+                              '%s.%s' % (self.package_dotted_name, name),
+                              ignore_nonsource=self.ignore_nonsource)
         elif os.path.isfile(path + '.py') or os.path.isfile(path + '.pyc'):
                 return ModuleInfo(path + '.py',
-                                  '%s.%s' % (self.package_dotted_name, name))
+                                  '%s.%s' % (self.package_dotted_name, name),
+                                  ignore_nonsource = self.ignore_nonsource)
         else:
             return None
 
@@ -154,7 +167,8 @@
     def getAnnotation(self, key, default):
         return default
 
-def module_info_from_dotted_name(dotted_name, exclude_filter=None):
+def module_info_from_dotted_name(dotted_name, exclude_filter=None,
+                                 ignore_nonsource=True):
     if dotted_name == '__builtin__':
         # in case of the use of individually grokking something during a
         # test the dotted_name being passed in could be __builtin__
@@ -162,10 +176,12 @@
         # implements enough interface to work
         return BuiltinModuleInfo()
     module = resolve(dotted_name)
-    return ModuleInfo(module.__file__, dotted_name, exclude_filter)
+    return ModuleInfo(module.__file__, dotted_name, exclude_filter,
+                      ignore_nonsource)
 
-def module_info_from_module(module, exclude_filter=None):
-    return ModuleInfo(module.__file__, module.__name__, exclude_filter)
+def module_info_from_module(module, exclude_filter=None, ignore_nonsource=True):
+    return ModuleInfo(module.__file__, module.__name__, exclude_filter,
+                      ignore_nonsource)
 
 
 # taken from zope.dottedname.resolve
