Ejemplo n.º 1
0
 def part_render(self, attr, *a, **kw):
     """Renders the part of a template associated with the %def
     whose name is 'attr'.  This is used primarily by
     r2.lib.menus.Styled"""
     style = kw.get('style', 'html')
     template = self.template(style)
     dt = template.get_def(attr)
     return unsafe(dt.render(thing=self, *a, **kw))
Ejemplo n.º 2
0
 def part_render(self, attr, *a, **kw):
     """Renders the part of a template associated with the %def
     whose name is 'attr'.  This is used primarily by
     r2.lib.menus.Styled"""
     style = kw.get('style', 'html')
     template = self.template(style)
     dt = template.get_def(attr)
     return unsafe(dt.render(thing = self, *a, **kw))
def class_dict():
    t_cls = [Link, Comment, Message, Subreddit]
    l_cls = [Listing, OrganicListing]

    classes  = [('%s: %s') % ('t'+ str(cl._type_id), cl.__name__ ) for cl in t_cls] \
             + [('%s: %s') % (cl.__name__, cl._js_cls) for cl in l_cls]

    res = ', '.join(classes)
    return unsafe('{ %s }' % res)
Ejemplo n.º 4
0
def class_dict():
    t_cls = [Link, Comment, Message, Subreddit]
    l_cls = [Listing, OrganicListing]

    classes  = [('%s: %s') % ('t'+ str(cl._type_id), cl.__name__ ) for cl in t_cls] \
             + [('%s: %s') % (cl.__name__, cl._js_cls) for cl in l_cls]

    res = ', '.join(classes)
    return unsafe('{ %s }' % res)
Ejemplo n.º 5
0
 def render(self, style = None):
     """Renders the template corresponding to this class in the given style."""
     from pylons import c
     style = style or c.render_style or 'html'
     template = self.template(style)
     if template:
         res = template.render(thing = self)
         return res if (style and style.startswith('api')) else unsafe(res)
     else:
         raise NoTemplateFound, repr(self)
Ejemplo n.º 6
0
def class_dict():
    t_cls = [Link, Comment, Message, Subreddit]
    l_cls = [Listing, OrganicListing]

    classes = [("%s: %s") % ("t" + str(cl._type_id), cl.__name__) for cl in t_cls] + [
        ("%s: %s") % (cl.__name__, cl._js_cls) for cl in l_cls
    ]

    res = ", ".join(classes)
    return unsafe("{ %s }" % res)
Ejemplo n.º 7
0
 def render(self, style=None):
     """Renders the template corresponding to this class in the given style."""
     from pylons import c
     style = style or c.render_style or 'html'
     template = self.template(style)
     if template:
         res = template.render(thing=self)
         return res if (style and style.startswith('api')) else unsafe(res)
     else:
         raise NoTemplateFound, repr(self)
def format_html(format_string, *args, **kwargs):
    """
    Similar to str % foo, but passes all arguments through conditional_websafe,
    and calls 'unsafe' on the result. This function should be used instead
    of str.format or % interpolation to build up small HTML fragments.

    Example:

      format_html("Are you %s? %s", name, unsafe(checkbox_html))
    """
    if args and kwargs:
        raise ValueError("Can't specify both positional and keyword args")
    args_safe = tuple(map(conditional_websafe, args))
    kwargs_gen = ((k, conditional_websafe(v)) for (k, v) in kwargs.iteritems())
    kwargs_safe = dict(kwargs_gen)

    format_args = args_safe or kwargs_safe
    return unsafe(format_string % format_args)
Ejemplo n.º 9
0
def format_html(format_string, *args, **kwargs):
    """
    Similar to str % foo, but passes all arguments through conditional_websafe,
    and calls 'unsafe' on the result. This function should be used instead
    of str.format or % interpolation to build up small HTML fragments.

    Example:

      format_html("Are you %s? %s", name, unsafe(checkbox_html))
    """
    if args and kwargs:
        raise ValueError("Can't specify both positional and keyword args")
    args_safe = tuple(map(conditional_websafe, args))
    kwargs_gen = ((k, conditional_websafe(v)) for (k, v) in kwargs.iteritems())
    kwargs_safe = dict(kwargs_gen)

    format_args = args_safe or kwargs_safe
    return unsafe(format_string % format_args)
