Coverage for webapp/first_snap/views.py: 90%

116 statements  

« prev     ^ index     » next       coverage.py v7.10.2, created at 2025-08-05 22:06 +0000

1import re 

2from io import StringIO 

3 

4import flask 

5from webapp import helpers 

6from webapp.first_snap import logic 

7 

8YAML_KEY_REGEXP = re.compile(r"([^\s:]*)(:.*)") 

9FSF_FLOW = "first-snap" 

10 

11first_snap = flask.Blueprint( 

12 "first_snap_flow", 

13 __name__, 

14 template_folder="/templates", 

15 static_folder="/static", 

16) 

17 

18 

19def transform_snapcraft_yaml(snapcraft_yaml): 

20 """ 

21 Transforms a snapcraft.yaml dict top-level key 

22 values into renderable HTML. 

23 

24 Keyword arguments: 

25 snapcraft_yaml -- content of a snapcraft.yaml file 

26 """ 

27 for key in snapcraft_yaml: 

28 stream = StringIO() 

29 data = {} 

30 data[key] = snapcraft_yaml[key] 

31 helpers.dump_yaml(data, stream, typ="rt") 

32 stream = stream.getvalue() 

33 

34 # Assuming content starts with yaml key name, wrap it in <b> 

35 # for some code highligthing in HTML 

36 content = re.sub(YAML_KEY_REGEXP, r"<b>\1</b>\2", stream) 

37 snapcraft_yaml[key] = content 

38 

39 return snapcraft_yaml 

40 

41 

42@first_snap.route("/") 

43def get_pick_language(): 

44 return flask.render_template("first-snap/language.html") 

45 

46 

47@first_snap.route("/<language>") 

48def get_language(language): 

49 filename = f"first_snap/content/{language}" 

50 if not helpers.directory_exists(filename): 

51 return flask.abort(404) 

52 

53 context = {"language": language, "fsf_flow": FSF_FLOW} 

54 return flask.render_template( 

55 "first-snap/install-snapcraft.html", **context 

56 ) 

57 

58 

59@first_snap.route("/<language>/snapcraft.yaml") 

60def get_language_snapcraft_yaml(language): 

61 filename = f"first_snap/content/{language}/package.yaml" 

62 snapcraft_yaml_filename = f"first_snap/content/{language}/snapcraft.yaml" 

63 snap_name_cookie = f"fsf_snap_name_{language}" 

64 steps = helpers.get_yaml(filename, typ="rt") 

65 

66 if not steps: 

67 return flask.abort(404) 

68 

69 snap_name = steps["name"] 

70 

71 if snap_name_cookie in flask.request.cookies: 

72 snap_name = flask.request.cookies.get(snap_name_cookie) 

73 

74 snapcraft_yaml = helpers.get_file( 

75 snapcraft_yaml_filename, {"${name}": snap_name} 

76 ) 

77 

78 if not snapcraft_yaml: 

79 return flask.abort(404) 

80 

81 return flask.Response( 

82 snapcraft_yaml, 

83 mimetype="text/yaml", 

84 headers={"Content-Disposition": "attachment;filename=snapcraft.yaml"}, 

85 ) 

86 

87 

88@first_snap.route("/<language>/<operating_system>/package") 

89def get_package(language, operating_system): 

90 if not logic.is_valid_language_and_os( 

91 language=language, os=operating_system 

92 ): 

93 return flask.abort(404) 

94 

95 filename = f"first_snap/content/{language}/package.yaml" 

96 snapcraft_yaml_filename = f"first_snap/content/{language}/snapcraft.yaml" 

97 annotations_filename = "first_snap/content/snapcraft_yaml_annotations.yaml" 

98 

99 snap_name_cookie = f"fsf_snap_name_{language}" 

100 steps = helpers.get_yaml(filename, typ="rt") 

101 

102 if not steps: 

103 return flask.abort(404) 

104 

105 snap_name = steps["name"] 

106 has_user_chosen_name = False 

107 

108 if "publisher" in flask.session: 

109 user_name = flask.session["publisher"]["nickname"] 

110 snap_name = snap_name.replace("{name}", user_name) 

111 

112 if snap_name_cookie in flask.request.cookies: 

113 snap_name = flask.request.cookies.get(snap_name_cookie) 

114 has_user_chosen_name = True 

115 

