Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@

sphinx_gallery_conf = {
'doc_module': 'sklearn',
'backreferences_dir': os.path.join('modules', 'generated'),
'reference_url': {
'sklearn': None,
'matplotlib': 'http://matplotlib.org',
Expand Down
3 changes: 1 addition & 2 deletions doc/sphinxext/sphinx_gallery/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
"""
==============
Sphinx Gallery
==============

"""
import os
__version__ = '0.1.7'
__version__ = '0.1.11'


def glr_path_static():
Expand Down
22 changes: 0 additions & 22 deletions doc/sphinxext/sphinx_gallery/_static/gallery.css
Original file line number Diff line number Diff line change
Expand Up @@ -190,25 +190,3 @@ p.sphx-glr-signature a.reference.external {
margin-left: auto;
display: table;
}

a.sphx-glr-code-links:hover{
text-decoration: none;
}

a.sphx-glr-code-links[tooltip]:hover:before{
background: rgba(0,0,0,.8);
border-radius: 5px;
color: white;
content: attr(tooltip);
padding: 5px 15px;
position: absolute;
z-index: 98;
width: 16em;
word-break: normal;
white-space: normal;
display: inline-block;
text-align: center;
text-indent: 0;
margin-left: 0; /* Use zero to avoid overlapping with sidebar */
margin-top: 1.2em;
}
23 changes: 16 additions & 7 deletions doc/sphinxext/sphinx_gallery/backreferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
# Author: Óscar Nájera
# License: 3-clause BSD
"""
========================
Backreferences Generator
========================

Reviews generated example files in order to keep track of used modules
Parses example file code in order to keep track of used functions
"""

from __future__ import print_function
Expand Down Expand Up @@ -97,7 +96,10 @@ def identify_names(code):
e.HelloWorld HelloWorld d d
"""
finder = NameFinder()
finder.visit(ast.parse(code))
try:
finder.visit(ast.parse(code))
except SyntaxError:
return {}

example_code_obj = {}
for name, full_name in finder.get_mapping():
Expand Down Expand Up @@ -133,8 +135,6 @@ def scan_used_functions(example_file, gallery_conf):
return backrefs


# XXX This figure:: uses a forward slash even on Windows, but the op.join's
# elsewhere will use backslashes...
THUMBNAIL_TEMPLATE = """
.. raw:: html

Expand Down Expand Up @@ -162,6 +162,10 @@ def _thumbnail_div(full_dir, fname, snippet, is_backref=False):
"""Generates RST to place a thumbnail in a gallery"""
thumb = os.path.join(full_dir, 'images', 'thumb',
'sphx_glr_%s_thumb.png' % fname[:-3])

# Inside rst files forward slash defines paths
thumb = thumb.replace(os.sep, "/")

ref_name = os.path.join(full_dir, fname).replace(os.path.sep, '_')

template = BACKREF_THUMBNAIL_TEMPLATE if is_backref else THUMBNAIL_TEMPLATE
Expand All @@ -172,17 +176,22 @@ def write_backreferences(seen_backrefs, gallery_conf,
target_dir, fname, snippet):
"""Writes down back reference files, which include a thumbnail list
of examples using a certain module"""
if gallery_conf['backreferences_dir'] is None:
return

example_file = os.path.join(target_dir, fname)
build_target_dir = os.path.relpath(target_dir, gallery_conf['src_dir'])
backrefs = scan_used_functions(example_file, gallery_conf)
for backref in backrefs:
include_path = os.path.join(gallery_conf['mod_example_dir'],
include_path = os.path.join(gallery_conf['src_dir'],
gallery_conf['backreferences_dir'],
'%s.examples' % backref)
seen = backref in seen_backrefs
with open(include_path, 'a' if seen else 'w') as ex_file:
if not seen:
heading = '\n\nExamples using ``%s``' % backref
ex_file.write(heading + '\n')
ex_file.write('^' * len(heading) + '\n')
ex_file.write(_thumbnail_div(target_dir, fname, snippet,
ex_file.write(_thumbnail_div(build_target_dir, fname, snippet,
is_backref=True))
seen_backrefs.add(backref)
143 changes: 75 additions & 68 deletions doc/sphinxext/sphinx_gallery/docs_resolv.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# -*- coding: utf-8 -*-
# Author: Óscar Nájera
# License: 3-clause BSD
###############################################################################
# Documentation link resolver objects
"""
Link resolver objects
=====================
"""
from __future__ import print_function
import gzip
import os
Expand All @@ -11,6 +13,8 @@
import shelve
import sys

from sphinx.util.console import fuchsia

# Try Python 2 first, otherwise load from Python 3
try:
import cPickle as pickle
Expand Down Expand Up @@ -291,7 +295,7 @@ def resolve(self, cobj, this_url):
cobj : dict
Dict with information about the "code object" for which we are
resolving a link.
cobi['name'] : function or class name (str)
cobj['name'] : function or class name (str)
cobj['module_short'] : shortened module name (str)
cobj['module'] : module name (str)
this_url: str
Expand Down Expand Up @@ -331,16 +335,17 @@ def _embed_code_links(app, gallery_conf, gallery_dir):
# Add resolvers for the packages for which we want to show links
doc_resolvers = {}

src_gallery_dir = os.path.join(app.builder.srcdir, gallery_dir)
for this_module, url in gallery_conf['reference_url'].items():
try:
if url is None:
doc_resolvers[this_module] = SphinxDocLinkResolver(
app.builder.outdir,
gallery_dir,
src_gallery_dir,
relative=True)
else:
doc_resolvers[this_module] = SphinxDocLinkResolver(url,
gallery_dir)
src_gallery_dir)

except HTTPError as e:
print("The following HTTP Error has occurred:\n")
Expand All @@ -357,72 +362,74 @@ def _embed_code_links(app, gallery_conf, gallery_dir):
gallery_dir))

# patterns for replacement
link_pattern = ('<a href="%s" class="sphx-glr-code-links" '
'tooltip="Link to documentation for %s">%s</a>')
link_pattern = ('<a href="%s" title="View documentation for %s">%s</a>')
orig_pattern = '<span class="n">%s</span>'
period = '<span class="o">.</span>'

for dirpath, _, filenames in os.walk(html_gallery_dir):
for fname in filenames:
print('\tprocessing: %s' % fname)
full_fname = os.path.join(html_gallery_dir, dirpath, fname)
subpath = dirpath[len(html_gallery_dir) + 1:]
pickle_fname = os.path.join(gallery_dir, subpath,
fname[:-5] + '_codeobj.pickle')

if os.path.exists(pickle_fname):
# we have a pickle file with the objects to embed links for
with open(pickle_fname, 'rb') as fid:
example_code_obj = pickle.load(fid)
fid.close()
str_repl = {}
# generate replacement strings with the links
for name, cobj in example_code_obj.items():
this_module = cobj['module'].split('.')[0]

if this_module not in doc_resolvers:
continue

try:
link = doc_resolvers[this_module].resolve(cobj,
full_fname)
except (HTTPError, URLError) as e:
if isinstance(e, HTTPError):
extra = e.code
else:
extra = e.reason
print("\t\tError resolving %s.%s: %r (%s)"
% (cobj['module'], cobj['name'], e, extra))
continue

if link is not None:
parts = name.split('.')
name_html = period.join(orig_pattern % part
for part in parts)
full_function_name = '%s.%s' % (
cobj['module'], cobj['name'])
str_repl[name_html] = link_pattern % (
link, full_function_name, name_html)
# do the replacement in the html file

# ensure greediness
names = sorted(str_repl, key=len, reverse=True)
expr = re.compile(r'(?<!\.)\b' + # don't follow . or word
'|'.join(re.escape(name)
for name in names))

def substitute_link(match):
return str_repl[match.group()]

if len(str_repl) > 0:
with open(full_fname, 'rb') as fid:
lines_in = fid.readlines()
with open(full_fname, 'wb') as fid:
for line in lines_in:
line = line.decode('utf-8')
line = expr.sub(substitute_link, line)
fid.write(line.encode('utf-8'))
print('[done]')
# This could be turned into a generator if necessary, but should be okay
flat = [[dirpath, filename]
for dirpath, _, filenames in os.walk(html_gallery_dir)
for filename in filenames]
iterator = app.status_iterator(
flat, os.path.basename(html_gallery_dir), colorfunc=fuchsia,
length=len(flat), stringify_func=lambda x: os.path.basename(x[1]))
for dirpath, fname in iterator:
full_fname = os.path.join(html_gallery_dir, dirpath, fname)
subpath = dirpath[len(html_gallery_dir) + 1:]
pickle_fname = os.path.join(src_gallery_dir, subpath,
fname[:-5] + '_codeobj.pickle')

if os.path.exists(pickle_fname):
# we have a pickle file with the objects to embed links for
with open(pickle_fname, 'rb') as fid:
example_code_obj = pickle.load(fid)
fid.close()
str_repl = {}
# generate replacement strings with the links
for name, cobj in example_code_obj.items():
this_module = cobj['module'].split('.')[0]

if this_module not in doc_resolvers:
continue

try:
link = doc_resolvers[this_module].resolve(cobj,
full_fname)
except (HTTPError, URLError) as e:
if isinstance(e, HTTPError):
extra = e.code
else:
extra = e.reason
print("\n\t\tError resolving %s.%s: %r (%s)"
% (cobj['module'], cobj['name'], e, extra))
continue

if link is not None:
parts = name.split('.')
name_html = period.join(orig_pattern % part
for part in parts)
full_function_name = '%s.%s' % (
cobj['module'], cobj['name'])
str_repl[name_html] = link_pattern % (
link, full_function_name, name_html)
# do the replacement in the html file

# ensure greediness
names = sorted(str_repl, key=len, reverse=True)
regex_str = '|'.join(re.escape(name) for name in names)
regex = re.compile(regex_str)

def substitute_link(match):
return str_repl[match.group()]

if len(str_repl) > 0:
with open(full_fname, 'rb') as fid:
lines_in = fid.readlines()
with open(full_fname, 'wb') as fid:
for line in lines_in:
line = line.decode('utf-8')
line = regex.sub(substitute_link, line)
fid.write(line.encode('utf-8'))


def embed_code_links(app, exception):
Expand Down
11 changes: 7 additions & 4 deletions doc/sphinxext/sphinx_gallery/downloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ def python_zip(file_list, gallery_path, extension='.py'):
zip file name, written as `target_dir_{python,jupyter}.zip`
depending on the extension
"""
zipname = gallery_path.replace(os.path.sep, '_')
zipname = os.path.basename(gallery_path)
zipname += '_python' if extension == '.py' else '_jupyter'
zipname = os.path.join(gallery_path, zipname + '.zip')

zipf = zipfile.ZipFile(zipname, mode='w')
for fname in file_list:
file_src = os.path.splitext(fname)[0] + extension
zipf.write(file_src)
zipf.write(file_src, os.path.relpath(file_src, gallery_path))
zipf.close()

return zipname
Expand Down Expand Up @@ -110,8 +110,11 @@ def generate_zipfiles(gallery_dir):
py_zipfile = python_zip(listdir, gallery_dir)
jy_zipfile = python_zip(listdir, gallery_dir, ".ipynb")

def rst_path(filepath):
return filepath.replace(os.sep, '/')

dw_rst = CODE_ZIP_DOWNLOAD.format(os.path.basename(py_zipfile),
py_zipfile,
rst_path(py_zipfile),
os.path.basename(jy_zipfile),
jy_zipfile)
rst_path(jy_zipfile))
return dw_rst
Loading