PyKubeGrader 0.0.9__tar.gz → 0.1.1__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. {pykubegrader-0.0.9/src/PyKubeGrader.egg-info → pykubegrader-0.1.1}/PKG-INFO +1 -1
  2. {pykubegrader-0.0.9 → pykubegrader-0.1.1/src/PyKubeGrader.egg-info}/PKG-INFO +1 -1
  3. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/src/PyKubeGrader.egg-info/SOURCES.txt +11 -9
  4. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/src/pykubegrader/__init__.py +1 -2
  5. pykubegrader-0.1.1/src/pykubegrader/initialize.py +28 -0
  6. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/src/pykubegrader/telemetry.py +25 -15
  7. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/src/pykubegrader/validate.py +17 -12
  8. pykubegrader-0.1.1/src/pykubegrader/widgets/__init__.py +1 -0
  9. pykubegrader-0.0.9/src/pykubegrader/mc_widget.py → pykubegrader-0.1.1/src/pykubegrader/widgets/multiple_choice.py +11 -2
  10. pykubegrader-0.0.9/src/pykubegrader/reading_widget.py → pykubegrader-0.1.1/src/pykubegrader/widgets/reading_question.py +1 -1
  11. pykubegrader-0.0.9/src/pykubegrader/select_many_widget.py → pykubegrader-0.1.1/src/pykubegrader/widgets/select_many.py +10 -1
  12. pykubegrader-0.0.9/src/pykubegrader/info_widget.py → pykubegrader-0.1.1/src/pykubegrader/widgets/student_info.py +9 -1
  13. pykubegrader-0.0.9/src/pykubegrader/types_widget.py → pykubegrader-0.1.1/src/pykubegrader/widgets/types_question.py +11 -2
  14. pykubegrader-0.1.1/src/pykubegrader/widgets_base/__init__.py +1 -0
  15. pykubegrader-0.0.9/src/pykubegrader/multi_select_base.py → pykubegrader-0.1.1/src/pykubegrader/widgets_base/multi_select.py +2 -2
  16. pykubegrader-0.0.9/src/pykubegrader/reading_base.py → pykubegrader-0.1.1/src/pykubegrader/widgets_base/reading.py +2 -2
  17. pykubegrader-0.0.9/src/pykubegrader/select_base.py → pykubegrader-0.1.1/src/pykubegrader/widgets_base/select.py +4 -2
  18. pykubegrader-0.0.9/src/pykubegrader/initialize.py +0 -18
  19. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/.coveragerc +0 -0
  20. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/.github/workflows/main.yml +0 -0
  21. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/.gitignore +0 -0
  22. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/.readthedocs.yml +0 -0
  23. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/AUTHORS.rst +0 -0
  24. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/CHANGELOG.rst +0 -0
  25. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/CONTRIBUTING.rst +0 -0
  26. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/LICENSE.txt +0 -0
  27. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/README.rst +0 -0
  28. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/docs/Makefile +0 -0
  29. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/docs/_static/Drexel_blue_Logo_square_Dark.png +0 -0
  30. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/docs/_static/Drexel_blue_Logo_square_Light.png +0 -0
  31. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/docs/_static/custom.css +0 -0
  32. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/docs/authors.rst +0 -0
  33. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/docs/changelog.rst +0 -0
  34. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/docs/conf.py +0 -0
  35. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/docs/contributing.rst +0 -0
  36. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/docs/index.rst +0 -0
  37. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/docs/license.rst +0 -0
  38. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/docs/readme.rst +0 -0
  39. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/docs/requirements.txt +0 -0
  40. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/pyproject.toml +0 -0
  41. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/setup.cfg +0 -0
  42. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/setup.py +0 -0
  43. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/src/PyKubeGrader.egg-info/dependency_links.txt +0 -0
  44. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/src/PyKubeGrader.egg-info/not-zip-safe +0 -0
  45. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/src/PyKubeGrader.egg-info/requires.txt +0 -0
  46. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/src/PyKubeGrader.egg-info/top_level.txt +0 -0
  47. /pykubegrader-0.0.9/src/pykubegrader/misc.py → /pykubegrader-0.1.1/src/pykubegrader/utils.py +0 -0
  48. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/tests/conftest.py +0 -0
  49. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/tests/import_test.py +0 -0
  50. {pykubegrader-0.0.9 → pykubegrader-0.1.1}/tox.ini +0 -0
@@ -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
@@ -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
@@ -30,17 +30,19 @@ src/PyKubeGrader.egg-info/not-zip-safe
30
30
  src/PyKubeGrader.egg-info/requires.txt
31
31
  src/PyKubeGrader.egg-info/top_level.txt
32
32
  src/pykubegrader/__init__.py
33
- src/pykubegrader/info_widget.py
34
33
  src/pykubegrader/initialize.py
35
- src/pykubegrader/mc_widget.py
36
- src/pykubegrader/misc.py
37
- src/pykubegrader/multi_select_base.py
38
- src/pykubegrader/reading_base.py
39
- src/pykubegrader/reading_widget.py
40
- src/pykubegrader/select_base.py
41
- src/pykubegrader/select_many_widget.py
42
34
  src/pykubegrader/telemetry.py
43
- src/pykubegrader/types_widget.py
35
+ src/pykubegrader/utils.py
44
36
  src/pykubegrader/validate.py
37
+ src/pykubegrader/widgets/__init__.py
38
+ src/pykubegrader/widgets/multiple_choice.py
39
+ src/pykubegrader/widgets/reading_question.py
40
+ src/pykubegrader/widgets/select_many.py
41
+ src/pykubegrader/widgets/student_info.py
42
+ src/pykubegrader/widgets/types_question.py
43
+ src/pykubegrader/widgets_base/__init__.py
44
+ src/pykubegrader/widgets_base/multi_select.py
45
+ src/pykubegrader/widgets_base/reading.py
46
+ src/pykubegrader/widgets_base/select.py
45
47
  tests/conftest.py
46
48
  tests/import_test.py
@@ -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"
@@ -0,0 +1,28 @@
1
+ import json
2
+
3
+ import panel as pn
4
+ from IPython import get_ipython
5
+
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
14
+
15
+ try:
16
+ ipython.events.register("pre_run_cell", telemetry)
17
+ except TypeError as e:
18
+ print(f"Failed to register telemetry: {e}")
19
+
20
+ pn.extension()
21
+
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
27
+
28
+ print("Assignment successfully initialized")
@@ -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,
@@ -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")
@@ -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,
@@ -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
- import panel as pn
2
- from IPython import get_ipython
3
-
4
- from .telemetry import telemetry
5
-
6
- # Check if in a Jupyter environment
7
- ipython = get_ipython()
8
-
9
- if ipython is not None:
10
- # Initialize Panel extension
11
- pn.extension()
12
-
13
- # Register telemetry with pre_run_cell event
14
- ipython.events.register("pre_run_cell", telemetry)
15
-
16
- print("Setup completed successfully")
17
- else:
18
- print("Setup unsuccessful. Are you in a Jupyter environment?")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes