educommon 3.13.0__py3-none-any.whl → 3.13.2__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.
Files changed (220) hide show
  1. educommon/__init__.py +0 -1
  2. educommon/about/ui/actions.py +16 -30
  3. educommon/about/ui/ui.py +3 -12
  4. educommon/about/utils.py +6 -5
  5. educommon/async_task/__init__.py +0 -1
  6. educommon/async_task/actions.py +18 -13
  7. educommon/async_task/apps.py +4 -0
  8. educommon/async_task/locker.py +2 -5
  9. educommon/async_task/migrations/0001_initial.py +55 -9
  10. educommon/async_task/migrations/0002_task_type_and_status_data.py +94 -89
  11. educommon/async_task/migrations/0003_alter_runningtask_options.py +0 -1
  12. educommon/async_task/models.py +9 -6
  13. educommon/async_task/tasks.py +11 -7
  14. educommon/async_task/ui.py +16 -35
  15. educommon/async_tasks/__init__.py +0 -1
  16. educommon/async_tasks/apps.py +4 -0
  17. educommon/async_tasks/locks.py +11 -21
  18. educommon/async_tasks/migrations/0001_initial.py +68 -8
  19. educommon/async_tasks/migrations/0002_load_initial_data.py +0 -1
  20. educommon/async_tasks/models.py +9 -29
  21. educommon/async_tasks/tasks.py +25 -54
  22. educommon/audit_log/__init__.py +1 -0
  23. educommon/audit_log/actions.py +27 -36
  24. educommon/audit_log/app_meta.py +7 -4
  25. educommon/audit_log/apps.py +44 -29
  26. educommon/audit_log/constants.py +7 -4
  27. educommon/audit_log/error_log/actions.py +1 -3
  28. educommon/audit_log/helpers.py +2 -4
  29. educommon/audit_log/management/commands/reinstall_audit_log.py +11 -7
  30. educommon/audit_log/migrations/0001_initial.py +91 -16
  31. educommon/audit_log/migrations/0002_install_audit_log.py +13 -13
  32. educommon/audit_log/migrations/0003_logproxy.py +1 -3
  33. educommon/audit_log/migrations/0004_reinstall_audit_log.py +1 -4
  34. educommon/audit_log/migrations/0005_postgresql_error.py +4 -2
  35. educommon/audit_log/migrations/0006_auto_20200806_1707.py +3 -4
  36. educommon/audit_log/migrations/0007_create_selective_tables_function.py +8 -5
  37. educommon/audit_log/migrations/0008_table_logged.py +0 -1
  38. educommon/audit_log/migrations/0009_reinstall_audit_log.py +0 -1
  39. educommon/audit_log/models.py +36 -42
  40. educommon/audit_log/permissions.py +11 -9
  41. educommon/audit_log/proxies.py +12 -23
  42. educommon/audit_log/ui.py +18 -15
  43. educommon/audit_log/utils/__init__.py +28 -60
  44. educommon/audit_log/utils/operations.py +16 -2
  45. educommon/auth/__init__.py +0 -3
  46. educommon/auth/rbac/__init__.py +2 -4
  47. educommon/auth/rbac/actions.py +148 -145
  48. educommon/auth/rbac/app_meta.py +9 -6
  49. educommon/auth/rbac/backends/base.py +2 -8
  50. educommon/auth/rbac/backends/caching.py +27 -37
  51. educommon/auth/rbac/backends/simple.py +1 -4
  52. educommon/auth/rbac/checker.py +1 -3
  53. educommon/auth/rbac/management/commands/rbac.py +6 -11
  54. educommon/auth/rbac/manager.py +18 -47
  55. educommon/auth/rbac/migrations/0001_initial.py +73 -12
  56. educommon/auth/rbac/migrations/0002_model_modifier_metaclass_fix.py +7 -6
  57. educommon/auth/rbac/migrations/0003_permission_hidden.py +1 -5
  58. educommon/auth/rbac/migrations/0004_auto_20171024_1245.py +26 -19
  59. educommon/auth/rbac/models.py +63 -68
  60. educommon/auth/rbac/permissions.py +6 -7
  61. educommon/auth/rbac/ui.py +83 -84
  62. educommon/auth/rbac/utils.py +10 -11
  63. educommon/auth/rbac/validators.py +4 -5
  64. educommon/auth/simple_auth/__init__.py +1 -5
  65. educommon/auth/simple_auth/actions.py +79 -92
  66. educommon/auth/simple_auth/app_meta.py +2 -9
  67. educommon/auth/simple_auth/checkers.py +3 -3
  68. educommon/auth/simple_auth/migrations/0001_initial.py +23 -4
  69. educommon/auth/simple_auth/validators.py +0 -1
  70. educommon/contingent/actions.py +7 -7
  71. educommon/contingent/app_meta.py +1 -4
  72. educommon/contingent/base.py +10 -15
  73. educommon/contingent/catalogs.py +424 -540
  74. educommon/contingent/contingent_plugin/actions.py +4 -15
  75. educommon/contingent/contingent_plugin/apps.py +10 -4
  76. educommon/contingent/contingent_plugin/migrations/0001_initial.py +5 -6
  77. educommon/contingent/contingent_plugin/migrations/0002_add_contingent_model_deleted.py +6 -11
  78. educommon/contingent/contingent_plugin/model_views.py +2 -12
  79. educommon/contingent/contingent_plugin/models.py +2 -7
  80. educommon/contingent/contingent_plugin/observer.py +14 -13
  81. educommon/contingent/contingent_plugin/plugin_meta.py +1 -3
  82. educommon/contingent/contingent_plugin/storage.py +8 -7
  83. educommon/contingent/contingent_plugin/utils.py +6 -6
  84. educommon/django/db/fields.py +72 -86
  85. educommon/django/db/migration/__init__.py +3 -7
  86. educommon/django/db/migration/operations.py +29 -51
  87. educommon/django/db/mixins/__init__.py +16 -10
  88. educommon/django/db/mixins/date_interval.py +47 -75
  89. educommon/django/db/mixins/validation.py +26 -26
  90. educommon/django/db/model_view/__init__.py +18 -22
  91. educommon/django/db/models.py +9 -8
  92. educommon/django/db/observer.py +9 -27
  93. educommon/django/db/partitioning/__init__.py +66 -92
  94. educommon/django/db/partitioning/management/commands/apply_partitioning.py +3 -13
  95. educommon/django/db/partitioning/management/commands/clear_table.py +18 -14
  96. educommon/django/db/partitioning/management/commands/split_table.py +18 -13
  97. educommon/django/db/routers.py +6 -15
  98. educommon/django/db/signals.py +4 -2
  99. educommon/django/db/utils.py +14 -19
  100. educommon/django/db/validators/__init__.py +1 -0
  101. educommon/django/db/validators/simple.py +72 -100
  102. educommon/django/storages/atcfs/api.py +39 -53
  103. educommon/django/storages/atcfs/app_meta.py +1 -1
  104. educommon/django/storages/atcfs/management/commands/atcfs_migrate.py +42 -55
  105. educommon/django/storages/atcfs/models.py +0 -3
  106. educommon/django/storages/atcfs/monkey_patching.py +18 -12
  107. educommon/django/storages/atcfs/storage.py +14 -23
  108. educommon/extjs/fields/input_params.py +15 -45
  109. educommon/importer/XLSReader.py +143 -241
  110. educommon/importer/__init__.py +86 -4
  111. educommon/importer/api.py +53 -84
  112. educommon/importer/constants.py +4 -14
  113. educommon/importer/loggers.py +16 -26
  114. educommon/importer/proxy.py +131 -176
  115. educommon/importer/proxy_import.py +11 -12
  116. educommon/importer/report.py +4 -6
  117. educommon/importer/ui.py +32 -26
  118. educommon/importer/validators.py +4 -7
  119. educommon/integration_entities/helpers.py +14 -18
  120. educommon/ioc/__init__.py +3 -6
  121. educommon/logger/loggers.py +10 -14
  122. educommon/m3/__init__.py +20 -38
  123. educommon/m3/extensions/__init__.py +1 -0
  124. educommon/m3/extensions/listeners/__init__.py +22 -38
  125. educommon/m3/extensions/listeners/delete_check/listeners.py +31 -41
  126. educommon/m3/extensions/listeners/delete_check/mixins.py +20 -25
  127. educommon/m3/extensions/listeners/delete_check/signals.py +2 -2
  128. educommon/m3/extensions/listeners/delete_check/ui.py +15 -14
  129. educommon/m3/extensions/listeners/delete_check/utils.py +9 -11
  130. educommon/m3/extensions/ui.py +15 -33
  131. educommon/m3/transaction_context.py +17 -19
  132. educommon/objectpack/actions.py +70 -88
  133. educommon/objectpack/apps.py +5 -0
  134. educommon/objectpack/filters.py +9 -15
  135. educommon/objectpack/ui.py +59 -77
  136. educommon/report/__init__.py +9 -5
  137. educommon/report/actions.py +29 -32
  138. educommon/report/constructor/__init__.py +5 -8
  139. educommon/report/constructor/app_meta.py +1 -3
  140. educommon/report/constructor/apps.py +1 -0
  141. educommon/report/constructor/base.py +33 -80
  142. educommon/report/constructor/builders/excel/_base.py +138 -286
  143. educommon/report/constructor/builders/excel/_header.py +2 -9
  144. educommon/report/constructor/builders/excel/product.py +13 -34
  145. educommon/report/constructor/builders/excel/with_merged_cells.py +18 -14
  146. educommon/report/constructor/config.py +2 -0
  147. educommon/report/constructor/editor/actions.py +101 -215
  148. educommon/report/constructor/editor/ui.py +71 -93
  149. educommon/report/constructor/exceptions.py +6 -12
  150. educommon/report/constructor/migrations/0001_initial.py +36 -44
  151. educommon/report/constructor/migrations/0002_report_filters.py +86 -72
  152. educommon/report/constructor/migrations/0003_reportfilter_exclude.py +5 -5
  153. educommon/report/constructor/migrations/0004_reportfilter_fields.py +22 -18
  154. educommon/report/constructor/migrations/0005_reportcolumn_visible.py +5 -4
  155. educommon/report/constructor/migrations/0006_reportsorting.py +21 -17
  156. educommon/report/constructor/migrations/0007_include_available_units.py +14 -14
  157. educommon/report/constructor/migrations/0008_auto_20170407_1318.py +4 -5
  158. educommon/report/constructor/migrations/0009_auto_20180405_0642.py +1 -4
  159. educommon/report/constructor/migrations/0010_add_aggregate_fields.py +7 -8
  160. educommon/report/constructor/mixins.py +14 -15
  161. educommon/report/constructor/models.py +76 -124
  162. educommon/report/constructor/utils.py +3 -8
  163. educommon/report/constructor/validators.py +1 -3
  164. educommon/report/reporter.py +25 -43
  165. educommon/report/utils.py +14 -40
  166. educommon/rest/actions.py +7 -11
  167. educommon/rest/context.py +6 -16
  168. educommon/rest/controllers.py +10 -10
  169. educommon/rest/mixins.py +29 -27
  170. educommon/secure_media/app_meta.py +9 -9
  171. educommon/utils/__init__.py +3 -2
  172. educommon/utils/caching.py +1 -3
  173. educommon/utils/conversion.py +1 -3
  174. educommon/utils/crypto.py +1 -2
  175. educommon/utils/date.py +13 -26
  176. educommon/utils/db/__init__.py +17 -26
  177. educommon/utils/db/postgresql.py +1 -4
  178. educommon/utils/fonts/__init__.py +3 -4
  179. educommon/utils/licence/__init__.py +5 -16
  180. educommon/utils/misc.py +9 -18
  181. educommon/utils/object_grid.py +55 -62
  182. educommon/utils/phone_number/modelfields.py +1 -3
  183. educommon/utils/phone_number/phone_number.py +5 -8
  184. educommon/utils/phone_number/validators.py +8 -23
  185. educommon/utils/plugins.py +15 -28
  186. educommon/utils/registry.py +2 -1
  187. educommon/utils/seqtools.py +1 -3
  188. educommon/utils/serializer.py +9 -16
  189. educommon/utils/storage.py +3 -2
  190. educommon/utils/system.py +1 -3
  191. educommon/utils/system_app/management/commands/delete_objects.py +17 -34
  192. educommon/utils/ui.py +87 -84
  193. educommon/utils/xml/__init__.py +2 -7
  194. educommon/utils/xml/resolver.py +1 -0
  195. educommon/ws_log/actions.py +31 -76
  196. educommon/ws_log/base.py +6 -20
  197. educommon/ws_log/migrations/0001_initial.py +25 -8
  198. educommon/ws_log/migrations/0002_auto_20160628_1334.py +0 -1
  199. educommon/ws_log/migrations/0003_add_fields_to_smev_logs.py +20 -4
  200. educommon/ws_log/migrations/0004_auto_20160727_1600.py +7 -6
  201. educommon/ws_log/migrations/0005_auto_20161130_1615.py +14 -4
  202. educommon/ws_log/migrations/0006_auto_20170327_1027.py +3 -2
  203. educommon/ws_log/migrations/0007_auto_20180607_1040.py +8 -9
  204. educommon/ws_log/migrations/0008_auto_20180713_1445.py +23 -10
  205. educommon/ws_log/migrations/0009_auto_20201130_1553.py +7 -2
  206. educommon/ws_log/models.py +21 -35
  207. educommon/ws_log/provider.py +2 -1
  208. educommon/ws_log/report.py +8 -13
  209. educommon/ws_log/smev/applications.py +12 -27
  210. educommon/ws_log/smev/exceptions.py +2 -3
  211. educommon/ws_log/ui.py +32 -32
  212. educommon/ws_log/utils.py +1 -3
  213. {educommon-3.13.0.dist-info → educommon-3.13.2.dist-info}/METADATA +26 -14
  214. educommon-3.13.2.dist-info/RECORD +354 -0
  215. educommon/utils/patches.py +0 -27
  216. educommon/version.conf +0 -11
  217. educommon-3.13.0.dist-info/RECORD +0 -357
  218. educommon-3.13.0.dist-info/dependency_links.txt +0 -1
  219. {educommon-3.13.0.dist-info → educommon-3.13.2.dist-info}/WHEEL +0 -0
  220. {educommon-3.13.0.dist-info → educommon-3.13.2.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
1
1
  """Вспомогательные средства для работы с подсистемой RBAC."""
2
+
2
3
  import operator
3
4
  from inspect import (
4
5
  getfullargspec,
@@ -16,6 +17,7 @@ from educommon.m3 import (
16
17
 
17
18
  def _resolve_packs_or_actions(packs_or_actions):
18
19
  """Возвращает список из паков и экшенов, заданных классами и строками."""
20
+
19
21
  def resolve(pack_or_action):
20
22
  if isinstance(pack_or_action, tuple):
21
23
  pack, action = pack_or_action
@@ -25,24 +27,18 @@ def _resolve_packs_or_actions(packs_or_actions):
25
27
  result = get_pack(pack_or_action)
26
28
  return result
27
29
 
28
- result = [
29
- resolve(pack_or_action)
30
- for pack_or_action in packs_or_actions
31
- ]
30
+ result = [resolve(pack_or_action) for pack_or_action in packs_or_actions]
32
31
 
33
32
  return result
34
33
 
35
34
 
36
35
  def _rule_filter(rule_handler, packs_or_actions, operator_):
37
36
  """Возвращает обработчик правила, "обернутый" в фильтрующую функцию."""
37
+
38
38
  def action_in_list(action):
39
39
  for pack_or_action in _resolve_packs_or_actions(packs_or_actions):
40
- if (
41
- isinstance(pack_or_action, Action) and
42
- action.__class__ is pack_or_action.__class__
43
- ) or (
44
- isinstance(pack_or_action, ActionPack) and
45
- action.parent is pack_or_action
40
+ if (isinstance(pack_or_action, Action) and action.__class__ is pack_or_action.__class__) or (
41
+ isinstance(pack_or_action, ActionPack) and action.parent is pack_or_action
46
42
  ):
47
43
  return True
48
44
 
@@ -97,6 +93,7 @@ def invert_rule(rule_handler):
97
93
 
98
94
  :rtype: callable
99
95
  """
96
+
100
97
  def wrapper(action, request, user, *args, **kwargs):
101
98
  return not rule_handler(action, request, user, *args, **kwargs)
102
99
 
@@ -118,6 +115,7 @@ def any_rules(*rule_handlers):
118
115
 
119
116
  :rtype: callable
120
117
  """
118
+
121
119
  def wrapper(action, request, user, *args, **kwargs):
122
120
  for rule_handler in rule_handlers:
123
121
  if rule_handler(action, request, user, *args, **kwargs):
@@ -145,6 +143,7 @@ def all_rules(*rule_handlers):
145
143
 
146
144
  :rtype: callable
147
145
  """
146
+
148
147
  def wrapper(action, request, user, *args, **kwargs):
149
148
  for rule_handler in rule_handlers:
150
149
  if not rule_handler(action, request, user, *args, **kwargs):
@@ -176,7 +175,7 @@ def get_rbac_rule_data(request, action):
176
175
  :type action: m3.actions.Action
177
176
  """
178
177
  if not hasattr(request, '_rbac_rule_data'):
179
- if (hasattr(action, 'get_rbac_rule_data')):
178
+ if hasattr(action, 'get_rbac_rule_data'):
180
179
  method = action.get_rbac_rule_data
181
180
  else:
182
181
  method = action.parent.get_rbac_rule_data
@@ -12,10 +12,9 @@ from educommon.django.db.validators.simple import (
12
12
  )
13
13
 
14
14
 
15
- package_name_validator = RegexValidator(re.compile(
16
- r'(^[_a-z][_a-z0-9]*$)|(^[_a-z][._a-z0-9]*[_a-z0-9]{1}$)', re.IGNORECASE
17
- ))
15
+ package_name_validator = RegexValidator(
16
+ re.compile(r'(^[_a-z][_a-z0-9]*$)|(^[_a-z][._a-z0-9]*[_a-z0-9]{1}$)', re.IGNORECASE)
17
+ )
18
18
  """Валидатор имени пакета."""
19
19
 
20
- is_package_name_valid = partial(validate_value,
21
- validator=package_name_validator)
20
+ is_package_name_valid = partial(validate_value, validator=package_name_validator)
@@ -5,8 +5,4 @@ from educommon.auth.simple_auth import (
5
5
 
6
6
  # Например, settings.LOGIN_URL = simple_auth.get_login_url()
7
7
  def get_login_url():
8
- return ''.join((
9
- const.AUTH_CONTROLLER_URL,
10
- const.AUTH_PACK_URL,
11
- const.LOGIN_PAGE_URL
12
- ))
8
+ return ''.join((const.AUTH_CONTROLLER_URL, const.AUTH_PACK_URL, const.LOGIN_PAGE_URL))
@@ -73,7 +73,8 @@ class AuthPack(BasePack):
73
73
  login_checker = checkers.DefaultLoginChecker()
74
74
 
75
75
  def __init__(self):
76
- super(AuthPack, self).__init__()
76
+ super().__init__()
77
+
77
78
  self.login_page_action = LoginPageAction()
78
79
  self.login_action = LoginAction()
79
80
 
@@ -86,43 +87,55 @@ class AuthPack(BasePack):
86
87
  self.change_password_page_action = ChangeResetPasswordPageAction()
87
88
  self.change_password_action = ChangeResetPasswordAction()
88
89
 
89
- self.actions.extend((
90
- self.login_page_action,
91
- self.logout_confirm_action,
92
- self.login_action,
93
- self.logout_action,
94
- self.reset_password_page_action,
95
- self.reset_password_action,
96
- self.change_password_page_action,
97
- self.change_password_action
98
- ))
90
+ self.actions.extend(
91
+ (
92
+ self.login_page_action,
93
+ self.logout_confirm_action,
94
+ self.login_action,
95
+ self.logout_action,
96
+ self.reset_password_page_action,
97
+ self.reset_password_action,
98
+ self.change_password_page_action,
99
+ self.change_password_action,
100
+ )
101
+ )
99
102
 
100
103
  def declare_context(self, action):
101
- ctx = super(AuthPack, self).declare_context(action)
104
+ """Определяет контекст для экшена входа."""
105
+ ctx = super().declare_context(action)
106
+
102
107
  if action is self.login_action:
103
108
  ctx['login'] = dict(type='str', default='')
104
109
  ctx['password'] = dict(type='str', default='')
110
+
105
111
  return ctx
106
112
 
107
113
  def get_login_url(self):
114
+ """Возвращает URL экшена входа."""
108
115
  return self.login_action.get_absolute_url()
109
116
 
110
117
  def get_logout_url(self):
118
+ """Возвращает URL экшена выхода."""
111
119
  return self.logout_action.get_absolute_url()
112
120
 
113
121
  def get_login_page_url(self):
122
+ """Возвращает URL страницы входа."""
114
123
  return self.login_page_action.get_absolute_url()
115
124
 
116
125
  def get_reset_password_page_url(self):
126
+ """Возвращает URL страницы восстановления пароля."""
117
127
  return self.reset_password_page_action.get_absolute_url()
118
128
 
119
129
  def get_reset_password_url(self):
130
+ """Возвращает URL экшена восстановления пароля."""
120
131
  return self.reset_password_action.get_absolute_url()
121
132
 
122
133
  def get_change_password_page_url(self):
134
+ """Возвращает URL страницы изменения пароля."""
123
135
  return self.change_password_page_action.get_absolute_url()
124
136
 
125
137
  def get_change_password_url(self):
138
+ """Возвращает URL экшена изменения пароля."""
126
139
  return self.change_password_action.get_absolute_url()
127
140
 
128
141
 
@@ -133,26 +146,21 @@ class LoginPageAction(BaseAction):
133
146
  template_file_name = 'simple_auth/login_page.html'
134
147
 
135
148
  def _get_login_panel(self, request, context):
149
+ """Возвращает компонент панели логина."""
136
150
  get_login_panel = ioc.get('simple_auth__get_login_panel')
137
151
 
138
- return self.handle(
139
- 'get_login_panel',
140
- get_login_panel(request, context)
141
- )
152
+ return self.handle('get_login_panel', get_login_panel(request, context))
142
153
 
143
154
  def get_template_context(self, request, context):
155
+ """Формирует контекст шаблона страницы входа."""
144
156
  return dict(
145
157
  login_url=self.parent.get_login_url(),
146
158
  login_panel=self._get_login_panel(request, context),
147
- reset_password_page_url=self.parent.get_reset_password_page_url()
159
+ reset_password_page_url=self.parent.get_reset_password_page_url(),
148
160
  )
149
161
 
150
162
  def run(self, request, context):
151
- return render(
152
- request,
153
- self.template_file_name,
154
- self.get_template_context(request, context)
155
- )
163
+ return render(request, self.template_file_name, self.get_template_context(request, context))
156
164
 
157
165
 
158
166
  class LoginAction(BaseAction):
@@ -169,19 +177,23 @@ class LoginAction(BaseAction):
169
177
  if not request.is_ajax():
170
178
  result = HttpResponseRedirect('/')
171
179
  elif err_msg:
172
- result = PreJsonResult(dict(
173
- success=False,
174
- redirect='',
175
- message=err_msg or '',
176
- ))
180
+ result = PreJsonResult(
181
+ dict(
182
+ success=False,
183
+ redirect='',
184
+ message=err_msg or '',
185
+ )
186
+ )
177
187
  else:
178
188
  user = auth.authenticate(username=username, password=password)
179
189
  auth.login(request, user)
180
190
 
181
- result = PreJsonResult(dict(
182
- success=True,
183
- redirect='/',
184
- ))
191
+ result = PreJsonResult(
192
+ dict(
193
+ success=True,
194
+ redirect='/',
195
+ )
196
+ )
185
197
 
186
198
  return result
187
199
 
@@ -193,16 +205,13 @@ class ResetPasswordPageAction(BaseAction):
193
205
  template_file_name = 'simple_auth/reset_password_page.html'
194
206
 
195
207
  def get_template_context(self, request, context):
208
+ """Формирует контекст для шаблона восстановления пароля."""
196
209
  return dict(
197
- login_page_url=self.parent.get_login_page_url(),
198
- reset_password_url=self.parent.get_reset_password_url()
210
+ login_page_url=self.parent.get_login_page_url(), reset_password_url=self.parent.get_reset_password_url()
199
211
  )
200
212
 
201
213
  def run(self, request, context):
202
- return render(
203
- request, self.template_file_name,
204
- self.get_template_context(request, context)
205
- )
214
+ return render(request, self.template_file_name, self.get_template_context(request, context))
206
215
 
207
216
 
208
217
  class ResetPasswordAction(BaseAction):
@@ -212,22 +221,22 @@ class ResetPasswordAction(BaseAction):
212
221
  email_template_file_name = 'simple_auth/email/reset_password.html'
213
222
 
214
223
  def context_declaration(self):
224
+ """Определяет входной контекст с email для восстановления."""
215
225
  return {'email': {'type': 'str'}}
216
226
 
217
227
  def get_email_template_context(self, request, context):
228
+ """Формирует контекст для email шаблона восстановления пароля."""
218
229
  site_url = settings.SITE_URL.rstrip('/')
219
- return dict(
220
- site_url=site_url,
221
- recover_url=urljoin(
222
- site_url, self.parent.get_change_password_page_url()
223
- )
224
- )
230
+
231
+ return dict(site_url=site_url, recover_url=urljoin(site_url, self.parent.get_change_password_page_url()))
225
232
 
226
233
  @staticmethod
227
234
  def _get_user_by_email(email):
235
+ """Ищет пользователя по email."""
228
236
  if ioc.has_value('get_user_by_email'):
229
237
  get_user_by_email = ioc.get('get_user_by_email')
230
238
  else:
239
+
231
240
  def get_user_by_email(email):
232
241
  query = get_user_model().objects.filter(email=email)
233
242
  if query.count() == 1:
@@ -238,10 +247,13 @@ class ResetPasswordAction(BaseAction):
238
247
  def run(self, request, context):
239
248
  user = ResetPasswordAction._get_user_by_email(context.email)
240
249
  if user is None:
241
- return OperationResult(False, message=(
242
- 'Этот адрес электронной почты не связан ни с одной учетной '
243
- 'записью. Вы уверены, что зарегистрированы?'
244
- ))
250
+ return OperationResult(
251
+ False,
252
+ message=(
253
+ 'Этот адрес электронной почты не связан ни с одной учетной '
254
+ 'записью. Вы уверены, что зарегистрированы?'
255
+ ),
256
+ )
245
257
 
246
258
  now = datetime.datetime.now()
247
259
  life = getattr(settings, 'RESET_CODES_LIFE', None)
@@ -253,29 +265,17 @@ class ResetPasswordAction(BaseAction):
253
265
  code = uuid4().hex
254
266
  ResetPasswords.objects.create(user=user, code=code)
255
267
  template_context = self.get_email_template_context(request, context)
256
- template_context.update({
257
- 'username': user.username,
258
- 'code': code
259
- })
268
+ template_context.update({'username': user.username, 'code': code})
260
269
 
261
270
  # Шаблон отправки email
262
- template = render_to_string(
263
- self.email_template_file_name,
264
- template_context
265
- )
271
+ template = render_to_string(self.email_template_file_name, template_context)
266
272
 
267
273
  # Отправка письма
268
- msg = EmailMessage(
269
- 'Восстановление пароля', template,
270
- settings.DEFAULT_FROM_EMAIL, [context.email]
271
- )
274
+ msg = EmailMessage('Восстановление пароля', template, settings.DEFAULT_FROM_EMAIL, [context.email])
272
275
  msg.content_subtype = 'html'
273
276
  msg.send()
274
277
 
275
- return OperationResult(
276
- message='На указанный адрес отправлено письмо с дальнейшими'
277
- ' инструкциями.'
278
- )
278
+ return OperationResult(message='На указанный адрес отправлено письмо с дальнейшими инструкциями.')
279
279
 
280
280
 
281
281
  class ChangeResetPasswordPageAction(BaseAction):
@@ -285,13 +285,15 @@ class ChangeResetPasswordPageAction(BaseAction):
285
285
  template_file_name = 'simple_auth/change_reset_password_page.html'
286
286
 
287
287
  def context_declaration(self):
288
+ """Определяет контекст с кодом восстановления пароля."""
288
289
  return {'code': {'type': 'str'}}
289
290
 
290
291
  def get_template_context(self, request, context):
292
+ """Формирует контекст для шаблона смены пароля."""
291
293
  return dict(
292
294
  code=context.code,
293
295
  login_page_url=self.parent.get_login_page_url(),
294
- change_password_url=self.parent.get_change_password_url()
296
+ change_password_url=self.parent.get_change_password_url(),
295
297
  )
296
298
 
297
299
  def run(self, request, context):
@@ -299,17 +301,10 @@ class ChangeResetPasswordPageAction(BaseAction):
299
301
  life = getattr(settings, 'RESET_CODES_LIFE', None)
300
302
  life = datetime.timedelta(minutes=life or const.RESET_CODES_LIFE)
301
303
  # Если не найден пользователь
302
- if not ResetPasswords.objects.filter(
303
- date__gte=now - life, code=context.code
304
- ).exists():
305
- return HttpResponseRedirect(
306
- self.parent.get_reset_password_page_url()
307
- )
304
+ if not ResetPasswords.objects.filter(date__gte=now - life, code=context.code).exists():
305
+ return HttpResponseRedirect(self.parent.get_reset_password_page_url())
308
306
 
309
- return render(
310
- request, self.template_file_name,
311
- self.get_template_context(request, context)
312
- )
307
+ return render(request, self.template_file_name, self.get_template_context(request, context))
313
308
 
314
309
 
315
310
  class ChangeResetPasswordAction(BaseAction):
@@ -319,15 +314,10 @@ class ChangeResetPasswordAction(BaseAction):
319
314
  validator = validators.DefaultPasswordValidator()
320
315
 
321
316
  def context_declaration(self):
322
- return {
323
- 'code': {'type': 'str'},
324
- 'password': {'type': 'str'},
325
- 'password_confirm': {'type': 'str'}
326
- }
327
-
328
- @convert_validation_error_to(
329
- ApplicationLogicException, model=ResetPasswords
330
- )
317
+ """Определяет контекст с кодом и паролями."""
318
+ return {'code': {'type': 'str'}, 'password': {'type': 'str'}, 'password_confirm': {'type': 'str'}}
319
+
320
+ @convert_validation_error_to(ApplicationLogicException, model=ResetPasswords)
331
321
  def run(self, request, context):
332
322
  password = context.password
333
323
  confirm = context.password_confirm
@@ -337,13 +327,9 @@ class ChangeResetPasswordAction(BaseAction):
337
327
  life = datetime.timedelta(minutes=life or const.RESET_CODES_LIFE)
338
328
 
339
329
  try:
340
- user = ResetPasswords.objects.filter(
341
- date__gte=now - life
342
- ).get(code=context.code).user
330
+ user = ResetPasswords.objects.filter(date__gte=now - life).get(code=context.code).user
343
331
  except ResetPasswords.DoesNotExist:
344
- return HttpResponseRedirect(
345
- self.parent.get_reset_password_page_url()
346
- )
332
+ return HttpResponseRedirect(self.parent.get_reset_password_page_url())
347
333
 
348
334
  if password != confirm:
349
335
  raise ValidationError('Пароль и подтверждение не совпадают!')
@@ -356,6 +342,7 @@ class ChangeResetPasswordAction(BaseAction):
356
342
  user.save()
357
343
 
358
344
  ResetPasswords.objects.filter(user=user).delete()
345
+
359
346
  return OperationResult(message='Новый пароль установлен!')
360
347
 
361
348
 
@@ -366,8 +353,8 @@ class LogoutConfirmAction(BaseAction):
366
353
 
367
354
  def run(self, request, context):
368
355
  msg_box = MessageBox(
369
- '', 'Вы действительно хотите выйти из системы?',
370
- MessageBox.ICON_QUESTION, MessageBox.BTN_YESNO)
356
+ '', 'Вы действительно хотите выйти из системы?', MessageBox.ICON_QUESTION, MessageBox.BTN_YESNO
357
+ )
371
358
 
372
359
  msg_box.handler_yes = """
373
360
  Ext.Ajax.request({
@@ -379,6 +366,7 @@ class LogoutConfirmAction(BaseAction):
379
366
  }
380
367
  });
381
368
  """ % {'url': self.parent.logout_action.get_absolute_url()}
369
+
382
370
  return http.HttpResponse(msg_box.get_script())
383
371
 
384
372
 
@@ -388,7 +376,6 @@ class LogoutAction(BaseAction):
388
376
  url = '/logout'
389
377
 
390
378
  def run(self, request, context):
391
-
392
379
  auth.logout(request)
393
380
 
394
381
  if request.is_ajax():
@@ -26,9 +26,7 @@ auth_controller = ioc.get('auth_controller')
26
26
 
27
27
 
28
28
  def register_actions():
29
- auth_controller.extend_packs((
30
- AuthPack(),
31
- ))
29
+ auth_controller.extend_packs((AuthPack(),))
32
30
 
33
31
 
34
32
  def register_desktop_menu():
@@ -37,12 +35,7 @@ def register_desktop_menu():
37
35
  DesktopLoader.add(
38
36
  GENERIC_USER,
39
37
  DesktopLoader.TOOLBOX,
40
- DesktopShortcut(
41
- pack=auth_pack.logout_confirm_action,
42
- name='Выход',
43
- index=256,
44
- icon='logout'
45
- )
38
+ DesktopShortcut(pack=auth_pack.logout_confirm_action, name='Выход', index=256, icon='logout'),
46
39
  )
47
40
 
48
41
  uificate_the_controller(auth_controller)
@@ -1,4 +1,5 @@
1
1
  """Классы, осуществляющие проверку пользовательских данных."""
2
+
2
3
  from m3_django_compat import (
3
4
  get_user_model,
4
5
  )
@@ -17,7 +18,7 @@ class DefaultLoginChecker:
17
18
 
18
19
  def _check_lic(self, *args, **kwargs):
19
20
  # TODO: проверка лицензии
20
- request = kwargs['request']
21
+ kwargs['request']
21
22
  return None
22
23
 
23
24
  def _check_user_exists(self, *args, **kwargs):
@@ -63,8 +64,7 @@ class DefaultLoginChecker:
63
64
  средствами django.
64
65
  """
65
66
  for checker in self._checkers:
66
- error = checker(
67
- self, request=request, username=username, password=password)
67
+ error = checker(self, request=request, username=username, password=password)
68
68
 
69
69
  if error:
70
70
  return error
@@ -8,7 +8,6 @@ from django.db import (
8
8
 
9
9
 
10
10
  class Migration(migrations.Migration):
11
-
12
11
  dependencies = [
13
12
  migrations.swappable_dependency(settings.AUTH_USER_MODEL),
14
13
  ]
@@ -18,9 +17,29 @@ class Migration(migrations.Migration):
18
17
  name='ResetPasswords',
19
18
  fields=[
20
19
  ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
21
- ('code', models.CharField(unique=True, max_length=32, verbose_name='\u041a\u043e\u0434 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f')),
22
- ('date', models.DateTimeField(auto_now_add=True, verbose_name='\u0414\u0430\u0442\u0430 \u0441\u0431\u0440\u043e\u0441\u0430 \u043f\u0430\u0440\u043e\u043b\u044f')),
23
- ('user', models.ForeignKey(verbose_name='\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE,)),
20
+ (
21
+ 'code',
22
+ models.CharField(
23
+ unique=True,
24
+ max_length=32,
25
+ verbose_name='\u041a\u043e\u0434 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f',
26
+ ),
27
+ ),
28
+ (
29
+ 'date',
30
+ models.DateTimeField(
31
+ auto_now_add=True,
32
+ verbose_name='\u0414\u0430\u0442\u0430 \u0441\u0431\u0440\u043e\u0441\u0430 \u043f\u0430\u0440\u043e\u043b\u044f',
33
+ ),
34
+ ),
35
+ (
36
+ 'user',
37
+ models.ForeignKey(
38
+ verbose_name='\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c',
39
+ to=settings.AUTH_USER_MODEL,
40
+ on_delete=models.CASCADE,
41
+ ),
42
+ ),
24
43
  ],
25
44
  options={
26
45
  'verbose_name': '\u0421\u0431\u0440\u043e\u0448\u0435\u043d\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c',
@@ -1,5 +1,4 @@
1
1
  class DefaultPasswordValidator:
2
-
3
2
  """Валидация пароля."""
4
3
 
5
4
  _validators = []
@@ -1,4 +1,5 @@
1
1
  """Паки справочников контингента."""
2
+
2
3
  from django.db.models import (
3
4
  Q,
4
5
  )
@@ -48,7 +49,7 @@ class OkoguPack(ObjectPack):
48
49
 
49
50
  Добавляется css класс для переноса строк в ячейках грида
50
51
  """
51
- super(OkoguPack, self).configure_grid(grid)
52
+ super().configure_grid(grid)
52
53
 
53
54
  grid.cls = 'word-wrap-grid' # перенос строк в ячейках грида
54
55
 
@@ -90,7 +91,7 @@ class OKSMPack(ObjectPack):
90
91
  'sortable': True,
91
92
  'searchable': True,
92
93
  'width': 3,
93
- }
94
+ },
94
95
  ]
95
96
 
96
97
  def get_rows_query(self, request, context):
@@ -99,16 +100,15 @@ class OKSMPack(ObjectPack):
99
100
 
100
101
  Исключается отображение РФ.
101
102
  """
102
- records = super(OKSMPack, self).get_rows_query(request, context)
103
+ records = super().get_rows_query(request, context)
103
104
 
104
105
  return records.exclude(code=OksmVirtialModel.rf_code)
105
106
 
106
107
  def apply_search(self, query, request, context):
107
108
  """Поиск по краткому наименованию или коду."""
108
- query = super(
109
- OKSMPack, self).apply_search(query, request, context)
109
+ query = super(OKSMPack, self).apply_search(query, request, context)
110
110
 
111
111
  if hasattr(context, 'filter'):
112
- query = query.filter(Q(shortname__icontains=context.filter) |
113
- Q(code=context.filter))
112
+ query = query.filter(Q(shortname__icontains=context.filter) | Q(code=context.filter))
113
+
114
114
  return query
@@ -9,7 +9,4 @@ from educommon.contingent.actions import (
9
9
 
10
10
  def register_actions():
11
11
  """Регистрация паков."""
12
- ioc.get('main_controller').extend_packs((
13
- OkoguPack(),
14
- OKSMPack()
15
- ))
12
+ ioc.get('main_controller').extend_packs((OkoguPack(), OKSMPack()))
@@ -4,6 +4,7 @@ BaseCatalogVirtualModel - виртуальная модель на основе
4
4
  BaseEnumerateProductSpecific - перечисление с продуктовыми зависимостями.
5
5
  BaseModelView - перечисление на основе виртуальной модели.
6
6
  """
7
+
7
8
  import json
8
9
  import os
9
10
 
@@ -66,11 +67,8 @@ class BaseCatalogVirtualModel(VirtualModel):
66
67
 
67
68
  @classmethod
68
69
  def get_serialized_values(cls, ids):
69
- """Список сериализованных объектов
70
- для маппинга в ExtMultiSelectField.
71
- """
72
- return json.dumps(list(cls.objects.filter(id__in=ids).values(
73
- *cls.fields_to_serialize)))
70
+ """Список сериализованных объектов для маппинга в ExtMultiSelectField."""
71
+ return json.dumps(list(cls.objects.filter(id__in=ids).values(*cls.fields_to_serialize)))
74
72
 
75
73
  @classmethod
76
74
  def _get_ids(cls):
@@ -84,7 +82,8 @@ class BaseCatalogVirtualModel(VirtualModel):
84
82
 
85
83
  :param dict params: Данные объекта модели.
86
84
  """
87
- super(BaseCatalogVirtualModel, self).__init__()
85
+ super().__init__()
86
+
88
87
  for param in params:
89
88
  setattr(self, param, params[param])
90
89
 
@@ -130,18 +129,15 @@ class BaseEnumerateProductSpecific(BaseEnumerate, ProductSpecific):
130
129
  assert all(code in cls.values for code in list_codes), (
131
130
  'Все значения list_codes должны содержаться в values класса'
132
131
  )
133
- super(BaseEnumerateProductSpecific, cls).set_category(list_codes)
132
+
133
+ super().set_category(list_codes)
134
134
 
135
135
  @classmethod
136
136
  def get_choices(cls):
137
137
  """Возвращает заданные для конкретных продуктов значения."""
138
138
  codes = cls.current_kind or cls.values
139
139
 
140
- return [
141
- (k, v)
142
- for k, v in cls.values.items()
143
- if k in codes
144
- ]
140
+ return [(k, v) for k, v in cls.values.items() if k in codes]
145
141
 
146
142
 
147
143
  class BaseModelView(ProductSpecific):
@@ -170,9 +166,7 @@ class BaseModelView(ProductSpecific):
170
166
 
171
167
  :return: [(value_field, display_field), ...]
172
168
  """
173
- codes = cls.current_kind or [
174
- rec[cls.value_field]
175
- for rec in cls.model.data]
169
+ codes = cls.current_kind or [rec[cls.value_field] for rec in cls.model.data]
176
170
 
177
171
  result = (
178
172
  (record[cls.value_field], record[cls.display_field])
@@ -181,4 +175,5 @@ class BaseModelView(ProductSpecific):
181
175
  )
182
176
 
183
177
  result = tuple(sorted(result, key=lambda code_name: code_name[1]))
178
+
184
179
  return result