Ejemplo n.º 10
0
    def _replace_render(style=None, display=True):
        """
        A helper function for listings to set uncachable attributes on a
        rendered thing (item) to its proper display values for the current
        context.
        """
        style = style or c.render_style or 'html'
        replacements = {}

        if hasattr(item, 'child'):
            if item.child:
                replacements['childlisting'] = item.child.render(style=style)
            else:
                # Special case for when the comment tree wasn't built which
                # occurs both in the inbox and spam page view of comments.
                replacements['childlisting'] = None
        else:
            replacements['childlisting'] = ''

        #only LinkListing has a show_nums attribute
        if listing:
            if hasattr(listing, "show_nums"):
                if listing.show_nums:
                    num_str = str(item.num)
                    if hasattr(listing, "num_margin"):
                        num_margin = str(listing.num_margin)
                    else:
                        num_margin = "%.2fex" % (len(str(listing.max_num)) *
                                                 1.1)
                else:
                    num_str = ''
                    num_margin = "0px;display:none"

                replacements["numcolmargin"] = num_margin
                replacements["num"] = num_str

            if hasattr(listing, "max_score"):
                mid_margin = len(str(listing.max_score))
                if hasattr(listing, "mid_margin"):
                    mid_margin = str(listing.mid_margin)
                elif mid_margin == 1:
                    mid_margin = "15px"
                else:
                    mid_margin = "%dex" % (mid_margin + 1)

                replacements["midcolmargin"] = mid_margin

            #$votehash is only present when voting arrows are present
            if c.user_is_loggedin:
                replacements['votehash'] = vote_hash(c.user, item,
                                                     listing.vote_hash_type)
        if hasattr(item, "num_comments"):
            com_label, com_cls = comment_label(item.num_comments)
            if style == "compact":
                com_label = unicode(item.num_comments)
            replacements['numcomments'] = com_label
            replacements['commentcls'] = com_cls

        replacements['display'] = "" if display else "style='display:none'"

        if hasattr(item, "render_score"):
            # replace the score stub
            (replacements['scoredislikes'], replacements['scoreunvoted'],
             replacements['scorelikes']) = item.render_score

        # compute the timesince here so we don't end up caching it
        if hasattr(item, "_date"):
            if hasattr(item, "promoted") and item.promoted is not None:
                from r2.lib import promote
                # promoted links are special in their date handling
                replacements['timesince'] = timesince(item._date -
                                                      promote.timezone_offset)
            else:
                replacements['timesince'] = timesince(item._date)

            replacements['time_period'] = calc_time_period(item._date)

        # compute the last edited time here so we don't end up caching it
        if hasattr(item, "editted") and not isinstance(item.editted, bool):
            replacements['lastedited'] = timesince(item.editted)

        # Set in front.py:GET_comments()
        replacements['previous_visits_hex'] = c.previous_visits_hex

        renderer = render_func or item.render
        res = renderer(style=style, **replacements)

        if isinstance(res, (str, unicode)):
            rv = unsafe(res)
            if g.debug:
                for leftover in re.findall('<\$>(.+?)(?:<|$)', rv):
                    print "replace_render didn't replace %s" % leftover

            return rv

        return res
