idolezal commited on
Commit
2e42a59
β€’
1 Parent(s): dfdc202

Locks only on confirmation of submission

Browse files
Files changed (2) hide show
  1. app.py +38 -6
  2. server.py +56 -23
app.py CHANGED
@@ -1,5 +1,6 @@
1
  import os
2
 
 
3
  import regex as re
4
  import gradio as gr
5
  from gradio.themes.utils.sizes import text_md
@@ -181,8 +182,12 @@ def get_submission_ids_and_titles():
181
 
182
  return submission_ids_and_titles
183
 
184
- def submit_results():
185
- leaderboard_server.save_pre_submit()
 
 
 
 
186
  gr.Info('Submission successful!')
187
 
188
  with leaderboard_server.var_lock.ro:
@@ -215,10 +220,14 @@ def submit_results():
215
  )
216
 
217
 
218
- def erase_pre_submit():
219
- with leaderboard_server.pre_submit_lock:
220
- if leaderboard_server.pre_submit:
221
- leaderboard_server.pre_submit = None # NOTE: Is it safe? How to confirm that `submission_id` is equal?
 
 
 
 
222
  return (
223
  gr.update(value='Pre-submit model', visible=True, interactive=True),
224
  gr.update(visible=False),
@@ -908,6 +917,13 @@ def gradio_app():
908
  pre_submission_btn.click(
909
  fn=on_submit_pressed,
910
  outputs=[pre_submission_btn],
 
 
 
 
 
 
 
911
  ).then(
912
  fn=process_submission,
913
  inputs=list(submission_inputs.values()),
@@ -938,6 +954,7 @@ def gradio_app():
938
  ]
939
  ).then(
940
  fn=submit_results,
 
941
  outputs=[
942
  pre_submission_btn,
943
  submission_btn_yes,
@@ -961,6 +978,13 @@ def gradio_app():
961
  modal_submit_yes,
962
  modal_submit_no,
963
  ]
 
 
 
 
 
 
 
964
  )
965
 
966
  modal_submit_no.click(
@@ -982,6 +1006,7 @@ def gradio_app():
982
 
983
  submission_btn_no.click(
984
  fn=erase_pre_submit,
 
985
  outputs=[
986
  pre_submission_btn,
987
  submission_btn_yes,
@@ -993,6 +1018,13 @@ def gradio_app():
993
  pre_submit_model_tournament_results_table,
994
  pre_submit_model_tournament_results_table_csv,
995
  ],
 
 
 
 
 
 
 
996
  )
997
 
998
  with gr.TabItem('About'):
 
1
  import os
2
 
3
+ import json
4
  import regex as re
5
  import gradio as gr
6
  from gradio.themes.utils.sizes import text_md
 
182
 
183
  return submission_ids_and_titles
184
 
185
+ def submit_results(*inputs):
186
+ inputs = dict(zip(SUBMISSION_INPUTS, inputs))
187
+ with open(inputs["submission_file"]) as fp:
188
+ data = json.load(fp)
189
+ metadata = data["submission_metadata"]
190
+ leaderboard_server.save_model_submission(inputs["submission_file"], metadata)
191
  gr.Info('Submission successful!')
192
 
193
  with leaderboard_server.var_lock.ro:
 
220
  )
221
 
222
 
223
+ def erase_pre_submit(*inputs):
224
+ inputs = dict(zip(SUBMISSION_INPUTS, inputs))
225
+ with open(inputs["submission_file"]) as fp:
226
+ data = json.load(fp)
227
+ metadata = data["submission_metadata"]
228
+ submission_id = metadata["submission_id"]
229
+ leaderboard_server.pre_submit.pop(submission_id)
230
+
231
  return (
232
  gr.update(value='Pre-submit model', visible=True, interactive=True),
233
  gr.update(visible=False),
 
917
  pre_submission_btn.click(
918
  fn=on_submit_pressed,
919
  outputs=[pre_submission_btn],
920
+ ).then(
921
+ fn=lambda *inputs: tuple(
922
+ gr.update(interactive=False)
923
+ for _ in inputs
924
+ ),
925
+ inputs=list(submission_inputs.values()),
926
+ outputs=list(submission_inputs.values()),
927
  ).then(
928
  fn=process_submission,
929
  inputs=list(submission_inputs.values()),
 
954
  ]
955
  ).then(
956
  fn=submit_results,
957
+ inputs=list(submission_inputs.values()),
958
  outputs=[
959
  pre_submission_btn,
960
  submission_btn_yes,
 
978
  modal_submit_yes,
979
  modal_submit_no,
980
  ]
981
+ ).then(
982
+ fn=lambda *inputs: tuple(
983
+ gr.update(interactive=True)
984
+ for _ in inputs
985
+ ),
986
+ inputs=list(submission_inputs.values()),
987
+ outputs=list(submission_inputs.values()),
988
  )
