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
@@ -21,9 +21,9 @@ class ProxyLoader:
21
21
  message = None
22
22
  """Сообщение о результате."""
23
23
 
24
- def __init__(self, loaders, _file, file_name, context=None,
25
- separate_logs=False, ignore_bad_rows=False,
26
- result_logger=None):
24
+ def __init__(
25
+ self, loaders, _file, file_name, context=None, separate_logs=False, ignore_bad_rows=False, result_logger=None
26
+ ):
27
27
  """Загрузка файла по словарю прокси-загрузчиков.
28
28
 
29
29
  :param dict loaders: словарь постраничных загрузчиков файла
@@ -55,8 +55,7 @@ class ProxyLoader:
55
55
  :param dict log: лог
56
56
  :rtype str
57
57
  """
58
- return '\n'.join(
59
- self.xls_loader.log + self.xls_loader.prepare_row_errors(log))
58
+ return '\n'.join(self.xls_loader.log + self.xls_loader.prepare_row_errors(log))
60
59
 
61
60
  def load(self):
62
61
  """Импорт данных из файла."""
@@ -96,7 +95,7 @@ class ProxyLoader:
96
95
  loader_cls = self.loaders.get(sheet.upper())
97
96
  if not loader_cls:
98
97
  # Если не найден загрузчик для листа
99
- error_msg = 'Некорректное имя листа "%s"' % sheet
98
+ error_msg = f'Некорректное имя листа "{sheet}"'
100
99
  import_log[data[0][self.xls_loader.XLS_POS]] = error_msg
101
100
  # Заносим запись об ошибке при обработке листа в общий лог
102
101
  self.result_logger.on_sheet_errors(sheet, [error_msg])
@@ -110,7 +109,7 @@ class ProxyLoader:
110
109
  log=import_log,
111
110
  context=self.context,
112
111
  warning_log=warning_log,
113
- result_logger=self.result_logger
112
+ result_logger=self.result_logger,
114
113
  )
115
114
 
116
115
  log = self.make_log(import_log)
@@ -120,14 +119,14 @@ class ProxyLoader:
120
119
  # если задан режим разделения логов
121
120
  if log:
122
121
  # всё же были какие-то ошибки
123
- final_log = [" ОШИБКИ:\n ", log]
122
+ final_log = [' ОШИБКИ:\n ', log]
124
123
  else:
125
- final_log = [SUCCESFUL_IMPORTED, ]
124
+ final_log = [
125
+ SUCCESFUL_IMPORTED,
126
+ ]
126
127
 
127
128
  if warning_log:
128
- final_log.extend([
129
- " ПРЕДУПРЕЖДЕНИЯ:\n ", self.make_log(warning_log)
130
- ])
129
+ final_log.extend([' ПРЕДУПРЕЖДЕНИЯ:\n ', self.make_log(warning_log)])
131
130
 
132
131
  self.message = '\n'.join(final_log)
133
132
  else:
@@ -13,14 +13,14 @@ from educommon.report.reporter import (
13
13
 
14
14
 
15
15
  class BaseFailureImportReport:
16
- """Базовый класс отчета об импорте"""
16
+ """Базовый класс отчета об импорте."""
17
17
 
18
18
  template_name = None
19
19
  reports_dir = 'reports'
20
20
  default_extension = 'xlsx'
21
21
 
22
22
  def __init__(self, data):
23
- """:param data - данные для отчета"""
23
+ """:param data - данные для отчета."""
24
24
 
25
25
  self.data = data
26
26
  # Текущая директория
@@ -33,9 +33,7 @@ class BaseFailureImportReport:
33
33
  self.out_file_path = get_path(self.base_name)
34
34
  # url адрес, по которому будет доступен отчет
35
35
  self.out_file_url = get_url(self.base_name)
36
- self.report = SpreadsheetReport(os.path.join(
37
- reports_dir, '%s.%s' % (self.template_name, self.default_extension)
38
- ))
36
+ self.report = SpreadsheetReport(os.path.join(reports_dir, f'{self.template_name}.{self.default_extension}'))
39
37
 
40
38
  # Создадим директории, если их нет
41
39
  folder_path = get_path('')
@@ -43,5 +41,5 @@ class BaseFailureImportReport:
43
41
  os.makedirs(folder_path)
44
42
 
45
43
  def make(self):
46
- """Сбор отчета"""
44
+ """Сбор отчета."""
47
45
  raise NotImplementedError
educommon/importer/ui.py CHANGED
@@ -12,58 +12,61 @@ class BaseImportWindow(BaseEditWindow):
12
12
  """Базовое окно загрузки шаблона импорта."""
13
13
 
14
14
  def _init_components(self):
15
- super(BaseImportWindow, self)._init_components()
15
+ super()._init_components()
16
+
16
17
  self.file_field = ext.ExtFileUploadField(
17
18
  anchor='100%',
18
19
  allow_blank=False,
19
20
  name='uploaded',
20
- label="Файл для загрузки",
21
+ label='Файл для загрузки',
21
22
  )
22
23
 
23
24
  def _do_layout(self):
24
- super(BaseImportWindow, self)._do_layout()
25
+ super()._do_layout()
26
+
25
27
  self.form.items.append(self.file_field)
26
28
 
27
29
  def set_params(self, params):
28
- super(BaseImportWindow, self).set_params(params)
30
+ super().set_params(params)
31
+
29
32
  self.height = 110
30
33
  # FIXME: При переопределении придется копипастить
31
34
  # Проброс ID окна для окна результата
32
- self.handler_beforesubmit = '''
35
+ self.handler_beforesubmit = """
33
36
  function (submit) {submit.params["import_window_id"] = win.id}
34
- '''
37
+ """
35
38
 
36
39
  self.form.file_upload = True
37
40
  self.save_btn.text = 'Загрузить'
38
- self.file_field.possible_file_extensions = params.get(
39
- 'extensions', None
40
- )
41
+ self.file_field.possible_file_extensions = params.get('extensions', None)
41
42
 
42
43
 
43
44
  class ImportResultWindow(BaseWindow):
44
45
  """Окно для вывода результата импорта."""
45
46
 
46
47
  def _init_components(self):
47
- super(ImportResultWindow, self)._init_components()
48
+ super()._init_components()
49
+
48
50
  self.result_field = ext.ExtTextArea(read_only=True)
49
51
 
50
- self.close_btn = ext.ExtButton(
51
- text='Закрыть',
52
- handler='function() {win.close()}'
53
- )
52
+ self.close_btn = ext.ExtButton(text='Закрыть', handler='function() {win.close()}')
54
53
 
55
54
  # Кнопка "Отмена" не блокируется в режиме "только для чтения"
56
55
  self._mro_exclude_list.append(self.close_btn)
57
56
 
58
57
  def _do_layout(self):
59
- super(ImportResultWindow, self)._do_layout()
58
+ super()._do_layout()
59
+
60
60
  self.items.append(self.result_field)
61
- self.buttons.extend([
62
- self.close_btn,
63
- ])
61
+ self.buttons.extend(
62
+ [
63
+ self.close_btn,
64
+ ]
65
+ )
64
66
 
65
67
  def set_params(self, params):
66
- super(ImportResultWindow, self).set_params(params)
68
+ super().set_params(params)
69
+
67
70
  self.body_style = 'padding: 0;'
68
71
  self.layout = 'fit'
69
72
  self.modal = False
@@ -75,37 +78,40 @@ class ConfirmImportResultWindow(ImportResultWindow):
75
78
  """Окно для подтверждения импорта при наличии ошибок."""
76
79
 
77
80
  def _init_components(self):
78
- super(ConfirmImportResultWindow, self)._init_components()
81
+ super()._init_components()
82
+
79
83
  self.confirm_import_btn = ext.ExtButton(
80
84
  text='Загрузить данные, в которых нет ошибок',
81
85
  )
82
86
 
83
87
  def _do_layout(self):
84
- super(ConfirmImportResultWindow, self)._do_layout()
88
+ super()._do_layout()
89
+
85
90
  self.buttons.insert(0, self.confirm_import_btn)
86
91
 
87
92
  def set_params(self, params):
88
- super(ConfirmImportResultWindow, self).set_params(params)
93
+ super().set_params(params)
94
+
89
95
  self.parent_window_id = params['import_window_id']
90
96
 
91
97
  if params.get('exit_from_import_on_close', False):
92
98
  # Закрытие окна импорта и окна результата
93
- self.close_btn.handler = '''
99
+ self.close_btn.handler = """
94
100
  function() {
95
101
  if (win.parentWindow) win.parentWindow.close();
96
102
  win.close();
97
103
  }
98
- '''
104
+ """
99
105
 
100
106
  if params.get('hide_confirm_button', False):
101
107
  self.confirm_import_btn.hidden = True
102
108
  else:
103
109
  # Хэндлер пробрасывает параметр для пропуска ошибок и снова
104
110
  # сабмитит форму импорта.
105
- self.confirm_import_btn.handler = '''
111
+ self.confirm_import_btn.handler = """
106
112
  function() {
107
113
  win.close();
108
114
  win.parentWindow.actionContextJson.ignore_bad_rows = true;
109
115
  win.parentWindow.submitForm();
110
116
  }
111
- '''
117
+ """
@@ -1,23 +1,20 @@
1
- """
2
- Базовые валидаторы для импортируемых данных.
1
+ """Базовые валидаторы для импортируемых данных.
3
2
 
4
3
  Использовать только для расширения/исправления логики, реализованной с помощью
5
4
  `educommon.importer`. При написании новых классов для импорта/экспорта данных
6
5
  рекомендуется использовать пакет `data-transfer`.
7
6
  """
7
+
8
8
  from abc import (
9
9
  ABCMeta,
10
10
  )
11
11
 
12
12
 
13
13
  class IImportDataValidator(metaclass=ABCMeta):
14
- """
15
- Базовый класс валидатора импортируемых данных.
16
- """
14
+ """Базовый класс валидатора импортируемых данных."""
17
15
 
18
16
  def __call__(self, data_row, errors, warnings):
19
- """
20
- Валидирует строку входных данных.
17
+ """Валидирует строку входных данных.
21
18
 
22
19
  :param data_row: словарь, представляющий одну строку импортируемых
23
20
  данных
@@ -29,8 +29,7 @@ from educommon.integration_entities.enums import (
29
29
 
30
30
 
31
31
  class AbstractEntitySaver(ABC):
32
- """
33
- Абстрактный класс сохранения записей в моделях.
32
+ """Абстрактный класс сохранения записей в моделях.
34
33
 
35
34
  Используется в рамках выгрузок РВД, Сферум и ГИСРУО.
36
35
  """
@@ -72,8 +71,7 @@ class AbstractEntitySaver(ABC):
72
71
 
73
72
  @property
74
73
  def _to_delete_entities(self) -> Union[list, Iterable[Model]]:
75
- """
76
- Возвращает записи для удаления.
74
+ """Возвращает записи для удаления.
77
75
 
78
76
  Частный случай, поэтому по умолчанию возвращает пустой список.
79
77
  """
@@ -119,16 +117,14 @@ class AbstractEntitySaver(ABC):
119
117
  )
120
118
 
121
119
  def _delete_entities(self) -> None:
122
- """
123
- Удаляет записи или обрабатывает записи для удаления.
120
+ """Удаляет записи или обрабатывает записи для удаления.
124
121
 
125
122
  Частный случай, поэтому метод мало где может пригодиться.
126
123
  """
127
124
 
128
125
 
129
126
  class EntitySaver(AbstractEntitySaver):
130
- """
131
- Стандартный класс для сохранения моделей.
127
+ """Стандартный класс для сохранения моделей.
132
128
 
133
129
  Стандартный, потому что используется в большинстве случаев.
134
130
  """
@@ -171,25 +167,25 @@ class EntitySaverWithRealDeleting(EntitySaver):
171
167
 
172
168
 
173
169
  class ChainEntitySaver(AbstractEntitySaver):
174
- """
175
- Класс для сохранения моделей.
170
+ """Класс для сохранения моделей.
176
171
 
177
172
  Chain, потому что формирование объектов для сохранения происходит с помощью itertools.chain
178
173
  """
179
174
 
180
175
  def _get_entities_base(self, operation_type: EntityLogOperation) -> Iterable[Model]:
181
176
  """Базовый метод, возвращающий объекты для сохранения в зависимости от типа операции."""
182
- return chain.from_iterable([
183
- entities.values()
184
- for operation_entities in self._to_save_entities.values()
185
- for operation, entities in operation_entities.items()
186
- if operation == operation_type
187
- ])
177
+ return chain.from_iterable(
178
+ [
179
+ entities.values()
180
+ for operation_entities in self._to_save_entities.values()
181
+ for operation, entities in operation_entities.items()
182
+ if operation == operation_type
183
+ ]
184
+ )
188
185
 
189
186
 
190
187
  class IterableEntitySaver(AbstractEntitySaver):
191
- """
192
- Класс для сохранения моделей.
188
+ """Класс для сохранения моделей.
193
189
 
194
190
  Iterable, потому что формирование объектов для сохранения происходит в цикле.
195
191
  Используется в gis_ruo.
educommon/ioc/__init__.py CHANGED
@@ -4,6 +4,7 @@
4
4
  При необходимости использования в общей кодовой базе объектов проекта,
5
5
  нужно добавить переменные со значением ``educommon.Undefined`` в данный модуль.
6
6
  """
7
+
7
8
  from educommon import (
8
9
  Undefined,
9
10
  )
@@ -85,9 +86,7 @@ def register(name, value):
85
86
  if globals()[name] is value:
86
87
  return value
87
88
 
88
- assert globals()[name] is Undefined, (
89
- '"{}" already registered'.format(name)
90
- )
89
+ assert globals()[name] is Undefined, '"{}" already registered'.format(name)
91
90
 
92
91
  globals()[name] = value
93
92
 
@@ -100,8 +99,6 @@ def get(name):
100
99
  *name* должен быть предварительно зарегистрирован через **register**.
101
100
  """
102
101
  assert name in globals(), 'Object {} is not registered'.format(name)
103
- assert globals()[name] is not Undefined, (
104
- '"{}" not registered'.format(name)
105
- )
102
+ assert globals()[name] is not Undefined, '"{}" not registered'.format(name)
106
103
 
107
104
  return globals()[name]
@@ -29,9 +29,7 @@ _srcfile = os.path.normcase(addLevelName.__code__.co_filename)
29
29
 
30
30
 
31
31
  class WebEduLogger(getLoggerClass()):
32
- """
33
- Расширенный логер для работы с различными версиями Python.
34
- """
32
+ """Расширенный логер для работы с различными версиями Python."""
35
33
 
36
34
  def makeRecord(
37
35
  self,
@@ -46,9 +44,7 @@ class WebEduLogger(getLoggerClass()):
46
44
  extra: Optional[Mapping[str, object]] = ...,
47
45
  sinfo: Optional[str] = ...,
48
46
  ) -> WebEduLogRecord:
49
- """
50
- Метод формирования записи лога.
51
- """
47
+ """Метод формирования записи лога."""
52
48
  rv = WebEduLogRecord(name, level, fn, lno, msg, args, exc_info, func)
53
49
 
54
50
  if extra:
@@ -71,16 +67,16 @@ class WebEduLogger(getLoggerClass()):
71
67
  stacklevel=1,
72
68
  request=None,
73
69
  ):
