Make an extension that combines an admonition and ifconfig extension.

109 views
Skip to first unread message

Leandro Lucarella

unread,
May 19, 2008, 9:30:43 PM5/19/08
to sphinx-dev
Hi!

Related to my last message, I'm trying to make a simple sphinx
extension that combines the ifconfig extension with an admonition, to
get a conditionally generated "box" with the internal documentation.

I based the extension con sphinx.ext.ifconfig, but I can't get arround
the admonition part :)

I can conditionally generate a portion of documentation, but it's
inserted without any <div class="..."> surrounding it or whatsoever.

what I want to do is basically convert this:
.. ifconfig:: internal

.. admonition:: Internal

Some internal documentation

to just::

.. internal::

Some internal documentation

Here you can find what I've done so far: http://pastebin.lugmen.org.ar/4106

But I get this traceback when internal=True (i.e., when my internal
node is not 'self-replaced' with nothing):

Traceback (most recent call last):
File "/usr/lib/python2.5/site-packages/sphinx/__init__.py", line
135, in main
app.builder.build_update()
File "/usr/lib/python2.5/site-packages/sphinx/builder.py", line 174,
in build_update
'out of date' % len(to_build))
File "/usr/lib/python2.5/site-packages/sphinx/builder.py", line 213,
in build
self.write(docnames, updated_docnames, method)
File "/usr/lib/python2.5/site-packages/sphinx/builder.py", line 249,
in write
self.write_doc(docname, doctree)
File "/usr/lib/python2.5/site-packages/sphinx/builder.py", line 354,
in write_doc
self.docwriter.write(doctree, destination)
File "/usr/lib/python2.5/site-packages/docutils/writers/
__init__.py", line 78, in write
self.translate()
File "/usr/lib/python2.5/site-packages/sphinx/htmlwriter.py", line
31, in translate
self.document.walkabout(visitor)
File "/usr/lib/python2.5/site-packages/docutils/nodes.py", line 159,
in walkabout
child.walkabout(visitor)
File "/usr/lib/python2.5/site-packages/docutils/nodes.py", line 159,
in walkabout
child.walkabout(visitor)
File "/usr/lib/python2.5/site-packages/docutils/nodes.py", line 159,
in walkabout
child.walkabout(visitor)
File "/usr/lib/python2.5/site-packages/docutils/nodes.py", line 159,
in walkabout
child.walkabout(visitor)
File "/usr/lib/python2.5/site-packages/docutils/nodes.py", line 159,
in walkabout
child.walkabout(visitor)
File "/usr/lib/python2.5/site-packages/docutils/nodes.py", line 151,
in walkabout
visitor.dispatch_visit(self)
File "/usr/lib/python2.5/site-packages/docutils/nodes.py", line
1507, in dispatch_visit
return method(node)
File "/usr/lib/python2.5/site-packages/docutils/nodes.py", line
1528, in unknown_visit
if (node.document.settings.strict_visitor
AttributeError: 'NoneType' object has no attribute 'settings'

I've tried using docutil's directives.register_directive() function by
myself and some other things but nothing seems to work :S

Any ideas on how to make it work?

PS: Please Cc me, I'm not in the list.

Sebastian Wiesner

unread,
May 20, 2008, 6:18:11 AM5/20/08
to sphin...@googlegroups.com, llu...@gmail.com
[ Leandro Lucarella <llu...@gmail.com> ]

> Any ideas on how to make it work?

The following snippet does the work:

http://paste.pocoo.org/show/51691/

--
Freedom is always the freedom of dissenters.
(Rosa Luxemburg)

signature.asc

Leandro Lucarella

unread,
May 20, 2008, 10:13:46 AM5/20/08
to Sebastian Wiesner, sphin...@googlegroups.com
Sebastian Wiesner, el 20 de mayo a las 12:18 me escribiste:

> [ Leandro Lucarella <llu...@gmail.com> ]
> > Any ideas on how to make it work?
>
> The following snippet does the work:
>
> http://paste.pocoo.org/show/51691/

Ok, thanks! That helped.

Any ideas why what I wanted to do didn't worked? It looks kid of hackish
adding a dummy extra node (maybe just because I almost know nothing about
docutils internals ;). There is no way to really create a new admonition
class and replace_self([]) when you don't want to show it?

--
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
----------------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------------
Did you know the originally a Danish guy invented the burglar-alarm
unfortunately, it got stolen

Sebastian Wiesner

unread,
May 20, 2008, 11:20:36 AM5/20/08
to sphin...@googlegroups.com
[ Leandro Lucarella <llu...@gmail.com> ]

> Any ideas why what I wanted to do didn't worked?
No, sorry. I'm neither a Sphinx nor a docutils expert ;)

> It looks kid of hackish adding a dummy extra node (maybe just because I
> almost know nothing about docutils internals ;).

If this way is good enough to be used in the "official" ifconfig extension,
it can't be totally wrong to use it in your own extensions, right? ;)

> There is no way to really create a new admonition class and
> replace_self([]) when you don't want to show it?

http://paste.pocoo.org/show/51767/

signature.asc

Georg Brandl

unread,
May 20, 2008, 11:39:49 AM5/20/08
to sphin...@googlegroups.com
Leandro Lucarella schrieb:

> Sebastian Wiesner, el 20 de mayo a las 12:18 me escribiste:
>> [ Leandro Lucarella <llu...@gmail.com> ]
>> > Any ideas on how to make it work?
>>
>> The following snippet does the work:
>>
>> http://paste.pocoo.org/show/51691/
>
> Ok, thanks! That helped.
>
> Any ideas why what I wanted to do didn't worked? It looks kid of hackish
> adding a dummy extra node (maybe just because I almost know nothing about
> docutils internals ;). There is no way to really create a new admonition
> class and replace_self([]) when you don't want to show it?

Well, the writer has to support new nodes that make it through to it.
(In your first example, the "internal" node.)
The custom nodes that the ifconfig directive inserts are removed while
processing the tree, so no new node type is there for the writer to
handle.

Georg

Leandro Lucarella

unread,
May 20, 2008, 10:12:10 PM5/20/08
to sphinx-dev
Ok, so all note, warning, tip, etc. are recognized by the writer? They
are not treated generally as an admonition?

Leandro Lucarella

unread,
May 20, 2008, 10:17:49 PM5/20/08
to sphinx-dev
On 20 mayo, 12:20, Sebastian Wiesner <basti.wies...@gmx.net> wrote:
> [ Leandro Lucarella <llu...@gmail.com> ]> Any ideas why what I wanted to do didn't worked?
>
> No, sorry.  I'm neither a Sphinx nor a docutils expert ;)
>
> > It looks kid of hackish adding a dummy extra node (maybe just because I
> > almost know nothing about docutils internals ;).
>
> If this way is good enough to be used in the "official" ifconfig extension,
> it can't be totally wrong to use it in your own extensions, right? ;)
>
> > There is no way to really create a new admonition class and
> > replace_self([]) when you don't want to show it?
>
> http://paste.pocoo.org/show/51767/

I like this way better, thank you =)