Ejemplo n.º 11
0
    def _replace_render(style = None, display = True):
        """
        A helper function for listings to set uncachable attributes on a
        rendered thing (item) to its proper display values for the current
        context.
        """
        style = style or c.render_style or 'html'
        replacements = {}

        if hasattr(item, 'child'):
            if item.child:
                replacements['childlisting'] = item.child.render(style=style)
            else:
                # Special case for when the comment tree wasn't built which
                # occurs both in the inbox and spam page view of comments.
                replacements['childlisting'] = None
        else:
            replacements['childlisting'] = ''

        #only LinkListing has a show_nums attribute
        if listing and hasattr(listing, "show_nums"):
            if listing.show_nums and item.num > 0:
                num = str(item.num)
            else:
                num = ""
            replacements["num"] = num

        if getattr(item, "rowstyle_cls", None):
            replacements["rowstyle"] = item.rowstyle_cls

        if hasattr(item, "num_comments"):
            com_label, com_cls = comment_label(item.num_comments)
            if style == "compact":
                com_label = unicode(item.num_comments)
            replacements['numcomments'] = com_label
            replacements['commentcls'] = com_cls

        if hasattr(item, "num_children"):
            label = ungettext("child", "children", item.num_children)
            numchildren_text = strings.number_label % {'num': item.num_children,
                                                       'thing': label}
            replacements['numchildren_text'] = numchildren_text

        replacements['display'] =  "" if display else "style='display:none'"

        if hasattr(item, "render_score"):
            # replace the score stub
            (replacements['scoredislikes'],
             replacements['scoreunvoted'],
             replacements['scorelikes'])  = item.render_score

        # compute the timesince here so we don't end up caching it
        if hasattr(item, "_date"):
            if hasattr(item, "promoted") and item.promoted is not None:
                from r2.lib import promote
                # promoted links are special in their date handling
                replacements['timesince'] = \
                    simplified_timesince(item._date - promote.timezone_offset)
            else:
                replacements['timesince'] = simplified_timesince(item._date)

        # compute the last edited time here so we don't end up caching it
        if hasattr(item, "editted") and not isinstance(item.editted, bool):
            replacements['lastedited'] = simplified_timesince(item.editted)

        renderer = render_func or item.render
        res = renderer(style = style, **replacements)

        if isinstance(res, (str, unicode)):
            rv = unsafe(res)
            if g.debug:
                for leftover in re.findall('<\$>(.+?)(?:<|$)', rv):
                    print "replace_render didn't replace %s" % leftover

            return rv

        return res
Ejemplo n.º 12
0
    def _replace_render(style=None, display=True):
        """
        A helper function for listings to set uncachable attributes on a
        rendered thing (item) to its proper display values for the current
        context.
        """
        style = style or c.render_style or 'html'
        replacements = {}

        child_txt = ( hasattr(item, "child") and item.child )\
            and item.child.render(style = style) or ""
        replacements["childlisting"] = child_txt

        #only LinkListing has a show_nums attribute
        if listing:
            if hasattr(listing, "show_nums"):
                if listing.show_nums:
                    num_str = str(item.num)
                    if hasattr(listing, "num_margin"):
                        num_margin = str(listing.num_margin)
                    else:
                        num_margin = "%.2fex" % (len(str(listing.max_num)) *
                                                 1.1)
                else:
                    num_str = ''
                    num_margin = "0px;display:none"

                replacements["numcolmargin"] = num_margin
                replacements["num"] = num_str

            if hasattr(listing, "max_score"):
                mid_margin = len(str(listing.max_score))
                if hasattr(listing, "mid_margin"):
                    mid_margin = str(listing.mid_margin)
                elif mid_margin == 1:
                    mid_margin = "15px"
                else:
                    mid_margin = "%dex" % (mid_margin + 1)

                replacements["midcolmargin"] = mid_margin

            #$votehash is only present when voting arrows are present
            if c.user_is_loggedin:
                replacements['votehash'] = vote_hash(c.user, item,
                                                     listing.vote_hash_type)
        if hasattr(item, "num_comments"):
            if not item.num_comments:
                # generates "comment" the imperative verb
                com_label = _("comment {verb}")
                com_cls = 'comments empty'
            else:
                # generates "XX comments" as a noun
                com_label = ungettext("comment", "comments", item.num_comments)
                com_label = strings.number_label % dict(num=item.num_comments,
                                                        thing=com_label)
                com_cls = 'comments'
            if style == "compact":
                com_label = unicode(item.num_comments)
            replacements['numcomments'] = com_label
            replacements['commentcls'] = com_cls

        replacements['display'] = "" if display else "style='display:none'"

        if hasattr(item, "render_score"):
            # replace the score stub
            (replacements['scoredislikes'], replacements['scoreunvoted'],
             replacements['scorelikes']) = item.render_score

        # compute the timesince here so we don't end up caching it
        if hasattr(item, "_date"):
            if hasattr(item, "promoted") and item.promoted is not None:
                from r2.lib import promote
                # promoted links are special in their date handling
                replacements['timesince'] = timesince(item._date -
                                                      promote.timezone_offset)
            else:
                replacements['timesince'] = timesince(item._date)

            replacements['time_period'] = calc_time_period(item._date)

        # Set in front.py:GET_comments()
        replacements['previous_visits_hex'] = c.previous_visits_hex

        renderer = render_func or item.render
        res = renderer(style=style, **replacements)

        if isinstance(res, (str, unicode)):
            rv = unsafe(res)
            if g.debug:
                for leftover in re.findall('<\$>(.+?)(?:<|$)', rv):
                    print "replace_render didn't replace %s" % leftover

            return rv

        return res