74
- """
75
- Low-level logging routine which creates a LogRecord and then calls
76
- all the handlers of this logger to handle the record.
70
+ """Низкоуровневая процедура логирования.
71
+
72
+ Создает LogRecord и передает его всем обработчикам данного логгера.
77
73
  """
78
74
  sinfo = None
79
75
 
80
76
  if _srcfile:
81
- #IronPython doesn't track Python frames, so findCaller raises an
82
- #exception on some versions of IronPython. We trap it here so that
83
- #IronPython can use logging.
77
+ # IronPython doesn't track Python frames, so findCaller raises an
78
+ # exception on some versions of IronPython. We trap it here so that
79
+ # IronPython can use logging.
84
80
  try:
85
81
  python_version = platform.python_version()
86
82
 
@@ -90,9 +86,9 @@ class WebEduLogger(getLoggerClass()):
90
86
  fn, lno, func, sinfo = self.findCaller(stack_info, stacklevel)
91
87
 
92
88
  except ValueError: # pragma: no cover
93
- fn, lno, func = "(unknown file)", 0, "(unknown function)"
89
+ fn, lno, func = '(unknown file)', 0, '(unknown function)'
94
90
  else: # pragma: no cover
95
- fn, lno, func = "(unknown file)", 0, "(unknown function)"
91
+ fn, lno, func = '(unknown file)', 0, '(unknown function)'
96
92
 
97
93
  if exc_info:
98
94
  if isinstance(exc_info, BaseException):
educommon/m3/__init__.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Вспомогательные средства для работы с компонентами M3."""
2
+
2
3
  import inspect
