Abhishek Thakur commited on
Commit
42c2745
·
1 Parent(s): c2fd2d2

further improvements

Browse files
competitions/app.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import os
2
  import threading
3
 
@@ -6,9 +7,11 @@ from fastapi import FastAPI, File, Form, Request, UploadFile
6
  from fastapi.responses import HTMLResponse, JSONResponse
7
  from fastapi.staticfiles import StaticFiles
8
  from fastapi.templating import Jinja2Templates
 
9
  from loguru import logger
10
  from pydantic import BaseModel
11
 
 
12
  from competitions.info import CompetitionInfo
13
  from competitions.leaderboard import Leaderboard
14
  from competitions.runner import JobRunner
@@ -20,6 +23,9 @@ HF_TOKEN = os.environ.get("HF_TOKEN", None)
20
  BASE_DIR = os.path.dirname(os.path.abspath(__file__))
21
  COMPETITION_ID = os.getenv("COMPETITION_ID")
22
  OUTPUT_PATH = os.getenv("OUTPUT_PATH", "/tmp/model")
 
 
 
23
  COMP_INFO = CompetitionInfo(competition_id=COMPETITION_ID, autotrain_token=HF_TOKEN)
24
 
25
 
@@ -91,8 +97,12 @@ async def get_leaderboard(request: Request, lb: str):
91
  eval_higher_is_better=COMP_INFO.eval_higher_is_better,
92
  max_selected_submissions=COMP_INFO.selection_limit,
93
  competition_id=COMPETITION_ID,
94
- autotrain_token=HF_TOKEN,
95
  )
 
 
 
 
96
  df = leaderboard.fetch(private=lb == "private")
97
  logger.info(df)
98
  resp = {"response": df.to_markdown(index=False)}
@@ -108,7 +118,15 @@ async def my_submissions(request: Request, user: User):
108
  token=HF_TOKEN,
109
  competition_type=COMP_INFO.competition_type,
110
  )
111
- success_subs, failed_subs = sub.my_submissions(user.user_token)
 
 
 
 
 
 
 
 
112
  subs = pd.concat([success_subs, failed_subs], axis=0)
113
  subs = subs.to_markdown(index=False)
114
  if len(subs.strip()) == 0:
@@ -140,10 +158,13 @@ async def new_submission(
140
  token=HF_TOKEN,
141
  competition_type=COMP_INFO.competition_type,
142
  )
143
- if COMP_INFO.competition_type == "generic":
144
- resp = sub.new_submission(token, submission_file, submission_comment)
145
- return {"response": f"Success! You have {resp} submissions remaining today."}
146
- elif COMP_INFO.competition_type == "code":
147
- resp = sub.new_submission(token, hub_model, submission_comment)
148
- return {"response": f"Success! You have {resp} submissions remaining today."}
 
 
 
149
  return {"response": "Invalid competition type"}
 
1
+ import datetime
2
  import os
3
  import threading
4
 
 
7
  from fastapi.responses import HTMLResponse, JSONResponse
8
  from fastapi.staticfiles import StaticFiles
9
  from fastapi.templating import Jinja2Templates
10
+ from huggingface_hub.utils import disable_progress_bars
11
  from loguru import logger
12
  from pydantic import BaseModel
13
 
14
+ from competitions.errors import AuthenticationError
15
  from competitions.info import CompetitionInfo
16
  from competitions.leaderboard import Leaderboard
17
  from competitions.runner import JobRunner
 
23
  BASE_DIR = os.path.dirname(os.path.abspath(__file__))
24
  COMPETITION_ID = os.getenv("COMPETITION_ID")
25
  OUTPUT_PATH = os.getenv("OUTPUT_PATH", "/tmp/model")
26
+
27
+ disable_progress_bars()
28
+
29
  COMP_INFO = CompetitionInfo(competition_id=COMPETITION_ID, autotrain_token=HF_TOKEN)
30
 
31
 
 
97
  eval_higher_is_better=COMP_INFO.eval_higher_is_better,
98
  max_selected_submissions=COMP_INFO.selection_limit,
99
  competition_id=COMPETITION_ID,
100
+ token=HF_TOKEN,
101
  )
102
+ if lb == "private":
103
+ current_utc_time = datetime.datetime.utcnow()
104
+ if current_utc_time < COMP_INFO.end_date:
105
+ return {"response": "Private leaderboard will be available after the competition ends."}
106
  df = leaderboard.fetch(private=lb == "private")
107
  logger.info(df)
108
  resp = {"response": df.to_markdown(index=False)}
 
118
  token=HF_TOKEN,
119
  competition_type=COMP_INFO.competition_type,
120
  )
121
+ try:
122
+ success_subs, failed_subs = sub.my_submissions(user.user_token)
123
+ except AuthenticationError:
124
+ return {
125
+ "response": {
126
+ "submissions": "**Invalid token**",
127
+ "submission_text": SUBMISSION_TEXT.format(COMP_INFO.submission_limit),
128
+ }
129
+ }
130
  subs = pd.concat([success_subs, failed_subs], axis=0)
