PyKubeGrader 0.0.9__py3-none-any.whl → 0.1.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyKubeGrader
3
- Version: 0.0.9
3
+ Version: 0.1.1
4
4
  Summary: Add a short description here!
5
5
  Home-page: https://github.com/pyscaffold/pyscaffold/
6
6
  Author: jagar2
@@ -0,0 +1,20 @@
1
+ pykubegrader/__init__.py,sha256=AoAkdfIjDDZGWLlsIRENNq06L9h46kDGBIE8vRmsCfg,311
2
+ pykubegrader/initialize.py,sha256=PACquuxFkvOKUx51Rv6_RVu1YnYXf9L_W3hmMY5IxMw,706
3
+ pykubegrader/telemetry.py,sha256=eAzb54-lHFcgv0IsLFwsWr4nm_D7u-n-zOdR4cKGID4,3291
4
+ pykubegrader/utils.py,sha256=dKw6SyRYU3DWRgD3xER7wq-C9e1daWPkqr901LpcwiQ,642
5
+ pykubegrader/validate.py,sha256=QzdsjSS7rBzvBj_s_VHk-shjkPE-NYHQrYI3UHbq7Yo,10632
6
+ pykubegrader/widgets/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
7
+ pykubegrader/widgets/multiple_choice.py,sha256=NjD3-uXSnibpUQ0mO3hRp_O-rynFyl0Dz6IXE4tnCRI,2078
8
+ pykubegrader/widgets/reading_question.py,sha256=y30_swHwzH8LrT8deWTnxctAAmR8BSxTlXAqMgUrAT4,3031
9
+ pykubegrader/widgets/select_many.py,sha256=NRRs9P3Jygl9eUVW16nxMLNlHfFDuINgsFhMyXiOsXU,3826
10
+ pykubegrader/widgets/student_info.py,sha256=xhQgKehk1r5e6N_hnjAIovLdPvQju6ZqQTOiPG0aevg,3568
11
+ pykubegrader/widgets/types_question.py,sha256=kZdRRXyFzOtYTmGdC7XWb_2oaxqg1WSuLcQn_sTj6Qc,2300
12
+ pykubegrader/widgets_base/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
13
+ pykubegrader/widgets_base/multi_select.py,sha256=o9FwOSkfjarSZuC0wgBJLSRNtnY1-q_og1k_cdyJki8,3105
14
+ pykubegrader/widgets_base/reading.py,sha256=4uTLmlPzCwxVzufFhPjM7W19uMGguRb6y4eAV3x-zAc,5314
15
+ pykubegrader/widgets_base/select.py,sha256=QfJ72bScZbwdRcPUWLMVaaPJbAJHXnWSHtzjy7UZWkc,2255
16
+ PyKubeGrader-0.1.1.dist-info/LICENSE.txt,sha256=YTp-Ewc8Kems8PJEE27KnBPFnZSxoWvSg7nnknzPyYw,1546
17
+ PyKubeGrader-0.1.1.dist-info/METADATA,sha256=0DH4khXyZ6ibFLbqgPAvSLpu9EnkP4hClSwGi6oCXhA,2640
18
+ PyKubeGrader-0.1.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
19
+ PyKubeGrader-0.1.1.dist-info/top_level.txt,sha256=e550Klfze6higFxER1V62fnGOcIgiKRbsrl9CC4UdtQ,13
20
+ PyKubeGrader-0.1.1.dist-info/RECORD,,
pykubegrader/__init__.py CHANGED
@@ -1,8 +1,7 @@
1
1
  from importlib.metadata import PackageNotFoundError, version # pragma: no cover
2
2
 
3
3
  try:
4
- # Change here if project is renamed and does not equal the package name
5
- dist_name = "PyKubeGrader"
4
+ dist_name = "PyKubeGrader" # Change if project is renamed
6
5
  __version__ = version(dist_name)
7
6
  except PackageNotFoundError: # pragma: no cover
8
7
  __version__ = "unknown"
@@ -1,18 +1,28 @@
1
+ import json
2
+
1
3
  import panel as pn
2
4
  from IPython import get_ipython
3
5
 
4
- from .telemetry import telemetry
6
+ from .telemetry import telemetry, update_responses
7
+
8
+
9
+ def initialize_assignment(name: str) -> None:
10
+ ipython = get_ipython()
11
+ if ipython is None:
12
+ print("Setup unsuccessful. Are you in a Jupyter environment?")
13
+ return
5
14
 
