[Python-modules-commits] [cloud-sptheme] 01/10: Import cloud-sptheme_1.8.0.orig.tar.gz

Sandro Tosi morph at moszumanska.debian.org
Tue Dec 13 12:22:13 UTC 2016


This is an automated email from the git hooks/post-receive script.

morph pushed a commit to branch master
in repository cloud-sptheme.

commit 8d2f240f4fd198977cd9c73a2b34804bada9bccb
Author: Sandro Tosi <morph at debian.org>
Date:   Tue Dec 13 06:59:55 2016 -0500

    Import cloud-sptheme_1.8.0.orig.tar.gz
---
 CHANGES                                            |  111 +-
 MANIFEST.in                                        |    1 +
 PKG-INFO                                           |    5 +-
 cloud_sptheme.egg-info/PKG-INFO                    |    5 +-
 cloud_sptheme.egg-info/SOURCES.txt                 |   30 +-
 cloud_sptheme.egg-info/entry_points.txt            |    3 +
 cloud_sptheme.egg-info/requires.txt                |    2 +-
 cloud_sptheme/__init__.py                          |   31 +-
 cloud_sptheme/ext/__init__.pyc                     |  Bin 0 -> 413 bytes
 cloud_sptheme/ext/autoattribute_search_bases.py    |   62 +
 cloud_sptheme/ext/autoattribute_search_bases.pyc   |  Bin 0 -> 1964 bytes
 cloud_sptheme/ext/autodoc_sections.py              |  420 +++-
 cloud_sptheme/ext/autodoc_sections.pyc             |  Bin 0 -> 7433 bytes
 cloud_sptheme/ext/docfield_markup.py               |   67 +
 cloud_sptheme/ext/docfield_markup.pyc              |  Bin 0 -> 1841 bytes
 cloud_sptheme/ext/escaped_samp_literals.py         |   27 +-
 cloud_sptheme/ext/escaped_samp_literals.pyc        |  Bin 0 -> 2898 bytes
 cloud_sptheme/ext/index_styling.py                 |   11 +-
 cloud_sptheme/ext/index_styling.pyc                |  Bin 0 -> 2632 bytes
 cloud_sptheme/ext/issue_tracker.py                 |   11 +-
 cloud_sptheme/ext/issue_tracker.pyc                |  Bin 0 -> 3341 bytes
 cloud_sptheme/ext/page_only.py                     |  191 ++
 cloud_sptheme/ext/perpage.py                       |    5 +
 cloud_sptheme/ext/relbar_toc.py                    |   21 +-
 cloud_sptheme/ext/relbar_toc.pyc                   |  Bin 0 -> 1407 bytes
 cloud_sptheme/ext/role_index.py                    |  119 +
 cloud_sptheme/ext/table_styling.css                |   18 +
 cloud_sptheme/ext/table_styling.py                 |   10 +-
 cloud_sptheme/ext/table_styling.pyc                |  Bin 0 -> 7991 bytes
 cloud_sptheme/make_helper.py                       |   44 +-
 cloud_sptheme/themes/cloud/globaltoc.html          |    2 +-
 cloud_sptheme/themes/cloud/layout.html             |   29 +-
 cloud_sptheme/themes/cloud/localtoc.html           |    2 +-
 cloud_sptheme/themes/cloud/quicklinks.html         |    2 +-
 cloud_sptheme/themes/cloud/relations.html          |    8 +-
 cloud_sptheme/themes/cloud/static/cloud.css_t      | 2482 ++++++++++++++------
 cloud_sptheme/themes/cloud/static/cloud.js_t       | 1420 ++++++++---
 cloud_sptheme/themes/cloud/static/icon-caution.png |  Bin 0 -> 1100 bytes
 cloud_sptheme/themes/cloud/static/icon-danger.png  |  Bin 0 -> 1272 bytes
 cloud_sptheme/themes/cloud/static/jquery.cookie.js |  154 +-
 cloud_sptheme/themes/cloud/theme.conf              |  137 +-
 cloud_sptheme/themes/greencloud/theme.conf         |    5 +-
 cloud_sptheme/themes/magenta_cloud/theme.conf      |   15 +
 cloud_sptheme/themes/redcloud/static/overlay.jpg   |  Bin 7973 -> 0 bytes
 cloud_sptheme/themes/redcloud/static/overlay.xcf   |  Bin 990868 -> 0 bytes
 .../themes/redcloud/static/redcloud.css_t          |   24 -
 cloud_sptheme/themes/redcloud/theme.conf           |   20 +-
 cloud_sptheme/themes/solarcloud/theme.conf         |   73 +
 cloud_sptheme/utils.py                             |   81 +
 docs/_static/logo-128.png                          |  Bin 11941 -> 0 bytes
 docs/_static/logo-64.png                           |  Bin 5481 -> 0 bytes
 docs/_static/longline.txt                          |    4 +
 docs/cloud_theme.rst                               |   52 +-
 docs/cloud_theme_test.rst                          |   93 +-
 docs/conf.py                                       |    5 +-
 docs/contents.rst                                  |    4 +
 docs/index.rst                                     |   18 +
 docs/install.rst                                   |    6 +-
 ...loud_sptheme.ext.autoattribute_search_bases.rst |   16 +
 docs/lib/cloud_sptheme.ext.autodoc_sections.rst    |   36 +-
 docs/lib/cloud_sptheme.ext.docfield_markup.rst     |   16 +
 docs/lib/cloud_sptheme.ext.index_styling.rst       |    2 +-
 docs/lib/cloud_sptheme.ext.issue_tracker.rst       |    2 +-
 docs/lib/cloud_sptheme.ext.page_only.rst           |    2 +
 docs/lib/cloud_sptheme.ext.role_index.rst          |    1 +
 docs/lib/cloud_sptheme.ext.table_styling.rst       |    4 +-
 setup.cfg                                          |    6 +-
 setup.py                                           |   35 +-
 68 files changed, 4528 insertions(+), 1422 deletions(-)

