educommon 3.12.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 (221) 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 +149 -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.2.dist-info/METADATA +57 -0
  214. educommon-3.13.2.dist-info/RECORD +354 -0
  215. {educommon-3.12.0.dist-info → educommon-3.13.2.dist-info}/WHEEL +1 -1
  216. educommon/utils/patches.py +0 -27
  217. educommon/version.conf +0 -11
  218. educommon-3.12.0.dist-info/METADATA +0 -47
  219. educommon-3.12.0.dist-info/RECORD +0 -357
  220. educommon-3.12.0.dist-info/dependency_links.txt +0 -1
  221. {educommon-3.12.0.dist-info → educommon-3.13.2.dist-info}/top_level.txt +0 -0
@@ -33,9 +33,7 @@ class ColumnFilterEngine(BaseFilterEngine):
33
33
  def configure_grid(self, grid):
34
34
  """Метод конфигурации грида."""
35
35
  # расширение плагином
36
- if not ExtensionManager().execute(
37
- 'column_filter_engine.configure_grid', self, grid
38
- ):
36
+ if not ExtensionManager().execute('column_filter_engine.configure_grid', self, grid):
39
37
  super().configure_grid(grid)
40
38
 
41
39
 
@@ -50,7 +48,7 @@ class ModifiedChoicesFilter(CustomFilter):
50
48
  self._choices = choices
51
49
  kwargs['xtype'] = 'combo'
52
50
 
53
- super(ModifiedChoicesFilter, self).__init__(*args, **kwargs)
51
+ super().__init__(*args, **kwargs)
54
52
 
55
53
  def create_control(self):
56
54
  """Контрол."""
@@ -58,6 +56,7 @@ class ModifiedChoicesFilter(CustomFilter):
58
56
  choices = self._choices()
59
57
  else:
60
58
  choices = self._choices
59
+
61
60
  return make_combo_box(data=list(choices))
62
61
 
63
62
  def get_control(self):
@@ -69,6 +68,7 @@ class ModifiedChoicesFilter(CustomFilter):
69
68
  control.allow_blank = True
70
69
  control.hide_clear_trigger = False
71
70
  control.value = None
71
+
72
72
  return control
73
73
 
74
74
  def get_script(self):
@@ -87,9 +87,7 @@ class BoolChoicesFilter(ModifiedChoicesFilter):
87
87
  """Формирование lookup для фильтра."""
88
88
  return Q(**{field_name: v}) if v is not None else Q()
89
89
 
90
- super(BoolChoicesFilter, self).__init__(
91
- *args, choices=choices, parser='boolean', lookup=lookup, **kwargs
92
- )
90
+ super().__init__(*args, choices=choices, parser='boolean', lookup=lookup, **kwargs)
93
91
 
94
92
 
95
93
  class DateFilter(ColumnFilterWithDefaultValue):
@@ -97,10 +95,7 @@ class DateFilter(ColumnFilterWithDefaultValue):
97
95
 
98
96
  def create_control(self):
99
97
  """Создание контрола."""
100
- return _create_control_for_field(
101
- self.field,
102
- **self._field_fabric_params
103
- )
98
+ return _create_control_for_field(self.field, **self._field_fabric_params)
104
99
 
105
100
  def get_control(self):
106
101
  """Настройка контрола."""
@@ -126,10 +121,7 @@ class DateFilterByAnnotatedField(DateFilter):
126
121
  собираются в кварисете через annotate.
