meerschaum 2.7.8__py3-none-any.whl → 2.7.9__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. meerschaum/_internal/term/TermPageHandler.py +54 -4
  2. meerschaum/_internal/term/__init__.py +13 -5
  3. meerschaum/_internal/term/tools.py +41 -6
  4. meerschaum/actions/start.py +25 -10
  5. meerschaum/api/dash/callbacks/dashboard.py +43 -2
  6. meerschaum/api/dash/components.py +13 -6
  7. meerschaum/api/dash/keys.py +82 -108
  8. meerschaum/api/dash/pages/dashboard.py +17 -17
  9. meerschaum/api/dash/sessions.py +1 -0
  10. meerschaum/api/dash/webterm.py +17 -6
  11. meerschaum/api/resources/static/js/terminado.js +0 -2
  12. meerschaum/api/resources/templates/termpage.html +47 -4
  13. meerschaum/api/routes/_webterm.py +15 -11
  14. meerschaum/config/_default.py +6 -0
  15. meerschaum/config/_version.py +1 -1
  16. meerschaum/config/static/__init__.py +2 -2
  17. meerschaum/core/Pipe/_sync.py +7 -7
  18. meerschaum/core/Pipe/_verify.py +1 -1
  19. meerschaum/utils/daemon/Daemon.py +15 -9
  20. meerschaum/utils/dtypes/__init__.py +9 -0
  21. meerschaum/utils/dtypes/sql.py +19 -13
  22. meerschaum/utils/formatting/_pprint.py +1 -1
  23. meerschaum/utils/misc.py +16 -0
  24. meerschaum/utils/venv/__init__.py +10 -14
  25. {meerschaum-2.7.8.dist-info → meerschaum-2.7.9.dist-info}/METADATA +1 -1
  26. {meerschaum-2.7.8.dist-info → meerschaum-2.7.9.dist-info}/RECORD +32 -32
  27. {meerschaum-2.7.8.dist-info → meerschaum-2.7.9.dist-info}/LICENSE +0 -0
  28. {meerschaum-2.7.8.dist-info → meerschaum-2.7.9.dist-info}/NOTICE +0 -0
  29. {meerschaum-2.7.8.dist-info → meerschaum-2.7.9.dist-info}/WHEEL +0 -0
  30. {meerschaum-2.7.8.dist-info → meerschaum-2.7.9.dist-info}/entry_points.txt +0 -0
  31. {meerschaum-2.7.8.dist-info → meerschaum-2.7.9.dist-info}/top_level.txt +0 -0
  32. {meerschaum-2.7.8.dist-info → meerschaum-2.7.9.dist-info}/zip-safe +0 -0
@@ -105,59 +105,58 @@ action_dropdown_row = html.Div(
105
105
  dbc.Col(
106
106
  html.Div(
107
107
  dcc.Dropdown(
108
- id = 'flags-dropdown',
109
- multi = True,
110
- placeholder = 'Boolean flags',
111
- options = ['--yes'],
112
- value = ['--yes'],
108
+ id='flags-dropdown',
109
+ multi=True,
110
+ placeholder='Boolean flags',
111
+ options=[],
112
+ value=[],
113
113
  ),
114
- id = 'flags-dropdown-div',
115
- className = 'dbc_dark input-text',
114
+ id='flags-dropdown-div',
115
+ className='dbc_dark input-text',
116
116
  ),
117
- width = widths['flags'],
117
+ width=widths['flags'],
118
118
  ),
119
119
  ],
120
120
  ),
121
121
  html.Br(),
122
122
  html.Div(id='input-flags-div'),
