Edgewall Software
Modify

Opened 13 months ago

Closed 13 months ago

Last modified 12 months ago

#13582 closed defect (fixed)

TypeError is raised from Chrome.get_navigation_items() with Babel

Reported by: Jun Omae Owned by: Jun Omae
Priority: normal Milestone: 1.4.4
Component: i18n Version: 1.4.3
Severity: normal Keywords:
Cc: Branch:
Release Notes:

Fixed handling of util.html functions and navigation items for LazyProxy objects.

API Changes:
Internal Changes:

Description

I encountered the following error while developing th:AccountManagerPlugin with Trac 1.5.x and Python 3.

2023-03-25 06:14:25,244 Trac[main] ERROR: [127.0.0.1] Internal Server Error: <RequestWithSession "POST '/prefs/account'">, referrer 'http://127.0.0.1:46741/trac/prefs/account'
Traceback (most recent call last):
  File "/home/jun66j5/src/accountmanagerplugin.git/.tox/py39-trac15/lib/python3.9/site-packages/trac/web/main.py", line 610, in dispatch_request
    dispatcher.dispatch(req)
  File "/home/jun66j5/src/accountmanagerplugin.git/.tox/py39-trac15/lib/python3.9/site-packages/trac/web/main.py", line 302, in dispatch
    raise e
  File "/home/jun66j5/src/accountmanagerplugin.git/.tox/py39-trac15/lib/python3.9/site-packages/trac/web/main.py", line 248, in dispatch
    resp = chosen_handler.process_request(req)
  File "/home/jun66j5/src/accountmanagerplugin.git/.tox/py39-trac15/lib/python3.9/site-packages/trac/prefs/web_ui.py", line 108, in process_request
    resp = chosen_provider.render_preference_panel(req, panel_id)
  File "/home/jun66j5/src/accountmanagerplugin.git/acct_mgr/web_ui.py", line 136, in render_preference_panel
    data.update(self._do_account(req))
  File "/home/jun66j5/src/accountmanagerplugin.git/acct_mgr/web_ui.py", line 248, in _do_account
    if self._do_change_password(req) and force_change_password:
  File "/home/jun66j5/src/accountmanagerplugin.git/acct_mgr/web_ui.py", line 286, in _do_change_password
    add_notice(req, _("Password updated successfully."))
  File "/home/jun66j5/src/accountmanagerplugin.git/.tox/py39-trac15/lib/python3.9/site-packages/trac/web/chrome.py", line 213, in add_notice
    _add_message(req, 'notices', msg, args)
  File "/home/jun66j5/src/accountmanagerplugin.git/.tox/py39-trac15/lib/python3.9/site-packages/trac/web/chrome.py", line 221, in _add_message
    if msg not in req.chrome[name]:
  File "/home/jun66j5/src/accountmanagerplugin.git/.tox/py39-trac15/lib/python3.9/site-packages/trac/web/api.py", line 569, in __getattr__
    value = self.callbacks[name](self)
  File "/home/jun66j5/src/accountmanagerplugin.git/.tox/py39-trac15/lib/python3.9/site-packages/trac/web/chrome.py", line 818, in prepare_request
    chrome['nav'] = self.get_navigation_items(req, handler)
  File "/home/jun66j5/src/accountmanagerplugin.git/.tox/py39-trac15/lib/python3.9/site-packages/trac/web/chrome.py", line 938, in get_navigation_items
    if attributes['enabled'] and attributes['link'] and \
  File "/home/jun66j5/src/accountmanagerplugin.git/.tox/py39-trac15/lib/python3.9/site-packages/babel/support.py", line 207, in __len__
    return len(self.value)
TypeError: object of type 'Fragment' has no len()

The root cause is that babal.support.LazyProxy doesn't have __bool__ method. However, we should check whether the instance is a LazyProxy before checking whether the instance is a Fragment or Element.

  • trac/util/html.py

    diff --git a/trac/util/html.py b/trac/util/html.py
    index 3e19c5268..3430257b2 100644
    a b def escape(text, quotes=True):  
    9595    """
    9696    if isinstance(text, Markup):
    9797        return text
     98    if LazyProxy and isinstance(text, LazyProxy):
     99        text = text.value
    98100    if isinstance(text, Fragment):
    99101        return Markup(text)
    100102    e = escape_quotes(text)
    def plaintext(text, keeplinebreaks=True):  
    968970    :param keeplinebreaks: optionally keep linebreaks
    969971
    970972    """
     973    if LazyProxy and isinstance(text, LazyProxy):
     974        text = text.value
    971975    if isinstance(text, Fragment):
    972976        text = text.as_text()
    973977    else:
    def find_element(frag, attr=None, cls=None, tag=None):  
    982986    attribute, class or tag, using a preorder depth-first search.
    983987
    984988    """
     989    if LazyProxy and isinstance(frag, LazyProxy):
     990        frag = frag.value
    985991    if isinstance(frag, Element):
    986992        if attr is not None and attr in frag.attrib:
    987993            return frag
  • trac/web/chrome.py

    diff --git a/trac/web/chrome.py b/trac/web/chrome.py
    index 4a559a142..95bd81818 100644
    a b from functools import partial  
    3434
    3535from jinja2 import FileSystemLoader
    3636
     37try:
     38    import babel
     39except ImportError:
     40    babel = LazyProxy = None
     41else:
     42    from babel.support import LazyProxy
     43
    3744from trac.api import IEnvironmentSetupParticipant, ISystemInfoProvider
    3845from trac.config import *
    3946from trac.core import *
    class Chrome(Component):  
    640647        info = get_pkginfo(jinja2).get('version')
    641648        yield 'Jinja2', info
    642649        # Optional Babel
    643         try:
    644             import babel
    645         except ImportError:
    646             babel = None
    647650        if babel is not None:
    648651            info = get_pkginfo(babel).get('version')
    649652            if not get_available_locales():
    class Chrome(Component):  
    877880            label = section.get(name + '.label')
    878881            if href and href.startswith('/'):
    879882                href = req.href + href
     883            if LazyProxy and isinstance(text, LazyProxy):
     884                text = text.value
    880885            if isinstance(text, Element) and text.tag == 'a':
    881886                link = text
    882887                if label:

Attachments (0)

Change History (2)

comment:1 by Jun Omae, 13 months ago

Milestone: 1.61.4.4
Owner: set to Jun Omae
Status: newassigned
Version: 1.5.41.4.3

The same issue exists in Trac 1.4.

$ ~/venv/trac/1.4.3/bin/python
>>> from trac.util.html import find_element, tag
>>> from trac.util.translation import tag_
>>> find_element(tag('logged in as ', tag.b('admin')), tag='b')
<trac.util.html.Element object at 0x7f3ff0c31fa0>
>>> find_element(tag_("logged in as %(name)s", name=tag.b('admin')), tag='b')
>>> #=> should be a Element object

comment:2 by Jun Omae, 13 months ago

Release Notes: modified (diff)
Resolution: fixed
Status: assignedclosed

Fixed in [17693] and merged in [17694].

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain Jun Omae.
The resolution will be deleted. Next status will be 'reopened'.
to The owner will be changed from Jun Omae to the specified user.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.