summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshimizukawa <shimizukawa@gmail.com>2013-09-16 23:57:58 +0900
committershimizukawa <shimizukawa@gmail.com>2013-09-16 23:57:58 +0900
commit4f10b03d228f6453d4ba7cc27eb5a1236e710394 (patch)
tree785bb86320595925ccc132a7d0a58889c936342a
parent0f6902e6f88b198cf8ee815d11bae6268084f695 (diff)
downloadsphinx-4f10b03d228f6453d4ba7cc27eb5a1236e710394.tar.gz
Add feature: theme package collection by using setuptools plugin mechanism.
-rw-r--r--CHANGES1
-rw-r--r--doc/theming.rst29
-rw-r--r--sphinx/theming.py47
3 files changed, 74 insertions, 3 deletions
diff --git a/CHANGES b/CHANGES
index 4d244985..848e9486 100644
--- a/CHANGES
+++ b/CHANGES
@@ -16,6 +16,7 @@ Features added
* PR#136: Autodoc directives now support an ``imported-members`` option to
include members imported from different modules.
* New locales: Macedonian, Sinhala, Indonesian.
+* Theme package collection by using setuptools plugin mechanism.
Incompatible changes
--------------------
diff --git a/doc/theming.rst b/doc/theming.rst
index 0375bc71..771dfb96 100644
--- a/doc/theming.rst
+++ b/doc/theming.rst
@@ -34,7 +34,7 @@ That would give you the default theme, but with a sidebar on the right side and
a black background for the relation bar (the bar with the navigation links at
the page's top and bottom).
-If the theme does not come with Sphinx, it can be in two forms: either a
+If the theme does not come with Sphinx, it can be in two static forms: either a
directory (containing :file:`theme.conf` and other needed files), or a zip file
with the same contents. Either of them must be put where Sphinx can find it;
for this there is the config value :confval:`html_theme_path`. It gives a list
@@ -46,6 +46,33 @@ file :file:`blue.zip`, you can put it right in the directory containing
html_theme = "blue"
html_theme_path = ["."]
+The third form provides your theme path dynamically to Sphinx if ``setuptools``
+installed. You can provide ``sphinx_themes`` entry_points section in your setup.py
+and write get_path function in this case that return path of themes::
+
+ // in your 'setup.py'
+
+ setup(
+ ...
+ entry_points = {
+ 'sphinx_themes': [
+ 'path = your_package:get_path',
+ ]
+ },
+ ...
+ )
+
+ // in 'your_package.py'
+
+ from os import path
+ package_dir = path.abspath(path.dirname(__file__))
+ template_path = path.join(package_dir, 'themes')
+
+ def get_path():
+ return template_path
+
+.. versionadded:: 1.2
+ 'sphinx_themes' entry_points feature.
.. _builtin-themes:
diff --git a/sphinx/theming.py b/sphinx/theming.py
index dd20aa2b..c7f73478 100644
--- a/sphinx/theming.py
+++ b/sphinx/theming.py
@@ -16,6 +16,11 @@ import tempfile
import ConfigParser
from os import path
+try:
+ import pkg_resources
+except ImportError:
+ pkg_resources = False
+
from sphinx import package_dir
from sphinx.errors import ThemeError
@@ -59,10 +64,22 @@ class Theme(object):
tinfo = None
cls.themes[tname] = (path.join(themedir, theme), tinfo)
+ @classmethod
+ def load_extra_themes(cls):
+ for themedir in load_theme_plugins():
+ if not path.isdir(themedir):
+ continue
+ for theme in os.listdir(themedir):
+ if not path.isfile(path.join(themedir, theme, THEMECONF)):
+ continue
+ cls.themes[theme] = (path.join(themedir, theme), None)
+
def __init__(self, name):
if name not in self.themes:
- raise ThemeError('no theme named %r found '
- '(missing theme.conf?)' % name)
+ self.load_extra_themes()
+ if name not in self.themes:
+ raise ThemeError('no theme named %r found '
+ '(missing theme.conf?)' % name)
self.name = name
tdir, tinfo = self.themes[name]
@@ -152,3 +169,29 @@ class Theme(object):
pass
if self.base:
self.base.cleanup()
+
+
+def load_theme_plugins():
+ """load plugins by using``sphinx_themes`` section in setuptools entry_points.
+ This API will return list of directory that contain some theme directory.
+ """
+
+ if not pkg_resources:
+ return []
+
+ theme_paths = []
+
+ for plugin in pkg_resources.iter_entry_points('sphinx_themes'):
+ func_or_path = plugin.load()
+ try:
+ path = func_or_path()
+ except:
+ path = func_or_path
+
+ if isinstance(path, basestring):
+ theme_paths.append(path)
+ else:
+ raise ThemeError('Plugin %r does not response correctly.' %
+ plugin.module_name)
+
+ return theme_paths