123
123
  dbc.Row(
124
- children = [
124
+ children=[
125
125
  dbc.Col(
126
- children = [
126
+ children=[
127
127
  html.Div(
128
- children = [
128
+ children=[
129
129
  dbc.Button(
130
130
  'Additional parameters',
131
- id = 'show-arguments-collapse-button',
132
- color = 'link',
133
- size = 'md',
134
- outline = True,
135
- style = {'display': 'none'},
131
+ id='show-arguments-collapse-button',
132
+ color='link',
133
+ size='md',
134
+ outline=True,
135
+ style={'display': 'none'},
136
136
  ),
137
- # html.Br(),
138
137
  dbc.Collapse(
139
- children = [
138
+ children=[
140
139
  dbc.Button(
141
140
  'Clear',
142
- id = 'clear-begin-end-datepicker-button',
143
- color = 'link',
144
- size = 'sm',
141
+ id='clear-begin-end-datepicker-button',
142
+ color='link',
143
+ size='sm',
145
144
  ),
146
145
  dcc.DatePickerRange(
147
- id = 'begin-end-datepicker',
146
+ id='begin-end-datepicker',
148
147
  ),
149
148
  ],
150
- id = 'arguments-collapse',
149
+ id='arguments-collapse',
151
150
  ),
152
151
  ], ### end of div children
153
152
  ),
154
153
  ], ### end of col children
155
- width = widths['arguments'],
154
+ width=widths['arguments'],
156
155
  ),
157
156
  ], ### end of row children
158
157
  ),
159
158
  ], ### end of parent div children
160
- id = 'action-div',
159
+ id='action-div',
161
160
  )
162
161
 
163
162
 
@@ -167,49 +166,49 @@ dropdown_keys_row = dbc.Row(
167
166
  html.Div(
168
167
  [
169
168
  dcc.Dropdown(
170
- id = 'connector-keys-dropdown',
171
- options = [],
172
- placeholder = placeholders['ck'],
173
- multi = True,
169
+ id='connector-keys-dropdown',
170
+ options=[],
171
+ placeholder=placeholders['ck'],
172
+ multi=True,
174
173
  ),
175
174
  ],
176
- className = 'dbc_dark',
175
+ className='dbc_dark',
177
176
  ),
178
- lg = 4,
179
- md = 12,
180
- sm = 12,
177
+ lg=4,
178
+ md=12,
179
+ sm=12,
181
180
  ),
182
181
  dbc.Col(
183
182
  html.Div(
184
183
  [
185
184
  dcc.Dropdown(
186
- id = 'metric-keys-dropdown',
187
- options = [],
188
- placeholder = placeholders['mk'],
189
- multi = True,
185
+ id='metric-keys-dropdown',
186
+ options=[],
187
+ placeholder=placeholders['mk'],
188
+ multi=True,
190
189
  ),
191
190
  ],
192
- className = 'dbc_dark'
191
+ className='dbc_dark'
193
192
  ),
194
- lg = 4,
195
- md = 12,
196
- sm = 12,
193
+ lg=4,
194
+ md=12,
195
+ sm=12,
197
196
  ),
198
197
  dbc.Col(
199
198
  html.Div(
200
199
  [
201
200
  dcc.Dropdown(
202
- id = 'location-keys-dropdown',
203
- options = [],
204
- placeholder = placeholders['lk'],
205
- multi = True,
201
+ id='location-keys-dropdown',
202
+ options=[],
203
+ placeholder=placeholders['lk'],
204
+ multi=True,
206
205
  ),
207
206
  ],
208
- className = 'dbc_dark'
207
+ className='dbc_dark'
209
208
  ),
210
- lg = 4,
211
- md = 12,
212
- sm = 12,
209
+ lg=4,
210
+ md=12,
211
+ sm=12,
213
212
  ),
214
213
  ] ### end of filters row children
215
214
  )
@@ -217,10 +216,9 @@ dropdown_tab_content = html.Div([
217
216
  dbc.Card(
218
217
  dbc.CardBody(
219
218
  [
220
- # html.P('Pipe Keys'),
221
219
  dropdown_keys_row,
222
220
  ], ### end of card children
223
- className = 'card-text',
221
+ className='card-text',
224
222
  )
225
223
  ),
226
224
  html.Br(),
@@ -229,7 +227,7 @@ dropdown_tab_content = html.Div([
229
227
  [
230
228
  action_dropdown_row,
231
229
  ],
232
- className = 'card-text',
230
+ className='card-text',
233
231
  ),
234
232
  ),
235
233
  ])