diff --git a/CHANGES b/CHANGES
index d0c886a..099ad8a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,12 +1,120 @@
 .. -*- restructuredtext -*-
 
+.. _whats-new:
+
 ===============
 Release History
 ===============
 
-**1.6** (2013-12-28)
+**1.8** (2016-11-20)
+====================
+
+   * Admonitions now support "without-title" class to hide title prefix ("Note", "See also", etc)
+
+   * Added :mod:`~cloud_sptheme.ext.role_index` extension
+
+   * Added :mod:`~cloud_sptheme.ext.page_only` extension
+
+   * Fixed :mod:`~cloud_sptheme.ext.index_styling` extension to be compatible with Sphinx 1.4
+
+   * Sticky sidebar code now allows sidebar to be scrolled independantly
+     of main document -- just scroll mouse while overing over sidebar.
+
+   * Sidebar can now be viewed from mobile mode; hidden state is stored
+     independantly of large screen menu.
+
+   * ``collapsablesidebar`` flag is now ignored, sidebar is always collapsable.
+     flag will be removed in 1.9.
+
+   * A large amount of the sidebar css & js was rewritten,
+     many of the DOM classes have changed.
+
+**1.7.1** (2015-12-12)
+======================
+
+    Bugfix release
+
+    * Fixed divide-by-zero error under python 3 (:issue:`23`).
+
+    * JS url comparison code now handles ``file://`` urls (:issue:`24`).
+
+    * Now requires Sphinx >= 1.3.
+
+**1.7** (2015-07-25)
 ==========================
 