131
  subs = subs.to_markdown(index=False)
132
  if len(subs.strip()) == 0:
 
158
  token=HF_TOKEN,
159
  competition_type=COMP_INFO.competition_type,
160
  )
161
+ try:
162
+ if COMP_INFO.competition_type == "generic":
163
+ resp = sub.new_submission(token, submission_file, submission_comment)
164
+ return {"response": f"Success! You have {resp} submissions remaining today."}
165
+ elif COMP_INFO.competition_type == "code":
166
+ resp = sub.new_submission(token, hub_model, submission_comment)
167
+ return {"response": f"Success! You have {resp} submissions remaining today."}
168
+ except AuthenticationError:
169
+ return {"response": "Invalid token"}
170
  return {"response": "Invalid competition type"}
competitions/evaluate.py CHANGED
@@ -75,7 +75,6 @@ def generate_submission_file(params):
75
  @utils.monitor
76
  def run(params):
77
  logger.info(params)
78
- logger.info(f"User token: {os.environ.get('USER_TOKEN')}")
79
  if isinstance(params, dict):
80
  params = EvalParams(**params)
81
 
 
75
  @utils.monitor
76
  def run(params):
77
  logger.info(params)
 
78
  if isinstance(params, dict):
79
  params = EvalParams(**params)
80
 
competitions/leaderboard.py CHANGED
@@ -6,10 +6,9 @@ from dataclasses import dataclass
6
  from datetime import datetime
7
 
8
  import pandas as pd
 
9
  from loguru import logger
10
 
11
- from .download import snapshot_download
12
-
13
 
14
  @dataclass
15
  class Leaderboard:
@@ -17,7 +16,7 @@ class Leaderboard:
17
  eval_higher_is_better: bool
18
  max_selected_submissions: int
19
  competition_id: str
20
- autotrain_token: str
21
 
22
  def __post_init__(self):
23
  self._refresh_columns()
@@ -42,7 +41,7 @@ class Leaderboard:
42
  submissions_folder = snapshot_download(
43
  repo_id=self.competition_id,
44
  allow_patterns="submission_info/*.json",
45
- use_auth_token=self.autotrain_token,
46
  repo_type="dataset",
47
  )
48
  logger.info(f"Downloaded submissions in {time.time() - start_time} seconds")
@@ -77,10 +76,7 @@ class Leaderboard:
77
  _sub[f"public_score_{skey}"] = _sub["public_score"][skey]
78
  _sub["public_score"] = _sub["public_score"][score_key]
79
 
80
- submission_info["submissions"].sort(
81
- key=lambda x: x["public_score"],
82
- reverse=True if self.eval_higher_is_better else False,
83
- )
84
  # select only the best submission
85
  submission_info["submissions"] = submission_info["submissions"][0]
86
  temp_info = {
@@ -105,7 +101,7 @@ class Leaderboard:
105
  submissions_folder = snapshot_download(
106
  repo_id=self.competition_id,
107
  allow_patterns="submission_info/*.json",
108
- use_auth_token=self.autotrain_token,
109
  repo_type="dataset",
110
  )
111
  logger.info(f"Downloaded submissions in {time.time() - start_time} seconds")
@@ -253,4 +249,17 @@ class Leaderboard:
253
  # send submission_datetime to the end
254
  columns.remove("submission_datetime")
255
  columns.append("submission_datetime")
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  return df[columns]
 
6
  from datetime import datetime
7
 
8
  import pandas as pd
9
+ from huggingface_hub import hf_hub_download, snapshot_download
10
  from loguru import logger
11
 
 
 
12
 
13
  @dataclass
14
  class Leaderboard:
 
16
  eval_higher_is_better: bool
17
  max_selected_submissions: int
18
  competition_id: str
19
+ token: str
20
 
21
  def __post_init__(self):
22
  self._refresh_columns()
 
41
  submissions_folder = snapshot_download(
42
  repo_id=self.competition_id,
43
  allow_patterns="submission_info/*.json",
44
+ use_auth_token=self.token,
45
  repo_type="dataset",
46
  )
47
  logger.info(f"Downloaded submissions in {time.time() - start_time} seconds")
 
76
  _sub[f"public_score_{skey}"] = _sub["public_score"][skey]
77
  _sub["public_score"] = _sub["public_score"][score_key]
78
 
79
+ submission_info["submissions"].sort(key=lambda x: x["public_score"], reverse=self.eval_higher_is_better)
 
 
 
80
  # select only the best submission
81
  submission_info["submissions"] = submission_info["submissions"][0]
82
  temp_info = {
 
101
  submissions_folder = snapshot_download(
102
  repo_id=self.competition_id,
103
  allow_patterns="submission_info/*.json",
104
+ use_auth_token=self.token,
105
  repo_type="dataset",
106
  )
107
  logger.info(f"Downloaded submissions in {time.time() - start_time} seconds")
 
249
  # send submission_datetime to the end
250
  columns.remove("submission_datetime")
251
  columns.append("submission_datetime")
252
+
253
+ team_metadata = hf_hub_download(
254
+ repo_id=self.competition_id,
255
+ filename="teams.json",
256
+ token=self.token,
257
+ repo_type="dataset",
258
+ )
259
+
260
+ with open(team_metadata, "r", encoding="utf-8") as f:
261
+ team_metadata = json.load(f)
262
+
263
+ df["id"] = df["id"].apply(lambda x: team_metadata[x]["name"])
264
+
265
  return df[columns]
competitions/runner.py CHANGED
@@ -87,6 +87,7 @@ class JobRunner:
87
  "submission_rows": self.submission_rows,
88
  "output_path": self.output_path,
89
  "submission_repo": row["submission_repo"],
 
90
  }
91
  eval_params = json.dumps(eval_params)
92
  eval_pid = run_evaluation(eval_params, local=True, wait=True)
 
87
  "submission_rows": self.submission_rows,
88
  "output_path": self.output_path,
89
  "submission_repo": row["submission_repo"],
90
+ "time_limit": self.time_limit,
91
  }
