# -*- coding: utf-8 -*- """ (c) 2014-2016 - Copyright Red Hat Inc Authors: Pierre-Yves Chibon """ # pylint: disable=too-many-branches # pylint: disable=too-many-arguments # pylint: disable=too-many-locals import datetime import textwrap import urlparse import arrow import flask import md5 from pygments import highlight from pygments.lexers.text import DiffLexer from pygments.formatters import HtmlFormatter import pagure.exceptions import pagure.lib import pagure.forms from pagure import (APP, SESSION, authenticated, is_repo_admin) # Jinja filters @APP.template_filter('hasattr') def jinja_hasattr(obj, string): """ Template filter checking if the provided object at the provided string as attribute """ return hasattr(obj, string) @APP.template_filter('render') def jinja_render(tmpl, **kwargs): """ Render the given template with the provided arguments """ return flask.render_template_string(tmpl, **kwargs) @APP.template_filter('humanize') def humanize_date(date): """ Template filter returning the last commit date of the provided repo. """ return arrow.get(date).humanize() @APP.template_filter('format_ts') def format_ts(string): """ Template filter transforming a timestamp to a date """ dattime = datetime.datetime.fromtimestamp(int(string)) return dattime.strftime('%b %d %Y %H:%M:%S') @APP.template_filter('format_loc') def format_loc(loc, commit=None, filename=None, tree_id=None, prequest=None, index=None): """ Template filter putting the provided lines of code into a table """ if loc is None: return output = [ '
', '' ] comments = {} if prequest and not isinstance(prequest, flask.wrappers.Request): for com in prequest.comments: if commit and unicode(com.commit_id) == unicode(commit) \ and unicode(com.filename) == unicode(filename): if com.line in comments: comments[com.line].append(com) else: comments[com.line] = [com] for key in comments: comments[key] = sorted( comments[key], key=lambda obj: obj.date_created) if not index: index = '' cnt = 1 for line in loc.split('\n'): if line == '': break if filename and commit: output.append( '' '' % ( { 'cnt': '%s_%s' % (index, cnt), 'cnt_lbl': cnt, 'filename': filename.decode('UTF-8'), 'commit': commit, 'tree_id': tree_id, } ) ) else: output.append( '' % ( { 'cnt': '%s_%s' % (index, cnt), 'cnt_lbl': cnt, } ) ) cnt += 1 if not line: output.append(line) continue if line.startswith('')[1] output.append('' % line) output.append('') tpl_edit = '' \ '' \ '' tpl_edited = ' ' \ 'Edited %(human_edit_date)s by %(user)s ' tpl_delete = '' if cnt - 1 in comments: for comment in comments[cnt - 1]: templ_delete = '' templ_edit = '' templ_edited = '' status = str(comment.parent.status).lower() if authenticated() and ( ( status in ['true', 'open'] and comment.user.user == flask.g.fas_user.username ) or is_repo_admin(comment.parent.project)): templ_delete = tpl_delete % ({'commentid': comment.id}) templ_edit = tpl_edit % ({ 'edit_url': flask.url_for( 'pull_request_edit_comment', repo=comment.parent.project.name, requestid=comment.parent.id, commentid=comment.id, username=comment.parent.user.user if comment.parent.project.is_fork else None ), 'requestid': comment.parent.id, 'commentid': comment.id, }) if comment.edited_on: templ_edited = tpl_edited % ({ 'edit_date': comment.edited_on.strftime( '%b %d %Y %H:%M:%S'), 'human_edit_date': humanize_date(comment.edited_on), 'user': comment.editor.user, }) output.append( '' '' % ( { 'url': flask.url_for( 'view_user', username=comment.user.user), 'templ_delete': templ_delete, 'templ_edit': templ_edit, 'templ_edited': templ_edited, 'user': comment.user.user, 'avatar_url': avatar_url( comment.user.default_email, 16), 'date': comment.date_created.strftime( '%b %d %Y %H:%M:%S'), 'human_date': humanize_date(comment.date_created), 'comment': markdown_filter(comment.comment), 'commentid': comment.id, } ) ) output.append('
' '' '

' '' '

' '
' '
%s
' '
' '
' '
' '' ' %(user)s commented ' '' '%(human_date)s' '
' '
' '
' '%(comment)s' '
' '
' '
' '%(templ_edited)s' '' '
' '
') return '\n'.join(output) @APP.template_filter('wraps') def text_wraps(text, size=10): """ Template filter to wrap text at a specified size """ if text: parts = textwrap.wrap(text, size) if len(parts) > 1: parts = '%s...' % parts[0] else: parts = parts[0] return parts @APP.template_filter('avatar') def avatar(packager, size=64): """ Template filter sorting the given branches, Fedora first then EPEL, then whatever is left. """ if '@' not in packager: user = pagure.lib.search_user(SESSION, username=packager) if user: packager = user.default_email output = '' % ( avatar_url(packager, size) ) return output @APP.template_filter('avatar_url') def avatar_url(email, size=64): """ Template filter sorting the given branches, Fedora first then EPEL, then whatever is left. """ return pagure.lib.avatar_url_from_openid(email, size) @APP.template_filter('short') def shorted_commit(cid): """Gets short version of the commit id""" return str(cid)[:APP.config['SHORT_LENGTH']] @APP.template_filter('markdown') def markdown_filter(text): """ Template filter converting a string into html content using the markdown library. """ return pagure.lib.text2markdown(text) @APP.template_filter('html_diff') def html_diff(diff): """Display diff as HTML""" if diff is None: return return highlight( diff, DiffLexer(), HtmlFormatter( noclasses=True, style="tango",) ) @APP.template_filter('patch_to_diff') def patch_to_diff(patch): """Render a hunk as a diff""" content = "" for hunk in patch.hunks: content = content + "@@ -%i,%i +%i,%i @@\n" % ( hunk.old_start, hunk.old_lines, hunk.new_start, hunk.new_lines) for line in hunk.lines: if hasattr(line, 'content'): origin = line.origin if line.origin in ['<', '>', '=']: origin = '' content = content + origin + ' ' + line.content else: # Avoid situation where at the end of a file we get: # + foo< # \ No newline at end of file if line[0] in ['<', '>', '=']: line = ('', line[1]) content = content + ' '.join(line) return content @APP.template_filter('author2user') def author_to_user(author, size=16): """ Template filter transforming a pygit2 Author object into a text either with just the username or linking to the user in pagure. """ output = author.name if not author.email: return output user = pagure.lib.search_user(SESSION, email=author.email) if user: output = "%s %s" % ( avatar(user.default_email, size), flask.url_for('view_user', username=user.username), author.name, ) return output @APP.template_filter('author2avatar') def author_to_avatar(author, size=32): """ Template filter transforming a pygit2 Author object into an avatar. """ user = pagure.lib.search_user(SESSION, email=author.email) output = user.default_email if user else author.email return avatar(output.encode('utf-8'), size) @APP.template_filter('InsertDiv') def insert_div(content): """ Template filter inserting an opening
and closing
after the first title and then at the end of the content. """ # This is quite a hack but simpler solution using .replace() didn't work # for some reasons... content = content.split('\n') output = [] for row in content: if row.startswith('
' in row: row = str(row).replace( '

', '

' '  ' ) output.append(row) output = "\n".join(output) output = output.replace('

', '\n
', 1) output = output.replace('h1', 'h3') return output @APP.template_filter('noJS') def no_js(content, ignore=None): """ Template filter replacing