6
- # Check if in a Jupyter environment
7
- ipython = get_ipython()
15
+ try:
16
+ ipython.events.register("pre_run_cell", telemetry)
17
+ except TypeError as e:
18
+ print(f"Failed to register telemetry: {e}")
8
19
 
9
- if ipython is not None:
10
- # Initialize Panel extension
11
20
  pn.extension()
12
21
 
13
- # Register telemetry with pre_run_cell event
14
- ipython.events.register("pre_run_cell", telemetry)
22
+ try:
23
+ update_responses(key="assignment", value=name)
24
+ except (TypeError, json.JSONDecodeError) as e:
25
+ print(f"Failed to initialize assignment: {e}")
26
+ return
15
27
 
16
- print("Setup completed successfully")
17
- else:
18
- print("Setup unsuccessful. Are you in a Jupyter environment?")
28
+ print("Assignment successfully initialized")
pykubegrader/telemetry.py CHANGED
@@ -10,12 +10,12 @@ from IPython.core.interactiveshell import ExecutionInfo
10
10
  from requests import Response
11
11
  from requests.auth import HTTPBasicAuth
12
12
 
13
+ # Set logging config (`force` is important)
13
14
  logging.basicConfig(filename=".output.log", level=logging.INFO, force=True)
14
15
 
15
-
16
- def telemetry(info: ExecutionInfo) -> None:
17
- cell_content = info.raw_cell
18
- log_encrypted(f"code run: {cell_content}")
16
+ #
17
+ # Local functions
18
+ #
19
19
 
20
20
 
21
21
  def encrypt_to_b64(message: str) -> str:
@@ -34,17 +34,6 @@ def encrypt_to_b64(message: str) -> str:
34
34
  return encrypted_b64
35
35
 
36
36
 
37
- def log_encrypted(message: str) -> None:
38
- encrypted_b64 = encrypt_to_b64(message)
39
- logging.info(f"Encrypted Output: {encrypted_b64}")
40
-
41
-
42
- def log_variable(value, info_type) -> None:
43
- timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
44
- message = f"{info_type}, {value}, {timestamp}"
45
- log_encrypted(message)
46
-
47
-
48
37
  def ensure_responses() -> dict:
49
38
  with open(".responses.json", "a") as _:
50
39
  pass
@@ -61,6 +50,22 @@ def ensure_responses() -> dict:
61
50
  return data
62
51
 
63
52
 
53
+ def log_encrypted(message: str) -> None:
54
+ encrypted_b64 = encrypt_to_b64(message)
55
+ logging.info(f"Encrypted Output: {encrypted_b64}")
56
+
57
+
58
+ def log_variable(value, info_type) -> None:
59
+ timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
60
+ message = f"{info_type}, {value}, {timestamp}"
61
+ log_encrypted(message)
62
+
63
+
64
+ def telemetry(info: ExecutionInfo) -> None:
65
+ cell_content = info.raw_cell
66
+ log_encrypted(f"code run: {cell_content}")
67
+
68
+
64
69
  def update_responses(key: str, value) -> dict:
65
70
  data = ensure_responses()
66
71
  data[key] = value
@@ -84,6 +89,11 @@ def update_responses(key: str, value) -> dict:
84
89
  return data
85
90
 
86
91
 
