codeforlife-portal 8.7.2__py2.py3-none-any.whl → 8.7.4__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.

Potentially problematic release.


This version of codeforlife-portal might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeforlife-portal
3
- Version: 8.7.2
3
+ Version: 8.7.4
4
4
  Classifier: Programming Language :: Python
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Framework :: Django
@@ -8,11 +8,11 @@ Description-Content-Type: text/markdown
8
8
  License-File: LICENSE.md
9
9
  Requires-Dist: asgiref==3.8.1; python_version >= "3.8"
10
10
  Requires-Dist: certifi==2025.4.26; python_version >= "3.6"
11
- Requires-Dist: cfl-common==8.7.2
11
+ Requires-Dist: cfl-common==8.7.4
12
12
  Requires-Dist: chardet==5.2.0; python_version >= "3.7"
13
13
  Requires-Dist: charset-normalizer==3.4.2; python_version >= "3.7"
14
14
  Requires-Dist: diff-match-patch==20241021; python_version >= "3.7"
15
- Requires-Dist: django==5.1.9; python_version >= "3.10"
15
+ Requires-Dist: django==5.1.10; python_version >= "3.10"
16
16
  Requires-Dist: django-classy-tags==4.1.0; python_version >= "3.8"
17
17
  Requires-Dist: django-countries==7.6.1
18
18
  Requires-Dist: django-csp==3.8
@@ -32,41 +32,41 @@ Requires-Dist: idna==3.10; python_version >= "3.6"
32
32
  Requires-Dist: importlib-metadata==4.13.0; python_version >= "3.7"
33
33
  Requires-Dist: libsass==0.23.0; python_version >= "3.8"
34
34
  Requires-Dist: more-itertools==8.7.0; python_version >= "3.5"
35
- Requires-Dist: numpy==2.2.5; python_version >= "3.10"
36
- Requires-Dist: pandas==2.2.3; python_version >= "3.9"
35
+ Requires-Dist: numpy==2.2.6; python_version >= "3.10"
36
+ Requires-Dist: pandas==2.3.0; python_version >= "3.9"
37
37
  Requires-Dist: pgeocode==0.4.0; python_version >= "3.8"
38
38
  Requires-Dist: phonenumbers==8.12.12
39
39
  Requires-Dist: pillow==11.2.1; python_version >= "3.9"
40
40
  Requires-Dist: pyjwt==2.6.0; python_version >= "3.7"
41
41
  Requires-Dist: pypng==0.20220715.0
42
- Requires-Dist: python-dateutil==2.9.0.post0; python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2"
42
+ 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"
43
43
  Requires-Dist: pytz==2025.2
44
44
  Requires-Dist: pyyaml==6.0.2; python_version >= "3.8"
45
45
  Requires-Dist: qrcode==7.4.2; python_version >= "3.7"
46
46
  Requires-Dist: reportlab==4.2.5; python_version >= "3.7" and python_version < "4"
47
47
  Requires-Dist: requests==2.32.3; python_version >= "3.8"
48
- Requires-Dist: setuptools==80.3.1; python_version >= "3.9"
49
- Requires-Dist: six==1.17.0; python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2"
48
+ Requires-Dist: setuptools==80.9.0; python_version >= "3.9"
49
+ Requires-Dist: six==1.17.0; python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2, 3.3"
50
50
  Requires-Dist: sqlparse==0.5.3; python_version >= "3.8"
51
51
  Requires-Dist: tablib==3.7.0; python_version >= "3.9"
52
- Requires-Dist: typing-extensions==4.13.2; python_version >= "3.8"
52
+ Requires-Dist: typing-extensions==4.14.0; python_version >= "3.9"
53
53
  Requires-Dist: tzdata==2025.2; python_version >= "2"
54
54
  Requires-Dist: urllib3==2.4.0; python_version >= "3.9"
55
55
  Requires-Dist: wheel==0.45.1; python_version >= "3.8"