92
  eval_params = json.dumps(eval_params)
93
  eval_pid = run_evaluation(eval_params, local=True, wait=True)
competitions/submissions.py CHANGED
@@ -82,7 +82,7 @@ class Submissions:
82
  with open(team_fname, "r", encoding="utf-8") as f:
83
  team_submission_info = json.load(f)
84
 
85
- todays_date = datetime.now().strftime("%Y-%m-%d")
86
  if len(team_submission_info["submissions"]) == 0:
87
  team_submission_info["submissions"] = []
88
 
@@ -120,7 +120,7 @@ class Submissions:
120
  with open(team_fname, "r", encoding="utf-8") as f:
121
  team_submission_info = json.load(f)
122
 
123
- todays_date = datetime.now().strftime("%Y-%m-%d")
124
  if len(team_submission_info["submissions"]) == 0:
125
  team_submission_info["submissions"] = []
126
 
@@ -155,7 +155,7 @@ class Submissions:
155
  )
156
  with open(team_fname, "r", encoding="utf-8") as f:
157
  team_submission_info = json.load(f)
158
- datetime_now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
159
 
160
  # here goes all the default stuff for submission
161
  team_submission_info["submissions"].append(
@@ -175,7 +175,7 @@ class Submissions:
175
  )
176
  # count the number of times user has submitted today
177
  todays_submissions = 0
178
- todays_date = datetime.now().strftime("%Y-%m-%d")
179
  for sub in team_submission_info["submissions"]:
180
  submission_datetime = sub["datetime"]
181
  submission_date = submission_datetime.split(" ")[0]
@@ -206,13 +206,12 @@ class Submissions:
206
  return team_submission_info["submissions"]
207
 
208
  def update_selected_submissions(self, user_token, selected_submission_ids):
209
- current_datetime = datetime.now()
210
  if current_datetime > self.end_date:
211
  raise PastDeadlineError("Competition has ended.")
212
 
213
  user_info = self._get_user_info(user_token)
214
- user_id = user_info["id"]
215
- team_id = self._get_team_id(user_id)
216
 
