kattis2canvas 0.1.5__tar.gz → 0.1.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kattis2canvas
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Summary: CLI tool to integrate Kattis offerings with Canvas LMS courses
5
5
  Author: bcr33d
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "kattis2canvas"
7
- version = "0.1.5"
7
+ version = "0.1.7"
8
8
  description = "CLI tool to integrate Kattis offerings with Canvas LMS courses"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -734,7 +734,8 @@ def kattislinks(canvas_course):
734
734
  @click.option("--dryrun/--no-dryrun", default=True, help="show planned actions, do not make them happen.")
735
735
  @click.option("--assignment-group", default="kattis", help="the canvas assignment group to use (default: kattis).")
736
736
  @click.option("--section", help="only process submissions for students in this specific section.")
737
- def submissions2canvas(offering, canvas_course, dryrun, assignment_group, section):
737
+ @click.option("--force-comment/--no-force-comment", default=False, help="add a comment about the best submission even if there is already a comment in canvas.")
738
+ def submissions2canvas(offering, canvas_course, dryrun, assignment_group, section, force_comment):
738
739
  """
739
740
  mirror summary of submission from kattis into canvas as a submission comment.
740
741
  """
@@ -796,20 +797,22 @@ def submissions2canvas(offering, canvas_course, dryrun, assignment_group, sectio
796
797
  f'duplicate submission for {kattis_user2canvas_id[canvas_submission.user_id]} in {assignment.title}')
797
798
  submissions_by_user[canvas_id2kattis_user[canvas_submission.user_id]] = canvas_submission
798
799
  last_comment = datetime.datetime.fromordinal(1).replace(tzinfo=datetime.timezone.utc)
800
+ last_comment_text = ''
799
801
  if canvas_submission.submission_comments:
800
802
  for comment in canvas_submission.submission_comments:
801
803
  created_at = extract_canvas_date(comment['created_at'])
802
- if created_at > last_comment:
804
+ if config.kattis_hostname in comment.get('comment', '') and created_at > last_comment:
803
805
  last_comment = created_at
806
+ last_comment_text = comment.get('comment', '')
804
807
  canvas_submission.last_comment = last_comment
805
-
808
+ canvas_submission.last_comment_text = last_comment_text
806
809
  for user, best in best_submissions.items():
807
810
  for kattis_submission in best.values():
808
811
  if user not in submissions_by_user:
809
812
  warn(f"i don't see a canvas user for {user}")
810
813
  elif user not in kattis_user2canvas_id:
811
814
  warn(f'skipping submission for unknown user {user}')
812
- elif kattis_submission.date > submissions_by_user[user].last_comment:
815
+ elif kattis_submission.date > submissions_by_user[user].last_comment or force_comment:
813
816
  if dryrun:
814
817
  warn(
815
818
  f"would update {kattis_user2canvas_id[kattis_submission.user]} on problem {kattis_submission.problem} scored {kattis_submission.score}")
