Improve Deep RL certification Space runtime pins and writeback errors
Browse filesFor an issue observed in this thread: https://huggingface.co/static-proxy/discuss.huggingface.co/t/error-generating-deep-rl-course-certificate/177241
---
## Summary
This PR makes the Deep RL Course Certification Space easier to rebuild and improves the error message around the certificate writeback step.
Changes:
- Pin Python to 3.10 because a fresh build currently uses Python 3.13 and `Pillow == 9.4.0` fails to build there.
- Pin `huggingface_hub<1` as a temporary compatibility fix because the Space imports the legacy `Repository` class.
- Add input validation for empty username / name fields to avoid accidentally scanning all matching public Hub models.
- Replace the generic Gradio failure around the certified-users writeback step with a clearer message and a logged exception.
This PR intentionally does **not** return a certificate when the writeback step fails, because `certified_users.csv` may be intended as the official issuance record. It only makes the failure explicit instead of surfacing a generic `Error`.
## Investigation notes
I duplicated the Space and tested the current code path with the affected username `szymon-hyziak`.
Observed:
- With Python 3.10, `huggingface_hub<1`, and a valid `HF_TOKEN`, the UI starts.
- The app finds the user's models, downloads/parses the model card metadata, and computes `pass_percentage ~= 81.8`, which should qualify for a completion certificate.
- If the certified-users writeback step is bypassed, the certificate image and progress table render correctly.
- In my duplicate, the remaining failure is the final push to `huggingface-projects/Deep-RL-Course-Certification`, which my token understandably cannot write to.
## Maintainer-side follow-up required
This PR cannot update or verify the official Space secret.
Please check:
- whether the official Space `HF_TOKEN` secret is still valid;
- whether the token owner still has write access to `huggingface-projects/Deep-RL-Course-Certification`;
- whether the official Space logs show a failure around `repo.push_to_hub(...)`;
- whether the Space should be restarted/rebuilt after updating the secret.
I cannot prove the official Space fails at exactly the same line because I do not have access to the official Space logs or maintainer token, but the duplicated Space strongly points to the certificate writeback path rather than the user's progress/model metadata.
- README.md +1 -0
- app.py +34 -2
- requirements.txt +2 -1
|
@@ -5,6 +5,7 @@ colorFrom: red
|
|
| 5 |
colorTo: yellow
|
| 6 |
sdk: gradio
|
| 7 |
sdk_version: 5.36.2
|
|
|
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
---
|
|
|
|
| 5 |
colorTo: yellow
|
| 6 |
sdk: gradio
|
| 7 |
sdk_version: 5.36.2
|
| 8 |
+
python_version: "3.10"
|
| 9 |
app_file: app.py
|
| 10 |
pinned: false
|
| 11 |
---
|
|
@@ -7,12 +7,15 @@ from PIL import Image, ImageDraw, ImageFont
|
|
| 7 |
from datetime import date
|
| 8 |
import time
|
| 9 |
|
|
|
|
| 10 |
import os
|
|
|
|
| 11 |
import pandas as pd
|
| 12 |
|
| 13 |
from utils import *
|
| 14 |
|
| 15 |
api = HfApi()
|
|
|
|
| 16 |
|
| 17 |
DATASET_REPO_URL = "https://huggingface.co/datasets/huggingface-projects/Deep-RL-Course-Certification"
|
| 18 |
CERTIFIED_USERS_FILENAME = "certified_users.csv"
|
|
@@ -140,6 +143,15 @@ def check_if_passed(model):
|
|
| 140 |
|
| 141 |
|
| 142 |
def certification(hf_username, first_name, last_name):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
results_certification = [
|
| 144 |
{
|
| 145 |
"unit": "Unit 1",
|
|
@@ -283,6 +295,24 @@ def certification(hf_username, first_name, last_name):
|
|
| 283 |
|
| 284 |
return message, pdf, certificate, df, output_row.update(visible=visible)
|
| 285 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 286 |
"""
|
| 287 |
Verify that the user pass.
|
| 288 |
If yes:
|
|
@@ -312,7 +342,8 @@ def verify_certification(df, hf_username, first_name, last_name):
|
|
| 312 |
certificate, pdf = generate_certificate("./certificate_models/certificate-excellence.png", first_name, last_name)
|
| 313 |
|
| 314 |
# Add this user to our database
|
| 315 |
-
|
|
|
|
| 316 |
|
| 317 |
# Add a message
|
| 318 |
message = """
|
|
@@ -328,7 +359,8 @@ def verify_certification(df, hf_username, first_name, last_name):
|
|
| 328 |
certificate, pdf = generate_certificate("./certificate_models/certificate-completion.png", first_name, last_name)
|
| 329 |
|
| 330 |
# Add this user to our database
|
| 331 |
-
|
|
|
|
| 332 |
|
| 333 |
# Add a message
|
| 334 |
message = """
|
|
|
|
| 7 |
from datetime import date
|
| 8 |
import time
|
| 9 |
|
| 10 |
+
import logging
|
| 11 |
import os
|
| 12 |
+
import requests
|
| 13 |
import pandas as pd
|
| 14 |
|
| 15 |
from utils import *
|
| 16 |
|
| 17 |
api = HfApi()
|
| 18 |
+
logger = logging.getLogger(__name__)
|
| 19 |
|
| 20 |
DATASET_REPO_URL = "https://huggingface.co/datasets/huggingface-projects/Deep-RL-Course-Certification"
|
| 21 |
CERTIFIED_USERS_FILENAME = "certified_users.csv"
|
|
|
|
| 143 |
|
| 144 |
|
| 145 |
def certification(hf_username, first_name, last_name):
|
| 146 |
+
hf_username = (hf_username or "").strip()
|
| 147 |
+
first_name = (first_name or "").strip()
|
| 148 |
+
last_name = (last_name or "").strip()
|
| 149 |
+
|
| 150 |
+
if not hf_username or not first_name or not last_name:
|
| 151 |
+
message = "Please fill in your Hugging Face username, first name, and last name before checking certification."
|
| 152 |
+
certificate = Image.new("RGB", (100, 100), (255, 255, 255))
|
| 153 |
+
return message, "./fail.pdf", certificate, pd.DataFrame(), output_row.update(visible=False)
|
| 154 |
+
|
| 155 |
results_certification = [
|
| 156 |
{
|
| 157 |
"unit": "Unit 1",
|
|
|
|
| 295 |
|
| 296 |
return message, pdf, certificate, df, output_row.update(visible=visible)
|
| 297 |
|
| 298 |
+
def try_add_certified_user(hf_username, first_name, last_name, pass_percentage):
|
| 299 |
+
try:
|
| 300 |
+
add_certified_user(hf_username, first_name, last_name, pass_percentage)
|
| 301 |
+
return True
|
| 302 |
+
except Exception:
|
| 303 |
+
logger.exception("Failed to update certified users dataset")
|
| 304 |
+
return False
|
| 305 |
+
|
| 306 |
+
def writeback_error_response():
|
| 307 |
+
certificate = Image.new("RGB", (100, 100), (255, 255, 255))
|
| 308 |
+
pdf = "./fail.pdf"
|
| 309 |
+
message = """
|
| 310 |
+
Your progress appears to qualify for a certificate, but an internal error occurred while saving your result.
|
| 311 |
+
|
| 312 |
+
Please contact the course maintainers and include your Hugging Face username and a screenshot of this page.
|
| 313 |
+
"""
|
| 314 |
+
return certificate, message, pdf, False
|
| 315 |
+
|
| 316 |
"""
|
| 317 |
Verify that the user pass.
|
| 318 |
If yes:
|
|
|
|
| 342 |
certificate, pdf = generate_certificate("./certificate_models/certificate-excellence.png", first_name, last_name)
|
| 343 |
|
| 344 |
# Add this user to our database
|
| 345 |
+
if not try_add_certified_user(hf_username, first_name, last_name, pass_percentage):
|
| 346 |
+
return writeback_error_response()
|
| 347 |
|
| 348 |
# Add a message
|
| 349 |
message = """
|
|
|
|
| 359 |
certificate, pdf = generate_certificate("./certificate_models/certificate-completion.png", first_name, last_name)
|
| 360 |
|
| 361 |
# Add this user to our database
|
| 362 |
+
if not try_add_certified_user(hf_username, first_name, last_name, pass_percentage):
|
| 363 |
+
return writeback_error_response()
|
| 364 |
|
| 365 |
# Add a message
|
| 366 |
message = """
|
|
@@ -1 +1,2 @@
|
|
| 1 |
-
Pillow == 9.4.0
|
|
|
|
|
|
| 1 |
+
Pillow == 9.4.0
|
| 2 |
+
huggingface_hub<1
|