fnschool 20250109.80531.837__py3-none-any.whl → 20251011.81638.854__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 fnschool might be problematic. Click here for more details.

Files changed (278) hide show
  1. fnschoo1/__init__.py +53 -0
  2. fnschoo1/canteen/admin.py +3 -0
  3. fnschoo1/canteen/apps.py +6 -0
  4. fnschoo1/canteen/forms.py +84 -0
  5. fnschoo1/canteen/migrations/0001_initial.py +119 -0
  6. fnschoo1/canteen/migrations/0002_ingredient_is_disabled.py +20 -0
  7. fnschoo1/canteen/migrations/0003_consumption_is_disabled_alter_ingredient_is_disabled.py +23 -0
  8. fnschoo1/canteen/migrations/0004_alter_ingredient_name_category_and_more.py +66 -0
  9. fnschoo1/canteen/migrations/0005_alter_category_created_at_alter_category_name_and_more.py +41 -0
  10. fnschoo1/canteen/migrations/0006_category_is_disabled_alter_category_user_and_more.py +49 -0
  11. fnschoo1/canteen/migrations/0007_alter_consumption_amount_used_and_more.py +30 -0
  12. fnschoo1/canteen/migrations/0008_category_abbreviation_mealtype.py +67 -0
  13. fnschoo1/canteen/migrations/0009_alter_category_abbreviation_and_more.py +55 -0
  14. fnschoo1/canteen/migrations/0010_alter_consumption_options_alter_ingredient_options_and_more.py +215 -0
  15. fnschoo1/canteen/migrations/0011_category_pin_to_consumptions_top.py +23 -0
  16. fnschoo1/canteen/migrations/0012_alter_ingredient_storage_date.py +18 -0
  17. fnschoo1/canteen/models.py +179 -0
  18. fnschoo1/canteen/templates/canteen/category/create.html +17 -0
  19. fnschoo1/canteen/templates/canteen/category/delete.html +61 -0
  20. fnschoo1/canteen/templates/canteen/category/list.html +63 -0
  21. fnschoo1/canteen/templates/canteen/category/update.html +23 -0
  22. fnschoo1/canteen/templates/canteen/close.html +11 -0
  23. fnschoo1/canteen/templates/canteen/consumption/_create.html +19 -0
  24. fnschoo1/canteen/templates/canteen/consumption/create.html +456 -0
  25. fnschoo1/canteen/templates/canteen/ingredient/close.html +11 -0
  26. fnschoo1/canteen/templates/canteen/ingredient/create.html +19 -0
  27. fnschoo1/canteen/templates/canteen/ingredient/create_one.html +17 -0
  28. fnschoo1/canteen/templates/canteen/ingredient/delete.html +41 -0
  29. fnschoo1/canteen/templates/canteen/ingredient/list.html +128 -0
  30. fnschoo1/canteen/templates/canteen/ingredient/update.html +23 -0
  31. fnschoo1/canteen/templates/canteen/meal_type/create.html +17 -0
  32. fnschoo1/canteen/templates/canteen/meal_type/delete.html +56 -0
  33. fnschoo1/canteen/templates/canteen/meal_type/list.html +59 -0
  34. fnschoo1/canteen/templates/canteen/meal_type/update.html +23 -0
  35. fnschoo1/canteen/tests.py +3 -0
  36. fnschoo1/canteen/urls.py +116 -0
  37. fnschoo1/canteen/views.py +814 -0
  38. fnschoo1/canteen/workbook/generate.py +2098 -0
  39. fnschoo1/db.sqlite3 +0 -0
  40. fnschoo1/fnschool/__init__.py +13 -0
  41. fnschoo1/fnschool/asgi.py +16 -0
  42. fnschoo1/fnschool/settings.py +167 -0
  43. fnschoo1/fnschool/templatetags/fnschool_tags.py +27 -0
  44. fnschoo1/fnschool/urls.py +30 -0
  45. fnschoo1/fnschool/views.py +9 -0
  46. fnschoo1/fnschool/wsgi.py +16 -0
  47. fnschoo1/locale/en/LC_MESSAGES/django.mo +0 -0
  48. fnschoo1/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  49. fnschoo1/manage.py +25 -0
  50. fnschoo1/profiles/admin.py +27 -0
  51. fnschoo1/profiles/apps.py +12 -0
  52. fnschoo1/profiles/forms.py +67 -0
  53. fnschoo1/profiles/migrations/0001_initial.py +192 -0
  54. fnschoo1/profiles/migrations/0002_alter_profile_bio.py +20 -0
  55. fnschoo1/profiles/migrations/0003_alter_profile_options_alter_profile_address_and_more.py +67 -0
  56. fnschoo1/profiles/migrations/0004_profile_gender.py +26 -0
  57. fnschoo1/profiles/migrations/0005_alter_profile_gender.py +23 -0
  58. fnschoo1/profiles/models.py +60 -0
  59. fnschoo1/profiles/signals.py +20 -0
  60. fnschoo1/profiles/templates/profiles/create.html +16 -0
  61. fnschoo1/profiles/templates/profiles/detail.html +14 -0
  62. fnschoo1/profiles/templates/profiles/edit.html +12 -0
  63. fnschoo1/profiles/templates/profiles/log_in.html +20 -0
  64. fnschoo1/profiles/templates/profiles/log_out.html +12 -0
  65. fnschoo1/profiles/tests.py +3 -0
  66. fnschoo1/profiles/urls.py +15 -0
  67. fnschoo1/profiles/views.py +63 -0
  68. fnschoo1/static/css/bootstrap.min.css +11776 -0
  69. fnschoo1/static/css/fnschool.css +26 -0
  70. fnschoo1/static/images/favicon.ico +0 -0
  71. fnschoo1/static/js/bootstrap.bundle.min.js +4223 -0
  72. fnschoo1/static/js/bootstrap.min.js +2919 -0
  73. fnschoo1/static/js/fnschool.js +84 -0
  74. fnschoo1/static/js/jquery.min.js +5413 -0
  75. fnschoo1/static/js/jquery.slim.min.js +4331 -0
  76. fnschoo1/static/js/popper.min.js +1306 -0
  77. fnschoo1/static_collected/admin/css/autocomplete.css +377 -0
  78. fnschoo1/static_collected/admin/css/base.css +1224 -0
  79. fnschoo1/static_collected/admin/css/changelists.css +334 -0
  80. fnschoo1/static_collected/admin/css/dark_mode.css +136 -0
  81. fnschoo1/static_collected/admin/css/dashboard.css +30 -0
  82. fnschoo1/static_collected/admin/css/forms.css +546 -0
  83. fnschoo1/static_collected/admin/css/login.css +62 -0
  84. fnschoo1/static_collected/admin/css/nav_sidebar.css +145 -0
  85. fnschoo1/static_collected/admin/css/responsive.css +1043 -0
  86. fnschoo1/static_collected/admin/css/responsive_rtl.css +84 -0
  87. fnschoo1/static_collected/admin/css/rtl.css +311 -0
  88. fnschoo1/static_collected/admin/css/vendor/select2/select2.css +708 -0
  89. fnschoo1/static_collected/admin/css/vendor/select2/select2.min.css +1 -0
  90. fnschoo1/static_collected/admin/css/widgets.css +639 -0
  91. fnschoo1/static_collected/admin/js/SelectBox.js +128 -0
  92. fnschoo1/static_collected/admin/js/SelectFilter2.js +503 -0
  93. fnschoo1/static_collected/admin/js/actions.js +232 -0
  94. fnschoo1/static_collected/admin/js/admin/DateTimeShortcuts.js +496 -0
  95. fnschoo1/static_collected/admin/js/admin/RelatedObjectLookups.js +276 -0
  96. fnschoo1/static_collected/admin/js/autocomplete.js +33 -0
  97. fnschoo1/static_collected/admin/js/calendar.js +251 -0
  98. fnschoo1/static_collected/admin/js/cancel.js +29 -0
  99. fnschoo1/static_collected/admin/js/change_form.js +21 -0
  100. fnschoo1/static_collected/admin/js/collapse.js +43 -0
  101. fnschoo1/static_collected/admin/js/core.js +174 -0
  102. fnschoo1/static_collected/admin/js/filters.js +37 -0
  103. fnschoo1/static_collected/admin/js/inlines.js +439 -0
  104. fnschoo1/static_collected/admin/js/jquery.init.js +8 -0
  105. fnschoo1/static_collected/admin/js/nav_sidebar.js +81 -0
  106. fnschoo1/static_collected/admin/js/popup_response.js +24 -0
  107. fnschoo1/static_collected/admin/js/prepopulate.js +43 -0
  108. fnschoo1/static_collected/admin/js/prepopulate_init.js +20 -0
  109. fnschoo1/static_collected/admin/js/theme.js +57 -0
  110. fnschoo1/static_collected/admin/js/urlify.js +529 -0
  111. fnschoo1/static_collected/admin/js/vendor/jquery/jquery.js +10913 -0
  112. fnschoo1/static_collected/admin/js/vendor/jquery/jquery.min.js +2 -0
  113. fnschoo1/static_collected/admin/js/vendor/select2/i18n/af.js +43 -0
  114. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ar.js +36 -0
  115. fnschoo1/static_collected/admin/js/vendor/select2/i18n/az.js +33 -0
  116. fnschoo1/static_collected/admin/js/vendor/select2/i18n/bg.js +38 -0
  117. fnschoo1/static_collected/admin/js/vendor/select2/i18n/bn.js +39 -0
  118. fnschoo1/static_collected/admin/js/vendor/select2/i18n/bs.js +48 -0
  119. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ca.js +41 -0
  120. fnschoo1/static_collected/admin/js/vendor/select2/i18n/cs.js +62 -0
  121. fnschoo1/static_collected/admin/js/vendor/select2/i18n/da.js +37 -0
  122. fnschoo1/static_collected/admin/js/vendor/select2/i18n/de.js +41 -0
  123. fnschoo1/static_collected/admin/js/vendor/select2/i18n/dsb.js +51 -0
  124. fnschoo1/static_collected/admin/js/vendor/select2/i18n/el.js +43 -0
  125. fnschoo1/static_collected/admin/js/vendor/select2/i18n/en.js +41 -0
  126. fnschoo1/static_collected/admin/js/vendor/select2/i18n/es.js +41 -0
  127. fnschoo1/static_collected/admin/js/vendor/select2/i18n/et.js +38 -0
  128. fnschoo1/static_collected/admin/js/vendor/select2/i18n/eu.js +45 -0
  129. fnschoo1/static_collected/admin/js/vendor/select2/i18n/fa.js +42 -0
  130. fnschoo1/static_collected/admin/js/vendor/select2/i18n/fi.js +42 -0
  131. fnschoo1/static_collected/admin/js/vendor/select2/i18n/fr.js +43 -0
  132. fnschoo1/static_collected/admin/js/vendor/select2/i18n/gl.js +40 -0
  133. fnschoo1/static_collected/admin/js/vendor/select2/i18n/he.js +44 -0
  134. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hi.js +40 -0
  135. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hr.js +45 -0
  136. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hsb.js +51 -0
  137. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hu.js +44 -0
  138. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hy.js +40 -0
  139. fnschoo1/static_collected/admin/js/vendor/select2/i18n/id.js +36 -0
  140. fnschoo1/static_collected/admin/js/vendor/select2/i18n/is.js +37 -0
  141. fnschoo1/static_collected/admin/js/vendor/select2/i18n/it.js +43 -0
  142. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ja.js +40 -0
  143. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ka.js +42 -0
  144. fnschoo1/static_collected/admin/js/vendor/select2/i18n/km.js +38 -0
  145. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ko.js +42 -0
  146. fnschoo1/static_collected/admin/js/vendor/select2/i18n/lt.js +45 -0
  147. fnschoo1/static_collected/admin/js/vendor/select2/i18n/lv.js +41 -0
  148. fnschoo1/static_collected/admin/js/vendor/select2/i18n/mk.js +42 -0
  149. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ms.js +38 -0
  150. fnschoo1/static_collected/admin/js/vendor/select2/i18n/nb.js +38 -0
  151. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ne.js +44 -0
  152. fnschoo1/static_collected/admin/js/vendor/select2/i18n/nl.js +46 -0
  153. fnschoo1/static_collected/admin/js/vendor/select2/i18n/pl.js +43 -0
  154. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ps.js +41 -0
  155. fnschoo1/static_collected/admin/js/vendor/select2/i18n/pt-BR.js +39 -0
  156. fnschoo1/static_collected/admin/js/vendor/select2/i18n/pt.js +41 -0
  157. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ro.js +43 -0
  158. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ru.js +48 -0
  159. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sk.js +61 -0
  160. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sl.js +41 -0
  161. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sq.js +43 -0
  162. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sr-Cyrl.js +48 -0
  163. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sr.js +48 -0
  164. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sv.js +40 -0
  165. fnschoo1/static_collected/admin/js/vendor/select2/i18n/th.js +36 -0
  166. fnschoo1/static_collected/admin/js/vendor/select2/i18n/tk.js +36 -0
  167. fnschoo1/static_collected/admin/js/vendor/select2/i18n/tr.js +40 -0
  168. fnschoo1/static_collected/admin/js/vendor/select2/i18n/uk.js +59 -0
  169. fnschoo1/static_collected/admin/js/vendor/select2/i18n/vi.js +37 -0
  170. fnschoo1/static_collected/admin/js/vendor/select2/i18n/zh-CN.js +36 -0
  171. fnschoo1/static_collected/admin/js/vendor/select2/i18n/zh-TW.js +33 -0
  172. fnschoo1/static_collected/admin/js/vendor/select2/select2.full.js +7115 -0
  173. fnschoo1/static_collected/admin/js/vendor/select2/select2.full.min.js +2 -0
  174. fnschoo1/static_collected/admin/js/vendor/xregexp/xregexp.js +4993 -0
  175. fnschoo1/static_collected/admin/js/vendor/xregexp/xregexp.min.js +160 -0
  176. fnschoo1/static_collected/css/bootstrap.min.css +11776 -0
  177. fnschoo1/static_collected/css/fnschool.css +26 -0
  178. fnschoo1/static_collected/images/favicon.ico +0 -0
  179. fnschoo1/static_collected/js/bootstrap.bundle.min.js +4223 -0
  180. fnschoo1/static_collected/js/bootstrap.min.js +2919 -0
  181. fnschoo1/static_collected/js/fnschool.js +84 -0
  182. fnschoo1/static_collected/js/jquery.min.js +5413 -0
  183. fnschoo1/static_collected/js/jquery.slim.min.js +4331 -0
  184. fnschoo1/static_collected/js/popper.min.js +1306 -0
  185. fnschoo1/templates/base/_css.html +1 -0
  186. fnschoo1/templates/base/_js.html +15 -0
  187. fnschoo1/templates/base/content.html +30 -0
  188. fnschoo1/templates/base/header_content_footer.html +35 -0
  189. fnschoo1/templates/close.html +11 -0
  190. fnschoo1/templates/home.html +51 -0
  191. fnschoo1/templates/includes/_footer.html +39 -0
  192. fnschoo1/templates/includes/_header.html +77 -0
  193. fnschoo1/templates/includes/_navigation.html +0 -0
  194. fnschoo1/templates/includes/_paginator.html +27 -0
  195. fnschoo1/templates/registration/logged_out.html +0 -0
  196. fnschoo1/templates/registration/login.html +0 -0
  197. fnschool-20251011.81638.854.dist-info/METADATA +179 -0
  198. fnschool-20251011.81638.854.dist-info/RECORD +209 -0
  199. {fnschool-20250109.80531.837.dist-info → fnschool-20251011.81638.854.dist-info}/WHEEL +1 -1
  200. fnschool-20251011.81638.854.dist-info/entry_points.txt +2 -0
  201. fnschool-20251011.81638.854.dist-info/top_level.txt +1 -0
  202. fnschool/__init__.py +0 -35
  203. fnschool/__main__.py +0 -16
  204. fnschool/app.py +0 -103
  205. fnschool/canteen/__init__.py +0 -3
  206. fnschool/canteen/__main__.py +0 -3
  207. fnschool/canteen/bill.py +0 -253
  208. fnschool/canteen/canteen.py +0 -1
  209. fnschool/canteen/canteen.toml +0 -61
  210. fnschool/canteen/config.py +0 -10
  211. fnschool/canteen/consuming.py +0 -53
  212. fnschool/canteen/currency.py +0 -17
  213. fnschool/canteen/data/bill.i18n.xlsx +0 -0
  214. fnschool/canteen/data/bill.xlsx +0 -0
  215. fnschool/canteen/data/consuming.xlsx +0 -0
  216. fnschool/canteen/data/purchase_list.xlsx +0 -0
  217. fnschool/canteen/entry.py +0 -40
  218. fnschool/canteen/food.py +0 -206
  219. fnschool/canteen/food_classes.py +0 -33
  220. fnschool/canteen/food_classes.toml +0 -64
  221. fnschool/canteen/operator.py +0 -91
  222. fnschool/canteen/path.py +0 -28
  223. fnschool/canteen/spreadsheet/base.py +0 -213
  224. fnschool/canteen/spreadsheet/consuming.py +0 -310
  225. fnschool/canteen/spreadsheet/consumingsum.py +0 -76
  226. fnschool/canteen/spreadsheet/cover.py +0 -64
  227. fnschool/canteen/spreadsheet/ctspreadsheet.py +0 -351
  228. fnschool/canteen/spreadsheet/food.py +0 -680
  229. fnschool/canteen/spreadsheet/inventory.py +0 -375
  230. fnschool/canteen/spreadsheet/merging.py +0 -340
  231. fnschool/canteen/spreadsheet/preconsuming.py +0 -329
  232. fnschool/canteen/spreadsheet/purchasing.py +0 -885
  233. fnschool/canteen/spreadsheet/purchasingsum.py +0 -110
  234. fnschool/canteen/spreadsheet/spreadsheet.py +0 -363
  235. fnschool/canteen/spreadsheet/translating.py +0 -12
  236. fnschool/canteen/spreadsheet/unwarehousing.py +0 -178
  237. fnschool/canteen/spreadsheet/unwarehousingsum.py +0 -11
  238. fnschool/canteen/spreadsheet/warehousing.py +0 -360
  239. fnschool/canteen/spreadsheet/workbook.py +0 -17
  240. fnschool/canteen/test.py +0 -97
  241. fnschool/config.py +0 -48
  242. fnschool/entry.py +0 -67
  243. fnschool/exam/__init__.py +0 -8
  244. fnschool/exam/data/parental_emails.xlsx +0 -0
  245. fnschool/exam/data/score.xlsx +0 -0
  246. fnschool/exam/email.py +0 -349
  247. fnschool/exam/entry.py +0 -36
  248. fnschool/exam/language.py +0 -19
  249. fnschool/exam/path.py +0 -24
  250. fnschool/exam/score.py +0 -1191
  251. fnschool/exam/subject.py +0 -20
  252. fnschool/exam/teacher.py +0 -54
  253. fnschool/external.py +0 -89
  254. fnschool/games/__init__.py +0 -1
  255. fnschool/games/__main__.py +0 -1
  256. fnschool/games/games.py +0 -1
  257. fnschool/inoutput.py +0 -97
  258. fnschool/language.py +0 -40
  259. fnschool/locales/en_US/LC_MESSAGES/fnschool.mo +0 -0
  260. fnschool/locales/zh_CN/LC_MESSAGES/fnschool.mo +0 -0
  261. fnschool/locales/zh_HK/LC_MESSAGES/fnschool.mo +0 -0
  262. fnschool/locales/zh_SG/LC_MESSAGES/fnschool.mo +0 -0
  263. fnschool/locales/zh_TW/LC_MESSAGES/fnschool.mo +0 -0
  264. fnschool/path.py +0 -45
  265. fnschool/test.py +0 -24
  266. fnschool/user.py +0 -262
  267. fnschool-20250109.80531.837.dist-info/METADATA +0 -342
  268. fnschool-20250109.80531.837.dist-info/RECORD +0 -78
  269. fnschool-20250109.80531.837.dist-info/entry_points.txt +0 -5
  270. fnschool-20250109.80531.837.dist-info/top_level.txt +0 -1
  271. /fnschool/canteen/consume.py → /fnschoo1/canteen/__init__.py +0 -0
  272. /fnschool/canteen/food_recount.toml → /fnschoo1/canteen/migrations/__init__.py +0 -0
  273. {fnschool/canteen/spreadsheet → fnschoo1/canteen/workbook}/__init__.py +0 -0
  274. /fnschool/exam/__main__.py → /fnschoo1/fnschool/templatetags/__init__.py +0 -0
  275. /fnschool/canteen/food_recounts.toml → /fnschoo1/profiles/__init__.py +0 -0
  276. /fnschool/canteen/warehouse.py → /fnschoo1/profiles/migrations/__init__.py +0 -0
  277. /fnschool/canteen/workbook.toml → /fnschoo1/templates/base/_content.html +0 -0
  278. {fnschool-20250109.80531.837.dist-info → fnschool-20251011.81638.854.dist-info/licenses}/LICENSE +0 -0
