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