Commits

Olemis Lang  committed 0f219be

TracBasicMacros: Added rendering styles for config options. Tested except for extensions.

  • Participants
  • Parent commits 6f79fb2

Comments (0)

Files changed (2)

File trac-dev/tracbm/tracbm/config.py

 __author__ = 'Olemis Lang'
 
 from trac.core import TracError
+from trac.config import ExtensionOption, OrderedExtensionsOption, _TRUE_VALUES
 from trac.util.text import to_unicode
+from trac.util.translation import _
 from trac.wiki.api import parse_args
 from trac.wiki.macros import WikiMacroBase
 
+from tracbm.util import load_interface
+
 from genshi.builder import tag
 
 class ConfigOptionMacro(WikiMacroBase):
     
     `[[ConfigOption(section, name, type=option_type, sep=char)]]`
     
-    ''section'' :  the section in trac.ini (mandatory)
-    ''name'' :     option name (mandatory)
-    ''type'' :     if this keyword argument is present then 
-                   the value will be rendered using an
-                   appropriate format according to the option 
-                   type. Supported values are `text` (default),
-                   `bool`, `int`, `list`, `path`, `extension`.
-    ''sep'' :      list separator (otional, ignored if 
-                   `type`! = `list`)
+    ''section'' :           the section in trac.ini (mandatory).
+    ''name'' :              option name (mandatory).
+    ''type'' :              if this keyword argument is present then 
+                            the value will be rendered using an
+                            appropriate format according to the option 
+                            type. Supported values are `text`,
+                            `bool`, `int`, `list`, `path`, `extension`,
+                            `extension_list`. The `default` is to use 
+                            the information stored in the global 
+                            options cache.
+    ''sep'' :               list separator (optional, ignored if 
+                            `type`! = `list`).
+    ''keep_empty'':         include empty list items (optional, ignored if 
+                            `type`! = `list`).
+    ''interface'' :         components should implement this interface. Value 
+                            should be of the form `some.module:some.attribute`
+                            (e.g. `trac.web:IRequestHandler`). If missing and 
+                            `type` is set to `extension` or `extension_list`) 
+                            then the interface type will be looked up in the 
+                            options cache. If it can't be found an error is 
+                            raised.
+    ''include_missing'' :   if true (the default) all components implementing 
+                            the interface are returned, with those specified 
+                            by the option ordered first (optional if type is 
+                            `extension_list`).
     """
     def expand_macro(self, formatter, name, content):
         # TODO: Implement `type` and `sep` options
         # TODO: Permissions for sections and individual options
         args, kw = parse_args(content)
-        opt_type, sep = [kw.get(k) for k in ('type', 'sep')]
         try :
-            value = self.env.config.get(args[0], args[1])
+            s, o = args
         except IndexError :
-            raise TracError('Section and option name are both needed')
+            raise TracError(_('Specify both section and option name, and nothing else'))
         else :
-            return value
-
+            s = s.strip() ; o = o.strip()
+            opt_type = kw.get('type', 'text')
+            self.log.debug('Rendering config option %s in %s using %s', 
+                            s, o, opt_type)
+            return getattr(self, '_render_' + opt_type, self._do_render_unknown) (s, o, kw)
+    
+    # Rendering methods
+    def _render_text(self, s, o, opts):
+        value = self.config.get(s, o, None)
+        if value is not None :
+            return to_unicode(value)
+        else :
+            return self._do_render_none(s, o, opts)
+    
+    def _render_bool(self, s, o, opts):
+        value = self.config.getbool(s, o, None)
+        if value is not None :
+            return tag.input(type="radio", 
+                            checked=value in _TRUE_VALUES and "true" or None, 
+                            disabled="true")
+        else :
+            return self._do_render_none(s, o, opts)
+    
+    def _render_int(self, s, o, opts):
+        value = self.config.getint(s, o, None)
+        if value is not None :
+            return tag.tt(str(value))
+        else :
+            return self._do_render_none(s, o, opts)
+    
+    def _render_list(self, s, o, opts):
+        value = self.config.getlist(s, o, None, opts.get('sep', ','), 
+                                        opts.get('keep_empty', 'true').lower() in _TRUE_VALUES)
+        if value is not None :
+            return tag.o([tag.li(item) for item in value])
+        else :
+            return self._do_render_none(s, o, opts)
+    
+    _render_path = _render_text
+    
+    def _render_extension(self, s, o, opts):
+        try :
+            intf_path = opts['interface']
+        except :
+            raise TracError(_('Keyword argument `interface` is required'))
+        interface = load_interface()
+        try :
+            if s is not None :
+                value = ExtensionOption(s, o, interface, None).__get__(self, self.__class__)
+            else :
+                # A component is supplied instead of option name
+                value = o
+        except AttributeError :
+            value = self.env.config.get(s, o, None)
+            if value is not None :
+                return tag.span(tag.strike(value), 
+                                tag.span(_('missing ?'), style="color: red;"))
+            else :
+                return tag.strike(_('Value not found'))
+        else :
+            value = value.__class__
+            return tag.span(tag.tt(value.__name__), ' at ', tag.i(value.__module__))
+    
+    def _render_extension_list(self, s, o, opts):
+        include_missing = opts.get('include_missing', 'true').lower()  in _TRUE_VALUES
+        try :
+            intf_path = opts['interface']
+        except :
+            raise TracError(_('Keyword argument `interface` is required'))
+        interface = load_interface()
+        option = OrderedExtensionsOption(s, o, interface, None, include_missing)
+        components = option.__get__(self, self.__class__)
+        if components :
+            return tag.strike(_('Empty list'))
+        else :
+            return tag.ol([tag.li(self._render_extension(None, c, opts))] \
+                            for c in components)
+    
+    def _do_render_none(self, s, o, opts):
+        return tag.strike(_('Default value'))
+    
+    def _do_render_unknown(self, s, o, opts):
+        raise TracError(_('Invalid configuration option type'))

File trac-dev/tracbm/tracbm/wiki.py

 from trac.resource import Resource
 from trac.util.datefmt import format_datetime, localtz
 from trac.util.text import to_unicode
+from trac.util.translation import _
 from trac.wiki.api import parse_args
 from trac.wiki.macros import WikiMacroBase
 from trac.wiki.model import WikiPage
     """
     
     table_class = Option('wiki', 'chgtable_class', 'listing', 
-                                doc="""CSS class to render wiki history table""")
+                                doc=_("""CSS class to render wiki history table"""))
     labels = ListOption('wiki', 'chgtable_titles', u'Version, Date, Author, Comment', 
                                 keep_empty=True,
-                                doc="""Comma separated list of column labels for """
-                                """version, time, author, and comment (in that order)""",
+                                doc=_("""Comma separated list of column labels for """
+                                """version, time, author, and comment (in that order)"""),
                                 )
     
     def expand_macro(self, formatter, name, content):
             pagename = args[0]
         except IndexError :
             if not is_wiki :