Ejemplo n.º 13
0
    def _replace_render(style = None, display = True):
        """
        A helper function for listings to set uncachable attributes on a
        rendered thing (item) to its proper display values for the current
        context.
        """
        style = style or c.render_style or 'html'
        replacements = {}
    
        child_txt = ( hasattr(item, "child") and item.child )\
            and item.child.render(style = style) or ""
        replacements["childlisting"] = child_txt
        
    
        #only LinkListing has a show_nums attribute
        if listing: 
            if hasattr(listing, "show_nums"):
                if listing.show_nums:
                    num_str = str(item.num) 
                    if hasattr(listing, "num_margin"):
                        num_margin = str(listing.num_margin)
                    else:
                        num_margin = "%.2fex" % (len(str(listing.max_num))*1.1)
                else:
                    num_str = ''
                    num_margin = "0px"
    
                replacements["numcolmargin"] = num_margin
                replacements["num"] = num_str
    
            if hasattr(listing, "max_score"):
                mid_margin = len(str(listing.max_score)) 
                if hasattr(listing, "mid_margin"):
                    mid_margin = str(listing.mid_margin)
                elif mid_margin == 1:
                    mid_margin = "15px"
                else:
                    mid_margin = "%dex" % (mid_margin+1)
    
                replacements["midcolmargin"] = mid_margin
    
            #$votehash is only present when voting arrows are present
            if c.user_is_loggedin:
                replacements['votehash'] = vote_hash(c.user, item,
                                                     listing.vote_hash_type)
        if hasattr(item, "num_comments"):
            if not item.num_comments:
                # generates "comment" the imperative verb
                com_label = _("comment {verb}")
                com_cls = 'comments empty'
            else:
                # generates "XX comments" as a noun
                com_label = ungettext("comment", "comments", item.num_comments)
                com_label = strings.number_label % dict(num=item.num_comments,
                                                        thing=com_label)
                com_cls = 'comments'
            replacements['numcomments'] = com_label
            replacements['commentcls'] = com_cls
    
        replacements['display'] =  "" if display else "style='display:none'"
    
        if hasattr(item, "render_score"):
            # replace the score stub
            (replacements['scoredislikes'],
             replacements['scoreunvoted'],
             replacements['scorelikes'])  = item.render_score
    
        # compute the timesince here so we don't end up caching it
        if hasattr(item, "_date"):
            replacements['timesince'] = timesince(item._date)

        renderer = render_func or item.render
        res = renderer(style = style, **replacements)
        if isinstance(res, (str, unicode)):
            return unsafe(res)
        return res
Ejemplo n.º 14
0
def json(value):
    return unsafe(simplejson.dumps(value, separators=(',', ':')))