3
4
  import sys
4
5
  from functools import (
@@ -72,6 +73,7 @@ def convert_validation_error_to(exc, new_line='<br/>', model=None):
72
73
  Если аргумент указан, то данные будут извлекаться именно из этой
73
74
  модели.
74
75
  """
76
+
75
77
  def get_model_meta(error):
76
78
  if model is not None:
77
79
  return model._meta
@@ -85,31 +87,24 @@ def convert_validation_error_to(exc, new_line='<br/>', model=None):
85
87
  if 'self' not in error_frame.f_locals:
86
88
  raise
87
89
  model_instance = error_frame.f_locals['self']
90
+
88
91
  return model_instance._meta
89
92
 
90
93
  def get_messages_from_dict(model_meta, data):
91
94
  result = []
92
95
  for field_name, field_errors in data.items():
93
96
  if field_name == NON_FIELD_ERRORS:
94
- result.append(
95
- new_line.join(
96
- '- {0}'.format(err) for err in field_errors
97
- )
98
- )
97
+ result.append(new_line.join('- {0}'.format(err) for err in field_errors))
99
98
  else:
100
99
  model_field = model_meta.get_field(field_name)
101
- verbose_name = (model_field.verbose_name or '')
102
- result.append(new_line.join(
103
- '- {0}: {1}'.format(verbose_name, err)
104
- for err in field_errors
105
- ))
100
+ verbose_name = model_field.verbose_name or ''
101
+ result.append(new_line.join('- {0}: {1}'.format(verbose_name, err) for err in field_errors))
102
+
106
103
  return result
107
104
 
108
105
  def get_messages_from_list(messages):
109
- result = [
110
- '- ' + message
111
- for message in messages
112
- ]
106
+ result = ['- ' + message for message in messages]
107
+
113
108
  return result
114
109
 
115
110
  assert issubclass(exc, Exception), type(exc)
@@ -127,8 +122,7 @@ def convert_validation_error_to(exc, new_line='<br/>', model=None):
127
122
 
128
123
  if hasattr(e, 'message_dict'):
129
124
  title = 'На форме имеются некорректно заполненные поля:'
130
- messages = [title] + get_messages_from_dict(model_meta,
131
- e.message_dict)
125
+ messages = [title] + get_messages_from_dict(model_meta, e.message_dict)
132
126
  else:
133
127
  title = 'При проверке данных найдены ошибки:'
134
128
  messages = [title] + get_messages_from_list(e.messages)
@@ -155,12 +149,10 @@ class ModelProxyValidationMixin:
155
149
  model_errors = error.update_error_dict({})
156
150
 
157
151
  for field_name, messages in model_errors.items():
158
-
159
152
  # В зависимости от версии Django в messages могут быть
160
153
  # как сообщения в виде строк, так и экземпляры ValidationError,
161
154
  # поэтому приводим его к списку, содержащему только строки
162
- messages = sum([m.messages if isinstance(
163
- m, DjangoValidationError) else [m] for m in messages], [])
155
+ messages = sum([m.messages if isinstance(m, DjangoValidationError) else [m] for m in messages], [])
164
156
 
165
157
  if field_name != NON_FIELD_ERRORS:
166
158
  full_field_name = '.'.join((model_name, field_name))
@@ -216,9 +208,7 @@ class ModelProxyValidationMixin:
216
208
  errors = {}
217
209
 
218
210
  models = ( # элементы составной модели
219
- name
220
- for name in (list(self.relations) + [primary_model_name])
221
- if not exclude or name not in exclude
211
+ name for name in (list(self.relations) + [primary_model_name]) if not exclude or name not in exclude
222
212
  )
223
213
 
224
214
  for model_name in models:
@@ -250,8 +240,7 @@ class ModelProxyValidationMixin:
250
240
  try:
251
241
  model.full_clean(model_exclude)
252
242
  except DjangoValidationError as error:
253
- errors = self.__update_error_dict(error, errors,
254
- model_name)
243
+ errors = self.__update_error_dict(error, errors, model_name)
255
244
  if not errors:
256
245
  valid_key = '_ModelValidationMixin__object_is_valid'
257
246
  model.__dict__[valid_key] = True
@@ -296,10 +285,9 @@ class PackValidationMixin:
296
285
  from objectpack.slave_object_pack.actions import (
297
286
  SlavePack,
298
287
  )
288
+
299
289
  if isinstance(self, SlavePack):
300
- obj.__dict__.update(
301
- self._get_parents_dict(context, key_fmt='%s_id')
302
- )
290
+ obj.__dict__.update(self._get_parents_dict(context, key_fmt='%s_id'))
303
291
  save_row = super(SlavePack, self).save_row
304
292
  else:
305
293
  save_row = super(PackValidationMixin, self).save_row
@@ -336,14 +324,8 @@ def get_pack(pack_or_model):
336
324
  """
337
325
  observer = ioc.get('observer')
338
326
 
339
- if (
340
- (
341
- isinstance(pack_or_model, str) and
342
- '.' in pack_or_model
343
- ) or (
344
- inspect.isclass(pack_or_model) and
345
- issubclass(pack_or_model, ActionPack)
346
- )
327
+ if (isinstance(pack_or_model, str) and '.' in pack_or_model) or (
328
+ inspect.isclass(pack_or_model) and issubclass(pack_or_model, ActionPack)
347
329
  ):
348
330
  # Пак задан именем класса в пакете или классом
349
331
  result = ControllerCache.find_pack(pack_or_model)
@@ -376,6 +358,7 @@ def get_pack_id(pack_or_model):
376
358
  """
377
359
  pack = get_pack(pack_or_model)
378
360
  result = pack.id_param_name
361
+
379
362
  return result
380
363
 
381
364
 
@@ -396,13 +379,12 @@ def get_id_value(context, pack_or_model):
396
379
  :param pack_or_model: Аргумент, определяющий пак, из которого будет
397
380
  получено имя параметра, идентифицирующего объект (*id_param_name*).
398
381
  """
399
- assert isinstance(
400
- context, ObservableController.VerboseDeclarativeContext
401
- ), type(context)
382
+ assert isinstance(context, ObservableController.VerboseDeclarativeContext), type(context)
402
383
 
403
384
  if isinstance(pack_or_model, (Action, ActionPack)):
404
385
  pack_or_model = pack_or_model.__class__
405
386
 
406
387
  pack = get_pack(pack_or_model)
407
388
  result = getattr(context, pack.id_param_name)
389
+
408
390
  return result
@@ -1,4 +1,5 @@
1
1
  """Утилиты для расширения интерфейсов и действий."""
2
+
2
3
  from educommon.m3.extensions.listeners import (
3
4
  BaseEditWinListener,
4
5
  BaseSaveListener,