Browse Source

Add attributetable and add some class-level sections.

The extensions have yet to receive this treatment and CSS needs work,
but for now this is fine.
pull/6176/head
Rapptz 5 years ago
parent
commit
9b88c63163
  1. 8
      docs/_static/custom.js
  2. 25
      docs/_static/style.css
  3. 209
      docs/api.rst
  4. 3
      docs/conf.py
  5. 199
      docs/extensions/attributetable.py

8
docs/_static/custom.js

@ -27,5 +27,13 @@ $(document).ready(function () {
activeLink = $('.sphinxsidebar a[href="#' + currentSection.attr('id') + '"]'); activeLink = $('.sphinxsidebar a[href="#' + currentSection.attr('id') + '"]');
activeLink.parent().addClass('active'); activeLink.parent().addClass('active');
} }
const tables = document.querySelectorAll('.py-attribute-table[data-move-to-id]');
tables.forEach(table => {
let element = document.getElementById(table.getAttribute('data-move-to-id'));
let parent = element.parentNode;
// insert ourselves after the element
parent.insertBefore(table, element.nextSibling);
});
}); });
}); });

25
docs/_static/style.css

@ -278,6 +278,12 @@ div.attention, div.warning, div.caution, div.seealso {
border: 1px solid #fbe091; border: 1px solid #fbe091;
} }
dl.field-list > dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 20px;
}
/* no disgusting background in the FAQ */ /* no disgusting background in the FAQ */
div.topic { div.topic {
background-color: transparent; background-color: transparent;
@ -352,6 +358,25 @@ div.helpful > p.admonition-title:after {
list-style: '»' !important; list-style: '»' !important;
} }
/* attribute tables */
.py-attribute-table {
display: flex;
flex-direction: row;
justify-content: space-between;
margin: 0 2em;
padding-top: 16px;
}
.py-attribute-table-column > span {
font-weight: bold;
}
div.body .py-attribute-table-column > ul {
list-style: none;
margin: 4px 0px;
padding-left: 12px;
}
pre { pre {
background-color: #f5f5f5; background-color: #f5f5f5;
border: 1px solid #C6C9CB; border: 1px solid #C6C9CB;

209
docs/api.rst

@ -30,48 +30,116 @@ There are two main ways to query version information about the library. For guar
A string representation of the version. e.g. ``'1.0.0rc1'``. This is based A string representation of the version. e.g. ``'1.0.0rc1'``. This is based
off of :pep:`440`. off of :pep:`440`.
Clients
--------
Client Client
------- ~~~~~~~
.. attributetable:: Client
.. autoclass:: Client .. autoclass:: Client
:members: :members:
AutoShardedClient
~~~~~~~~~~~~~~~~~~
.. attributetable:: AutoShardedClient
.. autoclass:: AutoShardedClient .. autoclass:: AutoShardedClient
:members: :members:
Application Info
------------------
AppInfo
~~~~~~~~
.. attributetable:: AppInfo
.. autoclass:: AppInfo() .. autoclass:: AppInfo()
:members: :members:
Team
~~~~~
.. attributetable:: Team
.. autoclass:: Team() .. autoclass:: Team()
:members: :members:
TeamMember
~~~~~~~~~~~
.. attributetable:: TeamMember
.. autoclass:: TeamMember() .. autoclass:: TeamMember()
:members: :members:
Voice Voice Related
------ ---------------
VoiceClient
~~~~~~~~~~~~
.. attributetable:: VoiceClient
.. autoclass:: VoiceClient() .. autoclass:: VoiceClient()
:members: :members:
VoiceProtocol
~~~~~~~~~~~~~~~
.. attributetable:: VoiceProtocol
.. autoclass:: VoiceProtocol .. autoclass:: VoiceProtocol
:members: :members:
AudioSource
~~~~~~~~~~~~
.. attributetable:: AudioSource
.. autoclass:: AudioSource .. autoclass:: AudioSource
:members: :members:
PCMAudio
~~~~~~~~~
.. attributetable:: PCMAudio
.. autoclass:: PCMAudio .. autoclass:: PCMAudio
:members: :members:
FFmpegAudio
~~~~~~~~~~~~
.. attributetable:: FFmpegAudio
.. autoclass:: FFmpegAudio .. autoclass:: FFmpegAudio
:members: :members:
FFmpegPCMAudio
~~~~~~~~~~~~~~~
.. attributetable:: FFmpegPCMAudio
.. autoclass:: FFmpegPCMAudio .. autoclass:: FFmpegPCMAudio
:members: :members:
FFmpegOpusAudio
~~~~~~~~~~~~~~~~
.. attributetable:: FFmpegOpusAudio
.. autoclass:: FFmpegOpusAudio .. autoclass:: FFmpegOpusAudio
:members: :members:
PCMVolumeTransformer
~~~~~~~~~~~~~~~~~~~~~
.. attributetable:: PCMVolumeTransformer
.. autoclass:: PCMVolumeTransformer .. autoclass:: PCMVolumeTransformer
:members: :members:
@ -2149,9 +2217,19 @@ Working with :meth:`Guild.audit_logs` is a complicated process with a lot of mac
involved. The library attempts to make it easy to use and friendly. In order to accomplish involved. The library attempts to make it easy to use and friendly. In order to accomplish
this goal, it must make use of a couple of data classes that aid in this goal. this goal, it must make use of a couple of data classes that aid in this goal.
AuditLogEntry
~~~~~~~~~~~~~~~
.. attributetable:: AuditLogEntry
.. autoclass:: AuditLogEntry .. autoclass:: AuditLogEntry
:members: :members:
AuditLogChanges
~~~~~~~~~~~~~~~~~
.. attributetable:: AuditLogChanges
.. class:: AuditLogChanges .. class:: AuditLogChanges
An audit log change set. An audit log change set.
@ -2196,6 +2274,11 @@ this goal, it must make use of a couple of data classes that aid in this goal.
| ``None`` | No attributes are set. | | ``None`` | No attributes are set. |
+----------------------------------------+--------------------------------------------------+ +----------------------------------------+--------------------------------------------------+
AuditLogDiff
~~~~~~~~~~~~~
.. attributetable:: AuditLogDiff
.. class:: AuditLogDiff .. class:: AuditLogDiff
Represents an audit log "change" object. A change object has dynamic Represents an audit log "change" object. A change object has dynamic
@ -2541,6 +2624,8 @@ Webhook Support
discord.py offers support for creating, editing, and executing webhooks through the :class:`Webhook` class. discord.py offers support for creating, editing, and executing webhooks through the :class:`Webhook` class.
.. attributetable:: Webhook
.. autoclass:: Webhook .. autoclass:: Webhook
:members: :members:
@ -2575,18 +2660,43 @@ They are mainly there for usage with :func:`py:isinstance` and :func:`py:issubcl
This library has a module related to abstract base classes, some of which are actually from the :doc:`abc <py:library/abc>` standard This library has a module related to abstract base classes, some of which are actually from the :doc:`abc <py:library/abc>` standard
module, others which are not. module, others which are not.
Snowflake
~~~~~~~~~~
.. attributetable:: discord.abc.Snowflake
.. autoclass:: discord.abc.Snowflake .. autoclass:: discord.abc.Snowflake
:members: :members:
User
~~~~~
.. attributetable:: discord.abc.User
.. autoclass:: discord.abc.User .. autoclass:: discord.abc.User
:members: :members:
PrivateChannel
~~~~~~~~~~~~~~~
.. attributetable:: discord.abc.PrivateChannel
.. autoclass:: discord.abc.PrivateChannel .. autoclass:: discord.abc.PrivateChannel
:members: :members:
GuildChannel
~~~~~~~~~~~~~
.. attributetable:: discord.abc.GuildChannel
.. autoclass:: discord.abc.GuildChannel .. autoclass:: discord.abc.GuildChannel
:members: :members:
Messageable
~~~~~~~~~~~~
.. attributetable:: discord.abc.Messageable
.. autoclass:: discord.abc.Messageable .. autoclass:: discord.abc.Messageable
:members: :members:
:exclude-members: history, typing :exclude-members: history, typing
@ -2597,6 +2707,11 @@ module, others which are not.
.. automethod:: discord.abc.Messageable.typing .. automethod:: discord.abc.Messageable.typing
:async-with: :async-with:
Connectable
~~~~~~~~~~~~
.. attributetable:: discord.abc.Connectable
.. autoclass:: discord.abc.Connectable .. autoclass:: discord.abc.Connectable
.. _discord_api_models: .. _discord_api_models:
@ -2629,6 +2744,8 @@ the user of the library.
ClientUser ClientUser
~~~~~~~~~~~~ ~~~~~~~~~~~~
.. attributetable:: ClientUser
.. autoclass:: ClientUser() .. autoclass:: ClientUser()
:members: :members:
:inherited-members: :inherited-members:
@ -2636,12 +2753,16 @@ ClientUser
Relationship Relationship
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
.. attributetable:: Relationship
.. autoclass:: Relationship() .. autoclass:: Relationship()
:members: :members:
User User
~~~~~ ~~~~~
.. attributetable:: User
.. autoclass:: User() .. autoclass:: User()
:members: :members:
:inherited-members: :inherited-members:
@ -2656,18 +2777,24 @@ User
Attachment Attachment
~~~~~~~~~~~ ~~~~~~~~~~~
.. attributetable:: Attachment
.. autoclass:: Attachment() .. autoclass:: Attachment()
:members: :members:
Asset Asset
~~~~~ ~~~~~
.. attributetable:: Asset
.. autoclass:: Asset() .. autoclass:: Asset()
:members: :members:
Message Message
~~~~~~~ ~~~~~~~
.. attributetable:: Message
.. autoclass:: Message() .. autoclass:: Message()
:members: :members:
@ -2681,6 +2808,8 @@ DeletedReferencedMessage
Reaction Reaction
~~~~~~~~~ ~~~~~~~~~
.. attributetable:: Reaction
.. autoclass:: Reaction() .. autoclass:: Reaction()
:members: :members:
:exclude-members: users :exclude-members: users
@ -2691,18 +2820,24 @@ Reaction
CallMessage CallMessage
~~~~~~~~~~~~ ~~~~~~~~~~~~
.. attributetable:: CallMessage
.. autoclass:: CallMessage() .. autoclass:: CallMessage()
:members: :members:
GroupCall GroupCall
~~~~~~~~~~ ~~~~~~~~~~
.. attributetable:: GroupCall
.. autoclass:: GroupCall() .. autoclass:: GroupCall()
:members: :members:
Guild Guild
~~~~~~ ~~~~~~
.. attributetable:: Guild
.. autoclass:: Guild() .. autoclass:: Guild()
:members: :members:
:exclude-members: audit_logs :exclude-members: audit_logs
@ -2722,6 +2857,8 @@ Integration
Member Member
~~~~~~ ~~~~~~
.. attributetable:: Member
.. autoclass:: Member() .. autoclass:: Member()
:members: :members:
:inherited-members: :inherited-members:
@ -2736,30 +2873,40 @@ Member
Spotify Spotify
~~~~~~~~ ~~~~~~~~
.. attributetable:: Spotify
.. autoclass:: Spotify() .. autoclass:: Spotify()
:members: :members:
VoiceState VoiceState
~~~~~~~~~~~ ~~~~~~~~~~~
.. attributetable:: VoiceState
.. autoclass:: VoiceState() .. autoclass:: VoiceState()
:members: :members:
Emoji Emoji
~~~~~ ~~~~~
.. attributetable:: Emoji
.. autoclass:: Emoji() .. autoclass:: Emoji()
:members: :members:
PartialEmoji PartialEmoji
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
.. attributetable:: PartialEmoji
.. autoclass:: PartialEmoji() .. autoclass:: PartialEmoji()
:members: :members:
Role Role
~~~~~ ~~~~~
.. attributetable:: Role
.. autoclass:: Role() .. autoclass:: Role()
:members: :members:
@ -2772,6 +2919,8 @@ RoleTags
TextChannel TextChannel
~~~~~~~~~~~~ ~~~~~~~~~~~~
.. attributetable:: TextChannel
.. autoclass:: TextChannel() .. autoclass:: TextChannel()
:members: :members:
:inherited-members: :inherited-members:
@ -2786,6 +2935,8 @@ TextChannel
VoiceChannel VoiceChannel
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
.. attributetable:: VoiceChannel
.. autoclass:: VoiceChannel() .. autoclass:: VoiceChannel()
:members: :members:
:inherited-members: :inherited-members:
@ -2793,6 +2944,8 @@ VoiceChannel
CategoryChannel CategoryChannel
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
.. attributetable:: CategoryChannel
.. autoclass:: CategoryChannel() .. autoclass:: CategoryChannel()
:members: :members:
:inherited-members: :inherited-members:
@ -2800,6 +2953,8 @@ CategoryChannel
DMChannel DMChannel
~~~~~~~~~ ~~~~~~~~~
.. attributetable:: DMChannel
.. autoclass:: DMChannel() .. autoclass:: DMChannel()
:members: :members:
:inherited-members: :inherited-members:
@ -2814,6 +2969,8 @@ DMChannel
GroupChannel GroupChannel
~~~~~~~~~~~~ ~~~~~~~~~~~~
.. attributetable:: GroupChannel
.. autoclass:: GroupChannel() .. autoclass:: GroupChannel()
:members: :members:
:inherited-members: :inherited-members:
@ -2828,18 +2985,24 @@ GroupChannel
PartialInviteGuild PartialInviteGuild
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
.. attributetable:: PartialInviteGuild
.. autoclass:: PartialInviteGuild() .. autoclass:: PartialInviteGuild()
:members: :members:
PartialInviteChannel PartialInviteChannel
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
.. attributetable:: PartialInviteChannel
.. autoclass:: PartialInviteChannel() .. autoclass:: PartialInviteChannel()
:members: :members:
Invite Invite
~~~~~~~ ~~~~~~~
.. attributetable:: Invite
.. autoclass:: Invite() .. autoclass:: Invite()
:members: :members:
@ -2852,12 +3015,16 @@ Template
WidgetChannel WidgetChannel
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
.. attributetable:: WidgetChannel
.. autoclass:: WidgetChannel() .. autoclass:: WidgetChannel()
:members: :members:
WidgetMember WidgetMember
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
.. attributetable:: WidgetMember
.. autoclass:: WidgetMember() .. autoclass:: WidgetMember()
:members: :members:
:inherited-members: :inherited-members:
@ -2865,6 +3032,8 @@ WidgetMember
Widget Widget
~~~~~~~ ~~~~~~~
.. attributetable:: Widget
.. autoclass:: Widget() .. autoclass:: Widget()
:members: :members:
@ -2877,36 +3046,48 @@ Sticker
RawMessageDeleteEvent RawMessageDeleteEvent
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
.. attributetable:: RawMessageDeleteEvent
.. autoclass:: RawMessageDeleteEvent() .. autoclass:: RawMessageDeleteEvent()
:members: :members:
RawBulkMessageDeleteEvent RawBulkMessageDeleteEvent
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
.. attributetable:: RawBulkMessageDeleteEvent
.. autoclass:: RawBulkMessageDeleteEvent() .. autoclass:: RawBulkMessageDeleteEvent()
:members: :members:
RawMessageUpdateEvent RawMessageUpdateEvent
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
.. attributetable:: RawMessageUpdateEvent
.. autoclass:: RawMessageUpdateEvent() .. autoclass:: RawMessageUpdateEvent()
:members: :members:
RawReactionActionEvent RawReactionActionEvent
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
.. attributetable:: RawReactionActionEvent
.. autoclass:: RawReactionActionEvent() .. autoclass:: RawReactionActionEvent()
:members: :members:
RawReactionClearEvent RawReactionClearEvent
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
.. attributetable:: RawReactionClearEvent
.. autoclass:: RawReactionClearEvent() .. autoclass:: RawReactionClearEvent()
:members: :members:
RawReactionClearEmojiEvent RawReactionClearEmojiEvent
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. attributetable:: RawReactionClearEmojiEvent
.. autoclass:: RawReactionClearEmojiEvent() .. autoclass:: RawReactionClearEmojiEvent()
:members: :members:
@ -2937,12 +3118,16 @@ Object
Embed Embed
~~~~~~ ~~~~~~
.. attributetable:: Embed
.. autoclass:: Embed .. autoclass:: Embed
:members: :members:
AllowedMentions AllowedMentions
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
.. attributetable:: AllowedMentions
.. autoclass:: AllowedMentions .. autoclass:: AllowedMentions
:members: :members:
@ -2973,54 +3158,72 @@ MemberCacheFlags
File File
~~~~~ ~~~~~
.. attributetable:: File
.. autoclass:: File .. autoclass:: File
:members: :members:
Colour Colour
~~~~~~ ~~~~~~
.. attributetable:: Colour
.. autoclass:: Colour .. autoclass:: Colour
:members: :members:
BaseActivity BaseActivity
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
.. attributetable:: BaseActivity
.. autoclass:: BaseActivity .. autoclass:: BaseActivity
:members: :members:
Activity Activity
~~~~~~~~~ ~~~~~~~~~
.. attributetable:: Activity
.. autoclass:: Activity .. autoclass:: Activity
:members: :members:
Game Game
~~~~~ ~~~~~
.. attributetable:: Game
.. autoclass:: Game .. autoclass:: Game
:members: :members:
Streaming Streaming
~~~~~~~~~~~ ~~~~~~~~~~~
.. attributetable:: Streaming
.. autoclass:: Streaming .. autoclass:: Streaming
:members: :members:
CustomActivity CustomActivity
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
.. attributetable:: CustomActivity
.. autoclass:: CustomActivity .. autoclass:: CustomActivity
:members: :members:
Permissions Permissions
~~~~~~~~~~~~ ~~~~~~~~~~~~
.. attributetable:: Permissions
.. autoclass:: Permissions .. autoclass:: Permissions
:members: :members:
PermissionOverwrite PermissionOverwrite
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
.. attributetable:: PermissionOverwrite
.. autoclass:: PermissionOverwrite .. autoclass:: PermissionOverwrite
:members: :members:

3
docs/conf.py

@ -38,7 +38,8 @@ extensions = [
'sphinx.ext.napoleon', 'sphinx.ext.napoleon',
'sphinxcontrib_trio', 'sphinxcontrib_trio',
'details', 'details',
'exception_hierarchy' 'exception_hierarchy',
'attributetable',
] ]
autodoc_member_order = 'bysource' autodoc_member_order = 'bysource'

199
docs/extensions/attributetable.py

@ -0,0 +1,199 @@
from sphinx.util.docutils import SphinxDirective
from sphinx.locale import _
from docutils import nodes
from sphinx import addnodes
from collections import OrderedDict
import importlib
import inspect
import os
import re
class attributetable(nodes.General, nodes.Element):
pass
class attributetablecolumn(nodes.General, nodes.Element):
pass
class attributetabletitle(nodes.TextElement):
pass
class attributetableplaceholder(nodes.General, nodes.Element):
pass
def visit_attributetable_node(self, node):
self.body.append('<div class="py-attribute-table" data-move-to-id="%s">' % node['python-class'])
def visit_attributetablecolumn_node(self, node):
self.body.append(self.starttag(node, 'div', CLASS='py-attribute-table-column'))
def visit_attributetabletitle_node(self, node):
self.body.append(self.starttag(node, 'span'))
def depart_attributetable_node(self, node):
self.body.append('</div>')
def depart_attributetablecolumn_node(self, node):
self.body.append('</div>')
def depart_attributetabletitle_node(self, node):
self.body.append('</span>')
_name_parser_regex = re.compile(r'(?P<module>[\w.]+\.)?(?P<name>\w+)')
class PyAttributeTable(SphinxDirective):
has_content = False
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = False
option_spec = {}
def parse_name(self, content):
path, name = _name_parser_regex.match(content).groups()
if path:
modulename = path.rstrip('.')
else:
modulename = self.env.temp_data.get('autodoc:module')
if not modulename:
modulename = self.env.ref_context.get('py:module')
if modulename is None:
raise RuntimeError('modulename somehow None for %s in %s.' % (content, self.env.docname))
return modulename, name
def run(self):
"""If you're curious on the HTML this is meant to generate:
<div class="py-attribute-table">
<div class="py-attribute-table-column">
<span>_('Attributes')</span>
<ul>
<li><a href="..."></li>
</ul>
</div>
<div class="py-attribute-table-column">
<span>_('Coroutines')</span>
<ul>
<li><a href="..."></li>
</ul>
</div>
<div class="py-attribute-table-column">
<span>_('Methods')</span>
<ul>
<li><a href="..."></li>
</ul>
</div>
...
</div>
However, since this requires the tree to be complete
and parsed, it'll need to be done at a different stage and then
replaced.
"""
content = self.arguments[0].strip()
node = attributetableplaceholder('')
modulename, name = self.parse_name(content)
node['python-module'] = modulename
node['python-class'] = name
node['python-full-name'] = '%s.%s' % (modulename, name)
return [node]
def build_lookup_table(env):
# Given an environment, load up a lookup table of
# full-class-name: objects
result = {}
domain = env.domains['py']
ignored = {
'data', 'exception', 'module', 'class',
}
for (fullname, (docname, objtype)) in domain.objects.items():
if objtype in ignored:
continue
classname, _, child = fullname.rpartition('.')
try:
result[classname].append(child)
except KeyError:
result[classname] = [child]
return result
def process_attributetable(app, doctree, fromdocname):
env = app.builder.env
lookup = build_lookup_table(env)
for node in doctree.traverse(attributetableplaceholder):
modulename, classname, fullname = node['python-module'], node['python-class'], node['python-full-name']
groups = get_class_results(lookup, modulename, classname, fullname)
table = attributetable('')
for label, subitems in groups.items():
if not subitems:
continue
table.append(class_results_to_node(label, subitems))
table['python-class'] = fullname
if not table:
node.replace_self([])
else:
node.replace_self([table])
def get_class_results(lookup, modulename, name, fullname):
module = importlib.import_module(modulename)
cls_dict = getattr(module, name).__dict__
groups = OrderedDict([
('Attributes', []),
('Coroutines', []),
('Methods', []),
('Decorators', []),
])
try:
members = lookup[fullname]
except KeyError:
return groups
for attr in members:
attrlookup = '%s.%s' % (fullname, attr)
key = 'Attributes'
label = attr
value = cls_dict.get(attr)
if value is not None:
doc = value.__doc__ or ''
if inspect.iscoroutinefunction(value) or doc.startswith('|coro|'):
key = 'Coroutines'
elif inspect.isfunction(value):
if doc.startswith(('A decorator', 'A shortcut decorator')):
# finicky but surprisingly consistent
key = 'Decorators'
else:
key = 'Methods'
groups[key].append((attrlookup, label))
return groups
def class_results_to_node(key, elements):
title = attributetabletitle(key, key)
ul = nodes.bullet_list('')
for fullname, label in elements:
ref = nodes.reference('', '', internal=True,
refuri='#' + fullname,
anchorname='',
*[nodes.Text(label)])
para = addnodes.compact_paragraph('', '', ref)
item = nodes.list_item('', para)
ul.append(item)
return attributetablecolumn('', title, ul)
def setup(app):
app.add_directive('attributetable', PyAttributeTable)
app.add_node(attributetable, html=(visit_attributetable_node, depart_attributetable_node))
app.add_node(attributetablecolumn, html=(visit_attributetablecolumn_node, depart_attributetablecolumn_node))
app.add_node(attributetabletitle, html=(visit_attributetabletitle_node, depart_attributetabletitle_node))
app.add_node(attributetableplaceholder)
app.connect('doctree-resolved', process_attributetable)
Loading…
Cancel
Save