Ejemplo n.º 15
0
def json(value):
    return unsafe(simplejson.dumps(value, separators=(",", ":")))
Ejemplo n.º 16
0
    def _replace_render(style=None, display=True):
        """
        A helper function for listings to set uncachable attributes on a
        rendered thing (item) to its proper display values for the current
        context.
        """
        style = style or c.render_style or 'html'
        replacements = {}

        if hasattr(item, 'child'):
            if item.child:
                replacements['childlisting'] = item.child.render(style=style)
            else:
                # Special case for when the comment tree wasn't built which
                # occurs both in the inbox and spam page view of comments.
                replacements['childlisting'] = None
        else:
            replacements['childlisting'] = ''

        #only LinkListing has a show_nums attribute
        if listing and hasattr(listing, "show_nums"):
            if listing.show_nums and item.num > 0:
                num = str(item.num)
            else:
                num = ""
            replacements["num"] = num

        if getattr(item, "rowstyle_cls", None):
            replacements["rowstyle"] = item.rowstyle_cls

        if hasattr(item, "num_comments"):
            com_label, com_cls = comment_label(item.num_comments)
            if style == "compact":
                com_label = unicode(item.num_comments)
            replacements['numcomments'] = com_label
            replacements['commentcls'] = com_cls

        if hasattr(item, "num_children"):
            label = ungettext("child", "children", item.num_children)
            numchildren_text = strings.number_label % {
                'num': item.num_children,
                'thing': label
            }
            replacements['numchildren_text'] = numchildren_text

        replacements['display'] = "" if display else "style='display:none'"

        if hasattr(item, "render_score"):
            # replace the score stub
            (replacements['scoredislikes'], replacements['scoreunvoted'],
             replacements['scorelikes']) = item.render_score

        # compute the timesince here so we don't end up caching it
        if hasattr(item, "_date"):
            if hasattr(item, "promoted") and item.promoted is not None:
                from r2.lib import promote
                # promoted links are special in their date handling
                replacements['timesince'] = \
                    simplified_timesince(item._date - promote.timezone_offset)
            else:
                replacements['timesince'] = simplified_timesince(item._date)

        # compute the last edited time here so we don't end up caching it
        if hasattr(item, "editted") and not isinstance(item.editted, bool):
            replacements['lastedited'] = simplified_timesince(item.editted)

        renderer = render_func or item.render
        res = renderer(style=style, **replacements)

        if isinstance(res, (str, unicode)):
            rv = unsafe(res)
            if g.debug:
                for leftover in re.findall('<\$>(.+?)(?:<|$)', rv):
                    print "replace_render didn't replace %s" % leftover

            return rv

        return res
Ejemplo n.º 17
0
 def render(self, style = None, **kw):
     from r2.lib.filters import unsafe
     res = self._render(None, style, **kw)
     return unsafe(res) if isinstance(res, str) else res