56
- Requires-Dist: zipp==3.21.0; python_version >= "3.9"
56
+ Requires-Dist: zipp==3.22.0; python_version >= "3.9"
57
57
  Provides-Extra: dev
58
58
  Requires-Dist: asgiref==3.8.1; python_version >= "3.8" and extra == "dev"
59
59
  Requires-Dist: asttokens==3.0.0; python_version >= "3.8" and extra == "dev"
60
60
  Requires-Dist: attrs==25.3.0; python_version >= "3.8" and extra == "dev"
61
61
  Requires-Dist: black==25.1.0; python_version >= "3.9" and extra == "dev"
62
62
  Requires-Dist: certifi==2025.4.26; python_version >= "3.6" and extra == "dev"
63
- Requires-Dist: cfl-common==8.7.2; extra == "dev"
63
+ Requires-Dist: cfl-common==8.7.4; extra == "dev"
64
64
  Requires-Dist: charset-normalizer==3.4.2; python_version >= "3.7" and extra == "dev"
65
- Requires-Dist: click==8.1.8; python_version >= "3.7" and extra == "dev"
66
- Requires-Dist: coverage[toml]==7.8.0; python_version >= "3.9" and extra == "dev"
65
+ Requires-Dist: click==8.2.1; python_version >= "3.10" and extra == "dev"
66
+ Requires-Dist: coverage[toml]==7.8.2; python_version >= "3.9" and extra == "dev"
67
67
  Requires-Dist: decorator==5.2.1; python_version >= "3.8" and extra == "dev"
68
68
  Requires-Dist: diff-match-patch==20241021; python_version >= "3.7" and extra == "dev"
69
- Requires-Dist: django==5.1.9; python_version >= "3.10" and extra == "dev"
69
+ Requires-Dist: django==5.1.10; python_version >= "3.10" and extra == "dev"
70
70
  Requires-Dist: django-countries==7.6.1; extra == "dev"
71
71
  Requires-Dist: django-csp==3.8; extra == "dev"
72
72
  Requires-Dist: django-formtools==2.5.1; python_version >= "3.8" and extra == "dev"
@@ -93,16 +93,16 @@ Requires-Dist: libsass==0.23.0; python_version >= "3.8" and extra == "dev"
93
93
  Requires-Dist: matplotlib-inline==0.1.7; python_version >= "3.8" and extra == "dev"
94
94
  Requires-Dist: more-itertools==8.7.0; python_version >= "3.5" and extra == "dev"
95
95
  Requires-Dist: mypy-extensions==1.1.0; python_version >= "3.8" and extra == "dev"
96
- Requires-Dist: numpy==2.2.5; python_version >= "3.10" and extra == "dev"
96
+ Requires-Dist: numpy==2.2.6; python_version >= "3.10" and extra == "dev"
97
97
  Requires-Dist: outcome==1.3.0.post0; python_version >= "3.7" and extra == "dev"
98
98
  Requires-Dist: packaging==25.0; python_version >= "3.8" and extra == "dev"
99
- Requires-Dist: pandas==2.2.3; python_version >= "3.9" and extra == "dev"
99
+ Requires-Dist: pandas==2.3.0; python_version >= "3.9" and extra == "dev"
100
100
  Requires-Dist: parso==0.8.4; python_version >= "3.6" and extra == "dev"
101
101
  Requires-Dist: pathspec==0.12.1; python_version >= "3.8" and extra == "dev"
102
102
  Requires-Dist: pexpect==4.9.0; (sys_platform != "win32" and sys_platform != "emscripten") and extra == "dev"
103
103
  Requires-Dist: pgeocode==0.4.0; python_version >= "3.8" and extra == "dev"
104
104
  Requires-Dist: platformdirs==4.3.8; python_version >= "3.9" and extra == "dev"
