• 
      

    Add default renderers for group actions.

    Review Request #14700 — Created Nov. 18, 2025 and submitted

    Information

    Review Board
    release-7.1.x

    Reviewers

    Attachment points and groups both support specifying default renderers
    for any actions nested within. This applied to both standard actions and
    group actions, which would do the wrong thing for group actions, and
    necessitated that group actions always specify their own renderers.

    These can now specify the default renderer for any group actions. With
    this, an attachment point for a menubar could specify that all group
    actions are rendered as menus, and groups in sidebars are rendered as
    subsections, as a couple of examples.

    As an internal optimization, actions now have an is_action_group
    boolean property, which differentiates between an action and an action
    group. This avoids the more costly isinstance checks that'd otherwise
    need to be done multiple times per action render.

    I also noted cases where fallback renderers weren't being used, and
    where an detailed menu item action failed to render correctly with an
    action lacking an icon. These have been fixed.

    Unit tests pass.

    Tested that existing actions work as expected.

    Tested along with the upcoming addition of sidebar renderers.

    Summary ID
    Add default renderers for group actions.
    Attachment points and groups both support specifying default renderers for any actions nested within. This applied to both standard actions and group actions, which would do the wrong thing for group actions, and necessitated that group actions always specify their own renderers. These can now specify the default renderer for any group actions. With this, an attachment point for a menubar could specify that all group actions are rendered as menus, and groups in sidebars are rendered as subsections, as a couple of examples. Group renderers can assign a special value of "self" for subgroup renderers, which ensures the same group renderer is used for its children. Group renderers are also now responsible for rendering their children, moving much of the logic from `{% child_actions_html %}` into a new `BaseActionGroupRenderer.render_children()` method. As an internal optimization, actions now have an `_is_action_group` boolean property, which differentiates between an action and an action group. This avoids the more costly `isinstance` checks that'd otherwise need to be done multiple times per action render. I also noted cases where fallback renderers weren't being used, and where an detailed menu item action failed to render correctly with an action lacking an icon. These have been fixed.
    6c921413768587ed07e84713f9c062a466fa70d6
    Description From Last Updated

    Just noticed that this class docstring is missing "Version Added"

    daviddavid

    Given that this is not public API, should we call it _is_action_group?

    daviddavid

    Can we add the "Instance variables" comment in here?

    daviddavid

    'reviewboard.actions.renderers.ActionSubgroupRendererType' imported but unused Column: 5 Error code: F401

    reviewbotreviewbot

    line too long (89 > 79 characters) Column: 80 Error code: E501

    reviewbotreviewbot

    line too long (95 > 79 characters) Column: 80 Error code: E501

    reviewbotreviewbot

    continuation line under-indented for visual indent Column: 39 Error code: E128

    reviewbotreviewbot

    'logging' imported but unused Column: 1 Error code: F401

    reviewbotreviewbot

    Can we add a comment here explaining this case, something like "This attachment point does not allow for child actions."

    maubinmaubin

    This is missing its docstring.

    maubinmaubin

    Seems like these should probably both be logger.error. I don't think we need the traceback in the second case.

    daviddavid
    david
    1. 
        
    2. reviewboard/actions/base.py (Diff revision 1)
       
       
      Show all issues

      Just noticed that this class docstring is missing "Version Added"

    3. reviewboard/actions/base.py (Diff revision 1)
       
       
       
       
       
       
       
       
       
       
       
      Show all issues

      Given that this is not public API, should we call it _is_action_group?

    4. reviewboard/actions/renderers.py (Diff revision 1)
       
       
      Show all issues

      Can we add the "Instance variables" comment in here?

      1. These are all class variables. I'll type them as such. Initially I had intended to let these be set as instance variables, but I've changed that design.

    5. 
        
    chipx86
    Review request changed
    Change Summary:
    • Added BaseActionGroupRenderer.render_children() to handle children rendering, recursively. This addresses issues with renderer selection from the previous code, and can recurse.
    • Added support for 'self' as a value for subgroup renderers, so a group can easily recurse. The template tag is now a thin wrapper around this.
    • Renamed is_action_group to _is_action_group.
    • default_item_renderer_cls and default_subgroup_renderer_cls are now ClassVars.
    • Added a missing Version Added.
    Commits:
    Summary ID
    Add default renderers for group actions.
    Attachment points and groups both support specifying default renderers for any actions nested within. This applied to both standard actions and group actions, which would do the wrong thing for group actions, and necessitated that group actions always specify their own renderers. These can now specify the default renderer for any group actions. With this, an attachment point for a menubar could specify that all group actions are rendered as menus, and groups in sidebars are rendered as subsections, as a couple of examples. As an internal optimization, actions now have an `is_action_group` boolean property, which differentiates between an action and an action group. This avoids the more costly `isinstance` checks that'd otherwise need to be done multiple times per action render. I also noted cases where fallback renderers weren't being used, and where an detailed menu item action failed to render correctly with an action lacking an icon. These have been fixed.
    7a279edeaf0730e8c028399fa73ffe61c3f927d3
    Add default renderers for group actions.
    Attachment points and groups both support specifying default renderers for any actions nested within. This applied to both standard actions and group actions, which would do the wrong thing for group actions, and necessitated that group actions always specify their own renderers. These can now specify the default renderer for any group actions. With this, an attachment point for a menubar could specify that all group actions are rendered as menus, and groups in sidebars are rendered as subsections, as a couple of examples. Group renderers can assign a special value of "self" for subgroup renderers, which ensures the same group renderer is used for its children. Group renderers are also now responsible for rendering their children, moving much of the logic from `{% child_actions_html %}` into a new `BaseActionGroupRenderer.render_children()` method. As an internal optimization, actions now have an `_is_action_group` boolean property, which differentiates between an action and an action group. This avoids the more costly `isinstance` checks that'd otherwise need to be done multiple times per action render. I also noted cases where fallback renderers weren't being used, and where an detailed menu item action failed to render correctly with an action lacking an icon. These have been fixed.
    24cb0636eac8536774cd08e3ec2378e49e02a9b4

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    chipx86
    david
    1. 
        
    2. reviewboard/actions/renderers.py (Diff revision 3)
       
       
       
       
       
       
       
       
       
       
       
       
       
      Show all issues

      Seems like these should probably both be logger.error. I don't think we need the traceback in the second case.

      1. Not sure what happened there.

    3. 
        
    maubin
    1. 
        
    2. reviewboard/actions/base.py (Diff revision 3)
       
       
       
       
      Show all issues

      Can we add a comment here explaining this case, something like "This attachment point does not allow for child actions."

    3. reviewboard/actions/renderers.py (Diff revision 3)
       
       
      Show all issues

      This is missing its docstring.

    4. 
        
    chipx86
    maubin
    1. Ship It!
    2. 
        
    chipx86
    Review request changed
    Status:
    Completed
    Change Summary:
    Pushed to release-7.1.x (1f1f6e8)