@@ -242,75 +240,66 @@ text_tab_content = dbc.Card(
242
240
  dbc.Col(html.Div(className='dbc_dark', children=[
243
241
  dbc.InputGroup(
244
242
  [
245
- # dbc.InputGroupAddon(
246
243
  dbc.Button(
247
244
  'Clear',
248
- id = 'clear-connector-keys-input-button',
249
- color = 'link',
250
- size = 'sm',
245
+ id='clear-connector-keys-input-button',
246
+ color='link',
247
+ size='sm',
251
248
  ),
252
- # addon_type = 'prepend',
253
- # ),
254
249
  dbc.Input(
255
- id = 'connector-keys-input',
256
- placeholder = placeholders['ck'],
257
- type = 'text',
258
- value = '',
259
- list = 'connector-keys-list',
260
- className = 'dbc_dark'
250
+ id='connector-keys-input',
251
+ placeholder=placeholders['ck'],
252
+ type='text',
253
+ value='',
254
+ list='connector-keys-list',
255
+ className='dbc_dark'
261
256
  ),
262
257
  ],
263
- size = input_group_sizes['ck'],
258
+ size=input_group_sizes['ck'],
264
259
  )]),
265
- width = 4,
260
+ width=4,
266
261
  ),
267
262
  dbc.Col(
268
263
  dbc.InputGroup(
269
264
  [
270
- # dbc.InputGroupAddon(
271
265
  dbc.Button(
272
266
  'Clear',
273
- id = 'clear-metric-keys-input-button',
274
- color = 'link',
275
- size = 'sm',
267
+ id='clear-metric-keys-input-button',
268
+ color='link',
269
+ size='sm',
276
270
  ),
277
- # addon_type = 'prepend',
278
- # ),
279
271
  dbc.Input(
280
- id = 'metric-keys-input',
281
- placeholder = placeholders['mk'],
282
- type = 'text',
283
- value = '',
284
- list = 'metric-keys-list',
272
+ id='metric-keys-input',
273
+ placeholder=placeholders['mk'],
274
+ type='text',
275
+ value='',
276
+ list='metric-keys-list',
285
277
  ),
286
278
  ],
287
- size = input_group_sizes['mk'],
279
+ size=input_group_sizes['mk'],
288
280
  ),
289
- width = 4,
281
+ width=4,
290
282
  ),
291
283
  dbc.Col(
292
284
  dbc.InputGroup(
293
285
  [
294
- # dbc.InputGroupAddon(
295
286
  dbc.Button(
296
287
  'Clear',
297
- id = 'clear-location-keys-input-button',
298
- color = 'link',
299
- size = 'sm',
288
+ id='clear-location-keys-input-button',
289
+ color='link',
290
+ size='sm',
300
291
  ),
301
- # addon_type = 'prepend',
302
- # ),
303
292
  dbc.Input(
304
- id = 'location-keys-input',
305
- placeholder = placeholders['lk'],
306
- type = 'text',
307
- value = '',
308
- list = 'location-keys-list',
293
+ id='location-keys-input',
294
+ placeholder=placeholders['lk'],
295
+ type='text',
296
+ value='',
297
+ list='location-keys-list',
309
298
  ),
310
299
  ],
311
- size = input_group_sizes['lk'],
300
+ size=input_group_sizes['lk'],
312
301
  ),
313
- width = 4,
302
+ width=4,
314
303
  ),
315
304
  ]
316
305
  ),
@@ -319,23 +308,9 @@ text_tab_content = dbc.Card(
319
308
  dbc.Col(
320
309
  dbc.InputGroup(
321
310
  [
322
- # dbc.InputGroupAddon(
323
- # dbc.Button(
324
- # 'Clear',
325
- # id = 'clear-params-textarea-button',
326
- # color = 'link',
327
- # size = 'sm',
328
- # ),
329
- # addon_type = 'prepend',
330
- # ),
331
311
  search_parameters_editor,
332
- # dbc.Textarea(
333
- # id = 'params-textarea',
334
- # placeholder = placeholders['params'],
335
- # value = '',
336
- # )
337
312
  ],
338
- size = input_group_sizes['params'],
313
+ size=input_group_sizes['params'],
339
314
  )
340
315
  )
341
316
  ),
@@ -348,4 +323,3 @@ keys_lists_content = html.Div([
348
323
  html.Datalist(id='metric-keys-list'),
349
324
  html.Datalist(id='location-keys-list'),
350
325
  ], hidden=True)
351
-
@@ -65,16 +65,16 @@ layout = html.Div(
65
65
  children = [
66
66
  dbc.Tab(
67
67
  dropdown_tab_content,
68
- label = 'Filter',
69
- id = 'pipes-filter-dropdown-tab',
70
- tab_id = 'dropdown',
68
+ label='Filters',
69
+ id='pipes-filter-dropdown-tab',
70
+ tab_id='dropdown',
71
71
  ),
72
72
  dbc.Tab(
73
73
  text_tab_content,
74
- label = 'Text',
75
- id = 'pipes-filter-input-tab',
76
- tab_id = 'input',
77
- tab_style = {"display": "none"},
74
+ label='Text',
75
+ id='pipes-filter-input-tab',
76
+ tab_id='input',
77
+ tab_style={"display": "none"},
78
78
  ),
79
79
  ]
80
80
  ),