105
- Requires-Dist: pluggy==1.5.0; python_version >= "3.8" and extra == "dev"
105
+ Requires-Dist: pluggy==1.6.0; python_version >= "3.9" and extra == "dev"
106
106
  Requires-Dist: prompt-toolkit==3.0.51; python_version >= "3.8" and extra == "dev"
107
107
  Requires-Dist: ptyprocess==0.7.0; extra == "dev"
108
108
  Requires-Dist: pure-eval==0.2.3; extra == "dev"
@@ -112,22 +112,22 @@ Requires-Dist: pyjwt==2.6.0; python_version >= "3.7" and extra == "dev"
112
112
  Requires-Dist: pypdf==5.1.0; python_version >= "3.8" and extra == "dev"
113
113
  Requires-Dist: pypng==0.20220715.0; extra == "dev"
114
114
  Requires-Dist: pysocks==1.7.1; extra == "dev"
115
- Requires-Dist: pytest==8.3.5; python_version >= "3.8" and extra == "dev"
115
+ Requires-Dist: pytest==8.4.0; python_version >= "3.9" and extra == "dev"
116
116
  Requires-Dist: pytest-cov==6.1.1; python_version >= "3.9" and extra == "dev"
117
117
  Requires-Dist: pytest-django==4.8.0; python_version >= "3.8" and extra == "dev"
118
- Requires-Dist: pytest-mock==3.14.0; python_version >= "3.8" and extra == "dev"
118
+ Requires-Dist: pytest-mock==3.14.1; python_version >= "3.8" and extra == "dev"
119
119
  Requires-Dist: pytest-order==1.3.0; python_version >= "3.7" and extra == "dev"