Ejemplo n.º 18
0
    def _replace_render(style = None, display = True):
        """
        A helper function for listings to set uncachable attributes on a
        rendered thing (item) to its proper display values for the current
        context.
        """
        style = style or c.render_style or 'html'
        replacements = {}

        if hasattr(item, 'child'):
            if item.child:
                replacements['childlisting'] = item.child.render(style=style)
            else:
                # Special case for when the comment tree wasn't built which
                # occurs both in the inbox and spam page view of comments.
                replacements['childlisting'] = None
        else:
            replacements['childlisting'] = ''

        #only LinkListing has a show_nums attribute
        if listing:
            if hasattr(listing, "show_nums"):
                if listing.show_nums:
                    num_str = str(item.num)
                    if hasattr(listing, "num_margin"):
                        num_margin = str(listing.num_margin)
                    else:
                        num_margin = "%.2fex" % (len(str(listing.max_num))*1.1)
                else:
                    num_str = ''
                    num_margin = "0px;display:none"

                replacements["numcolmargin"] = num_margin
                replacements["num"] = num_str

            if hasattr(listing, "max_score"):
                mid_margin = len(str(listing.max_score))
                if hasattr(listing, "mid_margin"):
                    mid_margin = str(listing.mid_margin)
                elif mid_margin == 1:
                    mid_margin = "15px"
                else:
                    mid_margin = "%dex" % (mid_margin+1)

                replacements["midcolmargin"] = mid_margin

            #$votehash is only present when voting arrows are present
            if c.user_is_loggedin:
                replacements['votehash'] = vote_hash(c.user, item,
                                                     listing.vote_hash_type)
        if hasattr(item, "num_comments"):
            com_label, com_cls = comment_label(item.num_comments)
            if style == "compact":
                com_label = unicode(item.num_comments)
            replacements['numcomments'] = com_label
            replacements['commentcls'] = com_cls

        replacements['display'] =  "" if display else "style='display:none'"

        if hasattr(item, "render_score"):
            # replace the score stub
            (replacements['scoredislikes'],
             replacements['scoreunvoted'],
             replacements['scorelikes'])  = item.render_score

        # compute the timesince here so we don't end up caching it
        if hasattr(item, "_date"):
            if hasattr(item, "promoted") and item.promoted is not None:
                from r2.lib import promote
                # promoted links are special in their date handling
                replacements['timesince'] = timesince(item._date -
                                                      promote.timezone_offset)
            else:
                replacements['timesince'] = timesince(item._date)

            replacements['time_period'] = calc_time_period(item._date)

        # compute the last edited time here so we don't end up caching it
        if hasattr(item, "editted") and not isinstance(item.editted, bool):
            replacements['lastedited'] = timesince(item.editted)

        # Set in front.py:GET_comments()
        replacements['previous_visits_hex'] = c.previous_visits_hex

        renderer = render_func or item.render
        res = renderer(style = style, **replacements)

        if isinstance(res, (str, unicode)):
            rv = unsafe(res)
            if g.debug:
                for leftover in re.findall('<\$>(.+?)(?:<|$)', rv):
                    print "replace_render didn't replace %s" % leftover

            return rv

        return res
Ejemplo n.º 19
0
def json(value):
    return unsafe(simplejson.dumps(value, separators=(',', ':')))
Ejemplo n.º 20
0
def path_info():
    loc = dict(path=request.path, params=dict(request.get))

    return unsafe(simplejson.dumps(loc))
Ejemplo n.º 21
0
def path_info():
    loc = dict(path = request.path,
               params = dict(request.get))
    
    return unsafe(simplejson.dumps(loc))