Leandro Lucarella

unread,
May 20, 2008, 11:04:19 PM5/20/08
to sphinx-dev
Almost :S

When I add an argument (I want to use an admonition with /title/
"Internals") I get an error about loosing classes attribute:
File "/home/luca/repos/pymin/doc/source/sphinx_extensions/
internal.py", line 37, in process_internals_nodes
node.replace_self([])
File "/usr/lib/python2.5/site-packages/docutils/nodes.py", line 602,
in replace_self
'Losing "%s" attribute: %s' % (att, self[att])
AssertionError: Losing "classes" attribute: ['admonition-internals']

If I make:
def internals_directive(name, arguments, *args):
node = admonitions.make_admonition(nodes.admonition, 'internals',
arguments, *args)
node[0].tagname = 'internals'
return node
It works, but with:
def internals_directive(name, arguments, *args):
node = admonitions.make_admonition(nodes.admonition, 'internals',
['Internals'], *args)
node[0].tagname = 'internals'
return node
I get the error.

Is there any way to avoid the assert? I want to remove the node, so I
don't really care if it's loosing attributes or not.

Max Battcher

unread,
May 21, 2008, 3:49:50 AM5/21/08
to sphin...@googlegroups.com
Leandro Lucarella wrote:
> Ok, so all note, warning, tip, etc. are recognized by the writer? They
> are not treated generally as an admonition?