120
- Requires-Dist: pytest-xdist==3.6.1; python_version >= "3.8" and extra == "dev"
121
- Requires-Dist: python-dateutil==2.9.0.post0; (python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2") and extra == "dev"
120
+ Requires-Dist: pytest-xdist==3.7.0; python_version >= "3.9" and extra == "dev"
121
+ 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"
122
122
  Requires-Dist: pytz==2025.2; extra == "dev"
123
123
  Requires-Dist: pyvirtualdisplay==3.0; extra == "dev"
124
124
  Requires-Dist: qrcode==7.4.2; python_version >= "3.7" and extra == "dev"
125
- Requires-Dist: rapid-router==7.5.5; extra == "dev"
125
+ Requires-Dist: rapid-router==7.5.10; extra == "dev"
126
126
  Requires-Dist: requests==2.32.3; python_version >= "3.8" and extra == "dev"
127
127
  Requires-Dist: responses==0.18.0; python_version >= "3.7" and extra == "dev"
128
128
  Requires-Dist: selenium==4.29.0; python_version >= "3.9" and extra == "dev"
129
- Requires-Dist: setuptools==80.3.1; python_version >= "3.9" and extra == "dev"
130
- Requires-Dist: six==1.17.0; (python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2") and extra == "dev"
129
+ Requires-Dist: setuptools==80.9.0; python_version >= "3.9" and extra == "dev"
130
+ 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"
131
131
  Requires-Dist: snapshottest==1.0.0a1; extra == "dev"
132
132
  Requires-Dist: sniffio==1.3.1; python_version >= "3.7" and extra == "dev"
133
133
  Requires-Dist: sortedcontainers==2.4.0; extra == "dev"
@@ -138,7 +138,7 @@ Requires-Dist: termcolor==3.1.0; python_version >= "3.9" and extra == "dev"
138
138
  Requires-Dist: traitlets==5.14.3; python_version >= "3.8" and extra == "dev"
139
139
  Requires-Dist: trio==0.30.0; python_version >= "3.9" and extra == "dev"
140
140
  Requires-Dist: trio-websocket==0.12.2; python_version >= "3.8" and extra == "dev"
141
- Requires-Dist: typing-extensions==4.13.2; python_version >= "3.8" and extra == "dev"
141
+ Requires-Dist: typing-extensions==4.14.0; python_version >= "3.9" and extra == "dev"
142
142
  Requires-Dist: tzdata==2025.2; python_version >= "2" and extra == "dev"
143
143
  Requires-Dist: urllib3==2.4.0; python_version >= "3.9" and extra == "dev"
144
144
  Requires-Dist: wasmer==1.1.0; extra == "dev"
@@ -87,7 +87,7 @@ cfl_common/common/tests/utils/organisation.py,sha256=vNgKFtU3VPcWRnZfh82yCS90PLA
87
87
  cfl_common/common/tests/utils/student.py,sha256=PLd980iSlxmMoB8J3C2pVjNC5xHdVxfAkJXzhv_dRhg,3814
88
88
  cfl_common/common/tests/utils/teacher.py,sha256=KQ_NAl4yQqiX_zwcULQjkovc29JPhnkLR5Nk3Ljzbpg,2661
89
89
  cfl_common/common/tests/utils/user.py,sha256=NvLzZLVP4jy5Hn1iztOYF_BTQ9WsbSmuWMEzGzhAsRU,919
90
- codeforlife_portal-8.7.2.dist-info/licenses/LICENSE.md,sha256=9AbRlCDqD2D1tPibimysFv3zg3AIc49-eyv9aEsyq9w,115
90
+ codeforlife_portal-8.7.4.dist-info/licenses/LICENSE.md,sha256=9AbRlCDqD2D1tPibimysFv3zg3AIc49-eyv9aEsyq9w,115
91
91
  deploy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
92
  deploy/captcha.py,sha256=MbOBuGnbT_SOIltSjP1XMOLrfo1DldCilaVAEim0vM4,23
93
93
  deploy/views.py,sha256=7mY2zNPkaBFrlWGByJHp2zFqHIHSMc0YArjE_sFWMMU,131
@@ -111,7 +111,7 @@ example_project/portal_test_settings.py,sha256=AaXwSSB2A6qu6My_7cBciQa_jONy084uq
111
111
  example_project/settings.py,sha256=RRSHhAgJVDn4uNZG395V6_Td7jwsSaBGNwQBZ_KJm0Y,5973
112
112
  example_project/urls.py,sha256=FUTzHPlUS1O5kqMHjL5V4L552N2ln7uTDXcw9wjKUto,422
113
113
  example_project/wsgi.py,sha256=U1W6WzZxZaIdYZ5tks7w9fqp5WS5qvn2iThsVcskrWw,829
114
- portal/__init__.py,sha256=uSwVjG_R40j30Fl03Na-I7aeCcDlrjICeihLirz59ho,22
114
+ portal/__init__.py,sha256=wHEOdRusBiLao3c9nqf81YK6XRQABxAMpJ9HVGTQfWg,22
115
115
  portal/admin.py,sha256=RKJizTF6dPJKmGPZw7nZUM0X8jkiTjgyKhLQxtvHJ0I,6148
116
116
  portal/app_settings.py,sha256=DhWLQOwM0zVOXE3O5TNKbMM9K6agfLuCsHOdr1J7xEI,651
117
117
  portal/backends.py,sha256=2Dss6_WoQwPuDzJUF1yEaTQTNG4eUrD12ujJQ5cp5Tc,812
@@ -126,7 +126,7 @@ portal/forms/admin.py,sha256=Cdl8-wvasAzvMfgUlFYzQjYeuyC7gIsSiy8V_-jMp7w,2080
126
126
  portal/forms/dotmailer.py,sha256=AiHoN8ZRl3A69FYSldkjlhICGx_l4BujP5HjYdSRCok,897
127
127
  portal/forms/error_messages.py,sha256=8d3z_3e2L-5zwj5hFhnUByC5k2CEpIVVuJg2nYkCUQ8,148
128
128
  portal/forms/invite_teacher.py,sha256=jkDNcCfkts4_lXRzhcI3xBam21Zn2yX9wMpMVhDtW1w,880
129
- portal/forms/organisation.py,sha256=QcQyd7AiqBmvt4y8uQSQylguUbKOKqo2pjqWIkpWjDg,7433
129
+ portal/forms/organisation.py,sha256=-h4Lpl4WisqNGgohlsmqh_ABA0aLfeXtUxAR1sUdi0I,7278
130
130
  portal/forms/play.py,sha256=j_QYAKb4qyW0uy0VUUG49dmzDLINc3jR6ddK-djrbc4,11523
131
131
  portal/forms/registration.py,sha256=a-TuzikRc0Q-BAYs3rJ3Sz1wmQ1o_rTEtZmWdF7-xss,6008
132
132
  portal/forms/teach.py,sha256=lQivQ4pXnvJw8nJMSbqtg-Il5RYkw54ZxE5rJuNlFn0,22391
@@ -543,12 +543,12 @@ portal/tests/test_helper_methods.py,sha256=-SQCDZm2XUtyXGEp0CHIb_SSC9CPD-XOSnpnY
543
543
  portal/tests/test_independent_student.py,sha256=NrRjTEr6V4WXpCE74N8LYNVocvLSvddkjuo3dYpfAZc,27245
544
544
  portal/tests/test_invite_teacher.py,sha256=hynk2p63URQocCS8N6-IQnQWkdzggQ-1jGDuWcRSY_Y,14902
545
545
  portal/tests/test_middleware.py,sha256=HV7AdgWyvgrtPyDMw3np5YDbUstFpKif7Qqw-e8gs5s,8258
546
- portal/tests/test_organisation.py,sha256=kCMUNzLN6EzaMUBcFkqXwnqLGgOuQxQWIHHt63nhqBs,7574
546
+ portal/tests/test_organisation.py,sha256=1rTHTUhdDHMG1Xf4FXMvwOAuXWzFWTVUnryJyW9zOgs,8949
547
547
  portal/tests/test_partials.py,sha256=cSLNLjdsriROjPxkZlM3HKD3CSKDuKgpaDIdL3fPyBs,1794
548
548
  portal/tests/test_ratelimit.py,sha256=XWq1A9XgRrlcMHibGoJ0kc4gLc5U_u5UhKHjthxCfYA,19376
549
549
  portal/tests/test_school_student.py,sha256=bFZwY4twaFHQLp0cltMq8cLNDZGgCHTZBCZHK0JcV8s,8604
550
550
  portal/tests/test_security.py,sha256=FGrlRfnzi-Xx2_bn4fTZlYORKm7w_GhGkD3havvplwc,3239
551
- portal/tests/test_teacher.py,sha256=y4h5Bt7Xlglh9pylSl1jOOl5tl6rqHTewddBjB3RzRA,29171
551
+ portal/tests/test_teacher.py,sha256=fYdqWYVT-EcWUzQBNZ5qOORO7UC_S14NtACx64Rsrbg,29159
552
552
  portal/tests/test_teacher_student.py,sha256=4Di29Lsymbmh6WxZ0FYpqZ4fMN8NqNMTXXOsii1dfW4,21624
553
553
  portal/tests/test_views.py,sha256=Hv0rVOLmYivMqzJK1AQeRJ85YHTCRrlr12hcf1B83Bk,47566
554
554
  portal/tests/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -588,7 +588,7 @@ portal/tests/pageObjects/portal/teach/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCe
588
588
  portal/tests/pageObjects/portal/teach/add_independent_student_to_class_page.py,sha256=P2iW94L7tiLfPz789GcQMyEvGf0QW5i4FUQ_EyVCQyY,931
589
589
  portal/tests/pageObjects/portal/teach/added_independent_student_to_class_page.py,sha256=FnFfIref2Izu6Gquql_D5rvQ32_khulGM1LHnU0cHv8,585
590
590
  portal/tests/pageObjects/portal/teach/class_page.py,sha256=4UuKJxEglZcprR5redmoeVuO3wf0tuwsn-glucS8hKc,3932
591
- portal/tests/pageObjects/portal/teach/dashboard_page.py,sha256=Ttxvd7jOvEKMKQV21lqC6uBWjMLCebeoC7gEAZ76kkI,6709
591
+ portal/tests/pageObjects/portal/teach/dashboard_page.py,sha256=rWtKgw6urggoIgKj10fj5IAh_X_C9MVPeLD7CWnTo1Y,6404
592
592
  portal/tests/pageObjects/portal/teach/dismiss_students_page.py,sha256=qU3D3og4sxIbn4RAKYTaQNQxF0OKodbYzH5XA2detnE,882
593
593
  portal/tests/pageObjects/portal/teach/edit_student_page.py,sha256=qv0B9tc2w1nmW21zu2ObhIhBYOAvF-HswqNZe39jkts,1399
594
594
  portal/tests/pageObjects/portal/teach/move_class_page.py,sha256=GbhCrSfUSIm_NWmqgw4qQPH8tgNiTn6HNSmOyTQ_CJU,1032
@@ -596,7 +596,7 @@ portal/tests/pageObjects/portal/teach/move_classes_page.py,sha256=FsXJV8s9hvI5lf
596
596
  portal/tests/pageObjects/portal/teach/move_students_disambiguate_page.py,sha256=-seb1yylbDzGMLeUrlu2-SlTqTBU-Awa_kPV_EXpfpM,673
597
597
  portal/tests/pageObjects/portal/teach/move_students_page.py,sha256=j_nt8e908Deq-d51tL88KHJfcRQkEJH2eQm6Hvz9Vfs,1078
598
598
  portal/tests/pageObjects/portal/teach/onboarding_classes_page.py,sha256=rVKaJyDeRpSYkG86KB3QWQfgsxuL4Gftj-z19KYOmNM,1046
599
- portal/tests/pageObjects/portal/teach/onboarding_organisation_page.py,sha256=86npz-pbyL9xYYEid4O08m-OTXOsLT2-zoUG7Ee06Rs,2005
599
+ portal/tests/pageObjects/portal/teach/onboarding_organisation_page.py,sha256=Rm_zxQYn2STpgLPUyASnjG8Mdf5TvXeTIz8k5ve6-NM,1679
600
600
  portal/tests/pageObjects/portal/teach/onboarding_student_list_page.py,sha256=28Vz8-IrKf0VoFE_KisAApkunfEE7lX1yj0-nxvKsDw,1147
601
601
  portal/tests/pageObjects/portal/teach/onboarding_students_page.py,sha256=522Y79PfNV1PcR-Clf19KnNe2r3xf4sPPAUnroIzk80,971
602
602
  portal/tests/pageObjects/portal/teach/teach_base_page.py,sha256=vnd5YO15baBgCkqyBkXGZpdjZRMRpeeN69dH-fG383A,1229
@@ -634,7 +634,7 @@ portal/views/two_factor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
634
634
  portal/views/two_factor/core.py,sha256=Lk32z2SN2Pg0rRkK-N-LXMvXC1kKKsH3l692kiSDQ4E,964
635
635
  portal/views/two_factor/form.py,sha256=lnHNKI-BMlpncTuW3zUzjPaJJNuEra2I_nOam0eOKFY,257
636
636
  portal/views/two_factor/profile.py,sha256=SHSg_xHccE5PtD-OfuOkYhREYz_er4bj5ro1RjJ88Yw,393
637
- codeforlife_portal-8.7.2.dist-info/METADATA,sha256=f3A1s2lnbvdtRq0ZRF99F6A1bbLuHnq9RkZqvpf3YD4,12318
638
- codeforlife_portal-8.7.2.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
639
- codeforlife_portal-8.7.2.dist-info/top_level.txt,sha256=8e5pdsuIoTqEAMqpelHBjGjLbffcBtgOoggmd2q7nMw,41
640
- codeforlife_portal-8.7.2.dist-info/RECORD,,
637
+ codeforlife_portal-8.7.4.dist-info/METADATA,sha256=GjLnfnrWW_nLiHkpJOUYaC-HqcOKkLqJ4F6FOkY-4i4,12342
638
+ codeforlife_portal-8.7.4.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
639
+ codeforlife_portal-8.7.4.dist-info/top_level.txt,sha256=8e5pdsuIoTqEAMqpelHBjGjLbffcBtgOoggmd2q7nMw,41
640
+ codeforlife_portal-8.7.4.dist-info/RECORD,,
portal/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "8.7.2"
1
+ __version__ = "8.7.4"
@@ -1,9 +1,9 @@
1
+ import re
1
2
  from builtins import object
2
3
 
3
4
  from common.models import School
4
5
  from django import forms
5
6
  from django.core.exceptions import ObjectDoesNotExist
6
- from django.core.validators import EmailValidator
7
7
  from django_countries.widgets import CountrySelectWidget
8
8
 
9
9
 
@@ -167,16 +167,10 @@ class OrganisationForm(forms.ModelForm):
167
167
 
168
168
  def clean_name(self):
169
169
  name = self.cleaned_data.get("name", None)
170
- validator = EmailValidator()
171
170
 
172
- if name:
173
- try:
174
- validator(name)
175
- is_email = True
176
- except forms.ValidationError:
177
- is_email = False
178
-
179
- if is_email:
180
- raise forms.ValidationError("Please make sure your organisation name is valid")
171
+ if re.match(re.compile("^[\w\.' ]+$"), name) is None:
172
+ raise forms.ValidationError(
173
+ "School names cannot contain special characters except full stops and apostrophes."
174
+ )
181
175
 
182
176
  return name
@@ -52,12 +52,6 @@ class TeachDashboardPage(TeachBasePage):
52
52
  self.browser.find_element(By.ID, "update_details_button").click()
53
53
  return self
54
54
 
55
- def has_edit_failed(self):
56
- self.wait_for_element_by_id("edit_form")
57
- errorlist = self.browser.find_element(By.ID, "edit_form").find_element(By.CLASS_NAME, "errorlist").text
58
- error = "There is already a school or club registered with that name"
59
- return error in errorlist
60
-
61
55
  def create_class(self, name, classmate_progress, teacher_id=None):
62
56
  self.browser.find_element(By.ID, "id_class_name").send_keys(name)
63
57
  if classmate_progress:
@@ -13,13 +13,13 @@ class OnboardingOrganisationPage(TeachBasePage):
13
13
 
14
14
  assert self.on_correct_page("onboarding_organisation_page")
15
15
 
16
- def create_organisation(self, name, password, country="GB"):
17
- self._create_organisation(name, password, country)
16
+ def create_organisation(self, name, country="GB"):
17
+ self._create_organisation(name, country)
18
18
 
19
19
  return onboarding_classes_page.OnboardingClassesPage(self.browser)
20
20
 
21
- def create_organisation_failure(self, name, password, country="GB"):
22
- self._create_organisation(name, password, country)
21
+ def create_organisation_failure(self, name, country="GB"):
22
+ self._create_organisation(name, country)
23
23
 
24
24
  return self
25
25
 
@@ -28,7 +28,7 @@ class OnboardingOrganisationPage(TeachBasePage):
28
28
 
29
29
  return self
30
30
 
31
- def _create_organisation(self, name, password, country):
31
+ def _create_organisation(self, name, country):
32
32
  self.browser.find_element(By.ID, "id_name").send_keys(name)
33
33
  country_element = self.browser.find_element(By.ID, "id_country")
34
34
  select = Select(country_element)
@@ -47,10 +47,3 @@ class OnboardingOrganisationPage(TeachBasePage):
47
47
  )
48
48
  error = "There is already a school or club registered with that name and postcode"
49
49
  return error in errors
50
-
51
- def was_postcode_invalid(self):
52
- errors = (
53
- self.browser.find_element(By.ID, "form-create-organisation").find_element(By.CLASS_NAME, "errorlist").text
54
- )
55
- error = "Please enter a valid postcode or ZIP code"
56
- return error in errors
@@ -16,7 +16,6 @@ from selenium.webdriver.common.by import By
16
16
  from portal.tests.pageObjects.portal.base_page import BasePage
17
17
  from portal.tests.pageObjects.portal.home_page import HomePage
18
18
  from portal.tests.test_invite_teacher import FADE_TIME
19
-
20
19
  from .base_test import BaseTest
21
20
  from .utils.messages import is_organisation_created_message_showing
22
21
 
@@ -28,8 +27,22 @@ class TestOrganisation(BaseTest, BasePage):
28
27
  self.selenium.get(self.live_server_url)
29
28
  page = HomePage(self.selenium).go_to_teacher_login_page().login_no_school(email, password)
30
29
 
31
- page, name = create_organisation(page, password)
32
- assert is_organisation_created_message_showing(self.selenium, name)
30
+ school_name = "My School"
31
+ page.create_organisation(school_name)
32
+ assert is_organisation_created_message_showing(self.selenium, school_name)
33
+
34
+ def test_create_invalid_name(self):
35
+ email, password = signup_teacher_directly()
36
+
37
+ self.selenium.get(self.live_server_url)
38
+ page = HomePage(self.selenium).go_to_teacher_login_page().login_no_school(email, password)
39
+
40
+ invalid_school_name = "<a>My School</a"
41
+ page.create_organisation_failure(invalid_school_name)
42
+ assert page.was_form_invalid(
43
+ "form-create-organisation",
44
+ "School names cannot contain special characters except full stops and apostrophes.",
45
+ )
33
46
 
34
47
  def test_kick(self):
35
48
  email_1, password_1 = signup_teacher_directly()
@@ -171,11 +184,30 @@ class TestOrganisation(BaseTest, BasePage):
171
184
 
172
185
  assert page.check_organisation_details({"name": school.name})
173
186
 
174
- new_name = "new " + school.name
187
+ new_name = f"new {school.name}"
175
188
 
176
189
  page.change_organisation_details({"name": new_name})
177
190
  assert page.check_organisation_details({"name": new_name})
178
191
 
192
+ def test_edit_details_invalid_name(self):
193
+ email, password = signup_teacher_directly()
194
+ school = create_organisation_directly(email)
195
+ _, _, access_code = create_class_directly(email)
196
+ create_school_student_directly(access_code)
197
+
198
+ self.selenium.get(self.live_server_url)
199
+ page = HomePage(self.selenium).go_to_teacher_login_page().login(email, password)
200
+
201
+ assert page.check_organisation_details({"name": school.name})
202
+
203
+ new_name = f"<a>{school.name}</a>"
204
+
205
+ page.change_organisation_details({"name": new_name})
206
+
207
+ assert page.was_form_invalid(
208
+ "edit_form", "School names cannot contain special characters except full stops and apostrophes."
209
+ )
210
+
179
211
  def test_edit_clash(self):
180
212
  email_1, _ = signup_teacher_directly()
181
213
  email_2, password_2 = signup_teacher_directly()
@@ -193,4 +225,4 @@ class TestOrganisation(BaseTest, BasePage):
193
225
 
194
226
  page = page.change_organisation_details({"name": school1.name})
195
227
 
196
- assert page.has_edit_failed()
228
+ assert page.was_form_invalid("edit_form", "There is already a school or club registered with that name")
@@ -772,7 +772,7 @@ class TestTeacherFrontend(BaseTest):
772
772
  .login_no_school(email, password)
773
773
  )
774
774
 
775
- page = page.create_organisation("Test school", "W1", "GB")
775
+ page = page.create_organisation("Test school")
776
776
  page = page.create_class("Test class", True)
777
777
  page = (
778
778
  page.type_student_name("Test Student")