127
122
  """
128
123
 
129
- def __init__(
130
- self, model, field_name, lookup=None, tooltip=None, default_value=None,
131
- **field_fabric_params
132
- ):
124
+ def __init__(self, model, field_name, lookup=None, tooltip=None, default_value=None, **field_fabric_params):
133
125
  """Инициализация параметров."""
134
126
  field_name = field_name.replace('.', '__')
135
127
  self._model = model
@@ -143,8 +135,10 @@ class DateFilterByAnnotatedField(DateFilter):
143
135
  if not callable(lookup) and '%s' in lookup:
144
136
  lookup = lookup % field_name
145
137
  else:
138
+
146
139
  def lookup(x):
147
140
  return Q(**{field_name: x})
141
+
148
142
  self._lookup = lookup
149
143
 
150
144
  def create_control(self):
@@ -32,9 +32,7 @@ from educommon.utils.ui import (
32
32
 
33
33
 
34
34
  class GridPanel(ext.ExtPanel):
35
- """
36
- Панель, имеющая grid_url, по которому получает грид и вставляет в себя
37
- """
35
+ """Панель, имеющая grid_url, по которому получает грид и вставляет в себя."""
38
36
 
39
37
  grid_url = None
40
38
  template = 'grid-panel.js'
@@ -43,24 +41,21 @@ class GridPanel(ext.ExtPanel):
43
41
  def __init__(self, *args, **kwargs):
44
42
  # в инитах затирается темплейт
45
43
  t = self.template
46
- super(GridPanel, self).__init__(*args, **kwargs)
44
+
45
+ super().__init__(*args, **kwargs)
46
+
47
47
  self.template = t
48
48
 
49
49
  @staticmethod
50
50
  def _create_grid(pack, columns, grid_cls, group_by=None, **kwargs):
51
- """
52
- Метод возвращает грид
51
+ """Метод возвращает грид.
52
+
53
53
  :param grid_cls: класс грида
54
54
  :type grid_cls: ExtObjectGrid
55
55
  :param str group_by: темплейт для группирования
56
56
  """
57
57
  grid = grid_cls(
58
- region='north',
59
- force_fit=False,
60
- auto_scroll=True,
61
- auto_width=False,
62
- cls='word-wrap-grid',
63
- **kwargs
58
+ region='north', force_fit=False, auto_scroll=True, auto_width=False, cls='word-wrap-grid', **kwargs
64
59
  )
65
60
  grid.flex = 1
66
61
  grid.sm = ext.ExtGridCellSelModel()
@@ -72,23 +67,17 @@ class GridPanel(ext.ExtPanel):
72
67
  # если грид с группирующими строками
73
68
  if group_by:
74
69
  grid.store = ext_store.ExtGroupingStore(
75
- url=grid.get_store().url,
76
- total_property='total',
77
- root='rows',
78
- auto_load=True
79
- )
80
- grid.store.reader = ext_store.ExtJsonReader(
81
- total_property='total',
82
- root='rows')
83
- grid.view = ExtGridGroupingView(
84
- group_text_template=group_by,
85
- force_fit=grid.force_fit
70
+ url=grid.get_store().url, total_property='total', root='rows', auto_load=True
86
71
  )
72
+ grid.store.reader = ext_store.ExtJsonReader(total_property='total', root='rows')
73
+ grid.view = ExtGridGroupingView(group_text_template=group_by, force_fit=grid.force_fit)
87
74
 
88
75
  def configure_reader(col):
89
76
  grid.store.reader.set_fields(col['data_index'])
90
77
  else:
91
- configure_reader = lambda col: None
78
+
79
+ def configure_reader(col):
80
+ return None
92
81
 
93
82
  def populate(root, columns):
94
83
  for c in columns:
@@ -123,7 +112,7 @@ class GridPanel(ext.ExtPanel):
123
112
 
124
113
  @classmethod
125
114
  def configure_grid(cls, grid, params):
126
- """Конфигурирование грида"""
115
+ """Конфигурирование грида."""
127
116
 
128
117
  pack = params['pack']
129
118
  # обычное поведение
@@ -138,6 +127,7 @@ class GridPanel(ext.ExtPanel):
138
127
  @classmethod
139
128
  def create_grid(cls, pack, columns, **kwargs):
140
129
  grid = cls._create_grid(pack, columns, cls.grid_class, **kwargs)
130
+
141
131
  return grid
142
132
 
143
133
  def pre_render(self):
@@ -146,35 +136,30 @@ class GridPanel(ext.ExtPanel):
146
136
 
147
137
  def render(self):