989
 
990
  modal_submit_no.click(
 
1006
 
1007
  submission_btn_no.click(
1008
  fn=erase_pre_submit,
1009
+ inputs=list(submission_inputs.values()),
1010
  outputs=[
1011
  pre_submission_btn,
1012
  submission_btn_yes,
 
1018
  pre_submit_model_tournament_results_table,
1019
  pre_submit_model_tournament_results_table_csv,
1020
  ],
1021
+ ).then(
1022
+ fn=lambda *inputs: tuple(
1023
+ gr.update(interactive=True)
1024
+ for _ in inputs
1025
+ ),
1026
+ inputs=list(submission_inputs.values()),
1027
+ outputs=list(submission_inputs.values()),
1028
  )
1029
 
1030
  with gr.TabItem('About'):
server.py CHANGED
@@ -167,6 +167,19 @@ def check_significance(model_a_path, model_b_path):
167
  result = check_significance_wait_for_result(result_url)
168
  return result
169
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  class TimeoutLock:
171
  def __init__(self, lock=None, timeout=-1):
172
  self.lock = lock or Lock()
@@ -187,8 +200,6 @@ class TimeoutLock:
187
  def __call__(self, timeout):
188
  return TimeoutLock(lock=self.lock, timeout=timeout)
189
 
190
- pre_submit_lock = TimeoutLock()
191
-
192
  class _ReadLock:
193
  def __init__(self, lock):
194
  self._lock = lock
@@ -259,8 +270,8 @@ class LeaderboardServer:
259
  self.results_dataset_local_snapshot_lock = ReadWriteLock()
260
  self.results_dataset_local_snapshot = None
261
 
262
- self.pre_submit_lock = pre_submit_lock
263
- self.pre_submit = None
264
 
265
  self.results_dataset_integrity_check() # Check integrity of the results dataset after (re)start Hugging Face Space
266
  self.update_leaderboard()
@@ -410,8 +421,8 @@ class LeaderboardServer:
410
  """
411
 
412
  while True:
413
- with self.pre_submit_lock(timeout=5) as acquired:
414
- if acquired and self.pre_submit == None:
415
  gr.Info('Checking integrity...', duration=15)
416
  self._update_models_and_tournament_results()
417
 
@@ -765,6 +776,13 @@ class LeaderboardServer:
765
  def start_tournament(self, new_submission_id, new_model_file):
766
  with self.var_lock.ro:
767
  new_tournament = copy.deepcopy(self.tournament_results)
 
 
 
 
 
 
 
768
  if new_submission_id not in new_tournament:
769
  new_tournament[new_submission_id] = {}
770
  new_tournament[new_submission_id][new_submission_id] = {
@@ -849,7 +867,7 @@ class LeaderboardServer:
849
  return result
850
 
851
  PreSubmit = namedtuple('PreSubmit', 'tournament_results, submission_id, file, data')
852
-
853
  def prepare_model_for_submission(self, file, metadata) -> PreSubmit:
854
  with open(file, "r") as f:
855
  data = json.load(f)
@@ -867,17 +885,35 @@ class LeaderboardServer:
867
  with open(file, "w") as f:
868
  json.dump(data, f, separators=(',', ':')) # compact JSON
869
 
 
 
 
 
 
 
 
 
 
 
 
870
  while True:
871
- with self.pre_submit_lock(timeout=5) as acquired:
872
- if acquired and self.pre_submit == None:
873
- gr.Info('Running tournament...', duration=15)
 
 
 
 
 
 
 
874
  self.update_leaderboard()
875
  if HF_FAKE_TOURNAMENT:
876
  with self.var_lock.ro:
877
  tournament_results = copy.deepcopy(self.tournament_results)
878
  else:
879
  tournament_results = self.start_tournament(submission_id, file)
880
- self.pre_submit = self.PreSubmit(
881
  tournament_results,
882
  submission_id,
883
  file,
@@ -887,22 +923,19 @@ class LeaderboardServer:
887
  "submission_metadata": metadata,
888
  }
889
  )
 
 
 
 
 
 
 
 
890
  break
891
  gr.Info("Waiting in queue...", duration=5)
892
  time.sleep(10)
893
 
894
- return self.pre_submit
895
-
896
- def save_pre_submit(self):
897
- with self.pre_submit_lock:
898
- if self.pre_submit:
899
- tournament_results, submission_id, file, data = self.pre_submit
900
-
901
- self._upload_submission(submission_id, file)
902
- self._upload_tournament_results(tournament_results)
903
-
904
- self.pre_submit = None
905
- self.update_leaderboard()
906
 
907
  def _upload_submission_id_to_model_title(self):
908
  # Temporary save tournament results
 
167
  result = check_significance_wait_for_result(result_url)
168
  return result
169
 
170
+ class NoneLock:
171
+ def __init__(self, *args, **kwargs):
172
+ pass
173
+
174
+ def __enter__(self):
175
+ return True
176
+
177
+ def __exit__(self, exc_type, exc_val, exc_tb):
178
+ return
179
+
180
+ def __call__(self, *args, **kwargs):
181
+ return NoneLock(*args, **kwargs)
182
+
183
  class TimeoutLock:
184
  def __init__(self, lock=None, timeout=-1):
185
  self.lock = lock or Lock()
 
200
  def __call__(self, timeout):
201
  return TimeoutLock(lock=self.lock, timeout=timeout)
202
 
 
 
203
  class _ReadLock:
204
  def __init__(self, lock):
205
  self._lock = lock
 
270
  self.results_dataset_local_snapshot_lock = ReadWriteLock()
271
  self.results_dataset_local_snapshot = None
272
 
273
+ self.pre_submit = {}
274
+ self.submit_lock = TimeoutLock()
275
 
276
  self.results_dataset_integrity_check() # Check integrity of the results dataset after (re)start Hugging Face Space
277
  self.update_leaderboard()
 
421
  """
422
 
423
  while True:
424
+ with self.submit_lock(timeout=5) as acquired:
425
+ if acquired:
426
  gr.Info('Checking integrity...', duration=15)
427
  self._update_models_and_tournament_results()
428
 
 
776
  def start_tournament(self, new_submission_id, new_model_file):
777
  with self.var_lock.ro:
778
  new_tournament = copy.deepcopy(self.tournament_results)
779
+
780
+ pre_submit = self.pre_submit.get(new_submission_id)
781
+ if pre_submit:
782
+ new_tournament[new_submission_id] = pre_submit.tournament_results[new_submission_id]
783
+ for competitor_id in pre_submit.tournament_results[new_submission_id].keys() - {new_submission_id}:
784
+ new_tournament[competitor_id][new_submission_id] = pre_submit.tournament_results[competitor_id][new_submission_id]
785
+
786
  if new_submission_id not in new_tournament:
787
  new_tournament[new_submission_id] = {}
788
  new_tournament[new_submission_id][new_submission_id] = {
 
867
  return result
868
 
869
  PreSubmit = namedtuple('PreSubmit', 'tournament_results, submission_id, file, data')
870
+
871
  def prepare_model_for_submission(self, file, metadata) -> PreSubmit:
872
  with open(file, "r") as f:
873
  data = json.load(f)
 
885
  with open(file, "w") as f:
886
  json.dump(data, f, separators=(',', ':')) # compact JSON
887
 
888
+ return self._prepare_model_for_submission(file, metadata, do_submit=False)
889
+
890
+ def save_model_submission(self, file, metadata) -> PreSubmit:
891
+ return self._prepare_model_for_submission(file, metadata, do_submit=True)
892
+
893
+ def _prepare_model_for_submission(self, file, metadata, do_submit=False) -> PreSubmit:
894
+ with open(file, "r") as f:
895
+ data = json.load(f)
896
+
897
+ submission_id = metadata["submission_id"]
898
+
899
  while True:
900
+ submit_lock = self.submit_lock if do_submit else NoneLock()
901
+
902
+ with submit_lock(timeout=5) as acquired:
903
+ if acquired:
904
+ info_msg = 'Running tournament...'
905
+ gr.Info(info_msg, duration=15)
906
+ if do_submit:
907
+ print(f"Locked `submit_lock` for {submission_id = }")
908
+ print(info_msg)
909
+
910
  self.update_leaderboard()
911
  if HF_FAKE_TOURNAMENT:
912
  with self.var_lock.ro:
913
  tournament_results = copy.deepcopy(self.tournament_results)
914
  else:
915
  tournament_results = self.start_tournament(submission_id, file)
916
+ pre_submit = self.PreSubmit(
917
  tournament_results,
918
  submission_id,
919
  file,
 
923
  "submission_metadata": metadata,
924
  }
925
  )
926
+ self.pre_submit[submission_id] = pre_submit
927
+
928
+ if do_submit:
929
+ self._upload_submission(pre_submit.submission_id, pre_submit.file)
930
+ self._upload_tournament_results(pre_submit.tournament_results)
931
+ self.update_leaderboard()
932
+ print(f"Unlocked `submit_lock` for {submission_id = }")
933
+
934
  break
935
  gr.Info("Waiting in queue...", duration=5)
936
  time.sleep(10)
937
 
938
+ return pre_submit
 
 
 
 
 
 
 
 
 
 
 
939
 
940
  def _upload_submission_id_to_model_title(self):
941
  # Temporary save tournament results