Ejemplo n.º 22
0
    def _replace_render(style = None, display = True):
        """
        A helper function for listings to set uncachable attributes on a
        rendered thing (item) to its proper display values for the current
        context.
        """
        style = style or c.render_style or 'html'
        replacements = {}

        child_txt = ( hasattr(item, "child") and item.child )\
            and item.child.render(style = style) or ""
        replacements["childlisting"] = child_txt


        #only LinkListing has a show_nums attribute
        if listing:
            if hasattr(listing, "show_nums"):
                if listing.show_nums:
                    num_str = str(item.num)
                    if hasattr(listing, "num_margin"):
                        num_margin = str(listing.num_margin)
                    else:
                        num_margin = "%.2fex" % (len(str(listing.max_num))*1.1)
                else:
                    num_str = ''
                    num_margin = "0px;display:none"

                replacements["numcolmargin"] = num_margin
                replacements["num"] = num_str

            if hasattr(listing, "max_score"):
                mid_margin = len(str(listing.max_score))
                if hasattr(listing, "mid_margin"):
                    mid_margin = str(listing.mid_margin)
                elif mid_margin == 1:
                    mid_margin = "15px"
                else:
                    mid_margin = "%dex" % (mid_margin+1)

                replacements["midcolmargin"] = mid_margin

            #$votehash is only present when voting arrows are present
            if c.user_is_loggedin:
                replacements['votehash'] = vote_hash(c.user, item,
                                                     listing.vote_hash_type)
        if hasattr(item, "num_comments"):
            if not item.num_comments:
                # generates "comment" the imperative verb
                com_label = _("comment {verb}")
                com_cls = 'comments empty'
            else:
                # generates "XX comments" as a noun
                com_label = ungettext("comment", "comments", item.num_comments)
                com_label = strings.number_label % dict(num=item.num_comments,
                                                        thing=com_label)
                com_cls = 'comments'
            if style == "compact":
                com_label = unicode(item.num_comments)
            replacements['numcomments'] = com_label
            replacements['commentcls'] = com_cls

        replacements['display'] =  "" if display else "style='display:none'"

        if hasattr(item, "render_score"):
            # replace the score stub
            (replacements['scoredislikes'],
             replacements['scoreunvoted'],
             replacements['scorelikes'])  = item.render_score

        # compute the timesince here so we don't end up caching it
        if hasattr(item, "_date"):
            if hasattr(item, "promoted") and item.promoted is not None:
                from r2.lib import promote
                # promoted links are special in their date handling
                replacements['timesince'] = timesince(item._date -
                                                      promote.timezone_offset)
            else:
                replacements['timesince'] = timesince(item._date)

            replacements['time_period'] = calc_time_period(item._date)

        # Set in front.py:GET_comments()
        replacements['previous_visits_hex'] = c.previous_visits_hex

        renderer = render_func or item.render
        res = renderer(style = style, **replacements)

        if isinstance(res, (str, unicode)):
            rv = unsafe(res)
            if g.debug:
                for leftover in re.findall('<\$>(.+?)(?:<|$)', rv):
                    print "replace_render didn't replace %s" % leftover

            return rv

        return res
Ejemplo n.º 23
0
    def _replace_render(style=None, display=True):
        """
        A helper function for listings to set uncachable attributes on a
        rendered thing (item) to its proper display values for the current
        context.
        """
        style = style or c.render_style or "html"
        replacements = {}

        if hasattr(item, "child"):
            if item.child:
                replacements["childlisting"] = item.child.render(style=style)
            else:
                # Special case for when the comment tree wasn't built which
                # occurs both in the inbox and spam page view of comments.
                replacements["childlisting"] = None
        else:
            replacements["childlisting"] = ""

        # only LinkListing has a show_nums attribute
        if listing and hasattr(listing, "show_nums"):
            replacements["num"] = str(item.num) if listing.show_nums else ""

        if hasattr(item, "num_comments"):
            com_label, com_cls = comment_label(item.num_comments)
            if style == "compact":
                com_label = unicode(item.num_comments)
            replacements["numcomments"] = com_label
            replacements["commentcls"] = com_cls

        replacements["display"] = "" if display else "style='display:none'"

        if hasattr(item, "render_score"):
            # replace the score stub
            (
                replacements["scoredislikes"],
                replacements["scoreunvoted"],
                replacements["scorelikes"],
            ) = item.render_score

        # compute the timesince here so we don't end up caching it
        if hasattr(item, "_date"):
            if hasattr(item, "promoted") and item.promoted is not None:
                from r2.lib import promote

                # promoted links are special in their date handling
                replacements["timesince"] = timesince(item._date - promote.timezone_offset)
            else:
                replacements["timesince"] = timesince(item._date)

            replacements["time_period"] = calc_time_period(item._date)

        # compute the last edited time here so we don't end up caching it
        if hasattr(item, "editted") and not isinstance(item.editted, bool):
            replacements["lastedited"] = timesince(item.editted)

        # Set in front.py:GET_comments()
        replacements["previous_visits_hex"] = c.previous_visits_hex

        renderer = render_func or item.render
        res = renderer(style=style, **replacements)

        if isinstance(res, (str, unicode)):
            rv = unsafe(res)
            if g.debug:
                for leftover in re.findall("<\$>(.+?)(?:<|$)", rv):
                    print "replace_render didn't replace %s" % leftover

            return rv

        return res