rapid-router 5.18.0__py2.py3-none-any.whl → 7.6.8__py2.py3-none-any.whl
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.
- example_project/rapid_router_test_settings.py +19 -7
- example_project/settings.py +21 -8
- example_project/urls.py +5 -6
- game/__init__.py +1 -1
- game/admin.py +7 -2
- game/character.py +8 -0
- game/decor.py +40 -0
- game/end_to_end_tests/base_game_test.py +34 -27
- game/end_to_end_tests/editor_page.py +15 -0
- game/end_to_end_tests/game_page.py +88 -20
- game/end_to_end_tests/selenium_test_case.py +1 -20
- game/end_to_end_tests/test_cow_crashes.py +3 -5
- game/end_to_end_tests/test_level_editor.py +273 -10
- game/end_to_end_tests/test_level_selection.py +25 -3
- game/end_to_end_tests/test_play_through.py +222 -127
- game/end_to_end_tests/test_python_levels.py +41 -7
- game/end_to_end_tests/test_saving_workspace.py +2 -1
- game/forms.py +7 -1
- game/level_management.py +26 -11
- game/messages.py +899 -337
- game/migrations/0001_squashed_0025_levels_ordering_pt1.py +19 -1
- game/migrations/0026_levels_pt2.py +13 -2
- game/migrations/0032_cannot_turn_left_level.py +13 -2
- game/migrations/0033_recursion_level.py +13 -2
- game/migrations/0034_joes_level.py +13 -2
- game/migrations/0035_disable_route_score_level_70.py +0 -2
- game/migrations/0036_level_score_73.py +0 -2
- game/migrations/0037_level_score_79.py +0 -2
- game/migrations/0038_level_score_40.py +0 -1
- game/migrations/0042_level_score_73.py +0 -2
- game/migrations/0048_add_cow_field_and_blocks.py +0 -2
- game/migrations/0049_level_score_34.py +0 -2
- game/migrations/0050_level_score_40.py +0 -2
- game/migrations/0051_level_score_49.py +0 -1
- game/migrations/0086_loop_levels.py +13 -2
- game/migrations/0092_disable_algo_score_in_custom_levels.py +28 -0
- game/migrations/0093_alter_level_character_name.py +18 -0
- game/migrations/0094_add_hint_lesson_subtitle_to_levels.py +28 -0
- game/migrations/0095_level_commands.py +18 -0
- game/migrations/0096_alter_level_commands.py +18 -0
- game/migrations/0097_add_python_den_levels.py +1515 -0
- game/migrations/0098_add_episode_link_fields.py +44 -0
- game/migrations/0099_python_episodes_links.py +103 -0
- game/migrations/0100_reorder_python_levels.py +179 -0
- game/migrations/0101_rename_episodes.py +45 -0
- game/migrations/0102_reoder_episodes_13_14.py +136 -0
- game/migrations/0103_level_1015_solution.py +26 -0
- game/migrations/0104_remove_level_direct_drive.py +17 -0
- game/migrations/0105_delete_invalid_attempts.py +18 -0
- game/migrations/0106_fields_to_snake_case.py +48 -0
- game/migrations/0107_rename_worksheet_link_episode_student_worksheet_link.py +18 -0
- game/migrations/0108_episode_indy_worksheet_link.py +18 -0
- game/migrations/0109_create_episodes_23_and_24.py +99 -0
- game/migrations/0110_remove_episode_indy_worksheet_link_and_more.py +100 -0
- game/migrations/0111_create_worksheets.py +149 -0
- game/migrations/0112_worksheet_locked_classes.py +21 -0
- game/migrations/0113_level_needs_approval.py +18 -0
- game/migrations/0114_default_and_non_student_levels_no_approval.py +31 -0
- game/migrations/0115_level_level__default_does_not_need_approval.py +22 -0
- game/migrations/0116_update_worksheet_video_links.py +68 -0
- game/migrations/0117_update_solutions_to_if_else.py +61 -0
- game/models.py +127 -17
- game/permissions.py +51 -19
- game/python_den_urls.py +26 -0
- game/random_road.py +9 -9
- game/serializers.py +12 -17
- game/static/django_reverse_js/js/reverse.js +171 -0
- game/static/game/css/LilitaOne-Regular.ttf +0 -0
- game/static/game/css/backgrounds.css +8 -12
- game/static/game/css/dataTables.custom.css +3 -2
- game/static/game/css/editor.css +47 -0
- game/static/game/css/game.css +37 -43
- game/static/game/css/game_screen.css +16 -0
- game/static/game/css/level_editor.css +5 -0
- game/static/game/css/level_selection.css +17 -2
- game/static/game/image/Python_Den_hero_student.png +0 -0
- game/static/game/image/Python_levels_page.svg +1954 -0
- game/static/game/image/characters/front_view/Electric_van.svg +448 -0
- game/static/game/image/characters/top_view/Electric_van.svg +448 -0
- game/static/game/image/decor/city/solar_panel.svg +1200 -0
- game/static/game/image/decor/farm/solar_panel.svg +86 -0
- game/static/game/image/decor/grass/solar_panel.svg +86 -0
- game/static/game/image/decor/snow/solar_panel.svg +173 -0
- game/static/game/image/electric_van.svg +448 -0
- game/static/game/image/icons/description.svg +1 -0
- game/static/game/image/icons/hint.svg +1 -0
- game/static/game/image/icons/python.svg +1 -1
- game/static/game/image/pigeon.svg +684 -0
- game/static/game/image/python_den_header.svg +19 -0
- game/static/game/js/animation.js +65 -24
- game/static/game/js/blockly/msg/js/bg.js +52 -1
- game/static/game/js/blockly/msg/js/ca.js +52 -1
- game/static/game/js/blockly/msg/js/en-gb.js +2 -0
- game/static/game/js/blockly/msg/js/en.js +2 -0
- game/static/game/js/blockly/msg/js/es.js +52 -1
- game/static/game/js/blockly/msg/js/fr.js +2 -0
- game/static/game/js/blockly/msg/js/hi.js +2 -0
- game/static/game/js/blockly/msg/js/it.js +52 -1
- game/static/game/js/blockly/msg/js/pl.js +52 -1
- game/static/game/js/blockly/msg/js/pt-br.js +52 -1
- game/static/game/js/blockly/msg/js/ru.js +52 -1
- game/static/game/js/blockly/msg/js/ur.js +52 -1
- game/static/game/js/blocklyCustomBlocks.js +93 -52
- game/static/game/js/button.js +12 -0
- game/static/game/js/cow.js +11 -7
- game/static/game/js/drawing.js +68 -29
- game/static/game/js/editor.js +23 -0
- game/static/game/js/game.js +74 -110
- game/static/game/js/level_editor.js +646 -274
- game/static/game/js/level_moderation.js +33 -2
- game/static/game/js/level_selection.js +1 -1
- game/static/game/js/loadLanguages.js +2 -2
- game/static/game/js/model.js +32 -2
- game/static/game/js/pythonControl.js +14 -1
- game/static/game/js/scoreboard.js +0 -37
- game/static/game/js/scoreboardSharedLevels.js +48 -0
- game/static/game/js/skulpt/skulpt-stdlib.js +1 -1
- game/static/game/js/sound.js +52 -5
- game/static/game/raphael_image/characters/top_view/Electric_van.svg +448 -0
- game/static/game/raphael_image/decor/city/solar_panel.svg +1200 -0
- game/static/game/raphael_image/decor/farm/solar_panel.svg +86 -0
- game/static/game/raphael_image/decor/grass/solar_panel.svg +86 -0
- game/static/game/raphael_image/decor/snow/solar_panel.svg +173 -0
- game/static/game/raphael_image/pigeon.svg +685 -0
- game/static/game/sass/game.scss +2 -2
- game/static/game/sound/clown_horn.mp3 +0 -0
- game/static/game/sound/clown_horn.ogg +0 -0
- game/static/game/sound/electric_van_starting.mp3 +0 -0
- game/static/game/sound/electric_van_starting.ogg +0 -0
- game/static/game/sound/pigeon.mp3 +0 -0
- game/static/game/sound/pigeon.ogg +0 -0
- game/static/game/sound/sleigh_bells.mp3 +0 -0
- game/static/game/sound/sleigh_bells.ogg +0 -0
- game/static/game/sound/sleigh_crash.mp3 +0 -0
- game/static/game/sound/sleigh_crash.ogg +0 -0
- game/templates/game/base.html +34 -14
- game/templates/game/basenonav.html +11 -5
- game/templates/game/game.html +142 -38
- game/templates/game/level_editor.html +340 -236
- game/templates/game/level_moderation.html +19 -6
- game/templates/game/level_selection.html +18 -110
- game/templates/game/python_den_level_selection.html +291 -0
- game/templates/game/python_den_worksheet.html +101 -0
- game/templates/game/scoreboard.html +83 -64
- game/tests/test_level_editor.py +94 -26
- game/tests/test_level_selection.py +149 -46
- game/tests/test_python_den_worksheet.py +85 -0
- game/tests/test_scoreboard.py +34 -7
- game/tests/utils/level.py +32 -26
- game/theme.py +5 -5
- game/urls.py +199 -61
- game/views/language_code_conversions.py +86 -86
- game/views/level.py +155 -63
- game/views/level_editor.py +88 -55
- game/views/level_moderation.py +23 -0
- game/views/level_selection.py +116 -47
- game/views/level_solutions.py +491 -106
- game/views/scoreboard.py +76 -51
- game/views/worksheet.py +25 -0
- rapid_router-7.6.8.dist-info/METADATA +174 -0
- {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info}/RECORD +164 -104
- {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info}/WHEEL +1 -1
- example_project/manage.py +0 -10
- game/static/game/image/actions/go.svg +0 -18
- game/static/game/js/js-reverse.js +0 -14
- game/static/game/js/pqselect.min.js +0 -9
- game/static/game/js/widget-scroller.js +0 -906
- rapid_router-5.18.0.dist-info/METADATA +0 -17
- {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info/licenses}/LICENSE.md +0 -0
- {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info}/top_level.txt +0 -0
game/views/scoreboard.py
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
from __future__ import absolute_import
|
|
2
|
-
from __future__ import division
|
|
1
|
+
from __future__ import absolute_import, division
|
|
3
2
|
|
|
4
|
-
from builtins import map
|
|
5
|
-
from builtins import next
|
|
6
|
-
from builtins import object
|
|
3
|
+
from builtins import map, next, object
|
|
7
4
|
from datetime import timedelta
|
|
8
5
|
|
|
9
6
|
from common.models import Class, Teacher, Student
|
|
@@ -99,7 +96,7 @@ def student_row(levels_sorted, student, best_attempts):
|
|
|
99
96
|
total_possible_score += max_score
|
|
100
97
|
|
|
101
98
|
elapsed_time = attempt.elapsed_time()
|
|
102
|
-
times.append(
|
|
99
|
+
times.append(chop_milliseconds(elapsed_time))
|
|
103
100
|
# '-' is used to show that the student has started the level but has not submitted any attempts
|
|
104
101
|
|
|
105
102
|
level_scores[level.id]["score"] = (
|
|
@@ -137,6 +134,10 @@ def to_name(level):
|
|
|
137
134
|
return f"L{level.name}"
|
|
138
135
|
|
|
139
136
|
|
|
137
|
+
def to_python_name(level):
|
|
138
|
+
return f"L{int(level.name) - 1000}"
|
|
139
|
+
|
|
140
|
+
|
|
140
141
|
def shared_level_to_name(level, user):
|
|
141
142
|
return (
|
|
142
143
|
f"{level.name} (you)"
|
|
@@ -145,14 +146,16 @@ def shared_level_to_name(level, user):
|
|
|
145
146
|
)
|
|
146
147
|
|
|
147
148
|
|
|
148
|
-
def scoreboard_data(episode_ids, attempts_per_students):
|
|
149
|
+
def scoreboard_data(episode_ids, attempts_per_students, language):
|
|
149
150
|
# Show the total score, total time and score of each level
|
|
150
151
|
levels_sorted = []
|
|
151
152
|
for episode_id in episode_ids:
|
|
152
153
|
episode = Episode.objects.get(id=episode_id)
|
|
153
154
|
levels_sorted += episode.levels
|
|
154
155
|
|
|
155
|
-
|
|
156
|
+
to_name_function = to_name if language == "blockly" else to_python_name
|
|
157
|
+
|
|
158
|
+
level_headers = list(map(to_name_function, levels_sorted))
|
|
156
159
|
student_data = [
|
|
157
160
|
student_row(levels_sorted, student, best_attempts)
|
|
158
161
|
for student, best_attempts in attempts_per_students.items()
|
|
@@ -238,6 +241,7 @@ def scoreboard_view(
|
|
|
238
241
|
shared_headers,
|
|
239
242
|
shared_level_headers,
|
|
240
243
|
shared_student_data,
|
|
244
|
+
language,
|
|
241
245
|
):
|
|
242
246
|
database_episodes = level_selection.fetch_episode_data(False)
|
|
243
247
|
|
|
@@ -256,11 +260,20 @@ def scoreboard_view(
|
|
|
256
260
|
"shared_headers": shared_headers,
|
|
257
261
|
"shared_level_headers": shared_level_headers,
|
|
258
262
|
"shared_student_data": shared_student_data,
|
|
263
|
+
"language": language,
|
|
259
264
|
},
|
|
260
265
|
)
|
|
261
266
|
|
|
262
267
|
|
|
263
|
-
def
|
|
268
|
+
def blockly_scoreboard(request):
|
|
269
|
+
return scoreboard(request, "blockly")
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def python_scoreboard(request):
|
|
273
|
+
return scoreboard(request, "python")
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def scoreboard(request, language):
|
|
264
277
|
"""
|
|
265
278
|
Renders a page with students' scores. A teacher can see the visible classes in
|
|
266
279
|
their school. Student's view is restricted to their class if their teacher enabled
|
|
@@ -271,8 +284,11 @@ def scoreboard(request):
|
|
|
271
284
|
|
|
272
285
|
user = User(request.user.userprofile)
|
|
273
286
|
users_classes = classes_for(user)
|
|
287
|
+
|
|
288
|
+
episodes_range = range(1, 10) if language == "blockly" else range(12, 16)
|
|
289
|
+
|
|
274
290
|
all_episode_ids = [
|
|
275
|
-
episode.id for episode in Episode.objects.filter(
|
|
291
|
+
episode.id for episode in Episode.objects.filter(pk__in=episodes_range)
|
|
276
292
|
]
|
|
277
293
|
|
|
278
294
|
if user.is_independent_student():
|
|
@@ -305,6 +321,7 @@ def scoreboard(request):
|
|
|
305
321
|
form = ScoreboardForm(
|
|
306
322
|
request.POST or None,
|
|
307
323
|
classes=users_classes,
|
|
324
|
+
language=language,
|
|
308
325
|
initial={
|
|
309
326
|
"classes": class_ids,
|
|
310
327
|
"episodes": episode_ids,
|
|
@@ -322,56 +339,63 @@ def scoreboard(request):
|
|
|
322
339
|
all_levels += episode.levels
|
|
323
340
|
|
|
324
341
|
attempts_per_student = {}
|
|
325
|
-
attempts_per_student_shared_levels = {}
|
|
326
|
-
|
|
327
|
-
if user.is_teacher():
|
|
328
|
-
if user.teacher.is_admin:
|
|
329
|
-
# Get all custom levels owned by non-admin teachers
|
|
330
|
-
standard_teachers = Teacher.objects.filter(
|
|
331
|
-
school=user.teacher.school, is_admin=False
|
|
332
|
-
)
|
|
333
|
-
for standard_teacher in standard_teachers:
|
|
334
|
-
shared_levels += levels_owned_by(standard_teacher.new_user)
|
|
335
|
-
else:
|
|
336
|
-
# Get logged in teacher's custom levels
|
|
337
|
-
shared_levels += levels_owned_by(request.user)
|
|
338
|
-
|
|
339
|
-
# In all cases, get all admins' custom levels
|
|
340
|
-
school_admins = Teacher.objects.filter(
|
|
341
|
-
school=user.teacher.school, is_admin=True
|
|
342
|
-
)
|
|
343
|
-
for school_admin in school_admins:
|
|
344
|
-
shared_levels += levels_owned_by(school_admin.new_user)
|
|
345
|
-
|
|
346
|
-
elif user.is_student():
|
|
347
|
-
shared_levels += levels_shared_with(request.user)
|
|
348
342
|
|
|
349
343
|
for student in students:
|
|
350
344
|
best_attempts = Attempt.objects.filter(
|
|
351
345
|
level__in=all_levels, student=student, is_best_attempt=True
|
|
352
346
|
).select_related("level")
|
|
353
347
|
attempts_per_student[student] = best_attempts
|
|
354
|
-
shared_levels += levels_owned_by(student.new_user)
|
|
355
|
-
best_attempts_shared_levels = Attempt.objects.filter(
|
|
356
|
-
level__in=shared_levels, student=student, is_best_attempt=True
|
|
357
|
-
).select_related("level")
|
|
358
|
-
attempts_per_student_shared_levels[
|
|
359
|
-
student
|
|
360
|
-
] = best_attempts_shared_levels
|
|
361
348
|
|
|
362
349
|
(student_data, headers, level_headers, levels_sorted) = scoreboard_data(
|
|
363
|
-
episode_ids, attempts_per_student
|
|
350
|
+
episode_ids, attempts_per_student, language
|
|
364
351
|
)
|
|
365
352
|
improvement_data = get_improvement_data(attempts_per_student)
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
353
|
+
|
|
354
|
+
shared_headers = shared_level_headers = shared_student_data = []
|
|
355
|
+
|
|
356
|
+
if language == "blockly":
|
|
357
|
+
attempts_per_student_shared_levels = {}
|
|
358
|
+
|
|
359
|
+
if user.is_teacher():
|
|
360
|
+
if user.teacher.is_admin:
|
|
361
|
+
# Get all custom levels owned by non-admin teachers
|
|
362
|
+
standard_teachers = Teacher.objects.filter(
|
|
363
|
+
school=user.teacher.school, is_admin=False
|
|
364
|
+
)
|
|
365
|
+
for standard_teacher in standard_teachers:
|
|
366
|
+
shared_levels += levels_owned_by(standard_teacher.new_user)
|
|
367
|
+
else:
|
|
368
|
+
# Get logged in teacher's custom levels
|
|
369
|
+
shared_levels += levels_owned_by(request.user)
|
|
370
|
+
|
|
371
|
+
# In all cases, get all admins' custom levels
|
|
372
|
+
school_admins = Teacher.objects.filter(
|
|
373
|
+
school=user.teacher.school, is_admin=True
|
|
374
|
+
)
|
|
375
|
+
for school_admin in school_admins:
|
|
376
|
+
shared_levels += levels_owned_by(school_admin.new_user)
|
|
377
|
+
|
|
378
|
+
elif user.is_student():
|
|
379
|
+
shared_levels += levels_shared_with(request.user)
|
|
380
|
+
|
|
381
|
+
for student in students:
|
|
382
|
+
shared_levels += levels_owned_by(student.new_user)
|
|
383
|
+
best_attempts_shared_levels = Attempt.objects.filter(
|
|
384
|
+
level__in=shared_levels, student=student, is_best_attempt=True
|
|
385
|
+
).select_related("level")
|
|
386
|
+
attempts_per_student_shared_levels[
|
|
387
|
+
student
|
|
388
|
+
] = best_attempts_shared_levels
|
|
389
|
+
|
|
390
|
+
(
|
|
391
|
+
shared_headers,
|
|
392
|
+
shared_level_headers,
|
|
393
|
+
shared_student_data,
|
|
394
|
+
) = shared_levels_data(
|
|
395
|
+
request.user.userprofile,
|
|
396
|
+
shared_levels,
|
|
397
|
+
attempts_per_student_shared_levels,
|
|
398
|
+
)
|
|
375
399
|
|
|
376
400
|
csv_export = "export" in request.POST
|
|
377
401
|
|
|
@@ -394,6 +418,7 @@ def scoreboard(request):
|
|
|
394
418
|
shared_headers,
|
|
395
419
|
shared_level_headers,
|
|
396
420
|
shared_student_data,
|
|
421
|
+
language,
|
|
397
422
|
)
|
|
398
423
|
|
|
399
424
|
|
|
@@ -485,7 +510,7 @@ def is_viewable(class_):
|
|
|
485
510
|
return class_.classmates_data_viewable
|
|
486
511
|
|
|
487
512
|
|
|
488
|
-
def
|
|
513
|
+
def chop_milliseconds(delta):
|
|
489
514
|
return delta - timedelta(microseconds=delta.microseconds)
|
|
490
515
|
|
|
491
516
|
|
game/views/worksheet.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import absolute_import, division
|
|
2
|
+
|
|
3
|
+
from django.shortcuts import render
|
|
4
|
+
|
|
5
|
+
from game import messages
|
|
6
|
+
from game.models import Worksheet
|
|
7
|
+
from .helper import renderError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def worksheet(request, worksheetId):
|
|
11
|
+
if request.user.is_anonymous:
|
|
12
|
+
return renderError(
|
|
13
|
+
request,
|
|
14
|
+
messages.no_permission_python_den_worksheet_title(),
|
|
15
|
+
messages.no_permission_python_den_worksheet_page(),
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
worksheet = Worksheet.objects.get(pk=worksheetId)
|
|
19
|
+
starter_code = messages.worksheet_starter_code()
|
|
20
|
+
|
|
21
|
+
return render(
|
|
22
|
+
request,
|
|
23
|
+
"game/python_den_worksheet.html",
|
|
24
|
+
context={"worksheet": worksheet, "starter_code": starter_code},
|
|
25
|
+
)
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rapid-router
|
|
3
|
+
Version: 7.6.8
|
|
4
|
+
Classifier: Programming Language :: Python
|
|
5
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
6
|
+
Classifier: Framework :: Django
|
|
7
|
+
License-File: LICENSE.md
|
|
8
|
+
Requires-Dist: asgiref==3.10.0; python_version >= "3.9"
|
|
9
|
+
Requires-Dist: asttokens==3.0.0; python_version >= "3.8"
|
|
10
|
+
Requires-Dist: certifi==2025.10.5; python_version >= "3.7"
|
|
11
|
+
Requires-Dist: cffi==2.0.0; platform_python_implementation != "PyPy"
|
|
12
|
+
Requires-Dist: cfl-common==8.9.8
|
|
13
|
+
Requires-Dist: charset-normalizer==3.4.4; python_version >= "3.7"
|
|
14
|
+
Requires-Dist: cryptography==44.0.1; python_version >= "3.7" and python_full_version not in "3.9.0, 3.9.1"
|
|
15
|
+
Requires-Dist: decorator==5.2.1; python_version >= "3.8"
|
|
16
|
+
Requires-Dist: diff-match-patch==20241021; python_version >= "3.7"
|
|
17
|
+
Requires-Dist: django==5.1.14; python_version >= "3.10"
|
|
18
|
+
Requires-Dist: django-countries==7.6.1
|
|
19
|
+
Requires-Dist: django-csp==3.8
|
|
20
|
+
Requires-Dist: django-formtools==2.5.1; python_version >= "3.8"
|
|
21
|
+
Requires-Dist: django-import-export==4.2.0; python_version >= "3.9"
|
|
22
|
+
Requires-Dist: django-otp==1.6.3; python_version >= "3.7"
|
|
23
|
+
Requires-Dist: django-phonenumber-field==8.3.0; python_version >= "3.9"
|
|
24
|
+
Requires-Dist: django-pipeline==4.0.0; python_version >= "3.9"
|
|
25
|
+
Requires-Dist: django-reverse-js==0.1.8; python_version >= "3.10"
|
|
26
|
+
Requires-Dist: django-two-factor-auth==1.17.0; python_version >= "3.8"
|
|
27
|
+
Requires-Dist: djangorestframework==3.16.0; python_version >= "3.9"
|
|
28
|
+
Requires-Dist: executing==2.2.1; python_version >= "3.8"
|
|
29
|
+
Requires-Dist: idna==3.11; python_version >= "3.8"
|
|
30
|
+
Requires-Dist: ipython==9.7.0; python_version >= "3.11"
|
|
31
|
+
Requires-Dist: ipython-pygments-lexers==1.1.1; python_version >= "3.8"
|
|
32
|
+
Requires-Dist: jedi==0.19.2; python_version >= "3.6"
|
|
33
|
+
Requires-Dist: libsass==0.23.0; python_version >= "3.8"
|
|
34
|
+
Requires-Dist: matplotlib-inline==0.2.1; python_version >= "3.9"
|
|
35
|
+
Requires-Dist: more-itertools==8.7.0; python_version >= "3.5"
|
|
36
|
+
Requires-Dist: numpy==2.3.4; python_version >= "3.11"
|
|
37
|
+
Requires-Dist: pandas==2.3.3; python_version >= "3.9"
|
|
38
|
+
Requires-Dist: parso==0.8.5; python_version >= "3.6"
|
|
39
|
+
Requires-Dist: pexpect==4.9.0; sys_platform != "win32" and sys_platform != "emscripten"
|
|
40
|
+
Requires-Dist: pgeocode==0.4.0; python_version >= "3.8"
|
|
41
|
+
Requires-Dist: prompt-toolkit==3.0.52; python_version >= "3.8"
|
|
42
|
+
Requires-Dist: ptyprocess==0.7.0
|
|
43
|
+
Requires-Dist: pure-eval==0.2.3
|
|
44
|
+
Requires-Dist: pycparser==2.23; implementation_name != "PyPy"
|
|
45
|
+
Requires-Dist: pygments==2.19.2; python_version >= "3.8"
|
|
46
|
+
Requires-Dist: pyhamcrest==2.0.2; python_version >= "3.5"
|
|
47
|
+
Requires-Dist: pyjwt==2.6.0; python_version >= "3.7"
|
|
48
|
+
Requires-Dist: pypng==0.20220715.0
|
|
49
|
+
Requires-Dist: python-dateutil==2.9.0.post0; python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2, 3.3"
|
|
50
|
+
Requires-Dist: pytz==2025.2
|
|
51
|
+
Requires-Dist: qrcode==7.4.2; python_version >= "3.7"
|
|
52
|
+
Requires-Dist: requests==2.32.5; python_version >= "3.9"
|
|
53
|
+
Requires-Dist: setuptools==80.9.0; python_version >= "3.9"
|
|
54
|
+
Requires-Dist: six==1.17.0; python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2, 3.3"
|
|
55
|
+
Requires-Dist: sqlparse==0.5.3; python_version >= "3.8"
|
|
56
|
+
Requires-Dist: stack-data==0.6.3
|
|
57
|
+
Requires-Dist: tablib==3.7.0; python_version >= "3.9"
|
|
58
|
+
Requires-Dist: traitlets==5.14.3; python_version >= "3.8"
|
|
59
|
+
Requires-Dist: typing-extensions==4.15.0; python_version >= "3.9"
|
|
60
|
+
Requires-Dist: tzdata==2025.2; python_version >= "2"
|
|
61
|
+
Requires-Dist: urllib3==2.5.0; python_version >= "3.9"
|
|
62
|
+
Requires-Dist: wcwidth==0.2.14; python_version >= "3.6"
|
|
63
|
+
Requires-Dist: wheel==0.45.1; python_version >= "3.8"
|
|
64
|
+
Provides-Extra: dev
|
|
65
|
+
Requires-Dist: amqp==5.3.1; python_version >= "3.6" and extra == "dev"
|
|
66
|
+
Requires-Dist: asgiref==3.10.0; python_version >= "3.9" and extra == "dev"
|
|
67
|
+
Requires-Dist: attrs==25.4.0; python_version >= "3.9" and extra == "dev"
|
|
68
|
+
Requires-Dist: billiard==4.2.2; python_version >= "3.7" and extra == "dev"
|
|
69
|
+
Requires-Dist: black==25.11.0; python_version >= "3.9" and extra == "dev"
|
|
70
|
+
Requires-Dist: boto3==1.36.14; python_version >= "3.8" and extra == "dev"
|
|
71
|
+
Requires-Dist: botocore==1.36.26; python_version >= "3.8" and extra == "dev"
|
|
72
|
+
Requires-Dist: celery[sqs]==5.4.0; python_version >= "3.8" and extra == "dev"
|
|
73
|
+
Requires-Dist: certifi==2025.10.5; python_version >= "3.7" and extra == "dev"
|
|
74
|
+
Requires-Dist: cffi==2.0.0; platform_python_implementation != "PyPy" and extra == "dev"
|
|
75
|
+
Requires-Dist: cfl-common==8.9.8; extra == "dev"
|
|
76
|
+
Requires-Dist: charset-normalizer==3.4.4; python_version >= "3.7" and extra == "dev"
|
|
77
|
+
Requires-Dist: click==8.3.0; python_version >= "3.10" and extra == "dev"
|
|
78
|
+
Requires-Dist: click-didyoumean==0.3.1; python_full_version >= "3.6.2" and extra == "dev"
|
|
79
|
+
Requires-Dist: click-plugins==1.1.1.2; extra == "dev"
|
|
80
|
+
Requires-Dist: click-repl==0.3.0; python_version >= "3.6" and extra == "dev"
|
|
81
|
+
Requires-Dist: codeforlife-portal==8.9.8; extra == "dev"
|
|
82
|
+
Requires-Dist: cryptography==44.0.1; (python_version >= "3.7" and python_full_version not in "3.9.0, 3.9.1") and extra == "dev"
|
|
83
|
+
Requires-Dist: diff-match-patch==20241021; python_version >= "3.7" and extra == "dev"
|
|
84
|
+
Requires-Dist: django==5.1.14; python_version >= "3.10" and extra == "dev"
|
|
85
|
+
Requires-Dist: django-classy-tags==4.1.0; python_version >= "3.8" and extra == "dev"
|
|
86
|
+
Requires-Dist: django-countries==7.6.1; extra == "dev"
|
|
87
|
+
Requires-Dist: django-csp==3.8; extra == "dev"
|
|
88
|
+
Requires-Dist: django-extensions==4.1; python_version >= "3.9" and extra == "dev"
|
|
89
|
+
Requires-Dist: django-formtools==2.5.1; python_version >= "3.8" and extra == "dev"
|
|
90
|
+
Requires-Dist: django-import-export==4.2.0; python_version >= "3.9" and extra == "dev"
|
|
91
|
+
Requires-Dist: django-otp==1.6.3; python_version >= "3.7" and extra == "dev"
|
|
92
|
+
Requires-Dist: django-phonenumber-field==8.3.0; python_version >= "3.9" and extra == "dev"
|
|
93
|
+
Requires-Dist: django-pipeline==4.0.0; python_version >= "3.9" and extra == "dev"
|
|
94
|
+
Requires-Dist: django-preventconcurrentlogins==0.8.2; extra == "dev"
|
|
95
|
+
Requires-Dist: django-ratelimit==3.0.1; python_version >= "3.4" and extra == "dev"
|
|
96
|
+
Requires-Dist: django-recaptcha==4.0.0; extra == "dev"
|
|
97
|
+
Requires-Dist: django-sekizai==4.1.0; python_version >= "3.8" and extra == "dev"
|
|
98
|
+
Requires-Dist: django-selenium-clean==1.0.1; extra == "dev"
|
|
99
|
+
Requires-Dist: django-test-migrations==1.4.0; (python_version >= "3.9" and python_version < "4.0") and extra == "dev"
|
|
100
|
+
Requires-Dist: django-treebeard==4.7.1; python_version >= "3.8" and extra == "dev"
|
|
101
|
+
Requires-Dist: django-two-factor-auth==1.17.0; python_version >= "3.8" and extra == "dev"
|
|
102
|
+
Requires-Dist: djangorestframework==3.16.0; python_version >= "3.9" and extra == "dev"
|
|
103
|
+
Requires-Dist: execnet==2.1.1; python_version >= "3.8" and extra == "dev"
|
|
104
|
+
Requires-Dist: gunicorn==23.0.0; python_version >= "3.7" and extra == "dev"
|
|
105
|
+
Requires-Dist: h11==0.16.0; python_version >= "3.8" and extra == "dev"
|
|
106
|
+
Requires-Dist: idna==3.11; python_version >= "3.8" and extra == "dev"
|
|
107
|
+
Requires-Dist: importlib-metadata==4.13.0; python_version >= "3.7" and extra == "dev"
|
|
108
|
+
Requires-Dist: iniconfig==2.3.0; python_version >= "3.10" and extra == "dev"
|
|
109
|
+
Requires-Dist: isort==7.0.0; python_full_version >= "3.10.0" and extra == "dev"
|
|
110
|
+
Requires-Dist: jmespath==1.0.1; python_version >= "3.7" and extra == "dev"
|
|
111
|
+
Requires-Dist: kombu[sqs]==5.6.0; python_version >= "3.9" and extra == "dev"
|
|
112
|
+
Requires-Dist: libsass==0.23.0; python_version >= "3.8" and extra == "dev"
|
|
113
|
+
Requires-Dist: markupsafe==3.0.3; python_version >= "3.9" and extra == "dev"
|
|
114
|
+
Requires-Dist: more-itertools==8.7.0; python_version >= "3.5" and extra == "dev"
|
|
115
|
+
Requires-Dist: mypy-extensions==1.1.0; python_version >= "3.8" and extra == "dev"
|
|
116
|
+
Requires-Dist: numpy==2.3.4; python_version >= "3.11" and extra == "dev"
|
|
117
|
+
Requires-Dist: outcome==1.3.0.post0; python_version >= "3.7" and extra == "dev"
|
|
118
|
+
Requires-Dist: packaging==25.0; python_version >= "3.8" and extra == "dev"
|
|
119
|
+
Requires-Dist: pandas==2.3.3; python_version >= "3.9" and extra == "dev"
|
|
120
|
+
Requires-Dist: pathspec==0.12.1; python_version >= "3.8" and extra == "dev"
|
|
121
|
+
Requires-Dist: pgeocode==0.4.0; python_version >= "3.8" and extra == "dev"
|
|
122
|
+
Requires-Dist: phonenumbers==8.12.12; extra == "dev"
|
|
123
|
+
Requires-Dist: pillow==12.0.0; python_version >= "3.10" and extra == "dev"
|
|
124
|
+
Requires-Dist: platformdirs==4.5.0; python_version >= "3.10" and extra == "dev"
|
|
125
|
+
Requires-Dist: pluggy==1.6.0; python_version >= "3.9" and extra == "dev"
|
|
126
|
+
Requires-Dist: prompt-toolkit==3.0.52; python_version >= "3.8" and extra == "dev"
|
|
127
|
+
Requires-Dist: psycopg2-binary==2.9.9; python_version >= "3.7" and extra == "dev"
|
|
128
|
+
Requires-Dist: pycparser==2.23; implementation_name != "PyPy" and extra == "dev"
|
|
129
|
+
Requires-Dist: pycurl==7.45.7; python_version >= "3.5" and extra == "dev"
|
|
130
|
+
Requires-Dist: pygments==2.19.2; python_version >= "3.8" and extra == "dev"
|
|
131
|
+
Requires-Dist: pyjwt==2.6.0; python_version >= "3.7" and extra == "dev"
|
|
132
|
+
Requires-Dist: pyopenssl==25.1.0; python_version >= "3.7" and extra == "dev"
|
|
133
|
+
Requires-Dist: pypng==0.20220715.0; extra == "dev"
|
|
134
|
+
Requires-Dist: pysocks==1.7.1; extra == "dev"
|
|
135
|
+
Requires-Dist: pytest==8.4.2; python_version >= "3.9" and extra == "dev"
|
|
136
|
+
Requires-Dist: pytest-django==4.8.0; python_version >= "3.8" and extra == "dev"
|
|
137
|
+
Requires-Dist: pytest-order==1.3.0; python_version >= "3.7" and extra == "dev"
|
|
138
|
+
Requires-Dist: pytest-xdist==3.8.0; python_version >= "3.9" and extra == "dev"
|
|
139
|
+
Requires-Dist: python-dateutil==2.9.0.post0; (python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2, 3.3") and extra == "dev"
|
|
140
|
+
Requires-Dist: python-dotenv==1.0.1; python_version >= "3.8" and extra == "dev"
|
|
141
|
+
Requires-Dist: pytokens==0.3.0; python_version >= "3.8" and extra == "dev"
|
|
142
|
+
Requires-Dist: pytz==2025.2; extra == "dev"
|
|
143
|
+
Requires-Dist: pyyaml==6.0.2; python_version >= "3.8" and extra == "dev"
|
|
144
|
+
Requires-Dist: qrcode==7.4.2; python_version >= "3.7" and extra == "dev"
|
|
145
|
+
Requires-Dist: reportlab==4.4.2; (python_version >= "3.7" and python_version < "4") and extra == "dev"
|
|
146
|
+
Requires-Dist: requests==2.32.5; python_version >= "3.9" and extra == "dev"
|
|
147
|
+
Requires-Dist: requests-toolbelt==1.0.0; (python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2, 3.3") and extra == "dev"
|
|
148
|
+
Requires-Dist: s3transfer==0.11.3; python_version >= "3.8" and extra == "dev"
|
|
149
|
+
Requires-Dist: selenium==4.29.0; python_version >= "3.9" and extra == "dev"
|
|
150
|
+
Requires-Dist: setuptools==80.9.0; python_version >= "3.9" and extra == "dev"
|
|
151
|
+
Requires-Dist: six==1.17.0; (python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2, 3.3") and extra == "dev"
|
|
152
|
+
Requires-Dist: sniffio==1.3.1; python_version >= "3.7" and extra == "dev"
|
|
153
|
+
Requires-Dist: sortedcontainers==2.4.0; extra == "dev"
|
|
154
|
+
Requires-Dist: sqlparse==0.5.3; python_version >= "3.8" and extra == "dev"
|
|
155
|
+
Requires-Dist: tablib==3.7.0; python_version >= "3.9" and extra == "dev"
|
|
156
|
+
Requires-Dist: trio==0.32.0; python_version >= "3.10" and extra == "dev"
|
|
157
|
+
Requires-Dist: trio-websocket==0.12.2; python_version >= "3.8" and extra == "dev"
|
|
158
|
+
Requires-Dist: typing-extensions==4.15.0; python_version >= "3.9" and extra == "dev"
|
|
159
|
+
Requires-Dist: tzdata==2025.2; python_version >= "2" and extra == "dev"
|
|
160
|
+
Requires-Dist: urllib3==2.5.0; python_version >= "3.9" and extra == "dev"
|
|
161
|
+
Requires-Dist: uvicorn==0.38.0; python_version >= "3.9" and extra == "dev"
|
|
162
|
+
Requires-Dist: uvicorn-worker==0.2.0; python_version >= "3.8" and extra == "dev"
|
|
163
|
+
Requires-Dist: vine==5.1.0; python_version >= "3.6" and extra == "dev"
|
|
164
|
+
Requires-Dist: wcwidth==0.2.14; python_version >= "3.6" and extra == "dev"
|
|
165
|
+
Requires-Dist: websocket-client==1.9.0; python_version >= "3.9" and extra == "dev"
|
|
166
|
+
Requires-Dist: werkzeug==3.1.3; python_version >= "3.9" and extra == "dev"
|
|
167
|
+
Requires-Dist: wheel==0.45.1; python_version >= "3.8" and extra == "dev"
|
|
168
|
+
Requires-Dist: whitenoise==6.9.0; python_version >= "3.9" and extra == "dev"
|
|
169
|
+
Requires-Dist: wsproto==1.2.0; python_full_version >= "3.7.0" and extra == "dev"
|
|
170
|
+
Requires-Dist: zipp==3.23.0; python_version >= "3.9" and extra == "dev"
|
|
171
|
+
Dynamic: classifier
|
|
172
|
+
Dynamic: license-file
|
|
173
|
+
Dynamic: provides-extra
|
|
174
|
+
Dynamic: requires-dist
|