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
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-05 22:06 +0000
1import re
2from io import StringIO
4import flask
5from webapp import helpers
6from webapp.first_snap import logic
8YAML_KEY_REGEXP = re.compile(r"([^\s:]*)(:.*)")
9FSF_FLOW = "first-snap"
11first_snap = flask.Blueprint(
12 "first_snap_flow",
13 __name__,
14 template_folder="/templates",
15 static_folder="/static",
16)
19def transform_snapcraft_yaml(snapcraft_yaml):
20 """
21 Transforms a snapcraft.yaml dict top-level key
22 values into renderable HTML.
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()
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
39 return snapcraft_yaml
42@first_snap.route("/")
43def get_pick_language():
44 return flask.render_template("first-snap/language.html")
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)
53 context = {"language": language, "fsf_flow": FSF_FLOW}
54 return flask.render_template(
55 "first-snap/install-snapcraft.html", **context
56 )
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")
66 if not steps:
67 return flask.abort(404)
69 snap_name = steps["name"]
71 if snap_name_cookie in flask.request.cookies:
72 snap_name = flask.request.cookies.get(snap_name_cookie)
74 snapcraft_yaml = helpers.get_file(
75 snapcraft_yaml_filename, {"${name}": snap_name}
76 )
78 if not snapcraft_yaml:
79 return flask.abort(404)
81 return flask.Response(
82 snapcraft_yaml,
83 mimetype="text/yaml",
84 headers={"Content-Disposition": "attachment;filename=snapcraft.yaml"},
85 )
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)
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"
99 snap_name_cookie = f"fsf_snap_name_{language}"
100 steps = helpers.get_yaml(filename, typ="rt")
102 if not steps:
103 return flask.abort(404)
105 snap_name = steps["name"]
106 has_user_chosen_name = False
108 if "publisher" in flask.session:
109 user_name = flask.session["publisher"]["nickname"]
110 snap_name = snap_name.replace("{name}", user_name)
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
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 }
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")
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)
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)
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("-")
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 )
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)
169 snap_name = build_steps["name"]
171 if "publisher" in flask.session:
172 user_name = flask.session["publisher"]["nickname"]
173 snap_name = snap_name.replace("{name}", user_name)
175 if snap_name_cookie in flask.request.cookies:
176 snap_name = flask.request.cookies.get(snap_name_cookie)
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 }
187 return flask.render_template("first-snap/build-and-test.html", **context)
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")
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}"
200 if not logic.is_valid_language_and_os(
201 language=language, os=operating_system
202 ):
203 return flask.abort(404)
205 data = helpers.get_yaml(filename, typ="rt")
207 snap_name = data["name"]
208 has_user_chosen_name = False
210 if "publisher" in flask.session:
211 user_name = flask.session["publisher"]["nickname"]
212 snap_name = snap_name.replace("{name}", user_name)
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
218 flask_user = flask.session.get("publisher", {})
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
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 }
239 return flask.render_template("first-snap/upload.html", **context)