fnschool/exam/email.py DELETED
@@ -1,349 +0,0 @@
1
- import smtplib
2
- import email.utils
3
- from email import encoders
4
- from email.mime.multipart import MIMEMultipart
5
- from email.mime.text import MIMEText
6
- from email.mime.image import MIMEImage
7
- from email.mime.base import MIMEBase
8
-
9
- from redmail import EmailSender
10
-
11
- import shutil
12
- from fnschool import *
13
- from fnschool.exam import *
14
- from fnschool.exam.path import *
15
-
16
-
17
- class Email:
18
- def __init__(self, score=None):
19
- self._fpath = None
20
- self.score = score
21
- self._teacher = None
22
- self.fext0 = ".xlsx"
23
- self._wb = None
24
- self._sheet0 = None
25
- self._email = None
26
- self._html = None
27
- self.host_key = _("smtp_host")
28
- self.port_key = _("smtp_port")
29
- self.user_name_key = _("smtp_user_name")
30
- self.passw0rd_key = _("smtp_password")
31
- self._chaperones = None
32
- pass
33
-
34
- @property
35
- def chaperones(self):
36
- if not self._chaperones:
37
- _chaperones0 = [
38
- _("self"),
39
- _("dad"),
40
- _("mum"),
41
- _("father’s father"),
42
- _("father's mother"),
43
- _("mother's father"),
44
- _("mother's mother"),
45
- _("father's older brother"),
46
- _("father's younger brother"),
47
- _("father's sister"),
48
- _("father's sister's husband"),
49
- _("mother's sister"),
50
- _("mother's sister's husband"),
51
- _("relative"),
52
- _("friend"),
53
- _("parent"),
54
- _("chaperone"),
55
- ]
56
- _chaperones = _chaperones0 if is_zh_CN else _chaperones0
57
- self._chaperones = _chaperones
58
- return self._chaperones
59
- pass
60
-
61
- @property
62
- def html(self):
63
- if not self._html:
64
- html = None
65
- with open(
66
- self.teacher.scores_html_fpath, "r+", encoding="utf-8"
67
- ) as f:
68
- html = f.read()
69
- self._html = html
70
- return self._html
71
-
72
- @property
73
- def host(self):
74
- h = self.teacher.get_profile(
75
- self.host_key,
76
- info=_("Tell {0} your SMTP server host, please!").format(app_name),
77
- )
78
- return h
79
-
80
- @property
81
- def port(self):
82
- p = self.teacher.get_profile(
83
- self.port_key,
84
- info=_("Tell {0} your SMTP server port, please!").format(app_name),
85
- )
86
- p = int(p)
87
- return p
88
-
89
- @property
90
- def user_name(self):
91
- u = self.teacher.get_profile(
92
- self.user_name_key,
93
- info=_("Tell {0} your user name at SMTP server, please!").format(
94
- app_name
95
- ),
96
- )
97
- return u
98
-
99
- @property
100
- def passw0rd(self):
101
- p = self.teacher.get_profile(
102
- self.passw0rd_key,
103
- _("Tell {0} your password for SMTP server, please!").format(
104
- app_name
105
- ),
106
- )
107
- return p
108
-
109
- @property
110
- def email(self):
111
- if not self._email:
112
- from smtplib import SMTP_SSL, SMTP, LMTP
113
-
114
- email = EmailSender(
115
- host=self.host,
116
- port=self.port,
117
- username=self.user_name,
118
- password=self.passw0rd,
119
- use_starttls=True,
120
- )
121
- self._email = email
122
- return self._email
123
-
124
- def send_scores(self):
125
- print_info(
126
- _(
127
- "Hey! {0}, do you want to "
128
- + "send these scores of students"
129
- + " to chaperones? (Yes: 'Y','y')"
130
- ).format(self.teacher.name)
131
- )
132
- s_input = get_input()
133
- if s_input and s_input in "Yy":
134
- scores_img_fpaths = self.score.scores_img_fpaths
135
- msg_subject = _('The scores of Test "{0}"').format(
136
- self.score.full_name
137
- )
138
-
139
- student_names = self.score.student_names
140
- scores_img_fpaths_len = len(scores_img_fpaths)
141
- scores_img_fpaths_len2 = len(str(scores_img_fpaths_len))
142
- student_names_lenx = max([get_len(n) for n in student_names])
143
- chaperone_lenx = 0
144
-
145
- get_full_chaperone = lambda chaperone: (
146
- student_name
147
- + (
148
- ""
149
- if chaperone == self.chaperones[0]
150
- else _("'s") + chaperone
151
- )
152
- if is_zh_CN
153
- else (
154
- student_name + "' " + chaperone
155
- if student_name.endswith("s")
156
- else student_name + "s' " + chaperone
157
- )
158
- )
159
- get_full_chaperone0 = lambda chaperone, email: (
160
- f"{email}({chaperone})"
161
- )
162
-
163
- for student_name, __, __0 in scores_img_fpaths:
164
- chaperones_emails = self.get_chaperones_emails(student_name)
165
- for chaperone, cemails in chaperones_emails:
166
- for cemail in cemails:
167
- chaperone0 = get_full_chaperone0(
168
- get_full_chaperone(chaperone), cemail
169
- )
170
- lenx = get_len(chaperone0)
171
- if lenx > chaperone_lenx:
172
- chaperone_lenx = lenx
173
-
174
- for i, (
175
- student_name,
176
- scores_m1_img_fpath,
177
- scores_img_fpath,
178
- ) in enumerate(scores_img_fpaths):
179
- chaperones_emails = self.get_chaperones_emails(student_name)
180
- if not chaperones_emails:
181
- print_warning(
182
- f"[{i+1:>{scores_img_fpaths_len2}}] "
183
- + _(
184
- "There is no emails of "
185
- + "chaperones for {0}. Skip."
186
- )
187
- )
188
- continue
189
-
190
- student_name0 = (
191
- student_name[0] + " " + student_name[1]
192
- if (
193
- all([is_zh_CN_char(c) for c in student_name])
194
- and len(student_name) == 2
195
- )
196
- else student_name
197
- )
198
- student_name_len_diff = (
199
- student_names_lenx
200
- - get_zh_CN_chars_len(student_name0)
201
- - len(student_name0)
202
- )
203
- student_name0 = " " * student_name_len_diff + student_name0
204
-
205
- for chaperone, cemails in chaperones_emails:
206
- for cemail in cemails:
207
- chaperone = get_full_chaperone(chaperone)
208
- sender = (
209
- _("Teacher {0}")
210
- if is_zh_CN
211
- else (
212
- _("Mr. {0}")
213
- if self.teacher.is_male
214
- else _("Ms. {0}")
215
- )
216
- ).format(self.teacher.name)
217
- chaperone0 = get_full_chaperone0(chaperone, cemail)
218
- chaperone_len_diff = (
219
- chaperone_lenx
220
- - get_zh_CN_chars_len(chaperone0)
221
- - len(chaperone0)
222
- )
223
-
224
- self.email.send(
225
- subject=msg_subject,
226
- receivers=[cemail],
227
- html=self.html,
228
- body_images={
229
- "scores_img": scores_m1_img_fpath,
230
- "scores_m1_img": scores_img_fpath,
231
- },
232
- body_params={
233
- "chaperone": chaperone,
234
- "scores_s": _(
235
- 'The "{0}" scores of {1} are: '
236
- ).format(self.score.full_name, student_name),
237
- "sender": sender,
238
- },
239
- )
240
-
241
- print_info(
242
- f"[{i+1:>{scores_img_fpaths_len2}}/{scores_img_fpaths_len}] "
243
- + _(
244
- 'The scores information of "{0}" has been '
245
- + "sent to {2}{1}"
246
- ).format(
247
- student_name0,
248
- chaperone0,
249
- " " * chaperone_len_diff,
250
- )
251
- )
252
-
253
- @property
254
- def wb(self):
255
- if not self._wb:
256
- self._wb = load_workbook(self.fpath)
257
- return self._wb
258
-
259
- @property
260
- def sheet0(self):
261
- wb = self.wb
262
- if not self._sheet0:
263
- self._sheet0 = wb[wb.sheetnames[0]]
264
- return self._sheet0
265
-
266
- @property
267
- def teacher(self):
268
- if not self._teacher:
269
- self._teacher = self.score.teacher
270
- return self._teacher
271
-
272
- def get_chaperones_emails(self, student_name):
273
- emails = []
274
- student_name = student_name
275
- sheet = self.sheet0
276
- for col_i in range(2, sheet.max_column + 1):
277
- if sheet.cell(1, col_i).value == student_name:
278
- for row_i in range(2, sheet.max_row + 1):
279
- cemails = sheet.cell(row_i, col_i).value
280
- if cemails:
281
- chaperone = sheet.cell(row_i, 1).value
282
- cemails = (
283
- cemails.replace("/", " ")
284
- .replace("、", " ")
285
- .replace("|", " ")
286
- .replace(";", " ")
287
- .replace(":", " ")
288
- .replace("\n", " ")
289
- .strip()
290
- .split(" ")
291
- )
292
- emails.append([chaperone, cemails])
293
-
294
- if not emails:
295
- return None
296
-
297
- return emails
298
-
299
- @property
300
- def fpath(self):
301
- if not self._fpath:
302
- fpath = self.score.sclass_dpath / (
303
- _("parental_emails") + self.fext0
304
- )
305
- if not fpath.exists():
306
- fpath0 = parental_emails_fpath0
307
- shutil.copy(fpath0, fpath)
308
- print_warning(
309
- _(
310
- 'Parental emails spreadsheet "{0}"'
311
- + ' doesn\'t exist, spreadsheet "{1}"'
312
- + ' was copied to "{0}".'
313
- ).format(fpath, fpath0)
314
- )
315
- wb = load_workbook(fpath)
316
- sheet = wb[wb.sheetnames[0]]
317
- for i, sname in enumerate(self.score.student_names):
318
- sheet.cell(1, 2 + i, sname)
319
-
320
- chaperone_row_offset = 2
321
- for i, chaperone in enumerate(self.chaperones):
322
- sheet.cell(i + chaperone_row_offset, 1, chaperone)
323
- wb.save(fpath)
324
-
325
- print_info(
326
- _(
327
- "The student's name has been filled "
328
- + 'in spreadsheet "{0}".'
329
- + " Please fill in the email "
330
- + "addresses according to the "
331
- + "comments. (Ok! open the file for "
332
- + "me. [Press any key to open it])"
333
- ).format(fpath)
334
- )
335
- get_input()
336
- open_path(fpath)
337
- print_info(
338
- _(
339
- "(Ok! I have filled them in? [Press any key to continue])"
340
- )
341
- )
342
- get_input()
343
-
344
- self._fpath = fpath
345
-
346
- return self._fpath
347
-
348
-
349
- # The end.
fnschool/exam/entry.py DELETED
@@ -1,36 +0,0 @@
1
- import os
2
- import sys
3
- from fnschool import *
4
-
5
-
6
- def set_exam(args):
7
- from fnschool.exam.score import Score
8
-
9
- print_app()
10
-
11
- if args.action in "enter":
12
- score = Score()
13
- score.enter()
14
- elif args.action in "read":
15
- score = Score()
16
- score.read()
17
- else:
18
- print_info(_("Function is not found."))
19
-
20
-
21
- def parse_exam(subparsers):
22
- parser_exam = subparsers.add_parser(
23
- "exam", help=_("Examination related functions.")
24
- )
25
- parser_exam.add_argument(
26
- "action",
27
- choices=["enter", "read"],
28
- help=_(
29
- '"enter": Enter the examination scores. '
30
- + '"read": Read the examination scores.'
31
- ),
32
- )
33
- parser_exam.set_defaults(func=set_exam)
34
-
35
-
36
- # The end.
fnschool/exam/language.py DELETED
@@ -1,19 +0,0 @@
1
- import matplotlib
2
- import matplotlib.font_manager as fm
3
- from fnschool.language import *
4
-
5
- if is_zh_CN:
6
- ttves = fm.fontManager.ttflist
7
- ttves = [
8
- f.name
9
- for f in ttves
10
- if (
11
- "hei" in f.name.lower()
12
- or "cjk" in f.name.lower()
13
- or "kai" in f.name.lower()
14
- or "song" in f.name.lower()
15
- or "ming" in f.name.lower()
16
- )
17
- ]
18
- random.shuffle(ttves)
19
- matplotlib.rcParams["font.family"] = ttves
fnschool/exam/path.py DELETED
@@ -1,24 +0,0 @@
1
- import os
2
- import sys
3
- from fnschool import *
4
-
5
- exam_dpath = Path(__file__).parent
6
- exam_data_dpath = exam_dpath / "data"
7
- user_exam_dpath = user_data_dir / _("exam")
8
- teach_name_fpath = user_exam_dpath / (_("teacher_name") + ".txt")
9
- score_fpath0 = exam_data_dpath / "score.xlsx"
10
- parental_emails_fpath0 = exam_data_dpath / "parental_emails.xlsx"
11
-
12
- for d in [
13
- user_exam_dpath,
14
- ]:
15
- if not d.exists():
16
- os.makedirs(d.as_posix(), exist_ok=True)
17
-
18
- if not teach_name_fpath.exists():
19
- if not teach_name_fpath.parent.exists():
20
- os.makedirs(teach_name_fpath.parent.as_posix(), exist_ok=True)
21
- with open(teach_name_fpath, "w", encoding="utf-8") as f:
22
- f.write("")
23
-
24
- # The end.