From: Jeffrey C. J. <doc...@ne...> - 2009-03-15 16:40:56
|
David Goodger <goodger <at> python.org> writes: > > On Fri, Mar 13, 2009 at 15:00, Jeffrey C. Jacobs > <docutils.org.timehorse <at> neverbox.com> wrote: > > In the former case, the root document node has the desired class attributes. > > In the second, the code sets the 'classes' attribute in the document > > properly, > > but when the parse is complete, the original document has been replaced > > with a > > new one that does not contain the class attributes. Very strange! If you > > have > > 2 or more top-level section heading, the document node is maintained, but > > when > > you have only one, it is replaced? Is this expected behaviour? > > Yes, it is replaced by the sole top-level section. Thus the solution > that Günter showed. It's caused by the doctitle transform, which you > can turn off if you want > (http://docutils.sourceforge.net/docs/user/config.html#doctitle-xform). Thanks Günter and David! Well, I did examine the class directive code and see that to compensate for the behaviour of the transform to simplify the doc tree, it sets the class both to itself as a place holder element and to any children uncovered via recursive processing. I don't see a problem with this behaviour per se, so I think it best to write my document-class level directive as follows: -------- class DocumentClassDirective(rst.Directive): required_arguments = 1 optional_arguments = 0 final_argument_whitespace = True option_spec = { } has_content = False def run(self): # Turn the argument into a class-ID doc_class = rst.directives.class_option(self.arguments[0]) # Alias for Root Node document = self.state_machine.document # Set the class for the root node document['classes'].extend(doc_class) # Set the class for any child nodes in case the root is replaced for node in document: node['classes'].extend(doc_class) return [ ] rst.directives.register_directive('doc-class', DocumentClassDirective) -------- But it brings up another issue with I think I would like to investigate. Specifically, if the reason for the removal of a higher-level node is done to make the tree simpler, I think this is the right behaviour. But, it strikes me that, say we take two arbitrary Element derived nodes A and B, such that A is the direct ancestor of B and A has no other children than B. In this case, assuming A is a fairly generic node -- a place holder, such as the root document, then it is fair to delete A and replace B with it. But, the issue IMHO arises when A has more than just its type associated with it. Since we are talking about Element-derived nodes here, it's safe to say A may have any of the Element.list_attributes as attributes: * ids * classes * names * dupnames * backrefs Now, I admit I don't know how ids, names, dupnames or backrefs are used so it would not be fair for me to judge how this information should be handled when A is replaced by B. But at least for classes, since classes is an additive list, it seems that here it would be logical to append any classes in A to B's classes list. So, if initially: >>> A['classes'] [ 'john', 'paul' ] >>> B['classes'] [ 'dark-horse', 'richard' ] Then, the new class that replaces A with B (call it C) should yield: >>> C['classes'] [ 'dark-horse', 'richard', 'john', 'paul' ] IMHO, if the node replacement was instead a node "merge" where in some cases B dominates, and in others, like 'classes', the attributes of A and B are merged to produce C. By this, if A and B are abstract classes, C will look most like B, having all the normal attributes B does, but also having merged in ONLY the attributes common to Element from A. This could be done as one function, Element.merge_node, that could be called any time a node was deleted. First, C would be created from B (which could be a no-op), and then C.merge_node(A) would be called to pull in additional attributes common to an Element in A. I shall look into this possibility as the change may make both class and doc-class directives faster since I assume there are many fewer tree-trimming calls than there are class assignments and IMHO this behaviour would be better expected. |