I think that is the way this works. They share some code, but IIRC
ultimately the doc nodes generated from::

.. note::

is different from::

.. admonition:: Note

even though the resulting HTML is equivalent. They are two different
code paths because they are two different directives.

I remember that tripping up something or other that I was working on at
one point, but I don't recall exactly any circumstances. I just
remember looking at the docutils code and going "Huh, that's interesting".

--
--Max Battcher--
http://www.worldmaker.net

Sebastian Wiesner

unread,
May 21, 2008, 4:48:46 AM5/21/08
to sphin...@googlegroups.com
[ Leandro Lucarella <llu...@gmail.com> ]

> Is there any way to avoid the assert? I want to remove the node, so I
> don't really care if it's loosing attributes or not.

How about removing the "classes" attribute right before replacing the
node? ;)

http://paste.pocoo.org/show/52148/

Note, that you need to adapt your style sheet to style admonitions
with "internal" class.

signature.asc

Leandro Lucarella

unread,
May 21, 2008, 10:24:37 AM5/21/08
to sphinx-dev
On 21 mayo, 05:48, Sebastian Wiesner <basti.wies...@gmx.net> wrote:
> [ Leandro Lucarella <llu...@gmail.com> ]
>
> > Is there any way to avoid the assert? I want to remove the node, so I
> > don't really care if it's loosing attributes or not.
>
> How about removing the "classes" attribute right before replacing the
> node? ;)
>
> http://paste.pocoo.org/show/52148/
>
> Note, that you need to adapt your style sheet to style admonitions
> with "internal" class.

Alright then. Here's what it turned into:
http://paste.pocoo.org/show/52274/

Maybe some other people can find it useful, so you are free to include
it with sphinx =) (BOLA license is basically Public Domain).

Thank you all for your help.

Sebastian Wiesner

unread,
May 21, 2008, 11:39:20 AM5/21/08
to sphin...@googlegroups.com
[ Leandro Lucarella <llu...@gmail.com> ]

> On 21 mayo, 05:48, Sebastian Wiesner <basti.wies...@gmx.net> wrote:
> > [ Leandro Lucarella <llu...@gmail.com> ]
> >
> > > Is there any way to avoid the assert? I want to remove the node, so I
> > > don't really care if it's loosing attributes or not.
> >
> > How about removing the "classes" attribute right before replacing the
> > node? ;)
> >
> > http://paste.pocoo.org/show/52148/
> >
> > Note, that you need to adapt your style sheet to style admonitions
> > with "internal" class.
>
> Alright then. Here's what it turned into:
> http://paste.pocoo.org/show/52274/

Since you have already created a closure, that has access to config, you can
omit the traversal of the doctree and evaluate ``config['interal']``
directly inside the directive function, which shortens the code to a little
function:

http://paste.pocoo.org/show/52295/

signature.asc

Leandro Lucarella

unread,
May 21, 2008, 1:45:37 PM5/21/08
to sphinx-dev
On 21 mayo, 12:39, Sebastian Wiesner <basti.wies...@gmx.net> wrote:
> [ Leandro Lucarella <llu...@gmail.com> ]
> > On 21 mayo, 05:48, Sebastian Wiesner <basti.wies...@gmx.net> wrote:
> > > [ Leandro Lucarella <llu...@gmail.com> ]
>
> > > > Is there any way to avoid the assert? I want to remove the node, so I
> > > > don't really care if it's loosing attributes or not.
>
> > > How about removing the "classes" attribute right before replacing the
> > > node? ;)
>
> > >http://paste.pocoo.org/show/52148/
>
> > > Note, that you need to adapt your style sheet to style admonitions
> > > with "internal" class.
>
> > Alright then. Here's what it turned into:
> >http://paste.pocoo.org/show/52274/
>
> Since you have already created a closure, that has access to config, you can
> omit the traversal of the doctree and evaluate ``config['interal']``
> directly inside the directive function, which shortens the code to a little
> function:
>
> http://paste.pocoo.org/show/52295/

Nice! That remove the "loosing classes" hack too =)

The conditional expression is nice too but limits the extension to
Python 2.5 :S
Reply all
Reply to author
Forward
0 new messages