def find_module(self, module_name):
    """
    Attempts to find the module specified by *module_name* in the
    ModuleFinder's search path and returns a #ModuleInfo object.

    For builtin modules, the #ModuleInfo.filename will be None. Note that
    the #ModuleInfo.imported_from is not filled by this method. It is used
    with #ModuleFinder.iter_modules().
    """

    if not module_name:
      raise ValueError('empty module name')
    if module_name in sys.builtin_module_names:
      return ModuleInfo(module_name, None, 'builtin', [])
    if module_name in self.modules:
      return self.modules[module_name]

    parts = module_name.split('.')
    result = None
    for dirname in self.path:
      # TODO: Configurable behaviour for Python 2 where __init__.py is
      #       required and namespace packages are not automatically
      #       supported.
      script_file = os.path.join(dirname, os.sep.join(parts)) + '.py'
      if os.path.isfile(script_file):
        result = ModuleInfo(module_name, script_file, ModuleInfo.SRC)
        break
      package_file = os.path.join(dirname, os.sep.join(parts), '__init__.py')
      if os.path.isfile(package_file):
        result = ModuleInfo(module_name, package_file, ModuleInfo.SRC)
        break

      for suffix in self.native_suffixes:
        native_file = os.path.join(dirname, os.sep.join(parts)) + suffix
        if os.path.isfile(native_file):
          result = ModuleInfo(module_name, native_file, ModuleInfo.NATIVE)
          break
      if result:
        break
    else:
      return ModuleInfo(module_name, None, ModuleInfo.NOTFOUND)

    self.modules[module_name] = result
    return result
Attempts to find the module specified by *module_name* in the
    ModuleFinder's search path and returns a #ModuleInfo object.

    For builtin modules, the #ModuleInfo.filename will be None. Note that
    the #ModuleInfo.imported_from is not filled by this method. It is used
    with #ModuleFinder.iter_modules().