148
138
  self.pre_render()
149
- self.cmp_code = super(GridPanel, self).render()
139
+
140
+ self.cmp_code = super().render()
141
+
150
142
  return render_component(self)
151
143
 
152
144
 
153
145
  class FilterPanel(ext.ExtPanel):
154
- """
155
- Панель, умеющая fireevent'ить об изменении контрола,
156
- входящего в список filters
157
- """
146
+ """Панель, умеющая fireevent'ить об изменении контрола, входящего в список filters."""
158
147
 
159
148
  def __init__(self, *args, **kwargs):
160
149
  super(FilterPanel, self).__init__(*args, **kwargs)
150
+
161
151
  self.filters = []
162
152
 
163
153
  def configure_redirect(self, control, event):
154
+ """Связывает текущую панель с контролом control посредством fireevent'а event."""
155
+ self._listeners['changed'] = f"""
156
+ function(params) {{
157
+ Ext.getCmp('{control.client_id}').fireEvent('{event}', params);
158
+ }}
164
159
  """
165
- Связывает текущую панель с контролом control
166
- посредством fireevent'а event
167
- """
168
- self._listeners["changed"] = """
169
- function(params) {
170
- Ext.getCmp('%s').fireEvent('%s', params)
171
- }""" % (control.client_id, event)
172
160
 
173
161
  def configure_events(self):
174
- """
175
- Дополнение рендера fireevent'ом изменения значения контролов,
176
- входящих в список filters панели
177
- """
162
+ """Дополнение рендера fireevent'ом изменения значения контролов, входящих в список filters панели."""
178
163
  for control in self.filters:
179
164
  # определяется что за контрол и приделываются разные events
180
165
  if isinstance(control, ComboBoxWithStore):
@@ -195,25 +180,28 @@ class FilterPanel(ext.ExtPanel):
195
180
  def render(self):
196
181
  self.configure_events()
197
182
  self.pre_render()
183
+
198
184
  self.cmp_code = super(FilterPanel, self).render()
185
+
199
186
  # где-то в инитах затирается темплейт, опишем еще раз
200
187
  self.template = 'filter-panel.js'
188
+
201
189
  return render_component(self)
202
190
 
203
191
 
204
192
  class BaseGridWindow(BaseWindow):
205
- """
206
- Базовое окно с фильтрующей панелью и панелью с гридом
193
+ """Базовое окно с фильтрующей панелью и панелью с гридом.
194
+
207
195
  Клиент получает панель с гридом с сервера при изменении
208
- полей фильтрации на фильтрующей панели
196
+ полей фильтрации на фильтрующей панели.
209
197
  """
198
+
210
199
  grid_panel_cls = GridPanel # панель грида
211
200
 
212
201
  def _init_grid_panel(self):
213
202
  """Панель для грида."""
214
203
  self.grid_panel = self.grid_panel_cls(
215
- region='center', layout='hbox', flex=1,
216
- layout_config={"align": "stretch"}
204
+ region='center', layout='hbox', flex=1, layout_config={'align': 'stretch'}
217
205
  )
218
206
 
219
207
  def _init_filter_panel(self):
@@ -229,7 +217,8 @@ class BaseGridWindow(BaseWindow):
229
217
  )
230
218
 
231
219
  def _init_components(self):
232
- super(BaseGridWindow, self)._init_components()
220
+ super()._init_components()
221
+
233
222
  self._init_grid_panel()
234
223
  self._init_filter_panel()
235
224
  # связываются две панели
@@ -238,7 +227,8 @@ class BaseGridWindow(BaseWindow):
238
227
  self._mro_exclude_list.append(self.filter_cnt)
239
228
 
240
229
  def _do_layout(self):
241
- super(BaseGridWindow, self)._do_layout()
230
+ super()._do_layout()
231
+
242
232
  self.layout = 'border'
243
233
  self.maximizable = self.maximized = True
244
234
  self.minimizable = True
@@ -247,20 +237,16 @@ class BaseGridWindow(BaseWindow):
247
237
  self.grid_panel.layout_config['align'] = 'stretch'
248
238
 
249
239
  # добавление фильтрующих полей в фильтрующую панель
250
- assert self.filter_cnt.filters, (
251
- 'Необходимо добавить элементы в список фильтров '
252
- '(self.filter_cnt.filters)!')
240
+ assert self.filter_cnt.filters, 'Необходимо добавить элементы в список фильтров (self.filter_cnt.filters)!'
253
241
 
254
- self.items.extend([
255
- self.filter_cnt, self.grid_panel
256
- ])
242
+ self.items.extend([self.filter_cnt, self.grid_panel])
257
243
 
258
244
  def set_params(self, params):
245
+ super().set_params(params)
259
246
 
260
- super(BaseGridWindow, self).set_params(params)
261
247
  self.template_globals = 'base-grid-window.js'
262
248
 
263
- self.pack = params["grid_pack"]
249
+ self.pack = params['grid_pack']
264
250
 
265
251
  # урл получения грида для панели с гридом
266
252
  self.grid_panel.grid_url = self.pack.get_grid_action_url()
@@ -279,17 +265,18 @@ class RelatedErrorWindow(BaseWindow):
279
265
  Показывается, если невозможно удаление записи из-за наличия ссылок
280
266
  на удаляемый объект.
281
267
  """
