meerschaum 3.0.0rc3__py3-none-any.whl → 3.0.0rc7__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.
- meerschaum/_internal/arguments/_parser.py +14 -2
- meerschaum/_internal/cli/__init__.py +6 -0
- meerschaum/_internal/cli/daemons.py +103 -0
- meerschaum/_internal/cli/entry.py +220 -0
- meerschaum/_internal/cli/workers.py +434 -0
- meerschaum/_internal/docs/index.py +1 -2
- meerschaum/_internal/entry.py +44 -8
- meerschaum/_internal/shell/Shell.py +113 -19
- meerschaum/_internal/shell/__init__.py +4 -1
- meerschaum/_internal/static.py +3 -1
- meerschaum/_internal/term/TermPageHandler.py +1 -2
- meerschaum/_internal/term/__init__.py +40 -6
- meerschaum/_internal/term/tools.py +33 -8
- meerschaum/actions/__init__.py +6 -4
- meerschaum/actions/api.py +39 -11
- meerschaum/actions/attach.py +1 -0
- meerschaum/actions/delete.py +4 -2
- meerschaum/actions/edit.py +27 -8
- meerschaum/actions/login.py +8 -8
- meerschaum/actions/register.py +13 -7
- meerschaum/actions/reload.py +22 -5
- meerschaum/actions/restart.py +14 -0
- meerschaum/actions/show.py +69 -4
- meerschaum/actions/start.py +135 -14
- meerschaum/actions/stop.py +36 -3
- meerschaum/actions/sync.py +6 -1
- meerschaum/api/__init__.py +35 -13
- meerschaum/api/_events.py +7 -2
- meerschaum/api/_oauth2.py +47 -4
- meerschaum/api/dash/callbacks/dashboard.py +103 -97
- meerschaum/api/dash/callbacks/jobs.py +3 -2
- meerschaum/api/dash/callbacks/login.py +10 -1
- meerschaum/api/dash/callbacks/pipes.py +136 -57
- meerschaum/api/dash/callbacks/register.py +9 -2
- meerschaum/api/dash/callbacks/tokens.py +2 -1
- meerschaum/api/dash/components.py +6 -7
- meerschaum/api/dash/keys.py +17 -1
- meerschaum/api/dash/pages/login.py +2 -2
- meerschaum/api/dash/pages/pipes.py +14 -4
- meerschaum/api/dash/pipes.py +186 -65
- meerschaum/api/dash/tokens.py +1 -1
- meerschaum/api/dash/webterm.py +14 -6
- meerschaum/api/models/_pipes.py +7 -1
- meerschaum/api/resources/static/js/terminado.js +3 -0
- meerschaum/api/resources/static/js/xterm-addon-unicode11.js +2 -0
- meerschaum/api/resources/templates/termpage.html +1 -0
- meerschaum/api/routes/_jobs.py +23 -11
- meerschaum/api/routes/_login.py +73 -5
- meerschaum/api/routes/_pipes.py +6 -4
- meerschaum/api/routes/_webterm.py +3 -3
- meerschaum/config/__init__.py +60 -13
- meerschaum/config/_default.py +89 -61
- meerschaum/config/_edit.py +10 -8
- meerschaum/config/_formatting.py +2 -0
- meerschaum/config/_patch.py +4 -2
- meerschaum/config/_paths.py +127 -12
- meerschaum/config/_read_config.py +20 -10
- meerschaum/config/_version.py +1 -1
- meerschaum/config/environment.py +262 -0
- meerschaum/config/stack/__init__.py +7 -5
- meerschaum/connectors/_Connector.py +1 -2
- meerschaum/connectors/__init__.py +37 -2
- meerschaum/connectors/api/_APIConnector.py +1 -1
- meerschaum/connectors/api/_jobs.py +11 -0
- meerschaum/connectors/api/_pipes.py +7 -1
- meerschaum/connectors/instance/_plugins.py +9 -1
- meerschaum/connectors/instance/_tokens.py +20 -3
- meerschaum/connectors/instance/_users.py +8 -1
- meerschaum/connectors/parse.py +1 -1
- meerschaum/connectors/sql/_create_engine.py +3 -0
- meerschaum/connectors/sql/_pipes.py +98 -79
- meerschaum/connectors/sql/_users.py +8 -1
- meerschaum/connectors/sql/tables/__init__.py +20 -3
- meerschaum/connectors/valkey/_ValkeyConnector.py +3 -3
- meerschaum/connectors/valkey/_pipes.py +7 -5
- meerschaum/core/Pipe/__init__.py +62 -72
- meerschaum/core/Pipe/_attributes.py +66 -90
- meerschaum/core/Pipe/_cache.py +555 -0
- meerschaum/core/Pipe/_clear.py +0 -11
- meerschaum/core/Pipe/_data.py +0 -50
- meerschaum/core/Pipe/_deduplicate.py +0 -13
- meerschaum/core/Pipe/_delete.py +12 -21
- meerschaum/core/Pipe/_drop.py +11 -23
- meerschaum/core/Pipe/_dtypes.py +1 -1
- meerschaum/core/Pipe/_index.py +8 -14
- meerschaum/core/Pipe/_sync.py +12 -18
- meerschaum/core/Plugin/_Plugin.py +7 -1
- meerschaum/core/Token/_Token.py +1 -1
- meerschaum/core/User/_User.py +1 -2
- meerschaum/jobs/_Executor.py +88 -4
- meerschaum/jobs/_Job.py +135 -35
- meerschaum/jobs/systemd.py +7 -2
- meerschaum/plugins/__init__.py +277 -81
- meerschaum/utils/_get_pipes.py +30 -4
- meerschaum/utils/daemon/Daemon.py +195 -41
- meerschaum/utils/daemon/FileDescriptorInterceptor.py +0 -1
- meerschaum/utils/daemon/RotatingFile.py +63 -36
- meerschaum/utils/daemon/StdinFile.py +53 -13
- meerschaum/utils/daemon/__init__.py +18 -5
- meerschaum/utils/daemon/_names.py +6 -3
- meerschaum/utils/debug.py +34 -4
- meerschaum/utils/dtypes/__init__.py +5 -1
- meerschaum/utils/formatting/__init__.py +4 -1
- meerschaum/utils/formatting/_jobs.py +1 -1
- meerschaum/utils/formatting/_pipes.py +47 -46
- meerschaum/utils/formatting/_pprint.py +1 -0
- meerschaum/utils/formatting/_shell.py +16 -6
- meerschaum/utils/misc.py +18 -38
- meerschaum/utils/packages/__init__.py +15 -13
- meerschaum/utils/packages/_packages.py +1 -0
- meerschaum/utils/pipes.py +39 -7
- meerschaum/utils/process.py +1 -1
- meerschaum/utils/prompt.py +171 -144
- meerschaum/utils/sql.py +12 -2
- meerschaum/utils/threading.py +42 -0
- meerschaum/utils/venv/__init__.py +2 -0
- meerschaum/utils/warnings.py +19 -13
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/METADATA +3 -1
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/RECORD +125 -119
- meerschaum/config/_environment.py +0 -145
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/WHEEL +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/entry_points.txt +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/licenses/LICENSE +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/licenses/NOTICE +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/top_level.txt +0 -0
- {meerschaum-3.0.0rc3.dist-info → meerschaum-3.0.0rc7.dist-info}/zip-safe +0 -0
meerschaum/jobs/_Job.py
CHANGED
@@ -12,8 +12,8 @@ import shlex
|
|
12
12
|
import asyncio
|
13
13
|
import pathlib
|
14
14
|
import sys
|
15
|
+
import json
|
15
16
|
import traceback
|
16
|
-
from functools import partial
|
17
17
|
from datetime import datetime, timezone
|
18
18
|
|
19
19
|
import meerschaum as mrsm
|
@@ -25,6 +25,7 @@ from meerschaum.utils.warnings import warn
|
|
25
25
|
from meerschaum.config.paths import LOGS_RESOURCES_PATH
|
26
26
|
from meerschaum.config import get_config
|
27
27
|
from meerschaum._internal.static import STATIC_CONFIG
|
28
|
+
from meerschaum.utils.formatting._shell import clear_screen
|
28
29
|
|
29
30
|
if TYPE_CHECKING:
|
30
31
|
from meerschaum.jobs._Executor import Executor
|
@@ -39,6 +40,8 @@ RESTART_FLAGS: List[str] = [
|
|
39
40
|
'--schedule',
|
40
41
|
'--cron',
|
41
42
|
]
|
43
|
+
STOP_TOKEN: str = STATIC_CONFIG['jobs']['stop_token']
|
44
|
+
CLEAR_TOKEN: str = STATIC_CONFIG['jobs']['clear_token']
|
42
45
|
|
43
46
|
class StopMonitoringLogs(Exception):
|
44
47
|
"""
|
@@ -46,6 +49,20 @@ class StopMonitoringLogs(Exception):
|
|
46
49
|
"""
|
47
50
|
|
48
51
|
|
52
|
+
def _default_stdout_callback(line: str):
|
53
|
+
if line == '\n':
|
54
|
+
print('', end='', flush=True)
|
55
|
+
return
|
56
|
+
|
57
|
+
if CLEAR_TOKEN in line:
|
58
|
+
clear_screen()
|
59
|
+
return
|
60
|
+
|
61
|
+
if STOP_TOKEN in line:
|
62
|
+
return
|
63
|
+
|
64
|
+
print(line, end='', flush=True)
|
65
|
+
|
49
66
|
class Job:
|
50
67
|
"""
|
51
68
|
Manage a `meerschaum.utils.daemon.Daemon`, locally or remotely via the API.
|
@@ -58,6 +75,7 @@ class Job:
|
|
58
75
|
env: Optional[Dict[str, str]] = None,
|
59
76
|
executor_keys: Optional[str] = None,
|
60
77
|
delete_after_completion: bool = False,
|
78
|
+
refresh_seconds: Union[int, float, None] = None,
|
61
79
|
_properties: Optional[Dict[str, Any]] = None,
|
62
80
|
_rotating_log=None,
|
63
81
|
_stdin_file=None,
|
@@ -86,6 +104,10 @@ class Job:
|
|
86
104
|
delete_after_completion: bool, default False
|
87
105
|
If `True`, delete this job when it has finished executing.
|
88
106
|
|
107
|
+
refresh_seconds: Union[int, float, None], default None
|
108
|
+
The number of seconds to sleep between refreshes.
|
109
|
+
Defaults to the configured value `system.cli.refresh_seconds`.
|
110
|
+
|
89
111
|
_properties: Optional[Dict[str, Any]], default None
|
90
112
|
If provided, use this to patch the daemon's properties.
|
91
113
|
"""
|
@@ -112,6 +134,11 @@ class Job:
|
|
112
134
|
|
113
135
|
self.executor_keys = executor_keys
|
114
136
|
self.name = name
|
137
|
+
self.refresh_seconds = (
|
138
|
+
refresh_seconds
|
139
|
+
if refresh_seconds is not None
|
140
|
+
else mrsm.get_config('system', 'cli', 'refresh_seconds')
|
141
|
+
)
|
115
142
|
try:
|
116
143
|
self._daemon = (
|
117
144
|
Daemon(daemon_id=name)
|
@@ -257,7 +284,11 @@ class Job:
|
|
257
284
|
|
258
285
|
return success, f"Started {self}."
|
259
286
|
|
260
|
-
def stop(
|
287
|
+
def stop(
|
288
|
+
self,
|
289
|
+
timeout_seconds: Union[int, float, None] = None,
|
290
|
+
debug: bool = False,
|
291
|
+
) -> SuccessTuple:
|
261
292
|
"""
|
262
293
|
Stop the job's daemon.
|
263
294
|
"""
|
@@ -284,7 +315,11 @@ class Job:
|
|
284
315
|
|
285
316
|
return kill_success, f"Killed {self}."
|
286
317
|
|
287
|
-
def pause(
|
318
|
+
def pause(
|
319
|
+
self,
|
320
|
+
timeout_seconds: Union[int, float, None] = None,
|
321
|
+
debug: bool = False,
|
322
|
+
) -> SuccessTuple:
|
288
323
|
"""
|
289
324
|
Pause the job's daemon.
|
290
325
|
"""
|
@@ -342,7 +377,7 @@ class Job:
|
|
342
377
|
|
343
378
|
def monitor_logs(
|
344
379
|
self,
|
345
|
-
callback_function: Callable[[str], None] =
|
380
|
+
callback_function: Callable[[str], None] = _default_stdout_callback,
|
346
381
|
input_callback_function: Optional[Callable[[], str]] = None,
|
347
382
|
stop_callback_function: Optional[Callable[[SuccessTuple], None]] = None,
|
348
383
|
stop_event: Optional[asyncio.Event] = None,
|
@@ -350,6 +385,10 @@ class Job:
|
|
350
385
|
strip_timestamps: bool = False,
|
351
386
|
accept_input: bool = True,
|
352
387
|
debug: bool = False,
|
388
|
+
_logs_path: Optional[pathlib.Path] = None,
|
389
|
+
_log=None,
|
390
|
+
_stdin_file=None,
|
391
|
+
_wait_if_stopped: bool = True,
|
353
392
|
):
|
354
393
|
"""
|
355
394
|
Monitor the job's log files and execute a callback on new lines.
|
@@ -382,12 +421,6 @@ class Job:
|
|
382
421
|
accept_input: bool, default True
|
383
422
|
If `True`, accept input when the daemon blocks on stdin.
|
384
423
|
"""
|
385
|
-
def default_input_callback_function():
|
386
|
-
return sys.stdin.readline()
|
387
|
-
|
388
|
-
if input_callback_function is None:
|
389
|
-
input_callback_function = default_input_callback_function
|
390
|
-
|
391
424
|
if self.executor is not None:
|
392
425
|
self.executor.monitor_logs(
|
393
426
|
self.name,
|
@@ -409,29 +442,35 @@ class Job:
|
|
409
442
|
stop_on_exit=stop_on_exit,
|
410
443
|
strip_timestamps=strip_timestamps,
|
411
444
|
accept_input=accept_input,
|
445
|
+
debug=debug,
|
446
|
+
_logs_path=_logs_path,
|
447
|
+
_log=_log,
|
448
|
+
_stdin_file=_stdin_file,
|
449
|
+
_wait_if_stopped=_wait_if_stopped,
|
412
450
|
)
|
413
451
|
return asyncio.run(monitor_logs_coroutine)
|
414
452
|
|
415
453
|
async def monitor_logs_async(
|
416
454
|
self,
|
417
|
-
callback_function: Callable[[str], None] =
|
455
|
+
callback_function: Callable[[str], None] = _default_stdout_callback,
|
418
456
|
input_callback_function: Optional[Callable[[], str]] = None,
|
419
457
|
stop_callback_function: Optional[Callable[[SuccessTuple], None]] = None,
|
420
458
|
stop_event: Optional[asyncio.Event] = None,
|
421
459
|
stop_on_exit: bool = False,
|
422
460
|
strip_timestamps: bool = False,
|
423
461
|
accept_input: bool = True,
|
462
|
+
debug: bool = False,
|
424
463
|
_logs_path: Optional[pathlib.Path] = None,
|
425
464
|
_log=None,
|
426
465
|
_stdin_file=None,
|
427
|
-
|
466
|
+
_wait_if_stopped: bool = True,
|
428
467
|
):
|
429
468
|
"""
|
430
469
|
Monitor the job's log files and await a callback on new lines.
|
431
470
|
|
432
471
|
Parameters
|
433
472
|
----------
|
434
|
-
callback_function: Callable[[str], None], default
|
473
|
+
callback_function: Callable[[str], None], default _default_stdout_callback
|
435
474
|
The callback to execute as new data comes in.
|
436
475
|
Defaults to printing the output directly to `stdout`.
|
437
476
|
|
@@ -457,7 +496,13 @@ class Job:
|
|
457
496
|
accept_input: bool, default True
|
458
497
|
If `True`, accept input when the daemon blocks on stdin.
|
459
498
|
"""
|
499
|
+
from meerschaum.utils.prompt import prompt
|
500
|
+
|
460
501
|
def default_input_callback_function():
|
502
|
+
prompt_kwargs = self.get_prompt_kwargs(debug=debug)
|
503
|
+
if prompt_kwargs:
|
504
|
+
answer = prompt(**prompt_kwargs)
|
505
|
+
return answer + '\n'
|
461
506
|
return sys.stdin.readline()
|
462
507
|
|
463
508
|
if input_callback_function is None:
|
@@ -481,23 +526,26 @@ class Job:
|
|
481
526
|
events = {
|
482
527
|
'user': stop_event,
|
483
528
|
'stopped': asyncio.Event(),
|
529
|
+
'stop_token': asyncio.Event(),
|
530
|
+
'stop_exception': asyncio.Event(),
|
531
|
+
'stopped_timeout': asyncio.Event(),
|
484
532
|
}
|
485
533
|
combined_event = asyncio.Event()
|
486
534
|
emitted_text = False
|
487
535
|
stdin_file = _stdin_file if _stdin_file is not None else self.daemon.stdin_file
|
488
536
|
|
489
537
|
async def check_job_status():
|
490
|
-
|
491
|
-
stopped_event = events.get('stopped', None)
|
492
|
-
if stopped_event is None:
|
538
|
+
if not stop_on_exit:
|
493
539
|
return
|
494
540
|
|
541
|
+
nonlocal emitted_text
|
542
|
+
|
495
543
|
sleep_time = 0.1
|
496
|
-
while sleep_time <
|
544
|
+
while sleep_time < 0.2:
|
497
545
|
if self.status == 'stopped':
|
498
|
-
if not emitted_text:
|
546
|
+
if not emitted_text and _wait_if_stopped:
|
499
547
|
await asyncio.sleep(sleep_time)
|
500
|
-
sleep_time = round(sleep_time * 1.1,
|
548
|
+
sleep_time = round(sleep_time * 1.1, 3)
|
501
549
|
continue
|
502
550
|
|
503
551
|
if stop_callback_function is not None:
|
@@ -517,11 +565,13 @@ class Job:
|
|
517
565
|
break
|
518
566
|
await asyncio.sleep(0.1)
|
519
567
|
|
568
|
+
events['stopped_timeout'].set()
|
569
|
+
|
520
570
|
async def check_blocking_on_input():
|
521
571
|
while True:
|
522
572
|
if not emitted_text or not self.is_blocking_on_stdin():
|
523
573
|
try:
|
524
|
-
await asyncio.sleep(
|
574
|
+
await asyncio.sleep(self.refresh_seconds)
|
525
575
|
except asyncio.exceptions.CancelledError:
|
526
576
|
break
|
527
577
|
continue
|
@@ -536,14 +586,15 @@ class Job:
|
|
536
586
|
if asyncio.iscoroutinefunction(input_callback_function):
|
537
587
|
data = await input_callback_function()
|
538
588
|
else:
|
539
|
-
|
589
|
+
loop = asyncio.get_running_loop()
|
590
|
+
data = await loop.run_in_executor(None, input_callback_function)
|
540
591
|
except KeyboardInterrupt:
|
541
592
|
break
|
542
|
-
if not data.endswith('\n'):
|
543
|
-
data += '\n'
|
593
|
+
# if not data.endswith('\n'):
|
594
|
+
# data += '\n'
|
544
595
|
|
545
596
|
stdin_file.write(data)
|
546
|
-
await asyncio.sleep(
|
597
|
+
await asyncio.sleep(self.refresh_seconds)
|
547
598
|
|
548
599
|
async def combine_events():
|
549
600
|
event_tasks = [
|
@@ -571,15 +622,30 @@ class Job:
|
|
571
622
|
combine_events_task = asyncio.create_task(combine_events())
|
572
623
|
|
573
624
|
log = _log if _log is not None else self.daemon.rotating_log
|
574
|
-
lines_to_show =
|
625
|
+
lines_to_show = (
|
626
|
+
self.daemon.properties.get(
|
627
|
+
'logs', {}
|
628
|
+
).get(
|
629
|
+
'lines_to_show', get_config('jobs', 'logs', 'lines_to_show')
|
630
|
+
)
|
631
|
+
)
|
575
632
|
|
576
633
|
async def emit_latest_lines():
|
577
634
|
nonlocal emitted_text
|
635
|
+
nonlocal stop_event
|
578
636
|
lines = log.readlines()
|
579
637
|
for line in lines[(-1 * lines_to_show):]:
|
580
638
|
if stop_event is not None and stop_event.is_set():
|
581
639
|
return
|
582
640
|
|
641
|
+
if strip_timestamp_from_line(line.strip()) == STOP_TOKEN:
|
642
|
+
events['stop_token'].set()
|
643
|
+
return
|
644
|
+
|
645
|
+
if strip_timestamp_from_line(line.strip()) == CLEAR_TOKEN:
|
646
|
+
clear_screen(debug=debug)
|
647
|
+
continue
|
648
|
+
|
583
649
|
if strip_timestamps:
|
584
650
|
line = strip_timestamp_from_line(line)
|
585
651
|
|
@@ -590,6 +656,7 @@ class Job:
|
|
590
656
|
callback_function(line)
|
591
657
|
emitted_text = True
|
592
658
|
except StopMonitoringLogs:
|
659
|
+
events['stop_exception'].set()
|
593
660
|
return
|
594
661
|
except Exception:
|
595
662
|
warn(f"Error in logs callback:\n{traceback.format_exc()}")
|
@@ -608,9 +675,14 @@ class Job:
|
|
608
675
|
except Exception:
|
609
676
|
warn(f"Failed to run async checks:\n{traceback.format_exc()}")
|
610
677
|
|
611
|
-
watchfiles = mrsm.attempt_import('watchfiles')
|
678
|
+
watchfiles = mrsm.attempt_import('watchfiles', lazy=False)
|
679
|
+
dir_path_to_monitor = (
|
680
|
+
_logs_path
|
681
|
+
or (log.file_path.parent if log else None)
|
682
|
+
or LOGS_RESOURCES_PATH
|
683
|
+
)
|
612
684
|
async for changes in watchfiles.awatch(
|
613
|
-
|
685
|
+
dir_path_to_monitor,
|
614
686
|
stop_event=combined_event,
|
615
687
|
):
|
616
688
|
for change in changes:
|
@@ -633,6 +705,27 @@ class Job:
|
|
633
705
|
|
634
706
|
return self.is_running() and self.daemon.blocking_stdin_file_path.exists()
|
635
707
|
|
708
|
+
def get_prompt_kwargs(self, debug: bool = False) -> Dict[str, Any]:
|
709
|
+
"""
|
710
|
+
Return the kwargs to the blocking `prompt()`, if available.
|
711
|
+
"""
|
712
|
+
if self.executor is not None:
|
713
|
+
return self.executor.get_job_prompt_kwargs(self.name, debug=debug)
|
714
|
+
|
715
|
+
if not self.daemon.prompt_kwargs_file_path.exists():
|
716
|
+
return {}
|
717
|
+
|
718
|
+
try:
|
719
|
+
with open(self.daemon.prompt_kwargs_file_path, 'r', encoding='utf-8') as f:
|
720
|
+
prompt_kwargs = json.load(f)
|
721
|
+
|
722
|
+
return prompt_kwargs
|
723
|
+
|
724
|
+
except Exception:
|
725
|
+
import traceback
|
726
|
+
traceback.print_exc()
|
727
|
+
return {}
|
728
|
+
|
636
729
|
def write_stdin(self, data):
|
637
730
|
"""
|
638
731
|
Write to a job's daemon's `stdin`.
|
@@ -724,6 +817,20 @@ class Job:
|
|
724
817
|
self._sysargs = target_args[0] if len(target_args) > 0 else []
|
725
818
|
return self._sysargs
|
726
819
|
|
820
|
+
def get_daemon_properties(self) -> Dict[str, Any]:
|
821
|
+
"""
|
822
|
+
Return the `properties` dictionary for the job's daemon.
|
823
|
+
"""
|
824
|
+
remote_properties = (
|
825
|
+
{}
|
826
|
+
if self.executor is None
|
827
|
+
else self.executor.get_job_properties(self.name)
|
828
|
+
)
|
829
|
+
return {
|
830
|
+
**remote_properties,
|
831
|
+
**self._properties_patch
|
832
|
+
}
|
833
|
+
|
727
834
|
@property
|
728
835
|
def daemon(self) -> 'Daemon':
|
729
836
|
"""
|
@@ -733,20 +840,13 @@ class Job:
|
|
733
840
|
if self._daemon is not None and self.executor is None and self._sysargs:
|
734
841
|
return self._daemon
|
735
842
|
|
736
|
-
remote_properties = (
|
737
|
-
{}
|
738
|
-
if self.executor is None
|
739
|
-
else self.executor.get_job_properties(self.name)
|
740
|
-
)
|
741
|
-
properties = {**remote_properties, **self._properties_patch}
|
742
|
-
|
743
843
|
self._daemon = Daemon(
|
744
844
|
target=entry,
|
745
845
|
target_args=[self._sysargs],
|
746
846
|
target_kw={},
|
747
847
|
daemon_id=self.name,
|
748
848
|
label=shlex.join(self._sysargs),
|
749
|
-
properties=
|
849
|
+
properties=self.get_daemon_properties(),
|
750
850
|
)
|
751
851
|
if '_rotating_log' in self.__dict__:
|
752
852
|
self._daemon._rotating_log = self._rotating_log
|
meerschaum/jobs/systemd.py
CHANGED
@@ -12,7 +12,6 @@ import sys
|
|
12
12
|
import asyncio
|
13
13
|
import json
|
14
14
|
import time
|
15
|
-
import traceback
|
16
15
|
import shutil
|
17
16
|
from datetime import datetime, timezone
|
18
17
|
from functools import partial
|
@@ -23,7 +22,6 @@ from meerschaum.utils.typing import Dict, Any, List, SuccessTuple, Union, Option
|
|
23
22
|
from meerschaum.config import get_config
|
24
23
|
from meerschaum._internal.static import STATIC_CONFIG
|
25
24
|
from meerschaum.utils.warnings import warn, dprint
|
26
|
-
from meerschaum._internal.arguments._parse_arguments import parse_arguments
|
27
25
|
|
28
26
|
JOB_METADATA_CACHE_SECONDS: int = STATIC_CONFIG['api']['jobs']['metadata_cache_seconds']
|
29
27
|
|
@@ -705,6 +703,13 @@ class SystemdExecutor(Executor):
|
|
705
703
|
blocking_path = socket_path.parent / (socket_path.name + '.block')
|
706
704
|
return blocking_path.exists()
|
707
705
|
|
706
|
+
def get_job_prompt_kwargs(self, name: str, debug: bool = False) -> Dict[str, Any]:
|
707
|
+
"""
|
708
|
+
Return the kwargs to the blocking prompt.
|
709
|
+
"""
|
710
|
+
job = self.get_hidden_job(name, debug=debug)
|
711
|
+
return job.get_prompt_kwargs(debug=debug)
|
712
|
+
|
708
713
|
def get_job_rotating_file(self, name: str, debug: bool = False):
|
709
714
|
"""
|
710
715
|
Return a `RotatingFile` for the job's log output.
|