Skip to content

Commit 1bf5aa0

Browse files
Move theme into a python package (pandas-dev#22)
1 parent c8efa02 commit 1bf5aa0

File tree

14 files changed

+197
-149
lines changed

14 files changed

+197
-149
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ install:
2626

2727
script:
2828
- set -e
29+
- pip install -e .
2930
- cd pandas-docs
3031
- python make.py html
3132
- cd ..

pandas-docs/source/conf.py

Lines changed: 82 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@
2323

2424
logger = logging.getLogger(__name__)
2525

26-
27-
sys.path.append('.')
28-
from bootstrap_html_translator import BootstrapHTML5Translator
26+
import pandas_sphinx_theme
2927

3028

3129
# -----------------------------------------------------------------------------
@@ -109,144 +107,86 @@ def run(self):
109107
# -----------------------------------------------------------------------------
110108
# Sphinx monkeypatch
111109

112-
from sphinx.environment.adapters.toctree import process_only_nodes
113-
from docutils import nodes
114-
from sphinx import addnodes
115-
116-
117-
def get_toc_for(self, docname, builder):
118-
# type: (str, Builder) -> nodes.Node
119-
"""Return a TOC nodetree -- for use on the same page only!"""
120-
tocdepth = self.env.metadata[docname].get('tocdepth', 0)
121-
try:
122-
toc = self.env.tocs[docname].deepcopy()
123-
self._toctree_prune(toc, 2, tocdepth)
124-
except KeyError:
125-
# the document does not exist anymore: return a dummy node that
126-
# renders to nothing
127-
return nodes.paragraph()
128-
process_only_nodes(toc, builder.tags)
129-
for node in toc.traverse(nodes.reference):
130-
node['refuri'] = node['anchorname'] or '#'
131-
132-
# tag toc with attributes
133-
toc.attributes['classes'].append('section-nav')
134-
135-
def tag_childs(bullet_list, level):
136-
for sub in bullet_list.children:
137-
if getattr(sub, 'tagname', '') == 'list_item':
138-
sub.attributes['classes'].extend(['toc-entry', 'toc-h{}'.format(level)])
139-
for sub2 in sub.children:
140-
if getattr(sub2, 'tagname', '') == 'bullet_list':
141-
tag_childs(sub2, level + 1)
142-
143-
tag_childs(toc, 1)
144-
145-
return toc
146-
147-
def get_toctree_for(self, docname, builder, collapse, **kwds):
148-
# type: (str, Builder, bool, Any) -> nodes.Element
149-
"""Return the global TOC nodetree."""
150-
#import pdb; pdb.set_trace()
151-
doctree = self.env.get_doctree(self.env.config.master_doc)
152-
toctrees = [] # type: List[nodes.Element]
153-
if 'includehidden' not in kwds:
154-
kwds['includehidden'] = True
155-
if 'maxdepth' not in kwds:
156-
kwds['maxdepth'] = 0
157-
kwds['collapse'] = collapse
158-
mindepth = kwds.pop('mindepth', False)
159-
for toctreenode in doctree.traverse(addnodes.toctree):
160-
toctree = self.resolve(docname, builder, toctreenode, prune=True, **kwds)
161-
if toctree:
162-
toctrees.append(toctree)
163-
if not toctrees:
164-
return None
165-
result = toctrees[0]
166-
for toctree in toctrees[1:]:
167-
result.extend(toctree.children)
168-
if mindepth and docname not in ('index', 'genindex', 'search'):
169-
#import pdb; pdb.set_trace()
170-
result = get_current_section_toctree(result)
171-
return result
172-
173-
174-
def get_current_section_toctree(toctree):
175-
actual_toctree = toctree[0]
176-
for subtoc in actual_toctree.children:
177-
if 'current' in subtoc.attributes['classes']:
178-
newtoc = subtoc.children[1]
179-
break
180-
else:
181-
newtoc = actual_toctree
182-
toctree[0] = newtoc
183-
toctree[0].attributes['classes'].extend(['nav', 'bd-sidenav', 'active'])
184-
#import pdb; pdb.set_trace()
185-
return toctree
186-
187-
188-
import sphinx.environment.adapters.toctree
189-
sphinx.environment.adapters.toctree.TocTree.get_toc_for = get_toc_for
190-
sphinx.environment.adapters.toctree.TocTree.get_toctree_for = get_toctree_for
191-
192-
193-
def convert_docutils_node(list_item):
194-
if not list_item.children:
195-
return None
196-
reference = list_item.children[0].children[0]
197-
title = reference.astext()
198-
url = reference.attributes['refuri']
199-
active = 'current' in list_item.attributes['classes']
200-
201-
nav = {}
202-
nav['title'] = title
203-
nav['url'] = url
204-
nav['children'] = []
205-
nav['active'] = active
206-
207-
if len(list_item.children) > 1:
208-
for child_item in list_item.children[1].children:
209-
child_nav = convert_docutils_node(child_item)
210-
if child_nav is not None:
211-
nav['children'].append(child_nav)
212-
213-
return nav
214-
215-
216-
def update_page_context(self, pagename, templatename, ctx, event_arg):
217-
from sphinx.environment.adapters.toctree import TocTree
218-
219-
def get_nav_object(**kwds):
220-
toctree = TocTree(self.env).get_toctree_for(
221-
pagename, self, collapse=True, **kwds)
222-
223-
nav = []
224-
for child in toctree.children[0].children:
225-
child_nav = convert_docutils_node(child)
226-
nav.append(child_nav)
227-
228-
return nav
229-
230-
def get_page_toc_object():
231-
self_toc = TocTree(self.env).get_toc_for(pagename, self)
232-
toc = self.render_partial(self_toc)['fragment']
233-
234-
try:
235-
#import pdb; pdb.set_trace()
236-
nav = convert_docutils_node(self_toc.children[0])
237-
#import pdb; pdb.set_trace()
238-
return nav
239-
except:
240-
return {}
241-
242-
#import pdb; pdb.set_trace()
243-
ctx['get_nav_object'] = get_nav_object
244-
ctx['get_page_toc_object'] = get_page_toc_object
245-
return None
246-
110+
# from sphinx.environment.adapters.toctree import process_only_nodes
111+
# from docutils import nodes
112+
# from sphinx import addnodes
113+
114+
115+
# def get_toc_for(self, docname, builder):
116+
# # type: (str, Builder) -> nodes.Node
117+
# """Return a TOC nodetree -- for use on the same page only!"""
118+
# tocdepth = self.env.metadata[docname].get('tocdepth', 0)
119+
# try:
120+
# toc = self.env.tocs[docname].deepcopy()
121+
# self._toctree_prune(toc, 2, tocdepth)
122+
# except KeyError:
123+
# # the document does not exist anymore: return a dummy node that
124+
# # renders to nothing
125+
# return nodes.paragraph()
126+
# process_only_nodes(toc, builder.tags)
127+
# for node in toc.traverse(nodes.reference):
128+
# node['refuri'] = node['anchorname'] or '#'
129+
130+
# # tag toc with attributes
131+
# toc.attributes['classes'].append('section-nav')
132+
133+
# def tag_childs(bullet_list, level):
134+
# for sub in bullet_list.children:
135+
# if getattr(sub, 'tagname', '') == 'list_item':
136+
# sub.attributes['classes'].extend(['toc-entry', 'toc-h{}'.format(level)])
137+
# for sub2 in sub.children:
138+
# if getattr(sub2, 'tagname', '') == 'bullet_list':
139+
# tag_childs(sub2, level + 1)
140+
141+
# tag_childs(toc, 1)
142+
143+
# return toc
144+
145+
# def get_toctree_for(self, docname, builder, collapse, **kwds):
146+
# # type: (str, Builder, bool, Any) -> nodes.Element
147+
# """Return the global TOC nodetree."""
148+
# #import pdb; pdb.set_trace()
149+
# doctree = self.env.get_doctree(self.env.config.master_doc)
150+
# toctrees = [] # type: List[nodes.Element]
151+
# if 'includehidden' not in kwds:
152+
# kwds['includehidden'] = True
153+
# if 'maxdepth' not in kwds:
154+
# kwds['maxdepth'] = 0
155+
# kwds['collapse'] = collapse
156+
# mindepth = kwds.pop('mindepth', False)
157+
# for toctreenode in doctree.traverse(addnodes.toctree):
158+
# toctree = self.resolve(docname, builder, toctreenode, prune=True, **kwds)
159+
# if toctree:
160+
# toctrees.append(toctree)
161+
# if not toctrees:
162+
# return None
163+
# result = toctrees[0]
164+
# for toctree in toctrees[1:]:
165+
# result.extend(toctree.children)
166+
# if mindepth and docname not in ('index', 'genindex', 'search'):
167+
# #import pdb; pdb.set_trace()
168+
# result = get_current_section_toctree(result)
169+
# return result
170+
171+
172+
# def get_current_section_toctree(toctree):
173+
# actual_toctree = toctree[0]
174+
# for subtoc in actual_toctree.children:
175+
# if 'current' in subtoc.attributes['classes']:
176+
# newtoc = subtoc.children[1]
177+
# break
178+
# else:
179+
# newtoc = actual_toctree
180+
# toctree[0] = newtoc
181+
# toctree[0].attributes['classes'].extend(['nav', 'bd-sidenav', 'active'])
182+
# #import pdb; pdb.set_trace()
183+
# return toctree
184+
185+
186+
# import sphinx.environment.adapters.toctree
187+
# sphinx.environment.adapters.toctree.TocTree.get_toc_for = get_toc_for
188+
# sphinx.environment.adapters.toctree.TocTree.get_toctree_for = get_toctree_for
247189

248-
import sphinx.builders.html
249-
sphinx.builders.html.StandaloneHTMLBuilder.update_page_context = update_page_context
250190

251191
# -----------------------------------------------------------------------------
252192

@@ -420,7 +360,7 @@ def get_page_toc_object():
420360

421361
# The theme to use for HTML and HTML Help pages. Major themes that come with
422362
# Sphinx are currently 'default' and 'sphinxdoc'.
423-
html_theme = 'bootstrap_docs_theme'
363+
html_theme = 'pandas_sphinx_theme'
424364

425365
# The style sheet to use for HTML and HTML Help pages. A file of that name
426366
# must exist either in Sphinx' static/ path, or in one of the custom paths
@@ -433,7 +373,7 @@ def get_page_toc_object():
433373
# html_theme_options = {}
434374

435375
# Add any paths that contain custom themes here, relative to this directory.
436-
html_theme_path = ['_themes']
376+
#html_theme_path = ['_themes']
437377

438378
# The name for this set of Sphinx documents. If None, it defaults to
439379
# "<project> v<release> documentation".
@@ -989,4 +929,3 @@ def setup(app):
989929
app.add_autodocumenter(AccessorMethodDocumenter)
990930
app.add_autodocumenter(AccessorCallableDocumenter)
991931
app.add_directive('autosummary', PandasAutosummary)
992-
app.set_translator('html', BootstrapHTML5Translator)

pandas_sphinx_theme/__init__.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
"""
2+
Sphinx Bootstrap theme.
3+
4+
Adapted for the pandas documentation.
5+
"""
6+
import os
7+
8+
import sphinx.builders.html
9+
10+
from .bootstrap_html_translator import BootstrapHTML5Translator
11+
12+
13+
__version__ = "0.0.1.dev0"
14+
15+
16+
# -----------------------------------------------------------------------------
17+
# Sphinx monkeypatch for adding toctree objects into context
18+
19+
20+
def convert_docutils_node(list_item):
21+
if not list_item.children:
22+
return None
23+
reference = list_item.children[0].children[0]
24+
title = reference.astext()
25+
url = reference.attributes["refuri"]
26+
active = "current" in list_item.attributes["classes"]
27+
28+
nav = {}
29+
nav["title"] = title
30+
nav["url"] = url
31+
nav["children"] = []
32+
nav["active"] = active
33+
34+
if len(list_item.children) > 1:
35+
for child_item in list_item.children[1].children:
36+
child_nav = convert_docutils_node(child_item)
37+
if child_nav is not None:
38+
nav["children"].append(child_nav)
39+
40+
return nav
41+
42+
43+
def update_page_context(self, pagename, templatename, ctx, event_arg):
44+
from sphinx.environment.adapters.toctree import TocTree
45+
46+
def get_nav_object(**kwds):
47+
toctree = TocTree(self.env).get_toctree_for(
48+
pagename, self, collapse=True, **kwds
49+
)
50+
51+
nav = []
52+
for child in toctree.children[0].children:
53+
child_nav = convert_docutils_node(child)
54+
nav.append(child_nav)
55+
56+
return nav
57+
58+
def get_page_toc_object():
59+
self_toc = TocTree(self.env).get_toc_for(pagename, self)
60+
61+
try:
62+
nav = convert_docutils_node(self_toc.children[0])
63+
return nav
64+
except:
65+
return {}
66+
67+
ctx["get_nav_object"] = get_nav_object
68+
ctx["get_page_toc_object"] = get_page_toc_object
69+
return None
70+
71+
72+
sphinx.builders.html.StandaloneHTMLBuilder.update_page_context = update_page_context
73+
74+
75+
# -----------------------------------------------------------------------------
76+
77+
78+
def get_html_theme_path():
79+
"""Return list of HTML theme paths."""
80+
theme_path = os.path.abspath(os.path.dirname(__file__))
81+
return [theme_path]
82+
83+
84+
def setup(app):
85+
theme_path = get_html_theme_path()[0]
86+
app.add_html_theme("pandas_sphinx_theme", theme_path)
87+
app.set_translator("html", BootstrapHTML5Translator)

pandas-docs/source/_themes/bootstrap_docs_theme/docs-sidebar.html renamed to pandas_sphinx_theme/docs-sidebar.html

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,6 @@
3434
{% endfor %}
3535
</ul>
3636

37-
<!--
38-
{# Adding this because our list is not yet with two levels#}
39-
<div class="bd-toc-item active">
40-
{{ toctree(includehidden=theme_sidebar_includehidden, collapse=theme_sidebar_collapse, mindepth=True) }}
41-
</div>
42-
-->
4337
</nav>
4438

4539

setup.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""Sphinx Bootstrap Theme package."""
2+
from setuptools import setup
3+
4+
from pandas_sphinx_theme import __version__
5+
6+
7+
setup(
8+
name="pandas-sphinx-theme",
9+
version=__version__,
10+
description="Sphinx Bootstrap Theme - pandas version.",
11+
url="https://github.com/pandas-dev/pandas-sphinx-theme",
12+
#
13+
packages=["pandas_sphinx_theme"],
14+
package_data={
15+
"pandas_sphinx_theme": [
16+
"theme.conf",
17+
"*.html",
18+
"static/css/*.css",
19+
"static/js/*.js",
20+
"static/img/*",
21+
]
22+
},
23+
include_package_data=True,
24+
# See http://www.sphinx-doc.org/en/stable/theming.html#distribute-your-theme-as-a-python-package
25+
entry_points={"sphinx.html_themes": ["pandas_sphinx_theme = pandas_sphinx_theme"]},
26+
install_requires=["sphinx"],
27+
)

0 commit comments

Comments
 (0)