Better Documentation Through Automation:       Creating docutils & Sphinx Extensions       Doug Hellmann       @doughellma...
Markup LanguageSaturday, March 16, 13
Extensible                         Markup LanguageSaturday, March 16, 13
Saturday, March 16, 13
Sphinx         ApplicationSaturday, March 16, 13
Sphinx            Build         Application     Environment                            .rstSaturday, March 16, 13
Sphinx            Build      docutils         Application     Environment    parser                            .rstSaturda...
Sphinx            Build      docutils     Sphinx         Application     Environment    parser      Builder               ...
section                         title             paragraph                         #text    #text emphasis       #text   ...
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam      vulputate elementum lectus a viverra. Vivamus hendre...
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam      vulputate elementum lectus a viverra. Vivamus hendre...
.. seealso::           PyEnchant_             Python interface to enchant_.           :ref:`project-sphinxcontrib-spelling...
2.6        - Fixed a problem with hook script line endings under Cygwin          (`Issue 68 <https://bitbucket.org/dhellma...
2.6        - Fixed a problem with hook script line endings under Cygwin          (`Issue 68 <https://bitbucket.org/dhellma...
2.6        - Fixed a problem with hook script line endings under Cygwin          (`Issue 68 <https://bitbucket.org/dhellma...
`Issue 68 <https://bitbucket.org/dhellmann/virtualenvwrapper/issue/68>`_Saturday, March 16, 13
`Issue 68 <https://bitbucket.org/dhellmann/virtualenvwrapper/issue/68>`_Saturday, March 16, 13
`Issue 68 <https://bitbucket.org/dhellmann/virtualenvwrapper/issue/68>`_Saturday, March 16, 13
`Issue 68 <https://bitbucket.org/dhellmann/virtualenvwrapper/issue/68>`_                                          :bbissue...
from docutils import nodes, utils      from docutils.parsers.rst.roles import set_classes      def bbissue_role(name, rawt...
from docutils import nodes, utils      from docutils.parsers.rst.roles import set_classes      def bbissue_role(name, rawt...
from docutils import nodes, utils      from docutils.parsers.rst.roles import set_classes      def bbissue_role(name, rawt...
from docutils import nodes, utils      from docutils.parsers.rst.roles import set_classes      def bbissue_role(name, rawt...
from docutils import nodes, utils      from docutils.parsers.rst.roles import set_classes      def bbissue_role(name, rawt...
from docutils import nodes, utils      from docutils.parsers.rst.roles import set_classes      def bbissue_role(name, rawt...
app = inliner.document.settings.env.app        node = make_link_node(rawtext, app, issue,                              tex...
app = inliner.document.settings.env.app        node = make_link_node(rawtext, app, issue,                              tex...
app = inliner.document.settings.env.app        node = make_link_node(rawtext, app, issue,                              tex...
app = inliner.document.settings.env.app        node = make_link_node(rawtext, app, issue,                              tex...
app = inliner.document.settings.env.app        node = make_link_node(rawtext, app, issue,                              tex...
node = nodes.reference(rawtext,                                      type +   + utils.unescape(slug),                     ...
node = nodes.reference(rawtext,                                      type +   + utils.unescape(slug),                     ...
node = nodes.reference(rawtext,                                      type +   + utils.unescape(slug),                     ...
2.6           - Fixed a problem with hook script line endings under Cygwin             (:bbissue:`68`).           - Update...
2.6           - Fixed a problem with hook script line endings under Cygwin             (:bbissue:`68`).           - Update...
2.6        • Fixed a problem with hook script line endings under          Cygwin (issue 68).        • Updated documentatio...
.. name:: arguments                            :option: value                            :option: another-value           ...
.. name:: arguments                            :option: value                            :option: another-value           ...
.. name:: arguments                            :option: value                            :option: another-value           ...
.. name:: arguments                            :option: value                            :option: another-value           ...
.. sqltable:: List of Users         :connection_string: sqlite:///sampledata.db                 select                   n...
.. sqltable:: List of Users         :connection_string: sqlite:///sampledata.db                 select                   n...
.. sqltable:: List of Users         :connection_string: sqlite:///sampledata.db                 select                   n...
.. sqltable:: List of Users         :connection_string: sqlite:///sampledata.db                 select                   n...
from docutils.parsers.rst.directives.tables import Table      class SQLTable(Table):                option_spec = {widths:...
from docutils.parsers.rst.directives.tables import Table      class SQLTable(Table):                option_spec = {widths:...
from docutils.parsers.rst.directives.tables import Table      class SQLTable(Table):                option_spec = {widths:...
from docutils.parsers.rst.directives.tables import Table      class SQLTable(Table):                option_spec = {widths:...
from docutils.parsers.rst.directives.tables import Table      class SQLTable(Table):                option_spec = {widths:...
from docutils.parsers.rst.directives.tables import Table      class SQLTable(Table):                option_spec = {widths:...
from docutils.parsers.rst.directives.tables import Table      class SQLTable(Table):                option_spec = {widths:...
from docutils.parsers.rst.directives.tables import Table      class SQLTable(Table):                option_spec = {widths:...
def run(self):                    env = self.state.document.settings.env                    app = env.app                 ...
def run(self):                    env = self.state.document.settings.env                    app = env.app                 ...
def run(self):                    env = self.state.document.settings.env                    app = env.app                 ...
line=self.lineno)                             return [error]                         # Connect to the database            ...
line=self.lineno)                             return [error]                         # Connect to the database            ...
line=self.lineno)                             return [error]                         # Connect to the database            ...
# Run the query                         query = n.join(self.content)                         app.info(Running query %r % q...
# Run the query                         query = n.join(self.content)                         app.info(Running query %r % q...
# Run the query                         query = n.join(self.content)                         app.info(Running query %r % q...
# Run the query                         query = n.join(self.content)                         app.info(Running query %r % q...
# Handle the width settings and title                         col_widths = self.get_column_widths(max_cols)               ...
# Handle the width settings and title                         col_widths = self.get_column_widths(max_cols)               ...
# Handle the width settings and title                         col_widths = self.get_column_widths(max_cols)               ...
Table Node HierarchySaturday, March 16, 13
Table Node Hierarchy                              tableSaturday, March 16, 13
Table Node Hierarchy                              table                              tgroupSaturday, March 16, 13
Table Node Hierarchy                                    table                                    tgroup                   ...
Table Node Hierarchy                                    table                                    tgroup                   ...
Table Node Hierarchy                                    table                                    tgroup                   ...
Table Node Hierarchy                                    table                                    tgroup                   ...
Table Node Hierarchy                                      table                                     tgroup                ...
Table Node Hierarchy                                      table                                     tgroup                ...
Table Node Hierarchy                                      table                                     tgroup                ...
return [table_node] + messages                def build_table(self, table_data, col_widths, headers):                    t...
return [table_node] + messages                def build_table(self, table_data, col_widths, headers):                    t...
return [table_node] + messages                def build_table(self, table_data, col_widths, headers):                    t...
return [table_node] + messages                def build_table(self, table_data, col_widths, headers):                    t...
tgroup.extend(nodes.colspec(colwidth=col_width)                                       for col_width in col_widths)        ...
tgroup.extend(nodes.colspec(colwidth=col_width)                                       for col_width in col_widths)        ...
tgroup.extend(nodes.colspec(colwidth=col_width)                                       for col_width in col_widths)        ...
tgroup.extend(nodes.colspec(colwidth=col_width)                                       for col_width in col_widths)        ...
)            # The body of the table is made up of rows.            # Each row contains a series of entries,            # ...
)            # The body of the table is made up of rows.            # Each row contains a series of entries,            # ...
)            # The body of the table is made up of rows.            # Each row contains a series of entries,            # ...
)            # The body of the table is made up of rows.            # Each row contains a series of entries,            # ...
)            # The body of the table is made up of rows.            # Each row contains a series of entries,            # ...
.. sqltable:: List of Users        :connection_string: sqlite:///sampledata.db                select                  name...
.. sqltable:: List of Users        :connection_string: sqlite:///sampledata.db                select                  name...
.. sqltable:: List of Users        :connection_string: sqlite:///sampledata.db                select                  name...
.. sqltable:: List of Users        :connection_string: sqlite:///sampledata.db                select                  name...
Sphinx            Build      docutils     Sphinx         Application     Environment    parser      Builder               ...
Saturday, March 16, 13
.rstSaturday, March 16, 13
.rstSaturday, March 16, 13
.rst   check                                word                                 listSaturday, March 16, 13
.rst   check                                word                                 listSaturday, March 16, 13
section                         title             paragraph                         #text    #text emphasis       #text   ...
section                         title             paragraph                         #text    #text emphasis       #text   ...
from sphinx.builders import Builder      class SpellingBuilder(Builder):                name = spelling                def...
from sphinx.builders import Builder      class SpellingBuilder(Builder):                name = spelling                def...
from sphinx.builders import Builder      class SpellingBuilder(Builder):                name = spelling                def...
from sphinx.builders import Builder      class SpellingBuilder(Builder):                name = spelling                def...
from sphinx.builders import Builder      class SpellingBuilder(Builder):                name = spelling                def...
wt, encoding=UTF-8)                def write_doc(self, docname, doctree):                         filename = self.env.doc2...
wt, encoding=UTF-8)                def write_doc(self, docname, doctree):                         filename = self.env.doc2...
wt, encoding=UTF-8)                def write_doc(self, docname, doctree):                         filename = self.env.doc2...
wt, encoding=UTF-8)                def write_doc(self, docname, doctree):                         filename = self.env.doc2...
msg_parts = [ docname ]                          if lineno:                              msg_parts.append(                ...
msg_parts = [ docname ]                          if lineno:                              msg_parts.append(                ...
self.env.doc2path(docname, None),                                     lineno, word,                                     se...
self.env.doc2path(docname, None),                                     lineno, word,                                     se...
self.env.doc2path(docname, None),                                     lineno, word,                                     se...
$ sphinx-build -b spelling -d build/doctrees         source build/spelling      Running Sphinx v1.1.2      Initializing Sp...
$ sphinx-build -b spelling -d build/doctrees         source build/spelling      Running Sphinx v1.1.2      Initializing Sp...
$ sphinx-build -b spelling -d build/doctrees         source build/spelling      Running Sphinx v1.1.2      Initializing Sp...
Better Documentation Through Automation:       Creating docutils & Sphinx Extensions       Doug Hellmann       @doughellma...
Upcoming SlideShare
Loading in...5
×

Better Documentation Through Automation: Creating docutils & Sphinx Extensions

6,946

Published on

Sphinx is an incredibly useful tool for creating attractive documentation for your project, but if all you ever use it for is converting reStructuredText files to HTML you are barely scratching the surface of its power. This presentation shows how easy it is to extend Sphinx by defining new markup processors, allowing you to take your documentation to the next level.

PyCon 2013

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
6,946
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
34
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Better Documentation Through Automation: Creating docutils & Sphinx Extensions

  1. 1. Better Documentation Through Automation: Creating docutils & Sphinx Extensions Doug Hellmann @doughellmann PyCon 2013Saturday, March 16, 13
  2. 2. Markup LanguageSaturday, March 16, 13
  3. 3. Extensible Markup LanguageSaturday, March 16, 13
  4. 4. Saturday, March 16, 13
  5. 5. Sphinx ApplicationSaturday, March 16, 13
  6. 6. Sphinx Build Application Environment .rstSaturday, March 16, 13
  7. 7. Sphinx Build docutils Application Environment parser .rstSaturday, March 16, 13
  8. 8. Sphinx Build docutils Sphinx Application Environment parser Builder .rst .pdf .htmlSaturday, March 16, 13
  9. 9. section title paragraph #text #text emphasis #text literal #text #textSaturday, March 16, 13
  10. 10. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vulputate elementum lectus a viverra. Vivamus hendrerit egestas lacinia. Proin tellus lectus, scelerisque vitae rutrum eget, ultrices vel metus. Quisque :ref:`target-name` pharetra lorem vehicula lorem posuere molestie cursus ipsum ornare. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Maecenas eu sapien at tellus suscipit aliquet :pep:`8` ut non tellus. Nulla facilisis bibendum dolor, quis mattis urna posuere eget. Nulla quis dui id augue faucibus varius. Nam eu leo quam. Fusce :term:`condimentum` placerat nisi nec vestibulum. Duis tortor sapien, commodo ac faucibus nec :rfc:`1822`, rutrum quis urna. Pellentesque cursus facilisis odio, id aliquam sem commodo vestibulum. Proin eget velit sed justo ultricies vulputate.Saturday, March 16, 13
  11. 11. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vulputate elementum lectus a viverra. Vivamus hendrerit egestas lacinia. Proin tellus lectus, scelerisque vitae rutrum eget, ultrices vel metus. Quisque :ref:`target-name` pharetra lorem vehicula lorem posuere molestie cursus ipsum ornare. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Maecenas eu sapien at tellus suscipit aliquet :pep:`8` ut non tellus. Nulla facilisis bibendum dolor, quis mattis urna posuere eget. Nulla quis dui id augue faucibus varius. Nam eu leo quam. Fusce :term:`condimentum` placerat nisi nec vestibulum. Duis tortor sapien, commodo ac faucibus nec :rfc:`1822`, rutrum quis urna. Pellentesque cursus facilisis odio, id aliquam sem commodo vestibulum. Proin eget velit sed justo ultricies vulputate.Saturday, March 16, 13
  12. 12. .. seealso:: PyEnchant_ Python interface to enchant_. :ref:`project-sphinxcontrib-spelling` Project home page for the spelling checker. sphinxcontrib_ BitBucket repository for sphinxcontrib-spelling and several other Sphinx extensions. .. include:: example.py :literal: :start-after: # end-of-header-comment .. image:: figure.pngSaturday, March 16, 13
  13. 13. 2.6 - Fixed a problem with hook script line endings under Cygwin (`Issue 68 <https://bitbucket.org/dhellmann/ virtualenvwrapper/issue/68>`_). - Updated documentation to include a list of the compatible shells (:ref:`supported-shells`) and Python versions (:ref:`supported-versions`) (`Issue 70 <https:// bitbucket.org/dhellmann/virtualenvwrapper/issue/70>`_). - Fixed installation dependency on virtualenv (`Issue 60 <https://bitbucket.org/dhellmann/virtualenvwrapper/issue/60>`_). - Fixed the method for determining the Python version so it works under Python 2.4 (`Issue 61 <https://bitbucket.org/ dhellmann/virtualenvwrapper/issue/60>`_). - Converted the test infrastructure to use `tox <http://codespeak.net/tox/index.html>`_ instead of home- grown scripts in the Makefile.Saturday, March 16, 13
  14. 14. 2.6 - Fixed a problem with hook script line endings under Cygwin (`Issue 68 <https://bitbucket.org/dhellmann/ virtualenvwrapper/issue/68>`_). - Updated documentation to include a list of the compatible shells (:ref:`supported-shells`) and Python versions (:ref:`supported-versions`) (`Issue 70 <https:// bitbucket.org/dhellmann/virtualenvwrapper/issue/70>`_). - Fixed installation dependency on virtualenv (`Issue 60 <https://bitbucket.org/dhellmann/virtualenvwrapper/issue/60>`_). - Fixed the method for determining the Python version so it works under Python 2.4 (`Issue 61 <https://bitbucket.org/ dhellmann/virtualenvwrapper/issue/60>`_). - Converted the test infrastructure to use `tox <http://codespeak.net/tox/index.html>`_ instead of home- grown scripts in the Makefile.Saturday, March 16, 13
  15. 15. 2.6 - Fixed a problem with hook script line endings under Cygwin (`Issue 68 <https://bitbucket.org/dhellmann/ virtualenvwrapper/issue/68>`_). - Updated documentation to include a list of the compatible shells (:ref:`supported-shells`) and Python versions (:ref:`supported-versions`) (`Issue 70 <https:// bitbucket.org/dhellmann/virtualenvwrapper/issue/70>`_). - Fixed installation dependency on virtualenv (`Issue 60 <https://bitbucket.org/dhellmann/virtualenvwrapper/issue/60>`_). - Fixed the method for determining the Python version so it works under Python 2.4 (`Issue 61 <https://bitbucket.org/ dhellmann/virtualenvwrapper/issue/60>`_). - Converted the test infrastructure to use `tox <http://codespeak.net/tox/index.html>`_ instead of home- grown scripts in the Makefile.Saturday, March 16, 13
  16. 16. `Issue 68 <https://bitbucket.org/dhellmann/virtualenvwrapper/issue/68>`_Saturday, March 16, 13
  17. 17. `Issue 68 <https://bitbucket.org/dhellmann/virtualenvwrapper/issue/68>`_Saturday, March 16, 13
  18. 18. `Issue 68 <https://bitbucket.org/dhellmann/virtualenvwrapper/issue/68>`_Saturday, March 16, 13
  19. 19. `Issue 68 <https://bitbucket.org/dhellmann/virtualenvwrapper/issue/68>`_ :bbissue:`68`Saturday, March 16, 13
  20. 20. from docutils import nodes, utils from docutils.parsers.rst.roles import set_classes def bbissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]): "Link to a BitBucket issue." try: issue_num = int(text) if issue_num <= 0: raise ValueError except ValueError: msg = inliner.reporter.error( "%s" is an invalid bug id. % text, line=lineno) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] app = inliner.document.settings.env.app node = make_link_node(rawtext, app, issue, text, options) return [node], [] def make_link_node(rawtext, app, type, slug, options): "Create a link to a BitBucket resource." try: base = app.config.bitbucket_project_url if not base:Saturday, March 16, 13
  21. 21. from docutils import nodes, utils from docutils.parsers.rst.roles import set_classes def bbissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]): "Link to a BitBucket issue." try: issue_num = int(text) if issue_num <= 0: raise ValueError except ValueError: msg = inliner.reporter.error( "%s" is an invalid bug id. % text, line=lineno) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] app = inliner.document.settings.env.app node = make_link_node(rawtext, app, issue, text, options) return [node], [] def make_link_node(rawtext, app, type, slug, options): "Create a link to a BitBucket resource." try: base = app.config.bitbucket_project_url if not base:Saturday, March 16, 13
  22. 22. from docutils import nodes, utils from docutils.parsers.rst.roles import set_classes def bbissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]): "Link to a BitBucket issue." try: issue_num = int(text) if issue_num <= 0: raise ValueError except ValueError: msg = inliner.reporter.error( "%s" is an invalid bug id. % text, line=lineno) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] app = inliner.document.settings.env.app node = make_link_node(rawtext, app, issue, text, options) return [node], [] def make_link_node(rawtext, app, type, slug, options): "Create a link to a BitBucket resource." try: base = app.config.bitbucket_project_url if not base:Saturday, March 16, 13
  23. 23. from docutils import nodes, utils from docutils.parsers.rst.roles import set_classes def bbissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]): "Link to a BitBucket issue." try: issue_num = int(text) if issue_num <= 0: raise ValueError except ValueError: msg = inliner.reporter.error( "%s" is an invalid bug id. % text, line=lineno) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] app = inliner.document.settings.env.app node = make_link_node(rawtext, app, issue, text, options) return [node], [] def make_link_node(rawtext, app, type, slug, options): "Create a link to a BitBucket resource." try: base = app.config.bitbucket_project_url if not base:Saturday, March 16, 13
  24. 24. from docutils import nodes, utils from docutils.parsers.rst.roles import set_classes def bbissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]): "Link to a BitBucket issue." try: issue_num = int(text) if issue_num <= 0: raise ValueError except ValueError: msg = inliner.reporter.error( "%s" is an invalid bug id. % text, line=lineno) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] app = inliner.document.settings.env.app node = make_link_node(rawtext, app, issue, text, options) return [node], [] def make_link_node(rawtext, app, type, slug, options): "Create a link to a BitBucket resource." try: base = app.config.bitbucket_project_url if not base:Saturday, March 16, 13
  25. 25. from docutils import nodes, utils from docutils.parsers.rst.roles import set_classes def bbissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]): "Link to a BitBucket issue." try: issue_num = int(text) if issue_num <= 0: raise ValueError except ValueError: msg = inliner.reporter.error( "%s" is an invalid bug id. % text, line=lineno) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] app = inliner.document.settings.env.app node = make_link_node(rawtext, app, issue, text, options) return [node], [] def make_link_node(rawtext, app, type, slug, options): "Create a link to a BitBucket resource." try: base = app.config.bitbucket_project_url if not base:Saturday, March 16, 13
  26. 26. app = inliner.document.settings.env.app node = make_link_node(rawtext, app, issue, text, options) return [node], [] def make_link_node(rawtext, app, type, slug, options): "Create a link to a BitBucket resource." try: base = app.config.bitbucket_project_url if not base: raise AttributeError except AttributeError, err: raise ValueError(bitbucket_project_url not set (%s) % str(err)) slash = / if base[-1] != / else ref = base + slash + type + / + slug + / set_classes(options) node = nodes.reference(rawtext, type + + utils.unescape(slug), refuri=ref, **options) return node def setup(app): "Install the plugin." app.info(Initializing BitBucket plugin) app.add_role(bbissue, bbissue_role)Saturday, March 16, 13
  27. 27. app = inliner.document.settings.env.app node = make_link_node(rawtext, app, issue, text, options) return [node], [] def make_link_node(rawtext, app, type, slug, options): "Create a link to a BitBucket resource." try: base = app.config.bitbucket_project_url if not base: raise AttributeError except AttributeError, err: raise ValueError(bitbucket_project_url not set (%s) % str(err)) slash = / if base[-1] != / else ref = base + slash + type + / + slug + / set_classes(options) node = nodes.reference(rawtext, type + + utils.unescape(slug), refuri=ref, **options) return node def setup(app): "Install the plugin." app.info(Initializing BitBucket plugin) app.add_role(bbissue, bbissue_role)Saturday, March 16, 13
  28. 28. app = inliner.document.settings.env.app node = make_link_node(rawtext, app, issue, text, options) return [node], [] def make_link_node(rawtext, app, type, slug, options): "Create a link to a BitBucket resource." try: base = app.config.bitbucket_project_url if not base: raise AttributeError except AttributeError, err: raise ValueError(bitbucket_project_url not set (%s) % str(err)) slash = / if base[-1] != / else ref = base + slash + type + / + slug + / set_classes(options) node = nodes.reference(rawtext, type + + utils.unescape(slug), refuri=ref, **options) return node def setup(app): "Install the plugin." app.info(Initializing BitBucket plugin) app.add_role(bbissue, bbissue_role)Saturday, March 16, 13
  29. 29. app = inliner.document.settings.env.app node = make_link_node(rawtext, app, issue, text, options) return [node], [] def make_link_node(rawtext, app, type, slug, options): "Create a link to a BitBucket resource." try: base = app.config.bitbucket_project_url if not base: raise AttributeError except AttributeError, err: raise ValueError(bitbucket_project_url not set (%s) % str(err)) slash = / if base[-1] != / else ref = base + slash + type + / + slug + / set_classes(options) node = nodes.reference(rawtext, type + + utils.unescape(slug), refuri=ref, **options) return node def setup(app): "Install the plugin." app.info(Initializing BitBucket plugin) app.add_role(bbissue, bbissue_role)Saturday, March 16, 13
  30. 30. app = inliner.document.settings.env.app node = make_link_node(rawtext, app, issue, text, options) return [node], [] def make_link_node(rawtext, app, type, slug, options): "Create a link to a BitBucket resource." try: base = app.config.bitbucket_project_url if not base: raise AttributeError except AttributeError, err: raise ValueError(bitbucket_project_url not set (%s) % str(err)) slash = / if base[-1] != / else ref = base + slash + type + / + slug + / set_classes(options) node = nodes.reference(rawtext, type + + utils.unescape(slug), refuri=ref, **options) return node def setup(app): "Install the plugin." app.info(Initializing BitBucket plugin) app.add_role(bbissue, bbissue_role)Saturday, March 16, 13
  31. 31. node = nodes.reference(rawtext, type + + utils.unescape(slug), refuri=ref, **options) return node def setup(app): "Install the plugin." app.info(Initializing BitBucket plugin) app.add_role(bbissue, bbissue_role) app.add_config_value(bitbucket_project_url, None, env) returnSaturday, March 16, 13
  32. 32. node = nodes.reference(rawtext, type + + utils.unescape(slug), refuri=ref, **options) return node def setup(app): "Install the plugin." app.info(Initializing BitBucket plugin) app.add_role(bbissue, bbissue_role) app.add_config_value(bitbucket_project_url, None, env) returnSaturday, March 16, 13
  33. 33. node = nodes.reference(rawtext, type + + utils.unescape(slug), refuri=ref, **options) return node def setup(app): "Install the plugin." app.info(Initializing BitBucket plugin) app.add_role(bbissue, bbissue_role) app.add_config_value(bitbucket_project_url, None, env) returnSaturday, March 16, 13
  34. 34. 2.6 - Fixed a problem with hook script line endings under Cygwin (:bbissue:`68`). - Updated documentation to include a list of the compatible shells (:ref:`supported-shells`) and Python versions (:ref:`supported-versions`) (:bbissue:`70`). - Fixed installation dependency on virtualenv (:bbissue:`60`). - Fixed the method for determining the Python version so it works under Python 2.4 (:bbissue:`61`). - Converted the test infrastructure to use `tox <http://codespeak.net/tox/index.html>`_ instead of home-grown scripts in the Makefile.Saturday, March 16, 13
  35. 35. 2.6 - Fixed a problem with hook script line endings under Cygwin (:bbissue:`68`). - Updated documentation to include a list of the compatible shells (:ref:`supported-shells`) and Python versions (:ref:`supported-versions`) (:bbissue:`70`). - Fixed installation dependency on virtualenv (:bbissue:`60`). - Fixed the method for determining the Python version so it works under Python 2.4 (:bbissue:`61`). - Converted the test infrastructure to use `tox <http://codespeak.net/tox/index.html>`_ instead of home-grown scripts in the Makefile.Saturday, March 16, 13
  36. 36. 2.6 • Fixed a problem with hook script line endings under Cygwin (issue 68). • Updated documentation to include a list of the compatible shells (Supported Shells) and Python versions (Python Versions) (issue 70). • Fixed installation dependency on virtualenv (issue 60). • Fixed the method for determining the Python version so it works under Python 2.4 (issue 61). • Converted the test infrastructure to use tox instead of home-grown scripts in the Makefile.Saturday, March 16, 13
  37. 37. .. name:: arguments :option: value :option: another-value body line body lineSaturday, March 16, 13
  38. 38. .. name:: arguments :option: value :option: another-value body line body lineSaturday, March 16, 13
  39. 39. .. name:: arguments :option: value :option: another-value body line body lineSaturday, March 16, 13
  40. 40. .. name:: arguments :option: value :option: another-value body line body lineSaturday, March 16, 13
  41. 41. .. sqltable:: List of Users :connection_string: sqlite:///sampledata.db select name as Name, email as E-mail from users order by Name ascSaturday, March 16, 13
  42. 42. .. sqltable:: List of Users :connection_string: sqlite:///sampledata.db select name as Name, email as E-mail from users order by Name ascSaturday, March 16, 13
  43. 43. .. sqltable:: List of Users :connection_string: sqlite:///sampledata.db select name as Name, email as E-mail from users order by Name ascSaturday, March 16, 13
  44. 44. .. sqltable:: List of Users :connection_string: sqlite:///sampledata.db select name as Name, email as E-mail from users order by Name ascSaturday, March 16, 13
  45. 45. from docutils.parsers.rst.directives.tables import Table class SQLTable(Table): option_spec = {widths: directives.positive_int_list, class: directives.class_option, name: directives.unchanged, connection_string:directives.unchanged, } def run(self): env = self.state.document.settings.env app = env.app config = app.config # Make sure we have some content, which for now we # assume is a query. if not self.content: error = self.state_machine.reporter.error( No query in sqltable directive, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error]Saturday, March 16, 13 # Connect to the database
  46. 46. from docutils.parsers.rst.directives.tables import Table class SQLTable(Table): option_spec = {widths: directives.positive_int_list, class: directives.class_option, name: directives.unchanged, connection_string:directives.unchanged, } def run(self): env = self.state.document.settings.env app = env.app config = app.config # Make sure we have some content, which for now we # assume is a query. if not self.content: error = self.state_machine.reporter.error( No query in sqltable directive, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error]Saturday, March 16, 13 # Connect to the database
  47. 47. from docutils.parsers.rst.directives.tables import Table class SQLTable(Table): option_spec = {widths: directives.positive_int_list, class: directives.class_option, name: directives.unchanged, connection_string:directives.unchanged, } def run(self): env = self.state.document.settings.env app = env.app config = app.config # Make sure we have some content, which for now we # assume is a query. if not self.content: error = self.state_machine.reporter.error( No query in sqltable directive, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error]Saturday, March 16, 13 # Connect to the database
  48. 48. from docutils.parsers.rst.directives.tables import Table class SQLTable(Table): option_spec = {widths: directives.positive_int_list, class: directives.class_option, name: directives.unchanged, connection_string:directives.unchanged, } def run(self): env = self.state.document.settings.env app = env.app config = app.config # Make sure we have some content, which for now we # assume is a query. if not self.content: error = self.state_machine.reporter.error( No query in sqltable directive, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error]Saturday, March 16, 13 # Connect to the database
  49. 49. from docutils.parsers.rst.directives.tables import Table class SQLTable(Table): option_spec = {widths: directives.positive_int_list, class: directives.class_option, name: directives.unchanged, connection_string:directives.unchanged, } def run(self): env = self.state.document.settings.env app = env.app config = app.config # Make sure we have some content, which for now we # assume is a query. if not self.content: error = self.state_machine.reporter.error( No query in sqltable directive, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error]Saturday, March 16, 13 # Connect to the database
  50. 50. from docutils.parsers.rst.directives.tables import Table class SQLTable(Table): option_spec = {widths: directives.positive_int_list, class: directives.class_option, name: directives.unchanged, connection_string:directives.unchanged, } def run(self): env = self.state.document.settings.env app = env.app config = app.config # Make sure we have some content, which for now we # assume is a query. if not self.content: error = self.state_machine.reporter.error( No query in sqltable directive, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error]Saturday, March 16, 13 # Connect to the database
  51. 51. from docutils.parsers.rst.directives.tables import Table class SQLTable(Table): option_spec = {widths: directives.positive_int_list, class: directives.class_option, name: directives.unchanged, connection_string:directives.unchanged, } def run(self): env = self.state.document.settings.env app = env.app config = app.config # Make sure we have some content, which for now we # assume is a query. if not self.content: error = self.state_machine.reporter.error( No query in sqltable directive, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error]Saturday, March 16, 13 # Connect to the database
  52. 52. from docutils.parsers.rst.directives.tables import Table class SQLTable(Table): option_spec = {widths: directives.positive_int_list, class: directives.class_option, name: directives.unchanged, connection_string:directives.unchanged, } def run(self): env = self.state.document.settings.env app = env.app config = app.config # Make sure we have some content, which for now we # assume is a query. if not self.content: error = self.state_machine.reporter.error( No query in sqltable directive, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error]Saturday, March 16, 13 # Connect to the database
  53. 53. def run(self): env = self.state.document.settings.env app = env.app config = app.config # Make sure we have some content, which for now we # assume is a query. if not self.content: error = self.state_machine.reporter.error( No query in sqltable directive, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error] # Connect to the database connection_string = self.options.get( connection_string, config.sqltable_connection_string, ) app.info(Connecting to %s % connection_string) engine = sqlalchemy.create_engine(connection_string) # Run the query query = n.join(self.content) app.info(Running query %r % query)Saturday, March 16, 13
  54. 54. def run(self): env = self.state.document.settings.env app = env.app config = app.config # Make sure we have some content, which for now we # assume is a query. if not self.content: error = self.state_machine.reporter.error( No query in sqltable directive, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error] # Connect to the database connection_string = self.options.get( connection_string, config.sqltable_connection_string, ) app.info(Connecting to %s % connection_string) engine = sqlalchemy.create_engine(connection_string) # Run the query query = n.join(self.content) app.info(Running query %r % query)Saturday, March 16, 13
  55. 55. def run(self): env = self.state.document.settings.env app = env.app config = app.config # Make sure we have some content, which for now we # assume is a query. if not self.content: error = self.state_machine.reporter.error( No query in sqltable directive, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error] # Connect to the database connection_string = self.options.get( connection_string, config.sqltable_connection_string, ) app.info(Connecting to %s % connection_string) engine = sqlalchemy.create_engine(connection_string) # Run the query query = n.join(self.content) app.info(Running query %r % query)Saturday, March 16, 13
  56. 56. line=self.lineno) return [error] # Connect to the database connection_string = self.options.get( connection_string, config.sqltable_connection_string, ) app.info(Connecting to %s % connection_string) engine = sqlalchemy.create_engine(connection_string) # Run the query query = n.join(self.content) app.info(Running query %r % query) results = engine.execute(query) # Extract some values we need for building the table. table_headers = results.keys() table_body = results max_cols = len(table_headers) max_header_cols = max_cols # Handle the width settings and title col_widths = self.get_column_widths(max_cols) title, messages = self.make_title()Saturday, March 16, 13 # Build the node containing the table content
  57. 57. line=self.lineno) return [error] # Connect to the database connection_string = self.options.get( connection_string, config.sqltable_connection_string, ) app.info(Connecting to %s % connection_string) engine = sqlalchemy.create_engine(connection_string) # Run the query query = n.join(self.content) app.info(Running query %r % query) results = engine.execute(query) # Extract some values we need for building the table. table_headers = results.keys() table_body = results max_cols = len(table_headers) max_header_cols = max_cols # Handle the width settings and title col_widths = self.get_column_widths(max_cols) title, messages = self.make_title()Saturday, March 16, 13 # Build the node containing the table content
  58. 58. line=self.lineno) return [error] # Connect to the database connection_string = self.options.get( connection_string, config.sqltable_connection_string, ) app.info(Connecting to %s % connection_string) engine = sqlalchemy.create_engine(connection_string) # Run the query query = n.join(self.content) app.info(Running query %r % query) results = engine.execute(query) # Extract some values we need for building the table. table_headers = results.keys() table_body = results max_cols = len(table_headers) max_header_cols = max_cols # Handle the width settings and title col_widths = self.get_column_widths(max_cols) title, messages = self.make_title()Saturday, March 16, 13 # Build the node containing the table content
  59. 59. # Run the query query = n.join(self.content) app.info(Running query %r % query) results = engine.execute(query) # Extract some values we need for building the table. table_headers = results.keys() table_body = results max_cols = len(table_headers) max_header_cols = max_cols # Handle the width settings and title col_widths = self.get_column_widths(max_cols) title, messages = self.make_title() # Build the node containing the table content table_node = self.build_table(table_body, col_widths, table_headers) table_node[classes] += self.options.get(class, []) self.add_name(table_node) if title: table_node.insert(0, title) return [table_node] + messages def build_table(self, table_data, col_widths, headers):Saturday, March 16, 13
  60. 60. # Run the query query = n.join(self.content) app.info(Running query %r % query) results = engine.execute(query) # Extract some values we need for building the table. table_headers = results.keys() table_body = results max_cols = len(table_headers) max_header_cols = max_cols # Handle the width settings and title col_widths = self.get_column_widths(max_cols) title, messages = self.make_title() # Build the node containing the table content table_node = self.build_table(table_body, col_widths, table_headers) table_node[classes] += self.options.get(class, []) self.add_name(table_node) if title: table_node.insert(0, title) return [table_node] + messages def build_table(self, table_data, col_widths, headers):Saturday, March 16, 13
  61. 61. # Run the query query = n.join(self.content) app.info(Running query %r % query) results = engine.execute(query) # Extract some values we need for building the table. table_headers = results.keys() table_body = results max_cols = len(table_headers) max_header_cols = max_cols # Handle the width settings and title col_widths = self.get_column_widths(max_cols) title, messages = self.make_title() # Build the node containing the table content table_node = self.build_table(table_body, col_widths, table_headers) table_node[classes] += self.options.get(class, []) self.add_name(table_node) if title: table_node.insert(0, title) return [table_node] + messages def build_table(self, table_data, col_widths, headers):Saturday, March 16, 13
  62. 62. # Run the query query = n.join(self.content) app.info(Running query %r % query) results = engine.execute(query) # Extract some values we need for building the table. table_headers = results.keys() table_body = results max_cols = len(table_headers) max_header_cols = max_cols # Handle the width settings and title col_widths = self.get_column_widths(max_cols) title, messages = self.make_title() # Build the node containing the table content table_node = self.build_table(table_body, col_widths, table_headers) table_node[classes] += self.options.get(class, []) self.add_name(table_node) if title: table_node.insert(0, title) return [table_node] + messages def build_table(self, table_data, col_widths, headers):Saturday, March 16, 13
  63. 63. # Handle the width settings and title col_widths = self.get_column_widths(max_cols) title, messages = self.make_title() # Build the node containing the table content table_node = self.build_table(table_body, col_widths, table_headers) table_node[classes] += self.options.get(class, []) self.add_name(table_node) if title: table_node.insert(0, title) return [table_node] + messages def build_table(self, table_data, col_widths, headers): table = nodes.table() # Set up the column specifications # based on the widths. tgroup = nodes.tgroup(cols=len(col_widths)) table += tgroup tgroup.extend(nodes.colspec(colwidth=col_width) for col_width in col_widths) # Set the headers thead = nodes.thead() tgroup += theadSaturday, March 16, 13 row_node = nodes.row()
  64. 64. # Handle the width settings and title col_widths = self.get_column_widths(max_cols) title, messages = self.make_title() # Build the node containing the table content table_node = self.build_table(table_body, col_widths, table_headers) table_node[classes] += self.options.get(class, []) self.add_name(table_node) if title: table_node.insert(0, title) return [table_node] + messages def build_table(self, table_data, col_widths, headers): table = nodes.table() # Set up the column specifications # based on the widths. tgroup = nodes.tgroup(cols=len(col_widths)) table += tgroup tgroup.extend(nodes.colspec(colwidth=col_width) for col_width in col_widths) # Set the headers thead = nodes.thead() tgroup += theadSaturday, March 16, 13 row_node = nodes.row()
  65. 65. # Handle the width settings and title col_widths = self.get_column_widths(max_cols) title, messages = self.make_title() # Build the node containing the table content table_node = self.build_table(table_body, col_widths, table_headers) table_node[classes] += self.options.get(class, []) self.add_name(table_node) if title: table_node.insert(0, title) return [table_node] + messages def build_table(self, table_data, col_widths, headers): table = nodes.table() # Set up the column specifications # based on the widths. tgroup = nodes.tgroup(cols=len(col_widths)) table += tgroup tgroup.extend(nodes.colspec(colwidth=col_width) for col_width in col_widths) # Set the headers thead = nodes.thead() tgroup += theadSaturday, March 16, 13 row_node = nodes.row()
  66. 66. Table Node HierarchySaturday, March 16, 13
  67. 67. Table Node Hierarchy tableSaturday, March 16, 13
  68. 68. Table Node Hierarchy table tgroupSaturday, March 16, 13
  69. 69. Table Node Hierarchy table tgroup colspecSaturday, March 16, 13
  70. 70. Table Node Hierarchy table tgroup colspec theadSaturday, March 16, 13
  71. 71. Table Node Hierarchy table tgroup colspec thead rowSaturday, March 16, 13
  72. 72. Table Node Hierarchy table tgroup colspec thead row entrySaturday, March 16, 13
  73. 73. Table Node Hierarchy table tgroup colspec thead row entry paragraphSaturday, March 16, 13
  74. 74. Table Node Hierarchy table tgroup colspec thead tbody row entry paragraphSaturday, March 16, 13
  75. 75. Table Node Hierarchy table tgroup colspec thead tbody row row entry entry paragraph paragraphSaturday, March 16, 13
  76. 76. return [table_node] + messages def build_table(self, table_data, col_widths, headers): table = nodes.table() # Set up the column specifications # based on the widths. tgroup = nodes.tgroup(cols=len(col_widths)) table += tgroup tgroup.extend(nodes.colspec(colwidth=col_width) table for col_width in col_widths) # Set the headers thead = nodes.thead() tgroup tgroup += thead row_node = nodes.row() thead += row_node colspec row_node.extend( nodes.entry(h, nodes.paragraph(text=h)) for h in headers ) # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. tbody = nodes.tbody()Saturday, March 16, 13 tgroup += tbody
  77. 77. return [table_node] + messages def build_table(self, table_data, col_widths, headers): table = nodes.table() # Set up the column specifications # based on the widths. tgroup = nodes.tgroup(cols=len(col_widths)) table += tgroup tgroup.extend(nodes.colspec(colwidth=col_width) table for col_width in col_widths) # Set the headers thead = nodes.thead() tgroup tgroup += thead row_node = nodes.row() thead += row_node colspec row_node.extend( nodes.entry(h, nodes.paragraph(text=h)) for h in headers ) # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. tbody = nodes.tbody()Saturday, March 16, 13 tgroup += tbody
  78. 78. return [table_node] + messages def build_table(self, table_data, col_widths, headers): table = nodes.table() # Set up the column specifications # based on the widths. tgroup = nodes.tgroup(cols=len(col_widths)) table += tgroup tgroup.extend(nodes.colspec(colwidth=col_width) table for col_width in col_widths) # Set the headers thead = nodes.thead() tgroup tgroup += thead row_node = nodes.row() thead += row_node colspec row_node.extend( nodes.entry(h, nodes.paragraph(text=h)) for h in headers ) # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. tbody = nodes.tbody()Saturday, March 16, 13 tgroup += tbody
  79. 79. return [table_node] + messages def build_table(self, table_data, col_widths, headers): table = nodes.table() # Set up the column specifications # based on the widths. tgroup = nodes.tgroup(cols=len(col_widths)) table += tgroup tgroup.extend(nodes.colspec(colwidth=col_width) table for col_width in col_widths) # Set the headers thead = nodes.thead() tgroup tgroup += thead row_node = nodes.row() thead += row_node colspec row_node.extend( nodes.entry(h, nodes.paragraph(text=h)) for h in headers ) # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. tbody = nodes.tbody()Saturday, March 16, 13 tgroup += tbody
  80. 80. tgroup.extend(nodes.colspec(colwidth=col_width) for col_width in col_widths) # Set the headers thead = nodes.thead() tgroup += thead row_node = nodes.row() thead += row_node thead row_node.extend( nodes.entry(h, nodes.paragraph(text=h)) for h in headers ) row # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. entry tbody = nodes.tbody() tgroup += tbody rows = [] for row in table_data: paragraph trow = nodes.row() for cell in row: entry = nodes.entry() para = nodes.paragraph( text=unicode(cell)) entry += paraSaturday, March 16, 13 trow += entry
  81. 81. tgroup.extend(nodes.colspec(colwidth=col_width) for col_width in col_widths) # Set the headers thead = nodes.thead() tgroup += thead row_node = nodes.row() thead += row_node thead row_node.extend( nodes.entry(h, nodes.paragraph(text=h)) for h in headers ) row # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. entry tbody = nodes.tbody() tgroup += tbody rows = [] for row in table_data: paragraph trow = nodes.row() for cell in row: entry = nodes.entry() para = nodes.paragraph( text=unicode(cell)) entry += paraSaturday, March 16, 13 trow += entry
  82. 82. tgroup.extend(nodes.colspec(colwidth=col_width) for col_width in col_widths) # Set the headers thead = nodes.thead() tgroup += thead row_node = nodes.row() thead += row_node thead row_node.extend( nodes.entry(h, nodes.paragraph(text=h)) for h in headers ) row # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. entry tbody = nodes.tbody() tgroup += tbody rows = [] for row in table_data: paragraph trow = nodes.row() for cell in row: entry = nodes.entry() para = nodes.paragraph( text=unicode(cell)) entry += paraSaturday, March 16, 13 trow += entry
  83. 83. tgroup.extend(nodes.colspec(colwidth=col_width) for col_width in col_widths) # Set the headers thead = nodes.thead() tgroup += thead row_node = nodes.row() thead += row_node thead row_node.extend( nodes.entry(h, nodes.paragraph(text=h)) for h in headers ) row # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. entry tbody = nodes.tbody() tgroup += tbody rows = [] for row in table_data: paragraph trow = nodes.row() for cell in row: entry = nodes.entry() para = nodes.paragraph( text=unicode(cell)) entry += paraSaturday, March 16, 13 trow += entry
  84. 84. ) # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. tbody = nodes.tbody() tgroup += tbody rows = [] tbody for row in table_data: trow = nodes.row() for cell in row: entry = nodes.entry() row para = nodes.paragraph( text=unicode(cell)) entry += para trow += entry entry rows.append(trow) tbody.extend(rows) #print table paragraph return table def setup(app): app.info(Initializing SQLTable) app.add_config_value(sqltable_connection_string, ,Saturday, March 16, 13 env)
  85. 85. ) # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. tbody = nodes.tbody() tgroup += tbody rows = [] tbody for row in table_data: trow = nodes.row() for cell in row: entry = nodes.entry() row para = nodes.paragraph( text=unicode(cell)) entry += para trow += entry entry rows.append(trow) tbody.extend(rows) #print table paragraph return table def setup(app): app.info(Initializing SQLTable) app.add_config_value(sqltable_connection_string, ,Saturday, March 16, 13 env)
  86. 86. ) # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. tbody = nodes.tbody() tgroup += tbody rows = [] tbody for row in table_data: trow = nodes.row() for cell in row: entry = nodes.entry() row para = nodes.paragraph( text=unicode(cell)) entry += para trow += entry entry rows.append(trow) tbody.extend(rows) #print table paragraph return table def setup(app): app.info(Initializing SQLTable) app.add_config_value(sqltable_connection_string, ,Saturday, March 16, 13 env)
  87. 87. ) # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. tbody = nodes.tbody() tgroup += tbody rows = [] tbody for row in table_data: trow = nodes.row() for cell in row: entry = nodes.entry() row para = nodes.paragraph( text=unicode(cell)) entry += para trow += entry entry rows.append(trow) tbody.extend(rows) #print table paragraph return table def setup(app): app.info(Initializing SQLTable) app.add_config_value(sqltable_connection_string, ,Saturday, March 16, 13 env)
  88. 88. ) # The body of the table is made up of rows. # Each row contains a series of entries, # and each entry contains a paragraph of text. tbody = nodes.tbody() tgroup += tbody rows = [] tbody for row in table_data: trow = nodes.row() for cell in row: entry = nodes.entry() row para = nodes.paragraph( text=unicode(cell)) entry += para trow += entry entry rows.append(trow) tbody.extend(rows) #print table paragraph return table def setup(app): app.info(Initializing SQLTable) app.add_config_value(sqltable_connection_string, ,Saturday, March 16, 13 env)
  89. 89. .. sqltable:: List of Users :connection_string: sqlite:///sampledata.db select name as Name, email as E-mail from users order by Name ascSaturday, March 16, 13
  90. 90. .. sqltable:: List of Users :connection_string: sqlite:///sampledata.db select name as Name, email as E-mail from users order by Name ascSaturday, March 16, 13
  91. 91. .. sqltable:: List of Users :connection_string: sqlite:///sampledata.db select name as Name, email as E-mail from users order by Name ascSaturday, March 16, 13
  92. 92. .. sqltable:: List of Users :connection_string: sqlite:///sampledata.db select name as Name, email as E-mail from users order by Name ascSaturday, March 16, 13
  93. 93. Sphinx Build docutils Sphinx Application Environment parser Builder .rst .pdf .htmlSaturday, March 16, 13
  94. 94. Saturday, March 16, 13
  95. 95. .rstSaturday, March 16, 13
  96. 96. .rstSaturday, March 16, 13
  97. 97. .rst check word listSaturday, March 16, 13
  98. 98. .rst check word listSaturday, March 16, 13
  99. 99. section title paragraph #text #text emphasis #text literal #text #textSaturday, March 16, 13
  100. 100. section title paragraph #text #text emphasis #text literal #text #textSaturday, March 16, 13
  101. 101. from sphinx.builders import Builder class SpellingBuilder(Builder): name = spelling def init(self): self.docnames = [] self.document_data = [] project_words = os.path.join(self.srcdir, self.config.spelling_word_list_filename) self.checker = SpellingChecker( lang=self.config.spelling_lang, suggest=self.config.spelling_show_suggestions, word_list_filename=project_words, ) self.output_filename = os.path.join(self.outdir, output.txt) self.output = codecs.open(self.output_filename, wt, encoding=UTF-8) def write_doc(self, docname, doctree):Saturday, March 16, 13
  102. 102. from sphinx.builders import Builder class SpellingBuilder(Builder): name = spelling def init(self): self.docnames = [] self.document_data = [] project_words = os.path.join(self.srcdir, self.config.spelling_word_list_filename) self.checker = SpellingChecker( lang=self.config.spelling_lang, suggest=self.config.spelling_show_suggestions, word_list_filename=project_words, ) self.output_filename = os.path.join(self.outdir, output.txt) self.output = codecs.open(self.output_filename, wt, encoding=UTF-8) def write_doc(self, docname, doctree):Saturday, March 16, 13
  103. 103. from sphinx.builders import Builder class SpellingBuilder(Builder): name = spelling def init(self): self.docnames = [] self.document_data = [] project_words = os.path.join(self.srcdir, self.config.spelling_word_list_filename) self.checker = SpellingChecker( lang=self.config.spelling_lang, suggest=self.config.spelling_show_suggestions, word_list_filename=project_words, ) self.output_filename = os.path.join(self.outdir, output.txt) self.output = codecs.open(self.output_filename, wt, encoding=UTF-8) def write_doc(self, docname, doctree):Saturday, March 16, 13
  104. 104. from sphinx.builders import Builder class SpellingBuilder(Builder): name = spelling def init(self): self.docnames = [] self.document_data = [] project_words = os.path.join(self.srcdir, self.config.spelling_word_list_filename) self.checker = SpellingChecker( lang=self.config.spelling_lang, suggest=self.config.spelling_show_suggestions, word_list_filename=project_words, ) self.output_filename = os.path.join(self.outdir, output.txt) self.output = codecs.open(self.output_filename, wt, encoding=UTF-8) def write_doc(self, docname, doctree):Saturday, March 16, 13
  105. 105. from sphinx.builders import Builder class SpellingBuilder(Builder): name = spelling def init(self): self.docnames = [] self.document_data = [] project_words = os.path.join(self.srcdir, self.config.spelling_word_list_filename) self.checker = SpellingChecker( lang=self.config.spelling_lang, suggest=self.config.spelling_show_suggestions, word_list_filename=project_words, ) self.output_filename = os.path.join(self.outdir, output.txt) self.output = codecs.open(self.output_filename, wt, encoding=UTF-8) def write_doc(self, docname, doctree):Saturday, March 16, 13
  106. 106. wt, encoding=UTF-8) def write_doc(self, docname, doctree): filename = self.env.doc2path(docname, base=None) for node in doctree.traverse(docutils.nodes.Text): if (node.tagname == #text and node.parent and node.parent.tagname in TEXT_NODES): # Determine the line number for this node lineno = get_line_number(node) # Check the text of the node. for word, suggestions in self.checker.check(node.astext()): msg_parts = [ docname ] if lineno: msg_parts.append( darkgreen((line %3d) % lineno) ) msg_parts.append(red(word)) msg_parts.append( self.format_suggestions(suggestions)Saturday, March 16, 13 )
  107. 107. wt, encoding=UTF-8) def write_doc(self, docname, doctree): filename = self.env.doc2path(docname, base=None) for node in doctree.traverse(docutils.nodes.Text): if (node.tagname == #text and node.parent and node.parent.tagname in TEXT_NODES): # Determine the line number for this node lineno = get_line_number(node) # Check the text of the node. for word, suggestions in self.checker.check(node.astext()): msg_parts = [ docname ] if lineno: msg_parts.append( darkgreen((line %3d) % lineno) ) msg_parts.append(red(word)) msg_parts.append( self.format_suggestions(suggestions)Saturday, March 16, 13 )
  108. 108. wt, encoding=UTF-8) def write_doc(self, docname, doctree): filename = self.env.doc2path(docname, base=None) for node in doctree.traverse(docutils.nodes.Text): if (node.tagname == #text and node.parent and node.parent.tagname in TEXT_NODES): # Determine the line number for this node lineno = get_line_number(node) # Check the text of the node. for word, suggestions in self.checker.check(node.astext()): msg_parts = [ docname ] if lineno: msg_parts.append( darkgreen((line %3d) % lineno) ) msg_parts.append(red(word)) msg_parts.append( self.format_suggestions(suggestions)Saturday, March 16, 13 )
  109. 109. wt, encoding=UTF-8) def write_doc(self, docname, doctree): filename = self.env.doc2path(docname, base=None) for node in doctree.traverse(docutils.nodes.Text): if (node.tagname == #text and node.parent and node.parent.tagname in TEXT_NODES): # Determine the line number for this node lineno = get_line_number(node) # Check the text of the node. for word, suggestions in self.checker.check(node.astext()): msg_parts = [ docname ] if lineno: msg_parts.append( darkgreen((line %3d) % lineno) ) msg_parts.append(red(word)) msg_parts.append( self.format_suggestions(suggestions)Saturday, March 16, 13 )
  110. 110. msg_parts = [ docname ] if lineno: msg_parts.append( darkgreen((line %3d) % lineno) ) msg_parts.append(red(word)) msg_parts.append( self.format_suggestions(suggestions) ) msg = .join(msg_parts) self.info(msg) self.output.write(u"%s:%s: (%s) %sn" % ( self.env.doc2path(docname, None), lineno, word, self.format_suggestions(suggestions), )) # Found at least one bad spelling self.app.statuscode = 1 return def finish(self): self.output.close() self.info(Output written to %s % self.output_filename)Saturday, March 16, 13 return
  111. 111. msg_parts = [ docname ] if lineno: msg_parts.append( darkgreen((line %3d) % lineno) ) msg_parts.append(red(word)) msg_parts.append( self.format_suggestions(suggestions) ) msg = .join(msg_parts) self.info(msg) self.output.write(u"%s:%s: (%s) %sn" % ( self.env.doc2path(docname, None), lineno, word, self.format_suggestions(suggestions), )) # Found at least one bad spelling self.app.statuscode = 1 return def finish(self): self.output.close() self.info(Output written to %s % self.output_filename)Saturday, March 16, 13 return
  112. 112. self.env.doc2path(docname, None), lineno, word, self.format_suggestions(suggestions), )) # Found at least one bad spelling self.app.statuscode = 1 return def finish(self): self.output.close() self.info(Output written to %s % self.output_filename) return def setup(app): app.info(Initializing Spelling Checker) app.add_builder(SpellingBuilder) returnSaturday, March 16, 13
  113. 113. self.env.doc2path(docname, None), lineno, word, self.format_suggestions(suggestions), )) # Found at least one bad spelling self.app.statuscode = 1 return def finish(self): self.output.close() self.info(Output written to %s % self.output_filename) return def setup(app): app.info(Initializing Spelling Checker) app.add_builder(SpellingBuilder) returnSaturday, March 16, 13
  114. 114. self.env.doc2path(docname, None), lineno, word, self.format_suggestions(suggestions), )) # Found at least one bad spelling self.app.statuscode = 1 return def finish(self): self.output.close() self.info(Output written to %s % self.output_filename) return def setup(app): app.info(Initializing Spelling Checker) app.add_builder(SpellingBuilder) returnSaturday, March 16, 13
  115. 115. $ sphinx-build -b spelling -d build/doctrees source build/spelling Running Sphinx v1.1.2 Initializing Spelling Checker loading reprint directive loading books directives loading pickled environment... done building [spelling]: all documents updating environment: 0 added, 0 changed, 0 removed looking for now-outdated files... none found preparing documents... done index (line 13) blarg ["blare", "blarney", "Blair", "blamer", "blazer", "blog"] writing output... [100%] Spelling checker messages written to /Users/dhellmann/Devel/ website/website/build/spelling/output.txt build finished with problems.Saturday, March 16, 13
  116. 116. $ sphinx-build -b spelling -d build/doctrees source build/spelling Running Sphinx v1.1.2 Initializing Spelling Checker loading reprint directive loading books directives loading pickled environment... done building [spelling]: all documents updating environment: 0 added, 0 changed, 0 removed looking for now-outdated files... none found preparing documents... done index (line 13) blarg ["blare", "blarney", "Blair", "blamer", "blazer", "blog"] writing output... [100%] Spelling checker messages written to /Users/dhellmann/Devel/ website/website/build/spelling/output.txt build finished with problems.Saturday, March 16, 13
  117. 117. $ sphinx-build -b spelling -d build/doctrees source build/spelling Running Sphinx v1.1.2 Initializing Spelling Checker loading reprint directive loading books directives loading pickled environment... done building [spelling]: all documents updating environment: 0 added, 0 changed, 0 removed looking for now-outdated files... none found preparing documents... done index (line 13) blarg ["blare", "blarney", "Blair", "blamer", "blazer", "blog"] writing output... [100%] Spelling checker messages written to /Users/dhellmann/Devel/ website/website/build/spelling/output.txt build finished with problems.Saturday, March 16, 13
  118. 118. Better Documentation Through Automation: Creating docutils & Sphinx Extensions Doug Hellmann @doughellmann PyCon 2013 http://docutils.sourceforge.net/ https://bitbucket.org/birkenfeld/sphinx-contrib/ http://packages.python.org/pyenchant/ http://doughellmann.comSaturday, March 16, 13
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×