Edgewall Software
Modify

Ticket #8204 (closed enhancement: fixed)

Opened 3 years ago

Last modified 2 years ago

Unify wiki processors and macros

Reported by: rblank Owned by: rblank
Priority: normal Milestone: 0.12
Component: wiki system Version: 0.12dev
Severity: normal Keywords: wikiprocessor span
Cc:
Release Notes:
API Changes:

Description

Currently, wiki macros can be called in two different ways:

  • Macro syntax: [[Macro(params)]]
  • Wiki processor syntax: {{{#!Macro}}}

Both ways also allow calling MIME renderers and special-purpose processors, defined in WikiProcessor.

Wiki processors and macros are actually almost the same thing, except for the following differences:

  • Wiki processors can take additional arguments, defined on the #! line. When calling a macro using the processor syntax, these arguments are lost.
  • There is no extension point for defining wiki processors, they have to be implemented in WikiProcessor.

Instead of adding a new extension point to define wiki processors, I'd like to add an additional argument to IWikiMacroProvider.expand_macro() to pass the arguments of the wiki processor syntax. The interface would become:

def expand_macro(formatter, name, content, args=None):
    pass

When called with the macro syntax, args would be None. Otherwise, it would pass the .args attribute of WikiProcessor, which is a dictionary of arguments.

The existing processors defined in WikiProcessor could then be moved out into their own macro component, but this is optional.

To ensure backwards compatibility with existing macros and call sites, the following measures will be taken:

  • The existing expand_macro call sites will check if the method expects the additional argument or not, and only pass it in the former case.
  • The new args argument should have a default value of None, to ensure that call sites not in Trac core that still expect the old interface continue to work.

I should have a patch ready in a few days. Comments welcome.

Attachments

8204-processor-args-macro-r8371.patch (2.7 KB) - added by rblank 3 years ago.
Pass wiki processor arguments to macros.
wikiprocessors-or-macros-r9193.patch (4.0 KB) - added by cboos 2 years ago.
WikiProcessors: fix a potential problem with processor arguments.
span-blocks-r9193.patch (3.9 KB) - added by cboos 2 years ago.
WikiProcessors: span can be called as a wiki processor.

Download all attachments as: .zip

Change History

Changed 3 years ago by rblank

Pass wiki processor arguments to macros.

comment:1 follow-up: Changed 3 years ago by rblank

The patch above adds the new optional argument args to IWikiMacroProvider.expand_macro(), though it uses a default of {}, as WikiProcessor is also used for expanding [[Macro()]] syntax. So there's currently no way of differentiating between both forms of calls, which IMO is actually a good thing, as a macro should be written for either of the syntaxes, but normally not both.

The whole change is completely backwards compatible, and will allow implementing the commitlog macro for #1507.

The patch also fixes a minor off-by-two error in Formatter, where the #! at the start of a processor call was not taken into account (it doesn't make a difference, though, as the first item in the result list is dropped anyway).

comment:2 Changed 3 years ago by cboos

Patch reviewed, ok to apply.

Don't forget to update TracDev/ApiChanges/0.12.

comment:3 Changed 3 years ago by rblank

Thanks, applied in [8372].

comment:4 Changed 3 years ago by rblank

  • Resolution set to fixed
  • Status changed from new to closed

And documentation updated in TracDev/ApiChanges/0.12@2.

comment:5 Changed 3 years ago by cboos

Concerning the additional argument 'class': 'wikipage', I think I should fix that, by adding class='wikipage' in the div processor only:

  • trac/wiki/formatter.py

    diff --git a/trac/wiki/formatter.py b/trac/wiki/formatter.py
    a b  
    157157        return elt 
    158158 
    159159    def _div_processor(self, text): 
     160        if 'class' not in self.args: 
     161            self.args['class'] = 'wikipage' 
    160162        return self._elt_processor('div', format_to_html, text, self.args) 
    161163 
    162164    def _span_processor(self, text): 
     
    802804                values = [(v and v[0] in '"\'' and [v[1:-1]] or [v])[0] 
    803805                          for v in args[1::2]] 
    804806                args = dict(zip(keys, values)) 
    805                 if 'class' not in args: 
    806                     args['class'] = 'wikipage' 
    807807                self.code_processor = WikiProcessor(self, name, args) 
    808808            else: 
    809809                self.code_buf.append(line) 

What do you think?

comment:6 follow-up: Changed 3 years ago by rblank

I was indeed wondering if that argument was used elsewhere, but haven't taken the time to look. It does look like the div processor is the only user, so yes, please go ahead. I'll remove the comment from the API change documentation.

comment:7 in reply to: ↑ 6 Changed 3 years ago by cboos

Replying to rblank:
Ok, applied in [8374]

comment:8 in reply to: ↑ 1 ; follow-up: Changed 2 years ago by cboos

  • Keywords wikiprocessor span added
  • Resolution fixed deleted
  • Status changed from closed to reopened

Replying to rblank:

The patch above adds the new optional argument args to IWikiMacroProvider.expand_macro(), though it uses a default of {},

Putting {} (or []) as the default value for a parameter is almost always a bug.
I could have fixed it by assigning {} to self.args later, so that the code retains the following property:

there's currently no way of differentiating between both forms of calls,
which IMO is actually a good thing, as a macro should be written for either of the syntaxes, but normally not both.

But I think that being able to differentiate between those could be useful, as switching between both styles of call makes sense in some cases. A typical example would be the span processor, which should also become callable using a #!span block.

Hence wikiprocessors-or-macros-r9193.patch and span-blocks-r9193.patch.

Changed 2 years ago by cboos

WikiProcessors: fix a potential problem with processor arguments.

Changed 2 years ago by cboos

WikiProcessors: span can be called as a wiki processor.

comment:9 in reply to: ↑ 8 ; follow-up: Changed 2 years ago by rblank

Replying to cboos:

Putting {} (or []) as the default value for a parameter is almost always a bug.

That's a bit an exaggeration IMO, it's fine as long as you don't mutate the argument. But ok.

But I think that being able to differentiate between those could be useful, as switching between both styles of call makes sense in some cases. A typical example would be the span processor, which should also become callable using a #!span block.

Wasn't that already the case? IIRC, you can call the macro with both [[Span()]] and #!Span. Ah, except that you couldn't use the processor arguments for attributes, but you had to place them in the content (as was the case before). Ok, that's pretty useful (and an oversight on my part). Patches look good, please apply. Maybe also change the interface definition to show a default argument of None instead of {}?

comment:10 in reply to: ↑ 9 ; follow-up: Changed 2 years ago by cboos

  • Resolution set to fixed
  • Status changed from reopened to closed

Replying to rblank:

Replying to cboos:

Putting {} (or []) as the default value for a parameter is almost always a bug.

That's a bit an exaggeration IMO, it's fine as long as you don't mutate the argument.

... which can be done in a different place that in the method in question, as was the case there, so this can make things a bit more difficult to maintain. I think we should better avoid it, unless we really, really, REALLY need it :-).

Patches look good, please apply. Maybe also change the interface definition to show a default argument of None instead of {}?

Done in r9199 (with docstrings updated) and r9200.

comment:11 in reply to: ↑ 10 Changed 2 years ago by rblank

Replying to cboos:

... which can be done in a different place that in the method in question, as was the case there, so this can make things a bit more difficult to maintain.

Sure. What I meant is that it is not a bug per se, rather a "bug waiting to happen" ;-)

View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
The resolution will be deleted. Next status will be 'reopened'
to The owner will be changed from rblank. Next status will be 'closed'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.