268
+
282
269
  def _init_components(self):
283
- super(RelatedErrorWindow, self)._init_components()
284
- self.title = "Внимание!"
270
+ super()._init_components()
271
+
272
+ self.title = 'Внимание!'
285
273
  self.layout = 'fit'
286
- self.panel = ext.ExtPanel(
287
- auto_scroll=True
288
- )
274
+ self.panel = ext.ExtPanel(auto_scroll=True)
289
275
  self.items.append(self.panel)
290
276
 
291
277
  def set_params(self, params):
292
- super(RelatedErrorWindow, self).set_params(params)
278
+ super().set_params(params)
279
+
293
280
  assert 'html' in params
294
281
  self.panel.html = params['html']
295
282
 
@@ -303,19 +290,17 @@ class _ListWindowMixin:
303
290
  """
304
291
 
305
292
  def __init__(self):
306
- super(_ListWindowMixin, self).__init__()
293
+ super().__init__()
307
294
 
308
- self._mro_exclude_list.extend((
309
- self.grid,
310
- ))
295
+ self._mro_exclude_list.extend((self.grid,))
311
296
 
312
297
  def _init_components(self):
313
- super(_ListWindowMixin, self)._init_components()
298
+ super()._init_components()
314
299
 
315
300
  self._mro_exclude_list.remove(self.grid.top_bar.button_refresh)
316
301
 
317
302
  def set_params(self, params):
318
- super(_ListWindowMixin, self).set_params(params)
303
+ super().set_params(params)
319
304
 
320
305
  if params.get('read_only'):
321
306
  reconfigure_grid_by_access(self.grid)
@@ -334,7 +319,7 @@ class _SelectWindowMixin(_ListWindowMixin):
334
319
  """Класс-примесь для окон выбора объектов."""
335
320
 
336
321
  def set_params(self, params):
337
- super(_SelectWindowMixin, self).set_params(params)
322
+ super().set_params(params)
338
323
 
339
324
  reconfigure_grid_by_access(self.grid, can_view=False)
340
325
 
@@ -357,14 +342,11 @@ class BaseMultiSelectWindow(_SelectWindowMixin, OPBaseMultiSelectWindow):
357
342
  """
358
343
 
359
344
  def set_params(self, params):
360
- super(BaseMultiSelectWindow, self).set_params(params)
345
+ super().set_params(params)
346
+
361
347
  self.grid.allow_paging = False
362
- self.multiselect_page_fix = local_template(
363
- 'templates/multiselect-page-fix.js'
364
- )
365
- self.template_globals = local_template(
366
- 'templates/multiSelectWindow.js'
367
- )
348
+ self.multiselect_page_fix = local_template('templates/multiselect-page-fix.js')
349
+ self.template_globals = local_template('templates/multiSelectWindow.js')
368
350
 