@@ -83,12 +83,12 @@ layout = html.Div(
83
83
  test_button,
84
84
  html.Div(id='ws-div'),
85
85
  ],
86
- id = 'content-col-left',
87
- md = 12,
88
- lg = 6,
86
+ id='content-col-left',
87
+ md=12,
88
+ lg=6,
89
89
  ),
90
90
  dbc.Col(
91
- children = [
91
+ children=[
92
92
  dbc.Col([
93
93
  html.Div(id='success-alert-div'),
94
94
  html.Div(id='instance-alert-div')
@@ -97,20 +97,20 @@ layout = html.Div(
97
97
  ),
98
98
  html.Div(id='webterm-div'),
99
99
  html.Div(
100
- id = 'content-div-right',
101
- children = [console_div],
100
+ id='content-div-right',
101
+ children=[console_div],
102
102
  ),
103
103
  html.Div(id='terminal'),
104
104
  ],
105
- md = 12,
106
- lg = 6,
107
- id = 'content-col-right',
105
+ md=12,
106
+ lg=6,
107
+ id='content-col-right',
108
108
  ),
109
109
  ],
110
110
  style = {'max-width': '100%', 'padding': '15px'},
111
111
  ), ### end of Row
112
112
  className = 'container-fluid',
113
113
  ), ### end of Div
114
- html.P('', id='line-buffer', style = {'display': 'none'}),
114
+ html.P('', id='line-buffer', style={'display': 'none'}),
115
115
  ],
116
116
  )
@@ -97,6 +97,7 @@ def delete_session(session_id: str):
97
97
  """
98
98
  Delete a session if it's been set.
99
99
  """
100
+ ### TODO: Delete webterm sessions.
100
101
  if debug:
101
102
  dprint(f"Deleting {session_id=}")
102
103
  conn = get_cache_connector()
@@ -14,10 +14,12 @@ from meerschaum.utils.typing import WebState, Tuple, Any
14
14
  from meerschaum.utils.packages import attempt_import, import_html, import_dcc
15
15
  from meerschaum._internal.term.tools import is_webterm_running
16
16
  from meerschaum.utils.threading import Thread, RLock
17
+ from meerschaum.utils.misc import is_tmux_available
17
18
  dcc, html = import_dcc(check_update=CHECK_UPDATE), import_html(check_update=CHECK_UPDATE)
18
19
  dbc = attempt_import('dash_bootstrap_components', lazy=False, check_update=CHECK_UPDATE)
19
20
 
20
21
  MAX_WEBTERM_ATTEMPTS: int = 10
22
+ TMUX_IS_AVAILABLE: bool = is_tmux_available()
21
23
 
22
24
  _locks = {'webterm_thread': RLock()}
23
25
 
