What version of Djblets are you using?
1.0.2 (RB 3.0.2)
Which module(s) have the problem?
AvatarService
What steps will reproduce the problem?
- Enable my CustomAvatarService (https://github.com/misery/CustomUrlAvatar)
- Go to http://localhost/admin/db/reviews/defaultreviewer/1/
- RB throws error 500
What is the expected output? What do you see instead?
Expected:
Show the site or let reviewboard print missing REQUIRED methods immediately instead of "stacktrace on random sites".https://www.reviewboard.org/docs/djblets/1.0/coderef/python/djblets.avatars.services.base/
A service that provides avatar support.
At the very least, subclasses must set the avatar_service_id and name attributes, as well as override the get_avatar_urls() method.
"get_avatar_urls_uncached" should be mentioned if required.
What version of Python and Django?
python 2.7.14
django 1.6.11.6Please provide any additional information below.
Traceback (most recent call last):
File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/core/handlers/base.py", line 137, in get_response
response = response.render()File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/response.py", line 105, in render
self.content = self.rendered_contentFile "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/response.py", line 82, in rendered_content
content = template.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 140, in render
return self._render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 134, in _render
return self.nodelist.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 840, in render
bit = self.render_node(node, context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
return node.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/loader_tags.py", line 123, in render
return compiled_parent._render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 134, in _render
return self.nodelist.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 840, in render
bit = self.render_node(node, context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
return node.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/loader_tags.py", line 123, in render
return compiled_parent._render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 134, in _render
return self.nodelist.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 840, in render
bit = self.render_node(node, context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
return node.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/loader_tags.py", line 62, in render
result = block.nodelist.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 840, in render
bit = self.render_node(node, context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
return node.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/loader_tags.py", line 62, in render
result = block.nodelist.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 840, in render
bit = self.render_node(node, context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
return node.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/loader_tags.py", line 62, in render
result = block.nodelist.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 840, in render
bit = self.render_node(node, context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
return node.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/defaulttags.py", line 203, in render
nodelist.append(node.render(context))File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/loader_tags.py", line 155, in render
return self.render_template(self.template, context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/loader_tags.py", line 137, in render_template
output = template.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 140, in render
return self._render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 134, in _render
return self.nodelist.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 840, in render
bit = self.render_node(node, context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
return node.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/defaulttags.py", line 203, in render
nodelist.append(node.render(context))File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/defaulttags.py", line 203, in render
nodelist.append(node.render(context))File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/defaulttags.py", line 305, in render
return nodelist.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 840, in render
bit = self.render_node(node, context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
return node.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/defaulttags.py", line 305, in render
return nodelist.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 840, in render
bit = self.render_node(node, context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
return node.render(context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 897, in render
return render_value_in_context(output, context)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/template/base.py", line 875, in render_value_in_context
value = force_text(value)File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/utils/encoding.py", line 100, in force_text
s = s.unicode()File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/forms/forms.py", line 425, in str
return self.as_widget()File "/opt/reviewboard/dist/lib/python2.7/site-packages/django/forms/forms.py", line 475, in as_widget
return widget.render(name, self.value(), attrs=attrs)File "/opt/reviewboard/dist/lib/python2.7/site-packages/reviewboard/admin/form_widgets.py", line 101, in render
.get_avatar_urls_uncached(user, 40)File "/opt/reviewboard/dist/lib/python2.7/site-packages/djblets/avatars/services/base.py", line 174, in get_avatar_urls_uncached
% type(self)NotImplementedError: <class 'custom_url_avatar.extension.CustomAvatarService'> must implement get_avatar_urls_uncached().
This would be a good one to fix in the same change: https://hellosplat.com/s/beanbag/tickets/4634/
Thanks!
By the way.... get_avatar_urls provides the request and get_avatar_urls_uncached provides user and size only.
As I need to check whether the user uses HTTP or HTTPS I cannot provide a correct url with my extension. Otherwise the user could have a "mixed content" problem "https -> http" or a broken link "no https". Also maybe I don't know the used host.Any idea how I can fix this in an extension?
Snippet:
'1x': mark_safe( self._extension.settings[CONFIG_CUSTOM_URL].format( scheme='https' if request.is_secure() else 'http', host=request.get_host(), user=user, size=size, ))
If you use //www.blah.com, it will select the same HTTP/HTTPS scheme as the current page.
That said, I agree that uncached should ideally have the request, but the etag building would have to take care to provide the relevant data in the etag.