@@ -825,46 +828,62 @@ def submissions2canvas(offering, canvas_course, dryrun, assignment_group, sectio
825
828
 
826
829
  def get_best_submissions(offering: str, assignment_id: str) -> {str: {str: Submission}}:
827
830
  best_submissions = collections.defaultdict(dict)
828
- url = f"https://{config.kattis_hostname}{offering}/assignments/{assignment_id}/submissions"
829
- rsp = web_get(url)
830
- bs = BeautifulSoup(rsp.content, "html.parser")
831
- judge_table = bs.find("table", id="judge_table")
832
- if not judge_table:
833
- info(f"no submissions yet for {assignment_id}")
834
- return best_submissions
835
- headers = [x.get_text().strip() for x in judge_table.find_all("th")]
836
- tbody = judge_table.find("tbody")
837
- for submissions in tbody.find_all("tr", recursive=False):
838
- if not submissions.get("data-submission-id"):
839
- continue
840
- submissions = submissions.find_all("td", recursive=False)
841
- if not submissions:
842
- continue
843
- props = {}
844
- for index, td in enumerate(submissions):
845
- a = td.find("a")
846
- props[headers[index]] = a.get("href") if a else td.get_text().strip()
847
- date = props["Date"]
848
- if "-" in date:
849
- date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S").replace(tzinfo=now.tzinfo)
850
- else:
851
- hms = datetime.datetime.strptime(date, "%H:%M:%S")
852
- date = now.replace(hour=hms.hour, minute=hms.minute, second=hms.second)
853
- # it's not clear when the short date version is used. it might be used when it is less than 24 hours,
854
- # in which case, just setting the time will make the date 24 hours more than it should be
855
- if date > now:
856
- date -= datetime.timedelta(days=1)
857
-
858
- score = 0.0 if props["Test cases"] == "-/-" else float(Fraction(props["Test cases"])) * 100
859
- submission = Submission(user=extract_last(props["User"]), problem=extract_last(props["Problem"]), date=date,
860
- score=score, url=props[""])
861
- if submission.problem not in best_submissions[submission.user]:
862
- best_submissions[submission.user] = {submission.problem: submission}
863
- else:
864
- current_best = best_submissions[submission.user][submission.problem]
865
- if current_best.score < submission.score or (
866
- current_best.score == submission.score and current_best.date < submission.date):
831
+ base_url = f"https://{config.kattis_hostname}{offering}/assignments/{assignment_id}/submissions"
832
+ headers = None
833
+ page = 0
834
+
835
+ while True:
836
+ url = f"{base_url}?page={page}"
837
+ rsp = web_get(url)
838
+ bs = BeautifulSoup(rsp.content, "html.parser")
839
+ judge_table = bs.find("table", id="judge_table")
840
+
841
+ if not judge_table:
842
+ if page == 0:
843
+ info(f"no submissions yet for {assignment_id}")
844
+ break
845
+
846
+ if headers is None:
847
+ headers = [x.get_text().strip() for x in judge_table.find_all("th")]
848
+
849
+ tbody = judge_table.find("tbody")
850
+ rows = [r for r in tbody.find_all("tr", recursive=False) if r.get("data-submission-id")]
851
+
852
+ if not rows:
853
+ break
854
+
855
+ for row in rows:
856
+ cells = row.find_all("td", recursive=False)
857
+ if not cells:
858
+ continue
859
+ props = {}
860
+ for index, td in enumerate(cells):
861
+ a = td.find("a")
862
+ props[headers[index]] = a.get("href") if a else td.get_text().strip()
863
+ date = props["Date"]
864
+ if "-" in date:
865
+ date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S").replace(tzinfo=now.tzinfo)
866
+ else:
867
+ hms = datetime.datetime.strptime(date, "%H:%M:%S")
868
+ date = now.replace(hour=hms.hour, minute=hms.minute, second=hms.second)
869
+ # it's not clear when the short date version is used. it might be used when it is less than 24 hours,
870
+ # in which case, just setting the time will make the date 24 hours more than it should be
871
+ if date > now:
872
+ date -= datetime.timedelta(days=1)
873
+
874
+ score = 0.0 if props["Test cases"] == "-/-" else float(Fraction(props["Test cases"])) * 100
875
+ submission = Submission(user=extract_last(props["User"]), problem=extract_last(props["Problem"]), date=date,
876
+ score=score, url=props[""])
877
+ if submission.problem not in best_submissions[submission.user]:
867
878
  best_submissions[submission.user][submission.problem] = submission
879
+ else:
880
+ current_best = best_submissions[submission.user][submission.problem]
881
+ if current_best.score < submission.score or (
882
+ current_best.score == submission.score and current_best.date < submission.date):
883
+ best_submissions[submission.user][submission.problem] = submission
884
+
885
+ page += 1
886
+
868
887
  return best_submissions
869
888
 
870
889
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kattis2canvas
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Summary: CLI tool to integrate Kattis offerings with Canvas LMS courses
5
5
  Author: bcr33d
6
6
  License-Expression: MIT
File without changes
File without changes