116 context = { 

117 "language": language, 

118 "os": operating_system, 

119 "steps": steps, 

120 "snap_name": snap_name, 

121 "has_user_chosen_name": has_user_chosen_name, 

122 "fsf_flow": FSF_FLOW, 

123 } 

124 

125 snapcraft_yaml = helpers.get_yaml( 

126 snapcraft_yaml_filename, typ="rt", replaces={"${name}": snap_name} 

127 ) 

128 annotations = helpers.get_yaml(annotations_filename, typ="rt") 

129 

130 if snapcraft_yaml: 

131 context["snapcraft_yaml"] = transform_snapcraft_yaml(snapcraft_yaml) 

132 context["annotations"] = annotations 

133 return flask.render_template("first-snap/package.html", **context) 

134 else: 

135 return flask.abort(404) 

136 

137 

138@first_snap.route("/<language>/<operating_system>/build-and-test") 

139def get_build(language, operating_system): 

140 if not logic.is_valid_language_and_os( 

141 language=language, os=operating_system 

142 ): 

143 return flask.abort(404) 

144 

145 build_filename = f"first_snap/content/{language}/build.yaml" 

146 test_filename = f"first_snap/content/{language}/test.yaml" 

147 snap_name_cookie = f"fsf_snap_name_{language}" 

148 build_steps = helpers.get_yaml(build_filename, typ="rt") 

149 test_steps = helpers.get_yaml(test_filename, typ="rt") 

150 operating_system_parts = operating_system.split("-") 

151 

152 operating_system_only = operating_system_parts[0] 

153 install_type = ( 

154 operating_system_parts[1] 

155 if len(operating_system_parts) == 2 

156 else "auto" 

157 ) 

158 

159 if ( 

160 (not (build_steps and test_steps)) 

161 or ( 

162 (operating_system_only not in build_steps) 

163 and (operating_system_only not in test_steps) 

164 ) 

165 or (install_type not in build_steps[operating_system_only]) 

166 ): 

167 return flask.abort(404) 

168 

169 snap_name = build_steps["name"] 

170 

171 if "publisher" in flask.session: 

172 user_name = flask.session["publisher"]["nickname"] 

173 snap_name = snap_name.replace("{name}", user_name) 

174 

175 if snap_name_cookie in flask.request.cookies: 

176 snap_name = flask.request.cookies.get(snap_name_cookie) 

177 

178 context = { 

179 "language": language, 

180 "os": operating_system, 

181 "build_steps": build_steps[operating_system_only][install_type], 

182 "test_steps": test_steps[operating_system_only], 

183 "snap_name": snap_name, 

184 "fsf_flow": FSF_FLOW, 

185 } 

186 

187 return flask.render_template("first-snap/build-and-test.html", **context) 

188 

189 

190@first_snap.route("/<language>/<operating_system>/push") 

191def get_push(language, operating_system): 

192 return flask.redirect(f"/first-snap/{language}/{operating_system}/upload") 

193 

194 

195@first_snap.route("/<language>/<operating_system>/upload") 

196def get_upload(language, operating_system): 

197 filename = f"first_snap/content/{language}/package.yaml" 

198 snap_name_cookie = f"fsf_snap_name_{language}" 

199 

200 if not logic.is_valid_language_and_os( 

201 language=language, os=operating_system 

202 ): 

203 return flask.abort(404) 

204 

205 data = helpers.get_yaml(filename, typ="rt") 

206 

207 snap_name = data["name"] 

208 has_user_chosen_name = False 

209 

210 if "publisher" in flask.session: 

211 user_name = flask.session["publisher"]["nickname"] 

212 snap_name = snap_name.replace("{name}", user_name) 

213 

214 if snap_name_cookie in flask.request.cookies: 

215 snap_name = flask.request.cookies.get(snap_name_cookie) 

216 has_user_chosen_name = True 

217 

218 flask_user = flask.session.get("publisher", {}) 

219 

220 if "nickname" in flask_user: 

221 user = { 

222 "image": flask_user["image"], 

223 "username": flask_user["nickname"], 

224 "display_name": flask_user["fullname"], 

225 "email": flask_user["email"], 

226 } 

227 else: 

228 user = None 

229 

230 context = { 

231 "language": language, 

232 "os": operating_system, 

233 "user": user, 

234 "snap_name": snap_name, 

235 "has_user_chosen_name": has_user_chosen_name, 

236 "fsf_flow": FSF_FLOW, 

237 } 

238 

239 return flask.render_template("first-snap/upload.html", **context)