217
  team_fname = hf_hub_download(
218
  repo_id=self.competition_id,
@@ -326,15 +325,17 @@ class Submissions:
326
 
327
  def my_submissions(self, user_token):
328
  user_info = self._get_user_info(user_token)
329
- current_date_time = datetime.now()
330
  private = False
331
  if current_date_time >= self.end_date:
332
  private = True
333
- team_id = self._get_team_id(user_info["id"])
334
  success_subs, failed_subs = self._get_team_subs(team_id, private=private)
335
  return success_subs, failed_subs
336
 
337
- def _get_team_id(self, user_id):
 
 
338
  user_team = hf_hub_download(
339
  repo_id=self.competition_id,
340
  filename="user_team.json",
@@ -347,12 +348,35 @@ class Submissions:
347
  if user_id in user_team:
348
  return user_team[user_id]
349
 
 
 
 
 
 
 
 
 
 
 
350
  # create a new team, if user is not in any team
351
  team_id = str(uuid.uuid4())
352
  user_team[user_id] = team_id
 
 
 
 
 
 
 
 
353
  user_team_json = json.dumps(user_team, indent=4)
354
  user_team_json_bytes = user_team_json.encode("utf-8")
355
  user_team_json_buffer = io.BytesIO(user_team_json_bytes)
 
 
 
 
 
356
  api = HfApi(token=self.token)
357
  api.upload_file(
358
  path_or_fileobj=user_team_json_buffer,
@@ -360,6 +384,13 @@ class Submissions:
360
  repo_id=self.competition_id,
361
  repo_type="dataset",
362
  )
 
 
 
 
 
 
 
363
  return team_id
364
 
365
  def new_submission(self, user_token, uploaded_file, submission_comment):
@@ -367,7 +398,7 @@ class Submissions:
367
  user_info = self._get_user_info(user_token)
368
  submission_id = str(uuid.uuid4())
369
  user_id = user_info["id"]
370
- team_id = self._get_team_id(user_id)
371
 
372
  # check if team can submit to the competition
373
  if self._check_team_submission_limit(team_id) is False:
 
82
  with open(team_fname, "r", encoding="utf-8") as f:
83
  team_submission_info = json.load(f)
84
 
85
+ todays_date = datetime.utcnow().strftime("%Y-%m-%d")
86
  if len(team_submission_info["submissions"]) == 0:
87
  team_submission_info["submissions"] = []
88
 
 
120
  with open(team_fname, "r", encoding="utf-8") as f:
121
  team_submission_info = json.load(f)
122
 
123
+ todays_date = datetime.utcnow().strftime("%Y-%m-%d")
124
  if len(team_submission_info["submissions"]) == 0:
125
  team_submission_info["submissions"] = []
126
 
 
155
  )
156
  with open(team_fname, "r", encoding="utf-8") as f:
157
  team_submission_info = json.load(f)
158
+ datetime_now = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
159
 
160
  # here goes all the default stuff for submission
161
  team_submission_info["submissions"].append(
 
175
  )
176
  # count the number of times user has submitted today
177
  todays_submissions = 0
178
+ todays_date = datetime.utcnow().strftime("%Y-%m-%d")
179
  for sub in team_submission_info["submissions"]:
180
  submission_datetime = sub["datetime"]
181
  submission_date = submission_datetime.split(" ")[0]
 
206
  return team_submission_info["submissions"]
207
 
208
  def update_selected_submissions(self, user_token, selected_submission_ids):
209
+ current_datetime = datetime.utcnow()
210
  if current_datetime > self.end_date:
211
  raise PastDeadlineError("Competition has ended.")
212
 
213
  user_info = self._get_user_info(user_token)
214
+ team_id = self._get_team_id(user_info)
 
215
 
216
  team_fname = hf_hub_download(
217
  repo_id=self.competition_id,
 
325
 
326
  def my_submissions(self, user_token):
327
  user_info = self._get_user_info(user_token)
328
+ current_date_time = datetime.utcnow()
329
  private = False
330
  if current_date_time >= self.end_date:
331
  private = True
332
+ team_id = self._get_team_id(user_info)
333
  success_subs, failed_subs = self._get_team_subs(team_id, private=private)
334
  return success_subs, failed_subs
335
 
336
+ def _get_team_id(self, user_info):
337
+ user_id = user_info["id"]
338
+ user_name = user_info["name"]
339
  user_team = hf_hub_download(
340
  repo_id=self.competition_id,
341
  filename="user_team.json",
 
348
  if user_id in user_team:
349
  return user_team[user_id]
350
 
351
+ team_metadata = hf_hub_download(
352
+ repo_id=self.competition_id,
353
+ filename="teams.json",
354
+ token=self.token,
355
+ repo_type="dataset",
356
+ )
357
+
358
+ with open(team_metadata, "r", encoding="utf-8") as f:
359
+ team_metadata = json.load(f)
360
+
361
  # create a new team, if user is not in any team
362
  team_id = str(uuid.uuid4())
363
  user_team[user_id] = team_id
364
+
365
+ team_metadata[team_id] = {
366
+ "id": team_id,
367
+ "name": user_name,
368
+ "members": [user_id],
369
+ "leader": user_id,
370
+ }
371
+
372
  user_team_json = json.dumps(user_team, indent=4)
373
  user_team_json_bytes = user_team_json.encode("utf-8")
374
  user_team_json_buffer = io.BytesIO(user_team_json_bytes)
375
+
376
+ team_metadata_json = json.dumps(team_metadata, indent=4)
377
+ team_metadata_json_bytes = team_metadata_json.encode("utf-8")
378
+ team_metadata_json_buffer = io.BytesIO(team_metadata_json_bytes)
379
+
380
  api = HfApi(token=self.token)
381
  api.upload_file(
382
  path_or_fileobj=user_team_json_buffer,
 
384
  repo_id=self.competition_id,
385
  repo_type="dataset",
386
  )
387
+ api.upload_file(
388
+ path_or_fileobj=team_metadata_json_buffer,
389
+ path_in_repo="teams.json",
390
+ repo_id=self.competition_id,
391
+ repo_type="dataset",
392
+ )
393
+
394
  return team_id
395
 
396
  def new_submission(self, user_token, uploaded_file, submission_comment):
 
398
  user_info = self._get_user_info(user_token)
399
  submission_id = str(uuid.uuid4())
400
  user_id = user_info["id"]
401
+ team_id = self._get_team_id(user_info)
402
 
403
  # check if team can submit to the competition
404
  if self._check_team_submission_limit(team_id) is False:
competitions/templates/index.html CHANGED
@@ -23,6 +23,8 @@
23
  }
24
 
25
  function fetchAndDisplayCompetitionInfo() {
 
 
26
  fetch('/competition_info')
27
  .then(response => {
28
  if (!response.ok) {
@@ -35,13 +37,17 @@
35
  const contentDiv = document.getElementById('content');
36
  contentDiv.style.display = 'block';
37
  contentDiv.innerHTML = marked.parse(data.response);
 
38
  })
39
  .catch(error => {
40
  console.error('There has been a problem with your fetch operation:', error);
 
41
  });
42
  }
43
 
44
  function fetchAndDisplayDatasetInfo() {
 
 
45
  fetch('/dataset_info')
46
  .then(response => {
47
  if (!response.ok) {
@@ -53,13 +59,17 @@
53
  // Populate the 'content' div with the HTML from the response
54
  const contentDiv = document.getElementById('content');
55
  contentDiv.innerHTML = marked.parse(data.response);
 
56
  })
57
  .catch(error => {
58
  console.error('There has been a problem with your fetch operation:', error);
 
59
  });
60
  }
61
 
62
  function fetchAndDisplayPublicLeaderboard() {
 
 
63
  fetch('/leaderboard/public')
64
  .then(response => {
65
  if (!response.ok) {
@@ -71,13 +81,17 @@
71
  // Populate the 'content' div with the HTML from the response
72
  const contentDiv = document.getElementById('content');
73
  contentDiv.innerHTML = marked.parse(data.response);
 
74
  })
75
  .catch(error => {
76
  console.error('There has been a problem with your fetch operation:', error);
 
77
  });
78
  }
79
 
80
  function fetchAndDisplayPrivateLeaderboard() {
 
 
81
  fetch('/leaderboard/private')
82
  .then(response => {
83
  if (!response.ok) {
@@ -89,14 +103,18 @@
89
  // Populate the 'content' div with the HTML from the response
90
  const contentDiv = document.getElementById('content');
91
  contentDiv.innerHTML = marked.parse(data.response);
 
92
  })
93
  .catch(error => {
94
  console.error('There has been a problem with your fetch operation:', error);
 
95
  });
96
  }
97
  function fetchAndDisplaySubmissions() {
98
  const userToken = document.getElementById('user_token').value;
99
  const apiEndpoint = '/my_submissions';
 
 
100
 
101
  const requestOptions = {
102
  method: 'POST',
@@ -116,13 +134,17 @@
116
  .then(data => {
117
  const contentDiv = document.getElementById('content');
118
  contentDiv.innerHTML = marked.parse(data.response.submission_text) + marked.parse(data.response.submissions);
 
119
  })
120
  .catch(error => {
121
  console.error('There was a problem with the fetch operation:', error);
 
122
  });
123
  }
124
 
125
  function fetchAndDisplaySubmissionInfo() {
 
 
126
  fetch('/submission_info')
127
  .then(response => {
128
  if (!response.ok) {
@@ -134,9 +156,11 @@
134
  // Populate the 'content' div with the HTML from the response
135
  const contentDiv = document.getElementById('content');
136
  contentDiv.innerHTML = marked.parse(data.response);
 
137
  })
138
  .catch(error => {
139
  console.error('There has been a problem with your fetch operation:', error);
 
140
  });
141
  }
142
 
@@ -194,17 +218,17 @@
194
  </script>
195
  </head>
196
 
197
- <body class="flex h-screen bg-gray-100">
198
  <!-- Sidebar -->
199
  <aside id="sidebar-multi-level-sidebar"
200
  class="fixed top-0 left-0 z-40 w-64 h-screen transition-transform -translate-x-full sm:translate-x-0"
201
  aria-label="Sidebar">
202
- <div class="h-full px-3 py-4 overflow-y-auto bg-gray-50 dark:bg-gray-800">
203
  <ul class="space-y-2 font-medium">
204
  <li>
205
  <a href="#" id="home"
206
- class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group">
207
- <svg class="w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
208
  viewBox="0 0 22 21" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
209
  <path d="M1,10 L11,1 L21,10 L21,20 L1,20 Z" /> <!-- House structure -->
210
  <path d="M6,20 L6,14 L16,14 L16,20" /> <!-- Door -->
@@ -215,8 +239,8 @@
215
  </li>
216
  <li>
217
  <a href="#" id="dataset"
218
- class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group">
219
- <svg class="flex-shrink-0 w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
220
  aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
221
  viewBox="0 0 18 18">
222
  <path
@@ -227,9 +251,9 @@
227
  </li>
228
  <li>
229
  <button type="button"
230
- class="flex items-center w-full p-2 text-base text-gray-900 transition duration-75 rounded-lg group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
231
  aria-controls="lb-dropdown" data-collapse-toggle="lb-dropdown">
232
- <svg class="flex-shrink-0 w-5 h-5 text-gray-500 transition duration-75 group-hover:text-gray-900 dark:text-gray-400 dark:group-hover:text-white"
233
  aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
234
  viewBox="0 0 18 21">
235
  <path d="M2,4 L20,4 L20,16 L2,16 Z" />
@@ -242,22 +266,22 @@
242
  d="m1 1 4 4 4-4" />
243
  </svg>
244
  </button>
245
- <ul id="lb-dropdown" class="hidden py-2 space-y-2">
246
  <li>
247
  <a href="#" id="public_lb"
248
- class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">Public</a>
249
  </li>
250
  <li>
251
  <a href="#" id="private_lb"
252
- class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">Private</a>
253
  </li>
254
  </ul>
255
  </li>
256
  <li>
257
  <button type="button"
258
- class="flex items-center w-full p-2 text-base text-gray-900 transition duration-75 rounded-lg group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
259
  aria-controls="submissions-dropdown" data-collapse-toggle="submissions-dropdown">
260
- <svg class="flex-shrink-0 w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
261
  aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
262
  viewBox="0 0 20 20">
263
  <path d="M5 5V.13a2.96 2.96 0 0 0-1.293.749L.879 3.707A2.96 2.96 0 0 0 .13 5H5Z" />
@@ -273,28 +297,28 @@
273
  d="m1 1 4 4 4-4" />
274
  </svg>
275
  </button>
276
- <ul id="submissions-dropdown" class="hidden py-2 space-y-2">
277
  <li>
278
  <a href="#" id="submission_info"
279
- class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">Submission
280
  information</a>
281
  </li>
282
  <li>
283
  <a href="#" id="my_submissions"
284
- class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">My
285
  submissions</a>
286
  </li>
287
  <li>
288
  <a href="#" id="new_submission"
289
- class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">New
290
  submission</a>
291
  </li>
292
  </ul>
293
  </li>
294
- <li>
295
  <a href="#"
296
- class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group">
297
- <svg class="flex-shrink-0 w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
298
  aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
299
  viewBox="0 0 20 18">
300
  <path
@@ -302,20 +326,34 @@
302
  </svg>
303
  <span class="flex-1 ms-3 whitespace-nowrap">Team</span>
304
  </a>
305
- </li>
306
  <li>
307
- <label for="user_token" class="text-xs font-medium text-white">Hugging Face Token (read-only)
308
  </label>
309
  <input type="password" name="user_token" id="user_token"
310
  class="mt-1 block w-full border border-gray-300 px-3 py-1.5 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
311
  </li>
312
  </ul>
 
 
 
 
 
 
 
 
313
  </div>
314
  </aside>
315
  <div class="p-1 sm:ml-64">
316
- <img src={{logo}} alt="Competition logo" class="mx-auto">
317
  <hr class="mt-3 mb-2">
318
- <article class="prose max-w-5xl" id="content">
 
 
 
 
 
 
319
  </article>
320
  </div>
321
  <div id="submission-modal" tabindex="-1"
@@ -330,8 +368,7 @@
330
  <form action="#" method="post" class="gap-2" enctype="multipart/form-data">
331
  {% if competition_type == 'generic' %}
332
  <div class="form-group">
333
- <label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
334
- for="submission_file">Upload
335
  file</label>
336
  <input
337
  class="block w-full text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 focus:outline-none "
 
23
  }
24
 
25
  function fetchAndDisplayCompetitionInfo() {
26
+ const articleLoadingSpinner = document.getElementById('articleLoadingSpinner');
27
+ articleLoadingSpinner.classList.remove('hidden');
28
  fetch('/competition_info')
29
  .then(response => {
30
  if (!response.ok) {
 
37
  const contentDiv = document.getElementById('content');
38
  contentDiv.style.display = 'block';
39
  contentDiv.innerHTML = marked.parse(data.response);
40
+ articleLoadingSpinner.classList.add('hidden');
41
  })
42
  .catch(error => {
43
  console.error('There has been a problem with your fetch operation:', error);
44
+ articleLoadingSpinner.classList.add('hidden');
45
  });
46
  }
47
 
48
  function fetchAndDisplayDatasetInfo() {
49
+ const articleLoadingSpinner = document.getElementById('articleLoadingSpinner');
50
+ articleLoadingSpinner.classList.remove('hidden');
51
  fetch('/dataset_info')
52
  .then(response => {
53
  if (!response.ok) {
 
59
  // Populate the 'content' div with the HTML from the response
60
  const contentDiv = document.getElementById('content');
61
  contentDiv.innerHTML = marked.parse(data.response);
62
+ articleLoadingSpinner.classList.add('hidden');
63
  })
64
  .catch(error => {
65
  console.error('There has been a problem with your fetch operation:', error);
66
+ articleLoadingSpinner.classList.add('hidden');
67
  });
68
  }
69
 
70
  function fetchAndDisplayPublicLeaderboard() {
71
+ const articleLoadingSpinner = document.getElementById('articleLoadingSpinner');
72
+ articleLoadingSpinner.classList.remove('hidden');
73
  fetch('/leaderboard/public')
74
  .then(response => {
75
  if (!response.ok) {
 
81
  // Populate the 'content' div with the HTML from the response
82
  const contentDiv = document.getElementById('content');
83
  contentDiv.innerHTML = marked.parse(data.response);
84
+ articleLoadingSpinner.classList.add('hidden');
85
  })
86
  .catch(error => {
87
  console.error('There has been a problem with your fetch operation:', error);
88
+ articleLoadingSpinner.classList.add('hidden');
89
  });
90
  }
91
 
92
  function fetchAndDisplayPrivateLeaderboard() {
93
+ const articleLoadingSpinner = document.getElementById('articleLoadingSpinner');
94
+ articleLoadingSpinner.classList.remove('hidden');
95
  fetch('/leaderboard/private')
96
  .then(response => {
97
  if (!response.ok) {
 
103
  // Populate the 'content' div with the HTML from the response
104
  const contentDiv = document.getElementById('content');
105
  contentDiv.innerHTML = marked.parse(data.response);
106
+ articleLoadingSpinner.classList.add('hidden');
107
  })
108
  .catch(error => {
109
  console.error('There has been a problem with your fetch operation:', error);
110
+ articleLoadingSpinner.classList.add('hidden');
111
  });
112
  }
113
  function fetchAndDisplaySubmissions() {
114
  const userToken = document.getElementById('user_token').value;
115
  const apiEndpoint = '/my_submissions';
116
+ const articleLoadingSpinner = document.getElementById('articleLoadingSpinner');
117
+ articleLoadingSpinner.classList.remove('hidden');
118
 
119
  const requestOptions = {
120
  method: 'POST',
 
134
  .then(data => {
135
  const contentDiv = document.getElementById('content');
136
  contentDiv.innerHTML = marked.parse(data.response.submission_text) + marked.parse(data.response.submissions);
137
+ articleLoadingSpinner.classList.add('hidden');
138
  })
139
  .catch(error => {
140
  console.error('There was a problem with the fetch operation:', error);
141
+ articleLoadingSpinner.classList.add('hidden');
142
  });
143
  }
144
 
145
  function fetchAndDisplaySubmissionInfo() {
146
+ const articleLoadingSpinner = document.getElementById('articleLoadingSpinner');
147
+ articleLoadingSpinner.classList.remove('hidden');
148
  fetch('/submission_info')
149
  .then(response => {
150
  if (!response.ok) {
 
156
  // Populate the 'content' div with the HTML from the response
157
  const contentDiv = document.getElementById('content');
158
  contentDiv.innerHTML = marked.parse(data.response);
159
+ articleLoadingSpinner.classList.add('hidden');
160
  })
161
  .catch(error => {
162
  console.error('There has been a problem with your fetch operation:', error);
163
+ articleLoadingSpinner.classList.add('hidden');
164
  });
165
  }
166
 
 
218
  </script>
219
  </head>
220
 
221
+ <body class="flex h-screen">
222
  <!-- Sidebar -->
223
  <aside id="sidebar-multi-level-sidebar"
224
  class="fixed top-0 left-0 z-40 w-64 h-screen transition-transform -translate-x-full sm:translate-x-0"
225
  aria-label="Sidebar">
226
+ <div class="h-full px-3 py-4 overflow-y-auto">
227
  <ul class="space-y-2 font-medium">
228
  <li>
229
  <a href="#" id="home"
230
+ class="flex items-center p-2 text-gray-900 rounded-lg hover:bg-gray-100 group">
231
+ <svg class="w-5 h-5 text-gray-500 transition duration-75 group-hover:text-gray-900"
232
  viewBox="0 0 22 21" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
233
  <path d="M1,10 L11,1 L21,10 L21,20 L1,20 Z" /> <!-- House structure -->
234
  <path d="M6,20 L6,14 L16,14 L16,20" /> <!-- Door -->
 
239
  </li>
240
  <li>
241
  <a href="#" id="dataset"
242
+ class="flex items-center p-2 text-gray-900 rounded-lg hover:bg-gray-100 group">
243
+ <svg class="flex-shrink-0 w-5 h-5 text-gray-500 transition duration-75 group-hover:text-gray-900"
244
  aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
245
  viewBox="0 0 18 18">
246
  <path
 
251
  </li>
252
  <li>
253
  <button type="button"
254
+ class="flex items-center w-full p-2 text-base text-gray-900 transition duration-75 rounded-lg group hover:bg-gray-100"
255
  aria-controls="lb-dropdown" data-collapse-toggle="lb-dropdown">
256
+ <svg class="flex-shrink-0 w-5 h-5 text-gray-500 transition duration-75 group-hover:text-gray-900"
257
  aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
258
  viewBox="0 0 18 21">
259
  <path d="M2,4 L20,4 L20,16 L2,16 Z" />
 
266
  d="m1 1 4 4 4-4" />
267
  </svg>
268
  </button>
269
+ <ul id="lb-dropdown" class="py-2 space-y-2">
270
  <li>
271
  <a href="#" id="public_lb"
272
+ class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100">Public</a>
273
  </li>
274
  <li>
275
  <a href="#" id="private_lb"
276
+ class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100">Private</a>
277
  </li>
278
  </ul>
279
  </li>
280
  <li>
281
  <button type="button"
282
+ class="flex items-center w-full p-2 text-base text-gray-900 transition duration-75 rounded-lg group hover:bg-gray-100"
283
  aria-controls="submissions-dropdown" data-collapse-toggle="submissions-dropdown">
284
+ <svg class="flex-shrink-0 w-5 h-5 text-gray-500 transition duration-75 group-hover:text-gray-900"
285
  aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
286
  viewBox="0 0 20 20">
287
  <path d="M5 5V.13a2.96 2.96 0 0 0-1.293.749L.879 3.707A2.96 2.96 0 0 0 .13 5H5Z" />
 
297
  d="m1 1 4 4 4-4" />
298
  </svg>
299
  </button>
300
+ <ul id="submissions-dropdown" class="py-2 space-y-2">
301
  <li>
302
  <a href="#" id="submission_info"
303
+ class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100">Submission
304
  information</a>
305
  </li>
306
  <li>
307
  <a href="#" id="my_submissions"
308
+ class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100">My
309
  submissions</a>
310
  </li>
311
  <li>
312
  <a href="#" id="new_submission"
313
+ class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100">New
314
  submission</a>
315
  </li>
316
  </ul>
317
  </li>
318
+ <!-- <li>
319
  <a href="#"
320
+ class="flex items-center p-2 text-gray-900 rounded-lg hover:bg-gray-100">
321
+ <svg class="flex-shrink-0 w-5 h-5 text-gray-500 transition duration-75 group-hover:text-gray-900"
322
  aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
323
  viewBox="0 0 20 18">
324
  <path
 
326
  </svg>
327
  <span class="flex-1 ms-3 whitespace-nowrap">Team</span>
328
  </a>
329
+ </li> -->
330
  <li>
331
+ <label for="user_token" class="text-xs font-medium">Hugging Face Token (read-only)
332
  </label>
333
  <input type="password" name="user_token" id="user_token"
334
  class="mt-1 block w-full border border-gray-300 px-3 py-1.5 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
335
  </li>
336
  </ul>
337
+ <footer>
338
+ <div class="w-full mx-auto max-w-screen-xl p-4 md:flex md:items-center md:justify-between">
339
+ <span class="text-sm text-gray-500 sm:text-center">Powered by <a
340
+ href="https://github.com/huggingface/competitions" class="hover:underline">Hugging Face
341
+ Competitions</a>
342
+ </span>
343
+ </div>
344
+ </footer>
345
  </div>
346
  </aside>
347
  <div class="p-1 sm:ml-64">
348
+ <img src={{logo}} alt="Competition logo">
349
  <hr class="mt-3 mb-2">
350
+ <div id="articleLoadingSpinner" role="status"
351
+ class="hidden absolute -translate-x-1/2 -translate-y-1/2 top-2/4 left-1/2">
352
+ <div class="animate-spin rounded-full h-32 w-32 border-b-2 border-gray-900"></div>
353
+ <span class="sr-only">Loading...</span>
354
+ </div>
355
+ <article class="prose w-full mx-auto max-w-screen-xl p-4 md:flex md:items-center md:justify-between"
356
+ id="content">
357
  </article>
358
  </div>
359
  <div id="submission-modal" tabindex="-1"
 
368
  <form action="#" method="post" class="gap-2" enctype="multipart/form-data">
369
  {% if competition_type == 'generic' %}
370
  <div class="form-group">
371
+ <label class="block mb-2 text-sm font-medium text-gray-900" for="submission_file">Upload
 
372
  file</label>
373
  <input
374
  class="block w-full text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 focus:outline-none "
competitions/utils.py CHANGED
@@ -65,9 +65,10 @@ def run_evaluation(params, local=False, wait=False):
65
 
66
  def pause_space(params):
67
  if "SPACE_ID" in os.environ:
68
- logger.info("Pausing space...")
69
- api = HfApi(token=params.token)
70
- api.pause_space(repo_id=os.environ["SPACE_ID"])
 
71
 
72
 
73
  def download_submission_info(params):
 
65
 
66
  def pause_space(params):
67
  if "SPACE_ID" in os.environ:
68
+ if os.environ["SPACE_ID"].split("/")[-1].startswith("comp-"):
69
+ logger.info("Pausing space...")
70
+ api = HfApi(token=params.token)
71
+ api.pause_space(repo_id=os.environ["SPACE_ID"])
72
 
73
 
74
  def download_submission_info(params):