Coverage for webapp / template_utils.py: 97%
67 statements
« prev ^ index » next coverage.py v7.13.1, created at 2025-12-29 22:06 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2025-12-29 22:06 +0000
1# Core
2import hashlib
3import os
4from dateutil import parser
5from emoji import replace_emoji
8# generator functions for templates
9def generate_slug(path):
10 """
11 Generate a slug for each page
12 """
13 if path.endswith(
14 (
15 "/snaps",
16 "/listing",
17 "/releases",
18 "/metrics",
19 "/publicise",
20 "/publicise/badges",
21 "/publicise/cards",
22 "/settings",
23 "/account/details",
24 )
25 ):
26 return "account"
28 if path == "/" or path.startswith("/first-snap"):
29 return "home"
31 if path.startswith("/build"):
32 return "build"
34 if path.startswith("/blog"):
35 return "blog"
37 if path.startswith("/iot"):
38 return "iot"
40 if path.startswith("/docs/snap-tutorials"):
41 return "tutorials"
43 if path.startswith("/docs"):
44 return "docs"
46 return "store"
49# template filters
50def contains(arr, contents):
51 """
52 Template helper for detecting if an array contains an item
53 """
55 return contents in arr
58def join(arr, separator=""):
59 """
60 Template helper for joining array items into a string, using a separator
61 """
63 return separator.join(arr)
66def static_url(filename):
67 """
68 Template function for generating URLs to static assets:
69 Given the path for a static file, output a url path
70 with a hex hash as a query string for versioning
71 """
73 filepath = os.path.join("static", filename)
74 url = "/" + filepath
76 if not os.path.isfile(filepath):
77 # Could not find static file
78 return url
80 # Use MD5 as we care about speed a lot
81 # and not security in this case
82 file_hash = hashlib.md5()
83 with open(filepath, "rb") as file_contents:
84 for chunk in iter(lambda: file_contents.read(4096), b""):
85 file_hash.update(chunk)
87 return url + "?v=" + file_hash.hexdigest()[:7]
90def install_snippet(
91 package_name, default_track, lowest_risk_available, confinement
92):
93 """
94 Template function that returns the snippet value to
95 install a snap to be used in distro pages and/or snap
96 detail pages
97 """
99 snippet_value = "sudo snap install " + package_name
101 if lowest_risk_available != "stable":
102 snippet_value += f" --{lowest_risk_available}"
104 if confinement == "classic":
105 snippet_value += " --classic"
107 return snippet_value
110def format_number(number: int):
111 """
112 Template function that transforms a int into a string
113 with a comma between every thousands
114 """
115 return "{:,}".format(number)
118def format_display_name(display_name):
119 """Template function that formats the displayed name
120 primarily to remove emoji
121 """
122 return replace_emoji(display_name, replace="")
125def display_name(display_name, username):
126 """Template function that returns the displayed name if the username
127 is the same, or the dispayed name and the username if differents
128 """
129 display_name = format_display_name(display_name)
130 if display_name.lower() == username.lower():
131 return display_name
132 else:
133 return f"{display_name} ({username})"
136def format_date(timestamp, format):
137 """Template function that returns a formatted date
138 based on the given timestamp
139 """
140 datestring = parser.parse(timestamp)
142 return datestring.strftime(format)
145def format_member_role(role):
146 """Template function that returns the
147 correct label for a members role
148 """
149 roles = {
150 "admin": "admin",
151 "review": "reviewer",
152 "view": "viewer",
153 "access": "publisher",
154 }
156 return roles[role]
159def format_link(url):
160 """
161 Template function that removes protocol, path and query string from links
162 """
163 url_parts = url.split(":")
165 if url_parts[0] == "mailto":
166 return url_parts[1]
168 if url_parts[0] == "http" or url_parts[0] == "https":
169 url_parts_no_slashes = url_parts[1].split("//")[1]
170 url_parts_no_query = url_parts_no_slashes.split("?")[0]
171 url_parts_no_path = url_parts_no_query.split("/")[0]
173 if url_parts_no_path in [
174 "github.com",
175 "gitlab.com",
176 "bitbucket.org",
177 "launchpad.net",
178 "sourceforge.net",
179 ]:
180 return url_parts_no_query
182 return url_parts_no_path