@@ -32,7 +34,7 @@ def get_webterm(state: WebState) -> Tuple[Any, Any]:
32
34
  return (
33
35
  html.Div(
34
36
  html.Pre(msg, id='console-pre'),
35
- id = "console-div",
37
+ id="console-div",
36
38
  ),
37
39
  [alert_from_success_tuple((
38
40
  False,
@@ -41,12 +43,21 @@ def get_webterm(state: WebState) -> Tuple[Any, Any]:
41
43
  )
42
44
 
43
45
  for i in range(MAX_WEBTERM_ATTEMPTS):
44
- if is_webterm_running('localhost', 8765):
46
+ if is_webterm_running('localhost', 8765, session_id=(username or session_id)):
45
47
  return (
46
- html.Iframe(
47
- src = f"/webterm?s={session_id}",
48
- id = "webterm-iframe",
49
- ),
48
+ [
49
+ html.Div(
50
+ [
51
+ dbc.Button('Refresh', color='black', id='webterm-refresh-button'),
52
+ dbc.Button('New Tab', color='black', id='webterm-new-tab-button'),
53
+ ],
54
+ id='webterm-controls-div',
55
+ ),
56
+ html.Iframe(
57
+ src=f"/webterm/{session_id}",
58
+ id="webterm-iframe",
59
+ ),
60
+ ],
50
61
  []
51
62
  )
52
63
  time.sleep(1)
@@ -15,9 +15,7 @@ function make_terminal(element, size, ws_url) {
15
15
  term.attachCustomKeyEventHandler(copyPasteKeyEventHandler);
16
16
  term.open(element);
17
17
 
18
- sessionStore = localStorage.getItem("session-store");
19
18
  ws.onopen = function (event) {
20
- ws.send(sessionStore);
21
19
  ws.send(
22
20
  JSON.stringify([
23
21
  "set_size",
@@ -84,6 +84,15 @@ window.addEventListener(
84
84
  flags_str += " " + fl + " " + fl_val;
85
85
  }
86
86
 
87
+ let line = "";
88
+ if (action_str === "__TMUX_NEW_WINDOW") {
89
+ line = "\x02:";
90
+ window.terminal.socket.send(JSON.stringify(["stdin", line]));
91
+ line = "new-window python3 -m meerschaum\r";
92
+ window.terminal.socket.send(JSON.stringify(["stdin", line]));
93
+ return;
94
+ }
95
+
87
96
  line = (
88
97
  "\x03"
89
98
  + action_str
@@ -98,6 +107,26 @@ window.addEventListener(
98
107
  false,
99
108
  );
100
109
 
110
+ let reconnectTimeout;
111
+
112
+ function cleanUpWebSocket(socket) {
113
+ if (!socket) { return; }
114
+ socket.onopen = null;
115
+ socket.onmessage = null;
116
+ socket.onerror = null;
117
+ socket.onclose = null;
118
+
119
+ if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
120
+ socket.close(1000, "Reconnecting");
121
+ }
122
+
123
+ if (reconnectTimeout) {
124
+ clearTimeout(reconnectTimeout);
125
+ reconnectTimeout = null;
126
+ }
127
+
128
+ socket = null;
129
+ }
101
130
 
102
131
  window.onload = function() {
103
132
  var termRowHeight = 0.0 + 0.95*document.getElementById("dummy-screen").offsetHeight / 25;
@@ -115,15 +144,29 @@ window.onload = function() {
115
144
 
116
145
  xterm_div = document.getElementById("xterm-div");
117
146
  size = calculate_size(window);
118
- var terminal = make_terminal(xterm_div, size, ws_url);
119
- window.terminal = terminal;
147
+
148
+ function init_webterm() {
149
+ old_terminal = window.terminal;
150
+ if (old_terminal){
151
+ xterm_div.innerHTML = "";
152
+ cleanUpWebSocket(old_terminal.socket);
153
+ }
154
+ window.terminal = make_terminal(xterm_div, size, ws_url);
155
+ window.terminal.socket.onclose = function (event) {
156
+ if (!event.wasClean && event.code !== 1005) {
157
+ reconnectTimeout = setTimeout(init_webterm, 1000);
158
+ }
159
+ }
160
+ }
161
+
162
+ init_webterm();
120
163
 
121
164
  window.onresize = function() {
122
165
  var geom = calculate_size(window);
123
166
  rows = geom.rows;
124
167
  cols = geom.cols;
125
- terminal.term.resize(cols, rows);
126
- terminal.socket.send(
168
+ window.terminal.term.resize(cols, rows);
169
+ window.terminal.socket.send(
127
170
  JSON.stringify(
128
171
  ["set_size", rows, cols, xterm_div.innerHeight, xterm_div.innerWidth]
129
172
  )
@@ -10,7 +10,7 @@ import asyncio
10
10
  from meerschaum.utils.typing import Optional
11
11
  from meerschaum.api import app, endpoints
12
12
  from meerschaum.utils.packages import attempt_import
13
- from meerschaum.api.dash.sessions import is_session_authenticated
13
+ from meerschaum.api.dash.sessions import is_session_authenticated, get_username_from_session
14
14
  fastapi, fastapi_responses = attempt_import('fastapi', 'fastapi.responses')
15
15
  import starlette
16
16
 
@@ -27,12 +27,12 @@ PlainTextResponse = fastapi_responses.PlainTextResponse
27
27
  @app.get(endpoints['webterm'], tags=["Webterm"])
28
28
  async def get_webterm(
29
29
  request: Request,
30
- s: Optional[str] = None,
30
+ session_id: str,
31
31
  ) -> HTMLResponse:
32
32
  """
33
33
  Get the main HTML template for the Webterm.
34
34
  """
35
- if not is_session_authenticated(s):
35
+ if not is_session_authenticated(session_id):
36
36
  return HTMLResponse(
37
37
  """
38
38
  <html>
@@ -69,35 +69,39 @@ async def get_webterm(
69
69
  status_code = 401,
70
70
  )
71
71
 
72
+ username = get_username_from_session(session_id)
72
73
  async with httpx.AsyncClient() as client:
73
- response = await client.get("http://localhost:8765/")
74
+ webterm_url = f"http://localhost:8765/webterm/{username or session_id}"
75
+ response = await client.get(webterm_url)
74
76
  text = response.text
75
77
  if request.url.scheme == 'https':
76
78
  text = text.replace('ws://', 'wss://')
79
+ text = text.replace(f'_websocket/{username}', f'_websocket/{session_id}')
77
80
  return HTMLResponse(
78
- content = text,
79
- status_code = response.status_code,
80
- headers = request.headers,
81
+ content=text,
82
+ status_code=response.status_code,
83
+ headers=request.headers,
81
84
  )
82
85
 
83
86
 
84
87
  @app.websocket(endpoints['webterm_websocket'])
85
- async def webterm_websocket(websocket: WebSocket):
88
+ async def webterm_websocket(websocket: WebSocket, session_id: str):
86
89
  """
87
90
  Connect to the Webterm's websocket.
88
91
  """
89
92
  try:
90
93
  await websocket.accept()
91
- session_doc = await websocket.receive_json()
92
94
  except starlette.websockets.WebSocketDisconnect:
93
95
  return
94
- session_id = (session_doc or {}).get('session-id', 'no-auth')
95
96
 
96
97
  if not is_session_authenticated(session_id):
97
98
  await websocket.close()
98
99
  return
99
100
 
100
- async with websockets.connect("ws://localhost:8765/websocket") as ws:
101
+ username = get_username_from_session(session_id)
102
+
103
+ ws_url = f"ws://localhost:8765/_websocket/{username or session_id}"
104
+ async with websockets.connect(ws_url) as ws:
101
105
  async def forward_messages():
102
106
  try:
103
107
  while True:
@@ -127,6 +127,12 @@ default_system_config = {
127
127
  },
128
128
  'protocol': default_meerschaum_config['connectors']['api']['default']['protocol'],
129
129
  },
130
+ 'webterm': {
131
+ 'tmux': {
132
+ 'enabled': True,
133
+ 'session_suffix': '_mrsm',
134
+ },
135
+ },
130
136
  'experimental': {
131
137
  'fetch': False,
132
138
  'cache': True,
@@ -2,4 +2,4 @@
2
2
  Specify the Meerschaum release version.
3
3
  """
4
4
 
5
- __version__ = "2.7.8"
5
+ __version__ = "2.7.9"
@@ -32,8 +32,8 @@ STATIC_CONFIG: Dict[str, Any] = {
32
32
  'chaining': '/chaining',
33
33
  'websocket': '/ws',
34
34
  'dash': '/dash',
35
- 'webterm': '/webterm',
36
- 'webterm_websocket': '/websocket',
35
+ 'webterm': r'/webterm/{session_id}',
36
+ 'webterm_websocket': r'/_websocket/{session_id}',
37
37
  'info': '/info',
38
38
  'healthcheck': '/healthcheck',
39
39
  },
@@ -327,15 +327,15 @@ def sync(
327
327
  _chunk_success, _chunk_msg = False, str(e)
328
328
  if not _chunk_success:
329
329
  failed_chunks.append(_chunk)
330
- return (
331
- _chunk_success,
332
- (
333
- self._get_chunk_label(_chunk, dt_col)
334
- + '\n'
335
- + _chunk_msg
336
- )
330
+ _chunk_msg = (
331
+ self._get_chunk_label(_chunk, dt_col)
332
+ + '\n'
333
+ + _chunk_msg
337
334
  )
338
335
 
336
+ mrsm.pprint((_chunk_success, _chunk_msg), calm=True)
337
+ return _chunk_success, _chunk_msg
338
+
339
339
  results = sorted(
340
340
  [(chunk_success, chunk_msg)] + (
341
341
  list(pool.imap(_process_chunk, df))