369
351
 
370
352
  class EditWindowMixin:
@@ -377,7 +359,7 @@ class EditWindowMixin:
377
359
  """
378
360
 
379
361
  def set_params(self, params):
380
- super(EditWindowMixin, self).set_params(params)
362
+ super().set_params(params)
381
363
 
382
364
  if params.get('read_only'):
383
365
  # TODO: Выпилить эту функцию, а ее код перенести сюда
@@ -4,6 +4,7 @@
4
4
  различных элементов отчётной подсистемы: провайдера данных, построителя отчёта
5
5
  и собственно отчёта.
6
6
  """
7
+
7
8
  from abc import (
8
9
  ABCMeta,
9
10
  abstractmethod,
@@ -209,7 +210,7 @@ class AbstractReportBuilder(metaclass=ABCMeta):
209
210
 
210
211
  @abstractmethod
211
212
  def build(self):
212
- """ Метод, осуществляющий построение отчёта.
213
+ """Метод, осуществляющий построение отчёта.
213
214
 
214
215
  Должен возвращать результат в виде файла или иной структуры данных.
215
216
  """
@@ -241,7 +242,7 @@ class BaseProviderAdapter(Mapping, dict):
241
242
 
242
243
  'Магические' и некоторые отдельные методы будут игнорироваться.
243
244
  """
244
- return not(attr.startswith('_') or attr in self._attrs_stop_list)
245
+ return not (attr.startswith('_') or attr in self._attrs_stop_list)
245
246
 
246
247
 
247
248
  class FlatDataProviderAdapter(BaseProviderAdapter):
@@ -265,7 +266,7 @@ class FlatDataProviderAdapter(BaseProviderAdapter):
265
266
  """
266
267
  assert isinstance(splitter, str), type(splitter)
267
268
 
268
- super(FlatDataProviderAdapter, self).__init__(provider)
269
+ super().__init__(provider)
269
270
 
270
271
  self.level_splitter = splitter
271
272
  self._all_keys = self._get_all_keys(self.provider)
@@ -274,7 +275,7 @@ class FlatDataProviderAdapter(BaseProviderAdapter):
274
275
  """Все ключи в иерархии провайдеров."""
275
276
  result = []
276
277
  if key_level is None:
277
- key_level = ""
278
+ key_level = ''
278
279
  else:
279
280
  if key_level:
280
281
  key_level += self.level_splitter + provider.name
@@ -333,6 +334,7 @@ class FlatDataProviderAdapter(BaseProviderAdapter):
333
334
 
334
335
  def __bool__(self):
335
336
  return bool(self._all_keys)
337
+
336
338
  __nonzero__ = __bool__
337
339
 
338
340
  def __iter__(self):
@@ -361,7 +363,8 @@ class NestedDataProviderAdapter(BaseProviderAdapter):
361
363
 
362
364
  :param provider: провайдер данных
363
365
  """
364
- super(NestedDataProviderAdapter, self).__init__(provider)
366
+ super().__init__(provider)
367
+
365
368
  self._all_keys = self._get_top_keys(self.provider)
366
369
 
367
370
  def _get_top_keys(self, provider):
@@ -410,6 +413,7 @@ class NestedDataProviderAdapter(BaseProviderAdapter):
410
413
 
411
414
  def __bool__(self):
412
415
  return bool(self._all_keys)
416
+
413
417
  __nonzero__ = __bool__
414
418
 
415
419
  def __iter__(self):
@@ -1,4 +1,5 @@
1
1
  """Генерация отчётов средствами платформы M3."""
2
+
2
3
  from m3 import (
3
4
  ApplicationLogicException,
4
5
  )
@@ -17,7 +18,6 @@ from objectpack.ui import (
17
18
 
18
19
 
19
20
  class BaseReportPack(BasePack):
20
-
21
21
  """Базовый класс отчёта.
22
22
 
23
23
  Отчёты на любых движках могут быть описаны на основе этого класса.
@@ -74,19 +74,19 @@ def download_result(url):
74
74
  url = str(url, 'utf-8')
75
75
  return OperationResult(
76
76
  success=True,
77
- code="""
78
- (function(){
77
+ code=f"""
78
+ (function() {{
79
79
  var hiddenIFrameID = 'hiddenDownloader',
80
80
  iframe = document.getElementById(hiddenIFrameID);
81
- if (iframe === null) {
81
+ if (iframe === null) {{
82
82
  iframe = document.createElement('iframe');
83
83
  iframe.id = hiddenIFrameID;
84
84
  iframe.style.display = 'none';
85
85
  document.body.appendChild(iframe);
86
- }
87
- iframe.src = "%s";
88
- })()
89
- """ % url
86
+ }}
87
+ iframe.src = "{url}";
88
+ }})()
89
+ """,
90
90
  )
91
91
 
92
92
 
@@ -105,12 +105,12 @@ class CommonReportWindowAction(BaseWindowAction):
105
105
 
106
106
  def set_window_params(self):
107
107
  """Задание параметров окна."""
108
- super(CommonReportWindowAction, self).set_window_params()
108
+ super().set_window_params()
109
+
109
110
  params = self.win_params.copy()
110
111
  params['title'] = self.parent.title
111
112
  params['form_url'] = self.parent.get_reporting_url()
112
- self.win_params = self.parent.set_report_window_params(
113
- params, self.request, self.context)
113
+ self.win_params = self.parent.set_report_window_params(params, self.request, self.context)
114
114
 
115
115
 
116
116
  class CommonReportAction(BaseAction):
@@ -130,12 +130,12 @@ class CommonReportAction(BaseAction):
130
130
  builder_params.update(title=pack.title)
131
131
  # генерация отчёта
132
132
  out_file_url = pack.make_report(provider_params, builder_params)
133
+
133
134
  return download_result(out_file_url.encode('utf-8'))
134
135
 
135
136
 
136
137
  class CommonReportPack(BasePack):
137
- """
138
- Пак, реализующий генерацию отчётов.
138
+ """Пак, реализующий генерацию отчётов.
139
139
 
140
140
  Использует класс-построитель reporter.
141
141
  """