92
+ #
93
+ # API request functions
94
+ #
95
+
96
+
87
97
  def score_question(
88
98
  student_email: str,
89
99
  term: str,
pykubegrader/validate.py CHANGED
@@ -139,7 +139,7 @@ def validate_logfile(
139
139
  return entry
140
140
  return ""
141
141
 
142
- def get_len_of_entries(data, question_number) -> int:
142
+ def get_entries_len(data: list[str], question_number: int) -> int:
143
143
  """function to get the unique entries by length
144
144
 
145
145
  Args:
@@ -180,7 +180,7 @@ def validate_logfile(
180
180
  # Collect entries for each question in a list.
181
181
  entries = [
182
182
  entry
183
- for j in range(1, get_len_of_entries(data, i))
183
+ for j in range(1, get_entries_len(data, i))
184
184
  if (entry := get_last_entry(data, f"q{i}_{j}")) != ""
185
185
  ]
186
186
 
@@ -246,7 +246,7 @@ def validate_logfile(
246
246
  print("Writing to results.json")
247
247
  json.dump(result_structure, file, indent=4)
248
248
 
249
- login_(login_data, login_url)
249
+ verify_login(login_data, login_url)
250
250
 
251
251
  # The file to be uploaded. Ensure the path is correct.
252
252
  file_path = "results.json"
@@ -281,15 +281,9 @@ def validate_logfile(
281
281
  submission_message(response)
282
282
 
283
283
 
284
- def login_(login_data, login_url):
285
- login_response = requests.post(
286
- login_url, auth=HTTPBasicAuth(login_data["username"], login_data["password"])
287
- )
288
-
289
- if login_response.status_code == 200:
290
- print("Login successful")
291
- else:
292
- Exception("Login failed")
284
+ #
285
+ # Helper functions
286
+ #
293
287
 
294
288
 
295
289
  def submission_message(response) -> None:
@@ -309,3 +303,14 @@ def submission_message(response) -> None:
309
303
  pass
310
304
  else:
311
305
  print("results.json was not present")
306
+
307
+
308
+ def verify_login(login_data, login_url):
309
+ login_response = requests.post(
310
+ login_url, auth=HTTPBasicAuth(login_data["username"], login_data["password"])
311
+ )
312
+
313
+ if login_response.status_code == 200:
314
+ print("Login successful")
315
+ else:
316
+ Exception("Login failed")
@@ -0,0 +1 @@
1
+
@@ -2,8 +2,12 @@ from typing import Tuple
2
2
 
3
3
  import panel as pn
4
4
 
5
- from .misc import list_of_lists
6
- from .select_base import SelectQuestion
5
+ from ..utils import list_of_lists
6
+ from ..widgets_base.select import SelectQuestion
7
+
8
+ #
9
+ # Style function
10
+ #
7
11
 
8
12
 
9
13
  def MCQ(
@@ -35,6 +39,11 @@ def MCQ(
35
39
  return desc_widgets, radio_buttons
36
40
 
37
41
 
42
+ #
43
+ # Question class
44
+ #
45
+
46
+
38
47
  class MCQuestion(SelectQuestion):
39
48
  def __init__(
40
49
  self,
@@ -1,4 +1,4 @@
1
- from .reading_base import ReadingPython
1
+ from ..widgets_base.reading import ReadingPython
2
2
 
3
3
 
4
4
  class ReadingPythonQuestion(ReadingPython):
@@ -1,6 +1,10 @@
1
1
  import panel as pn
2
2
 
3
- from .multi_select_base import MultiSelectQuestion
3
+ from ..widgets_base.multi_select import MultiSelectQuestion
4
+
5
+ #
6
+ # Style function
7
+ #
4
8
 
5
9
 
6
10
  def MultiSelect(
@@ -42,6 +46,11 @@ def MultiSelect(
42
46
  return desc_widgets, checkboxes
43
47
 
44
48
 
49
+ #
50
+ # Question class
51
+ #
52
+
53
+
45
54
  class SelectMany(MultiSelectQuestion):
46
55
  def __init__(
47
56
  self,
@@ -5,7 +5,11 @@ import socket
5
5
  import numpy as np
6
6
  import panel as pn
7
7
 
8
- from .telemetry import ensure_responses, update_responses
8
+ from ..telemetry import ensure_responses, update_responses
9
+
10
+ #
11
+ # Constants
12
+ #
9
13
 
10
14
  EMAIL_PATTERN = re.compile(r"[a-z]+\d+@drexel\.edu")
11
15
 
@@ -20,6 +24,10 @@ KEYS = [
20
24
  "seed",
21
25
  ]
22
26
 
27
+ #
28
+ # Form class
29
+ #
30
+
23
31
 
24
32
  class StudentInfoForm:
25
33
  def __init__(self, **kwargs) -> None:
@@ -2,8 +2,12 @@ from typing import Tuple
2
2
 
3
3
  import panel as pn
4
4
 
5
- from .misc import list_of_lists
6
- from .select_base import SelectQuestion
5
+ from ..utils import list_of_lists
6
+ from ..widgets_base.select import SelectQuestion
7
+
8
+ #
9
+ # Style function
10
+ #
7
11
 
8
12
 
9
13
  def MultipleChoice(
@@ -31,6 +35,11 @@ def MultipleChoice(
31
35
  return desc_widgets, dropdowns
32
36
 
33
37
 
38
+ #
39
+ # Question class
40
+ #
41
+
42
+
34
43
  class TypesQuestion(SelectQuestion):
35
44
  def __init__(
36
45
  self,
@@ -0,0 +1 @@
1
+
@@ -2,8 +2,8 @@ from typing import Callable, Tuple
2
2
 
3
3
  import panel as pn
4
4
 
5
- from .misc import shuffle_questions
6
- from .telemetry import ensure_responses, update_responses
5
+ from ..telemetry import ensure_responses, update_responses
6
+ from ..utils import shuffle_questions
7
7
 
8
8
 
9
9
  class MultiSelectQuestion:
@@ -3,8 +3,8 @@ from typing import Optional
3
3
 
4
4
  import panel as pn
5
5
 
6
- from .misc import shuffle_options
7
- from .telemetry import ensure_responses, update_responses
6
+ from ..telemetry import ensure_responses, update_responses
7
+ from ..utils import shuffle_options
8
8
 
9
9
 
10
10
  class ReadingPython:
@@ -2,8 +2,8 @@ from typing import Callable, Tuple
2
2
 
3
3
  import panel as pn
4
4
 
5
- from .misc import shuffle_questions
6
- from .telemetry import ensure_responses, update_responses
5
+ from ..telemetry import ensure_responses, update_responses
6
+ from ..utils import shuffle_questions
7
7
 
8
8
 
9
9
  class SelectQuestion:
@@ -57,6 +57,8 @@ class SelectQuestion:
57
57
  )
58
58
 
59
59
  def submit(self, _) -> None:
60
+ print("Submit button clicked...") # For debugging; remove later
61
+
60
62
  selections = {key: widget.value for key, widget in zip(self.keys, self.widgets)}
61
63
 
62
64
  for value in selections.values():
@@ -1,18 +0,0 @@
1
- pykubegrader/__init__.py,sha256=L_TI3XcAgChNAmXaeDyMEdtgIclVl5czyC2f8Vhg_oE,355
2
- pykubegrader/info_widget.py,sha256=x73heTqmqJQ9XkaE3eW4eLXTGJlmmTdGEkGtbIcY7uY,3532
3
- pykubegrader/initialize.py,sha256=-s2hR8254hPz2-vKvlhHMDuNMBOZCqxxNdUpduBhYJs,444
4
- pykubegrader/mc_widget.py,sha256=_qmJ4ZvU-KXamS726LqnCgecRg29hDd7w5WOerkLvuA,2022
5
- pykubegrader/misc.py,sha256=dKw6SyRYU3DWRgD3xER7wq-C9e1daWPkqr901LpcwiQ,642
6
- pykubegrader/multi_select_base.py,sha256=GJQ-xFJTErar94cFwTxsSmLKPPmywJRUQELhAbv-uFs,3102
7
- pykubegrader/reading_base.py,sha256=vSoyThl2vFbnbgB_LDc-DDRPWCM2xGbazEptDjNn4uA,5311
8
- pykubegrader/reading_widget.py,sha256=e8lXSzGI9dHCxW7fIvwJUU6j8qWQgHnKR06ke2W1k7w,3022
9
- pykubegrader/select_base.py,sha256=90EnUPoNhJphkH1HXXxEgSmJDBrTWOqLNDha3DaZpGM,2178
10
- pykubegrader/select_many_widget.py,sha256=Rmb9Es42qzSdPfhU6ypcKnw_30PwuARX2UKVwgwbQhg,3772
11
- pykubegrader/telemetry.py,sha256=3GhItJ9dw18XcFutfQEk4z-DllCVtKXCKKLesf_jxzQ,3194
12
- pykubegrader/types_widget.py,sha256=FOrnR2x1eNM-pcFNIC8JnQdylgSUSUzuACmiIRuFTbQ,2244
13
- pykubegrader/validate.py,sha256=guEj0yeu9A_-Ig6S8diOfaNEWxud3k7t4tI-i4Steak,10585
14
- PyKubeGrader-0.0.9.dist-info/LICENSE.txt,sha256=YTp-Ewc8Kems8PJEE27KnBPFnZSxoWvSg7nnknzPyYw,1546
15
- PyKubeGrader-0.0.9.dist-info/METADATA,sha256=YifwDx2WiOdMXZTYNtSIIjEBi5AAsqUSdzOdM7szOaY,2640
16
- PyKubeGrader-0.0.9.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
17
- PyKubeGrader-0.0.9.dist-info/top_level.txt,sha256=e550Klfze6higFxER1V62fnGOcIgiKRbsrl9CC4UdtQ,13
18
- PyKubeGrader-0.0.9.dist-info/RECORD,,
File without changes