-                raise TracError('You must specify page name in this context')
+                raise TracError(_('You must specify page name in this context'))
             page = WikiPage(self.env, resource, version=resource.version)
         else :
             pagename = pagename or (is_wiki and resource.id or 'WikiStart')
         ALL_ATTRS = ['version', 'time', 'author', 'comment']
         ATTR_LABELS = self.labels
         ATTR_LABELS = (len(ATTR_LABELS) == len(ALL_ATTRS)) and \
-                        ATTR_LABELS or [u'Version', u'Date', u'Author', u'Comment']
+                        ATTR_LABELS or [_('Version'), _('Date'), _('Author'), _('Comment')]
         
         def format_verinfo(value, attridx):
             return {
                        1 : lambda x : tag.i(format_datetime(x, '%d/%m/%Y %H:%M:%S', tzinfo=localtz)), 
                        0 : lambda x : tag.b(to_unicode(x, 'utf-8')), 
-                       3 : lambda x : to_unicode(x or '(No comments)', 'utf-8'),
+                       3 : lambda x : to_unicode(x or _('(No comments)'), 'utf-8'),
                        2 : lambda x : tag.i(to_unicode(x, 'utf-8')),
-                   }.get(attridx, lambda x : tag.i('Atributo desconocido') ) (value)
+                   }.get(attridx, lambda x : tag.i(_('Atributo desconocido')) ) (value)
         
         if attr is None :
             if cols :
             try :
                 attridx = ALL_ATTRS.index(attr)
             except ValueError :
-                raise TracError('Invalid attribute name %s' % (attr,))
+                raise TracError(_('Invalid attribute name %s') % (attr,))
             else :
                 return format_verinfo(getattr(page, attr, None), attridx)