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

114 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-28 22:05 +0000

1import os 

2import re 

3from io import StringIO 

4 

5import flask 

6from webapp import helpers 

7 

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

9FSF_FLOW = "first-snap" 

10 

11 

12first_snap = flask.Blueprint( 

13 "fist_snap_flow", 

14 __name__, 

15 template_folder="/templates", 

16 static_folder="/static", 

17) 

18 

19 

20def transform_snapcraft_yaml(snapcraft_yaml): 

21 """ 

22 Transforms a snapcraft.yaml dict top-level key 

23 values into renderable HTML. 

24 

25 Keyword arguments: 

26 snapcraft_yaml -- content of a snapcraft.yaml file 

27 """ 

28 for key in snapcraft_yaml: 

29 stream = StringIO() 

30 data = {} 

31 data[key] = snapcraft_yaml[key] 

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

33 stream = stream.getvalue() 

34 

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

36 # for some code highligthing in HTML 

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

38 snapcraft_yaml[key] = content 

39 

40 return snapcraft_yaml 

41 

42 

43def directory_exists(file): 

44 return os.path.isdir(os.path.join(flask.current_app.root_path, file)) 

45 

46 

47@first_snap.route("/") 

48def get_pick_language(): 

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

50 

51 

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

53def get_language(language): 

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

55 if not directory_exists(filename): 

56 return flask.abort(404) 

57 

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

59 return flask.render_template( 

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

61 ) 

62 

63 

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

65def get_language_snapcraft_yaml(language): 

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

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

68 snap_name_cookie = f"fsf_snap_name_{language}" 

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

70 

71 if not steps: 

72 return flask.abort(404) 

73 

74 snap_name = steps["name"] 

75 

76 if snap_name_cookie in flask.request.cookies: 

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

78 

79 snapcraft_yaml = helpers.get_file( 

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

81 ) 

82 

83 if not snapcraft_yaml: 

84 return flask.abort(404) 

85 

86 return flask.Response( 

87 snapcraft_yaml, 

88 mimetype="text/yaml", 

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

90 ) 

91 

92 

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

94def get_package(language, operating_system): 

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 build_filename = f"first_snap/content/{language}/build.yaml" 

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

142 snap_name_cookie = f"fsf_snap_name_{language}" 

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

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

145 operating_system_parts = operating_system.split("-") 

146 

147 operating_system_only = operating_system_parts[0] 

148 install_type = ( 

149 operating_system_parts[1] 

150 if len(operating_system_parts) == 2 

151 else "auto" 

152 ) 

153 

154 if ( 

155 (not (build_steps and test_steps)) 

156 or ( 

157 (operating_system_only not in build_steps) 

158 and (operating_system_only not in test_steps) 

159 ) 

160 or (install_type not in build_steps[operating_system_only]) 

161 ): 

162 return flask.abort(404) 

163 

164 snap_name = build_steps["name"] 

165 

166 if "publisher" in flask.session: 

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

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

169 

170 if snap_name_cookie in flask.request.cookies: 

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

172 

173 context = { 

174 "language": language, 

175 "os": operating_system, 

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

177 "test_steps": test_steps[operating_system_only], 

178 "snap_name": snap_name, 

179 "fsf_flow": FSF_FLOW, 

180 } 

181 

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

183 

184 

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

186def get_push(language, operating_system): 

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

188 

189 

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

191def get_upload(language, operating_system): 

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

193 snap_name_cookie = f"fsf_snap_name_{language}" 

194 

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

196 

197 if not data: 

198 return flask.abort(404) 

199 

200 snap_name = data["name"] 

201 has_user_chosen_name = False 

202 

203 if "publisher" in flask.session: 

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

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

206 

207 if snap_name_cookie in flask.request.cookies: 

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

209 has_user_chosen_name = True 

210 

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

212 

213 if "nickname" in flask_user: 

214 user = { 

215 "image": flask_user["image"], 

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

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

218 "email": flask_user["email"], 

219 } 

220 else: 

221 user = None 

222 

223 context = { 

224 "language": language, 

225 "os": operating_system, 

226 "user": user, 

227 "snap_name": snap_name, 

228 "has_user_chosen_name": has_user_chosen_name, 

229 "fsf_flow": FSF_FLOW, 

230 } 

231 

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