PyKubeGrader 0.1.2__py3-none-any.whl → 0.1.3__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- {PyKubeGrader-0.1.2.dist-info → PyKubeGrader-0.1.3.dist-info}/METADATA +1 -1
- PyKubeGrader-0.1.3.dist-info/RECORD +24 -0
- PyKubeGrader-0.1.3.dist-info/entry_points.txt +2 -0
- pykubegrader/build/build_folder.py +1531 -0
- pykubegrader/widgets/__init__.py +9 -0
- pykubegrader/widgets/select_many.py +10 -0
- pykubegrader/widgets/style.py +47 -0
- pykubegrader/widgets/true_false.py +101 -0
- pykubegrader/widgets_base/multi_select.py +12 -2
- pykubegrader/widgets_base/select.py +19 -1
- PyKubeGrader-0.1.2.dist-info/RECORD +0 -20
- {PyKubeGrader-0.1.2.dist-info → PyKubeGrader-0.1.3.dist-info}/LICENSE.txt +0 -0
- {PyKubeGrader-0.1.2.dist-info → PyKubeGrader-0.1.3.dist-info}/WHEEL +0 -0
- {PyKubeGrader-0.1.2.dist-info → PyKubeGrader-0.1.3.dist-info}/top_level.txt +0 -0
pykubegrader/widgets/__init__.py
CHANGED
@@ -1 +1,10 @@
|
|
1
|
+
# Auto-generated __init__.py
|
1
2
|
|
3
|
+
from . import select_many
|
4
|
+
from . import multiple_choice
|
5
|
+
from . import true_false
|
6
|
+
from . import reading_question
|
7
|
+
from . import student_info
|
8
|
+
from . import types_question
|
9
|
+
|
10
|
+
__all__ = ['select_many', 'multiple_choice', 'true_false', 'reading_question', 'student_info', 'types_question']
|
@@ -1,6 +1,13 @@
|
|
1
1
|
import panel as pn
|
2
2
|
|
3
3
|
from ..widgets_base.multi_select import MultiSelectQuestion
|
4
|
+
from ..widgets.style import drexel_colors, raw_css
|
5
|
+
|
6
|
+
# Pass the custom CSS to Panel
|
7
|
+
pn.extension(design="material", global_css=[drexel_colors], raw_css=[raw_css])
|
8
|
+
|
9
|
+
# Add the custom CSS to Panel
|
10
|
+
pn.config.raw_css.append(raw_css)
|
4
11
|
|
5
12
|
#
|
6
13
|
# Style function
|
@@ -50,6 +57,8 @@ def MultiSelect(
|
|
50
57
|
# Question class
|
51
58
|
#
|
52
59
|
|
60
|
+
# TODO: add grade all or grade in parts.
|
61
|
+
|
53
62
|
|
54
63
|
class SelectMany(MultiSelectQuestion):
|
55
64
|
def __init__(
|
@@ -98,6 +107,7 @@ class SelectMany(MultiSelectQuestion):
|
|
98
107
|
""",
|
99
108
|
],
|
100
109
|
points=1,
|
110
|
+
grade="all",
|
101
111
|
):
|
102
112
|
super().__init__(
|
103
113
|
title=title,
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import panel as pn
|
2
|
+
|
3
|
+
# Extend the Material Design with custom Drexel colors
|
4
|
+
drexel_colors = """
|
5
|
+
:root {
|
6
|
+
--panel-primary-color: #07294D; /* Drexel Blue */
|
7
|
+
--design-primary-color: #07294D; /* Drexel Blue */
|
8
|
+
--design-primary-text-color: #FFFFFF; /* White text on primary */
|
9
|
+
--design-secondary-color: #FFC600; /* Drexel Gold */
|
10
|
+
--design-secondary-text-color: #07294D; /* Blue text on secondary */
|
11
|
+
--design-background-color: #F8F8F8; /* Soft background */
|
12
|
+
--design-background-text-color: #07294D; /* Blue text on background */
|
13
|
+
--design-surface-color: #FFFFFF; /* White surface */
|
14
|
+
--design-surface-text-color: #07294D; /* Blue text on surface */
|
15
|
+
}
|
16
|
+
:host {
|
17
|
+
--design-primary-color: #07294D; /* Drexel Blue */
|
18
|
+
--design-primary-text-color: #FFFFFF; /* White text on primary */
|
19
|
+
--design-secondary-color: #FFC600; /* Drexel Gold */
|
20
|
+
--design-secondary-text-color: #07294D; /* Blue text on secondary */
|
21
|
+
--design-background-color: #F8F8F8; /* Soft background */
|
22
|
+
--design-background-text-color: #07294D; /* Blue text on background */
|
23
|
+
--design-surface-color: #FFFFFF; /* White surface */
|
24
|
+
--design-surface-text-color: #07294D; /* Blue text on surface */}
|
25
|
+
"""
|
26
|
+
|
27
|
+
raw_css = """
|
28
|
+
/* Styling for the labels */
|
29
|
+
.bk-input-group label {
|
30
|
+
color: #07294D !important; /* Drexel Blue label text color */
|
31
|
+
}
|
32
|
+
|
33
|
+
/* Styling for CheckBoxGroup and RadioBoxGroup inputs */
|
34
|
+
.bk-input-group input[type="radio"] {
|
35
|
+
accent-color: #07294D !important; /* Drexel Blue accent for inputs */
|
36
|
+
}
|
37
|
+
|
38
|
+
input[type='checkbox']:checked {
|
39
|
+
accent-color: #07294D !important;
|
40
|
+
}
|
41
|
+
|
42
|
+
input[type='checkbox'] {
|
43
|
+
width: 16px;
|
44
|
+
height: 16px;
|
45
|
+
margin-right: 8px;
|
46
|
+
}
|
47
|
+
"""
|
@@ -0,0 +1,101 @@
|
|
1
|
+
from typing import Tuple
|
2
|
+
|
3
|
+
import panel as pn
|
4
|
+
|
5
|
+
from ..utils import list_of_lists
|
6
|
+
from ..widgets_base.select import SelectQuestion
|
7
|
+
from .style import drexel_colors, raw_css
|
8
|
+
|
9
|
+
import panel as pn
|
10
|
+
|
11
|
+
# Pass the custom CSS to Panel
|
12
|
+
pn.extension(design="material", global_css=[drexel_colors], raw_css=[raw_css])
|
13
|
+
|
14
|
+
#
|
15
|
+
# Style function
|
16
|
+
#
|
17
|
+
|
18
|
+
|
19
|
+
import panel as pn
|
20
|
+
from typing import List, Tuple
|
21
|
+
|
22
|
+
|
23
|
+
def TrueFalse_style(
|
24
|
+
descriptions: List[str],
|
25
|
+
options: List[str] | List[List[str]],
|
26
|
+
initial_vals: List[str],
|
27
|
+
) -> Tuple[List[pn.pane.HTML], List[pn.widgets.RadioBoxGroup]]:
|
28
|
+
"""
|
29
|
+
Creates a styled True/False question layout with descriptions and radio buttons.
|
30
|
+
|
31
|
+
Args:
|
32
|
+
descriptions (List[str]): List of question descriptions.
|
33
|
+
options (List[str] or List[List[str]]): List of options, either as a single list or list of lists.
|
34
|
+
initial_vals (List[str]): Initial selected values for each question.
|
35
|
+
|
36
|
+
Returns:
|
37
|
+
Tuple[List[pn.pane.HTML], List[pn.widgets.RadioBoxGroup]]: Styled description panes and radio button groups.
|
38
|
+
"""
|
39
|
+
desc_width = "100%" # Responsive width for descriptions
|
40
|
+
button_width = "100%" # Responsive width for radio buttons
|
41
|
+
|
42
|
+
# Create description widgets
|
43
|
+
desc_widgets = [
|
44
|
+
pn.pane.HTML(
|
45
|
+
f"""
|
46
|
+
<div style="text-align: left; width: {desc_width}; padding: 10px 0;">
|
47
|
+
<b>{desc}</b>
|
48
|
+
</div>
|
49
|
+
""",
|
50
|
+
sizing_mode="stretch_width",
|
51
|
+
)
|
52
|
+
for desc in descriptions
|
53
|
+
]
|
54
|
+
|
55
|
+
# Create radio button groups
|
56
|
+
radio_buttons = [
|
57
|
+
pn.widgets.RadioBoxGroup(
|
58
|
+
options=option,
|
59
|
+
value=value,
|
60
|
+
width_policy="max", # Automatically scales to fit content
|
61
|
+
sizing_mode="stretch_width", # Make width responsive
|
62
|
+
)
|
63
|
+
for value, option in zip(
|
64
|
+
initial_vals,
|
65
|
+
options if isinstance(options[0], list) else [options] * len(initial_vals),
|
66
|
+
)
|
67
|
+
]
|
68
|
+
|
69
|
+
return desc_widgets, radio_buttons
|
70
|
+
|
71
|
+
|
72
|
+
#
|
73
|
+
# Question class
|
74
|
+
#
|
75
|
+
|
76
|
+
class TFQuestion(SelectQuestion):
|
77
|
+
|
78
|
+
def __init__(
|
79
|
+
self,
|
80
|
+
title="Select if the statement is True or False",
|
81
|
+
style=TrueFalse_style,
|
82
|
+
question_number=2,
|
83
|
+
keys=["MC1", "MC2", "MC3", "MC4"],
|
84
|
+
options=None,
|
85
|
+
descriptions=[
|
86
|
+
"Which of the following stores key:value pairs?",
|
87
|
+
"The following condition returns to the next iteration of the loop",
|
88
|
+
"Which operator is used for exponentiation in Python?",
|
89
|
+
"Which method is used to add an element to the end of a list in Python?",
|
90
|
+
],
|
91
|
+
points=2,
|
92
|
+
):
|
93
|
+
super().__init__(
|
94
|
+
title=title,
|
95
|
+
style=style,
|
96
|
+
question_number=question_number,
|
97
|
+
keys=keys,
|
98
|
+
options=[["True", "False"] for _ in range(len(keys))],
|
99
|
+
descriptions=descriptions,
|
100
|
+
points=points,
|
101
|
+
)
|
@@ -1,9 +1,17 @@
|
|
1
1
|
from typing import Callable, Tuple
|
2
2
|
|
3
3
|
import panel as pn
|
4
|
+
import time
|
4
5
|
|
5
6
|
from ..telemetry import ensure_responses, update_responses
|
6
7
|
from ..utils import shuffle_questions
|
8
|
+
from ..widgets.style import drexel_colors, raw_css
|
9
|
+
|
10
|
+
# Pass the custom CSS to Panel
|
11
|
+
pn.extension(design="material", global_css=[drexel_colors], raw_css=[raw_css])
|
12
|
+
|
13
|
+
# Add the custom CSS to Panel
|
14
|
+
pn.config.raw_css.append(raw_css)
|
7
15
|
|
8
16
|
|
9
17
|
class MultiSelectQuestion:
|
@@ -50,7 +58,7 @@ class MultiSelectQuestion:
|
|
50
58
|
descriptions, options, self.initial_vals
|
51
59
|
)
|
52
60
|
|
53
|
-
self.submit_button = pn.widgets.Button(name="Submit")
|
61
|
+
self.submit_button = pn.widgets.Button(name="Submit", button_type="primary")
|
54
62
|
self.submit_button.on_click(self.submit)
|
55
63
|
|
56
64
|
widget_pairs = shuffle_questions(description_widgets, self.widgets, seed)
|
@@ -93,7 +101,9 @@ class MultiSelectQuestion:
|
|
93
101
|
for key, value in zip(self.keys, responses_flat):
|
94
102
|
update_responses(key, value)
|
95
103
|
|
96
|
-
|
104
|
+
self.submit_button.name = "Responses Submitted"
|
105
|
+
time.sleep(1)
|
106
|
+
self.submit_button.name = "Submit"
|
97
107
|
|
98
108
|
def show(self):
|
99
109
|
return self.layout
|
@@ -4,6 +4,12 @@ import panel as pn
|
|
4
4
|
|
5
5
|
from ..telemetry import ensure_responses, update_responses
|
6
6
|
from ..utils import shuffle_questions
|
7
|
+
from ..widgets.style import drexel_colors
|
8
|
+
import time
|
9
|
+
from IPython.display import update_display, display
|
10
|
+
|
11
|
+
# Pass the custom CSS to Panel
|
12
|
+
pn.extension(design="material", global_css=[drexel_colors])
|
7
13
|
|
8
14
|
|
9
15
|
class SelectQuestion:
|
@@ -66,7 +72,19 @@ class SelectQuestion:
|
|
66
72
|
for key, value in selections.items():
|
67
73
|
update_responses(key, value)
|
68
74
|
|
69
|
-
|
75
|
+
self.submit_button.name = "Responses Submitted"
|
76
|
+
time.sleep(1)
|
77
|
+
self.submit_button.name = "Submit"
|
78
|
+
|
79
|
+
# # Display the message with a unique display_id
|
80
|
+
# display_id = "temp_message"
|
81
|
+
# display("Responses recorded successfully", display_id=display_id)
|
82
|
+
|
83
|
+
# # Wait for 1 second
|
84
|
+
# time.sleep(1)
|
85
|
+
|
86
|
+
# # Update the display with an empty string to clear it
|
87
|
+
# update_display('', display_id=display_id)
|
70
88
|
|
71
89
|
def show(self):
|
72
90
|
return self.layout
|
@@ -1,20 +0,0 @@
|
|
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=5k-LoD3fTZYUOubRiTeQcVN5YDGK28x4Qb2l1aRVKzo,2181
|
16
|
-
PyKubeGrader-0.1.2.dist-info/LICENSE.txt,sha256=YTp-Ewc8Kems8PJEE27KnBPFnZSxoWvSg7nnknzPyYw,1546
|
17
|
-
PyKubeGrader-0.1.2.dist-info/METADATA,sha256=2S4jh--r5j8sNCgtk5YKn0ZHJ9OdvPmXDEZOu4a5VmI,2640
|
18
|
-
PyKubeGrader-0.1.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
19
|
-
PyKubeGrader-0.1.2.dist-info/top_level.txt,sha256=e550Klfze6higFxER1V62fnGOcIgiKRbsrl9CC4UdtQ,13
|
20
|
-
PyKubeGrader-0.1.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|