Repository: sphinx-gallery/sphinx-gallery

Issue:
backreferences processing breaks if module accessed without attribute
The scikit-learn docs fail to build at https://circleci.com/gh/scikit-learn/scikit-learn/7314?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link due to https://github.com/sphinx-gallery/sphinx-gallery/blob/master/sphinx_gallery/backreferences.py#L106 where it is assumed that a module being referenced is always referenced with an attribute. It should be possible to reference a module without its attribute and hence for no `.` to be present.

Discussion:

Patch:
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index 6f270e1..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,2 +0,0 @@
-include CHANGES.rst
-include LICENSE
\ No newline at end of file
diff --git a/README.rst b/README.rst
index 127aa3a..92b1b89 100644
--- a/README.rst
+++ b/README.rst
@@ -21,7 +21,7 @@ Who uses Sphinx-Gallery
 
 * `Sphinx-Gallery <http://sphinx-gallery.readthedocs.io/en/latest/auto_examples/index.html>`_
 * `Scikit-learn <http://scikit-learn.org/dev/auto_examples/index.html>`_
-* `Nilearn <http://nilearn.github.io/auto_examples/index.html>`_
+* `NiLearn <http://nilearn.github.io/auto_examples/index.html>`_
 * `MNE-python <http://www.martinos.org/mne/stable/auto_examples/index.html>`_
 * `PyStruct <http://pystruct.github.io/auto_examples/index.html>`_
 * `GIMLi <http://www.pygimli.org/_examples_auto/index.html>`_
diff --git a/sphinx_gallery/backreferences.py b/sphinx_gallery/backreferences.py
index 4fe579c..28cf10a 100644
--- a/sphinx_gallery/backreferences.py
+++ b/sphinx_gallery/backreferences.py
@@ -103,7 +103,13 @@ def identify_names(code):
     for name, full_name in finder.get_mapping():
         # name is as written in file (e.g. np.asarray)
         # full_name includes resolved import path (e.g. numpy.asarray)
-        module, attribute = full_name.rsplit('.', 1)
+        splitted = full_name.rsplit('.', 1)
+        if len(splitted) == 1:
+            # module without attribute. This is not useful for
+            # backreferences
+            continue
+
+        module, attribute = splitted
         # get shortened module name
         module_short = get_short_module_name(module, attribute)
         cobj = {'name': attribute, 'module': module,
diff --git a/sphinx_gallery/gen_rst.py b/sphinx_gallery/gen_rst.py
index 2d32e1e..3141bfd 100644
--- a/sphinx_gallery/gen_rst.py
+++ b/sphinx_gallery/gen_rst.py
@@ -288,15 +288,19 @@ def extract_intro(filename):
 def get_md5sum(src_file):
     """Returns md5sum of file"""
 
-    with open(src_file, 'rb') as src_data:
+    with open(src_file, 'r') as src_data:
         src_content = src_data.read()
 
+        # data needs to be encoded in python3 before hashing
+        if sys.version_info[0] == 3:
+            src_content = src_content.encode('utf-8')
+
         src_md5 = hashlib.md5(src_content).hexdigest()
     return src_md5
 
 
 def md5sum_is_current(src_file):
-    """Checks whether src_file has the same md5 hash as the one on disk"""
+    """Returns True if src_file has the same md5 hash as the one stored on disk"""
 
     src_md5 = get_md5sum(src_file)
 
@@ -331,11 +335,11 @@ def save_figures(image_path, fig_count, gallery_conf):
     """
     figure_list = []
 
-    fig_numbers = plt.get_fignums()
-    for fig_num in fig_numbers:
+    fig_managers = matplotlib._pylab_helpers.Gcf.get_all_fig_managers()
+    for fig_mngr in fig_managers:
         # Set the fig_num figure as the current figure as we can't
         # save a figure that's not the current figure.
-        fig = plt.figure(fig_num)
+        fig = plt.figure(fig_mngr.num)
         kwargs = {}
         to_rgba = matplotlib.colors.colorConverter.to_rgba
         for attr in ['facecolor', 'edgecolor']:
@@ -344,7 +348,7 @@ def save_figures(image_path, fig_count, gallery_conf):
             if to_rgba(fig_attr) != to_rgba(default_attr):
                 kwargs[attr] = fig_attr
 
-        current_fig = image_path.format(fig_count + fig_num)
+        current_fig = image_path.format(fig_count + fig_mngr.num)
         fig.savefig(current_fig, **kwargs)
         figure_list.append(current_fig)
 
@@ -636,6 +640,8 @@ def generate_file_rst(fname, target_dir, src_dir, gallery_conf):
         # Examples may contain if __name__ == '__main__' guards
         # for in example scikit-learn if the example uses multiprocessing
         '__name__': '__main__',
+        # And they might use the __file__ parameter
+        '__file__': example_file,
     }
 
     # A simple example has two blocks: one for the


Test patch:
diff --git a/sphinx_gallery/tests/test_backreferences.py b/sphinx_gallery/tests/test_backreferences.py
index d820378..1e9e6c9 100644
--- a/sphinx_gallery/tests/test_backreferences.py
+++ b/sphinx_gallery/tests/test_backreferences.py
@@ -60,3 +60,33 @@ def test_backref_thumbnail_div():
 """
 
     assert_equal(html_div, reference)
+
+
+def test_identify_names():
+    code_str = """
+import os
+os
+
+os.path.join
+
+import sphinx_gallery.back_references as br
+br.identify_names
+
+from sphinx_gallery.back_references import identify_names
+identify_names
+"""
+    res = sg.identify_names(code_str)
+    expected = {
+        'os.path.join':
+            {'name': 'join', 'module': 'os.path', 'module_short': 'os.path'},
+        'br.identify_names':
+            {'name': 'identify_names',
+             'module': 'sphinx_gallery.back_references',
+             'module_short': 'sphinx_gallery.back_references'},
+        'identify_names':
+            {'name': 'identify_names',
+             'module': 'sphinx_gallery.back_references',
+             'module_short': 'sphinx_gallery.back_references'}
+        }
+
+    assert_equal(expected, res)
diff --git a/sphinx_gallery/tests/test_gen_rst.py b/sphinx_gallery/tests/test_gen_rst.py
index 496c4e7..d1f5309 100644
--- a/sphinx_gallery/tests/test_gen_rst.py
+++ b/sphinx_gallery/tests/test_gen_rst.py
@@ -37,6 +37,8 @@ CONTENT = [
     '"""',
     '',
     '# and now comes the module code',
+    'assert __name__ == "__main__"',
+    'assert ".py" in __file__',
     'import logging',
     'import sys',
     'x, y = 1, 2',