@@ -159,14 +159,16 @@ class CommonReportPack(BasePack):
159
159
 
160
160
  def __init__(self):
161
161
  """Конструктор пака генерации отчётов."""
162
- super(CommonReportPack, self).__init__()
162
+ super().__init__()
163
163
 
164
164
  self.report_window_action = CommonReportWindowAction()
165
165
  self.report_action = CommonReportAction()
166
- self.actions.extend([
167
- self.report_window_action,
168
- self.report_action,
169
- ])
166
+ self.actions.extend(
167
+ [
168
+ self.report_window_action,
169
+ self.report_action,
170
+ ]
171
+ )
170
172
 
171
173
  def get_reporting_url(self):
172
174
  """Отдаёт адрес форме, куда передавать данные для обработки."""
@@ -174,7 +176,7 @@ class CommonReportPack(BasePack):
174
176
 
175
177
  @staticmethod
176
178
  def context2dict(context):
177
- """преобразование контекста в словарь."""
179
+ """Преобразование контекста в словарь."""
178
180
  result = {}
179
181
  for key, value in context.__dict__.items():
180
182
  try:
@@ -187,16 +189,14 @@ class CommonReportPack(BasePack):
187
189
  return result
188
190
 
189
191
  def check_report_params(self, request, context):
190
- """
191
- Проверка передаваемых параметров для формирования отчёта.
192
+ """Проверка передаваемых параметров для формирования отчёта.
192
193
 
193
194
  :raise: ApplicationLogicException
