QuizGenerator 0.1.0__tar.gz → 0.1.1__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.
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/.gitignore +2 -1
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/PKG-INFO +1 -1
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/generate.py +20 -117
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/pyproject.toml +1 -1
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/uv.lock +0 -71
- quizgenerator-0.1.0/.gitmodules +0 -0
- quizgenerator-0.1.0/performance_test.py +0 -51
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/.envrc +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/.github/pull_request_template.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/CLAUDE.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/CODEOWNERS +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/LICENSE +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/README.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/__init__.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/__main__.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/canvas/__init__.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/canvas/canvas_interface.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/canvas/classes.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/constants.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/contentast.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/logging.yaml +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/misc.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/mixins.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/performance.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/__init__.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/basic.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst334/__init__.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst334/languages.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst334/math_questions.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst334/memory_questions.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst334/ostep13_vsfs.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst334/persistence_questions.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst334/process.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/__init__.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/gradient_descent/__init__.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/gradient_descent/misc.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/math_and_data/__init__.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/neural-network-basics/__init__.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/tensorflow-intro/__init__.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/qrcode_generator.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/question.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/quiz.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/typst_utils.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/README.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/documentation/GRADING_GUIDE.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/documentation/LESSONS_LEARNED-adding_questions.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/documentation/PARAMETER_STANDARDS.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/documentation/README.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/documentation/WEB_UI_INTEGRATION.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/documentation/claude_todo.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/documentation/custom_questions.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/documentation/pypi_release_plan.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/documentation/typst_integration_strategy.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/example_files/all_classes.yaml +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/example_files/cst334.yaml +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/example_files/cst463.yaml +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/example_files/exam_generation.yaml +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/example_files/scratch.yaml +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/example_files/specific_generators/cst334.caching.yaml +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/example_files/specific_generators/cst334.lab-address_translation.yaml +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/examples/README.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/examples/web_ui_integration_example.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/grade_from_qr.py +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/scripts/README.md +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/scripts/generate_practice_yaml.sh +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/scripts/print.sh +0 -0
- {quizgenerator-0.1.0 → quizgenerator-0.1.1}/scripts/vendor_lms_interface.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: QuizGenerator
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Generate randomized quiz questions for Canvas LMS and PDF exams
|
|
5
5
|
Project-URL: Homepage, https://github.com/OtterDen-Lab/QuizGenerator
|
|
6
6
|
Project-URL: Documentation, https://github.com/OtterDen-Lab/QuizGenerator/tree/main/documentation
|
|
@@ -7,13 +7,10 @@ import subprocess
|
|
|
7
7
|
import tempfile
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from dotenv import load_dotenv
|
|
10
|
-
from QuizGenerator.canvas.canvas_interface import CanvasInterface
|
|
10
|
+
from QuizGenerator.canvas.canvas_interface import CanvasInterface
|
|
11
11
|
|
|
12
12
|
from QuizGenerator.quiz import Quiz
|
|
13
13
|
|
|
14
|
-
# Load environment variables from ~/.env
|
|
15
|
-
load_dotenv(Path.home() / '.env')
|
|
16
|
-
|
|
17
14
|
import logging
|
|
18
15
|
log = logging.getLogger(__name__)
|
|
19
16
|
|
|
@@ -23,20 +20,27 @@ from QuizGenerator.performance import PerformanceTracker
|
|
|
23
20
|
def parse_args():
|
|
24
21
|
parser = argparse.ArgumentParser()
|
|
25
22
|
|
|
26
|
-
parser.add_argument(
|
|
27
|
-
|
|
23
|
+
parser.add_argument(
|
|
24
|
+
"--env",
|
|
25
|
+
default=os.path.join(Path.home(), '.env'),
|
|
26
|
+
help="Path to .env file specifying canvas details"
|
|
27
|
+
)
|
|
28
28
|
|
|
29
29
|
parser.add_argument("--quiz_yaml", default=os.path.join(os.path.dirname(os.path.abspath(__file__)), "example_files/exam_generation.yaml"))
|
|
30
|
-
parser.add_argument("--num_canvas", default=0, type=int)
|
|
31
|
-
parser.add_argument("--num_pdfs", default=0, type=int)
|
|
32
30
|
parser.add_argument("--seed", type=int, default=None,
|
|
33
31
|
help="Random seed for quiz generation (default: None for random)")
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
parser.add_argument("--
|
|
37
|
-
|
|
32
|
+
|
|
33
|
+
# Canvas flags
|
|
34
|
+
parser.add_argument("--num_canvas", default=0, type=int, help="How many variations of each question to try to upload to canvas.")
|
|
35
|
+
parser.add_argument("--prod", action="store_true")
|
|
36
|
+
parser.add_argument("--course_id", type=int)
|
|
38
37
|
parser.add_argument("--delete-assignment-group", action="store_true",
|
|
39
38
|
help="Delete existing assignment group before uploading new quizzes")
|
|
39
|
+
|
|
40
|
+
# PDF Flags
|
|
41
|
+
parser.add_argument("--num_pdfs", default=0, type=int, help="How many PDF quizzes to create")
|
|
42
|
+
parser.add_argument("--typst", action="store_true",
|
|
43
|
+
help="Use Typst instead of LaTeX for PDF generation")
|
|
40
44
|
|
|
41
45
|
subparsers = parser.add_subparsers(dest='command')
|
|
42
46
|
test_parser = subparsers.add_parser("TEST")
|
|
@@ -54,111 +58,6 @@ def parse_args():
|
|
|
54
58
|
def test():
|
|
55
59
|
log.info("Running test...")
|
|
56
60
|
|
|
57
|
-
# Load the CST463 quiz configuration to test vector questions
|
|
58
|
-
quiz_yaml = os.path.join(os.path.dirname(os.path.abspath(__file__)), "example_files/cst463.yaml")
|
|
59
|
-
|
|
60
|
-
# Generate a quiz
|
|
61
|
-
quizzes = Quiz.from_yaml(quiz_yaml)
|
|
62
|
-
|
|
63
|
-
# Find a vector question to test
|
|
64
|
-
from QuizGenerator.question import QuestionRegistry
|
|
65
|
-
|
|
66
|
-
print("="*60)
|
|
67
|
-
print("CANVAS ANSWER DUPLICATION TEST")
|
|
68
|
-
print("="*60)
|
|
69
|
-
|
|
70
|
-
# Test multiple question types to find which ones use VECTOR variable kind
|
|
71
|
-
question_types = ["VectorAddition", "VectorDotProduct", "VectorMagnitude", "DerivativeBasic", "DerivativeChain"]
|
|
72
|
-
|
|
73
|
-
for question_type in question_types:
|
|
74
|
-
print(f"\n" + "="*20 + f" TESTING {question_type} " + "="*20)
|
|
75
|
-
question = QuestionRegistry.create(question_type, name=f"Test {question_type}", points_value=1)
|
|
76
|
-
|
|
77
|
-
print(f"Question answers: {len(question.answers)} answer objects")
|
|
78
|
-
|
|
79
|
-
# Show all individual answers and their Canvas representations
|
|
80
|
-
for key, answer in question.answers.items():
|
|
81
|
-
canvas_answers = answer.get_for_canvas()
|
|
82
|
-
print(f"\nAnswer key '{key}':")
|
|
83
|
-
print(f" Variable kind: {answer.variable_kind}")
|
|
84
|
-
print(f" Value: {answer.value}")
|
|
85
|
-
print(f" Canvas entries: {len(canvas_answers)}")
|
|
86
|
-
for i, canvas_answer in enumerate(canvas_answers):
|
|
87
|
-
print(f" {i+1}: '{canvas_answer['answer_text']}'")
|
|
88
|
-
|
|
89
|
-
# Show duplicates if they exist
|
|
90
|
-
texts = [ca['answer_text'] for ca in canvas_answers]
|
|
91
|
-
unique_texts = set(texts)
|
|
92
|
-
duplicates = len(texts) - len(unique_texts)
|
|
93
|
-
if duplicates > 0:
|
|
94
|
-
print(f" *** {duplicates} DUPLICATE ENTRIES FOUND ***")
|
|
95
|
-
for text in sorted(unique_texts):
|
|
96
|
-
count = texts.count(text)
|
|
97
|
-
if count > 1:
|
|
98
|
-
print(f" '{text}' appears {count} times")
|
|
99
|
-
|
|
100
|
-
# Check for phantom blank_ids that aren't displayed
|
|
101
|
-
print(f"\n" + "="*20 + " PHANTOM BLANK_ID CHECK " + "="*20)
|
|
102
|
-
|
|
103
|
-
for question_type in ["DerivativeBasic", "DerivativeChain"]:
|
|
104
|
-
print(f"\n--- {question_type} ---")
|
|
105
|
-
question = QuestionRegistry.create(question_type, name=f"Test {question_type}", points_value=1)
|
|
106
|
-
|
|
107
|
-
# Get the question body to see what blank_ids are actually displayed
|
|
108
|
-
body = question.get_body()
|
|
109
|
-
body_html = body.render("html")
|
|
110
|
-
|
|
111
|
-
print(f" HTML body preview:")
|
|
112
|
-
print(f" {body_html[:200]}...")
|
|
113
|
-
|
|
114
|
-
# Extract blank_ids from the HTML using regex
|
|
115
|
-
import re
|
|
116
|
-
displayed_blank_ids = set(re.findall(r'name="([^"]*)"', body_html))
|
|
117
|
-
|
|
118
|
-
# Get all blank_ids from the answers
|
|
119
|
-
question_type_enum, canvas_answers = question.get_answers()
|
|
120
|
-
all_blank_ids = set(answer['blank_id'] for answer in canvas_answers)
|
|
121
|
-
|
|
122
|
-
print(f" Total answers in self.answers: {len(question.answers)}")
|
|
123
|
-
print(f" Total Canvas answer entries: {len(canvas_answers)}")
|
|
124
|
-
print(f" Unique blank_ids in Canvas answers: {len(all_blank_ids)}")
|
|
125
|
-
print(f" Blank_ids displayed in HTML: {len(displayed_blank_ids)}")
|
|
126
|
-
|
|
127
|
-
# Find phantom blank_ids
|
|
128
|
-
phantom_blank_ids = all_blank_ids - displayed_blank_ids
|
|
129
|
-
if phantom_blank_ids:
|
|
130
|
-
print(f" *** PHANTOM BLANK_IDS FOUND: {phantom_blank_ids} ***")
|
|
131
|
-
for phantom_id in phantom_blank_ids:
|
|
132
|
-
phantom_answers = [a for a in canvas_answers if a['blank_id'] == phantom_id]
|
|
133
|
-
print(f" '{phantom_id}': {len(phantom_answers)} entries not displayed")
|
|
134
|
-
else:
|
|
135
|
-
print(f" No phantom blank_ids found")
|
|
136
|
-
|
|
137
|
-
# Show what blank_ids are actually displayed
|
|
138
|
-
print(f" Displayed blank_ids: {sorted(displayed_blank_ids)}")
|
|
139
|
-
print(f" All answer blank_ids: {sorted(all_blank_ids)}")
|
|
140
|
-
|
|
141
|
-
# Now create a synthetic test to demonstrate the VECTOR bug
|
|
142
|
-
print(f"\n" + "="*20 + " SYNTHETIC VECTOR TEST " + "="*20)
|
|
143
|
-
from QuizGenerator.misc import Answer
|
|
144
|
-
|
|
145
|
-
# Create a synthetic answer with VECTOR variable kind to demonstrate the bug
|
|
146
|
-
vector_answer = Answer(
|
|
147
|
-
key="test_vector",
|
|
148
|
-
value=[1, 2, 3], # 3D vector
|
|
149
|
-
variable_kind=Answer.VariableKind.VECTOR
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
canvas_answers = vector_answer.get_for_canvas()
|
|
153
|
-
print(f"Synthetic VECTOR answer:")
|
|
154
|
-
print(f" Value: {vector_answer.value}")
|
|
155
|
-
print(f" Canvas entries: {len(canvas_answers)}")
|
|
156
|
-
# Only show first few to save space
|
|
157
|
-
for i, canvas_answer in enumerate(canvas_answers[:5]):
|
|
158
|
-
print(f" {i+1}: '{canvas_answer['answer_text']}'")
|
|
159
|
-
if len(canvas_answers) > 5:
|
|
160
|
-
print(f" ... and {len(canvas_answers) - 5} more entries")
|
|
161
|
-
|
|
162
61
|
print("\n" + "="*60)
|
|
163
62
|
print("TEST COMPLETE")
|
|
164
63
|
print("="*60)
|
|
@@ -245,6 +144,7 @@ def generate_typst(typst_text, remove_previous=False):
|
|
|
245
144
|
if os.path.exists(tmp_typ.name):
|
|
246
145
|
os.unlink(tmp_typ.name)
|
|
247
146
|
|
|
147
|
+
|
|
248
148
|
def generate_quiz(
|
|
249
149
|
path_to_quiz_yaml,
|
|
250
150
|
num_pdfs=0,
|
|
@@ -337,6 +237,9 @@ def generate_quiz(
|
|
|
337
237
|
def main():
|
|
338
238
|
|
|
339
239
|
args = parse_args()
|
|
240
|
+
|
|
241
|
+
# Load environment variables
|
|
242
|
+
load_dotenv(args.env)
|
|
340
243
|
|
|
341
244
|
if args.command == "TEST":
|
|
342
245
|
test()
|
|
@@ -158,15 +158,6 @@ wheels = [
|
|
|
158
158
|
{ url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" },
|
|
159
159
|
]
|
|
160
160
|
|
|
161
|
-
[[package]]
|
|
162
|
-
name = "colorama"
|
|
163
|
-
version = "0.4.6"
|
|
164
|
-
source = { registry = "https://pypi.org/simple" }
|
|
165
|
-
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
|
166
|
-
wheels = [
|
|
167
|
-
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
|
168
|
-
]
|
|
169
|
-
|
|
170
161
|
[[package]]
|
|
171
162
|
name = "contourpy"
|
|
172
163
|
version = "1.3.3"
|
|
@@ -352,15 +343,6 @@ wheels = [
|
|
|
352
343
|
{ url = "https://files.pythonhosted.org/packages/c7/93/0dd45cd283c32dea1545151d8c3637b4b8c53cdb3a625aeb2885b184d74d/fonttools-4.60.1-py3-none-any.whl", hash = "sha256:906306ac7afe2156fcf0042173d6ebbb05416af70f6b370967b47f8f00103bbb", size = 1143175, upload-time = "2025-09-29T21:13:24.134Z" },
|
|
353
344
|
]
|
|
354
345
|
|
|
355
|
-
[[package]]
|
|
356
|
-
name = "fuzzywuzzy"
|
|
357
|
-
version = "0.18.0"
|
|
358
|
-
source = { registry = "https://pypi.org/simple" }
|
|
359
|
-
sdist = { url = "https://files.pythonhosted.org/packages/11/4b/0a002eea91be6048a2b5d53c5f1b4dafd57ba2e36eea961d05086d7c28ce/fuzzywuzzy-0.18.0.tar.gz", hash = "sha256:45016e92264780e58972dca1b3d939ac864b78437422beecebb3095f8efd00e8", size = 28888, upload-time = "2020-02-13T21:06:27.054Z" }
|
|
360
|
-
wheels = [
|
|
361
|
-
{ url = "https://files.pythonhosted.org/packages/43/ff/74f23998ad2f93b945c0309f825be92e04e0348e062026998b5eefef4c33/fuzzywuzzy-0.18.0-py2.py3-none-any.whl", hash = "sha256:928244b28db720d1e0ee7587acf660ea49d7e4c632569cad4f1cd7e68a5f0993", size = 18272, upload-time = "2020-02-13T21:06:25.209Z" },
|
|
362
|
-
]
|
|
363
|
-
|
|
364
346
|
[[package]]
|
|
365
347
|
name = "graphviz"
|
|
366
348
|
version = "0.21"
|
|
@@ -691,53 +673,6 @@ wheels = [
|
|
|
691
673
|
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
|
|
692
674
|
]
|
|
693
675
|
|
|
694
|
-
[[package]]
|
|
695
|
-
name = "pandas"
|
|
696
|
-
version = "2.3.3"
|
|
697
|
-
source = { registry = "https://pypi.org/simple" }
|
|
698
|
-
dependencies = [
|
|
699
|
-
{ name = "numpy" },
|
|
700
|
-
{ name = "python-dateutil" },
|
|
701
|
-
{ name = "pytz" },
|
|
702
|
-
{ name = "tzdata" },
|
|
703
|
-
]
|
|
704
|
-
sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" }
|
|
705
|
-
wheels = [
|
|
706
|
-
{ url = "https://files.pythonhosted.org/packages/9c/fb/231d89e8637c808b997d172b18e9d4a4bc7bf31296196c260526055d1ea0/pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53", size = 11597846, upload-time = "2025-09-29T23:19:48.856Z" },
|
|
707
|
-
{ url = "https://files.pythonhosted.org/packages/5c/bd/bf8064d9cfa214294356c2d6702b716d3cf3bb24be59287a6a21e24cae6b/pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35", size = 10729618, upload-time = "2025-09-29T23:39:08.659Z" },
|
|
708
|
-
{ url = "https://files.pythonhosted.org/packages/57/56/cf2dbe1a3f5271370669475ead12ce77c61726ffd19a35546e31aa8edf4e/pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908", size = 11737212, upload-time = "2025-09-29T23:19:59.765Z" },
|
|
709
|
-
{ url = "https://files.pythonhosted.org/packages/e5/63/cd7d615331b328e287d8233ba9fdf191a9c2d11b6af0c7a59cfcec23de68/pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89", size = 12362693, upload-time = "2025-09-29T23:20:14.098Z" },
|
|
710
|
-
{ url = "https://files.pythonhosted.org/packages/a6/de/8b1895b107277d52f2b42d3a6806e69cfef0d5cf1d0ba343470b9d8e0a04/pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98", size = 12771002, upload-time = "2025-09-29T23:20:26.76Z" },
|
|
711
|
-
{ url = "https://files.pythonhosted.org/packages/87/21/84072af3187a677c5893b170ba2c8fbe450a6ff911234916da889b698220/pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084", size = 13450971, upload-time = "2025-09-29T23:20:41.344Z" },
|
|
712
|
-
{ url = "https://files.pythonhosted.org/packages/86/41/585a168330ff063014880a80d744219dbf1dd7a1c706e75ab3425a987384/pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b", size = 10992722, upload-time = "2025-09-29T23:20:54.139Z" },
|
|
713
|
-
{ url = "https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", size = 11544671, upload-time = "2025-09-29T23:21:05.024Z" },
|
|
714
|
-
{ url = "https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", size = 10680807, upload-time = "2025-09-29T23:21:15.979Z" },
|
|
715
|
-
{ url = "https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", size = 11709872, upload-time = "2025-09-29T23:21:27.165Z" },
|
|
716
|
-
{ url = "https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", size = 12306371, upload-time = "2025-09-29T23:21:40.532Z" },
|
|
717
|
-
{ url = "https://files.pythonhosted.org/packages/33/81/a3afc88fca4aa925804a27d2676d22dcd2031c2ebe08aabd0ae55b9ff282/pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", size = 12765333, upload-time = "2025-09-29T23:21:55.77Z" },
|
|
718
|
-
{ url = "https://files.pythonhosted.org/packages/8d/0f/b4d4ae743a83742f1153464cf1a8ecfafc3ac59722a0b5c8602310cb7158/pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", size = 13418120, upload-time = "2025-09-29T23:22:10.109Z" },
|
|
719
|
-
{ url = "https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee", size = 10993991, upload-time = "2025-09-29T23:25:04.889Z" },
|
|
720
|
-
{ url = "https://files.pythonhosted.org/packages/f9/ca/3f8d4f49740799189e1395812f3bf23b5e8fc7c190827d55a610da72ce55/pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", size = 12048227, upload-time = "2025-09-29T23:22:24.343Z" },
|
|
721
|
-
{ url = "https://files.pythonhosted.org/packages/0e/5a/f43efec3e8c0cc92c4663ccad372dbdff72b60bdb56b2749f04aa1d07d7e/pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", size = 11411056, upload-time = "2025-09-29T23:22:37.762Z" },
|
|
722
|
-
{ url = "https://files.pythonhosted.org/packages/46/b1/85331edfc591208c9d1a63a06baa67b21d332e63b7a591a5ba42a10bb507/pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", size = 11645189, upload-time = "2025-09-29T23:22:51.688Z" },
|
|
723
|
-
{ url = "https://files.pythonhosted.org/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", size = 12121912, upload-time = "2025-09-29T23:23:05.042Z" },
|
|
724
|
-
{ url = "https://files.pythonhosted.org/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", size = 12712160, upload-time = "2025-09-29T23:23:28.57Z" },
|
|
725
|
-
{ url = "https://files.pythonhosted.org/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", size = 13199233, upload-time = "2025-09-29T23:24:24.876Z" },
|
|
726
|
-
{ url = "https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", size = 11540635, upload-time = "2025-09-29T23:25:52.486Z" },
|
|
727
|
-
{ url = "https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", size = 10759079, upload-time = "2025-09-29T23:26:33.204Z" },
|
|
728
|
-
{ url = "https://files.pythonhosted.org/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", size = 11814049, upload-time = "2025-09-29T23:27:15.384Z" },
|
|
729
|
-
{ url = "https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", size = 12332638, upload-time = "2025-09-29T23:27:51.625Z" },
|
|
730
|
-
{ url = "https://files.pythonhosted.org/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", size = 12886834, upload-time = "2025-09-29T23:28:21.289Z" },
|
|
731
|
-
{ url = "https://files.pythonhosted.org/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", size = 13409925, upload-time = "2025-09-29T23:28:58.261Z" },
|
|
732
|
-
{ url = "https://files.pythonhosted.org/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", size = 11109071, upload-time = "2025-09-29T23:32:27.484Z" },
|
|
733
|
-
{ url = "https://files.pythonhosted.org/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", size = 12048504, upload-time = "2025-09-29T23:29:31.47Z" },
|
|
734
|
-
{ url = "https://files.pythonhosted.org/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", size = 11410702, upload-time = "2025-09-29T23:29:54.591Z" },
|
|
735
|
-
{ url = "https://files.pythonhosted.org/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", size = 11634535, upload-time = "2025-09-29T23:30:21.003Z" },
|
|
736
|
-
{ url = "https://files.pythonhosted.org/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", size = 12121582, upload-time = "2025-09-29T23:30:43.391Z" },
|
|
737
|
-
{ url = "https://files.pythonhosted.org/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", size = 12699963, upload-time = "2025-09-29T23:31:10.009Z" },
|
|
738
|
-
{ url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" },
|
|
739
|
-
]
|
|
740
|
-
|
|
741
676
|
[[package]]
|
|
742
677
|
name = "pathvalidate"
|
|
743
678
|
version = "3.3.1"
|
|
@@ -942,14 +877,11 @@ version = "0.1.0"
|
|
|
942
877
|
source = { editable = "." }
|
|
943
878
|
dependencies = [
|
|
944
879
|
{ name = "canvasapi" },
|
|
945
|
-
{ name = "colorama" },
|
|
946
880
|
{ name = "cryptography" },
|
|
947
|
-
{ name = "fuzzywuzzy" },
|
|
948
881
|
{ name = "graphviz" },
|
|
949
882
|
{ name = "jinja2" },
|
|
950
883
|
{ name = "markdown" },
|
|
951
884
|
{ name = "matplotlib" },
|
|
952
|
-
{ name = "pandas" },
|
|
953
885
|
{ name = "pylatex" },
|
|
954
886
|
{ name = "pypandoc" },
|
|
955
887
|
{ name = "pytablewriter" },
|
|
@@ -969,14 +901,11 @@ grading = [
|
|
|
969
901
|
[package.metadata]
|
|
970
902
|
requires-dist = [
|
|
971
903
|
{ name = "canvasapi", specifier = "==3.2.0" },
|
|
972
|
-
{ name = "colorama" },
|
|
973
904
|
{ name = "cryptography", specifier = ">=41.0.0" },
|
|
974
|
-
{ name = "fuzzywuzzy" },
|
|
975
905
|
{ name = "graphviz", specifier = ">=0.21" },
|
|
976
906
|
{ name = "jinja2", specifier = "==3.1.3" },
|
|
977
907
|
{ name = "markdown", specifier = ">=3.9" },
|
|
978
908
|
{ name = "matplotlib" },
|
|
979
|
-
{ name = "pandas" },
|
|
980
909
|
{ name = "pillow", marker = "extra == 'grading'", specifier = ">=10.0.0" },
|
|
981
910
|
{ name = "pylatex", specifier = ">=1.4.2" },
|
|
982
911
|
{ name = "pypandoc", specifier = "~=1.6.3" },
|
quizgenerator-0.1.0/.gitmodules
DELETED
|
File without changes
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
|
-
"""
|
|
3
|
-
Test script to exercise the performance instrumentation system without
|
|
4
|
-
actually uploading to Canvas.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from QuizGenerator.quiz import Quiz
|
|
8
|
-
from QuizGenerator.performance import PerformanceTracker
|
|
9
|
-
|
|
10
|
-
def test_performance_instrumentation():
|
|
11
|
-
print("Testing performance instrumentation...")
|
|
12
|
-
|
|
13
|
-
# Clear any previous metrics
|
|
14
|
-
PerformanceTracker.clear_metrics()
|
|
15
|
-
|
|
16
|
-
# Load a quiz
|
|
17
|
-
quizzes = Quiz.from_yaml("example_files/scratch.yaml")
|
|
18
|
-
quiz = quizzes[0]
|
|
19
|
-
|
|
20
|
-
# Generate some questions to exercise the timing code
|
|
21
|
-
print("Generating questions...")
|
|
22
|
-
for i in range(3):
|
|
23
|
-
print(f" Generating question {i+1}/3")
|
|
24
|
-
quiz_doc = quiz.get_quiz(rng_seed=i)
|
|
25
|
-
|
|
26
|
-
# Render to HTML (to exercise AST rendering)
|
|
27
|
-
for element in quiz_doc.elements:
|
|
28
|
-
if hasattr(element, 'body'):
|
|
29
|
-
element.body.render("html")
|
|
30
|
-
if hasattr(element, 'explanation'):
|
|
31
|
-
element.explanation.render("html")
|
|
32
|
-
|
|
33
|
-
# Generate performance report
|
|
34
|
-
print("\n" + "="*80)
|
|
35
|
-
print("PERFORMANCE TEST REPORT")
|
|
36
|
-
print("="*80)
|
|
37
|
-
|
|
38
|
-
metrics = PerformanceTracker.get_metrics()
|
|
39
|
-
print(f"Total metrics recorded: {len(metrics)}")
|
|
40
|
-
|
|
41
|
-
if metrics:
|
|
42
|
-
PerformanceTracker.report_summary(min_duration=0.001)
|
|
43
|
-
|
|
44
|
-
print("\nDetailed breakdown:")
|
|
45
|
-
for metric in metrics[:10]: # Show first 10 metrics
|
|
46
|
-
print(f" {metric.operation}: {metric.duration:.4f}s ({metric.question_name}, {metric.question_type})")
|
|
47
|
-
else:
|
|
48
|
-
print("No metrics recorded. This suggests the instrumentation may not be working.")
|
|
49
|
-
|
|
50
|
-
if __name__ == "__main__":
|
|
51
|
-
test_performance_instrumentation()
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst334/__init__.py
RENAMED
|
File without changes
|
{quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst334/languages.py
RENAMED
|
File without changes
|
{quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst334/math_questions.py
RENAMED
|
File without changes
|
|
File without changes
|
{quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst334/ostep13_vsfs.py
RENAMED
|
File without changes
|
|
File without changes
|
{quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst334/process.py
RENAMED
|
File without changes
|
{quizgenerator-0.1.0 → quizgenerator-0.1.1}/QuizGenerator/premade_questions/cst463/__init__.py
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quizgenerator-0.1.0 → quizgenerator-0.1.1}/documentation/LESSONS_LEARNED-adding_questions.md
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
{quizgenerator-0.1.0 → quizgenerator-0.1.1}/example_files/specific_generators/cst334.caching.yaml
RENAMED
|
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
|