Package coprs :: Module filters
[hide private]
[frames] | no frames]

Source Code for Module coprs.filters

  1  import datetime 
  2  from six.moves.urllib.parse import urlparse 
  3  import pytz 
  4  import time 
  5   
  6  import CommonMark 
  7  from pygments import highlight 
  8  from pygments.lexers import get_lexer_by_name, guess_lexer 
  9  from pygments.lexers.special import TextLexer 
 10  from pygments.util import ClassNotFound 
 11  from pygments.formatters import HtmlFormatter 
 12   
 13  import os 
 14  import re 
 15   
 16  from flask import Markup, url_for 
 17   
 18  from coprs import app 
 19  from coprs import helpers 
20 21 -class CoprHtmlRenderer(CommonMark.HtmlRenderer):
22 - def code_block(self, node, entering):
23 info_words = node.info.split() if node.info else [] 24 attrs = self.attrs(node) 25 lexer = None 26 27 if len(info_words) > 0 and len(info_words[0]) > 0: 28 attrs.append(['class', 'language-' + 29 CommonMark.common.escape_xml(info_words[0], True)]) 30 try: 31 lexer = get_lexer_by_name(info_words[0]) 32 except ClassNotFound: 33 pass 34 35 if lexer is None: 36 try: 37 lexer = guess_lexer(node.literal) 38 except ClassNotFound: 39 lexer = TextLexer 40 41 self.cr() 42 self.tag('pre') 43 self.tag('code', attrs) 44 code = highlight(node.literal, lexer, HtmlFormatter()) 45 code = re.sub('<pre>', '', code) 46 code = re.sub('</pre>', '', code) 47 self.lit(code) 48 self.tag('/code') 49 self.tag('/pre') 50 self.cr()
51
52 53 @app.template_filter("remove_anchor") 54 -def remove_anchor(data):
55 if data: 56 data = re.sub("<.*?>", "", data) 57 data = re.sub("</a>", "", data) 58 return data 59 return None
60
61 @app.template_filter("date_from_secs") 62 -def date_from_secs(secs):
63 if secs: 64 return time.strftime("%Y-%m-%d %H:%M:%S %Z", time.gmtime(secs)) 65 66 return None
67
68 69 @app.template_filter("perm_type_from_num") 70 -def perm_type_from_num(num):
71 return helpers.PermissionEnum(num)
72
73 74 @app.template_filter("state_from_num") 75 -def state_from_num(num):
76 if num is None: 77 return "unknown" 78 return helpers.StatusEnum(num)
79
80 81 @app.template_filter("module_state_from_num") 82 -def module_state_from_num(num):
83 if num is None: 84 return "unknown" 85 return helpers.ModuleStatusEnum(num)
86
87 88 @app.template_filter("os_name_short") 89 -def os_name_short(os_name, os_version):
90 # TODO: make it models.MockChroot method or not? 91 if os_version: 92 if os_version == "rawhide": 93 return os_version 94 if os_name == "fedora": 95 return "fc.{0}".format(os_version) 96 elif os_name == "epel": 97 return "el{0}".format(os_version) 98 return os_name
99
100 101 @app.template_filter('localized_time') 102 -def localized_time(time_in, timezone):
103 """ return time shifted into timezone (and printed in ISO format) 104 105 Input is in EPOCH (seconds since epoch). 106 """ 107 if not time_in: 108 return "Not yet" 109 format_tz = "%Y-%m-%d %H:%M %Z" 110 utc_tz = pytz.timezone('UTC') 111 if timezone: 112 user_tz = pytz.timezone(timezone) 113 else: 114 user_tz = utc_tz 115 dt_aware = datetime.datetime.fromtimestamp(time_in).replace(tzinfo=utc_tz) 116 dt_my_tz = dt_aware.astimezone(user_tz) 117 return dt_my_tz.strftime(format_tz)
118
119 120 @app.template_filter('timestamp_diff') 121 -def timestamp_diff(time_in, until=None):
122 """ returns string with difference between two timestamps 123 124 Input is in EPOCH (seconds since epoch). 125 """ 126 if time_in is None: 127 return " - " 128 if until is not None: 129 now = datetime.datetime.fromtimestamp(until) 130 else: 131 now = datetime.datetime.now() 132 diff = now - datetime.datetime.fromtimestamp(time_in) 133 return str(int(diff.total_seconds()))
134
135 136 @app.template_filter('time_ago') 137 -def time_ago(time_in, until=None):
138 """ returns string saying how long ago the time on input was 139 140 Input is in EPOCH (seconds since epoch). 141 """ 142 if time_in is None: 143 return " - " 144 if until is not None: 145 now = datetime.datetime.fromtimestamp(until) 146 else: 147 now = datetime.datetime.now() 148 diff = now - datetime.datetime.fromtimestamp(time_in) 149 secdiff = int(diff.total_seconds()) 150 if secdiff < 120: 151 # less than 2 minutes 152 return "1 minute" 153 elif secdiff < 7200: 154 # less than 2 hours 155 return str(secdiff // 60) + " minutes" 156 elif secdiff < 172800: 157 # less than 2 days 158 return str(secdiff // 3600) + " hours" 159 elif secdiff < 5184000: 160 # less than 2 months 161 return str(secdiff // 86400) + " days" 162 elif secdiff < 63072000: 163 # less than 2 years 164 return str(secdiff // 2592000) + " months" 165 else: 166 # more than 2 years 167 return str(secdiff // 31536000) + " years"
168
169 170 @app.template_filter("markdown") 171 -def markdown_filter(data):
172 if not data: 173 return '' 174 175 parser = CommonMark.Parser() 176 renderer = CoprHtmlRenderer() 177 178 return Markup(renderer.render(parser.parse(data)))
179
180 181 @app.template_filter("pkg_name") 182 -def parse_package_name(pkg):
183 if pkg is not None: 184 return helpers.parse_package_name(os.path.basename(pkg)) 185 return pkg
186
187 188 @app.template_filter("basename") 189 -def parse_basename(pkg):
190 if pkg is not None: 191 return os.path.basename(pkg) 192 return pkg
193
194 195 @app.template_filter("build_state_description") 196 -def build_state_decoration(state):
197 198 description_map = { 199 "failed": "Build failed. See logs for more details.", 200 "succeeded": "Successfully built.", 201 "canceled": "The build has been cancelled manually.", 202 "running": "Build in progress.", 203 "pending": "Your build is waiting for a builder.", 204 "skipped": "This package has already been built previously.", 205 "starting": "Trying to acquire and configure builder for task.", 206 "importing": "Package content is being imported into Dist Git." 207 } 208 209 return description_map.get(state, "")
210
211 212 @app.template_filter("build_source_description") 213 -def build_source_description(state):
214 description_map = { 215 "unset": "No default source", 216 "link": "External link to .spec or SRPM", 217 "upload": "SRPM or .spec file upload", 218 "git_and_tito": "SCM-1 build from a Git repository", 219 "mock_scm": "SCM-2 build from a SCM repository", 220 "pypi": "Build from PyPI", 221 "rubygems": "Build from RubyGems", 222 } 223 224 return description_map.get(state, "")
225
226 227 @app.template_filter("fix_url_https_backend") 228 -def fix_url_https_backend(url):
229 return helpers.fix_protocol_for_backend(url)
230
231 232 @app.template_filter("fix_url_https_frontend") 233 -def fix_url_https_frontend(url):
234 return helpers.fix_protocol_for_frontend(url)
235
236 @app.template_filter("repo_url") 237 -def repo_url(url):
238 """ 239 render copr://<user>/<prj> or copr://g/<group>/<prj> 240 to be rendered as copr projects pages 241 """ 242 parsed = urlparse(url) 243 if parsed.scheme == "copr": 244 owner = parsed.netloc 245 prj = parsed.path.split("/")[1] 246 if owner[0] == '@': 247 url = url_for("coprs_ns.group_copr_detail", group_name=owner[1:], coprname=prj) 248 else: 249 url = url_for("coprs_ns.copr_detail", username=owner, coprname=prj) 250 251 return helpers.fix_protocol_for_frontend(url)
252
253 @app.template_filter("mailto") 254 -def mailto(url):
255 return url if urlparse(url).scheme else "mailto:{}".format(url)
256