+.. note::
+
+    This theme now requires Sphinx >= 1.2 (some of the javascript code won't work
+    with the jquery version bundled in Sphinx 1.1 and earlier).
+
+New Features
+------------
+
+    * Function, class, and other object declaration now have colored backgrounds
+      (controlled by ``colored_objects`` flag).
+
+    * All python code blocks now have button to hide prompts & output text,
+      for easier copying (Adapted from python's copybutton.js) (:issue:`17`).
+
+    * Added :ref:`font sizing options <font-options>`.
+
+    * Added :ref:`document options <decor-options>` to customize look and feel.
+
+    * Added :mod:`cloud_sptheme.ext.autoattribute_search_bases` extension.
+
+    * Added :mod:`cloud_sptheme.ext.docfield_markup` extension.
+
+Other Changes
+-------------
+
+    * :mod:`~cloud_sptheme.ext.autodoc_sections` has been completely rewritten.
+      now utilitizes docutil's native RST parser, creates real section elements
+      rather than hacked up definition lists; should now handle *any* valid
+      rest directive that can be put at module-level.
+
+    * Added styling for 2nd-level section headers, and the nested section
+      headers generated by :mod:`!autodoc_sections`.
+
+    * Default font size adjusted for compactness.
+
+    * The ``popuptoc`` feature has been removed.
+      It was just too awkward to maintain the required styling.
+      May revisit in the future using a JS-based approach.
+
+    * Unified button hover look & color through relbar, sidebar, and body.
+
+    * Completely rewrote TOC highlighter code, now indicates active section,
+      and collapses inactive TOC entries that are too large.
+
+    * Makes use of Sphinx 1.2's egg entry point,
+      so :func:`~cloud_sptheme.get_theme_dir` no longer needs to be used directly.
+
+Bugfixes
+--------
+
+    * :mod:`~cloud_sptheme.ext.autodoc_sections` now monkeypatches sphinx
+      so that `:param foo:` and other fields get formatted correctly
+      when they're embedded in a nested section (:issue:`21`).
+
+    * now compatibile with Sphinx 1.3's switch from ``<tt>`` to ``<code>``
+      for literals.
+
+    * :mod:`!autodoc_sections` now monkeypatches sphinx
+      so that ``:param foo:`` and other fields get formatted correctly
+      when they're embedded in a nested section (:issue:`21`).
+
+    * :mod:`!autodoc_sections` now handles method descriptors
+      correctly (:issue:`16`).
+
+    * the sidebar collapse state is now consistent across subfolders of document
+      (:issue:`9`).
+
+    * jumping to method or attribute permalink will now highlight the object.
+
+**1.6** (2013-12-28)
+====================
+
 New Features
 ------------
     * Added ``rightsidebar`` option to base theme, ala the Sphinx default theme.
@@ -21,7 +129,6 @@ New Features
 ..
     undocumented features:
 
-    * ``lighter_decor``, ``beveled_decor``, and ``borderless_decor`` flags.
     * :mod:`!cloud_sptheme.ext.perpage` extension.
 
 Bugfixes
diff --git a/MANIFEST.in b/MANIFEST.in
index 7a8199f..819497d 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,5 +1,6 @@
 recursive-include docs *
 recursive-include cloud_sptheme/themes *
+recursive-include cloud_sptheme/ext *
 include LICENSE CHANGES README
 prune docs/_build
 exclude .hgignore *.komodoproject
diff --git a/PKG-INFO b/PKG-INFO
index 7ff0078..0b35147 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cloud_sptheme
-Version: 1.6
+Version: 1.8.0
 Summary: a nice sphinx theme named 'Cloud', and some related extensions
 Home-page: https://bitbucket.org/ecollins/cloud_sptheme
 Author: Eli Collins
@@ -15,10 +15,11 @@ Description: This is a small package containing a Sphinx theme named "Cloud",
 Keywords: sphinx extension theme
 Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
+Classifier: Framework :: Sphinx :: Extension
+Classifier: Framework :: Sphinx :: Theme
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: BSD License
 Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 2.5
 Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
diff --git a/cloud_sptheme.egg-info/PKG-INFO b/cloud_sptheme.egg-info/PKG-INFO
index b060f59..9a51024 100644
--- a/cloud_sptheme.egg-info/PKG-INFO
+++ b/cloud_sptheme.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cloud-sptheme
-Version: 1.6
+Version: 1.8.0
 Summary: a nice sphinx theme named 'Cloud', and some related extensions
 Home-page: https://bitbucket.org/ecollins/cloud_sptheme
 Author: Eli Collins
@@ -15,10 +15,11 @@ Description: This is a small package containing a Sphinx theme named "Cloud",
 Keywords: sphinx extension theme
 Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
+Classifier: Framework :: Sphinx :: Extension
+Classifier: Framework :: Sphinx :: Theme
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: BSD License
 Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 2.5
 Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
diff --git a/cloud_sptheme.egg-info/SOURCES.txt b/cloud_sptheme.egg-info/SOURCES.txt
index 9312565..24d0499 100644
--- a/cloud_sptheme.egg-info/SOURCES.txt
+++ b/cloud_sptheme.egg-info/SOURCES.txt
@@ -6,20 +6,36 @@ setup.cfg
 setup.py
 cloud_sptheme/__init__.py
 cloud_sptheme/make_helper.py
+cloud_sptheme/utils.py
 cloud_sptheme.egg-info/PKG-INFO
 cloud_sptheme.egg-info/SOURCES.txt
 cloud_sptheme.egg-info/dependency_links.txt
+cloud_sptheme.egg-info/entry_points.txt
 cloud_sptheme.egg-info/not-zip-safe
 cloud_sptheme.egg-info/requires.txt
 cloud_sptheme.egg-info/top_level.txt
 cloud_sptheme/ext/__init__.py
+cloud_sptheme/ext/__init__.pyc
+cloud_sptheme/ext/autoattribute_search_bases.py
+cloud_sptheme/ext/autoattribute_search_bases.pyc
 cloud_sptheme/ext/autodoc_sections.py
+cloud_sptheme/ext/autodoc_sections.pyc
+cloud_sptheme/ext/docfield_markup.py
+cloud_sptheme/ext/docfield_markup.pyc
 cloud_sptheme/ext/escaped_samp_literals.py
+cloud_sptheme/ext/escaped_samp_literals.pyc
 cloud_sptheme/ext/index_styling.py
+cloud_sptheme/ext/index_styling.pyc
 cloud_sptheme/ext/issue_tracker.py
+cloud_sptheme/ext/issue_tracker.pyc
+cloud_sptheme/ext/page_only.py
 cloud_sptheme/ext/perpage.py
 cloud_sptheme/ext/relbar_toc.py
+cloud_sptheme/ext/relbar_toc.pyc
+cloud_sptheme/ext/role_index.py
+cloud_sptheme/ext/table_styling.css
 cloud_sptheme/ext/table_styling.py
+cloud_sptheme/ext/table_styling.pyc
 cloud_sptheme/themes/cloud/globaltoc.html
 cloud_sptheme/themes/cloud/layout.html
 cloud_sptheme/themes/cloud/localtoc.html
@@ -28,6 +44,8 @@ cloud_sptheme/themes/cloud/relations.html
 cloud_sptheme/themes/cloud/theme.conf
 cloud_sptheme/themes/cloud/static/cloud.css_t
 cloud_sptheme/themes/cloud/static/cloud.js_t
+cloud_sptheme/themes/cloud/static/icon-caution.png
+cloud_sptheme/themes/cloud/static/icon-danger.png
 cloud_sptheme/themes/cloud/static/icon-deprecated.png
 cloud_sptheme/themes/cloud/static/icon-note.png
 cloud_sptheme/themes/cloud/static/icon-seealso.png
@@ -35,10 +53,9 @@ cloud_sptheme/themes/cloud/static/icon-todo.png
 cloud_sptheme/themes/cloud/static/icon-warning.png
 cloud_sptheme/themes/cloud/static/jquery.cookie.js
 cloud_sptheme/themes/greencloud/theme.conf
+cloud_sptheme/themes/magenta_cloud/theme.conf
 cloud_sptheme/themes/redcloud/theme.conf
-cloud_sptheme/themes/redcloud/static/overlay.jpg
-cloud_sptheme/themes/redcloud/static/overlay.xcf
-cloud_sptheme/themes/redcloud/static/redcloud.css_t
+cloud_sptheme/themes/solarcloud/theme.conf
 docs/cloud_theme.rst
 docs/cloud_theme_test.rst
 docs/conf.py
@@ -47,16 +64,19 @@ docs/copyright.rst
 docs/history.rst
 docs/index.rst
 docs/install.rst
-docs/_static/logo-128.png
-docs/_static/logo-64.png
 docs/_static/logo.svg
+docs/_static/longline.txt
 docs/_static/masthead.png
 docs/_static/masthead.svg
+docs/lib/cloud_sptheme.ext.autoattribute_search_bases.rst
 docs/lib/cloud_sptheme.ext.autodoc_sections.rst
+docs/lib/cloud_sptheme.ext.docfield_markup.rst
 docs/lib/cloud_sptheme.ext.escaped_samp_literals.rst
 docs/lib/cloud_sptheme.ext.index_styling.rst
 docs/lib/cloud_sptheme.ext.issue_tracker.rst
+docs/lib/cloud_sptheme.ext.page_only.rst
 docs/lib/cloud_sptheme.ext.relbar_toc.rst
+docs/lib/cloud_sptheme.ext.role_index.rst
 docs/lib/cloud_sptheme.ext.table_styling.rst
 docs/lib/cloud_sptheme.make_helper.rst
 docs/lib/cloud_sptheme.rst
\ No newline at end of file
diff --git a/cloud_sptheme.egg-info/entry_points.txt b/cloud_sptheme.egg-info/entry_points.txt
new file mode 100644
index 0000000..68d704b
--- /dev/null
+++ b/cloud_sptheme.egg-info/entry_points.txt
@@ -0,0 +1,3 @@
+[sphinx_themes]
+path = cloud_sptheme:get_theme_dir
+
diff --git a/cloud_sptheme.egg-info/requires.txt b/cloud_sptheme.egg-info/requires.txt
index dac9b70..3ce9efe 100644
--- a/cloud_sptheme.egg-info/requires.txt
+++ b/cloud_sptheme.egg-info/requires.txt
@@ -1 +1 @@
-sphinx>=1.1
\ No newline at end of file
+sphinx>=1.4
diff --git a/cloud_sptheme/__init__.py b/cloud_sptheme/__init__.py
index ff9acc1..d62ce10 100644
--- a/cloud_sptheme/__init__.py
+++ b/cloud_sptheme/__init__.py
@@ -24,18 +24,19 @@ __all__ = [
 
     # internal helpers
     "is_cloud_theme",
-    "u",
 ]
 
 #=============================================================================
 # constants
 #=============================================================================
-__version__ = "1.6"
+__version__ = "1.8.0"
 
-# names of standard cloud extensions
-# used by most cloud themes
+# names of standard cloud extensions used by most cloud themes
 std_exts = [
     'cloud_sptheme.ext.autodoc_sections',
+    'cloud_sptheme.ext.autoattribute_search_bases',
+    'cloud_sptheme.ext.docfield_markup',
+    'cloud_sptheme.ext.escaped_samp_literals',
     'cloud_sptheme.ext.index_styling',
     'cloud_sptheme.ext.relbar_toc',
     'cloud_sptheme.ext.table_styling',
@@ -44,7 +45,6 @@ std_exts = [
 # names of all cloud extensions
 all_exts = std_exts + [
     'cloud_sptheme.ext.issue_tracker',
-    'cloud_sptheme.ext.escaped_samp_literals',
 ]
 
 #=============================================================================
@@ -55,10 +55,10 @@ _root_dir = os.path.abspath(os.path.dirname(__file__))
 def get_theme_dir():
     """Returns path to directory containing this package's Sphinx themes.
 
-    This is designed to be used when setting the ``html_theme_path``
-    option within Sphinx's ``conf.py`` file.
+    .. deprecated:: 1.7
 
-    .. seealso:: The :ref:`Cloud Sphinx Theme <cloud-theme-usage>` for a usage example.
+        As of Sphinx 1.2, this is passed to Sphinx via a ``setup.py`` entry point,
+        and no longer needs to be included in your documentation's ``conf.py``.
     """
     return os.path.join(_root_dir, "themes")
 
@@ -87,20 +87,5 @@ def is_cloud_theme(name):
     return os.path.isfile(os.path.join(get_theme_dir(), name, "theme.conf"))
 
 #=============================================================================
-# internal py2/3 compat helpers
-#=============================================================================
-PY2 = sys.version_info < (3,0)
-PY3 = not PY2
-if PY2:
-    def u(s):
-        return s.decode("unicode_escape")
-    def ru(s):
-        return s.decode("ascii")
-else:
-    def u(s):
-        return s
-    ru = u
-
-#=============================================================================
 # eof
 #=============================================================================
diff --git a/cloud_sptheme/ext/__init__.pyc b/cloud_sptheme/ext/__init__.pyc
new file mode 100644
index 0000000..01be2ba
Binary files /dev/null and b/cloud_sptheme/ext/__init__.pyc differ
diff --git a/cloud_sptheme/ext/autoattribute_search_bases.py b/cloud_sptheme/ext/autoattribute_search_bases.py
new file mode 100644
index 0000000..2ba1462
--- /dev/null
+++ b/cloud_sptheme/ext/autoattribute_search_bases.py
@@ -0,0 +1,62 @@
+"""
+cloud_sptheme.ext.autoattribute_search_bases -- monkeypatches autodoc so ``autoattribute`` searches base classes for attr doc.
+"""
+#=============================================================================
+# imports
+#=============================================================================
+# core
+import logging; log = logging.getLogger(__name__)
+# site
+# pkg
+from cloud_sptheme import __version__
+from cloud_sptheme.utils import patchapplier, monkeypatch
+# local
+__all__ = [
+    "setup",
+]
+
+#=============================================================================
+# patch
+#=============================================================================
+ at patchapplier
+def _patch_autoattribute():
+    from sphinx.ext.autodoc import AttributeDocumenter, ModuleAnalyzer, PycodeError
+
+    @monkeypatch(AttributeDocumenter)
+    def add_content(_wrapped, self, *args, **kwds):
+        if not self._datadescriptor and self.analyzer and self.objpath:
+            attr_docs = self.analyzer.find_attr_docs()
+            key = ('.'.join(self.objpath[:-1]), self.objpath[-1])
+            if key not in attr_docs:
+                # look for parent class w/ correct attr
+                if hasattr(self.parent, "__mro__"):
+                    for basecls in self.parent.__mro__[1:]:
+                        try:
+                            analyzer = ModuleAnalyzer.for_module(basecls.__module__)
+                            base_attr_docs = analyzer.find_attr_docs()
+                        except PycodeError as err:
+                            continue
+                        # FIXME: need qualname or equivalent for basecls
+                        base_key = (basecls.__name__, self.objpath[-1])
+                        if base_key in base_attr_docs:
+                            # insert data into existing analyzer
+                            # XXX: might be prettier way to handle this,
+                            #      (esp so actual source file was reported)
+                            #      but would have to duplicate much of add_content()
+                            attr_docs[key] = base_attr_docs[base_key]
+                            break
+        return _wrapped(self, *args, **kwds)
+
+#=============================================================================
+# sphinx entry point
+#=============================================================================
+def setup(app):
+    # don't apply our patch unless actually loaded by sphinx
+    _patch_autoattribute()
+
+    # identifies the version of our extension
+    return {'version': __version__}
+
+#=============================================================================
+# eoc
+#=============================================================================
diff --git a/cloud_sptheme/ext/autoattribute_search_bases.pyc b/cloud_sptheme/ext/autoattribute_search_bases.pyc
new file mode 100644
index 0000000..05787aa
Binary files /dev/null and b/cloud_sptheme/ext/autoattribute_search_bases.pyc differ
diff --git a/cloud_sptheme/ext/autodoc_sections.py b/cloud_sptheme/ext/autodoc_sections.py
index 7a8e45c..19ae99c 100644
--- a/cloud_sptheme/ext/autodoc_sections.py
+++ b/cloud_sptheme/ext/autodoc_sections.py
@@ -1,73 +1,293 @@
 """cloud_sptheme.ext.autodoc_sections - support ReST sections in docstrings"""
+#=============================================================================
+# imports
+#=============================================================================
+# core
+import inspect
 import re
 import logging; log = logging.getLogger(__name__)
+# site
+# pkg
+from cloud_sptheme import __version__
+from cloud_sptheme.utils import u, patchapplier, monkeypatch
+# local
+__all__ = [
+    "setup",
+]
 
-def indent_sections(lines, reference_prefix=''):
-    "replaces any section headers with indented paragraphs"
-    end = len(lines)-1
-    out = []
-
-    sections = []
-    indent_char = ' ' * 4
-    indent_level = 0
-    SCHARS = '#*=-^"'
-    section_chars = [""] #map of section char -> level (built up as scan progresses)
-    def get_level(c):
-        sc = section_chars[0]
-        if c not in sc:
-            sc = section_chars[0] = (sc+c)
-        return sc.index(c)
-    #FIXME: this doesn't detect double-barred sections
-    def detect_section(idx):
-        if idx == end:
-            return None
-        line = lines[idx].rstrip()
-        if not line or line.lstrip() != line:
-            return None
-        next = lines[idx+1].rstrip()
-        if next.lstrip() != next:
-            return None
-        for c in SCHARS:
-            if next.startswith(c * len(line)):
-                return c
-        return None
-    idx = 0
-    lss = False #set to true last non-empty line was a section heading
-    while idx <= end:
-        line = lines[idx].rstrip()
-        if not line:
-            if not lss:
-                out.append("")
-            idx += 1
-            continue
-        new_char = detect_section(idx)
-        if new_char:
-            new_level = get_level(new_char)
-            while sections and sections[-1] > new_level:
-                sections.pop()
-            if not sections or sections[-1] < new_level:
-                sections.append(new_level)
-            indent_level = max(0, len(sections))
-            name = line.lower().strip().replace(" ", "-").replace("--", "-")
-            indent = indent_char * (indent_level-1)
-            out.extend([
-                indent + ".. _%s:" % (reference_prefix + name),
-                indent + ".. rst-class:: nested-section nested-section-%d" % (new_level+1,),
-                "",
-                indent + "%s\n" % line.rstrip(),
-                ])
-            idx += 2 #skip section header
-            lss = True
-            continue
-        lss = False
-        indent = indent_char * indent_level
-        out.append(indent + line)
-        idx += 1
-    return out
-
-def _remove_oneline(name, lines):
-    #remove one-line description from top of module, if present,
-    #cause we don't want it being duplicated (should already be listed in module's header)
+#=============================================================================
+# internal helpers used for hacking up sphinx. almost ashamed to be doing this.
+#=============================================================================
+def get_caller_value(module, var, rtype=None, code=None):
+    """
+    helper which looks for nearest ancestor in call stack
+    which occurred in module, and return specified local variable.
+
+    :param module:
+        name of module to look for on stack
+
+    :param var:
+        name of local variable to return
+
+    :param rtype:
+        do optional type-check to ensure **name** has expected type.
+
+    :param code:
+        optionally match based on function name (``frame.f_code.co_name``)
+        as well as module.
+    """
+    frame = None
+    try:
+        frame = inspect.currentframe().f_back
+        while True:
+            if ((frame.f_globals.get("__name__") == module) and
+                (not code or frame.f_code.co_name == code)):
+                    break
+            frame = frame.f_back
+            if not frame:
+                raise RuntimeError("couldn't find module=%r, code=%r in call stack" %
+                                   (module, code or '<any>'))
+        value = frame.f_locals[var]
+        if rtype and not isinstance(value, rtype):
+            raise TypeError("%s: expected a %r instance: %r" % (var, rtype, value))
+        return value
+    finally:
+        frame = None
+
+#=============================================================================
+# autodoc monkeypatches / hacks
+#=============================================================================
+ at patchapplier
+def _patch_sphinx():
+    """
+    helper which monkeypatches sphinx to install some of our hooks.
+    """
+
+    #----------------------------------------------------------------------
+    # patch document.note_implicit_target() to look for _modify_new_desc_section
+    # attribute, as signal that it should munge up node that's passed to it,
+    # to represent new description-level section, rather than document-level section.
+    # this flag is then set by RSTState.new_subsection() patch, below.
+    # NOTE: ideally, all this action could be done by a hook w/in
+    #       RSTState.new_subsection(), but would have to modify source.
+    #----------------------------------------------------------------------
+    from docutils.nodes import document, make_id
+
+    @monkeypatch(document)
+    def note_implicit_target(_wrapped, self, target, *args, **kwds):
+        # use default behavior unless signal flag is set
+        entry = self._modify_new_desc_section
+        if not entry:
+            return _wrapped(self, target, *args, **kwds)
+        self._modify_new_desc_section = None
+
+        # NOTE: target should be section() node we're modifying,
+        #       as we just got called from RSTState.new_subsection(),
+        #       which is what sets modify_new_desc_section flag.
+        #       'entry' should be last item in memo.desc_stack
+        #       (see below).
+
+        # add our custom css classes for styling
+        # NOTE: adding 'section-header' class to H<N> node,
+        #       so that our css rules don't have to be duplicated for every H<N> value.
+        target['classes'].append("desc-section")
+        target['classes'].append("desc-section-%d" % entry['level'])
+        target[0]['classes'].append("section-header")
+
+        # for duration of call, modify settings.id_prefix to include
+        # decription prefix in any auto-generated ids. this helpers
+        # section names remaining unique even if used between classes
+        # (e.g. common names such as 'Constructor Options')
+        settings = self.settings
+        orig = settings.id_prefix
+        try:
+            if entry['prefix']:
+                if orig:
+                    settings.id_prefix = u("%s-%s") % (settings.id_prefix, entry['prefix'])
+                else:
+                    settings.id_prefix = entry['prefix']
+            return _wrapped(self, target, *args, **kwds)
+        finally:
+            settings.id_prefix = orig
+
+    document._modify_new_desc_section = None
+
+    #----------------------------------------------------------------------
+    # patch RSTState.new_subsection() to generate sections nested within
+    # a description. It reads ``memo.desc_stack`` to determine if it's within
+    # a description. If set, this attr should be a list of dicts,
+    # each entry representing a nested description (e.g. an ObjectDescription)
+    # whose content is being parsed, most recent should be last.
+    # Each entry should be a dict containing:
+    #
+    # If there are no description entries active, the normal behavior is used.
+    #
+    # Each dict should contain the following keys:
+    #   * prefix -- None, or string to use as prefix for section identifiers.
+    #               helps keep links unique w/in document.
+    #   * signode -- signature node used to generate prefix (for debugging)
+    #   * owner -- arbitary object (ObjectDescription in our case)
+    #              which added this entry to list. intended as sanity check
+    #              when popping entries back off stack.
+    #   * level -- section level w/in declaration (autoset by code below)
+    #----------------------------------------------------------------------
+    from docutils.parsers.rst.states import RSTState
+
+    @monkeypatch(RSTState)
+    def new_subsection(_wrapped, self, *args, **kwds):
+        desc_stack = getattr(self.memo, "desc_stack", None)
+        if desc_stack:
+            # after new_subsection() creates section node,
+            # it will invoke document.note_implicit_target().
+            # setting this attr signals our monkeypatch of that method (above)
+            # to make changes to that node based on desc_stack entry.
+            # NOTE: ideally, the note_implicit_target() monkeypatch,
+            #       as well as this code, would be placed inside RSTState.new_subsection(),
+            #       but that would require modifying sphinx's source :(
+            entry = desc_stack[-1]
+            entry['level'] = self.memo.section_level+1 # set level w/in description
+            self.document._modify_new_desc_section = entry # enable note hack
+
+        # hand off to real method
+        return _wrapped(self, *args, **kwds)
+
+    #----------------------------------------------------------------------
+    # monkeypatch ObjectDescription.run() so that:
+    # 1. before calling state.nested_parse(), we push a desc context
+    #    onto state_machine.desc_context_stack (see above).
+    # 2. when it does call state.nested_parse() the first time,
+    #    ``match_titles=True`` gets set.
+    #    FIXME: using a really awkward way to accomplish this :|
+    # 3. pop our context off desc_context_stack when done.
+    #----------------------------------------------------------------------
+    from sphinx.directives import ObjectDescription
+    from sphinx.addnodes import desc as DescNodeType
+
+    @monkeypatch(ObjectDescription)
+    def run(_wrapped_run, self):
+        # ObjectDescription.before_content() will be invoked right before
+        # run calls ``self.state.nested_parse()``. We take advantage of that
+        # by wrapping the instance's before_content() call so that the last
+        # thing is does is set up ``self.state`` the way we want.
+
+        # NOTE: have to patch per-instance, since subclasses that override this
+        #       don't tend to invoke super()
+        @monkeypatch(self)
+        def before_content(_wrapped_before):
+            # let real method do all the setup it wants.
+            _wrapped_before()
+
+            #----------------------------------------------------------------------
+            # need to figure out prefix to prepend to our description sections,
+            # so their IDs are unique. for now, using signature node
+            # ObjectDescription.run() has finished generating right before before_content()
+            # was called. Unfortunately, it's not available via self,
+            # so we have to reach into call stack to grab it...
+            # NOTE: ideally we would do this in ObjectDescription.run().
+            #----------------------------------------------------------------------
+            node = get_caller_value("sphinx.directives", "node",
+                                    rtype=DescNodeType, code="run")
+            # FIXME: would like a more bullet-proof way of deriving our id prefix...
+            signode = node.children[0]
+            if signode.get("ids"):
+                base = signode['ids'][0]
+            elif signode.get("names"):
+                base = signode['names'][0]
+            else:
+                base = signode.astext()
+            prefix = re.sub("[^a-zA-Z0-9_.]+", "-", base).strip("-") + "-"
+
+            # now that we've got that info, add our description context entry
+            # to the stack
+            memo = self.state.memo
+            if not hasattr(memo, "desc_stack"):
+                memo.desc_stack = []
+            memo.desc_stack.append(dict( # see new_subsection() above for dict format
+                prefix=prefix,
+                owner=self,
+                signode=signode,
+                level=0,
+            ))
+
+            #----------------------------------------------------------------------
+            # hack up ``state.nested_parse()`` so that the next time it's called,
+            # 'match_titles=True' is set. that call should happen as soon as this
+            # function returns back to ObjectDescription.run()
+            # NOTE: ideally, we would just set match_titles=True within ObjectDescription.run()
+            #----------------------------------------------------------------------
+            state = self.state
+            if not hasattr(state, "_set_next_match_titles_flag"):
+                # state is persistent object, only want to patch it once.
+                @monkeypatch(state)
+                def nested_parse(_wrapped_parse, *args, **kwds):
+                    if state._set_next_match_titles_flag:
+                        kwds['match_titles'] = True
+                        state._set_next_match_titles_flag = False
+                    return _wrapped_parse(*args, **kwds)
+
+            # signal our hack to set match_titles
+            state._set_next_match_titles_flag = True
+
+        @monkeypatch(self)
+        def after_content(_wrapped_after):
+            # remove our description context entry
+            # NOTE: ideally would do this in ObjectDescription.run()
+            desc = self.state.memo.desc_stack.pop()
+            assert desc['owner'] is self, "sanity check failed"
+
+            # let real method do it's work
+            return _wrapped_after()
+
+        # now invoke the real run() method.
+        # as soon as it calls before_content(), our hack above will patch self.state.
+        # after before_content() returns, real run method will call self.state.nested_parse(),
+        # and invoke our patched version instead.
+        return _wrapped_run(self)
+
+    #----------------------------------------------------------------------
+    # make autodoc invoke parse_nested_section_with_titles() for ALL objects
+    # if this isn't done, autodoc generates paragraphs instead of sections.
+    # this causes all nested content to be omitted
+    # FIXME: why is the lack of this causing a problem? should track it down.
+    #----------------------------------------------------------------------
+    from sphinx.ext.autodoc import Documenter
+    Documenter.titles_allowed = True
+
+    #----------------------------------------------------------------------
+    # finally, monkeypatch DocFieldTransformer.transform_all()
+    # so that it transforms doc fields  within one of our nested sections
+    # (default code only looks at top-level nodes)
+    #
+    # FIXME: find a cleaner way to do this :|
+    #----------------------------------------------------------------------
+    from sphinx.util.docfields import DocFieldTransformer
+    from docutils.nodes import section
+
+    @monkeypatch(DocFieldTransformer)
+    def transform_all(_wrapped, self, node):
+        # transform immediate node contents like normal
+        _wrapped(self, node)
+
+        # our nested sections show up as definition lists,
+        # so make sure transform_all is also invoked for the contents
+        # of any definition list
+        for child in node:
+            if isinstance(child, section):
+                _wrapped(self, child.children)
+
+    #----------------------------------------------------------------------
+    # sigh. done monkeypatching.
+    #----------------------------------------------------------------------
+
+#=============================================================================
+# docstring mangling
+#=============================================================================
+def trim_module_header(app, what, name, obj, options, lines):
+    """
+    helper to remove one-line description from top of module (if preset).
+    """
+    if what != "module":
+        return
     _title_re = re.compile(r"""
         ^ \s*
         ( {0} \s* -- \s* )?
@@ -77,18 +297,58 @@ def _remove_oneline(name, lines):
     if len(lines) > 1 and _title_re.match(lines[0]) and lines[1].strip() == '':
         del lines[:2]
 
-def mangle_docstrings(app, what, name, obj, options, lines):
-    if what == 'module':
-        _remove_oneline(name, lines)
-    elif what in ('class', 'exception', 'function', 'method'):
-        name = "%s.%s" % (obj.__module__, obj.__name__)
-        name = name.replace(".", "-").lower()
-        lines[:] = indent_sections(lines, reference_prefix=name + "-")
-    elif what in ('attribute',):
-        pass
-    else:
-        #FIXME: handle other cases
-        raise NotImplementedError("unknown node: %r %r" % (what, obj))
-
+#=============================================================================
+# sphinx extension entrypoint
+#=============================================================================
 def setup(app):
-    app.connect('autodoc-process-docstring', mangle_docstrings)
+    # don't patch sphinx unless this extension is actually in use
+    _patch_sphinx()
+
+    # clean up leading bit of module docstring
+    app.connect('autodoc-process-docstring', trim_module_header)
+
+    # identifies the version of our extension
+    return {'version': __version__}
+
+#=============================================================================
+# documentation helper
+#
+# NOTE: this function doesn't actually do anything,
+#       it exists to test this extension's behavior as part of docs/cloud_theme_test
+#=============================================================================
+def _doctestfunc():
+    """
+    The :mod:`~cloud_sptheme.ext.autodoc_sections` extension should generate
+    nested sections as found within object docstrings.
+
+    Nested Section
+    ==============
+
+    :param arg: xxx
+
+    .. attribute:: foo
+
+        bar
+
+    These sections can in turn contain others:
+
+    Child Section
+    -------------
+
+    Which allows breaking long class docstrings up in meaningful ways.
+
+    Child Section 2
+    ---------------
+
+    And more content
+
+    Nested Section 2
+    ================
+
+    end of class
+    """
+    pass
+
+#=============================================================================
+# eof
+#=============================================================================
diff --git a/cloud_sptheme/ext/autodoc_sections.pyc b/cloud_sptheme/ext/autodoc_sections.pyc
new file mode 100644
index 0000000..18a8ac4
Binary files /dev/null and b/cloud_sptheme/ext/autodoc_sections.pyc differ
diff --git a/cloud_sptheme/ext/docfield_markup.py b/cloud_sptheme/ext/docfield_markup.py
new file mode 100644
index 0000000..3dd1c59
--- /dev/null
+++ b/cloud_sptheme/ext/docfield_markup.py
@@ -0,0 +1,67 @@
+"""
+cloud_sptheme.ext.docfield_markup -- monkeypatches sphinx to allow ``~`` in docfields.
+"""
+#=============================================================================
+# imports
+#=============================================================================
+# core
+import logging; log = logging.getLogger(__name__)
+# site
+# pkg
+from cloud_sptheme import __version__
+from cloud_sptheme.utils import patchapplier, monkeypatch
+# local
+__all__ = [
+    "setup",
+]
+
+#=============================================================================
+# patch
+#=============================================================================
+ at patchapplier
+def _patch_docfield():
+    from sphinx.util.docfields import Field, nodes, addnodes
+
+    # NOTE: would like to just wrap make_xref(), but have to override so
+    #       many parts that just end up replicating all the code :(
+    #       hence this ignored _wrapped() entirely
+
+    @monkeypatch(Field)
+    def make_xref(_wrapped, self, rolename, domain, target, innernode=nodes.emphasis, contnode=None):
+        # 'contnode' argument added in sphinx 1.3 
+        # not sure what it does, aborting if feature is present
... 6708 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/cloud-sptheme.git



More information about the Python-modules-commits mailing list