194
195
  """
195
196
  pass
196
197
 
197
198
  def get_provider_params(self, request, context):
198
- """
199
- Преобразование request, context к словарю для создания провайдера.
199
+ """Преобразование request, context к словарю для создания провайдера.
200
200
 
201
201
  :param request:
202
202
  :param context:
@@ -204,8 +204,7 @@ class CommonReportPack(BasePack):
204
204
  return {}
205
205
 
206
206
  def get_builder_params(self, request, context):
207
- """
208
- Преобразование request, context к словарю для создания билдера.
207
+ """Преобразование request, context к словарю для создания билдера.
209
208
 
210
209
  :param request:
211
210
  :param context:
@@ -213,8 +212,7 @@ class CommonReportPack(BasePack):
213
212
  return {}
214
213
 
215
214
  def init_reporter(self, provider_params, builder_params):
216
- """
217
- Инициализация построителя с передачей параметров билдеру и провайдеру.
215
+ """Инициализация построителя с передачей параметров билдеру и провайдеру.
218
216
 
219
217
  Не требует переопределения.
220
218
  """
@@ -224,20 +222,19 @@ class CommonReportPack(BasePack):
224
222
  """Синхронное построение отчёта. Не требует переопределения."""
225
223
  reporter = self.init_reporter(provider_params, builder_params)
226
224
  url = reporter.make_report()
225
+
227
226
  return url
228
227
 
229
228
  def set_report_window_params(self, params, request, context):
230
229
  """Дополнение параметров окна отчёта."""
231
- if self.reporter_class.extension not in (
232
- self.reporter_class._available_extensions
233
- ):
230
+ if self.reporter_class.extension not in (self.reporter_class._available_extensions):
234
231
  raise ApplicationLogicException('Расширение указано неверно!')
235
232
  params['extension'] = self.reporter_class.extension
233
+
236
234
  return params
237
235
 
238
236
  def create_report_window(self, request, context):
239
- """
240
- Cоздание окна настройки параметров отчёта.
237
+ """Cоздание окна настройки параметров отчёта.
241
238
 
242
239
  Не требует переопределения.
243
240
  """
@@ -2,6 +2,7 @@
2
2
 
3
3
  Поддерживает конструирование пользователем простых отчетов в формате Excel.
4
4
  """
5
+
5
6
  import django
6
7
  from pkg_resources import (
7
8
  get_distribution,
@@ -19,16 +20,12 @@ default_app_config = __name__ + '.apps.AppConfig'
19
20
  dist = get_distribution('m3-ui').version
20
21
  version = tuple(int(x) for x in dist.split('.'))
21
22
 
22
- assert (
23
- (2, 0, 9) <= version < (2, 1) or
24
- (2, 1, 9) <= version < (2, 2) or
25
- (2, 2, 11) <= version < (2, 3)
26
- ), 'Конструктор отчетов не поддерживает версию {} пакета m3-ui'.format(dist)
23
+ assert (2, 0, 9) <= version < (2, 1) or (2, 1, 9) <= version < (2, 2) or (2, 2, 11) <= version < (2, 3), (
24
+ 'Конструктор отчетов не поддерживает версию {} пакета m3-ui'.format(dist)
25
+ )
27
26
  # -----------------------------------------------------------------------------
28
27
  # Проверка версии Django
29
28
 
30
29
 
31
- assert django.VERSION >= (1, 8), (
32
- 'Конструктор отчетов работает только в системах на базе Django 1.8+'
33
- )
30
+ assert django.VERSION >= (1, 8), 'Конструктор отчетов работает только в системах на базе Django 1.8+'
34
31
  # -----------------------------------------------------------------------------
@@ -7,6 +7,4 @@ from educommon.report.constructor.editor.actions import (
7
7
 
8
8
 
9
9
  def register_actions():
10
- ioc.get('main_controller').packs.extend((
11
- Pack(),
12
- ))
10
+ ioc.get('main_controller').packs.extend((Pack(),))
@@ -11,6 +11,7 @@ from django.db.models.functions import (
11
11
 
12
12
 
13
13
  class AppConfig(config.AppConfig):
14
+ """Конфигурация приложения конструктора отчётов."""
14
15
 
15
16
  name = __name__.rpartition('.')[0]
16
17
  label = 'report_constructor'